From 18330eafcdca65ddb4becfbd2b26aa69db124d5e Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Thu, 20 Jul 2017 19:35:53 +0200 Subject: [PATCH] New upstream version 3.9.0 --- .clang-tidy | 30 + Auxiliary/cmake.m4 | 4 +- Auxiliary/vim/cmake.vim.in | 48 +- Auxiliary/vim/extract-upper-case.pl | 27 +- Auxiliary/vim/indent/cmake.vim | 1 + Auxiliary/vim/syntax/cmake.vim | 411 +- CMakeLists.txt | 78 +- CONTRIBUTING.rst | 24 +- CompileFlags.cmake | 16 +- Help/command/FIND_XXX.txt | 35 +- Help/command/add_custom_command.rst | 2 +- Help/command/add_executable.rst | 3 + Help/command/add_library.rst | 15 +- Help/command/ctest_memcheck.rst | 3 + Help/command/ctest_submit.rst | 10 +- Help/command/ctest_test.rst | 17 + Help/command/find_file.rst | 3 + Help/command/find_library.rst | 18 + Help/command/find_package.rst | 30 +- Help/command/find_path.rst | 3 + Help/command/find_program.rst | 2 + Help/command/if.rst | 3 +- Help/command/include_external_msproject.rst | 4 + Help/command/install.rst | 23 +- Help/command/project.rst | 5 + Help/command/separate_arguments.rst | 9 +- Help/command/string.rst | 52 +- Help/dev/README.rst | 49 + Help/dev/maint.rst | 171 + Help/dev/review.rst | 350 ++ Help/dev/source.rst | 60 + Help/dev/testing.rst | 42 + Help/generator/VS_TOOLSET_HOST_ARCH.txt | 8 +- Help/generator/Visual Studio 15 2017.rst | 12 + Help/generator/Visual Studio 7 .NET 2003.rst | 10 +- Help/generator/Visual Studio 8 2005.rst | 9 +- Help/generator/Xcode.rst | 2 + Help/manual/OPTIONS_BUILD.txt | 24 +- Help/manual/cmake-buildsystem.7.rst | 12 +- Help/manual/cmake-commands.7.rst | 133 +- Help/manual/cmake-compile-features.7.rst | 22 +- Help/manual/cmake-developer.7.rst | 24 - Help/manual/cmake-generator-expressions.7.rst | 15 +- Help/manual/cmake-modules.7.rst | 3 + Help/manual/cmake-policies.7.rst | 9 + Help/manual/cmake-properties.7.rst | 14 + Help/manual/cmake-qt.7.rst | 37 +- Help/manual/cmake-toolchains.7.rst | 5 + Help/manual/cmake-variables.7.rst | 68 +- Help/manual/cmake.1.rst | 5 +- Help/manual/ctest.1.rst | 17 + Help/module/CPackArchive.rst | 1 + Help/module/CheckIPOSupported.rst | 1 + Help/module/GoogleTest.rst | 1 + Help/policy/CMP0068.rst | 35 + Help/policy/CMP0069.rst | 92 + .../VS_GLOBAL_SECTION_POST_section.rst | 6 +- .../VS_GLOBAL_SECTION_PRE_section.rst | 2 +- Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst | 15 + Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst | 4 +- Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst | 7 + Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst | 7 + .../prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst | 2 + .../prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst | 2 + .../FIND_LIBRARY_USE_LIBX32_PATHS.rst | 12 + Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst | 9 + Help/prop_sf/HEADER_FILE_ONLY.rst | 15 + Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst | 7 + Help/prop_test/DISABLED.rst | 15 + Help/prop_tgt/AUTOGEN_BUILD_DIR.rst | 17 + Help/prop_tgt/AUTOMOC.rst | 68 +- Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst | 45 + Help/prop_tgt/AUTORCC.rst | 3 + Help/prop_tgt/AUTOUIC.rst | 11 +- Help/prop_tgt/AUTOUIC_OPTIONS.rst | 2 +- Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst | 12 + Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst | 13 + Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst | 18 +- Help/prop_tgt/CUDA_PTX_COMPILATION.rst | 12 + Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst | 15 + Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst | 2 +- Help/prop_tgt/IMPORTED_OBJECTS.rst | 11 + Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst | 7 + .../prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst | 4 + .../INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst | 4 + Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst | 45 + Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst | 7 + Help/release/3.9.rst | 328 ++ Help/release/index.rst | 1 + .../CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst | 9 + .../variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst | 12 + Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst | 11 + .../CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst | 7 + Help/variable/CMAKE_CFG_INTDIR.rst | 2 +- .../CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst | 12 + Help/variable/CMAKE_GENERATOR_PLATFORM.rst | 15 +- Help/variable/CMAKE_GENERATOR_TOOLSET.rst | 45 +- Help/variable/CMAKE_HOST_WIN32.rst | 4 +- .../CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst | 8 + ...KE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst | 8 + Help/variable/CMAKE_LANG_COMPILER_AR.rst | 7 + Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst | 7 + Help/variable/CMAKE_LANG_COMPILER_VERSION.rst | 4 + Help/variable/CMAKE_MATCH_COUNT.rst | 7 +- Help/variable/CMAKE_MATCH_n.rst | 10 + Help/variable/CMAKE_MFC_FLAG.rst | 2 +- Help/variable/CMAKE_PROJECT_DESCRIPTION.rst | 7 + Help/variable/CMAKE_SYSROOT.rst | 3 + Help/variable/CMAKE_SYSROOT_COMPILE.rst | 9 + Help/variable/CMAKE_SYSROOT_LINK.rst | 9 + Help/variable/CMAKE_VS_DEVENV_COMMAND.rst | 2 +- ...CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst | 2 +- Help/variable/CMAKE_VS_PLATFORM_NAME.rst | 1 + Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst | 2 + .../CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst | 12 + ...AKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst | 5 + Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst | 11 + Help/variable/PROJECT_DESCRIPTION.rst | 6 + Modules/AutogenInfo.cmake.in | 37 +- Modules/BundleUtilities.cmake | 13 +- Modules/CMakeASMCompiler.cmake.in | 2 + Modules/CMakeASMInformation.cmake | 6 +- Modules/CMakeBackwardCompatibilityC.cmake | 6 - Modules/CMakeCCompiler.cmake.in | 3 + Modules/CMakeCInformation.cmake | 6 +- Modules/CMakeCSharpInformation.cmake | 22 +- Modules/CMakeCUDAInformation.cmake | 17 +- Modules/CMakeCXXCompiler.cmake.in | 3 + ...CMakeCheckCompilerFlagCommonPatterns.cmake | 1 + Modules/CMakeCommonLanguageInclude.cmake | 6 +- Modules/CMakeCompilerABI.h | 4 + Modules/CMakeCompilerIdDetection.cmake | 8 +- Modules/CMakeDetermineASMCompiler.cmake | 16 +- Modules/CMakeDetermineASM_NASMCompiler.cmake | 17 +- Modules/CMakeDetermineCCompiler.cmake | 9 + Modules/CMakeDetermineCSharpCompiler.cmake | 2 +- Modules/CMakeDetermineCUDACompiler.cmake | 58 +- Modules/CMakeDetermineCXXCompiler.cmake | 9 + Modules/CMakeDetermineCompilerId.cmake | 85 +- Modules/CMakeDetermineFortranCompiler.cmake | 7 +- Modules/CMakeDetermineSystem.cmake | 18 +- Modules/CMakeFindBinUtils.cmake | 4 + Modules/CMakeFindDependencyMacro.cmake | 38 +- Modules/CMakeFortranCompiler.cmake.in | 2 + Modules/CMakeFortranCompilerId.F.in | 5 + Modules/CMakeParseImplicitLinkInfo.cmake | 23 +- Modules/CMakeVS7BackwardCompatibility.cmake | 16 - Modules/CPack.cmake | 16 +- Modules/CPackArchive.cmake | 39 + Modules/CPackComponent.cmake | 69 +- Modules/CPackIFW.cmake | 162 +- Modules/CPackProductBuild.cmake | 8 + Modules/CPackRPM.cmake | 74 +- Modules/CPackWIX.cmake | 35 +- Modules/CTest.cmake | 6 +- Modules/CheckIPOSupported.cmake | 232 + Modules/CheckIPOSupported/CMakeLists-C.txt.in | 8 + .../CheckIPOSupported/CMakeLists-CXX.txt.in | 8 + .../CMakeLists-Fortran.txt.in | 8 + Modules/CheckIPOSupported/foo.c | 4 + Modules/CheckIPOSupported/foo.cpp | 4 + Modules/CheckIPOSupported/foo.f | 2 + Modules/CheckIPOSupported/main.c | 6 + Modules/CheckIPOSupported/main.cpp | 6 + Modules/CheckIPOSupported/main.f | 3 + Modules/CheckLanguage.cmake | 2 + Modules/CheckSymbolExists.cmake | 73 +- Modules/CheckTypeSize.cmake | 4 +- Modules/Compiler/AppleClang-C.cmake | 27 +- Modules/Compiler/AppleClang-CXX.cmake | 31 +- .../Compiler/CMakeCommonCompilerMacros.cmake | 93 + Modules/Compiler/Clang-C.cmake | 31 +- Modules/Compiler/Clang-CXX.cmake | 30 +- Modules/Compiler/Clang-FindBinUtils.cmake | 27 + Modules/Compiler/Clang.cmake | 52 + Modules/Compiler/Cray-C.cmake | 21 + Modules/Compiler/Cray-CXX.cmake | 19 + Modules/Compiler/Cray.cmake | 10 + Modules/Compiler/GNU-C.cmake | 31 +- Modules/Compiler/GNU-CXX.cmake | 33 +- Modules/Compiler/GNU-FindBinUtils.cmake | 35 + Modules/Compiler/GNU.cmake | 41 + Modules/Compiler/IAR-C.cmake | 2 +- Modules/Compiler/IAR-CXX.cmake | 2 +- Modules/Compiler/Intel-C.cmake | 59 +- Modules/Compiler/Intel-CXX.cmake | 79 +- Modules/Compiler/Intel.cmake | 4 + Modules/Compiler/MSVC-CXX.cmake | 32 +- Modules/Compiler/NVIDIA-CUDA.cmake | 6 + Modules/Compiler/PGI-C.cmake | 13 + Modules/Compiler/PGI-CXX.cmake | 19 + Modules/Compiler/PGI.cmake | 12 +- Modules/Compiler/QCC.cmake | 8 + Modules/Compiler/SunPro-C-FeatureTests.cmake | 14 + Modules/Compiler/SunPro-C.cmake | 21 + .../Compiler/SunPro-CXX-FeatureTests.cmake | 4 + Modules/Compiler/SunPro-CXX.cmake | 38 +- Modules/Compiler/SunPro-Fortran.cmake | 4 +- Modules/Compiler/SunPro.cmake | 10 + Modules/Compiler/XL-C.cmake | 39 +- Modules/Compiler/XL-CXX.cmake | 44 +- Modules/Compiler/XL.cmake | 2 + Modules/CompilerId/VS-10.vcxproj.in | 12 +- Modules/CompilerId/Xcode-1.pbxproj.in | 120 - Modules/CompilerId/Xcode-2.pbxproj.in | 119 - Modules/CompilerId/Xcode-3.pbxproj.in | 2 +- Modules/ExternalData.cmake | 2 +- Modules/ExternalProject.cmake | 27 +- Modules/FeatureSummary.cmake | 61 +- Modules/FindBoost.cmake | 111 +- Modules/FindCUDA.cmake | 23 +- Modules/FindCygwin.cmake | 4 +- Modules/FindDevIL.cmake | 10 +- Modules/FindDoxygen.cmake | 1137 ++++- Modules/FindGLEW.cmake | 2 +- Modules/FindGLUT.cmake | 8 +- Modules/FindGSL.cmake | 11 +- Modules/FindGTK2.cmake | 2 + Modules/FindGTest.cmake | 60 +- Modules/FindHDF5.cmake | 93 +- Modules/FindIce.cmake | 2 +- Modules/FindImageMagick.cmake | 23 +- Modules/FindJava.cmake | 3 + Modules/FindKDE3.cmake | 2 + Modules/FindMPI.cmake | 127 +- Modules/FindMatlab.cmake | 1 + Modules/FindOpenAL.cmake | 2 +- Modules/FindOpenCL.cmake | 7 +- Modules/FindOpenGL.cmake | 4 +- Modules/FindOpenMP.cmake | 541 ++- Modules/FindOpenSSL.cmake | 9 +- Modules/FindPackageHandleStandardArgs.cmake | 4 +- Modules/FindPkgConfig.cmake | 51 +- Modules/FindProtobuf.cmake | 129 +- Modules/FindPythonInterp.cmake | 7 +- Modules/FindXCTest.cmake | 4 + Modules/FindXMLRPC.cmake | 30 +- Modules/FindwxWidgets.cmake | 22 + Modules/FortranCInterface/CMakeLists.txt | 11 +- Modules/FortranCInterface/Detect.cmake | 5 +- Modules/FortranCInterface/MYMODULE.c | 3 + Modules/FortranCInterface/MY_MODULE.c | 3 + Modules/GNUInstallDirs.cmake | 44 +- Modules/GenerateExportHeader.cmake | 8 +- Modules/GetPrerequisites.cmake | 15 +- Modules/GoogleTest.cmake | 226 + Modules/InstallRequiredSystemLibraries.cmake | 6 + Modules/Internal/FeatureTesting.cmake | 10 + Modules/MacOSXBundleInfo.plist.in | 4 + Modules/Platform/AIX-GNU.cmake | 2 +- Modules/Platform/AIX-XL-C.cmake | 3 + Modules/Platform/AIX-XL-CXX.cmake | 3 + Modules/Platform/Android-Common.cmake | 15 +- Modules/Platform/Android-Determine.cmake | 91 +- Modules/Platform/Android-Initialize.cmake | 3 + Modules/Platform/Android/abi-common.cmake | 4 + .../Platform/Android/ndk-stl-c++_shared.cmake | 1 + Modules/Platform/BlueGeneP-dynamic-XL-C.cmake | 3 + .../Platform/BlueGeneP-dynamic-XL-CXX.cmake | 3 + Modules/Platform/BlueGeneP-static-XL-C.cmake | 3 + .../Platform/BlueGeneP-static-XL-CXX.cmake | 3 + Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake | 3 + .../Platform/BlueGeneQ-dynamic-XL-CXX.cmake | 3 + Modules/Platform/BlueGeneQ-static-XL-C.cmake | 3 + .../Platform/BlueGeneQ-static-XL-CXX.cmake | 3 + Modules/Platform/CYGWIN-GNU.cmake | 2 +- Modules/Platform/CYGWIN.cmake | 10 + Modules/Platform/Darwin-XL-C.cmake | 3 + Modules/Platform/Darwin-XL-CXX.cmake | 3 + Modules/Platform/HP-UX-GNU.cmake | 2 +- Modules/Platform/Linux-GNU.cmake | 1 + Modules/Platform/Linux-Intel.cmake | 6 + Modules/Platform/Linux-PGI.cmake | 1 + Modules/Platform/Linux-TinyCC-C.cmake | 1 + Modules/Platform/SunOS.cmake | 5 + Modules/Platform/UnixPaths.cmake | 32 +- Modules/Platform/Windows-GNU.cmake | 17 + Modules/Platform/Windows-MSVC.cmake | 4 +- Modules/Platform/Windows-NVIDIA-CUDA.cmake | 12 +- Modules/Platform/Windows-PGI-C.cmake | 2 + Modules/Platform/Windows-PGI-Fortran.cmake | 2 + Modules/Platform/Windows-PGI.cmake | 48 + Modules/Platform/Windows-df.cmake | 2 +- Modules/TestBigEndian.cmake | 26 +- Modules/UseEcos.cmake | 4 +- Modules/UseJava.cmake | 38 +- Modules/UseSWIG.cmake | 3 + Modules/WriteCompilerDetectionHeader.cmake | 23 +- README.rst | 8 +- Source/.gitattributes | 19 - Source/CMakeLists.txt | 125 +- Source/CMakeVersion.cmake | 2 +- Source/CPack/IFW/cmCPackIFWCommon.cxx | 137 + Source/CPack/IFW/cmCPackIFWCommon.h | 81 + Source/CPack/IFW/cmCPackIFWGenerator.cxx | 340 +- Source/CPack/IFW/cmCPackIFWGenerator.h | 34 +- Source/CPack/IFW/cmCPackIFWInstaller.cxx | 388 +- Source/CPack/IFW/cmCPackIFWInstaller.h | 19 +- Source/CPack/IFW/cmCPackIFWPackage.cxx | 531 ++- Source/CPack/IFW/cmCPackIFWPackage.h | 27 +- Source/CPack/IFW/cmCPackIFWRepository.cxx | 220 +- Source/CPack/IFW/cmCPackIFWRepository.h | 18 +- Source/CPack/OSXScriptLauncher.cxx | 9 +- Source/CPack/WiX/cmCPackWIXGenerator.cxx | 56 +- Source/CPack/WiX/cmCPackWIXGenerator.h | 6 +- Source/CPack/WiX/cmWIXAccessControlList.cxx | 4 +- Source/CPack/WiX/cmWIXAccessControlList.h | 4 +- .../CPack/WiX/cmWIXDirectoriesSourceWriter.h | 2 +- .../CPack/WiX/cmWIXFeaturesSourceWriter.cxx | 4 +- Source/CPack/WiX/cmWIXFeaturesSourceWriter.h | 2 +- Source/CPack/WiX/cmWIXFilesSourceWriter.cxx | 14 +- Source/CPack/WiX/cmWIXFilesSourceWriter.h | 2 +- Source/CPack/WiX/cmWIXPatch.cxx | 8 +- Source/CPack/WiX/cmWIXPatchParser.cxx | 30 +- Source/CPack/WiX/cmWIXPatchParser.h | 10 +- .../CPack/WiX/cmWIXRichTextFormatWriter.cxx | 2 +- Source/CPack/WiX/cmWIXRichTextFormatWriter.h | 4 +- Source/CPack/WiX/cmWIXShortcut.h | 2 +- Source/CPack/WiX/cmWIXSourceWriter.cxx | 4 +- Source/CPack/WiX/cmWIXSourceWriter.h | 4 +- Source/CPack/cmCPack7zGenerator.h | 2 +- Source/CPack/cmCPackArchiveGenerator.cxx | 67 +- Source/CPack/cmCPackArchiveGenerator.h | 7 +- Source/CPack/cmCPackBundleGenerator.h | 3 +- Source/CPack/cmCPackComponentGroup.h | 6 +- Source/CPack/cmCPackCygwinBinaryGenerator.cxx | 2 +- Source/CPack/cmCPackCygwinSourceGenerator.cxx | 4 +- Source/CPack/cmCPackDebGenerator.cxx | 4 +- Source/CPack/cmCPackDebGenerator.h | 2 +- Source/CPack/cmCPackDragNDropGenerator.cxx | 49 +- Source/CPack/cmCPackDragNDropGenerator.h | 3 +- Source/CPack/cmCPackGenerator.cxx | 28 +- Source/CPack/cmCPackGenerator.h | 31 +- Source/CPack/cmCPackGeneratorFactory.cxx | 2 +- Source/CPack/cmCPackGeneratorFactory.h | 2 +- Source/CPack/cmCPackLog.cxx | 2 +- Source/CPack/cmCPackLog.h | 14 +- Source/CPack/cmCPackNSISGenerator.cxx | 8 +- Source/CPack/cmCPackNSISGenerator.h | 2 +- Source/CPack/cmCPackOSXX11Generator.cxx | 2 +- Source/CPack/cmCPackOSXX11Generator.h | 3 +- Source/CPack/cmCPackPKGGenerator.h | 3 +- Source/CPack/cmCPackPackageMakerGenerator.cxx | 4 +- Source/CPack/cmCPackPackageMakerGenerator.h | 2 +- Source/CPack/cmCPackProductBuildGenerator.cxx | 21 +- Source/CPack/cmCPackProductBuildGenerator.h | 3 +- Source/CPack/cmCPackRPMGenerator.h | 2 +- Source/CPack/cmCPackSTGZGenerator.cxx | 7 +- Source/CPack/cmCPackSTGZGenerator.h | 2 +- Source/CPack/cmCPackTGZGenerator.h | 2 +- Source/CPack/cmCPackTXZGenerator.h | 2 +- Source/CPack/cmCPackTarBZip2Generator.h | 2 +- Source/CPack/cmCPackTarCompressGenerator.h | 2 +- Source/CPack/cmCPackZIPGenerator.h | 2 +- Source/CPack/cpack.cxx | 12 +- Source/CTest/cmCTestBZR.cxx | 18 +- Source/CTest/cmCTestBZR.h | 10 +- Source/CTest/cmCTestBatchTestHandler.h | 6 +- Source/CTest/cmCTestBuildAndTestHandler.cxx | 18 +- Source/CTest/cmCTestBuildAndTestHandler.h | 4 +- Source/CTest/cmCTestBuildCommand.h | 2 +- Source/CTest/cmCTestBuildHandler.cxx | 10 +- Source/CTest/cmCTestBuildHandler.h | 6 +- Source/CTest/cmCTestCVS.cxx | 4 +- Source/CTest/cmCTestCVS.h | 2 +- Source/CTest/cmCTestConfigureCommand.h | 2 +- Source/CTest/cmCTestConfigureHandler.h | 2 +- Source/CTest/cmCTestCoverageCommand.h | 2 +- Source/CTest/cmCTestCoverageHandler.cxx | 49 +- Source/CTest/cmCTestCoverageHandler.h | 4 +- Source/CTest/cmCTestCurl.cxx | 27 +- Source/CTest/cmCTestCurl.h | 9 +- .../cmCTestEmptyBinaryDirectoryCommand.h | 10 +- Source/CTest/cmCTestGIT.cxx | 20 +- Source/CTest/cmCTestGIT.h | 10 +- Source/CTest/cmCTestGenericHandler.cxx | 2 +- Source/CTest/cmCTestGenericHandler.h | 2 +- Source/CTest/cmCTestGlobalVC.cxx | 7 +- Source/CTest/cmCTestGlobalVC.h | 6 +- Source/CTest/cmCTestHG.cxx | 14 +- Source/CTest/cmCTestHG.h | 10 +- Source/CTest/cmCTestHandlerCommand.cxx | 9 +- Source/CTest/cmCTestHandlerCommand.h | 7 +- Source/CTest/cmCTestLaunch.cxx | 13 +- Source/CTest/cmCTestLaunch.h | 4 +- Source/CTest/cmCTestMemCheckCommand.cxx | 1 + Source/CTest/cmCTestMemCheckCommand.h | 9 +- Source/CTest/cmCTestMemCheckHandler.cxx | 10 +- Source/CTest/cmCTestMemCheckHandler.h | 2 +- Source/CTest/cmCTestMultiProcessHandler.cxx | 31 +- Source/CTest/cmCTestMultiProcessHandler.h | 4 +- Source/CTest/cmCTestP4.cxx | 18 +- Source/CTest/cmCTestP4.h | 10 +- Source/CTest/cmCTestReadCustomFilesCommand.h | 7 +- Source/CTest/cmCTestRunScriptCommand.h | 7 +- Source/CTest/cmCTestRunTest.cxx | 75 +- Source/CTest/cmCTestRunTest.h | 2 +- Source/CTest/cmCTestSVN.cxx | 47 +- Source/CTest/cmCTestSVN.h | 17 +- Source/CTest/cmCTestScriptHandler.cxx | 51 +- Source/CTest/cmCTestScriptHandler.h | 4 +- Source/CTest/cmCTestSleepCommand.h | 7 +- Source/CTest/cmCTestStartCommand.h | 7 +- Source/CTest/cmCTestSubmitCommand.cxx | 16 + Source/CTest/cmCTestSubmitCommand.h | 4 +- Source/CTest/cmCTestSubmitHandler.cxx | 39 +- Source/CTest/cmCTestSubmitHandler.h | 8 +- Source/CTest/cmCTestTestCommand.cxx | 18 +- Source/CTest/cmCTestTestCommand.h | 5 +- Source/CTest/cmCTestTestHandler.cxx | 333 +- Source/CTest/cmCTestTestHandler.h | 8 +- Source/CTest/cmCTestUpdateCommand.h | 2 +- Source/CTest/cmCTestUpdateHandler.cxx | 6 +- Source/CTest/cmCTestUpdateHandler.h | 2 +- Source/CTest/cmCTestUploadCommand.h | 2 +- Source/CTest/cmCTestUploadHandler.h | 2 +- Source/CTest/cmCTestVC.cxx | 14 +- Source/CTest/cmCTestVC.h | 6 +- Source/CTest/cmParseBlanketJSCoverage.cxx | 38 +- Source/CTest/cmParseBlanketJSCoverage.h | 2 +- Source/CTest/cmParseCacheCoverage.cxx | 4 +- Source/CTest/cmParseCacheCoverage.h | 2 +- Source/CTest/cmParseCoberturaCoverage.cxx | 4 +- Source/CTest/cmParseCoberturaCoverage.h | 2 +- Source/CTest/cmParseDelphiCoverage.cxx | 83 +- Source/CTest/cmParseDelphiCoverage.h | 2 +- Source/CTest/cmParseGTMCoverage.cxx | 8 +- Source/CTest/cmParseGTMCoverage.h | 2 +- Source/CTest/cmParseJacocoCoverage.cxx | 8 +- Source/CTest/cmParseJacocoCoverage.h | 2 +- Source/CTest/cmParseMumpsCoverage.cxx | 6 +- Source/CTest/cmParseMumpsCoverage.h | 2 +- Source/CTest/cmParsePHPCoverage.cxx | 4 +- Source/CTest/cmParsePHPCoverage.h | 2 +- Source/CTest/cmProcess.cxx | 6 +- Source/CTest/cmProcess.h | 4 +- .../Checks/cm_cxx_attribute_fallthrough.cxx | 11 + Source/Checks/cm_cxx_eq_delete.cxx | 14 + Source/Checks/cm_cxx_fallthrough.cxx | 11 + Source/Checks/cm_cxx_features.cmake | 37 +- Source/Checks/cm_cxx_gnu_fallthrough.cxx | 11 + Source/CursesDialog/ccmake.cxx | 6 +- Source/CursesDialog/cmCursesBoolWidget.h | 8 +- .../cmCursesCacheEntryComposite.cxx | 1 - .../cmCursesCacheEntryComposite.h | 7 +- Source/CursesDialog/cmCursesDummyWidget.h | 8 +- Source/CursesDialog/cmCursesFilePathWidget.h | 8 +- Source/CursesDialog/cmCursesForm.cxx | 2 - Source/CursesDialog/cmCursesForm.h | 9 +- Source/CursesDialog/cmCursesLabelWidget.h | 8 +- .../CursesDialog/cmCursesLongMessageForm.cxx | 3 +- Source/CursesDialog/cmCursesLongMessageForm.h | 7 +- Source/CursesDialog/cmCursesMainForm.cxx | 9 +- Source/CursesDialog/cmCursesMainForm.h | 7 +- Source/CursesDialog/cmCursesOptionsWidget.h | 6 +- Source/CursesDialog/cmCursesPathWidget.h | 7 +- .../CursesDialog/cmCursesStandardIncludes.h | 2 +- Source/CursesDialog/cmCursesStringWidget.h | 7 +- Source/CursesDialog/cmCursesWidget.cxx | 2 - Source/CursesDialog/cmCursesWidget.h | 7 +- Source/CursesDialog/form/form.h | 2 +- Source/LexerParser/.clang-tidy | 6 + Source/LexerParser/.gitattributes | 17 + .../cmCommandArgumentLexer.cxx | 0 .../cmCommandArgumentLexer.h | 0 .../cmCommandArgumentLexer.in.l | 0 .../cmCommandArgumentParser.cxx | 1332 +++--- .../cmCommandArgumentParser.y | 210 +- .../cmCommandArgumentParserTokens.h | 73 +- .../{ => LexerParser}/cmDependsJavaLexer.cxx | 0 Source/{ => LexerParser}/cmDependsJavaLexer.h | 0 .../{ => LexerParser}/cmDependsJavaLexer.in.l | 0 .../{ => LexerParser}/cmDependsJavaParser.cxx | 3965 +++++++++-------- .../{ => LexerParser}/cmDependsJavaParser.y | 34 +- .../LexerParser/cmDependsJavaParserTokens.h | 264 ++ Source/{ => LexerParser}/cmExprLexer.cxx | 0 Source/{ => LexerParser}/cmExprLexer.h | 0 Source/{ => LexerParser}/cmExprLexer.in.l | 0 Source/{ => LexerParser}/cmExprParser.cxx | 110 +- Source/{ => LexerParser}/cmExprParser.y | 8 +- Source/{ => LexerParser}/cmExprParserTokens.h | 0 Source/{ => LexerParser}/cmFortranLexer.cxx | 0 Source/{ => LexerParser}/cmFortranLexer.h | 0 Source/{ => LexerParser}/cmFortranLexer.in.l | 0 Source/{ => LexerParser}/cmFortranParser.cxx | 126 +- Source/{ => LexerParser}/cmFortranParser.y | 8 +- .../{ => LexerParser}/cmFortranParserTokens.h | 2 +- Source/{ => LexerParser}/cmListFileLexer.c | 10 +- Source/{ => LexerParser}/cmListFileLexer.in.l | 2 +- Source/Modules/FindLibUV.cmake | 2 +- Source/QtDialog/CMakeLists.txt | 21 +- Source/QtDialog/CMakeSetup.cxx | 10 +- Source/QtDialog/CMakeSetupDialog.cxx | 15 +- Source/QtDialog/Compilers.h | 2 +- Source/QtDialog/FirstConfigure.cxx | 2 +- Source/QtDialog/QCMake.cxx | 6 +- Source/QtDialog/QCMake.h | 2 +- Source/QtDialog/QCMakeCacheView.cxx | 26 +- Source/QtDialog/QCMakeWidgets.cxx | 8 +- Source/QtDialog/QCMakeWidgets.h | 2 +- Source/QtDialog/RegexExplorer.h | 2 +- .../{CMake.desktop => cmake-gui.desktop} | 0 Source/bindexplib.cxx | 505 +-- Source/bindexplib.h | 4 +- Source/cmAddCompileOptionsCommand.h | 8 +- Source/cmAddCustomCommandCommand.cxx | 2 +- Source/cmAddCustomCommandCommand.h | 8 +- Source/cmAddCustomTargetCommand.cxx | 6 +- Source/cmAddCustomTargetCommand.h | 8 +- Source/cmAddDefinitionsCommand.h | 8 +- Source/cmAddDependenciesCommand.cxx | 2 +- Source/cmAddDependenciesCommand.h | 8 +- Source/cmAddExecutableCommand.cxx | 2 +- Source/cmAddExecutableCommand.h | 8 +- Source/cmAddLibraryCommand.cxx | 15 +- Source/cmAddLibraryCommand.h | 8 +- Source/cmAddSubDirectoryCommand.cxx | 5 +- Source/cmAddSubDirectoryCommand.h | 8 +- Source/cmAddTestCommand.h | 8 +- Source/cmAlgorithms.h | 13 +- Source/cmArchiveWrite.cxx | 8 +- Source/cmArchiveWrite.h | 2 +- Source/cmAuxSourceDirectoryCommand.cxx | 8 +- Source/cmAuxSourceDirectoryCommand.h | 8 +- Source/cmBase32.cxx | 2 +- Source/cmBase32.h | 2 +- Source/cmBreakCommand.cxx | 2 +- Source/cmBreakCommand.h | 13 +- Source/cmBuildCommand.cxx | 4 +- Source/cmBuildCommand.h | 8 +- Source/cmBuildNameCommand.cxx | 8 +- Source/cmBuildNameCommand.h | 5 +- Source/cmCLocaleEnvironmentScope.h | 4 +- .../cmCMakeHostSystemInformationCommand.cxx | 4 +- Source/cmCMakeHostSystemInformationCommand.h | 16 +- Source/cmCMakeMinimumRequired.h | 13 +- Source/cmCMakePolicyCommand.h | 13 +- Source/cmCPackPropertiesGenerator.cxx | 2 +- Source/cmCPackPropertiesGenerator.h | 6 +- Source/cmCTest.cxx | 69 +- Source/cmCTest.h | 39 +- Source/cmCacheManager.cxx | 11 +- Source/cmCacheManager.h | 4 +- Source/cmCallVisualStudioMacro.h | 2 +- Source/cmCommand.cxx | 25 +- Source/cmCommand.h | 28 +- Source/cmCommandArgumentParserHelper.cxx | 3 - Source/cmCommandArgumentParserHelper.h | 26 +- Source/cmCommandArgumentsHelper.h | 2 +- Source/cmCommands.cxx | 344 +- Source/cmCommands.h | 11 +- Source/cmCommonTargetGenerator.cxx | 33 +- Source/cmCommonTargetGenerator.h | 10 +- Source/cmComputeComponentGraph.h | 2 +- Source/cmComputeLinkDepends.cxx | 2 +- Source/cmComputeLinkDepends.h | 4 +- Source/cmComputeLinkInformation.cxx | 32 +- Source/cmComputeLinkInformation.h | 10 +- Source/cmComputeTargetDepends.cxx | 18 +- Source/cmComputeTargetDepends.h | 3 +- Source/cmConditionEvaluator.cxx | 8 +- Source/cmConditionEvaluator.h | 2 +- Source/cmConfigure.cmake.h.in | 26 +- Source/cmConfigureFileCommand.cxx | 4 +- Source/cmConfigureFileCommand.h | 13 +- Source/cmContinueCommand.cxx | 2 +- Source/cmContinueCommand.h | 13 +- Source/cmCoreTryCompile.cxx | 15 +- Source/cmCoreTryCompile.h | 2 +- Source/cmCreateTestSourceList.h | 7 +- Source/cmCryptoHash.cxx | 6 +- Source/cmCryptoHash.h | 4 +- Source/cmCurl.h | 4 +- Source/cmCustomCommand.cxx | 2 +- Source/cmCustomCommand.h | 2 +- Source/cmCustomCommandGenerator.cxx | 2 +- Source/cmCustomCommandGenerator.h | 2 +- Source/cmCustomCommandLines.h | 2 +- Source/cmDefinePropertyCommand.cxx | 18 +- Source/cmDefinePropertyCommand.h | 8 +- Source/cmDefinitions.cxx | 2 +- Source/cmDefinitions.h | 8 +- Source/cmDepends.cxx | 16 +- Source/cmDepends.h | 8 +- Source/cmDependsC.cxx | 6 +- Source/cmDependsC.h | 10 +- Source/cmDependsFortran.cxx | 2 +- Source/cmDependsFortran.h | 8 +- Source/cmDependsJava.h | 8 +- Source/cmDependsJavaParserHelper.cxx | 4 +- Source/cmDependsJavaParserHelper.h | 19 +- Source/cmDependsJavaParserTokens.h | 254 -- Source/cmDisallowedCommand.cxx | 31 + Source/cmDisallowedCommand.h | 51 + Source/cmDocumentation.cxx | 21 +- Source/cmDocumentation.h | 2 +- Source/cmDocumentationEntry.h | 2 +- Source/cmDocumentationFormatter.h | 2 +- Source/cmDocumentationSection.h | 2 +- Source/cmDynamicLoader.cxx | 10 +- Source/cmDynamicLoader.h | 10 +- Source/cmELF.cxx | 21 +- Source/cmELF.h | 2 +- Source/cmEnableLanguageCommand.h | 8 +- Source/cmEnableTestingCommand.h | 8 +- Source/cmExecProgramCommand.cxx | 2 +- Source/cmExecProgramCommand.h | 13 +- Source/cmExecuteProcessCommand.cxx | 2 +- Source/cmExecuteProcessCommand.h | 13 +- Source/cmExecutionStatus.h | 31 +- Source/cmExpandedCommandArgument.h | 2 +- Source/cmExportBuildAndroidMKGenerator.h | 2 +- Source/cmExportBuildFileGenerator.cxx | 65 +- Source/cmExportBuildFileGenerator.h | 2 +- Source/cmExportCommand.cxx | 17 +- Source/cmExportCommand.h | 9 +- Source/cmExportFileGenerator.cxx | 34 +- Source/cmExportFileGenerator.h | 2 +- Source/cmExportInstallAndroidMKGenerator.h | 2 +- Source/cmExportInstallFileGenerator.cxx | 26 +- Source/cmExportInstallFileGenerator.h | 2 +- Source/cmExportLibraryDependenciesCommand.cxx | 9 +- Source/cmExportLibraryDependenciesCommand.h | 7 +- Source/cmExportSet.h | 2 +- Source/cmExportSetMap.h | 2 +- Source/cmExportTryCompileFileGenerator.h | 2 +- Source/cmExprParserHelper.cxx | 2 +- Source/cmExprParserHelper.h | 21 +- Source/cmExternalMakefileProjectGenerator.h | 2 +- Source/cmExtraCodeBlocksGenerator.cxx | 8 +- Source/cmExtraCodeBlocksGenerator.h | 2 +- Source/cmExtraCodeLiteGenerator.cxx | 109 +- Source/cmExtraCodeLiteGenerator.h | 6 +- Source/cmExtraEclipseCDT4Generator.cxx | 6 +- Source/cmExtraEclipseCDT4Generator.h | 2 +- Source/cmExtraKateGenerator.h | 2 +- Source/cmExtraSublimeTextGenerator.cxx | 2 +- Source/cmExtraSublimeTextGenerator.h | 2 +- Source/cmFLTKWrapUICommand.h | 8 +- Source/cmFileCommand.cxx | 182 +- Source/cmFileCommand.h | 14 +- Source/cmFileLock.h | 7 +- Source/cmFileLockPool.h | 18 +- Source/cmFileLockResult.h | 2 +- Source/cmFileMonitor.cxx | 20 +- Source/cmFileMonitor.h | 4 + Source/cmFilePathChecksum.cxx | 4 +- Source/cmFilePathChecksum.h | 6 +- Source/cmFileTimeComparison.cxx | 4 +- Source/cmFileTimeComparison.h | 2 +- Source/cmFindBase.cxx | 26 +- Source/cmFindBase.h | 3 +- Source/cmFindCommon.cxx | 52 +- Source/cmFindCommon.h | 12 +- Source/cmFindFileCommand.h | 4 +- Source/cmFindLibraryCommand.cxx | 39 +- Source/cmFindLibraryCommand.h | 13 +- Source/cmFindPackageCommand.cxx | 259 +- Source/cmFindPackageCommand.h | 16 +- Source/cmFindPathCommand.cxx | 6 +- Source/cmFindPathCommand.h | 13 +- Source/cmFindProgramCommand.cxx | 3 +- Source/cmFindProgramCommand.h | 15 +- Source/cmForEachCommand.cxx | 2 +- Source/cmForEachCommand.h | 13 +- Source/cmFortranParser.h | 9 +- Source/cmFortranParserImpl.cxx | 3 +- Source/cmFunctionCommand.cxx | 23 +- Source/cmFunctionCommand.h | 13 +- Source/cmGeneratedFileStream.cxx | 2 +- Source/cmGeneratedFileStream.h | 6 +- Source/cmGeneratorExpression.cxx | 8 +- Source/cmGeneratorExpression.h | 14 +- Source/cmGeneratorExpressionDAGChecker.h | 2 +- .../cmGeneratorExpressionEvaluationFile.cxx | 10 +- Source/cmGeneratorExpressionEvaluationFile.h | 9 +- Source/cmGeneratorExpressionEvaluator.h | 5 +- Source/cmGeneratorExpressionLexer.h | 2 +- Source/cmGeneratorExpressionNode.cxx | 171 +- Source/cmGeneratorExpressionNode.h | 2 +- Source/cmGeneratorExpressionParser.h | 2 +- Source/cmGeneratorTarget.cxx | 1203 ++--- Source/cmGeneratorTarget.h | 217 +- Source/cmGetCMakePropertyCommand.cxx | 2 +- Source/cmGetCMakePropertyCommand.h | 13 +- Source/cmGetDirectoryPropertyCommand.cxx | 3 +- Source/cmGetDirectoryPropertyCommand.h | 13 +- Source/cmGetFilenameComponentCommand.cxx | 6 +- Source/cmGetFilenameComponentCommand.h | 13 +- Source/cmGetPropertyCommand.cxx | 1 + Source/cmGetPropertyCommand.h | 13 +- Source/cmGetSourceFilePropertyCommand.cxx | 4 +- Source/cmGetSourceFilePropertyCommand.h | 11 +- Source/cmGetTargetPropertyCommand.cxx | 4 +- Source/cmGetTargetPropertyCommand.h | 8 +- Source/cmGetTestPropertyCommand.cxx | 4 +- Source/cmGetTestPropertyCommand.h | 8 +- Source/cmGhsMultiGpj.h | 2 +- Source/cmGhsMultiTargetGenerator.cxx | 8 +- Source/cmGlobalCommonGenerator.h | 2 +- Source/cmGlobalGenerator.cxx | 95 +- Source/cmGlobalGenerator.h | 28 +- Source/cmGlobalGeneratorFactory.h | 2 +- Source/cmGlobalGhsMultiGenerator.cxx | 2 +- Source/cmGlobalKdevelopGenerator.cxx | 6 +- Source/cmGlobalKdevelopGenerator.h | 2 +- Source/cmGlobalMSYSMakefileGenerator.cxx | 2 +- Source/cmGlobalNinjaGenerator.cxx | 71 +- Source/cmGlobalNinjaGenerator.h | 17 +- Source/cmGlobalUnixMakefileGenerator3.h | 4 +- Source/cmGlobalVisualStudio10Generator.cxx | 392 +- Source/cmGlobalVisualStudio10Generator.h | 33 +- Source/cmGlobalVisualStudio11Generator.h | 2 +- Source/cmGlobalVisualStudio12Generator.cxx | 16 +- Source/cmGlobalVisualStudio12Generator.h | 6 +- Source/cmGlobalVisualStudio14Generator.cxx | 53 +- Source/cmGlobalVisualStudio14Generator.h | 2 +- Source/cmGlobalVisualStudio15Generator.cxx | 4 +- Source/cmGlobalVisualStudio15Generator.h | 2 +- Source/cmGlobalVisualStudio71Generator.cxx | 83 +- Source/cmGlobalVisualStudio71Generator.h | 33 +- Source/cmGlobalVisualStudio7Generator.cxx | 54 +- Source/cmGlobalVisualStudio7Generator.h | 6 +- Source/cmGlobalVisualStudio8Generator.cxx | 24 +- Source/cmGlobalVisualStudio8Generator.h | 7 +- Source/cmGlobalVisualStudioGenerator.cxx | 102 +- Source/cmGlobalVisualStudioGenerator.h | 4 +- Source/cmGlobalWatcomWMakeGenerator.h | 2 +- Source/cmGlobalXCodeGenerator.cxx | 883 ++-- Source/cmGlobalXCodeGenerator.h | 22 +- Source/cmGraphAdjacencyList.h | 19 +- Source/cmGraphVizWriter.cxx | 4 +- Source/cmGraphVizWriter.h | 4 +- Source/cmHexFileConverter.cxx | 2 +- Source/cmIDEFlagTable.h | 3 + Source/cmIDEOptions.cxx | 10 +- Source/cmIDEOptions.h | 16 +- Source/cmIfCommand.cxx | 26 +- Source/cmIfCommand.h | 15 +- Source/cmIncludeCommand.h | 13 +- Source/cmIncludeDirectoryCommand.cxx | 2 +- Source/cmIncludeDirectoryCommand.h | 8 +- Source/cmIncludeExternalMSProjectCommand.h | 11 +- Source/cmIncludeRegularExpressionCommand.h | 11 +- Source/cmInstallCommand.cxx | 86 +- Source/cmInstallCommand.h | 8 +- Source/cmInstallCommandArguments.cxx | 2 +- Source/cmInstallCommandArguments.h | 2 +- Source/cmInstallDirectoryGenerator.cxx | 6 +- Source/cmInstallDirectoryGenerator.h | 10 +- Source/cmInstallExportGenerator.cxx | 4 +- Source/cmInstallExportGenerator.h | 8 +- Source/cmInstallFilesCommand.cxx | 6 +- Source/cmInstallFilesCommand.h | 8 +- Source/cmInstallFilesGenerator.cxx | 6 +- Source/cmInstallFilesGenerator.h | 9 +- Source/cmInstallGenerator.cxx | 2 +- Source/cmInstallGenerator.h | 6 +- Source/cmInstallProgramsCommand.h | 8 +- Source/cmInstallScriptGenerator.h | 2 +- Source/cmInstallTargetGenerator.cxx | 115 +- Source/cmInstallTargetGenerator.h | 37 +- Source/cmInstallTargetsCommand.h | 8 +- Source/cmInstalledFile.cxx | 2 +- Source/cmInstalledFile.h | 2 + Source/cmLinkDirectoriesCommand.cxx | 1 + Source/cmLinkDirectoriesCommand.h | 8 +- Source/cmLinkItem.h | 13 +- Source/cmLinkLibrariesCommand.h | 8 +- Source/cmLinkLineComputer.cxx | 2 +- Source/cmLinkLineComputer.h | 6 +- Source/cmLinkLineDeviceComputer.cxx | 34 +- Source/cmLinkLineDeviceComputer.h | 17 +- Source/cmLinkedTree.h | 2 +- Source/cmListCommand.cxx | 2 +- Source/cmListCommand.h | 13 +- Source/cmListFileCache.cxx | 22 +- Source/cmListFileCache.h | 14 +- Source/cmListFileLexer.h | 1 + Source/cmLoadCacheCommand.cxx | 2 +- Source/cmLoadCacheCommand.h | 8 +- Source/cmLoadCommandCommand.cxx | 25 +- Source/cmLoadCommandCommand.h | 4 +- Source/cmLocalCommonGenerator.cxx | 12 +- Source/cmLocalCommonGenerator.h | 3 +- Source/cmLocalGenerator.cxx | 188 +- Source/cmLocalGenerator.h | 21 +- Source/cmLocalNinjaGenerator.cxx | 30 +- Source/cmLocalNinjaGenerator.h | 6 +- Source/cmLocalUnixMakefileGenerator3.cxx | 44 +- Source/cmLocalUnixMakefileGenerator3.h | 2 +- Source/cmLocalVisualStudio10Generator.cxx | 2 +- Source/cmLocalVisualStudio10Generator.h | 2 +- Source/cmLocalVisualStudio7Generator.cxx | 206 +- Source/cmLocalVisualStudio7Generator.h | 6 +- Source/cmLocalVisualStudioGenerator.cxx | 24 +- Source/cmLocalVisualStudioGenerator.h | 2 +- Source/cmLocalXCodeGenerator.h | 3 +- Source/cmLocale.h | 7 +- Source/cmMSVC60LinkLineComputer.cxx | 6 +- Source/cmMSVC60LinkLineComputer.h | 6 +- Source/cmMachO.cxx | 2 +- Source/cmMachO.h | 2 +- Source/cmMacroCommand.cxx | 26 +- Source/cmMacroCommand.h | 13 +- Source/cmMakeDirectoryCommand.h | 13 +- Source/cmMakefile.cxx | 142 +- Source/cmMakefile.h | 33 +- .../cmMakefileExecutableTargetGenerator.cxx | 25 +- Source/cmMakefileExecutableTargetGenerator.h | 4 +- Source/cmMakefileLibraryTargetGenerator.cxx | 80 +- Source/cmMakefileLibraryTargetGenerator.h | 2 +- Source/cmMakefileTargetGenerator.cxx | 103 +- Source/cmMakefileTargetGenerator.h | 7 +- Source/cmMakefileUtilityTargetGenerator.h | 2 +- Source/cmMarkAsAdvancedCommand.cxx | 2 +- Source/cmMarkAsAdvancedCommand.h | 16 +- Source/cmMathCommand.h | 13 +- Source/cmMessageCommand.h | 13 +- Source/cmMessenger.cxx | 2 +- Source/cmMessenger.h | 2 +- Source/cmNewLineStyle.cxx | 2 +- Source/cmNewLineStyle.h | 2 +- Source/cmNinjaLinkLineComputer.cxx | 3 +- Source/cmNinjaLinkLineComputer.h | 6 +- Source/cmNinjaNormalTargetGenerator.cxx | 170 +- Source/cmNinjaNormalTargetGenerator.h | 2 +- Source/cmNinjaTargetGenerator.cxx | 103 +- Source/cmNinjaTargetGenerator.h | 5 +- Source/cmNinjaTypes.h | 8 +- Source/cmNinjaUtilityTargetGenerator.h | 2 +- Source/cmOSXBundleGenerator.cxx | 35 +- Source/cmOSXBundleGenerator.h | 2 +- Source/cmOptionCommand.h | 13 +- Source/cmOrderDirectories.cxx | 2 +- Source/cmOrderDirectories.h | 4 +- Source/cmOutputConverter.cxx | 4 +- Source/cmOutputConverter.h | 6 +- Source/cmOutputRequiredFilesCommand.cxx | 13 +- Source/cmOutputRequiredFilesCommand.h | 4 +- Source/cmParseArgumentsCommand.h | 13 +- Source/cmPathLabel.h | 2 +- Source/cmPolicies.cxx | 18 +- Source/cmPolicies.h | 15 +- Source/cmProcessOutput.h | 2 +- Source/cmProcessTools.cxx | 2 +- Source/cmProcessTools.h | 2 +- Source/cmProjectCommand.cxx | 74 +- Source/cmProjectCommand.h | 8 +- Source/cmProperty.cxx | 2 +- Source/cmProperty.h | 2 +- Source/cmPropertyDefinition.h | 2 +- Source/cmPropertyDefinitionMap.h | 2 +- Source/cmPropertyMap.cxx | 2 +- Source/cmPropertyMap.h | 2 +- Source/cmQTWrapCPPCommand.h | 8 +- Source/cmQTWrapUICommand.h | 8 +- Source/cmQtAutoGeneratorCommon.cxx | 216 + Source/cmQtAutoGeneratorCommon.h | 39 + Source/cmQtAutoGeneratorInitializer.cxx | 1295 +++--- Source/cmQtAutoGeneratorInitializer.h | 2 +- Source/cmQtAutoGenerators.cxx | 2326 ++++++---- Source/cmQtAutoGenerators.h | 255 +- Source/cmRST.cxx | 22 +- Source/cmRST.h | 4 +- Source/cmRemoveCommand.cxx | 2 +- Source/cmRemoveCommand.h | 13 +- Source/cmRemoveDefinitionsCommand.h | 8 +- Source/cmReturnCommand.cxx | 2 +- Source/cmReturnCommand.h | 13 +- Source/cmRulePlaceholderExpander.cxx | 26 +- Source/cmRulePlaceholderExpander.h | 5 +- Source/cmScriptGenerator.cxx | 14 +- Source/cmScriptGenerator.h | 18 +- Source/cmSearchPath.h | 2 +- Source/cmSeparateArgumentsCommand.cxx | 7 + Source/cmSeparateArgumentsCommand.h | 13 +- Source/cmServer.cxx | 21 +- Source/cmServer.h | 7 +- Source/cmServerConnection.cxx | 3 +- Source/cmServerConnection.h | 12 +- Source/cmServerProtocol.cxx | 58 +- Source/cmServerProtocol.h | 16 +- Source/cmSetCommand.h | 13 +- Source/cmSetDirectoryPropertiesCommand.h | 16 +- Source/cmSetPropertyCommand.cxx | 12 +- Source/cmSetPropertyCommand.h | 13 +- Source/cmSetSourceFilesPropertiesCommand.h | 11 +- Source/cmSetTargetPropertiesCommand.cxx | 3 +- Source/cmSetTargetPropertiesCommand.h | 8 +- Source/cmSetTestsPropertiesCommand.cxx | 3 +- Source/cmSetTestsPropertiesCommand.h | 8 +- Source/cmSiteNameCommand.cxx | 2 +- Source/cmSiteNameCommand.h | 13 +- Source/cmSourceFile.h | 2 +- Source/cmSourceFileLocation.cxx | 2 +- Source/cmSourceFileLocation.h | 2 +- Source/cmSourceGroup.h | 4 +- Source/cmSourceGroupCommand.cxx | 79 +- Source/cmSourceGroupCommand.h | 8 +- Source/cmStandardIncludes.h | 53 - Source/cmStandardLexer.h | 4 +- Source/cmState.cxx | 158 +- Source/cmState.h | 44 +- Source/cmStateDirectory.h | 2 +- Source/cmStatePrivate.h | 7 +- Source/cmStateSnapshot.cxx | 12 +- Source/cmStateSnapshot.h | 4 +- Source/cmStateTypes.h | 11 +- Source/cmStringCommand.cxx | 24 +- Source/cmStringCommand.h | 13 +- Source/cmSubdirCommand.h | 8 +- Source/cmSubdirDependsCommand.cxx | 5 - Source/cmSubdirDependsCommand.h | 4 +- Source/cmSystemTools.cxx | 163 +- Source/cmSystemTools.h | 26 +- Source/cmTarget.cxx | 199 +- Source/cmTarget.h | 10 +- Source/cmTargetCompileDefinitionsCommand.h | 11 +- Source/cmTargetCompileFeaturesCommand.h | 5 +- Source/cmTargetCompileOptionsCommand.h | 8 +- Source/cmTargetDepend.h | 4 +- Source/cmTargetExport.h | 3 +- Source/cmTargetIncludeDirectoriesCommand.h | 11 +- Source/cmTargetLinkLibrariesCommand.h | 8 +- Source/cmTargetPropCommandBase.cxx | 2 +- Source/cmTargetPropCommandBase.h | 2 +- Source/cmTargetPropertyComputer.h | 2 +- Source/cmTargetSourcesCommand.h | 8 +- Source/cmTest.h | 2 +- Source/cmTestGenerator.cxx | 14 +- Source/cmTestGenerator.h | 17 +- Source/cmTimestamp.cxx | 2 +- Source/cmTimestamp.h | 2 +- Source/cmTryCompileCommand.h | 8 +- Source/cmTryRunCommand.cxx | 2 +- Source/cmTryRunCommand.h | 8 +- Source/cmUnexpectedCommand.h | 7 +- Source/cmUnsetCommand.h | 13 +- Source/cmUseMangledMesaCommand.cxx | 10 +- Source/cmUseMangledMesaCommand.h | 6 +- Source/cmUtilitySourceCommand.cxx | 12 +- Source/cmUtilitySourceCommand.h | 4 +- Source/cmUtils.hxx | 2 +- Source/cmUuid.h | 2 +- Source/cmVS10CudaFlagTable.h | 51 + Source/cmVS10CudaHostFlagTable.h | 35 + Source/cmVS10MASMFlagTable.h | 76 +- Source/cmVS10NASMFlagTable.h | 50 + Source/cmVS10RCFlagTable.h | 1 + Source/cmVS11MASMFlagTable.h | 76 +- Source/cmVS11RCFlagTable.h | 1 + Source/cmVS12MASMFlagTable.h | 76 +- Source/cmVS12RCFlagTable.h | 1 + ...LinkFlagTable.h => cmVS140LinkFlagTable.h} | 12 +- Source/cmVS141LinkFlagTable.h | 283 ++ Source/cmVS14MASMFlagTable.h | 76 +- Source/cmVS14RCFlagTable.h | 1 + Source/cmVSSetupHelper.cxx | 28 + Source/cmVariableRequiresCommand.cxx | 10 +- Source/cmVariableRequiresCommand.h | 4 +- Source/cmVariableWatch.cxx | 2 +- Source/cmVariableWatch.h | 2 +- Source/cmVariableWatchCommand.cxx | 2 +- Source/cmVariableWatchCommand.h | 13 +- Source/cmVersion.h | 2 +- Source/cmVisualStudio10TargetGenerator.cxx | 833 ++-- Source/cmVisualStudio10TargetGenerator.h | 25 +- Source/cmVisualStudio10ToolsetOptions.cxx | 9 +- Source/cmVisualStudio10ToolsetOptions.h | 2 +- Source/cmVisualStudioGeneratorOptions.cxx | 177 +- Source/cmVisualStudioGeneratorOptions.h | 29 +- Source/cmVisualStudioSlnData.h | 2 +- Source/cmVisualStudioSlnParser.cxx | 2 +- Source/cmVisualStudioSlnParser.h | 2 +- Source/cmVisualStudioWCEPlatformParser.h | 2 +- Source/cmWhileCommand.cxx | 2 +- Source/cmWhileCommand.h | 13 +- Source/cmWorkingDirectory.cxx | 24 + Source/cmWorkingDirectory.h | 25 + Source/cmWriteFileCommand.cxx | 9 +- Source/cmWriteFileCommand.h | 13 +- Source/cmXCode21Object.h | 2 +- Source/cmXCodeObject.cxx | 4 +- Source/cmXCodeObject.h | 2 +- Source/cmXCodeScheme.cxx | 227 + Source/cmXCodeScheme.h | 50 + Source/cmXMLParser.cxx | 4 +- Source/cmXMLParser.h | 2 +- Source/cmXMLSafe.h | 2 +- Source/cmXMLWriter.cxx | 13 +- Source/cmXMLWriter.h | 10 +- Source/cm_auto_ptr.hxx | 12 +- Source/cm_codecvt.cxx | 290 +- Source/cm_codecvt.hxx | 30 +- Source/cm_sys_stat.h | 14 + Source/cm_unordered_map.hxx | 4 +- Source/cm_unordered_set.hxx | 4 +- Source/cm_utf8.c | 2 +- Source/cmake.cxx | 85 +- Source/cmake.h | 22 +- Source/cmakemain.cxx | 45 +- Source/cmakexbuild.cxx | 9 +- Source/cmcldeps.cxx | 4 +- Source/cmcmd.cxx | 74 +- Source/cmcmd.h | 2 +- Source/ctest.cxx | 24 +- Source/kwsys/.gitattributes | 17 +- Source/kwsys/Base64.c | 10 - Source/kwsys/CMakeLists.txt | 21 +- Source/kwsys/CONTRIBUTING.rst | 10 +- Source/kwsys/CommandLineArguments.cxx | 88 +- Source/kwsys/ConsoleBuf.hxx.in | 12 +- Source/kwsys/Directory.cxx | 9 +- Source/kwsys/DynamicLoader.cxx | 34 - Source/kwsys/Encoding.hxx.in | 13 +- Source/kwsys/EncodingCXX.cxx | 66 +- Source/kwsys/FStream.hxx.in | 10 +- Source/kwsys/Glob.cxx | 12 - Source/kwsys/MD5.c | 10 - Source/kwsys/Process.h.in | 73 +- Source/kwsys/ProcessUNIX.c | 233 +- Source/kwsys/ProcessWin32.c | 253 +- Source/kwsys/SharedForward.h.in | 18 - Source/kwsys/System.c | 4 - Source/kwsys/SystemInformation.cxx | 423 +- Source/kwsys/SystemInformation.hxx.in | 30 +- Source/kwsys/SystemTools.cxx | 247 +- Source/kwsys/SystemTools.hxx.in | 41 +- Source/kwsys/Terminal.c | 10 - Source/kwsys/kwsysPlatformTestsC.c | 3 - Source/kwsys/testConsoleBuf.cxx | 23 +- Source/kwsys/testConsoleBufChild.cxx | 1 - Source/kwsys/testEncoding.cxx | 86 +- Source/kwsys/testFStream.cxx | 3 - Source/kwsys/testSystemInformation.cxx | 2 +- Source/kwsys/testSystemTools.cxx | 107 +- Templates/MSBuild/nasm.props.in | 17 + Templates/MSBuild/nasm.targets | 41 + Templates/MSBuild/nasm.xml | 110 + Templates/TestDriver.cxx.in | 6 +- Tests/BuildDepends/CMakeLists.txt | 2 +- .../target_compile_features/CMakeLists.txt | 70 +- .../target_compile_features/dummy.cpp | 5 - .../target_link_libraries/empty.cpp | 4 +- Tests/CMakeLib/CMakeLists.txt | 10 - Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt | 15 - .../PseudoMemcheck/NoLog/CMakeLists.txt | 8 - .../CMakeLib/PseudoMemcheck/memtester.cxx.in | 2 +- Tests/CMakeLib/run_compile_commands.cxx | 2 +- Tests/CMakeLib/testEncoding.cxx | 8 +- Tests/CMakeLib/testRST.cxx | 2 +- Tests/CMakeLists.txt | 64 +- Tests/CMakeOnly/AllFindModules/CMakeLists.txt | 11 +- Tests/CMakeOnly/CMakeLists.txt | 17 +- Tests/CMakeOnly/find_library/CMakeLists.txt | 31 +- .../find_library/lib/A/libXYZ/libtest2.a} | 0 .../find_library/lib/A/libx32/libtest3.a} | 0 .../CMakeOnly/find_library/lib/XYZ/libtest1.a | 0 .../CMakeOnly/find_library/lib/x32/libtest2.a | 0 .../find_library/libXYZ/A/lib/libtest4.a | 0 .../find_library/libXYZ/A/libXYZ/libtest5.a | 0 .../find_library/libXYZ/A/libtest6.a | 0 .../CMakeOnly/find_library/libXYZ/libtest7.a | 0 .../find_library/libx32/A/lib/libtest2.a | 0 .../find_library/libx32/A/libtest1.a | 0 .../find_library/libx32/A/libx32/libtest1.a | 0 .../CMakeOnly/find_library/libx32/libtest1.a | 0 Tests/CMakeTestAllGenerators/RunCMake.cmake | 57 +- Tests/CMakeTests/CMakeLists.txt | 6 +- .../CMakeTests/CompilerIdVendorTest.cmake.in | 4 +- .../FileDownloadBadHashTest.cmake.in | 5 +- Tests/CMakeTests/FileDownloadTest.cmake.in | 5 +- Tests/CMakeTests/FileUploadTest.cmake.in | 5 +- .../CMakeTests/GetPrerequisitesTest.cmake.in | 7 +- .../CMakeTests/ImplicitLinkInfoTest.cmake.in | 105 +- .../CMakeTests/SeparateArgumentsTest.cmake.in | 25 - Tests/CMakeTests/ToolchainTest.cmake.in | 1 - Tests/CPackComponents/CMakeLists.txt | 2 +- Tests/CSharpLinkToCxx/CMakeLists.txt | 17 + Tests/CSharpLinkToCxx/cli.cpp | 10 + Tests/CSharpLinkToCxx/cli.hpp | 10 + Tests/CSharpLinkToCxx/csharp.cs | 16 + Tests/CheckFortran.cmake | 2 + Tests/CompileFeatures/CMakeLists.txt | 33 +- Tests/CompileFeatures/default_dialect.c | 3 +- Tests/Cuda/Complex/CMakeLists.txt | 8 + Tests/Cuda/Complex/dynamic.cu | 43 +- Tests/Cuda/Complex/file3.cu | 36 +- Tests/Cuda/Complex/main.cpp | 12 +- Tests/Cuda/Complex/mixed.cu | 36 +- Tests/Cuda/ObjectLibrary/CMakeLists.txt | 5 + Tests/Cuda/ObjectLibrary/main.cpp | 8 +- Tests/Cuda/ObjectLibrary/static.cu | 4 +- Tests/CudaOnly/CMakeLists.txt | 2 + Tests/CudaOnly/ExportPTX/CMakeLists.txt | 82 + Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake | 19 + Tests/CudaOnly/ExportPTX/kernelA.cu | 7 + Tests/CudaOnly/ExportPTX/kernelB.cu | 8 + Tests/CudaOnly/ExportPTX/main.cu | 28 + .../ResolveDeviceSymbols/CMakeLists.txt | 52 + Tests/CudaOnly/ResolveDeviceSymbols/file1.cu | 10 + Tests/CudaOnly/ResolveDeviceSymbols/file1.h | 7 + Tests/CudaOnly/ResolveDeviceSymbols/file2.cu | 25 + Tests/CudaOnly/ResolveDeviceSymbols/file2.h | 10 + Tests/CudaOnly/ResolveDeviceSymbols/main.cu | 85 + .../ResolveDeviceSymbols/verify.cmake | 14 + .../SeparateCompilation/CMakeLists.txt | 42 +- Tests/CudaOnly/SeparateCompilation/main.cu | 53 + Tests/CudaOnly/WithDefs/CMakeLists.txt | 12 +- Tests/CudaOnly/WithDefs/main.notcu | 4 + Tests/CudaOnly/WithDefs/main_for_vs.cu | 1 + .../CustomCommandByproducts/ninja-check.cmake | 2 +- .../CMakeLists.txt | 2 + Tests/ExportImport/Export/CMakeLists.txt | 13 +- Tests/ExportImport/Export/sub/testLib8C.c | 4 + Tests/ExportImport/Export/testLib8A.c | 4 + Tests/ExportImport/Export/testLib8B.c | 4 + Tests/ExportImport/Export/testLibNoSONAME.c | 2 +- Tests/ExportImport/Import/A/CMakeLists.txt | 10 + Tests/ExportImport/Import/A/imp_testExe1.c | 24 +- Tests/ExportImport/Import/A/imp_testLib8.c | 8 + Tests/ExternalProject/CMakeLists.txt | 10 + Tests/FindDoxygen/CMakeLists.txt | 20 + .../DotComponentTestTest/CMakeLists.txt | 18 + Tests/FindDoxygen/SimpleTest/CMakeLists.txt | 59 + Tests/FindDoxygen/SimpleTest/main.cpp | 4 + .../SimpleTest/spaces_in_name.cpp.in | 4 + Tests/FindGTest/Test/CMakeLists.txt | 3 - Tests/FindMPI/CMakeLists.txt | 21 + Tests/FindMPI/Test/CMakeLists.txt | 41 + Tests/FindMPI/Test/main.c | 7 + Tests/FindMPI/Test/main.f90 | 7 + Tests/FindModulesExecuteAll/CMakeLists.txt | 2 +- Tests/FindOpenMP/CMakeLists.txt | 21 + Tests/FindOpenMP/Test/CMakeLists.txt | 69 + Tests/FindOpenMP/Test/main.c | 7 + Tests/FindOpenMP/Test/main.f90.in | 5 + Tests/FindOpenMP/Test/scalprod.c | 16 + Tests/FindOpenMP/Test/scalprod.f90.in | 19 + Tests/FindOpenMP/Test/scaltest.c | 20 + Tests/FindOpenMP/Test/scaltest.f90.in | 21 + Tests/FindProtobuf/CMakeLists.txt | 10 + Tests/FindProtobuf/Test/CMakeLists.txt | 32 + Tests/FindProtobuf/Test/main-protoc.cxx | 8 + Tests/FindProtobuf/Test/main.cxx | 8 + Tests/FindTIFF/Test/CMakeLists.txt | 3 - Tests/FindXalanC/Test/CMakeLists.txt | 3 - Tests/FindXercesC/Test/CMakeLists.txt | 3 - Tests/GeneratorExpression/CMakeLists.txt | 16 + .../check_object_files.cmake | 26 + Tests/GeneratorExpression/objlib1.c | 4 + Tests/GeneratorExpression/objlib2.c | 4 + Tests/GoogleTest/CMakeLists.txt | 10 + Tests/GoogleTest/Test/CMakeLists.txt | 95 + Tests/GoogleTest/Test/main1.cxx | 30 + Tests/GoogleTest/Test/main2.cxx | 1 + Tests/GoogleTest/Test/main2.h | 21 + Tests/GoogleTest/Test/main3.cxx | 11 + Tests/GoogleTest/Test/main4.cxx | 1 + Tests/GoogleTest/Test/main4.h | 6 + .../BuildExport/CMakeLists.txt | 5 +- Tests/JavaExportImport/Import/CMakeLists.txt | 2 +- .../InstallExport/CMakeLists.txt | 1 + .../Module/CheckIPOSupported-C/CMakeLists.txt | 19 + Tests/Module/CheckIPOSupported-C/foo.c | 4 + Tests/Module/CheckIPOSupported-C/main.c | 9 + .../CheckIPOSupported-CXX/CMakeLists.txt | 19 + Tests/Module/CheckIPOSupported-CXX/foo.cpp | 4 + Tests/Module/CheckIPOSupported-CXX/main.cpp | 9 + .../CheckIPOSupported-Fortran/CMakeLists.txt | 19 + Tests/Module/CheckIPOSupported-Fortran/foo.f | 2 + Tests/Module/CheckIPOSupported-Fortran/main.f | 3 + .../CMakeLists.txt | 13 +- .../WriteCompilerDetectionHeader/main.cpp | 3 + .../multi_files.cpp | 3 + Tests/ModuleDefinition/CMakeLists.txt | 9 +- Tests/ModuleDefinition/example_exe.c | 6 +- Tests/ModuleDefinition/split_dll.c | 9 + Tests/ModuleDefinition/split_dll_1.def | 2 + Tests/ModuleDefinition/split_dll_2.def | 2 + Tests/ObjectLibrary/CMakeLists.txt | 6 +- Tests/Plugin/CMakeLists.txt | 6 +- Tests/Preprocess/CMakeLists.txt | 10 +- Tests/QtAutoUicInterface/CMakeLists.txt | 10 +- Tests/QtAutogen/CMakeLists.txt | 248 +- Tests/QtAutogen/automoc_rerun/CMakeLists.txt | 27 - Tests/QtAutogen/automoc_rerun/test1.cpp | 5 - Tests/QtAutogen/automoc_rerun/test1.h.in1 | 8 - Tests/QtAutogen/automoc_rerun/test1.h.in2 | 7 - .../QtAutogen/autorcc_depends/CMakeLists.txt | 27 - Tests/QtAutogen/mocDepends/CMakeLists.txt | 47 + Tests/QtAutogen/mocDepends/invalid.hpp.in | 1 + Tests/QtAutogen/mocDepends/object.hpp.in | 14 + Tests/QtAutogen/mocDepends/simpleLib.cpp.in | 9 + Tests/QtAutogen/mocDepends/simpleLib.hpp.in | 11 + Tests/QtAutogen/mocDepends/test1.cpp | 9 + Tests/QtAutogen/mocDepends/test2.cpp | 10 + Tests/QtAutogen/mocDepends/test2.hpp | 16 + Tests/QtAutogen/mocInclude/ObjA.cpp | 24 + Tests/QtAutogen/mocInclude/ObjA.hpp | 13 + Tests/QtAutogen/mocInclude/ObjB.cpp | 25 + Tests/QtAutogen/mocInclude/ObjB.hpp | 13 + Tests/QtAutogen/mocInclude/ObjC.cpp | 26 + Tests/QtAutogen/mocInclude/ObjC.hpp | 13 + Tests/QtAutogen/mocInclude/ObjD.cpp | 26 + Tests/QtAutogen/mocInclude/ObjD.hpp | 13 + Tests/QtAutogen/mocInclude/subA/SubObjA.cpp | 27 + Tests/QtAutogen/mocInclude/subA/SubObjA.hpp | 16 + Tests/QtAutogen/mocInclude/subB/SubObjB.cpp | 27 + Tests/QtAutogen/mocInclude/subB/SubObjB.hpp | 16 + Tests/QtAutogen/mocInclude/subC/SubObjC.cpp | 27 + Tests/QtAutogen/mocInclude/subC/SubObjC.hpp | 16 + .../mocIncludeRelaxed/CMakeLists.txt | 18 + Tests/QtAutogen/mocIncludeRelaxed/main.cpp | 14 + .../QtAutogen/mocIncludeStrict/CMakeLists.txt | 18 + Tests/QtAutogen/mocIncludeStrict/main.cpp | 14 + Tests/QtAutogen/mocPlugin/CMakeLists.txt | 33 + Tests/QtAutogen/mocPlugin/StyleA.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleA.hpp | 17 + Tests/QtAutogen/mocPlugin/StyleA.json | 1 + Tests/QtAutogen/mocPlugin/StyleA_Custom.json | 1 + Tests/QtAutogen/mocPlugin/StyleB.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleB.hpp | 17 + Tests/QtAutogen/mocPlugin/StyleC.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleC.hpp | 17 + Tests/QtAutogen/mocPlugin/StyleCommon.hpp | 7 + Tests/QtAutogen/mocPlugin/StyleD.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleD.hpp | 17 + Tests/QtAutogen/mocPlugin/StyleE.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleE.hpp | 17 + Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json | 1 + .../mocPlugin/jsonIn/StyleB_Custom.json | 1 + Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json | 1 + Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json | 1 + Tests/QtAutogen/mocPlugin/main.cpp | 6 + Tests/QtAutogen/mocRerun/CMakeLists.txt | 35 + .../{automoc_rerun => mocRerun}/input.txt | 0 Tests/QtAutogen/mocRerun/main.cpp.in | 18 + .../{automoc_rerun => mocRerun}/res1.qrc | 0 Tests/QtAutogen/mocRerun/test1a.h.in | 8 + Tests/QtAutogen/mocRerun/test1b.h.in | 7 + Tests/QtAutogen/rccDepends/CMakeLists.txt | 35 + .../test_res1.cpp => rccDepends/main.cpp} | 0 .../res/input1.txt.in} | 0 Tests/QtAutogen/rccDepends/res/input2.txt.in | 1 + .../res1.qrc.in => rccDepends/res1a.qrc.in} | 2 +- Tests/QtAutogen/rccDepends/res1b.qrc.in | 6 + Tests/QtAutogen/rccDepends/res2a.qrc.in | 5 + Tests/QtAutogen/rccDepends/res2b.qrc.in | 6 + Tests/QtAutogen/sameName/CMakeLists.txt | 11 + Tests/QtAutogen/uicInclude/CMakeLists.txt | 8 + Tests/QtAutogen/uicInclude/PageC.ui | 24 + Tests/QtAutogen/uicInclude/dirA/PageA.ui | 24 + Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui | 24 + Tests/QtAutogen/uicInclude/main.cpp | 10 + Tests/QtAutogen/uicInclude/main.hpp | 6 + Tests/RunCMake/Android/android_sysinc.c | 7 + Tests/RunCMake/Android/android_sysinc.cxx | 7 + Tests/RunCMake/Android/common.cmake | 16 + Tests/RunCMake/Android/sysinc/dlfcn.h | 1 + Tests/RunCMake/AutoExportDll/AutoExport.cmake | 6 + Tests/RunCMake/AutoExportDll/nop.asm | 12 + Tests/RunCMake/AutoExportDll/say.cxx | 4 + .../BuildDepends/MakeCustomIncludes.cmake | 13 + .../BuildDepends/MakeCustomIncludes.cxx | 6 + .../MakeCustomIncludes.step1.cmake | 3 + .../MakeCustomIncludes.step2.cmake | 3 + .../RunCMake/BuildDepends/RunCMakeTest.cmake | 10 +- Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt | 10 + .../CMP0022/CMP0022-WARN-tll-stderr.txt | 4 +- Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake | 2 + .../CMP0026-CONFIG-LOCATION-OLD-stderr.txt | 10 + .../CMP0026-LOCATION-CONFIG-OLD-stderr.txt | 10 + Tests/RunCMake/CMP0026/CMP0026-OLD-stderr.txt | 10 + Tests/RunCMake/CMP0026/CMP0026-OLD.cmake | 12 + Tests/RunCMake/CMP0026/RunCMakeTest.cmake | 1 + .../clear-cached-information-stderr.txt | 10 + .../CMP0028/CMP0028-OLD-iface-stderr.txt | 10 + Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt | 10 + Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt | 1 + Tests/RunCMake/CMP0068/CMP0068-NEW.cmake | 6 + Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt | 1 + Tests/RunCMake/CMP0068/CMP0068-OLD.cmake | 6 + .../RunCMake/CMP0068/CMP0068-WARN-result.txt | 1 + .../RunCMake/CMP0068/CMP0068-WARN-stderr.txt | 12 + Tests/RunCMake/CMP0068/CMP0068-WARN.cmake | 12 + Tests/RunCMake/CMP0068/CMakeLists.txt | 3 + Tests/RunCMake/CMP0068/RunCMakeTest.cmake | 5 + Tests/RunCMake/CMP0068/empty.cpp | 7 + .../CMP0069-NEW-cmake-result.txt} | 0 .../CMP0069/CMP0069-NEW-cmake-stderr.txt | 4 + .../RunCMake/CMP0069/CMP0069-NEW-cmake.cmake | 6 + .../CMP0069-NEW-compiler-result.txt} | 0 .../CMP0069/CMP0069-NEW-compiler-stderr.txt | 4 + .../CMP0069/CMP0069-NEW-compiler.cmake | 7 + .../CMP0069-NEW-generator-result.txt} | 0 .../CMP0069/CMP0069-NEW-generator-stderr.txt | 4 + .../CMP0069/CMP0069-NEW-generator.cmake | 7 + Tests/RunCMake/CMP0069/CMP0069-OLD.cmake | 4 + .../RunCMake/CMP0069/CMP0069-WARN-stderr.txt | 9 + Tests/RunCMake/CMP0069/CMP0069-WARN.cmake | 4 + Tests/RunCMake/CMP0069/CMakeLists.txt | 3 + Tests/RunCMake/CMP0069/RunCMakeTest.cmake | 10 + Tests/RunCMake/CMP0069/main.cpp | 3 + Tests/RunCMake/CMakeLists.txt | 44 +- .../CPack/ArchiveCommon/common_helpers.cmake | 2 +- Tests/RunCMake/CPack/RunCMakeTest.cmake | 4 +- Tests/RunCMake/CPack/STGZ/Helpers.cmake | 2 +- Tests/RunCMake/CPack/VerifyResult.cmake | 6 +- .../tests/CUSTOM_NAMES/ExpectedFiles.cmake | 3 + .../CPack/tests/CUSTOM_NAMES/test.cmake | 3 + .../CPack/tests/DEBUGINFO/ExpectedFiles.cmake | 8 +- .../RunCMake/CPack/tests/DEBUGINFO/test.cmake | 10 + .../EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake | 16 + .../EXTRA_SLASH_IN_PATH/VerifyResult.cmake | 7 + .../tests/EXTRA_SLASH_IN_PATH/test.cmake | 37 + .../CPack/tests/SYMLINKS/ExpectedFiles.cmake | 13 + .../tests/SYMLINKS/TGZ-Prerequirements.cmake | 5 + .../CPack/tests/SYMLINKS/VerifyResult.cmake | 26 + .../RunCMake/CPack/tests/SYMLINKS/test.cmake | 14 + .../RunCMake/CheckIPOSupported/CMakeLists.txt | 7 + .../CheckIPOSupported/RunCMakeTest.cmake | 13 + .../cmp0069-is-old-result.txt} | 0 .../cmp0069-is-old-stderr.txt | 5 + .../CheckIPOSupported/cmp0069-is-old.cmake | 6 + .../default-lang-none-result.txt} | 0 .../default-lang-none-stderr.txt | 7 + .../CheckIPOSupported/default-lang-none.cmake | 1 + .../not-supported-by-cmake-result.txt} | 0 .../not-supported-by-cmake-stderr.txt | 6 + .../not-supported-by-cmake.cmake | 3 + .../not-supported-by-compiler-result.txt} | 0 .../not-supported-by-compiler-stderr.txt | 6 + .../not-supported-by-compiler.cmake | 4 + .../not-supported-by-generator-result.txt} | 0 .../not-supported-by-generator-stderr.txt | 6 + .../not-supported-by-generator.cmake | 6 + .../CheckIPOSupported/save-to-result.cmake | 22 + .../unparsed-arguments-result.txt} | 0 .../unparsed-arguments-stderr.txt | 5 + .../unparsed-arguments.cmake | 1 + .../user-lang-unknown-result.txt | 1 + .../user-lang-unknown-stderr.txt | 6 + .../CheckIPOSupported/user-lang-unknown.cmake | 1 + .../DeprecateVS71-WARN-ON-stderr.txt | 5 - .../CommandLine/DeprecateVS8-WARN-OFF.cmake | 0 .../DeprecateVS8-WARN-ON-stderr.txt | 5 + .../CommandLine/DeprecateVS8-WARN-ON.cmake | 0 Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 23 +- .../CommandLine/reject_fifo-result.txt | 1 + .../CommandLine/reject_fifo-stderr.txt | 2 + .../LinkImplementationFeatureCycle.cmake | 5 +- .../CompileFeatures/RunCMakeTest.cmake | 5 +- .../DisallowedCommands/CMP0029-OLD-stderr.txt | 10 + .../DisallowedCommands/CMP0030-OLD-stderr.txt | 13 +- ...FeatureSummaryCustomDescription-stdout.txt | 91 + .../FeatureSummaryCustomDescription.cmake | 158 + ...eatureSummaryDefaultDescription-stdout.txt | 46 + .../FeatureSummaryDefaultDescription.cmake | 82 + .../FeatureSummary/RunCMakeTest.cmake | 2 + .../File_Generate/OutputConflict-stderr.txt | 5 +- .../OutputNameMatchesObjects-stderr.txt | 7 +- .../OutputNameMatchesObjects.cmake | 1 + .../RunCMake/File_Generate/RunCMakeTest.cmake | 2 +- .../FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake | 5 +- .../FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake | 5 +- .../FindPkgConfig_PKGCONFIG_PATH.cmake | 5 +- ...ONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake | 5 +- ...gConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake | 5 +- .../FindPkgConfig/dummy-pkg-config.bat | 11 +- .../FindPkgConfig/dummy-pkg-config.sh | 32 +- .../pc-bar/libx32/pkgconfig/.placeholder | 0 .../pc-foo/libx32/pkgconfig/.placeholder | 0 .../RunCMake/Framework/FrameworkLayout.cmake | 13 +- .../FrameworkTypeSHARED-build-stdout.txt | 4 +- .../FrameworkTypeSTATIC-build-stdout.txt | 3 +- .../OSXFrameworkLayout-build-check.cmake | 17 +- Tests/RunCMake/Framework/RunCMakeTest.cmake | 11 +- Tests/RunCMake/Framework/deepresource.txt | 0 Tests/RunCMake/Framework/flatresource.txt | 0 .../iOSFrameworkLayout-build-check.cmake | 17 +- Tests/RunCMake/Framework/some.txt | 0 Tests/RunCMake/GNUInstallDirs/Common.cmake | 4 +- .../GNUInstallDirs/Opt-BSD-stderr.txt | 30 + Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt | 2 + .../GNUInstallDirs/Root-BSD-stderr.txt | 30 + Tests/RunCMake/GNUInstallDirs/Root-stderr.txt | 2 + .../GNUInstallDirs/RunCMakeTest.cmake | 19 +- .../GNUInstallDirs/Usr-BSD-stderr.txt | 30 + Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt | 2 + .../GNUInstallDirs/UsrLocal-BSD-stderr.txt | 30 + .../GNUInstallDirs/UsrLocal-stderr.txt | 2 + Tests/RunCMake/GenerateExportHeader/GEH.cmake | 2 +- ...arget-TARGET_BUNDLE_CONTENT_DIR-result.txt | 1 + ...arget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt | 8 + ...rtedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake | 2 + ...mportedTarget-TARGET_BUNDLE_DIR-result.txt | 1 + ...mportedTarget-TARGET_BUNDLE_DIR-stderr.txt | 8 + .../ImportedTarget-TARGET_BUNDLE_DIR.cmake | 2 + ...arget-TARGET_BUNDLE_CONTENT_DIR-result.txt | 1 + ...arget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt | 8 + ...alidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake | 9 + ...onValidTarget-TARGET_BUNDLE_DIR-result.txt | 1 + ...onValidTarget-TARGET_BUNDLE_DIR-stderr.txt | 8 + .../NonValidTarget-TARGET_BUNDLE_DIR.cmake | 9 + .../GeneratorExpression/RunCMakeTest.cmake | 4 + .../BadToolsetFormat-result.txt | 1 + .../BadToolsetFormat-stderr.txt | 10 + .../GeneratorToolset/BadToolsetFormat.cmake | 1 + .../BadToolsetHostArch-stderr.txt | 4 +- .../BadToolsetHostArchTwice-result.txt | 1 + .../BadToolsetHostArchTwice-stderr.txt | 10 + .../BadToolsetHostArchTwice.cmake | 1 + .../BadToolsetHostArchXcode-result.txt | 1 + .../BadToolsetHostArchXcode-stderr.txt | 10 + .../BadToolsetHostArchXcode.cmake | 1 + .../GeneratorToolset/RunCMakeTest.cmake | 19 +- .../TestToolsetCudaBoth-stdout.txt | 2 + .../TestToolsetCudaBoth.cmake | 2 + .../TestToolsetCudaOnly-stdout.txt | 2 + .../TestToolsetCudaOnly.cmake | 2 + Tests/RunCMake/Ninja/AssumedSources.cmake | 20 + Tests/RunCMake/Ninja/CommandConcat.cmake | 14 + Tests/RunCMake/Ninja/LooseObjectDepends.cmake | 26 + Tests/RunCMake/Ninja/RunCMakeTest.cmake | 45 +- Tests/RunCMake/Ninja/dep.c | 4 + Tests/RunCMake/Ninja/top.c | 7 + .../RunCMake/ObjectLibrary/Dependencies.cmake | 7 + .../RunCMake/ObjectLibrary/Export-stderr.txt | 4 - .../ExportNotSupported-result.txt | 1 + .../ExportNotSupported-stderr.txt | 5 + .../ObjectLibrary/ExportNotSupported.cmake | 2 + Tests/RunCMake/ObjectLibrary/Import.cmake | 11 + .../ImportNotSupported-result.txt | 1 + ...derr.txt => ImportNotSupported-stderr.txt} | 5 +- .../ObjectLibrary/ImportNotSupported.cmake | 1 + .../InstallNotSupported-result.txt | 1 + ...err.txt => InstallNotSupported-stderr.txt} | 5 +- .../ObjectLibrary/InstallNotSupported.cmake | 2 + .../ObjectLibrary/OwnSources-result.txt | 1 + .../ObjectLibrary/OwnSources-stderr.txt | 5 + Tests/RunCMake/ObjectLibrary/OwnSources.cmake | 2 + .../RunCMake/ObjectLibrary/RunCMakeTest.cmake | 38 +- Tests/RunCMake/ObjectLibrary/b.c | 4 + Tests/RunCMake/ObjectLibrary/depends_lib.c | 7 + Tests/RunCMake/ObjectLibrary/depends_main.c | 7 + Tests/RunCMake/ObjectLibrary/depends_obj0.c | 4 + Tests/RunCMake/ObjectLibrary/depends_obj1.c | 4 + Tests/RunCMake/RunCMake.cmake | 6 +- .../TargetObjects/BadContext-stderr.txt | 27 - .../TargetObjects/NoTarget-result.txt | 1 + .../TargetObjects/NoTarget-stderr.txt | 24 + .../{BadContext.cmake => NoTarget.cmake} | 0 .../TargetObjects/NotObjlibTarget-result.txt | 1 + .../TargetObjects/NotObjlibTarget-stderr.txt | 8 + .../TargetObjects/NotObjlibTarget.cmake | 3 + .../RunCMake/TargetObjects/RunCMakeTest.cmake | 3 +- Tests/RunCMake/TargetObjects/empty.cpp | 4 + .../TargetPolicies/PolicyList-stderr.txt | 2 + .../TargetSources/CMP0026-LOCATION-stderr.txt | 10 + .../RunCMake/TargetSources/RunCMakeTest.cmake | 2 +- .../RunCMake/VSSolution/MorePost-check.cmake | 2 +- Tests/RunCMake/VSSolution/MorePre-check.cmake | 2 +- Tests/RunCMake/VSSolution/OnePost-check.cmake | 2 +- Tests/RunCMake/VSSolution/OnePre-check.cmake | 2 +- .../RunCMake/VSSolution/Override1-check.cmake | 2 +- .../RunCMake/VSSolution/Override2-check.cmake | 2 +- .../RunCMake/VSSolution/Override3-check.cmake | 3 + Tests/RunCMake/VSSolution/Override3.cmake | 4 + Tests/RunCMake/VSSolution/PrePost-check.cmake | 2 +- Tests/RunCMake/VSSolution/RunCMakeTest.cmake | 3 +- .../VSSolution/solution_parsing.cmake | 3 + .../RunCMake/XcodeProject/RunCMakeTest.cmake | 16 + .../RunCMake/XcodeProject/XcodeBundles.cmake | 24 + .../XcodeProject/XcodeSchemaGeneration.cmake | 5 + .../ctest_disabled_test/CMakeLists.txt.in | 6 + .../ctest_disabled_test/CTestConfig.cmake.in | 1 + .../DisableAllTests-result.txt | 1 + .../DisableAllTests-stderr.txt | 1 + .../DisableAllTests-stdout.txt | 2 + .../DisableCleanupTest-stdout.txt | 11 + .../DisableFailingTest-stdout.txt | 9 + .../DisableNotRunTest-result.txt | 1 + .../DisableNotRunTest-stderr.txt | 1 + .../DisableNotRunTest-stdout.txt | 17 + .../DisableRequiredTest-stdout.txt | 13 + .../DisableSetupTest-stdout.txt | 13 + .../DisabledTest-result.txt | 1 + .../DisabledTest-stderr.txt | 1 + .../DisabledTest-stdout.txt | 17 + .../ctest_disabled_test/RunCMakeTest.cmake | 89 + .../ctest_disabled_test/test.cmake.in | 16 + .../RunCMake/ctest_fixtures/CMakeLists.txt.in | 2 +- .../ctest_fixtures/RunCMakeTest.cmake | 50 + .../ctest_fixtures/exclude_any_bar-stdout.txt | 15 + .../ctest_fixtures/exclude_any_foo-stdout.txt | 13 + .../exclude_any_foobar-stdout.txt | 9 + .../exclude_cleanup_bar-stdout.txt | 15 + .../exclude_cleanup_foo-stdout.txt | 15 + .../exclude_setup_bar-stdout.txt | 17 + .../exclude_setup_foo-stdout.txt | 15 + Tests/RunCMake/ctest_fixtures/test.cmake.in | 2 +- .../ctest_skipped_test/CMakeLists.txt.in | 12 + .../ctest_skipped_test/CTestConfig.cmake.in | 1 + .../ctest_skipped_test/RunCMakeTest.cmake | 51 + .../SkipCleanupTest-stdout.txt | 11 + .../SkipRequiredTest-stdout.txt | 13 + .../SkipSetupTest-stdout.txt | 13 + .../ctest_skipped_test/SkipTest-stdout.txt | 11 + Tests/RunCMake/ctest_skipped_test/skip.bat | 1 + Tests/RunCMake/ctest_skipped_test/skip.sh | 3 + .../RunCMake/ctest_skipped_test/test.cmake.in | 16 + .../CDashSubmitHeaders-result.txt | 1 + .../CDashSubmitHeaders-stderr.txt | 3 + .../CDashSubmitHeaders-stdout.txt | 1 + .../CDashUploadHeaders-result.txt | 1 + .../CDashUploadHeaders-stderr.txt | 1 + .../CDashUploadHeaders-stdout.txt | 1 + .../RunCMake/ctest_submit/RunCMakeTest.cmake | 2 + .../file/DOWNLOAD-hash-mismatch.cmake | 5 +- .../file/DOWNLOAD-unused-argument.cmake | 5 +- .../INSTALL-FILES_FROM_DIR-bad-result.txt | 1 + .../INSTALL-FILES_FROM_DIR-bad-stderr.txt | 15 + .../file/INSTALL-FILES_FROM_DIR-bad.cmake | 5 + .../file/INSTALL-FILES_FROM_DIR-stdout.txt | 8 + .../file/INSTALL-FILES_FROM_DIR.cmake | 7 + .../RunCMake/file/INSTALL-SYMLINK-stdout.txt | 3 + Tests/RunCMake/file/INSTALL-SYMLINK.cmake | 13 + Tests/RunCMake/file/READ_ELF-result.txt | 1 + Tests/RunCMake/file/READ_ELF-stderr.txt | 2 + Tests/RunCMake/file/READ_ELF.cmake | 2 + Tests/RunCMake/file/RunCMakeTest.cmake | 4 + .../file/UPLOAD-unused-argument.cmake | 5 +- Tests/RunCMake/file/from/a.txt | 0 Tests/RunCMake/file/from/a/b.txt | 0 Tests/RunCMake/file/from/a/b/c.txt | 0 Tests/RunCMake/find_dependency/CMakeLists.txt | 1 - .../EXACT-no-version-stderr.txt | 6 - .../find_dependency/EXACT-no-version.cmake | 4 - .../find_dependency/RunCMakeTest.cmake | 13 +- .../bad-version-exact-result.txt | 1 + .../bad-version-exact-stderr.txt | 11 + .../find_dependency/bad-version-exact.cmake | 5 + .../bad-version-fuzzy-result.txt | 1 + .../bad-version-fuzzy-stderr.txt | 11 + .../find_dependency/bad-version-fuzzy.cmake | 5 + Tests/RunCMake/find_dependency/basic.cmake | 5 + .../find_dependency/empty-arg-3-stderr.txt | 5 - .../find_dependency/empty-arg-3.cmake | 4 - .../find_dependency/empty-version-stderr.txt | 5 - .../find_dependency/empty-version.cmake | 4 - .../find_dependency/extra-args-stderr.txt | 5 - .../RunCMake/find_dependency/extra-args.cmake | 4 - .../find_dependency/invalid-arg-3-stderr.txt | 5 - .../find_dependency/invalid-arg-result.txt | 1 + .../find_dependency/invalid-arg-stderr.txt | 5 + ...{invalid-arg-3.cmake => invalid-arg.cmake} | 1 + .../RunCMake/find_dependency/realistic.cmake | 3 + .../{ => share/cmake}/Pack1/Pack1Config.cmake | 0 .../cmake}/Pack1/Pack1ConfigVersion.cmake | 0 .../share/cmake/Pack2/Pack2Config.cmake | 6 + .../cmake/Pack2/Pack2ConfigVersion.cmake | 11 + .../find_package/MissingConfig-stderr.txt | 15 - .../find_package/MissingConfig-stdout.txt | 1 + .../MissingConfigNormal-stdout.txt | 1 + .../MissingConfigOneName-stderr.txt | 10 - .../MissingConfigOneName-stdout.txt | 1 + .../MissingConfigVersion-stderr.txt | 13 - .../MissingConfigVersion-stdout.txt | 1 + .../find_package/PackageRoot-stderr.txt | 383 ++ Tests/RunCMake/find_package/PackageRoot.cmake | 147 + .../find_package/PackageRoot/FindBar.cmake | 8 + .../find_package/PackageRoot/FindFoo.cmake | 9 + .../PackageRoot/bar/cmake_root/bin/bar.exe | 0 .../PackageRoot/bar/cmake_root/include/bar.h | 0 .../bar/cmake_root/include/zot/zot.h | 0 .../PackageRoot/bar/env_root/bin/bar.exe | 0 .../PackageRoot/bar/env_root/include/bar.h | 0 .../bar/env_root/include/zot/zot.h | 0 .../PackageRoot/foo/cmake_root/bin/bar.exe | 0 .../PackageRoot/foo/cmake_root/bin/foo.exe | 0 .../PackageRoot/foo/cmake_root/include/bar.h | 0 .../PackageRoot/foo/cmake_root/include/foo.h | 0 .../foo/cmake_root/include/zot/zot.h | 0 .../PackageRoot/foo/env_root/bin/bar.exe | 0 .../PackageRoot/foo/env_root/bin/foo.exe | 0 .../PackageRoot/foo/env_root/include/bar.h | 0 .../PackageRoot/foo/env_root/include/foo.h | 0 .../foo/env_root/include/zot/zot.h | 0 .../RunCMake/find_package/RunCMakeTest.cmake | 3 + .../VersionedA-1/VersionedAConfig.cmake | 0 .../VersionedAConfigVersion.cmake | 4 + .../VersionedA-2/VersionedAConfig.cmake | 0 .../VersionedAConfigVersion.cmake | 4 + .../find_package/WrongVersion-stderr.txt | 11 + .../RunCMake/find_package/WrongVersion.cmake | 2 + .../WrongVersionConfig-stderr.txt | 11 + .../find_package/WrongVersionConfig.cmake | 2 + .../get_property/IsMultiConfig-stdout.txt | 1 + .../RunCMake/get_property/IsMultiConfig.cmake | 2 + .../get_property/NotMultiConfig-stdout.txt | 1 + .../get_property/NotMultiConfig.cmake | 1 + .../RunCMake/get_property/RunCMakeTest.cmake | 6 + Tests/RunCMake/if/RunCMakeTest.cmake | 4 + .../if/duplicate-deep-else-result.txt | 1 + .../if/duplicate-deep-else-stderr.txt | 4 + Tests/RunCMake/if/duplicate-deep-else.cmake | 7 + .../if/duplicate-else-after-elseif-result.txt | 1 + .../if/duplicate-else-after-elseif-stderr.txt | 4 + .../if/duplicate-else-after-elseif.cmake | 5 + Tests/RunCMake/if/duplicate-else-result.txt | 1 + Tests/RunCMake/if/duplicate-else-stderr.txt | 4 + Tests/RunCMake/if/duplicate-else.cmake | 4 + Tests/RunCMake/if/misplaced-elseif-result.txt | 1 + Tests/RunCMake/if/misplaced-elseif-stderr.txt | 4 + Tests/RunCMake/if/misplaced-elseif.cmake | 4 + .../CustomConfig-check.cmake | 1 + .../CustomConfig.cmake | 3 + .../CustomGuid-check.cmake | 2 +- .../CustomGuidTypePlatform-check.cmake | 2 +- .../CustomTypePlatform-check.cmake | 2 +- .../RunCMakeTest.cmake | 1 + .../check_utils.cmake | 27 +- Tests/RunCMake/install/EXPORT-OldIFace.cmake | 1 + .../FILES-TARGET_OBJECTS-all-check.cmake | 1 + .../install/FILES-TARGET_OBJECTS.cmake | 3 + Tests/RunCMake/install/RunCMakeTest.cmake | 20 +- Tests/RunCMake/install/obj1.c | 4 + Tests/RunCMake/install/obj2.c | 4 + .../project/ProjectDescription-stdout.txt | 1 + .../RunCMake/project/ProjectDescription.cmake | 6 + .../project/ProjectDescription2-result.txt | 1 + .../project/ProjectDescription2-stderr.txt | 1 + .../project/ProjectDescription2.cmake | 2 + Tests/RunCMake/project/RunCMakeTest.cmake | 2 + .../separate_arguments/CMakeLists.txt | 3 + .../separate_arguments/EmptyCommand.cmake | 6 + .../separate_arguments/NativeCommand.cmake | 19 + .../separate_arguments/PlainCommand.cmake | 8 + .../separate_arguments/RunCMakeTest.cmake | 7 + .../separate_arguments/UnixCommand.cmake | 8 + .../separate_arguments/WindowsCommand.cmake | 8 + .../target_compile_features/CMakeLists.txt | 2 +- .../RunCMakeTest.cmake | 1 + .../alias_target-stderr.txt | 2 +- .../alias_target.cmake | 1 + .../cxx_not_enabled-result.txt | 1 + .../cxx_not_enabled-stderr.txt | 4 + .../cxx_not_enabled.cmake | 2 + .../imported_target-stderr.txt | 2 +- .../imported_target.cmake | 1 + .../invalid_args-stderr.txt | 2 +- .../invalid_args.cmake | 1 + .../invalid_args_on_interface-stderr.txt | 2 +- .../invalid_args_on_interface.cmake | 1 + .../no_matching_c_feature-stderr.txt | 2 +- .../no_matching_c_feature.cmake | 1 + .../no_matching_cxx_feature-stderr.txt | 2 +- .../no_matching_cxx_feature.cmake | 1 + .../no_target-stderr.txt | 2 +- .../target_compile_features/no_target.cmake | 1 + .../not_a_c_feature-stderr.txt | 2 +- .../not_a_c_feature.cmake | 1 + .../not_a_cxx_feature-stderr.txt | 2 +- .../not_a_cxx_feature.cmake | 1 + .../not_enough_args-stderr.txt | 2 +- .../not_enough_args.cmake | 1 + .../utility_target-stderr.txt | 2 +- Tests/Server/cmakelib.py | 5 +- Tests/Server/server-test.py | 1 + Tests/SimpleInstall/CMakeLists.txt | 1 + Tests/SourceGroups/CMakeLists.txt | 9 +- Tests/SourceGroups/main.c | 9 +- Tests/SourceGroups/tree_foo.c | 4 - Tests/SourceGroups/tree_prefix_bar.c | 4 + Tests/SourceGroups/tree_prefix_foo.c | 4 + Tests/VSNASM/CMakeLists.txt | 10 + Tests/VSNASM/foo.asm | 7 + Tests/VSNASM/include/foo-proc.asm | 7 + Tests/VSNASM/main.c | 5 + Tests/VSResource/CMakeLists.txt | 9 +- Tests/Wrapping/fakefluid.cxx | 4 +- Tests/XCTest/CMakeLists.txt | 16 + .../StaticLibExample/StaticLibExample.c | 6 + .../StaticLibExample/StaticLibExample.h | 1 + Tests/XCTest/StaticLibExampleTests/Info.plist | 24 + .../StaticLibExampleTests.m | 16 + Utilities/.clang-tidy | 6 + Utilities/CMakeLists.txt | 3 + Utilities/GitSetup/config | 9 +- Utilities/IWYU/mapping.imp | 161 + Utilities/KWIML/test/CMakeLists.txt | 2 + Utilities/Release/consolidate-relnotes.bash | 27 + Utilities/Release/hythloth_release.cmake | 10 - Utilities/Release/linux64_release.cmake | 1 + Utilities/Release/osx_release.cmake | 2 +- Utilities/Release/release_cmake.cmake | 9 +- Utilities/Release/release_cmake.sh.in | 6 +- Utilities/Release/upload_release.cmake | 2 +- Utilities/Scripts/update-curl.bash | 3 +- Utilities/Scripts/update-expat.bash | 5 +- Utilities/Scripts/update-kwsys.bash | 2 + Utilities/Scripts/update-libarchive.bash | 2 +- Utilities/Scripts/update-third-party.bash | 8 + Utilities/SetupForDevelopment.sh | 5 +- Utilities/Sphinx/CMakeLists.txt | 26 +- Utilities/Sphinx/conf.py.in | 24 +- Utilities/Sphinx/templates/layout.html | 12 + Utilities/cmcurl/CMake/CurlTests.c | 16 + Utilities/cmcurl/CMake/FindGSS.cmake | 2 +- Utilities/cmcurl/CMake/FindMbedTLS.cmake | 13 + Utilities/cmcurl/CMake/OtherTests.cmake | 25 +- Utilities/cmcurl/CMake/Utilities.cmake | 13 + Utilities/cmcurl/CMakeLists.txt | 302 +- Utilities/cmcurl/COPYING | 2 +- Utilities/cmcurl/include/curl/curl.h | 123 +- Utilities/cmcurl/include/curl/curlrules.h | 25 +- Utilities/cmcurl/include/curl/curlver.h | 18 +- Utilities/cmcurl/include/curl/easy.h | 4 +- Utilities/cmcurl/include/curl/stdcheaders.h | 6 +- Utilities/cmcurl/include/curl/system.h | 484 ++ Utilities/cmcurl/include/curl/typecheck-gcc.h | 188 +- Utilities/cmcurl/lib/Makefile.inc | 4 +- Utilities/cmcurl/lib/asyn-ares.c | 47 +- Utilities/cmcurl/lib/asyn-thread.c | 38 +- Utilities/cmcurl/lib/conncache.c | 67 +- Utilities/cmcurl/lib/conncache.h | 4 +- Utilities/cmcurl/lib/connect.c | 109 +- Utilities/cmcurl/lib/connect.h | 19 +- Utilities/cmcurl/lib/content_encoding.c | 28 +- Utilities/cmcurl/lib/cookie.c | 60 +- Utilities/cmcurl/lib/curl_addrinfo.c | 62 +- Utilities/cmcurl/lib/curl_addrinfo.h | 2 +- Utilities/cmcurl/lib/curl_config.h.cmake | 12 + Utilities/cmcurl/lib/curl_des.c | 2 +- Utilities/cmcurl/lib/curl_endian.c | 120 +- Utilities/cmcurl/lib/curl_endian.h | 32 +- Utilities/cmcurl/lib/curl_fnmatch.c | 8 +- Utilities/cmcurl/lib/curl_gethostname.c | 8 +- Utilities/cmcurl/lib/curl_gssapi.c | 2 +- Utilities/cmcurl/lib/curl_hmac.h | 26 +- Utilities/cmcurl/lib/curl_md4.h | 8 +- Utilities/cmcurl/lib/curl_memory.h | 4 +- Utilities/cmcurl/lib/curl_ntlm_core.c | 24 +- Utilities/cmcurl/lib/curl_ntlm_core.h | 27 +- Utilities/cmcurl/lib/curl_ntlm_wb.c | 15 +- Utilities/cmcurl/lib/curl_rtmp.c | 1 + Utilities/cmcurl/lib/curl_sasl.c | 29 +- Utilities/cmcurl/lib/curl_sec.h | 16 +- Utilities/cmcurl/lib/curl_setup.h | 31 +- Utilities/cmcurl/lib/curl_setup_once.h | 2 +- Utilities/cmcurl/lib/curl_threads.c | 5 +- Utilities/cmcurl/lib/curl_threads.h | 5 +- Utilities/cmcurl/lib/dict.c | 2 +- Utilities/cmcurl/lib/dotdot.c | 3 +- Utilities/cmcurl/lib/easy.c | 74 +- Utilities/cmcurl/lib/escape.c | 13 +- Utilities/cmcurl/lib/file.c | 32 +- Utilities/cmcurl/lib/fileinfo.c | 14 +- Utilities/cmcurl/lib/fileinfo.h | 12 +- Utilities/cmcurl/lib/formdata.c | 201 +- Utilities/cmcurl/lib/formdata.h | 2 +- Utilities/cmcurl/lib/ftp.c | 331 +- Utilities/cmcurl/lib/ftp.h | 2 +- Utilities/cmcurl/lib/ftplistparser.c | 67 +- Utilities/cmcurl/lib/getinfo.c | 29 +- Utilities/cmcurl/lib/gopher.c | 6 +- Utilities/cmcurl/lib/hash.c | 88 +- Utilities/cmcurl/lib/hash.h | 20 +- Utilities/cmcurl/lib/hmac.c | 10 +- Utilities/cmcurl/lib/hostcheck.c | 11 +- Utilities/cmcurl/lib/hostip.c | 18 +- Utilities/cmcurl/lib/hostip.h | 10 +- Utilities/cmcurl/lib/hostip4.c | 2 +- Utilities/cmcurl/lib/http.c | 287 +- Utilities/cmcurl/lib/http.h | 4 + Utilities/cmcurl/lib/http2.c | 324 +- Utilities/cmcurl/lib/http2.h | 8 + Utilities/cmcurl/lib/http_chunks.c | 14 +- Utilities/cmcurl/lib/http_digest.c | 20 +- Utilities/cmcurl/lib/http_negotiate.c | 16 +- Utilities/cmcurl/lib/http_ntlm.c | 6 +- Utilities/cmcurl/lib/http_proxy.c | 609 +-- Utilities/cmcurl/lib/http_proxy.h | 11 +- Utilities/cmcurl/lib/if2ip.c | 4 +- Utilities/cmcurl/lib/imap.c | 15 +- Utilities/cmcurl/lib/inet_ntop.c | 6 +- Utilities/cmcurl/lib/inet_pton.c | 8 +- Utilities/cmcurl/lib/krb5.c | 16 +- Utilities/cmcurl/lib/ldap.c | 147 +- Utilities/cmcurl/lib/libcurl.rc | 4 +- Utilities/cmcurl/lib/llist.c | 57 +- Utilities/cmcurl/lib/llist.h | 19 +- Utilities/cmcurl/lib/md4.c | 15 +- Utilities/cmcurl/lib/md5.c | 9 +- Utilities/cmcurl/lib/memdebug.c | 28 +- Utilities/cmcurl/lib/mprintf.c | 33 +- Utilities/cmcurl/lib/multi.c | 413 +- Utilities/cmcurl/lib/multihandle.h | 21 +- Utilities/cmcurl/lib/multiif.h | 7 +- Utilities/cmcurl/lib/non-ascii.c | 4 +- Utilities/cmcurl/lib/nonblock.c | 3 +- Utilities/cmcurl/lib/nwlib.c | 10 +- Utilities/cmcurl/lib/nwos.c | 8 +- Utilities/cmcurl/lib/pingpong.c | 35 +- Utilities/cmcurl/lib/pingpong.h | 8 +- Utilities/cmcurl/lib/pipeline.c | 123 +- Utilities/cmcurl/lib/pipeline.h | 6 +- Utilities/cmcurl/lib/pop3.c | 17 +- Utilities/cmcurl/lib/progress.c | 58 +- Utilities/cmcurl/lib/rand.c | 179 + Utilities/cmcurl/lib/rand.h | 47 + Utilities/cmcurl/lib/rtsp.c | 94 +- Utilities/cmcurl/lib/security.c | 17 +- Utilities/cmcurl/lib/select.c | 10 +- Utilities/cmcurl/lib/select.h | 8 +- Utilities/cmcurl/lib/sendf.c | 195 +- Utilities/cmcurl/lib/sendf.h | 2 + Utilities/cmcurl/lib/setup-os400.h | 52 +- Utilities/cmcurl/lib/setup-vms.h | 139 +- Utilities/cmcurl/lib/share.h | 8 +- Utilities/cmcurl/lib/smb.c | 49 +- Utilities/cmcurl/lib/smtp.c | 17 +- Utilities/cmcurl/lib/socks.c | 55 +- Utilities/cmcurl/lib/socks.h | 5 +- Utilities/cmcurl/lib/socks_gssapi.c | 24 +- Utilities/cmcurl/lib/socks_sspi.c | 11 +- Utilities/cmcurl/lib/speedcheck.c | 61 +- Utilities/cmcurl/lib/splay.c | 110 +- Utilities/cmcurl/lib/splay.h | 3 +- Utilities/cmcurl/lib/ssh.c | 377 +- Utilities/cmcurl/lib/strcase.c | 12 +- Utilities/cmcurl/lib/strcase.h | 1 + Utilities/cmcurl/lib/strdup.c | 23 + Utilities/cmcurl/lib/strdup.h | 1 + Utilities/cmcurl/lib/strerror.c | 32 +- Utilities/cmcurl/lib/strtoofft.c | 4 +- Utilities/cmcurl/lib/system_win32.c | 4 +- Utilities/cmcurl/lib/telnet.c | 154 +- Utilities/cmcurl/lib/tftp.c | 22 +- Utilities/cmcurl/lib/timeval.c | 13 +- Utilities/cmcurl/lib/timeval.h | 6 +- Utilities/cmcurl/lib/transfer.c | 187 +- Utilities/cmcurl/lib/url.c | 1586 ++++--- Utilities/cmcurl/lib/url.h | 13 + Utilities/cmcurl/lib/urldata.h | 251 +- Utilities/cmcurl/lib/vauth/cleartext.c | 24 +- Utilities/cmcurl/lib/vauth/digest.c | 36 +- Utilities/cmcurl/lib/vauth/digest_sspi.c | 290 +- Utilities/cmcurl/lib/vauth/krb5_gssapi.c | 4 +- Utilities/cmcurl/lib/vauth/krb5_sspi.c | 4 +- Utilities/cmcurl/lib/vauth/ntlm.c | 44 +- Utilities/cmcurl/lib/vauth/ntlm.h | 2 +- Utilities/cmcurl/lib/vauth/spnego_sspi.c | 5 +- Utilities/cmcurl/lib/version.c | 3 + Utilities/cmcurl/lib/vtls/axtls.c | 105 +- Utilities/cmcurl/lib/vtls/axtls.h | 8 +- Utilities/cmcurl/lib/vtls/cyassl.c | 212 +- Utilities/cmcurl/lib/vtls/cyassl.h | 10 +- Utilities/cmcurl/lib/vtls/darwinssl.c | 722 ++- Utilities/cmcurl/lib/vtls/darwinssl.h | 30 +- Utilities/cmcurl/lib/vtls/gskit.c | 400 +- Utilities/cmcurl/lib/vtls/gskit.h | 7 +- Utilities/cmcurl/lib/vtls/gtls.c | 465 +- Utilities/cmcurl/lib/vtls/gtls.h | 15 +- Utilities/cmcurl/lib/vtls/mbedtls.c | 263 +- Utilities/cmcurl/lib/vtls/mbedtls.h | 12 +- Utilities/cmcurl/lib/vtls/nss.c | 522 ++- Utilities/cmcurl/lib/vtls/nssg.h | 11 +- Utilities/cmcurl/lib/vtls/openssl.c | 706 +-- Utilities/cmcurl/lib/vtls/openssl.h | 9 +- Utilities/cmcurl/lib/vtls/polarssl.c | 173 +- Utilities/cmcurl/lib/vtls/polarssl.h | 3 +- Utilities/cmcurl/lib/vtls/schannel.c | 226 +- Utilities/cmcurl/lib/vtls/schannel.h | 4 +- Utilities/cmcurl/lib/vtls/vtls.c | 313 +- Utilities/cmcurl/lib/vtls/vtls.h | 48 +- Utilities/cmcurl/lib/warnless.c | 5 +- Utilities/cmcurl/lib/wildcard.c | 18 +- Utilities/cmcurl/lib/wildcard.h | 9 +- Utilities/cmcurl/lib/x509asn1.c | 195 +- Utilities/cmcurl/lib/x509asn1.h | 26 +- Utilities/cmexpat/COPYING | 5 +- Utilities/cmexpat/README | 4 +- Utilities/cmexpat/lib/expat.h | 30 +- Utilities/cmexpat/lib/expat_external.h | 5 +- Utilities/cmexpat/lib/siphash.h | 354 ++ Utilities/cmexpat/lib/winconfig.h | 19 +- Utilities/cmexpat/lib/xmlparse.c | 611 ++- Utilities/cmexpat/lib/xmlrole.c | 10 +- Utilities/cmexpat/lib/xmltok.c | 34 +- Utilities/cmexpat/lib/xmltok_impl.c | 4 + Utilities/cmjsoncpp/CMakeLists.txt | 1 + Utilities/cmlibarchive/CMakeLists.txt | 145 +- .../build/cmake/CheckStructMember.cmake | 43 - .../cmlibarchive/build/cmake/FindLZMA.cmake | 48 - .../cmlibarchive/build/cmake/config.h.in | 21 + Utilities/cmlibarchive/build/version | 2 +- .../cmlibarchive/libarchive/CMakeLists.txt | 18 + Utilities/cmlibarchive/libarchive/archive.h | 20 +- .../cmlibarchive/libarchive/archive_acl.c | 1639 +++++-- .../libarchive/archive_acl_private.h | 22 +- .../cmlibarchive/libarchive/archive_cryptor.c | 3 +- .../libarchive/archive_digest_private.h | 1 + .../cmlibarchive/libarchive/archive_entry.c | 234 +- .../cmlibarchive/libarchive/archive_entry.h | 91 +- .../libarchive/archive_entry_acl.3 | 335 +- .../libarchive/archive_entry_locale.h | 10 +- .../libarchive/archive_entry_strmode.c | 2 +- .../cmlibarchive/libarchive/archive_hmac.c | 4 + .../cmlibarchive/libarchive/archive_match.c | 14 +- .../libarchive/archive_openssl_evp_private.h | 5 +- .../libarchive/archive_openssl_hmac_private.h | 6 +- .../cmlibarchive/libarchive/archive_options.c | 11 +- .../libarchive/archive_platform.h | 28 +- .../libarchive/archive_ppmd7_private.h | 2 +- .../cmlibarchive/libarchive/archive_random.c | 2 +- .../cmlibarchive/libarchive/archive_rb.c | 2 +- .../cmlibarchive/libarchive/archive_read.c | 16 +- .../libarchive/archive_read_add_passphrase.c | 22 +- .../libarchive/archive_read_append_filter.c | 2 - .../libarchive/archive_read_disk.3 | 6 +- .../archive_read_disk_entry_from_file.c | 1090 ++++- .../libarchive/archive_read_disk_posix.c | 135 +- .../libarchive/archive_read_disk_private.h | 12 +- .../archive_read_disk_set_standard_lookup.c | 2 + .../libarchive/archive_read_disk_windows.c | 59 +- .../libarchive/archive_read_extract2.c | 3 +- .../libarchive/archive_read_open_filename.c | 20 +- .../libarchive/archive_read_open_memory.c | 3 +- .../libarchive/archive_read_private.h | 3 +- .../archive_read_support_filter_lz4.c | 13 +- .../archive_read_support_filter_lzop.c | 2 +- .../archive_read_support_filter_program.c | 2 + .../archive_read_support_filter_uu.c | 44 +- .../archive_read_support_filter_xz.c | 194 +- .../archive_read_support_format_7zip.c | 39 +- .../archive_read_support_format_ar.c | 22 +- .../archive_read_support_format_cab.c | 15 +- .../archive_read_support_format_cpio.c | 17 +- .../archive_read_support_format_iso9660.c | 40 +- .../archive_read_support_format_lha.c | 13 +- .../archive_read_support_format_mtree.c | 71 +- .../archive_read_support_format_rar.c | 5 +- .../archive_read_support_format_tar.c | 281 +- .../archive_read_support_format_warc.c | 241 +- .../archive_read_support_format_xar.c | 87 +- .../archive_read_support_format_zip.c | 122 +- .../cmlibarchive/libarchive/archive_string.c | 117 +- .../cmlibarchive/libarchive/archive_string.h | 8 +- .../libarchive/archive_string_composition.h | 2 +- .../cmlibarchive/libarchive/archive_util.c | 2 +- .../cmlibarchive/libarchive/archive_windows.c | 4 +- .../cmlibarchive/libarchive/archive_windows.h | 4 + .../cmlibarchive/libarchive/archive_write.c | 8 +- .../libarchive/archive_write_add_filter_lz4.c | 4 +- .../archive_write_add_filter_program.c | 1 + .../libarchive/archive_write_add_filter_xz.c | 2 +- .../libarchive/archive_write_disk_acl.c | 545 ++- .../libarchive/archive_write_disk_posix.c | 588 ++- .../archive_write_disk_set_standard_lookup.c | 6 +- .../libarchive/archive_write_disk_windows.c | 7 +- .../libarchive/archive_write_open.3 | 11 + .../libarchive/archive_write_open_memory.c | 3 +- .../archive_write_set_format_7zip.c | 4 +- .../libarchive/archive_write_set_format_ar.c | 3 +- .../archive_write_set_format_cpio.c | 2 +- .../archive_write_set_format_cpio_newc.c | 5 +- .../archive_write_set_format_gnutar.c | 14 +- .../archive_write_set_format_iso9660.c | 60 +- .../archive_write_set_format_mtree.c | 4 +- .../libarchive/archive_write_set_format_pax.c | 183 +- .../archive_write_set_format_shar.c | 3 +- .../archive_write_set_format_ustar.c | 11 +- .../archive_write_set_format_v7tar.c | 9 +- .../archive_write_set_format_warc.c | 2 +- .../libarchive/archive_write_set_format_xar.c | 21 +- .../libarchive/archive_write_set_format_zip.c | 12 +- .../cmlibarchive/libarchive/config_freebsd.h | 2 + .../libarchive/libarchive-formats.5 | 4 +- Utilities/cmlibarchive/libarchive/tar.5 | 11 +- Utilities/cmlibarchive/libarchive/xxhash.c | 6 +- Utilities/cmliblzma/CMakeLists.txt | 4 +- Utilities/cmlibuv/CMakeLists.txt | 45 + Utilities/cmlibuv/include/pthread-barrier.h | 2 + Utilities/cmlibuv/include/uv-os390.h | 3 + Utilities/cmlibuv/include/uv-posix.h | 31 + Utilities/cmlibuv/include/uv-unix.h | 21 +- Utilities/cmlibuv/include/uv-version.h | 4 +- Utilities/cmlibuv/include/uv-win.h | 1 + Utilities/cmlibuv/include/uv.h | 12 + Utilities/cmlibuv/src/threadpool.c | 35 +- Utilities/cmlibuv/src/unix/aix.c | 93 +- Utilities/cmlibuv/src/unix/async.c | 121 +- Utilities/cmlibuv/src/unix/atomic-ops.h | 27 +- Utilities/cmlibuv/src/unix/bsd-ifaddrs.c | 139 + Utilities/cmlibuv/src/unix/core.c | 102 +- Utilities/cmlibuv/src/unix/cygwin.c | 54 + Utilities/cmlibuv/src/unix/darwin.c | 104 - Utilities/cmlibuv/src/unix/freebsd.c | 114 - Utilities/cmlibuv/src/unix/fs.c | 69 +- Utilities/cmlibuv/src/unix/fsevents.c | 3 - Utilities/cmlibuv/src/unix/internal.h | 34 +- Utilities/cmlibuv/src/unix/kqueue.c | 36 +- Utilities/cmlibuv/src/unix/linux-core.c | 102 +- Utilities/cmlibuv/src/unix/linux-inotify.c | 67 + Utilities/cmlibuv/src/unix/loop.c | 38 +- Utilities/cmlibuv/src/unix/netbsd.c | 108 - Utilities/cmlibuv/src/unix/no-fsevents.c | 42 + Utilities/cmlibuv/src/unix/no-proctitle.c | 42 + Utilities/cmlibuv/src/unix/openbsd.c | 114 +- Utilities/cmlibuv/src/unix/os390-syscalls.c | 334 ++ Utilities/cmlibuv/src/unix/os390-syscalls.h | 69 + Utilities/cmlibuv/src/unix/os390.c | 807 ++++ Utilities/cmlibuv/src/unix/pipe.c | 15 +- Utilities/cmlibuv/src/unix/poll.c | 4 +- Utilities/cmlibuv/src/unix/posix-hrtime.c | 35 + Utilities/cmlibuv/src/unix/posix-poll.c | 324 ++ Utilities/cmlibuv/src/unix/process.c | 4 +- Utilities/cmlibuv/src/unix/procfs-exepath.c | 45 + Utilities/cmlibuv/src/unix/proctitle.c | 6 + Utilities/cmlibuv/src/unix/pthread-barrier.c | 3 +- Utilities/cmlibuv/src/unix/signal.c | 108 +- Utilities/cmlibuv/src/unix/stream.c | 47 +- Utilities/cmlibuv/src/unix/sunos.c | 72 +- Utilities/cmlibuv/src/unix/sysinfo-loadavg.c | 36 + Utilities/cmlibuv/src/unix/sysinfo-memory.c | 42 + Utilities/cmlibuv/src/unix/thread.c | 32 +- Utilities/cmlibuv/src/unix/udp.c | 33 +- Utilities/cmlibuv/src/uv-common.c | 12 +- Utilities/cmlibuv/src/uv-common.h | 35 +- Utilities/cmlibuv/src/win/async.c | 3 +- Utilities/cmlibuv/src/win/atomicops-inl.h | 3 +- Utilities/cmlibuv/src/win/core.c | 25 +- Utilities/cmlibuv/src/win/detect-wakeup.c | 6 +- Utilities/cmlibuv/src/win/error.c | 1 + Utilities/cmlibuv/src/win/fs-event.c | 36 +- Utilities/cmlibuv/src/win/fs.c | 14 +- Utilities/cmlibuv/src/win/getaddrinfo.c | 7 +- Utilities/cmlibuv/src/win/getnameinfo.c | 3 +- Utilities/cmlibuv/src/win/internal.h | 23 +- Utilities/cmlibuv/src/win/pipe.c | 17 +- Utilities/cmlibuv/src/win/poll.c | 10 +- Utilities/cmlibuv/src/win/process-stdio.c | 1 + Utilities/cmlibuv/src/win/process.c | 5 +- Utilities/cmlibuv/src/win/req-inl.h | 9 +- Utilities/cmlibuv/src/win/signal.c | 161 +- Utilities/cmlibuv/src/win/stream-inl.h | 3 +- Utilities/cmlibuv/src/win/stream.c | 3 +- Utilities/cmlibuv/src/win/tcp.c | 13 +- Utilities/cmlibuv/src/win/tty.c | 96 +- Utilities/cmlibuv/src/win/udp.c | 6 +- Utilities/cmlibuv/src/win/util.c | 195 +- Utilities/cmlibuv/src/win/winapi.c | 2 +- Utilities/cmlibuv/src/win/winapi.h | 4 + Utilities/cmlibuv/src/win/winsock.c | 2 +- bootstrap | 193 +- 2058 files changed, 47834 insertions(+), 24495 deletions(-) create mode 100644 .clang-tidy create mode 100644 Help/dev/README.rst create mode 100644 Help/dev/maint.rst create mode 100644 Help/dev/review.rst create mode 100644 Help/dev/source.rst create mode 100644 Help/dev/testing.rst create mode 100644 Help/module/CPackArchive.rst create mode 100644 Help/module/CheckIPOSupported.rst create mode 100644 Help/module/GoogleTest.rst create mode 100644 Help/policy/CMP0068.rst create mode 100644 Help/policy/CMP0069.rst create mode 100644 Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst create mode 100644 Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst create mode 100644 Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst create mode 100644 Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst create mode 100644 Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst create mode 100644 Help/prop_test/DISABLED.rst create mode 100644 Help/prop_tgt/AUTOGEN_BUILD_DIR.rst create mode 100644 Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst create mode 100644 Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst create mode 100644 Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst create mode 100644 Help/prop_tgt/CUDA_PTX_COMPILATION.rst create mode 100644 Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst create mode 100644 Help/prop_tgt/IMPORTED_OBJECTS.rst create mode 100644 Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst create mode 100644 Help/release/3.9.rst create mode 100644 Help/variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst create mode 100644 Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst create mode 100644 Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst create mode 100644 Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst create mode 100644 Help/variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst create mode 100644 Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst create mode 100644 Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst create mode 100644 Help/variable/CMAKE_LANG_COMPILER_AR.rst create mode 100644 Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst create mode 100644 Help/variable/CMAKE_MATCH_n.rst create mode 100644 Help/variable/CMAKE_PROJECT_DESCRIPTION.rst create mode 100644 Help/variable/CMAKE_SYSROOT_COMPILE.rst create mode 100644 Help/variable/CMAKE_SYSROOT_LINK.rst create mode 100644 Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst create mode 100644 Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst create mode 100644 Help/variable/PROJECT_DESCRIPTION.rst delete mode 100644 Modules/CMakeVS7BackwardCompatibility.cmake create mode 100644 Modules/CPackArchive.cmake create mode 100644 Modules/CheckIPOSupported.cmake create mode 100644 Modules/CheckIPOSupported/CMakeLists-C.txt.in create mode 100644 Modules/CheckIPOSupported/CMakeLists-CXX.txt.in create mode 100644 Modules/CheckIPOSupported/CMakeLists-Fortran.txt.in create mode 100644 Modules/CheckIPOSupported/foo.c create mode 100644 Modules/CheckIPOSupported/foo.cpp create mode 100644 Modules/CheckIPOSupported/foo.f create mode 100644 Modules/CheckIPOSupported/main.c create mode 100644 Modules/CheckIPOSupported/main.cpp create mode 100644 Modules/CheckIPOSupported/main.f create mode 100644 Modules/Compiler/CMakeCommonCompilerMacros.cmake create mode 100644 Modules/Compiler/Clang-FindBinUtils.cmake create mode 100644 Modules/Compiler/Cray.cmake create mode 100644 Modules/Compiler/GNU-FindBinUtils.cmake create mode 100644 Modules/Compiler/SunPro-C-FeatureTests.cmake create mode 100644 Modules/Compiler/SunPro.cmake delete mode 100644 Modules/CompilerId/Xcode-1.pbxproj.in delete mode 100644 Modules/CompilerId/Xcode-2.pbxproj.in create mode 100644 Modules/FortranCInterface/MYMODULE.c create mode 100644 Modules/FortranCInterface/MY_MODULE.c create mode 100644 Modules/GoogleTest.cmake create mode 100644 Modules/Platform/Windows-PGI-C.cmake create mode 100644 Modules/Platform/Windows-PGI-Fortran.cmake create mode 100644 Modules/Platform/Windows-PGI.cmake create mode 100644 Source/CPack/IFW/cmCPackIFWCommon.cxx create mode 100644 Source/CPack/IFW/cmCPackIFWCommon.h create mode 100644 Source/Checks/cm_cxx_attribute_fallthrough.cxx create mode 100644 Source/Checks/cm_cxx_eq_delete.cxx create mode 100644 Source/Checks/cm_cxx_fallthrough.cxx create mode 100644 Source/Checks/cm_cxx_gnu_fallthrough.cxx create mode 100644 Source/LexerParser/.clang-tidy create mode 100644 Source/LexerParser/.gitattributes rename Source/{ => LexerParser}/cmCommandArgumentLexer.cxx (100%) rename Source/{ => LexerParser}/cmCommandArgumentLexer.h (100%) rename Source/{ => LexerParser}/cmCommandArgumentLexer.in.l (100%) rename Source/{ => LexerParser}/cmCommandArgumentParser.cxx (58%) rename Source/{ => LexerParser}/cmCommandArgumentParser.y (54%) rename Source/{ => LexerParser}/cmCommandArgumentParserTokens.h (52%) rename Source/{ => LexerParser}/cmDependsJavaLexer.cxx (100%) rename Source/{ => LexerParser}/cmDependsJavaLexer.h (100%) rename Source/{ => LexerParser}/cmDependsJavaLexer.in.l (100%) rename Source/{ => LexerParser}/cmDependsJavaParser.cxx (58%) rename Source/{ => LexerParser}/cmDependsJavaParser.y (98%) create mode 100644 Source/LexerParser/cmDependsJavaParserTokens.h rename Source/{ => LexerParser}/cmExprLexer.cxx (100%) rename Source/{ => LexerParser}/cmExprLexer.h (100%) rename Source/{ => LexerParser}/cmExprLexer.in.l (100%) rename Source/{ => LexerParser}/cmExprParser.cxx (96%) rename Source/{ => LexerParser}/cmExprParser.y (97%) rename Source/{ => LexerParser}/cmExprParserTokens.h (100%) rename Source/{ => LexerParser}/cmFortranLexer.cxx (100%) rename Source/{ => LexerParser}/cmFortranLexer.h (100%) rename Source/{ => LexerParser}/cmFortranLexer.in.l (100%) rename Source/{ => LexerParser}/cmFortranParser.cxx (96%) rename Source/{ => LexerParser}/cmFortranParser.y (98%) rename Source/{ => LexerParser}/cmFortranParserTokens.h (98%) rename Source/{ => LexerParser}/cmListFileLexer.c (99%) rename Source/{ => LexerParser}/cmListFileLexer.in.l (99%) rename Source/QtDialog/{CMake.desktop => cmake-gui.desktop} (100%) delete mode 100644 Source/cmDependsJavaParserTokens.h create mode 100644 Source/cmDisallowedCommand.cxx create mode 100644 Source/cmDisallowedCommand.h create mode 100644 Source/cmQtAutoGeneratorCommon.cxx create mode 100644 Source/cmQtAutoGeneratorCommon.h delete mode 100644 Source/cmStandardIncludes.h create mode 100644 Source/cmVS10CudaFlagTable.h create mode 100644 Source/cmVS10CudaHostFlagTable.h create mode 100644 Source/cmVS10NASMFlagTable.h rename Source/{cmVS14LinkFlagTable.h => cmVS140LinkFlagTable.h} (97%) create mode 100644 Source/cmVS141LinkFlagTable.h create mode 100644 Source/cmWorkingDirectory.cxx create mode 100644 Source/cmWorkingDirectory.h create mode 100644 Source/cmXCodeScheme.cxx create mode 100644 Source/cmXCodeScheme.h create mode 100644 Source/cm_sys_stat.h create mode 100644 Templates/MSBuild/nasm.props.in create mode 100644 Templates/MSBuild/nasm.targets create mode 100644 Templates/MSBuild/nasm.xml delete mode 100644 Tests/CMakeCommands/target_compile_features/dummy.cpp rename Tests/{RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake => CMakeOnly/find_library/lib/A/libXYZ/libtest2.a} (100%) rename Tests/{RunCMake/CommandLine/DeprecateVS71-WARN-ON.cmake => CMakeOnly/find_library/lib/A/libx32/libtest3.a} (100%) create mode 100644 Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a create mode 100644 Tests/CMakeOnly/find_library/lib/x32/libtest2.a create mode 100644 Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a create mode 100644 Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a create mode 100644 Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a create mode 100644 Tests/CMakeOnly/find_library/libXYZ/libtest7.a create mode 100644 Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a create mode 100644 Tests/CMakeOnly/find_library/libx32/A/libtest1.a create mode 100644 Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a create mode 100644 Tests/CMakeOnly/find_library/libx32/libtest1.a delete mode 100644 Tests/CMakeTests/SeparateArgumentsTest.cmake.in create mode 100644 Tests/CSharpLinkToCxx/CMakeLists.txt create mode 100644 Tests/CSharpLinkToCxx/cli.cpp create mode 100644 Tests/CSharpLinkToCxx/cli.hpp create mode 100644 Tests/CSharpLinkToCxx/csharp.cs create mode 100644 Tests/CudaOnly/ExportPTX/CMakeLists.txt create mode 100644 Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake create mode 100644 Tests/CudaOnly/ExportPTX/kernelA.cu create mode 100644 Tests/CudaOnly/ExportPTX/kernelB.cu create mode 100644 Tests/CudaOnly/ExportPTX/main.cu create mode 100644 Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt create mode 100644 Tests/CudaOnly/ResolveDeviceSymbols/file1.cu create mode 100644 Tests/CudaOnly/ResolveDeviceSymbols/file1.h create mode 100644 Tests/CudaOnly/ResolveDeviceSymbols/file2.cu create mode 100644 Tests/CudaOnly/ResolveDeviceSymbols/file2.h create mode 100644 Tests/CudaOnly/ResolveDeviceSymbols/main.cu create mode 100644 Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake create mode 100644 Tests/CudaOnly/WithDefs/main_for_vs.cu create mode 100644 Tests/ExportImport/Export/sub/testLib8C.c create mode 100644 Tests/ExportImport/Export/testLib8A.c create mode 100644 Tests/ExportImport/Export/testLib8B.c create mode 100644 Tests/ExportImport/Import/A/imp_testLib8.c create mode 100644 Tests/FindDoxygen/CMakeLists.txt create mode 100644 Tests/FindDoxygen/DotComponentTestTest/CMakeLists.txt create mode 100644 Tests/FindDoxygen/SimpleTest/CMakeLists.txt create mode 100644 Tests/FindDoxygen/SimpleTest/main.cpp create mode 100644 Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in create mode 100644 Tests/FindMPI/CMakeLists.txt create mode 100644 Tests/FindMPI/Test/CMakeLists.txt create mode 100644 Tests/FindMPI/Test/main.c create mode 100644 Tests/FindMPI/Test/main.f90 create mode 100644 Tests/FindOpenMP/CMakeLists.txt create mode 100644 Tests/FindOpenMP/Test/CMakeLists.txt create mode 100644 Tests/FindOpenMP/Test/main.c create mode 100644 Tests/FindOpenMP/Test/main.f90.in create mode 100644 Tests/FindOpenMP/Test/scalprod.c create mode 100644 Tests/FindOpenMP/Test/scalprod.f90.in create mode 100644 Tests/FindOpenMP/Test/scaltest.c create mode 100644 Tests/FindOpenMP/Test/scaltest.f90.in create mode 100644 Tests/FindProtobuf/CMakeLists.txt create mode 100644 Tests/FindProtobuf/Test/CMakeLists.txt create mode 100644 Tests/FindProtobuf/Test/main-protoc.cxx create mode 100644 Tests/FindProtobuf/Test/main.cxx create mode 100644 Tests/GeneratorExpression/check_object_files.cmake create mode 100644 Tests/GeneratorExpression/objlib1.c create mode 100644 Tests/GeneratorExpression/objlib2.c create mode 100644 Tests/GoogleTest/CMakeLists.txt create mode 100644 Tests/GoogleTest/Test/CMakeLists.txt create mode 100644 Tests/GoogleTest/Test/main1.cxx create mode 100644 Tests/GoogleTest/Test/main2.cxx create mode 100644 Tests/GoogleTest/Test/main2.h create mode 100644 Tests/GoogleTest/Test/main3.cxx create mode 100644 Tests/GoogleTest/Test/main4.cxx create mode 100644 Tests/GoogleTest/Test/main4.h create mode 100644 Tests/Module/CheckIPOSupported-C/CMakeLists.txt create mode 100644 Tests/Module/CheckIPOSupported-C/foo.c create mode 100644 Tests/Module/CheckIPOSupported-C/main.c create mode 100644 Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt create mode 100644 Tests/Module/CheckIPOSupported-CXX/foo.cpp create mode 100644 Tests/Module/CheckIPOSupported-CXX/main.cpp create mode 100644 Tests/Module/CheckIPOSupported-Fortran/CMakeLists.txt create mode 100644 Tests/Module/CheckIPOSupported-Fortran/foo.f create mode 100644 Tests/Module/CheckIPOSupported-Fortran/main.f create mode 100644 Tests/ModuleDefinition/split_dll.c create mode 100644 Tests/ModuleDefinition/split_dll_1.def create mode 100644 Tests/ModuleDefinition/split_dll_2.def delete mode 100644 Tests/QtAutogen/automoc_rerun/CMakeLists.txt delete mode 100644 Tests/QtAutogen/automoc_rerun/test1.cpp delete mode 100644 Tests/QtAutogen/automoc_rerun/test1.h.in1 delete mode 100644 Tests/QtAutogen/automoc_rerun/test1.h.in2 delete mode 100644 Tests/QtAutogen/autorcc_depends/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocDepends/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocDepends/invalid.hpp.in create mode 100644 Tests/QtAutogen/mocDepends/object.hpp.in create mode 100644 Tests/QtAutogen/mocDepends/simpleLib.cpp.in create mode 100644 Tests/QtAutogen/mocDepends/simpleLib.hpp.in create mode 100644 Tests/QtAutogen/mocDepends/test1.cpp create mode 100644 Tests/QtAutogen/mocDepends/test2.cpp create mode 100644 Tests/QtAutogen/mocDepends/test2.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjA.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjA.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjB.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjB.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjC.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjC.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjD.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjD.hpp create mode 100644 Tests/QtAutogen/mocInclude/subA/SubObjA.cpp create mode 100644 Tests/QtAutogen/mocInclude/subA/SubObjA.hpp create mode 100644 Tests/QtAutogen/mocInclude/subB/SubObjB.cpp create mode 100644 Tests/QtAutogen/mocInclude/subB/SubObjB.hpp create mode 100644 Tests/QtAutogen/mocInclude/subC/SubObjC.cpp create mode 100644 Tests/QtAutogen/mocInclude/subC/SubObjC.hpp create mode 100644 Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocIncludeRelaxed/main.cpp create mode 100644 Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocIncludeStrict/main.cpp create mode 100644 Tests/QtAutogen/mocPlugin/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.json create mode 100644 Tests/QtAutogen/mocPlugin/StyleA_Custom.json create mode 100644 Tests/QtAutogen/mocPlugin/StyleB.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleB.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleC.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleC.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleCommon.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleD.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleD.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleE.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleE.hpp create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json create mode 100644 Tests/QtAutogen/mocPlugin/main.cpp create mode 100644 Tests/QtAutogen/mocRerun/CMakeLists.txt rename Tests/QtAutogen/{automoc_rerun => mocRerun}/input.txt (100%) create mode 100644 Tests/QtAutogen/mocRerun/main.cpp.in rename Tests/QtAutogen/{automoc_rerun => mocRerun}/res1.qrc (100%) create mode 100644 Tests/QtAutogen/mocRerun/test1a.h.in create mode 100644 Tests/QtAutogen/mocRerun/test1b.h.in create mode 100644 Tests/QtAutogen/rccDepends/CMakeLists.txt rename Tests/QtAutogen/{autorcc_depends/test_res1.cpp => rccDepends/main.cpp} (100%) rename Tests/QtAutogen/{autorcc_depends/res1/input.txt.in => rccDepends/res/input1.txt.in} (100%) create mode 100644 Tests/QtAutogen/rccDepends/res/input2.txt.in rename Tests/QtAutogen/{autorcc_depends/res1.qrc.in => rccDepends/res1a.qrc.in} (66%) create mode 100644 Tests/QtAutogen/rccDepends/res1b.qrc.in create mode 100644 Tests/QtAutogen/rccDepends/res2a.qrc.in create mode 100644 Tests/QtAutogen/rccDepends/res2b.qrc.in create mode 100644 Tests/QtAutogen/uicInclude/CMakeLists.txt create mode 100644 Tests/QtAutogen/uicInclude/PageC.ui create mode 100644 Tests/QtAutogen/uicInclude/dirA/PageA.ui create mode 100644 Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui create mode 100644 Tests/QtAutogen/uicInclude/main.cpp create mode 100644 Tests/QtAutogen/uicInclude/main.hpp create mode 100644 Tests/RunCMake/Android/android_sysinc.c create mode 100644 Tests/RunCMake/Android/android_sysinc.cxx create mode 100644 Tests/RunCMake/Android/sysinc/dlfcn.h create mode 100644 Tests/RunCMake/AutoExportDll/nop.asm create mode 100644 Tests/RunCMake/BuildDepends/MakeCustomIncludes.cmake create mode 100644 Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx create mode 100644 Tests/RunCMake/BuildDepends/MakeCustomIncludes.step1.cmake create mode 100644 Tests/RunCMake/BuildDepends/MakeCustomIncludes.step2.cmake create mode 100644 Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0026/CMP0026-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0026/CMP0026-OLD.cmake create mode 100644 Tests/RunCMake/CMP0026/clear-cached-information-stderr.txt create mode 100644 Tests/RunCMake/CMP0028/CMP0028-OLD-iface-stderr.txt create mode 100644 Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt create mode 100644 Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt create mode 100644 Tests/RunCMake/CMP0068/CMP0068-NEW.cmake create mode 100644 Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt create mode 100644 Tests/RunCMake/CMP0068/CMP0068-OLD.cmake create mode 100644 Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt create mode 100644 Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0068/CMP0068-WARN.cmake create mode 100644 Tests/RunCMake/CMP0068/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0068/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CMP0068/empty.cpp rename Tests/RunCMake/{ObjectLibrary/Export-result.txt => CMP0069/CMP0069-NEW-cmake-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt create mode 100644 Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake rename Tests/RunCMake/{ObjectLibrary/Import-result.txt => CMP0069/CMP0069-NEW-compiler-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt create mode 100644 Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake rename Tests/RunCMake/{ObjectLibrary/Install-result.txt => CMP0069/CMP0069-NEW-generator-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt create mode 100644 Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake create mode 100644 Tests/RunCMake/CMP0069/CMP0069-OLD.cmake create mode 100644 Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt create mode 100644 Tests/RunCMake/CMP0069/CMP0069-WARN.cmake create mode 100644 Tests/RunCMake/CMP0069/CMakeLists.txt create mode 100644 Tests/RunCMake/CMP0069/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/CMP0069/main.cpp create mode 100644 Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake create mode 100644 Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake create mode 100644 Tests/RunCMake/CheckIPOSupported/CMakeLists.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake rename Tests/RunCMake/{TargetObjects/BadContext-result.txt => CheckIPOSupported/cmp0069-is-old-result.txt} (100%) create mode 100644 Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake rename Tests/RunCMake/{find_dependency/EXACT-no-version-result.txt => CheckIPOSupported/default-lang-none-result.txt} (100%) create mode 100644 Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/default-lang-none.cmake rename Tests/RunCMake/{find_dependency/empty-arg-3-result.txt => CheckIPOSupported/not-supported-by-cmake-result.txt} (100%) create mode 100644 Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake rename Tests/RunCMake/{find_dependency/empty-version-result.txt => CheckIPOSupported/not-supported-by-compiler-result.txt} (100%) create mode 100644 Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake rename Tests/RunCMake/{find_dependency/extra-args-result.txt => CheckIPOSupported/not-supported-by-generator-result.txt} (100%) create mode 100644 Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake create mode 100644 Tests/RunCMake/CheckIPOSupported/save-to-result.cmake rename Tests/RunCMake/{find_dependency/invalid-arg-3-result.txt => CheckIPOSupported/unparsed-arguments-result.txt} (100%) create mode 100644 Tests/RunCMake/CheckIPOSupported/unparsed-arguments-stderr.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/unparsed-arguments.cmake create mode 100644 Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/user-lang-unknown-stderr.txt create mode 100644 Tests/RunCMake/CheckIPOSupported/user-lang-unknown.cmake delete mode 100644 Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/DeprecateVS8-WARN-OFF.cmake create mode 100644 Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON.cmake create mode 100644 Tests/RunCMake/CommandLine/reject_fifo-result.txt create mode 100644 Tests/RunCMake/CommandLine/reject_fifo-stderr.txt create mode 100644 Tests/RunCMake/DisallowedCommands/CMP0029-OLD-stderr.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake create mode 100644 Tests/RunCMake/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder create mode 100644 Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder create mode 100644 Tests/RunCMake/Framework/deepresource.txt create mode 100644 Tests/RunCMake/Framework/flatresource.txt create mode 100644 Tests/RunCMake/Framework/some.txt create mode 100644 Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt create mode 100644 Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt create mode 100644 Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt create mode 100644 Tests/RunCMake/GNUInstallDirs/UsrLocal-BSD-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt create mode 100644 Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake create mode 100644 Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-result.txt create mode 100644 Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR.cmake create mode 100644 Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt create mode 100644 Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake create mode 100644 Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-result.txt create mode 100644 Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake create mode 100644 Tests/RunCMake/Ninja/AssumedSources.cmake create mode 100644 Tests/RunCMake/Ninja/CommandConcat.cmake create mode 100644 Tests/RunCMake/Ninja/LooseObjectDepends.cmake create mode 100644 Tests/RunCMake/Ninja/dep.c create mode 100644 Tests/RunCMake/Ninja/top.c create mode 100644 Tests/RunCMake/ObjectLibrary/Dependencies.cmake delete mode 100644 Tests/RunCMake/ObjectLibrary/Export-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt rename Tests/RunCMake/ObjectLibrary/{Import-stderr.txt => ImportNotSupported-stderr.txt} (55%) create mode 100644 Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/InstallNotSupported-result.txt rename Tests/RunCMake/ObjectLibrary/{Install-stderr.txt => InstallNotSupported-stderr.txt} (54%) create mode 100644 Tests/RunCMake/ObjectLibrary/InstallNotSupported.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/OwnSources-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/OwnSources.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/b.c create mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.c create mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.c create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj0.c create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj1.c delete mode 100644 Tests/RunCMake/TargetObjects/BadContext-stderr.txt create mode 100644 Tests/RunCMake/TargetObjects/NoTarget-result.txt create mode 100644 Tests/RunCMake/TargetObjects/NoTarget-stderr.txt rename Tests/RunCMake/TargetObjects/{BadContext.cmake => NoTarget.cmake} (100%) create mode 100644 Tests/RunCMake/TargetObjects/NotObjlibTarget-result.txt create mode 100644 Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt create mode 100644 Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake create mode 100644 Tests/RunCMake/TargetObjects/empty.cpp create mode 100644 Tests/RunCMake/TargetSources/CMP0026-LOCATION-stderr.txt create mode 100644 Tests/RunCMake/VSSolution/Override3-check.cmake create mode 100644 Tests/RunCMake/VSSolution/Override3.cmake create mode 100644 Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake create mode 100644 Tests/RunCMake/ctest_disabled_test/CMakeLists.txt.in create mode 100644 Tests/RunCMake/ctest_disabled_test/CTestConfig.cmake.in create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableAllTests-result.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableAllTests-stderr.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableAllTests-stdout.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableFailingTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-result.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stderr.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisabledTest-result.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisabledTest-stderr.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/DisabledTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_disabled_test/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/ctest_disabled_test/test.cmake.in create mode 100644 Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt create mode 100644 Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt create mode 100644 Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt create mode 100644 Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt create mode 100644 Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt create mode 100644 Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt create mode 100644 Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt create mode 100644 Tests/RunCMake/ctest_skipped_test/CMakeLists.txt.in create mode 100644 Tests/RunCMake/ctest_skipped_test/CTestConfig.cmake.in create mode 100644 Tests/RunCMake/ctest_skipped_test/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt create mode 100644 Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt create mode 100755 Tests/RunCMake/ctest_skipped_test/skip.bat create mode 100755 Tests/RunCMake/ctest_skipped_test/skip.sh create mode 100644 Tests/RunCMake/ctest_skipped_test/test.cmake.in create mode 100644 Tests/RunCMake/ctest_submit/CDashSubmitHeaders-result.txt create mode 100644 Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stderr.txt create mode 100644 Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stdout.txt create mode 100644 Tests/RunCMake/ctest_submit/CDashUploadHeaders-result.txt create mode 100644 Tests/RunCMake/ctest_submit/CDashUploadHeaders-stderr.txt create mode 100644 Tests/RunCMake/ctest_submit/CDashUploadHeaders-stdout.txt create mode 100644 Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt create mode 100644 Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt create mode 100644 Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake create mode 100644 Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt create mode 100644 Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake create mode 100644 Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt create mode 100644 Tests/RunCMake/file/INSTALL-SYMLINK.cmake create mode 100644 Tests/RunCMake/file/READ_ELF-result.txt create mode 100644 Tests/RunCMake/file/READ_ELF-stderr.txt create mode 100644 Tests/RunCMake/file/READ_ELF.cmake create mode 100644 Tests/RunCMake/file/from/a.txt create mode 100644 Tests/RunCMake/file/from/a/b.txt create mode 100644 Tests/RunCMake/file/from/a/b/c.txt delete mode 100644 Tests/RunCMake/find_dependency/EXACT-no-version-stderr.txt delete mode 100644 Tests/RunCMake/find_dependency/EXACT-no-version.cmake create mode 100644 Tests/RunCMake/find_dependency/bad-version-exact-result.txt create mode 100644 Tests/RunCMake/find_dependency/bad-version-exact-stderr.txt create mode 100644 Tests/RunCMake/find_dependency/bad-version-exact.cmake create mode 100644 Tests/RunCMake/find_dependency/bad-version-fuzzy-result.txt create mode 100644 Tests/RunCMake/find_dependency/bad-version-fuzzy-stderr.txt create mode 100644 Tests/RunCMake/find_dependency/bad-version-fuzzy.cmake create mode 100644 Tests/RunCMake/find_dependency/basic.cmake delete mode 100644 Tests/RunCMake/find_dependency/empty-arg-3-stderr.txt delete mode 100644 Tests/RunCMake/find_dependency/empty-arg-3.cmake delete mode 100644 Tests/RunCMake/find_dependency/empty-version-stderr.txt delete mode 100644 Tests/RunCMake/find_dependency/empty-version.cmake delete mode 100644 Tests/RunCMake/find_dependency/extra-args-stderr.txt delete mode 100644 Tests/RunCMake/find_dependency/extra-args.cmake delete mode 100644 Tests/RunCMake/find_dependency/invalid-arg-3-stderr.txt create mode 100644 Tests/RunCMake/find_dependency/invalid-arg-result.txt create mode 100644 Tests/RunCMake/find_dependency/invalid-arg-stderr.txt rename Tests/RunCMake/find_dependency/{invalid-arg-3.cmake => invalid-arg.cmake} (57%) create mode 100644 Tests/RunCMake/find_dependency/realistic.cmake rename Tests/RunCMake/find_dependency/{ => share/cmake}/Pack1/Pack1Config.cmake (100%) rename Tests/RunCMake/find_dependency/{ => share/cmake}/Pack1/Pack1ConfigVersion.cmake (100%) create mode 100644 Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2Config.cmake create mode 100644 Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2ConfigVersion.cmake create mode 100644 Tests/RunCMake/find_package/MissingConfig-stdout.txt create mode 100644 Tests/RunCMake/find_package/MissingConfigNormal-stdout.txt delete mode 100644 Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt create mode 100644 Tests/RunCMake/find_package/MissingConfigOneName-stdout.txt delete mode 100644 Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt create mode 100644 Tests/RunCMake/find_package/MissingConfigVersion-stdout.txt create mode 100644 Tests/RunCMake/find_package/PackageRoot-stderr.txt create mode 100644 Tests/RunCMake/find_package/PackageRoot.cmake create mode 100644 Tests/RunCMake/find_package/PackageRoot/FindBar.cmake create mode 100644 Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake create mode 100755 Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/bin/bar.exe create mode 100644 Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/bar.h create mode 100644 Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/zot/zot.h create mode 100755 Tests/RunCMake/find_package/PackageRoot/bar/env_root/bin/bar.exe create mode 100644 Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/bar.h create mode 100644 Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/zot/zot.h create mode 100755 Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/bar.exe create mode 100755 Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/foo.exe create mode 100644 Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/bar.h create mode 100644 Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/foo.h create mode 100644 Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/zot/zot.h create mode 100755 Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/bar.exe create mode 100755 Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/foo.exe create mode 100644 Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/bar.h create mode 100644 Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/foo.h create mode 100644 Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/zot/zot.h create mode 100644 Tests/RunCMake/find_package/VersionedA-1/VersionedAConfig.cmake create mode 100644 Tests/RunCMake/find_package/VersionedA-1/VersionedAConfigVersion.cmake create mode 100644 Tests/RunCMake/find_package/VersionedA-2/VersionedAConfig.cmake create mode 100644 Tests/RunCMake/find_package/VersionedA-2/VersionedAConfigVersion.cmake create mode 100644 Tests/RunCMake/find_package/WrongVersion-stderr.txt create mode 100644 Tests/RunCMake/find_package/WrongVersion.cmake create mode 100644 Tests/RunCMake/find_package/WrongVersionConfig-stderr.txt create mode 100644 Tests/RunCMake/find_package/WrongVersionConfig.cmake create mode 100644 Tests/RunCMake/get_property/IsMultiConfig-stdout.txt create mode 100644 Tests/RunCMake/get_property/IsMultiConfig.cmake create mode 100644 Tests/RunCMake/get_property/NotMultiConfig-stdout.txt create mode 100644 Tests/RunCMake/get_property/NotMultiConfig.cmake create mode 100644 Tests/RunCMake/if/duplicate-deep-else-result.txt create mode 100644 Tests/RunCMake/if/duplicate-deep-else-stderr.txt create mode 100644 Tests/RunCMake/if/duplicate-deep-else.cmake create mode 100644 Tests/RunCMake/if/duplicate-else-after-elseif-result.txt create mode 100644 Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt create mode 100644 Tests/RunCMake/if/duplicate-else-after-elseif.cmake create mode 100644 Tests/RunCMake/if/duplicate-else-result.txt create mode 100644 Tests/RunCMake/if/duplicate-else-stderr.txt create mode 100644 Tests/RunCMake/if/duplicate-else.cmake create mode 100644 Tests/RunCMake/if/misplaced-elseif-result.txt create mode 100644 Tests/RunCMake/if/misplaced-elseif-stderr.txt create mode 100644 Tests/RunCMake/if/misplaced-elseif.cmake create mode 100644 Tests/RunCMake/include_external_msproject/CustomConfig-check.cmake create mode 100644 Tests/RunCMake/include_external_msproject/CustomConfig.cmake create mode 100644 Tests/RunCMake/install/FILES-TARGET_OBJECTS-all-check.cmake create mode 100644 Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake create mode 100644 Tests/RunCMake/install/obj1.c create mode 100644 Tests/RunCMake/install/obj2.c create mode 100644 Tests/RunCMake/project/ProjectDescription-stdout.txt create mode 100644 Tests/RunCMake/project/ProjectDescription.cmake create mode 100644 Tests/RunCMake/project/ProjectDescription2-result.txt create mode 100644 Tests/RunCMake/project/ProjectDescription2-stderr.txt create mode 100644 Tests/RunCMake/project/ProjectDescription2.cmake create mode 100644 Tests/RunCMake/separate_arguments/CMakeLists.txt create mode 100644 Tests/RunCMake/separate_arguments/EmptyCommand.cmake create mode 100644 Tests/RunCMake/separate_arguments/NativeCommand.cmake create mode 100644 Tests/RunCMake/separate_arguments/PlainCommand.cmake create mode 100644 Tests/RunCMake/separate_arguments/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/separate_arguments/UnixCommand.cmake create mode 100644 Tests/RunCMake/separate_arguments/WindowsCommand.cmake create mode 100644 Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt create mode 100644 Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt create mode 100644 Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake delete mode 100644 Tests/SourceGroups/tree_foo.c create mode 100644 Tests/SourceGroups/tree_prefix_bar.c create mode 100644 Tests/SourceGroups/tree_prefix_foo.c create mode 100644 Tests/VSNASM/CMakeLists.txt create mode 100644 Tests/VSNASM/foo.asm create mode 100644 Tests/VSNASM/include/foo-proc.asm create mode 100644 Tests/VSNASM/main.c create mode 100644 Tests/XCTest/StaticLibExample/StaticLibExample.c create mode 100644 Tests/XCTest/StaticLibExample/StaticLibExample.h create mode 100644 Tests/XCTest/StaticLibExampleTests/Info.plist create mode 100644 Tests/XCTest/StaticLibExampleTests/StaticLibExampleTests.m create mode 100644 Utilities/.clang-tidy create mode 100644 Utilities/IWYU/mapping.imp create mode 100755 Utilities/Release/consolidate-relnotes.bash delete mode 100644 Utilities/Release/hythloth_release.cmake create mode 100644 Utilities/cmcurl/CMake/FindMbedTLS.cmake create mode 100644 Utilities/cmcurl/include/curl/system.h create mode 100644 Utilities/cmcurl/lib/rand.c create mode 100644 Utilities/cmcurl/lib/rand.h create mode 100644 Utilities/cmexpat/lib/siphash.h delete mode 100644 Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake delete mode 100644 Utilities/cmlibarchive/build/cmake/FindLZMA.cmake create mode 100644 Utilities/cmlibuv/include/uv-posix.h create mode 100644 Utilities/cmlibuv/src/unix/bsd-ifaddrs.c create mode 100644 Utilities/cmlibuv/src/unix/cygwin.c create mode 100644 Utilities/cmlibuv/src/unix/no-fsevents.c create mode 100644 Utilities/cmlibuv/src/unix/no-proctitle.c create mode 100644 Utilities/cmlibuv/src/unix/os390-syscalls.c create mode 100644 Utilities/cmlibuv/src/unix/os390-syscalls.h create mode 100644 Utilities/cmlibuv/src/unix/posix-hrtime.c create mode 100644 Utilities/cmlibuv/src/unix/posix-poll.c create mode 100644 Utilities/cmlibuv/src/unix/procfs-exepath.c create mode 100644 Utilities/cmlibuv/src/unix/sysinfo-loadavg.c create mode 100644 Utilities/cmlibuv/src/unix/sysinfo-memory.c diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..a9d121aa0 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,30 @@ +--- +Checks: "-*,\ +misc-*,\ +-misc-incorrect-roundings,\ +-misc-macro-parentheses,\ +-misc-misplaced-widening-cast,\ +-misc-static-assert,\ +modernize-make-shared,\ +modernize-make-unique,\ +modernize-redundant-void-arg,\ +modernize-use-bool-literals,\ +modernize-use-nullptr,\ +modernize-use-override,\ +performance-*,\ +-performance-inefficient-string-concatenation,\ +readability-*,\ +-readability-function-size,\ +-readability-identifier-naming,\ +-readability-implicit-bool-cast,\ +-readability-inconsistent-declaration-parameter-name,\ +-readability-named-parameter,\ +-readability-redundant-declaration,\ +-readability-redundant-member-init,\ +-readability-simplify-boolean-expr,\ +" +HeaderFilterRegex: 'Source/cm[^/]*\.(h|hxx|cxx)$' +CheckOptions: + - key: modernize-use-nullptr.NullMacros + value: 'CM_NULLPTR' +... diff --git a/Auxiliary/cmake.m4 b/Auxiliary/cmake.m4 index 3ef4c1617..7beff41a8 100644 --- a/Auxiliary/cmake.m4 +++ b/Auxiliary/cmake.m4 @@ -24,10 +24,10 @@ AC_ARG_VAR([$1][_LIBS], [linker flags for $1. This overrides the cmake output])d failed=false AC_MSG_CHECKING([for $1]) -if test -n "$1[]_$2[]FLAGS"; then +if test -z "${$1[]_$2[]FLAGS}"; then $1[]_$2[]FLAGS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=COMPILE $4` || failed=true fi -if test -n "$1[]_LIBS"; then +if test -z "${$1[]_LIBS}"; then $1[]_LIBS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=LINK $4` || failed=true fi diff --git a/Auxiliary/vim/cmake.vim.in b/Auxiliary/vim/cmake.vim.in index 89ece6618..389d9e46e 100644 --- a/Auxiliary/vim/cmake.vim.in +++ b/Auxiliary/vim/cmake.vim.in @@ -14,54 +14,56 @@ if exists("b:current_syntax") finish endif -syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained syn region cmakeComment start="#" end="$" contains=cmakeTodo,@Spell syn region cmakeLuaComment start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell -syn region cmakeGeneratorExpression start=/$/ - \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable,cmakeProperty,cmakeGeneratorExpressions -syn region cmakeRegistry start=/\[/ end=/]/ - \ contained oneline contains=CONTAINED,cmakeTodo,cmakeEscaped -syn region cmakeVariableValue start=/\${/ end=/}/ - \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable -syn region cmakeEnvironment start=/\$ENV{/ end=/}/ - \ contained oneline contains=CONTAINED,cmakeTodo -syn region cmakeString start=/"/ end=/"/ - \ contains=CONTAINED,cmakeTodo -syn region cmakeArguments start=/(/ end=/)/ - \ contains=ALLBUT,cmakeArguments,cmakeTodo + +syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained +syn region cmakeRegistry start="\[" end="]" contained oneline contains=cmakeTodo,cmakeEscaped + +syn region cmakeGeneratorExpression start="$<" end=">" contained oneline contains=cmakeVariableValue,cmakeProperty,cmakeGeneratorExpressions,cmakeTodo + +syn region cmakeString start='"' end='"' contained contains=cmakeTodo,cmakeVariableValue + +syn region cmakeVariableValue start="${" end="}" contained oneline contains=cmakeVariable,cmakeTodo + +syn region cmakeEnvironment start="$ENV{" end="}" contained oneline contains=cmakeTodo + +syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeArguments,cmakeTodo syn case match -syn keyword cmakeProperty + +syn keyword cmakeProperty contained \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_DEBUG ARCHIVE_OUTPUT_DIRECTORY_RELEASE ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_DEBUG ARCHIVE_OUTPUT_NAME_RELEASE ATTACHED_FILES ATTACHED_FILES_ON_FAIL AUTOGEN_TARGETS_FOLDER AUTOGEN_TARGET_DEPENDS AUTOMOC AUTOMOC_MOC_OPTIONS AUTOMOC_TARGETS_FOLDER AUTORCC AUTORCC_OPTIONS AUTOUIC AUTOUIC_OPTIONS BINARY_DIR BUILD_WITH_INSTALL_RPATH BUNDLE BUNDLE_EXTENSION CACHE_VARIABLES CLEAN_NO_CUSTOM CMAKE_CONFIGURE_DEPENDS CMAKE_CXX_KNOWN_FEATURES CMAKE_C_KNOWN_FEATURES COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN COMPATIBLE_INTERFACE_STRING COMPILE_DEFINITIONS COMPILE_DEFINITIONS_DEBUG COMPILE_DEFINITIONS_RELEASE COMPILE_FEATURES COMPILE_FLAGS COMPILE_OPTIONS COMPILE_PDB_NAME COMPILE_PDB_NAME_DEBUG COMPILE_PDB_NAME_RELEASE COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG COMPILE_PDB_OUTPUT_DIRECTORY_RELEASE COST CPACK_DESKTOP_SHORTCUTS CPACK_NEVER_OVERWRITE CPACK_PERMANENT CPACK_STARTUP_SHORTCUTS CPACK_START_MENU_SHORTCUTS CPACK_WIX_ACL CROSSCOMPILING_EMULATOR CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEBUG_CONFIGURATIONS DEBUG_POSTFIX DEFINE_SYMBOL DEFINITIONS DEPENDS DISABLED_FEATURES ECLIPSE_EXTRA_NATURES ENABLED_FEATURES ENABLED_LANGUAGES ENABLE_EXPORTS ENVIRONMENT EXCLUDE_FROM_ALL EXCLUDE_FROM_DEFAULT_BUILD EXCLUDE_FROM_DEFAULT_BUILD_DEBUG EXCLUDE_FROM_DEFAULT_BUILD_RELEASE EXPORT_NAME EXTERNAL_OBJECT EchoString FAIL_REGULAR_EXPRESSION FIND_LIBRARY_USE_LIB64_PATHS FIND_LIBRARY_USE_OPENBSD_VERSIONING FOLDER FRAMEWORK FRAMEWORK_VERSION Fortran_FORMAT Fortran_MODULE_DIRECTORY GENERATED GENERATOR_FILE_NAME GLOBAL_DEPENDS_DEBUG_MODE GLOBAL_DEPENDS_NO_CYCLES GNUtoMS HAS_CXX HEADER_FILE_ONLY HELPSTRING IMPLICIT_DEPENDS_INCLUDE_TRANSFORM IMPORTED IMPORTED_CONFIGURATIONS IMPORTED_IMPLIB IMPORTED_IMPLIB_DEBUG IMPORTED_IMPLIB_RELEASE IMPORTED_LINK_DEPENDENT_LIBRARIES IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE IMPORTED_LINK_INTERFACE_LANGUAGES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE IMPORTED_LINK_INTERFACE_LIBRARIES IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE IMPORTED_LINK_INTERFACE_MULTIPLICITY IMPORTED_LINK_INTERFACE_MULTIPLICITY_DEBUG IMPORTED_LINK_INTERFACE_MULTIPLICITY_RELEASE IMPORTED_LOCATION IMPORTED_LOCATION_DEBUG IMPORTED_LOCATION_RELEASE IMPORTED_NO_SONAME IMPORTED_NO_SONAME_DEBUG IMPORTED_NO_SONAME_RELEASE IMPORTED_SONAME IMPORTED_SONAME_DEBUG IMPORTED_SONAME_RELEASE IMPORT_PREFIX IMPORT_SUFFIX INCLUDE_DIRECTORIES INCLUDE_REGULAR_EXPRESSION INSTALL_NAME_DIR INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH INTERFACE_AUTOUIC_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SOURCES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_DEBUG INTERPROCEDURAL_OPTIMIZATION_RELEASE IN_TRY_COMPILE JOB_POOLS JOB_POOL_COMPILE JOB_POOL_LINK KEEP_EXTENSION LABELS LANGUAGE LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_DEBUG LIBRARY_OUTPUT_DIRECTORY_RELEASE LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_DEBUG LIBRARY_OUTPUT_NAME_RELEASE LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED LINK_DIRECTORIES LINK_FLAGS LINK_FLAGS_DEBUG LINK_FLAGS_RELEASE LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_LIBRARIES_RELEASE LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_DEBUG LINK_INTERFACE_MULTIPLICITY_RELEASE LINK_LIBRARIES LINK_SEARCH_END_STATIC LINK_SEARCH_START_STATIC LISTFILE_STACK LOCATION LOCATION_DEBUG LOCATION_RELEASE MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_PACKAGE_LOCATION MACOSX_RPATH MACROS MAP_IMPORTED_CONFIG_DEBUG MAP_IMPORTED_CONFIG_RELEASE MEASUREMENT MODIFIED NAME NO_SONAME NO_SYSTEM_FROM_IMPORTED OBJECT_DEPENDS OBJECT_OUTPUTS OSX_ARCHITECTURES OSX_ARCHITECTURES_DEBUG OSX_ARCHITECTURES_RELEASE OUTPUT_NAME OUTPUT_NAME_DEBUG OUTPUT_NAME_RELEASE PACKAGES_FOUND PACKAGES_NOT_FOUND PARENT_DIRECTORY PASS_REGULAR_EXPRESSION PDB_NAME PDB_NAME_DEBUG PDB_NAME_RELEASE PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_DEBUG PDB_OUTPUT_DIRECTORY_RELEASE POSITION_INDEPENDENT_CODE POST_INSTALL_SCRIPT PREDEFINED_TARGETS_FOLDER PREFIX PRE_INSTALL_SCRIPT PRIVATE_HEADER PROCESSORS PROJECT_LABEL PUBLIC_HEADER REPORT_UNDEFINED_PROPERTIES REQUIRED_FILES RESOURCE RESOURCE_LOCK RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK RULE_MESSAGES RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_DEBUG RUNTIME_OUTPUT_DIRECTORY_RELEASE RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_DEBUG RUNTIME_OUTPUT_NAME_RELEASE RUN_SERIAL SKIP_BUILD_RPATH SKIP_RETURN_CODE SOURCES SOURCE_DIR SOVERSION STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_DEBUG STATIC_LIBRARY_FLAGS_RELEASE STRINGS SUFFIX SYMBOLIC TARGET_ARCHIVES_MAY_BE_SHARED_LIBS TARGET_MESSAGES TARGET_SUPPORTS_SHARED_LIBS TEST_INCLUDE_FILE TIMEOUT TYPE USE_FOLDERS VALUE VARIABLES VERSION VISIBILITY_INLINES_HIDDEN VS_DEPLOYMENT_CONTENT VS_DEPLOYMENT_LOCATION VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER VS_SHADER_ENTRYPOINT VS_SHADER_FLAGS VS_SHADER_MODEL VS_SHADER_TYPE VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES VS_XAML_TYPE WILL_FAIL WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS WORKING_DIRECTORY WRAP_EXCLUDE XCODE_EXPLICIT_FILE_TYPE XCODE_LAST_KNOWN_FILE_TYPE XCTEST - \ contained -syn keyword cmakeVariable +syn keyword cmakeVariable contained @VARIABLE_LIST@ - \ contained -syn keyword cmakeModule +syn keyword cmakeModule contained @MODULES@ - \ contained @KEYWORDS@ -syn keyword cmakeGeneratorExpressions +syn keyword cmakeGeneratorExpressions contained @GENERATOR_EXPRESSIONS@ - \ contained syn case ignore + syn keyword cmakeCommand @COMMAND_LIST@ \ nextgroup=cmakeArguments + syn keyword cmakeCommandConditional @CONDITIONALS@ \ nextgroup=cmakeArguments + syn keyword cmakeCommandRepeat @LOOPS@ \ nextgroup=cmakeArguments + syn keyword cmakeCommandDeprecated @DEPRECATED@ \ nextgroup=cmakeArguments + syn case match syn keyword cmakeTodo @@ -76,15 +78,15 @@ hi def link cmakeComment Comment hi def link cmakeEnvironment Special hi def link cmakeEscaped Special hi def link cmakeGeneratorExpression WarningMsg -hi def link cmakeGeneratorExpressions ModeMsg +hi def link cmakeGeneratorExpressions Constant hi def link cmakeLuaComment Comment hi def link cmakeModule Include hi def link cmakeProperty Constant hi def link cmakeRegistry Underlined hi def link cmakeString String hi def link cmakeTodo TODO -hi def link cmakeVariable Identifier hi def link cmakeVariableValue Type +hi def link cmakeVariable Identifier @KEYWORDS_HIGHLIGHT@ diff --git a/Auxiliary/vim/extract-upper-case.pl b/Auxiliary/vim/extract-upper-case.pl index e945d5211..ea77cbb5c 100755 --- a/Auxiliary/vim/extract-upper-case.pl +++ b/Auxiliary/vim/extract-upper-case.pl @@ -3,6 +3,9 @@ use strict; use warnings; +#my $cmake = "/home/pboettch/devel/upstream/cmake/build/bin/cmake"; +my $cmake = "cmake"; + my @variables; my @commands; my @properties; @@ -10,7 +13,7 @@ my @modules; my %keywords; # command => keyword-list # unwanted upper-cases -my %unwanted = map { $_ => 1 } qw(VS CXX IDE NOTFOUND NO_ DFOO DBAR); +my %unwanted = map { $_ => 1 } qw(VS CXX IDE NOTFOUND NO_ DFOO DBAR NEW); # cannot remove ALL - exists for add_custom_command # control-statements @@ -24,9 +27,10 @@ my %deprecated = map { $_ => 1 } qw(build_name exec_program export_library_depen push @modules, "ExternalProject"; # variables -open(CMAKE, "cmake --help-variable-list|") or die "could not run cmake"; +open(CMAKE, "$cmake --help-variable-list|") or die "could not run cmake"; while () { chomp; + next if /\-"templates" push @variables, $_; } close(CMAKE); @@ -35,17 +39,16 @@ close(CMAKE); my %variables = map { $_ => 1 } @variables; # commands -open(CMAKE, "cmake --help-command-list|"); +open(CMAKE, "$cmake --help-command-list|"); while (my $cmd = ) { chomp $cmd; - push @commands, $cmd; } close(CMAKE); # now generate a keyword-list per command foreach my $cmd (@commands) { - my @word = extract_upper("cmake --help-command $cmd|"); + my @word = extract_upper("$cmake --help-command $cmd|"); next if scalar @word == 0; @@ -54,7 +57,7 @@ foreach my $cmd (@commands) { # and now for modules foreach my $mod (@modules) { - my @word = extract_upper("cmake --help-module $mod|"); + my @word = extract_upper("$cmake --help-module $mod|"); next if scalar @word == 0; @@ -62,10 +65,10 @@ foreach my $mod (@modules) { } # and now for generator-expressions -my @generator_expr = extract_upper("cmake --help-manual cmake-generator-expressions |"); +my @generator_expr = extract_upper("$cmake --help-manual cmake-generator-expressions |"); # properties -open(CMAKE, "cmake --help-property-list|"); +open(CMAKE, "$cmake --help-property-list|"); while () { chomp; push @properties, $_; @@ -88,7 +91,7 @@ while() ! exists $deprecated{$_} } @commands; print OUT " " x 12 , "\\ ", join(" ", @tmp), "\n"; } elsif ($1 eq "VARIABLE_LIST") { - print OUT " " x 12 , "\\ ", join(" ", @variables), "\n"; + print OUT " " x 12 , "\\ ", join(" ", sort keys %variables), "\n"; } elsif ($1 eq "MODULES") { print OUT " " x 12 , "\\ ", join("\n", @modules), "\n"; } elsif ($1 eq "GENERATOR_EXPRESSIONS") { @@ -101,9 +104,8 @@ while() print OUT " " x 12 , "\\ ", join(" ", sort keys %deprecated), "\n"; } elsif ($1 eq "KEYWORDS") { foreach my $k (sort keys %keywords) { - print OUT "syn keyword cmakeKW$k\n"; + print OUT "syn keyword cmakeKW$k contained\n"; print OUT " " x 12, "\\ ", join(" ", @{$keywords{$k}}), "\n"; - print OUT " " x 12, "\\ contained\n"; print OUT "\n"; push @keyword_hi, "hi def link cmakeKW$k ModeMsg"; } @@ -130,7 +132,8 @@ sub extract_upper foreach my $w (m/\b([A-Z_]{2,})\b/g) { next if exists $variables{$w} or # skip if it is a variable - exists $unwanted{$w}; # skip if not wanted + exists $unwanted{$w} or # skip if not wanted + grep(/$w/, @word); # skip if already in array push @word, $w; } diff --git a/Auxiliary/vim/indent/cmake.vim b/Auxiliary/vim/indent/cmake.vim index 76aff64a6..6063e4311 100644 --- a/Auxiliary/vim/indent/cmake.vim +++ b/Auxiliary/vim/indent/cmake.vim @@ -14,6 +14,7 @@ if exists("b:did_indent") endif let b:did_indent = 1 +setlocal et setlocal indentexpr=CMakeGetIndent(v:lnum) setlocal indentkeys+==ENDIF(,ENDFOREACH(,ENDMACRO(,ELSE(,ELSEIF(,ENDWHILE( diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index 1f19cb783..a191c1872 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -14,425 +14,334 @@ if exists("b:current_syntax") finish endif -syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained syn region cmakeComment start="#" end="$" contains=cmakeTodo,@Spell syn region cmakeLuaComment start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell -syn region cmakeGeneratorExpression start=/$/ - \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable,cmakeProperty,cmakeGeneratorExpressions -syn region cmakeRegistry start=/\[/ end=/]/ - \ contained oneline contains=CONTAINED,cmakeTodo,cmakeEscaped -syn region cmakeVariableValue start=/\${/ end=/}/ - \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable -syn region cmakeEnvironment start=/\$ENV{/ end=/}/ - \ contained oneline contains=CONTAINED,cmakeTodo -syn region cmakeString start=/"/ end=/"/ - \ contains=CONTAINED,cmakeTodo -syn region cmakeArguments start=/(/ end=/)/ - \ contains=ALLBUT,cmakeArguments,cmakeTodo + +syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained +syn region cmakeRegistry start="\[" end="]" contained oneline contains=cmakeTodo,cmakeEscaped + +syn region cmakeGeneratorExpression start="$<" end=">" contained oneline contains=cmakeVariableValue,cmakeProperty,cmakeGeneratorExpressions,cmakeTodo + +syn region cmakeString start='"' end='"' contained contains=cmakeTodo,cmakeVariableValue + +syn region cmakeVariableValue start="${" end="}" contained oneline contains=cmakeVariable,cmakeTodo + +syn region cmakeEnvironment start="$ENV{" end="}" contained oneline contains=cmakeTodo + +syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeArguments,cmakeTodo syn case match -syn keyword cmakeProperty - \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_DEBUG ARCHIVE_OUTPUT_DIRECTORY_RELEASE ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_DEBUG ARCHIVE_OUTPUT_NAME_RELEASE ATTACHED_FILES ATTACHED_FILES_ON_FAIL AUTOGEN_TARGETS_FOLDER AUTOGEN_TARGET_DEPENDS AUTOMOC AUTOMOC_MOC_OPTIONS AUTOMOC_TARGETS_FOLDER AUTORCC AUTORCC_OPTIONS AUTOUIC AUTOUIC_OPTIONS BINARY_DIR BUILD_WITH_INSTALL_RPATH BUNDLE BUNDLE_EXTENSION CACHE_VARIABLES CLEAN_NO_CUSTOM CMAKE_CONFIGURE_DEPENDS CMAKE_CXX_KNOWN_FEATURES CMAKE_C_KNOWN_FEATURES COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN COMPATIBLE_INTERFACE_STRING COMPILE_DEFINITIONS COMPILE_DEFINITIONS_DEBUG COMPILE_DEFINITIONS_RELEASE COMPILE_FEATURES COMPILE_FLAGS COMPILE_OPTIONS COMPILE_PDB_NAME COMPILE_PDB_NAME_DEBUG COMPILE_PDB_NAME_RELEASE COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG COMPILE_PDB_OUTPUT_DIRECTORY_RELEASE COST CPACK_DESKTOP_SHORTCUTS CPACK_NEVER_OVERWRITE CPACK_PERMANENT CPACK_STARTUP_SHORTCUTS CPACK_START_MENU_SHORTCUTS CPACK_WIX_ACL CROSSCOMPILING_EMULATOR CXX_EXTENSIONS CXX_CPPLINT CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_CPPLINT C_STANDARD C_STANDARD_REQUIRED DEBUG_CONFIGURATIONS DEBUG_POSTFIX DEFINE_SYMBOL DEFINITIONS DEPENDS DISABLED_FEATURES ECLIPSE_EXTRA_NATURES ENABLED_FEATURES ENABLED_LANGUAGES ENABLE_EXPORTS ENVIRONMENT EXCLUDE_FROM_ALL EXCLUDE_FROM_DEFAULT_BUILD EXCLUDE_FROM_DEFAULT_BUILD_DEBUG EXCLUDE_FROM_DEFAULT_BUILD_RELEASE EXPORT_NAME EXTERNAL_OBJECT EchoString FAIL_REGULAR_EXPRESSION FIND_LIBRARY_USE_LIB64_PATHS FIND_LIBRARY_USE_OPENBSD_VERSIONING FOLDER FRAMEWORK FRAMEWORK_VERSION Fortran_FORMAT Fortran_MODULE_DIRECTORY GENERATED GENERATOR_FILE_NAME GLOBAL_DEPENDS_DEBUG_MODE GLOBAL_DEPENDS_NO_CYCLES GNUtoMS HAS_CXX HEADER_FILE_ONLY HELPSTRING IMPLICIT_DEPENDS_INCLUDE_TRANSFORM IMPORTED IMPORTED_CONFIGURATIONS IMPORTED_IMPLIB IMPORTED_IMPLIB_DEBUG IMPORTED_IMPLIB_RELEASE IMPORTED_LINK_DEPENDENT_LIBRARIES IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE IMPORTED_LINK_INTERFACE_LANGUAGES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE IMPORTED_LINK_INTERFACE_LIBRARIES IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE IMPORTED_LINK_INTERFACE_MULTIPLICITY IMPORTED_LINK_INTERFACE_MULTIPLICITY_DEBUG IMPORTED_LINK_INTERFACE_MULTIPLICITY_RELEASE IMPORTED_LOCATION IMPORTED_LOCATION_DEBUG IMPORTED_LOCATION_RELEASE IMPORTED_NO_SONAME IMPORTED_NO_SONAME_DEBUG IMPORTED_NO_SONAME_RELEASE IMPORTED_SONAME IMPORTED_SONAME_DEBUG IMPORTED_SONAME_RELEASE IMPORT_PREFIX IMPORT_SUFFIX INCLUDE_DIRECTORIES INCLUDE_REGULAR_EXPRESSION INSTALL_NAME_DIR INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH INTERFACE_AUTOUIC_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SOURCES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_DEBUG INTERPROCEDURAL_OPTIMIZATION_RELEASE IN_TRY_COMPILE JOB_POOLS JOB_POOL_COMPILE JOB_POOL_LINK KEEP_EXTENSION LABELS LANGUAGE LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_DEBUG LIBRARY_OUTPUT_DIRECTORY_RELEASE LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_DEBUG LIBRARY_OUTPUT_NAME_RELEASE LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED LINK_DIRECTORIES LINK_FLAGS LINK_FLAGS_DEBUG LINK_FLAGS_RELEASE LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_LIBRARIES_RELEASE LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_DEBUG LINK_INTERFACE_MULTIPLICITY_RELEASE LINK_LIBRARIES LINK_SEARCH_END_STATIC LINK_SEARCH_START_STATIC LISTFILE_STACK LOCATION LOCATION_DEBUG LOCATION_RELEASE MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_PACKAGE_LOCATION MACOSX_RPATH MACROS MAP_IMPORTED_CONFIG_DEBUG MAP_IMPORTED_CONFIG_RELEASE MEASUREMENT MODIFIED NAME NO_SONAME NO_SYSTEM_FROM_IMPORTED OBJECT_DEPENDS OBJECT_OUTPUTS OSX_ARCHITECTURES OSX_ARCHITECTURES_DEBUG OSX_ARCHITECTURES_RELEASE OUTPUT_NAME OUTPUT_NAME_DEBUG OUTPUT_NAME_RELEASE PACKAGES_FOUND PACKAGES_NOT_FOUND PARENT_DIRECTORY PASS_REGULAR_EXPRESSION PDB_NAME PDB_NAME_DEBUG PDB_NAME_RELEASE PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_DEBUG PDB_OUTPUT_DIRECTORY_RELEASE POSITION_INDEPENDENT_CODE POST_INSTALL_SCRIPT PREDEFINED_TARGETS_FOLDER PREFIX PRE_INSTALL_SCRIPT PRIVATE_HEADER PROCESSORS PROJECT_LABEL PUBLIC_HEADER REPORT_UNDEFINED_PROPERTIES REQUIRED_FILES RESOURCE RESOURCE_LOCK RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK RULE_MESSAGES RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_DEBUG RUNTIME_OUTPUT_DIRECTORY_RELEASE RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_DEBUG RUNTIME_OUTPUT_NAME_RELEASE RUN_SERIAL SKIP_BUILD_RPATH SKIP_RETURN_CODE SOURCES SOURCE_DIR SOVERSION STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_DEBUG STATIC_LIBRARY_FLAGS_RELEASE STRINGS SUFFIX SYMBOLIC TARGET_ARCHIVES_MAY_BE_SHARED_LIBS TARGET_MESSAGES TARGET_SUPPORTS_SHARED_LIBS TEST_INCLUDE_FILE TIMEOUT TYPE USE_FOLDERS VALUE VARIABLES VERSION VISIBILITY_INLINES_HIDDEN VS_DEPLOYMENT_CONTENT VS_DEPLOYMENT_LOCATION VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER VS_SHADER_ENTRYPOINT VS_SHADER_FLAGS VS_SHADER_MODEL VS_SHADER_TYPE VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES VS_XAML_TYPE WILL_FAIL WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS WORKING_DIRECTORY WRAP_EXCLUDE XCODE_EXPLICIT_FILE_TYPE XCODE_LAST_KNOWN_FILE_TYPE XCTEST - \ contained -syn keyword cmakeVariable - \ _BINARY_DIR _SOURCE_DIR _VERSION _VERSION_MAJOR _VERSION_MINOR _VERSION_PATCH _VERSION_TWEAK APPLE BORLAND BUILD_SHARED_LIBS CMAKE__POSTFIX CMAKE__ARCHIVE_APPEND CMAKE__ARCHIVE_CREATE CMAKE__ARCHIVE_FINISH CMAKE__COMPILER CMAKE__COMPILER_ABI CMAKE__COMPILER_EXTERNAL_TOOLCHAIN CMAKE__COMPILER_ID CMAKE__COMPILER_LAUNCHER CMAKE__COMPILER_LOADED CMAKE__COMPILER_TARGET CMAKE__COMPILER_VERSION CMAKE__COMPILE_OBJECT CMAKE__CREATE_SHARED_LIBRARY CMAKE__CREATE_SHARED_MODULE CMAKE__CREATE_STATIC_LIBRARY CMAKE__FLAGS CMAKE__FLAGS_DEBUG CMAKE__FLAGS_MINSIZEREL CMAKE__FLAGS_RELEASE CMAKE__FLAGS_RELWITHDEBINFO CMAKE__GHS_KERNEL_FLAGS_DEBUG CMAKE__GHS_KERNEL_FLAGS_MINSIZEREL CMAKE__GHS_KERNEL_FLAGS_RELEASE CMAKE__GHS_KERNEL_FLAGS_RELWITHDEBINFO CMAKE__IGNORE_EXTENSIONS CMAKE__IMPLICIT_INCLUDE_DIRECTORIES CMAKE__IMPLICIT_LINK_DIRECTORIES CMAKE__IMPLICIT_LINK_FRAMEWORK_DIRECTORIES CMAKE__IMPLICIT_LINK_LIBRARIES CMAKE__INCLUDE_WHAT_YOU_USE CMAKE__CPPLINT CMAKE__LIBRARY_ARCHITECTURE CMAKE__LINKER_PREFERENCE CMAKE__LINKER_PREFERENCE_PROPAGATES CMAKE__LINK_EXECUTABLE CMAKE__OUTPUT_EXTENSION CMAKE__PLATFORM_ID CMAKE__SIMULATE_ID CMAKE__SIMULATE_VERSION CMAKE__SIZEOF_DATA_PTR CMAKE__SOURCE_FILE_EXTENSIONS CMAKE__VISIBILITY_PRESET CMAKE_ABSOLUTE_DESTINATION_FILES CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS CMAKE_ANDROID_API CMAKE_ANDROID_API_MIN CMAKE_ANDROID_ARCH CMAKE_ANDROID_ASSETS_DIRECTORIES CMAKE_ANDROID_GUI CMAKE_ANDROID_JAR_DEPENDENCIES CMAKE_ANDROID_JAR_DIRECTORIES CMAKE_ANDROID_JAVA_SOURCE_DIR CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES CMAKE_ANDROID_PROCESS_MAX CMAKE_ANDROID_PROGUARD CMAKE_ANDROID_PROGUARD_CONFIG_PATH CMAKE_ANDROID_SECURE_PROPS_PATH CMAKE_ANDROID_SKIP_ANT_STEP CMAKE_ANDROID_STL_TYPE CMAKE_APPBUNDLE_PATH CMAKE_AR CMAKE_ARCHIVE_OUTPUT_DIRECTORY CMAKE_ARCHIVE_OUTPUT_DIRECTORY_ CMAKE_ARGC CMAKE_ARGV0 CMAKE_AUTOMOC CMAKE_AUTOMOC_MOC_OPTIONS CMAKE_AUTOMOC_RELAXED_MODE CMAKE_AUTORCC CMAKE_AUTORCC_OPTIONS CMAKE_AUTOUIC CMAKE_AUTOUIC_OPTIONS CMAKE_BACKWARDS_COMPATIBILITY CMAKE_BINARY_DIR CMAKE_BUILD_TOOL CMAKE_BUILD_TYPE CMAKE_BUILD_WITH_INSTALL_RPATH CMAKE_CACHEFILE_DIR CMAKE_CACHE_MAJOR_VERSION CMAKE_CACHE_MINOR_VERSION CMAKE_CACHE_PATCH_VERSION CMAKE_CFG_INTDIR CMAKE_CL_64 CMAKE_COLOR_MAKEFILE CMAKE_COMMAND CMAKE_COMPILER_2005 CMAKE_COMPILER_IS_GNU CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_ CMAKE_CONFIGURATION_TYPES CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR CMAKE_CTEST_COMMAND CMAKE_CURRENT_BINARY_DIR CMAKE_CURRENT_LIST_DIR CMAKE_CURRENT_LIST_FILE CMAKE_CURRENT_LIST_LINE CMAKE_CURRENT_SOURCE_DIR CMAKE_CXX_COMPILE_FEATURES CMAKE_CXX_EXTENSIONS CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED CMAKE_C_COMPILE_FEATURES CMAKE_C_EXTENSIONS CMAKE_C_STANDARD CMAKE_C_STANDARD_REQUIRED CMAKE_DEBUG_POSTFIX CMAKE_DEBUG_TARGET_PROPERTIES CMAKE_DISABLE_FIND_PACKAGE_ CMAKE_DL_LIBS CMAKE_EDIT_COMMAND CMAKE_ENABLE_EXPORTS CMAKE_ERROR_DEPRECATED CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_EXECUTABLE_SUFFIX CMAKE_EXE_LINKER_FLAGS CMAKE_EXE_LINKER_FLAGS_ CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_EXPORT_NO_PACKAGE_REGISTRY CMAKE_EXTRA_GENERATOR CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES CMAKE_FIND_APPBUNDLE CMAKE_FIND_FRAMEWORK CMAKE_FIND_LIBRARY_PREFIXES CMAKE_FIND_LIBRARY_SUFFIXES CMAKE_FIND_NO_INSTALL_PREFIX CMAKE_FIND_PACKAGE_NAME CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_WARN_NO_MODULE CMAKE_FIND_ROOT_PATH CMAKE_FIND_ROOT_PATH_MODE_INCLUDE CMAKE_FIND_ROOT_PATH_MODE_LIBRARY CMAKE_FIND_ROOT_PATH_MODE_PACKAGE CMAKE_FIND_ROOT_PATH_MODE_PROGRAM CMAKE_FRAMEWORK_PATH CMAKE_Fortran_FORMAT CMAKE_Fortran_MODDIR_DEFAULT CMAKE_Fortran_MODDIR_FLAG CMAKE_Fortran_MODOUT_FLAG CMAKE_Fortran_MODULE_DIRECTORY CMAKE_GENERATOR CMAKE_GENERATOR_PLATFORM CMAKE_GENERATOR_TOOLSET CMAKE_GNUtoMS CMAKE_HOME_DIRECTORY CMAKE_HOST_APPLE CMAKE_HOST_SYSTEM CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_PROCESSOR CMAKE_HOST_SYSTEM_VERSION CMAKE_HOST_UNIX CMAKE_HOST_WIN32 CMAKE_IGNORE_PATH CMAKE_IMPORT_LIBRARY_PREFIX CMAKE_IMPORT_LIBRARY_SUFFIX CMAKE_INCLUDE_CURRENT_DIR CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE CMAKE_INCLUDE_DIRECTORIES_BEFORE CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE CMAKE_INCLUDE_PATH CMAKE_INSTALL_DEFAULT_COMPONENT_NAME CMAKE_INSTALL_MESSAGE CMAKE_INSTALL_NAME_DIR CMAKE_INSTALL_PREFIX CMAKE_INSTALL_RPATH CMAKE_INSTALL_RPATH_USE_LINK_PATH CMAKE_INTERNAL_PLATFORM_ABI CMAKE_IOS_INSTALL_COMBINED CMAKE_JOB_POOL_COMPILE CMAKE_JOB_POOL_LINK CMAKE_LIBRARY_ARCHITECTURE CMAKE_LIBRARY_ARCHITECTURE_REGEX CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_LIBRARY_OUTPUT_DIRECTORY_ CMAKE_LIBRARY_PATH CMAKE_LIBRARY_PATH_FLAG CMAKE_LINK_DEF_FILE_FLAG CMAKE_LINK_DEPENDS_NO_SHARED CMAKE_LINK_INTERFACE_LIBRARIES CMAKE_LINK_LIBRARY_FILE_FLAG CMAKE_LINK_LIBRARY_FLAG CMAKE_LINK_LIBRARY_SUFFIX CMAKE_LINK_SEARCH_END_STATIC CMAKE_LINK_SEARCH_START_STATIC CMAKE_MACOSX_BUNDLE CMAKE_MACOSX_RPATH CMAKE_MAJOR_VERSION CMAKE_MAKE_PROGRAM CMAKE_MAP_IMPORTED_CONFIG_ CMAKE_MATCH_COUNT CMAKE_MFC_FLAG CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_MINOR_VERSION CMAKE_MODULE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS_ CMAKE_MODULE_PATH CMAKE_NOT_USING_CONFIG_FLAGS CMAKE_NO_BUILTIN_CHRPATH CMAKE_NO_SYSTEM_FROM_IMPORTED CMAKE_OBJECT_PATH_MAX CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT CMAKE_PARENT_LIST_FILE CMAKE_PATCH_VERSION CMAKE_PDB_OUTPUT_DIRECTORY CMAKE_PDB_OUTPUT_DIRECTORY_ CMAKE_POLICY_DEFAULT_CMP CMAKE_POLICY_WARNING_CMP CMAKE_POSITION_INDEPENDENT_CODE CMAKE_PREFIX_PATH CMAKE_PROGRAM_PATH CMAKE_PROJECT__INCLUDE CMAKE_PROJECT_NAME CMAKE_RANLIB CMAKE_ROOT CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_RUNTIME_OUTPUT_DIRECTORY_ CMAKE_SCRIPT_MODE_FILE CMAKE_SHARED_LIBRARY_PREFIX CMAKE_SHARED_LIBRARY_SUFFIX CMAKE_SHARED_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS_ CMAKE_SHARED_MODULE_PREFIX CMAKE_SHARED_MODULE_SUFFIX CMAKE_SIZEOF_VOID_P CMAKE_SKIP_BUILD_RPATH CMAKE_SKIP_INSTALL_ALL_DEPENDENCY CMAKE_SKIP_INSTALL_RPATH CMAKE_SKIP_INSTALL_RULES CMAKE_SKIP_RPATH CMAKE_SOURCE_DIR CMAKE_STAGING_PREFIX CMAKE_STANDARD_LIBRARIES CMAKE_STATIC_LIBRARY_PREFIX CMAKE_STATIC_LIBRARY_SUFFIX CMAKE_STATIC_LINKER_FLAGS CMAKE_STATIC_LINKER_FLAGS_ CMAKE_SYSROOT CMAKE_SYSTEM CMAKE_SYSTEM_APPBUNDLE_PATH CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_SYSTEM_IGNORE_PATH CMAKE_SYSTEM_INCLUDE_PATH CMAKE_SYSTEM_LIBRARY_PATH CMAKE_SYSTEM_NAME CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_PROCESSOR CMAKE_SYSTEM_PROGRAM_PATH CMAKE_SYSTEM_VERSION CMAKE_TOOLCHAIN_FILE CMAKE_TRY_COMPILE_CONFIGURATION CMAKE_TWEAK_VERSION CMAKE_USER_MAKE_RULES_OVERRIDE CMAKE_USER_MAKE_RULES_OVERRIDE_ CMAKE_USE_RELATIVE_PATHS CMAKE_VERBOSE_MAKEFILE CMAKE_VERSION CMAKE_VISIBILITY_INLINES_HIDDEN CMAKE_VS_DEVENV_COMMAND CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD CMAKE_VS_INTEL_Fortran_PROJECT_VERSION CMAKE_VS_MSBUILD_COMMAND CMAKE_VS_MSDEV_COMMAND CMAKE_VS_NsightTegra_VERSION CMAKE_VS_PLATFORM_NAME CMAKE_VS_PLATFORM_TOOLSET CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION CMAKE_WARN_DEPRECATED CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_WIN32_EXECUTABLE CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS CMAKE_XCODE_ATTRIBUTE_ CMAKE_XCODE_PLATFORM_TOOLSET CPACK_ABSOLUTE_DESTINATION_FILES CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CPACK_INCLUDE_TOPLEVEL_DIRECTORY CPACK_INSTALL_SCRIPT CPACK_PACKAGING_INSTALL_PREFIX CPACK_SET_DESTDIR CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CTEST_BINARY_DIRECTORY CTEST_BUILD_COMMAND CTEST_BUILD_NAME CTEST_BZR_COMMAND CTEST_BZR_UPDATE_OPTIONS CTEST_CHANGE_ID CTEST_CHECKOUT_COMMAND CTEST_CONFIGURATION_TYPE CTEST_CONFIGURE_COMMAND CTEST_COVERAGE_COMMAND CTEST_COVERAGE_EXTRA_FLAGS CTEST_CURL_OPTIONS CTEST_CUSTOM_COVERAGE_EXCLUDE CTEST_CUSTOM_ERROR_EXCEPTION CTEST_CUSTOM_ERROR_MATCH CTEST_CUSTOM_ERROR_POST_CONTEXT CTEST_CUSTOM_ERROR_PRE_CONTEXT CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MEMCHECK_IGNORE CTEST_CUSTOM_POST_MEMCHECK CTEST_CUSTOM_POST_TEST CTEST_CUSTOM_PRE_MEMCHECK CTEST_CUSTOM_PRE_TEST CTEST_CUSTOM_TEST_IGNORE CTEST_CUSTOM_WARNING_EXCEPTION CTEST_CUSTOM_WARNING_MATCH CTEST_CVS_CHECKOUT CTEST_CVS_COMMAND CTEST_CVS_UPDATE_OPTIONS CTEST_DROP_LOCATION CTEST_DROP_METHOD CTEST_DROP_SITE CTEST_DROP_SITE_CDASH CTEST_DROP_SITE_PASSWORD CTEST_DROP_SITE_USER CTEST_EXTRA_COVERAGE_GLOB CTEST_GIT_COMMAND CTEST_GIT_UPDATE_CUSTOM CTEST_GIT_UPDATE_OPTIONS CTEST_HG_COMMAND CTEST_HG_UPDATE_OPTIONS CTEST_MEMORYCHECK_COMMAND CTEST_MEMORYCHECK_COMMAND_OPTIONS CTEST_MEMORYCHECK_SANITIZER_OPTIONS CTEST_MEMORYCHECK_SUPPRESSIONS_FILE CTEST_MEMORYCHECK_TYPE CTEST_NIGHTLY_START_TIME CTEST_P4_CLIENT CTEST_P4_COMMAND CTEST_P4_OPTIONS CTEST_P4_UPDATE_OPTIONS CTEST_SCP_COMMAND CTEST_SITE CTEST_SOURCE_DIRECTORY CTEST_SVN_COMMAND CTEST_SVN_OPTIONS CTEST_SVN_UPDATE_OPTIONS CTEST_TEST_LOAD CTEST_TEST_TIMEOUT CTEST_TRIGGER_SITE CTEST_UPDATE_COMMAND CTEST_UPDATE_OPTIONS CTEST_UPDATE_VERSION_ONLY CTEST_USE_LAUNCHERS CYGWIN ENV EXECUTABLE_OUTPUT_PATH GHS-MULTI LIBRARY_OUTPUT_PATH MINGW MSVC MSVC10 MSVC11 MSVC12 MSVC14 MSVC60 MSVC70 MSVC71 MSVC80 MSVC90 MSVC_IDE MSVC_VERSION PROJECT_BINARY_DIR PROJECT_NAME PROJECT_SOURCE_DIR PROJECT_VERSION PROJECT_VERSION_MAJOR PROJECT_VERSION_MINOR PROJECT_VERSION_PATCH PROJECT_VERSION_TWEAK UNIX WIN32 WINCE WINDOWS_PHONE WINDOWS_STORE XCODE_VERSION - \ contained +syn keyword cmakeProperty contained + \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_DEBUG ARCHIVE_OUTPUT_DIRECTORY_RELEASE ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_DEBUG ARCHIVE_OUTPUT_NAME_RELEASE ATTACHED_FILES ATTACHED_FILES_ON_FAIL AUTOGEN_TARGETS_FOLDER AUTOGEN_TARGET_DEPENDS AUTOMOC AUTOMOC_MOC_OPTIONS AUTOMOC_TARGETS_FOLDER AUTORCC AUTORCC_OPTIONS AUTOUIC AUTOUIC_OPTIONS BINARY_DIR BUILD_WITH_INSTALL_RPATH BUNDLE BUNDLE_EXTENSION CACHE_VARIABLES CLEAN_NO_CUSTOM CMAKE_CONFIGURE_DEPENDS CMAKE_CXX_KNOWN_FEATURES CMAKE_C_KNOWN_FEATURES COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN COMPATIBLE_INTERFACE_STRING COMPILE_DEFINITIONS COMPILE_DEFINITIONS_DEBUG COMPILE_DEFINITIONS_RELEASE COMPILE_FEATURES COMPILE_FLAGS COMPILE_OPTIONS COMPILE_PDB_NAME COMPILE_PDB_NAME_DEBUG COMPILE_PDB_NAME_RELEASE COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG COMPILE_PDB_OUTPUT_DIRECTORY_RELEASE COST CPACK_DESKTOP_SHORTCUTS CPACK_NEVER_OVERWRITE CPACK_PERMANENT CPACK_STARTUP_SHORTCUTS CPACK_START_MENU_SHORTCUTS CPACK_WIX_ACL CROSSCOMPILING_EMULATOR CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEBUG_CONFIGURATIONS DEBUG_POSTFIX DEFINE_SYMBOL DEFINITIONS DEPENDS DISABLED_FEATURES ECLIPSE_EXTRA_NATURES ENABLED_FEATURES ENABLED_LANGUAGES ENABLE_EXPORTS ENVIRONMENT EXCLUDE_FROM_ALL EXCLUDE_FROM_DEFAULT_BUILD EXCLUDE_FROM_DEFAULT_BUILD_DEBUG EXCLUDE_FROM_DEFAULT_BUILD_RELEASE EXPORT_NAME EXTERNAL_OBJECT EchoString FAIL_REGULAR_EXPRESSION FIND_LIBRARY_USE_LIB64_PATHS FIND_LIBRARY_USE_OPENBSD_VERSIONING FOLDER FRAMEWORK FRAMEWORK_VERSION Fortran_FORMAT Fortran_MODULE_DIRECTORY GENERATED GENERATOR_FILE_NAME GLOBAL_DEPENDS_DEBUG_MODE GLOBAL_DEPENDS_NO_CYCLES GNUtoMS HAS_CXX HEADER_FILE_ONLY HELPSTRING IMPLICIT_DEPENDS_INCLUDE_TRANSFORM IMPORTED IMPORTED_CONFIGURATIONS IMPORTED_IMPLIB IMPORTED_IMPLIB_DEBUG IMPORTED_IMPLIB_RELEASE IMPORTED_LINK_DEPENDENT_LIBRARIES IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE IMPORTED_LINK_INTERFACE_LANGUAGES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE IMPORTED_LINK_INTERFACE_LIBRARIES IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE IMPORTED_LINK_INTERFACE_MULTIPLICITY IMPORTED_LINK_INTERFACE_MULTIPLICITY_DEBUG IMPORTED_LINK_INTERFACE_MULTIPLICITY_RELEASE IMPORTED_LOCATION IMPORTED_LOCATION_DEBUG IMPORTED_LOCATION_RELEASE IMPORTED_NO_SONAME IMPORTED_NO_SONAME_DEBUG IMPORTED_NO_SONAME_RELEASE IMPORTED_SONAME IMPORTED_SONAME_DEBUG IMPORTED_SONAME_RELEASE IMPORT_PREFIX IMPORT_SUFFIX INCLUDE_DIRECTORIES INCLUDE_REGULAR_EXPRESSION INSTALL_NAME_DIR INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH INTERFACE_AUTOUIC_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SOURCES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_DEBUG INTERPROCEDURAL_OPTIMIZATION_RELEASE IN_TRY_COMPILE JOB_POOLS JOB_POOL_COMPILE JOB_POOL_LINK KEEP_EXTENSION LABELS LANGUAGE LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_DEBUG LIBRARY_OUTPUT_DIRECTORY_RELEASE LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_DEBUG LIBRARY_OUTPUT_NAME_RELEASE LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED LINK_DIRECTORIES LINK_FLAGS LINK_FLAGS_DEBUG LINK_FLAGS_RELEASE LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_LIBRARIES_RELEASE LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_DEBUG LINK_INTERFACE_MULTIPLICITY_RELEASE LINK_LIBRARIES LINK_SEARCH_END_STATIC LINK_SEARCH_START_STATIC LISTFILE_STACK LOCATION LOCATION_DEBUG LOCATION_RELEASE MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_PACKAGE_LOCATION MACOSX_RPATH MACROS MAP_IMPORTED_CONFIG_DEBUG MAP_IMPORTED_CONFIG_RELEASE MEASUREMENT MODIFIED NAME NO_SONAME NO_SYSTEM_FROM_IMPORTED OBJECT_DEPENDS OBJECT_OUTPUTS OSX_ARCHITECTURES OSX_ARCHITECTURES_DEBUG OSX_ARCHITECTURES_RELEASE OUTPUT_NAME OUTPUT_NAME_DEBUG OUTPUT_NAME_RELEASE PACKAGES_FOUND PACKAGES_NOT_FOUND PARENT_DIRECTORY PASS_REGULAR_EXPRESSION PDB_NAME PDB_NAME_DEBUG PDB_NAME_RELEASE PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_DEBUG PDB_OUTPUT_DIRECTORY_RELEASE POSITION_INDEPENDENT_CODE POST_INSTALL_SCRIPT PREDEFINED_TARGETS_FOLDER PREFIX PRE_INSTALL_SCRIPT PRIVATE_HEADER PROCESSORS PROJECT_LABEL PUBLIC_HEADER REPORT_UNDEFINED_PROPERTIES REQUIRED_FILES RESOURCE RESOURCE_LOCK RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK RULE_MESSAGES RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_DEBUG RUNTIME_OUTPUT_DIRECTORY_RELEASE RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_DEBUG RUNTIME_OUTPUT_NAME_RELEASE RUN_SERIAL SKIP_BUILD_RPATH SKIP_RETURN_CODE SOURCES SOURCE_DIR SOVERSION STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_DEBUG STATIC_LIBRARY_FLAGS_RELEASE STRINGS SUFFIX SYMBOLIC TARGET_ARCHIVES_MAY_BE_SHARED_LIBS TARGET_MESSAGES TARGET_SUPPORTS_SHARED_LIBS TEST_INCLUDE_FILE TIMEOUT TYPE USE_FOLDERS VALUE VARIABLES VERSION VISIBILITY_INLINES_HIDDEN VS_DEPLOYMENT_CONTENT VS_DEPLOYMENT_LOCATION VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER VS_SHADER_ENTRYPOINT VS_SHADER_FLAGS VS_SHADER_MODEL VS_SHADER_TYPE VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES VS_XAML_TYPE WILL_FAIL WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS WORKING_DIRECTORY WRAP_EXCLUDE XCODE_EXPLICIT_FILE_TYPE XCODE_LAST_KNOWN_FILE_TYPE XCTEST -syn keyword cmakeModule +syn keyword cmakeVariable contained + \ ANDROID APPLE BORLAND BUILD_SHARED_LIBS CMAKE_ABSOLUTE_DESTINATION_FILES CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS CMAKE_ANDROID_API CMAKE_ANDROID_API_MIN CMAKE_ANDROID_ARCH CMAKE_ANDROID_ARCH_ABI CMAKE_ANDROID_ARM_MODE CMAKE_ANDROID_ARM_NEON CMAKE_ANDROID_ASSETS_DIRECTORIES CMAKE_ANDROID_GUI CMAKE_ANDROID_JAR_DEPENDENCIES CMAKE_ANDROID_JAR_DIRECTORIES CMAKE_ANDROID_JAVA_SOURCE_DIR CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES CMAKE_ANDROID_NDK CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION CMAKE_ANDROID_PROCESS_MAX CMAKE_ANDROID_PROGUARD CMAKE_ANDROID_PROGUARD_CONFIG_PATH CMAKE_ANDROID_SECURE_PROPS_PATH CMAKE_ANDROID_SKIP_ANT_STEP CMAKE_ANDROID_STANDALONE_TOOLCHAIN CMAKE_ANDROID_STL_TYPE CMAKE_APPBUNDLE_PATH CMAKE_AR CMAKE_ARCHIVE_OUTPUT_DIRECTORY CMAKE_ARGC CMAKE_ARGV0 CMAKE_AUTOMOC CMAKE_AUTOMOC_DEPEND_FILTERS CMAKE_AUTOMOC_MOC_OPTIONS CMAKE_AUTOMOC_RELAXED_MODE CMAKE_AUTORCC CMAKE_AUTORCC_OPTIONS CMAKE_AUTOUIC CMAKE_AUTOUIC_OPTIONS CMAKE_AUTOUIC_SEARCH_PATHS CMAKE_BACKWARDS_COMPATIBILITY CMAKE_BINARY_DIR CMAKE_BUILD_RPATH CMAKE_BUILD_TOOL CMAKE_BUILD_TYPE CMAKE_BUILD_WITH_INSTALL_NAME_DIR CMAKE_BUILD_WITH_INSTALL_RPATH CMAKE_CACHEFILE_DIR CMAKE_CACHE_MAJOR_VERSION CMAKE_CACHE_MINOR_VERSION CMAKE_CACHE_PATCH_VERSION CMAKE_CFG_INTDIR CMAKE_CL_64 CMAKE_CODELITE_USE_TARGETS CMAKE_COLOR_MAKEFILE CMAKE_COMMAND CMAKE_COMPILER_2005 CMAKE_COMPILER_IS_GNUCC CMAKE_COMPILER_IS_GNUCXX CMAKE_COMPILER_IS_GNUG77 CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY CMAKE_CONFIGURATION_TYPES CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR CMAKE_CTEST_COMMAND CMAKE_CUDA_EXTENSIONS CMAKE_CUDA_STANDARD CMAKE_CUDA_STANDARD_REQUIRED CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES CMAKE_CURRENT_BINARY_DIR CMAKE_CURRENT_LIST_DIR CMAKE_CURRENT_LIST_FILE CMAKE_CURRENT_LIST_LINE CMAKE_CURRENT_SOURCE_DIR CMAKE_CXX_COMPILE_FEATURES CMAKE_CXX_EXTENSIONS CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED CMAKE_C_COMPILE_FEATURES CMAKE_C_EXTENSIONS CMAKE_C_STANDARD CMAKE_C_STANDARD_REQUIRED CMAKE_DEBUG_POSTFIX CMAKE_DEBUG_TARGET_PROPERTIES CMAKE_DEPENDS_IN_PROJECT_ONLY CMAKE_DL_LIBS CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT CMAKE_ECLIPSE_MAKE_ARGUMENTS CMAKE_ECLIPSE_VERSION CMAKE_EDIT_COMMAND CMAKE_ENABLE_EXPORTS CMAKE_ERROR_DEPRECATED CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_EXECUTABLE_SUFFIX CMAKE_EXE_LINKER_FLAGS CMAKE_EXE_LINKER_FLAGS_INIT CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_EXPORT_NO_PACKAGE_REGISTRY CMAKE_EXTRA_GENERATOR CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES CMAKE_FIND_APPBUNDLE CMAKE_FIND_FRAMEWORK CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX CMAKE_FIND_LIBRARY_PREFIXES CMAKE_FIND_LIBRARY_SUFFIXES CMAKE_FIND_NO_INSTALL_PREFIX CMAKE_FIND_PACKAGE_NAME CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_SORT_DIRECTION CMAKE_FIND_PACKAGE_SORT_ORDER CMAKE_FIND_PACKAGE_WARN_NO_MODULE CMAKE_FIND_ROOT_PATH CMAKE_FIND_ROOT_PATH_MODE_INCLUDE CMAKE_FIND_ROOT_PATH_MODE_LIBRARY CMAKE_FIND_ROOT_PATH_MODE_PACKAGE CMAKE_FIND_ROOT_PATH_MODE_PROGRAM CMAKE_FRAMEWORK_PATH CMAKE_Fortran_FORMAT CMAKE_Fortran_MODDIR_DEFAULT CMAKE_Fortran_MODDIR_FLAG CMAKE_Fortran_MODOUT_FLAG CMAKE_Fortran_MODULE_DIRECTORY CMAKE_GENERATOR CMAKE_GENERATOR_PLATFORM CMAKE_GENERATOR_TOOLSET CMAKE_GNUtoMS CMAKE_HOME_DIRECTORY CMAKE_HOST_APPLE CMAKE_HOST_SOLARIS CMAKE_HOST_SYSTEM CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_PROCESSOR CMAKE_HOST_SYSTEM_VERSION CMAKE_HOST_UNIX CMAKE_HOST_WIN32 CMAKE_IGNORE_PATH CMAKE_IMPORT_LIBRARY_PREFIX CMAKE_IMPORT_LIBRARY_SUFFIX CMAKE_INCLUDE_CURRENT_DIR CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE CMAKE_INCLUDE_DIRECTORIES_BEFORE CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE CMAKE_INCLUDE_PATH CMAKE_INSTALL_DEFAULT_COMPONENT_NAME CMAKE_INSTALL_MESSAGE CMAKE_INSTALL_NAME_DIR CMAKE_INSTALL_PREFIX CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT CMAKE_INSTALL_RPATH CMAKE_INSTALL_RPATH_USE_LINK_PATH CMAKE_INTERNAL_PLATFORM_ABI CMAKE_INTERPROCEDURAL_OPTIMIZATION CMAKE_IOS_INSTALL_COMBINED CMAKE_JOB_POOL_COMPILE CMAKE_JOB_POOL_LINK CMAKE_LIBRARY_ARCHITECTURE CMAKE_LIBRARY_ARCHITECTURE_REGEX CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_LIBRARY_PATH CMAKE_LIBRARY_PATH_FLAG CMAKE_LINK_DEF_FILE_FLAG CMAKE_LINK_DEPENDS_NO_SHARED CMAKE_LINK_INTERFACE_LIBRARIES CMAKE_LINK_LIBRARY_FILE_FLAG CMAKE_LINK_LIBRARY_FLAG CMAKE_LINK_LIBRARY_SUFFIX CMAKE_LINK_SEARCH_END_STATIC CMAKE_LINK_SEARCH_START_STATIC CMAKE_LINK_WHAT_YOU_USE CMAKE_MACOSX_BUNDLE CMAKE_MACOSX_RPATH CMAKE_MAJOR_VERSION CMAKE_MAKE_PROGRAM CMAKE_MATCH_COUNT CMAKE_MFC_FLAG CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_MINOR_VERSION CMAKE_MODULE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS_INIT CMAKE_MODULE_PATH CMAKE_NINJA_OUTPUT_PATH_PREFIX CMAKE_NOT_USING_CONFIG_FLAGS CMAKE_NO_BUILTIN_CHRPATH CMAKE_NO_SYSTEM_FROM_IMPORTED CMAKE_OBJECT_PATH_MAX CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT CMAKE_PARENT_LIST_FILE CMAKE_PATCH_VERSION CMAKE_PDB_OUTPUT_DIRECTORY CMAKE_POSITION_INDEPENDENT_CODE CMAKE_PREFIX_PATH CMAKE_PROGRAM_PATH CMAKE_PROJECT_DESCRIPTION CMAKE_PROJECT_NAME CMAKE_RANLIB CMAKE_ROOT CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_SCRIPT_MODE_FILE CMAKE_SHARED_LIBRARY_PREFIX CMAKE_SHARED_LIBRARY_SUFFIX CMAKE_SHARED_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS_INIT CMAKE_SHARED_MODULE_PREFIX CMAKE_SHARED_MODULE_SUFFIX CMAKE_SIZEOF_VOID_P CMAKE_SKIP_BUILD_RPATH CMAKE_SKIP_INSTALL_ALL_DEPENDENCY CMAKE_SKIP_INSTALL_RPATH CMAKE_SKIP_INSTALL_RULES CMAKE_SKIP_RPATH CMAKE_SOURCE_DIR CMAKE_STAGING_PREFIX CMAKE_STATIC_LIBRARY_PREFIX CMAKE_STATIC_LIBRARY_SUFFIX CMAKE_STATIC_LINKER_FLAGS CMAKE_STATIC_LINKER_FLAGS_INIT CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE CMAKE_SYSROOT CMAKE_SYSTEM CMAKE_SYSTEM_APPBUNDLE_PATH CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_SYSTEM_IGNORE_PATH CMAKE_SYSTEM_INCLUDE_PATH CMAKE_SYSTEM_LIBRARY_PATH CMAKE_SYSTEM_NAME CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_PROCESSOR CMAKE_SYSTEM_PROGRAM_PATH CMAKE_SYSTEM_VERSION CMAKE_Swift_LANGUAGE_VERSION CMAKE_TOOLCHAIN_FILE CMAKE_TRY_COMPILE_CONFIGURATION CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_TRY_COMPILE_TARGET_TYPE CMAKE_TWEAK_VERSION CMAKE_USER_MAKE_RULES_OVERRIDE CMAKE_USE_RELATIVE_PATHS CMAKE_VERBOSE_MAKEFILE CMAKE_VERSION CMAKE_VISIBILITY_INLINES_HIDDEN CMAKE_VS_DEVENV_COMMAND CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD CMAKE_VS_INTEL_Fortran_PROJECT_VERSION CMAKE_VS_MSBUILD_COMMAND CMAKE_VS_NsightTegra_VERSION CMAKE_VS_PLATFORM_NAME CMAKE_VS_PLATFORM_TOOLSET CMAKE_VS_PLATFORM_TOOLSET_CUDA CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION CMAKE_WARN_DEPRECATED CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_WIN32_EXECUTABLE CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS CMAKE_XCODE_GENERATE_SCHEME CMAKE_XCODE_PLATFORM_TOOLSET CPACK_ABSOLUTE_DESTINATION_FILES CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CPACK_INCLUDE_TOPLEVEL_DIRECTORY CPACK_INSTALL_SCRIPT CPACK_PACKAGING_INSTALL_PREFIX CPACK_SET_DESTDIR CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CTEST_BINARY_DIRECTORY CTEST_BUILD_COMMAND CTEST_BUILD_NAME CTEST_BZR_COMMAND CTEST_BZR_UPDATE_OPTIONS CTEST_CHANGE_ID CTEST_CHECKOUT_COMMAND CTEST_CONFIGURATION_TYPE CTEST_CONFIGURE_COMMAND CTEST_COVERAGE_COMMAND CTEST_COVERAGE_EXTRA_FLAGS CTEST_CURL_OPTIONS CTEST_CUSTOM_COVERAGE_EXCLUDE CTEST_CUSTOM_ERROR_EXCEPTION CTEST_CUSTOM_ERROR_MATCH CTEST_CUSTOM_ERROR_POST_CONTEXT CTEST_CUSTOM_ERROR_PRE_CONTEXT CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MEMCHECK_IGNORE CTEST_CUSTOM_POST_MEMCHECK CTEST_CUSTOM_POST_TEST CTEST_CUSTOM_PRE_MEMCHECK CTEST_CUSTOM_PRE_TEST CTEST_CUSTOM_TEST_IGNORE CTEST_CUSTOM_WARNING_EXCEPTION CTEST_CUSTOM_WARNING_MATCH CTEST_CVS_CHECKOUT CTEST_CVS_COMMAND CTEST_CVS_UPDATE_OPTIONS CTEST_DROP_LOCATION CTEST_DROP_METHOD CTEST_DROP_SITE CTEST_DROP_SITE_CDASH CTEST_DROP_SITE_PASSWORD CTEST_DROP_SITE_USER CTEST_EXTRA_COVERAGE_GLOB CTEST_GIT_COMMAND CTEST_GIT_INIT_SUBMODULES CTEST_GIT_UPDATE_CUSTOM CTEST_GIT_UPDATE_OPTIONS CTEST_HG_COMMAND CTEST_HG_UPDATE_OPTIONS CTEST_MEMORYCHECK_COMMAND CTEST_MEMORYCHECK_COMMAND_OPTIONS CTEST_MEMORYCHECK_SANITIZER_OPTIONS CTEST_MEMORYCHECK_SUPPRESSIONS_FILE CTEST_MEMORYCHECK_TYPE CTEST_NIGHTLY_START_TIME CTEST_P4_CLIENT CTEST_P4_COMMAND CTEST_P4_OPTIONS CTEST_P4_UPDATE_OPTIONS CTEST_SCP_COMMAND CTEST_SITE CTEST_SOURCE_DIRECTORY CTEST_SVN_COMMAND CTEST_SVN_OPTIONS CTEST_SVN_UPDATE_OPTIONS CTEST_TEST_LOAD CTEST_TEST_TIMEOUT CTEST_TRIGGER_SITE CTEST_UPDATE_COMMAND CTEST_UPDATE_OPTIONS CTEST_UPDATE_VERSION_ONLY CTEST_USE_LAUNCHERS CYGWIN ENV EXECUTABLE_OUTPUT_PATH GHS-MULTI LIBRARY_OUTPUT_PATH MINGW MSVC MSVC10 MSVC11 MSVC12 MSVC14 MSVC60 MSVC70 MSVC71 MSVC80 MSVC90 MSVC_IDE MSVC_VERSION PROJECT_BINARY_DIR PROJECT_DESCRIPTION PROJECT_NAME PROJECT_SOURCE_DIR PROJECT_VERSION PROJECT_VERSION_MAJOR PROJECT_VERSION_MINOR PROJECT_VERSION_PATCH PROJECT_VERSION_TWEAK UNIX WIN32 WINCE WINDOWS_PHONE WINDOWS_STORE XCODE XCODE_VERSION + +syn keyword cmakeModule contained \ ExternalProject - \ contained -syn keyword cmakeKWExternalProject - \ ALGO ALWAYS BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE BYPRODUCTS CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS COMMAND COMMENT CONFIGURE_COMMAND CVS CVSROOT CVS_ CVS_MODULE CVS_REPOSITORY CVS_TAG DEPENDEES DEPENDERS DEPENDS DIRECTORY DOWNLOAD_COMMAND DOWNLOAD_DIR DOWNLOAD_NAME DOWNLOAD_NO_PROGRESS EP_BASE EP_INDEPENDENT_STEP_TARGETS EP_PREFIX EP_STEP_TARGETS EP_UPDATE_DISCONNECTED EXCLUDE_FROM_ALL EXCLUDE_FROM_MAIN FORCE GIT_REMOTE_NAME GIT_REPOSITORY GIT_SUBMODULES GIT_TAG HG_REPOSITORY HG_TAG INDEPENDENT INDEPENDENT_STEP_TARGETS INSTALL_COMMAND INSTALL_DIR JOB_POOLS LIST_SEPARATOR LOG LOG_BUILD LOG_CONFIGURE LOG_DOWNLOAD LOG_INSTALL LOG_TEST LOG_UPDATE NO_DEPENDS PATCH_COMMAND PREFIX PROPERTY SOURCE_DIR STAMP_DIR STEP_TARGETS SVN_ SVN_PASSWORD SVN_REPOSITORY SVN_REVISION SVN_TRUST_CERT SVN_USERNAME TEST_AFTER_INSTALL TEST_BEFORE_INSTALL TEST_COMMAND TEST_EXCLUDE_FROM_MAIN TIMEOUT TLS_CAINFO TLS_VERIFY TMP_DIR UPDATE_COMMAND UPDATE_DISCONNECTED URL URL_HASH HTTP_USERNAME HTTP_PASSWORD HTTP_HEADER USES_TERMINAL USES_TERMINAL_BUILD USES_TERMINAL_CONFIGURE USES_TERMINAL_DOWNLOAD USES_TERMINAL_INSTALL USES_TERMINAL_TEST USES_TERMINAL_UPDATE WORKING_DIRECTORY _COMMAND _DIR - \ contained +syn keyword cmakeKWExternalProject contained + \ ALGO BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS COMMENT CONFIGURE_COMMAND CVSROOT CVS_MODULE CVS_REPOSITORY CVS_TAG DEPENDEES DEPENDERS DEPENDS DOWNLOADED_FILE DOWNLOAD_COMMAND DOWNLOAD_DIR DOWNLOAD_NAME DOWNLOAD_NO_EXTRACT DOWNLOAD_NO_PROGRESS EP_BASE EP_INDEPENDENT_STEP_TARGETS EP_PREFIX EP_STEP_TARGETS EP_UPDATE_DISCONNECTED EXCLUDE_FROM_ALL FORCE GIT_CONFIG GIT_PROGRESS GIT_REMOTE_NAME GIT_REPOSITORY GIT_SHALLOW GIT_SUBMODULES GIT_TAG HG_REPOSITORY HG_TAG HTTP_HEADER HTTP_PASSWORD HTTP_USERNAME INDEPENDENT_STEP_TARGETS INSTALL_COMMAND INSTALL_DIR JOB_POOLS LIST_SEPARATOR LOG_BUILD LOG_CONFIGURE LOG_DOWNLOAD LOG_INSTALL LOG_TEST LOG_UPDATE NO_DEPENDS PATCH_COMMAND PREFIX PROPERTY SOURCE_DIR SOURCE_SUBDIR STAMP_DIR STEP_TARGETS SVN_PASSWORD SVN_REPOSITORY SVN_REVISION SVN_TRUST_CERT SVN_USERNAME TEST_AFTER_INSTALL TEST_BEFORE_INSTALL TEST_COMMAND TEST_EXCLUDE_FROM_MAIN TIMEOUT TLS_CAINFO TLS_VERIFY TMP_DIR UPDATE_COMMAND UPDATE_DISCONNECTED URL URL_HASH USES_TERMINAL_BUILD USES_TERMINAL_CONFIGURE USES_TERMINAL_DOWNLOAD USES_TERMINAL_INSTALL USES_TERMINAL_TEST USES_TERMINAL_UPDATE WORKING_DIRECTORY -syn keyword cmakeKWadd_compile_options +syn keyword cmakeKWadd_compile_options contained \ COMPILE_OPTIONS - \ contained -syn keyword cmakeKWadd_custom_command - \ APPEND ARGS BYPRODUCTS COMMAND COMMENT DEPENDS GENERATE GENERATED IMPLICIT_DEPENDS MAIN_DEPENDENCY NOT OUTPUT POST_BUILD PRE_BUILD PRE_LINK SYMBOLIC TARGET TARGET_FILE USES_TERMINAL VERBATIM WORKING_DIRECTORY - \ contained +syn keyword cmakeKWadd_custom_command contained + \ APPEND ARGS BYPRODUCTS CC COMMAND COMMAND_EXPAND_LISTS COMMENT CROSSCOMPILING_EMULATOR DEPENDS DEPFILE GENERATED IMPLICIT_DEPENDS INCLUDE_DIRECTORIES JOIN MAIN_DEPENDENCY NOT OUTPUT POST_BUILD PRE_BUILD PRE_LINK SYMBOLIC TARGET_FILE TARGET_PROPERTY USES_TERMINAL VERBATIM WORKING_DIRECTORY -syn keyword cmakeKWadd_custom_target - \ ALL BYPRODUCTS COMMAND COMMENT DEPENDS GENERATE GENERATED SOURCES USES_TERMINAL VERBATIM WORKING_DIRECTORY - \ contained +syn keyword cmakeKWadd_custom_target contained + \ ALL BYPRODUCTS CC COMMAND COMMAND_EXPAND_LISTS COMMENT CROSSCOMPILING_EMULATOR DEPENDS GENERATED INCLUDE_DIRECTORIES JOIN SOURCES TARGET_PROPERTY USES_TERMINAL VERBATIM WORKING_DIRECTORY -syn keyword cmakeKWadd_definitions +syn keyword cmakeKWadd_definitions contained \ COMPILE_DEFINITIONS - \ contained -syn keyword cmakeKWadd_dependencies +syn keyword cmakeKWadd_dependencies contained \ DEPENDS OBJECT_DEPENDS - \ contained -syn keyword cmakeKWadd_executable +syn keyword cmakeKWadd_executable contained \ ALIAS CONFIG EXCLUDE_FROM_ALL GLOBAL IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ MACOSX_BUNDLE OUTPUT_NAME RUNTIME_OUTPUT_DIRECTORY TARGET - \ contained -syn keyword cmakeKWadd_library - \ ALIAS ARCHIVE_OUTPUT_DIRECTORY CLI CONFIG DLL EXCLUDE_FROM_ALL FRAMEWORK GLOBAL IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ INTERFACE INTERFACE_ LIBRARY_OUTPUT_DIRECTORY MODULE OBJECT ON OS OUTPUT_NAME POSITION_INDEPENDENT_CODE POST_BUILD PRE_BUILD PRE_LINK RUNTIME_OUTPUT_DIRECTORY SHARED STATIC TARGET TARGET_OBJECTS UNKNOWN - \ contained +syn keyword cmakeKWadd_library contained + \ ALIAS ARCHIVE_OUTPUT_DIRECTORY CLI CONFIG DLL EXCLUDE_FROM_ALL FRAMEWORK GLOBAL IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ INTERFACE_ LIBRARY_OUTPUT_DIRECTORY MODULE OBJECT ON OUTPUT_NAME POSITION_INDEPENDENT_CODE POST_BUILD PRE_BUILD PRE_LINK RUNTIME_OUTPUT_DIRECTORY SHARED STATIC TARGET_OBJECTS UNKNOWN -syn keyword cmakeKWadd_subdirectory - \ ALL EXCLUDE_FROM_ALL - \ contained +syn keyword cmakeKWadd_subdirectory contained + \ EXCLUDE_FROM_ALL -syn keyword cmakeKWadd_test - \ BUILD_TESTING COMMAND CONFIGURATION CONFIGURATIONS FAIL_REGULAR_EXPRESSION NAME ON PASS_REGULAR_EXPRESSION TARGET_FILE WILL_FAIL WORKING_DIRECTORY - \ contained +syn keyword cmakeKWadd_test contained + \ BUILD_TESTING COMMAND CONFIGURATIONS FAIL_REGULAR_EXPRESSION NAME PASS_REGULAR_EXPRESSION TARGET_FILE WILL_FAIL WORKING_DIRECTORY -syn keyword cmakeKWbuild_command - \ CONFIGURATION NEW TARGET - \ contained +syn keyword cmakeKWbuild_command contained + \ CONFIGURATION TARGET -syn keyword cmakeKWbuild_name +syn keyword cmakeKWbuild_name contained \ CMAKE_CXX_COMPILER - \ contained -syn keyword cmakeKWcmake_host_system_information +syn keyword cmakeKWcmake_host_system_information contained \ AVAILABLE_PHYSICAL_MEMORY AVAILABLE_VIRTUAL_MEMORY FQDN HOSTNAME NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES QUERY RESULT TOTAL_PHYSICAL_MEMORY TOTAL_VIRTUAL_MEMORY - \ contained -syn keyword cmakeKWcmake_minimum_required +syn keyword cmakeKWcmake_minimum_required contained \ FATAL_ERROR VERSION - \ contained -syn keyword cmakeKWcmake_parse_arguments - \ ARGN CONFIGURATIONS DESTINATION FALSE FAST FILES MY_INSTALL MY_INSTALL_CONFIGURATIONS MY_INSTALL_DESTINATION MY_INSTALL_FAST MY_INSTALL_OPTIONAL MY_INSTALL_RENAME MY_INSTALL_TARGETS MY_INSTALL_UNPARSED_ARGUMENTS OPTIONAL RENAME TARGETS TRUE _UNPARSED_ARGUMENTS - \ contained +syn keyword cmakeKWcmake_parse_arguments contained + \ ARGN CONFIGURATIONS DESTINATION FALSE FAST FILES MY_INSTALL MY_INSTALL_CONFIGURATIONS MY_INSTALL_DESTINATION MY_INSTALL_FAST MY_INSTALL_OPTIONAL MY_INSTALL_RENAME MY_INSTALL_TARGETS MY_INSTALL_UNPARSED_ARGUMENTS OPTIONAL PARSE_ARGV RENAME TARGETS TRUE _UNPARSED_ARGUMENTS -syn keyword cmakeKWcmake_policy - \ CMAKE_POLICY_DEFAULT_CMP CMP GET NEW NNNN NO_POLICY_SCOPE OLD POP PUSH SET VERSION - \ contained +syn keyword cmakeKWcmake_policy contained + \ CMAKE_POLICY_DEFAULT_CMP CMP GET NNNN NO_POLICY_SCOPE OLD POP PUSH SET VERSION -syn keyword cmakeKWconfigure_file - \ COPYONLY CRLF DOS ESCAPE_QUOTES FOO_ENABLE FOO_STRING LF NEWLINE_STYLE ON ONLY VAR - \ contained +syn keyword cmakeKWconfigure_file contained + \ COPYONLY CRLF DOS ESCAPE_QUOTES FOO_ENABLE FOO_STRING LF NEWLINE_STYLE VAR -syn keyword cmakeKWcreate_test_sourcelist +syn keyword cmakeKWcreate_test_sourcelist contained \ CMAKE_TESTDRIVER_AFTER_TESTMAIN CMAKE_TESTDRIVER_BEFORE_TESTMAIN EXTRA_INCLUDE FUNCTION - \ contained -syn keyword cmakeKWctest_build - \ ALL_BUILD APPEND BUILD CONFIGURATION CTEST_BUILD_CONFIGURATION CTEST_BUILD_FLAGS CTEST_BUILD_TARGET CTEST_PROJECT_NAME FLAGS NUMBER_ERRORS NUMBER_WARNINGS QUIET RETURN_VALUE TARGET - \ contained +syn keyword cmakeKWctest_build contained + \ ALL_BUILD APPEND BUILD CAPTURE_CMAKE_ERROR CONFIGURATION CTEST_BUILD_CONFIGURATION CTEST_BUILD_FLAGS CTEST_BUILD_TARGET CTEST_PROJECT_NAME FLAGS NUMBER_ERRORS NUMBER_WARNINGS QUIET RETURN_VALUE TARGET -syn keyword cmakeKWctest_configure - \ APPEND BUILD OPTIONS QUIET RETURN_VALUE SOURCE - \ contained +syn keyword cmakeKWctest_configure contained + \ APPEND BUILD CAPTURE_CMAKE_ERROR OPTIONS QUIET RETURN_VALUE SOURCE -syn keyword cmakeKWctest_coverage - \ APPEND BUILD LABELS QUIET RETURN_VALUE - \ contained +syn keyword cmakeKWctest_coverage contained + \ APPEND BUILD CAPTURE_CMAKE_ERROR LABELS QUIET RETURN_VALUE -syn keyword cmakeKWctest_memcheck - \ APPEND BUILD DEFECT_COUNT END EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD - \ contained +syn keyword cmakeKWctest_memcheck contained + \ APPEND BUILD DEFECT_COUNT EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD -syn keyword cmakeKWctest_run_script +syn keyword cmakeKWctest_run_script contained \ NEW_PROCESS RETURN_VALUE - \ contained -syn keyword cmakeKWctest_start +syn keyword cmakeKWctest_start contained \ APPEND QUIET TAG TRACK - \ contained -syn keyword cmakeKWctest_submit +syn keyword cmakeKWctest_submit contained \ API CDASH_UPLOAD CDASH_UPLOAD_TYPE CTEST_EXTRA_SUBMIT_FILES CTEST_NOTES_FILES FILES PARTS QUIET RETRY_COUNT RETRY_DELAY RETURN_VALUE - \ contained -syn keyword cmakeKWctest_test - \ APPEND BUILD CPU END EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD - \ contained +syn keyword cmakeKWctest_test contained + \ APPEND BUILD CAPTURE_CMAKE_ERROR CPU EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD -syn keyword cmakeKWctest_update +syn keyword cmakeKWctest_update contained \ QUIET RETURN_VALUE SOURCE - \ contained -syn keyword cmakeKWctest_upload - \ FILES QUIET - \ contained +syn keyword cmakeKWctest_upload contained + \ CAPTURE_CMAKE_ERROR FILES QUIET -syn keyword cmakeKWdefine_property +syn keyword cmakeKWdefine_property contained \ BRIEF_DOCS CACHED_VARIABLE DIRECTORY FULL_DOCS GLOBAL INHERITED PROPERTY SOURCE TARGET TEST VARIABLE - \ contained -syn keyword cmakeKWenable_language +syn keyword cmakeKWenable_language contained \ OPTIONAL - \ contained -syn keyword cmakeKWexec_program +syn keyword cmakeKWexec_program contained \ ARGS OUTPUT_VARIABLE RETURN_VALUE - \ contained -syn keyword cmakeKWexecute_process - \ COMMAND ERROR_ ERROR_FILE ERROR_QUIET ERROR_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE INPUT_ INPUT_FILE OUTPUT_ OUTPUT_FILE OUTPUT_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE RESULT_VARIABLE TIMEOUT VERBATIM WORKING_DIRECTORY - \ contained +syn keyword cmakeKWexecute_process contained + \ ANSI AUTO COMMAND ENCODING ERROR_FILE ERROR_QUIET ERROR_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE INPUT_FILE NONE OEM OUTPUT_FILE OUTPUT_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE RESULT_VARIABLE TIMEOUT UTF VERBATIM WORKING_DIRECTORY -syn keyword cmakeKWexport - \ APPEND CONFIG EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE IMPORTED IMPORTED_ LINK_INTERFACE_LIBRARIES NAMESPACE NEW PACKAGE TARGETS - \ contained +syn keyword cmakeKWexport contained + \ ANDROID_MK APPEND CONFIG EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE IMPORTED IMPORTED_ NAMESPACE NDK OLD PACKAGE TARGETS -syn keyword cmakeKWexport_library_dependencies +syn keyword cmakeKWexport_library_dependencies contained \ APPEND EXPORT INCLUDE LINK_INTERFACE_LIBRARIES SET - \ contained -syn keyword cmakeKWfile - \ ALGO APPEND ASCII CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY CONDITION CONFIG CONTENT COPY CR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DOWNLOAD ENCODING EXCLUDE EXPECTED_HASH FILE FILES_MATCHING FILE_PERMISSIONS FOLLOW_SYMLINKS FUNCTION GENERATE GLOB GLOB_RECURSE GUARD HEX INACTIVITY_TIMEOUT INPUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NEW NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS OFF OFFSET OLD ON OUTPUT PATH PATTERN PERMISSIONS PROCESS READ REGEX RELATIVE RELATIVE_PATH RELEASE REMOVE REMOVE_RECURSE RENAME RESULT_VARIABLE SHOW_PROGRESS SORT SSL STATUS STRINGS TIMEOUT TIMESTAMP TLS TLS_CAINFO TLS_VERIFY TO_CMAKE_PATH TO_NATIVE_PATH UPLOAD USE_SOURCE_PERMISSIONS UTC UTF WRITE - \ contained +syn keyword cmakeKWfile contained + \ ALGO APPEND ASCII CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY CONDITION CONFIG CONTENT COPY CR DESTINATION DIRECTORY_PERMISSIONS DOWNLOAD ENCODING EXCLUDE EXPECTED_HASH FILES_MATCHING FILE_PERMISSIONS FOLLOW_SYMLINKS FUNCTION GENERATE GLOB GLOB_RECURSE GUARD HASH HEX HTTPHEADER INACTIVITY_TIMEOUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS OFFSET OLD PATTERN PROCESS READ REGEX RELATIVE RELATIVE_PATH RELEASE REMOVE REMOVE_RECURSE RENAME RESULT_VARIABLE SHOW_PROGRESS SORT SSL STATUS STRINGS TIMESTAMP TLS_CAINFO TLS_VERIFY TO_CMAKE_PATH TO_NATIVE_PATH UPLOAD USERPWD USE_SOURCE_PERMISSIONS UTC UTF WRITE -syn keyword cmakeKWfind_file - \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR - \ contained +syn keyword cmakeKWfind_file contained + \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR -syn keyword cmakeKWfind_library - \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS LIB NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR - \ contained +syn keyword cmakeKWfind_library contained + \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS LIB NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR -syn keyword cmakeKWfind_package - \ CMAKE_DISABLE_FIND_PACKAGE_ CMAKE_FIND_ROOT_PATH_BOTH COMPONENTS CONFIG CONFIGS DVAR EXACT HINTS MODULE NAMES NO_CMAKE_BUILDS_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_PATH NO_CMAKE_SYSTEM_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_MODULE NO_POLICY_SCOPE NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OPTIONAL_COMPONENTS OS PACKAGE_FIND_NAME PACKAGE_FIND_VERSION PACKAGE_FIND_VERSION_COUNT PACKAGE_FIND_VERSION_MAJOR PACKAGE_FIND_VERSION_MINOR PACKAGE_FIND_VERSION_PATCH PACKAGE_FIND_VERSION_TWEAK PACKAGE_VERSION PACKAGE_VERSION_COMPATIBLE PACKAGE_VERSION_EXACT PACKAGE_VERSION_UNSUITABLE PATH PATHS PATH_SUFFIXES QUIET REQUIRED TRUE _CONFIG _CONSIDERED_CONFIGS _CONSIDERED_VERSIONS _DIR _FIND_COMPONENTS _FIND_QUIETLY _FIND_REQUIRED _FIND_REQUIRED_ _FIND_VERSION _FIND_VERSION_COUNT _FIND_VERSION_EXACT _FIND_VERSION_MAJOR _FIND_VERSION_MINOR _FIND_VERSION_PATCH _FIND_VERSION_TWEAK _FOUND _VERSION _VERSION_COUNT _VERSION_MAJOR _VERSION_MINOR _VERSION_PATCH _VERSION_TWEAK - \ contained +syn keyword cmakeKWfind_package contained + \ CMAKE_DISABLE_FIND_PACKAGE_ CMAKE_FIND_ROOT_PATH_BOTH COMPONENTS CONFIG CONFIGS DEC DVAR EXACT HINTS MODULE NAMES NATURAL NO_CMAKE_BUILDS_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_PATH NO_CMAKE_SYSTEM_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_MODULE NO_POLICY_SCOPE NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OPTIONAL_COMPONENTS OS PACKAGE_FIND_NAME PACKAGE_FIND_VERSION PACKAGE_FIND_VERSION_COUNT PACKAGE_FIND_VERSION_MAJOR PACKAGE_FIND_VERSION_MINOR PACKAGE_FIND_VERSION_PATCH PACKAGE_FIND_VERSION_TWEAK PACKAGE_VERSION PACKAGE_VERSION_COMPATIBLE PACKAGE_VERSION_EXACT PACKAGE_VERSION_UNSUITABLE PATHS PATH_SUFFIXES QUIET REQUIRED SET TRUE _CONFIG _CONSIDERED_CONFIGS _CONSIDERED_VERSIONS _DIR _FIND_COMPONENTS _FIND_QUIETLY _FIND_REQUIRED _FIND_REQUIRED_ _FIND_VERSION_EXACT _FOUND -syn keyword cmakeKWfind_path - \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR - \ contained +syn keyword cmakeKWfind_path contained + \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR -syn keyword cmakeKWfind_program - \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR - \ contained +syn keyword cmakeKWfind_program contained + \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR -syn keyword cmakeKWfltk_wrap_ui +syn keyword cmakeKWfltk_wrap_ui contained \ FLTK - \ contained -syn keyword cmakeKWforeach +syn keyword cmakeKWforeach contained \ ARGS IN ITEMS LISTS RANGE - \ contained -syn keyword cmakeKWfunction +syn keyword cmakeKWfunction contained \ ARGC ARGN ARGS ARGV PARENT_SCOPE - \ contained -syn keyword cmakeKWget_cmake_property - \ VAR - \ contained +syn keyword cmakeKWget_cmake_property contained + \ COMPONENTS GLOBAL MACROS VAR VARIABLES -syn keyword cmakeKWget_directory_property +syn keyword cmakeKWget_directory_property contained \ DEFINITION DIRECTORY - \ contained -syn keyword cmakeKWget_filename_component +syn keyword cmakeKWget_filename_component contained \ ABSOLUTE ARG_VAR BASE_DIR CACHE COMP DIRECTORY EXT NAME NAME_WE PATH PROGRAM PROGRAM_ARGS REALPATH VAR - \ contained -syn keyword cmakeKWget_property +syn keyword cmakeKWget_property contained \ BRIEF_DOCS CACHE DEFINED DIRECTORY FULL_DOCS GLOBAL INSTALL PROPERTY SET SOURCE TARGET TEST VARIABLE - \ contained -syn keyword cmakeKWget_source_file_property +syn keyword cmakeKWget_source_file_property contained \ LOCATION VAR - \ contained -syn keyword cmakeKWget_target_property +syn keyword cmakeKWget_target_property contained \ VAR - \ contained -syn keyword cmakeKWget_test_property +syn keyword cmakeKWget_test_property contained \ VAR - \ contained -syn keyword cmakeKWif - \ AND ARGS CMP COMMAND DEFINED EQUAL EXISTS FALSE GREATER IGNORE IN_LIST IS_ABSOLUTE IS_DIRECTORY IS_NEWER_THAN IS_SYMLINK LESS MATCHES NNNN NO NOT OFF ON OR POLICY STREQUAL STRGREATER STRLESS TARGET TEST THEN TRUE VERSION_EQUAL VERSION_GREATER VERSION_LESS YES - \ contained +syn keyword cmakeKWif contained + \ ARGS CMAKE_MATCH_ CMP COMMAND DEFINED EQUAL EXISTS FALSE GREATER GREATER_EQUAL IGNORE IN_LIST IS_ABSOLUTE IS_DIRECTORY IS_NEWER_THAN IS_SYMLINK LESS LESS_EQUAL MATCHES NNNN NOT OFF OR POLICY STREQUAL STRGREATER STRGREATER_EQUAL STRLESS STRLESS_EQUAL TARGET TEST THEN TRUE VERSION_EQUAL VERSION_GREATER VERSION_GREATER_EQUAL VERSION_LESS VERSION_LESS_EQUAL YES -syn keyword cmakeKWinclude - \ NO_POLICY_SCOPE OPTIONAL RESULT_VARIABLE VAR - \ contained +syn keyword cmakeKWinclude contained + \ NO_POLICY_SCOPE OPTIONAL RESULT_VARIABLE -syn keyword cmakeKWinclude_directories +syn keyword cmakeKWinclude_directories contained \ AFTER BEFORE INCLUDE_DIRECTORIES ON SYSTEM - \ contained -syn keyword cmakeKWinclude_external_msproject - \ GUID PLATFORM TYPE WIX - \ contained +syn keyword cmakeKWinclude_external_msproject contained + \ GUID MAP_IMPORTED_CONFIG_ PLATFORM TYPE WIX -syn keyword cmakeKWinstall - \ ARCHIVE BUNDLE CODE COMPONENT CONFIG CONFIGURATIONS CVS DESTDIR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DLL EXCLUDE EXCLUDE_FROM_ALL EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE FILES FILES_MATCHING FILE_PERMISSIONS FRAMEWORK GROUP_EXECUTE GROUP_READ GROUP_WRITE IMPORTED_ INCLUDES INSTALL_PREFIX INTERFACE_INCLUDE_DIRECTORIES LIBRARY LINK_INTERFACE_LIBRARIES MACOSX_BUNDLE MESSAGE MESSAGE_NEVER NAMELINK_ONLY NAMELINK_SKIP NAMESPACE NEW OPTIONAL OS OWNER_EXECUTE OWNER_READ OWNER_WRITE PATTERN PERMISSIONS POST_INSTALL_SCRIPT PRE_INSTALL_SCRIPT PRIVATE_HEADER PROGRAMS PUBLIC_HEADER REGEX RENAME RESOURCE RUNTIME SCRIPT SETGID SETUID SOVERSION TARGETS TRUE USE_SOURCE_PERMISSIONS VERSION WORLD_EXECUTE WORLD_READ WORLD_WRITE - \ contained +syn keyword cmakeKWinstall contained + \ ARCHIVE BUNDLE CODE COMPONENT CONFIGURATIONS CVS DESTDIR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DLL EXCLUDE_FROM_ALL EXPORT EXPORT_ANDROID_MK EXPORT_LINK_INTERFACE_LIBRARIES FILES FILES_MATCHING FILE_PERMISSIONS FRAMEWORK GROUP_EXECUTE GROUP_READ GROUP_WRITE IMPORTED_ INCLUDES INSTALL_PREFIX INTERFACE_INCLUDE_DIRECTORIES LIBRARY MACOSX_BUNDLE MESSAGE_NEVER NAMELINK_ONLY NAMELINK_SKIP NAMESPACE NDK OBJECTS OPTIONAL OWNER_EXECUTE OWNER_READ OWNER_WRITE PATTERN PERMISSIONS POST_INSTALL_SCRIPT PRE_INSTALL_SCRIPT PRIVATE_HEADER PROGRAMS PUBLIC_HEADER REGEX RENAME RESOURCE RUNTIME SCRIPT SETGID SETUID SOVERSION TARGETS TRUE USE_SOURCE_PERMISSIONS VERSION WORLD_EXECUTE WORLD_READ WORLD_WRITE -syn keyword cmakeKWinstall_files +syn keyword cmakeKWinstall_files contained \ FILES GLOB - \ contained -syn keyword cmakeKWinstall_programs +syn keyword cmakeKWinstall_programs contained \ FILES GLOB PROGRAMS TARGETS - \ contained -syn keyword cmakeKWinstall_targets +syn keyword cmakeKWinstall_targets contained \ DLL RUNTIME_DIRECTORY TARGETS - \ contained -syn keyword cmakeKWlist - \ APPEND CACHE FIND GET INSERT INTERNAL LENGTH LIST NOTES PARENT_SCOPE REMOVE_AT REMOVE_DUPLICATES REMOVE_ITEM REVERSE SORT - \ contained +syn keyword cmakeKWlist contained + \ APPEND CACHE EXCLUDE FILTER FIND GET INCLUDE INSERT INTERNAL LENGTH LIST NOTES PARENT_SCOPE REGEX REMOVE_AT REMOVE_DUPLICATES REMOVE_ITEM REVERSE SORT -syn keyword cmakeKWload_cache +syn keyword cmakeKWload_cache contained \ EXCLUDE INCLUDE_INTERNALS READ_WITH_PREFIX - \ contained -syn keyword cmakeKWload_command +syn keyword cmakeKWload_command contained \ CMAKE_LOADED_COMMAND_ COMMAND_NAME - \ contained -syn keyword cmakeKWmacro - \ ARGC ARGN ARGS ARGV DEFINED GREATER IN LISTS NOT _BAR _FOO - \ contained +syn keyword cmakeKWmacro contained + \ ARGC ARGN ARGS ARGV DEFINED GREATER LISTS NOT _BAR _FOO -syn keyword cmakeKWmake_directory +syn keyword cmakeKWmake_directory contained \ MAKE_DIRECTORY - \ contained -syn keyword cmakeKWmark_as_advanced +syn keyword cmakeKWmark_as_advanced contained \ CLEAR FORCE VAR - \ contained -syn keyword cmakeKWmath +syn keyword cmakeKWmath contained \ EXPR - \ contained -syn keyword cmakeKWmessage +syn keyword cmakeKWmessage contained \ AUTHOR_WARNING DEPRECATION FATAL_ERROR GUI SEND_ERROR STATUS WARNING - \ contained -syn keyword cmakeKWoption +syn keyword cmakeKWoption contained \ OFF ON - \ contained -syn keyword cmakeKWproject - \ CMAKE_PROJECT_ LANGUAGES NAME NEW NONE PROJECT VERSION _BINARY_DIR _INCLUDE _SOURCE_DIR _VERSION _VERSION_MAJOR _VERSION_MINOR _VERSION_PATCH _VERSION_TWEAK - \ contained +syn keyword cmakeKWproject contained + \ CMAKE_PROJECT_ DESCRIPTION LANGUAGES NAME NONE PROJECT VERSION _BINARY_DIR _INCLUDE _SOURCE_DIR _VERSION _VERSION_MAJOR _VERSION_MINOR _VERSION_PATCH _VERSION_TWEAK -syn keyword cmakeKWremove +syn keyword cmakeKWremove contained \ REMOVE_ITEM VALUE VAR - \ contained -syn keyword cmakeKWseparate_arguments - \ MSDN UNIX_COMMAND VARIABLE WINDOWS WINDOWS_COMMAND _COMMAND - \ contained +syn keyword cmakeKWseparate_arguments contained + \ MSDN NATIVE NATIVE_COMMAND UNIX_COMMAND WINDOWS WINDOWS_COMMAND _COMMAND -syn keyword cmakeKWset - \ BOOL CACHE FILEPATH FORCE INTERNAL OFF ON PARENT_SCOPE PATH STRING STRINGS - \ contained +syn keyword cmakeKWset contained + \ BOOL CACHE FILEPATH FORCE INTERNAL OFF ON PARENT_SCOPE STRING STRINGS -syn keyword cmakeKWset_directory_properties +syn keyword cmakeKWset_directory_properties contained \ PROPERTIES - \ contained -syn keyword cmakeKWset_property +syn keyword cmakeKWset_property contained \ APPEND APPEND_STRING CACHE DIRECTORY GLOBAL INSTALL PROPERTY SOURCE TARGET TEST WIX - \ contained -syn keyword cmakeKWset_source_files_properties +syn keyword cmakeKWset_source_files_properties contained \ PROPERTIES - \ contained -syn keyword cmakeKWset_target_properties +syn keyword cmakeKWset_target_properties contained \ PROPERTIES - \ contained -syn keyword cmakeKWset_tests_properties +syn keyword cmakeKWset_tests_properties contained \ PROPERTIES - \ contained -syn keyword cmakeKWsource_group - \ FILES REGULAR_EXPRESSION - \ contained +syn keyword cmakeKWsource_group contained + \ FILES PREFIX REGULAR_EXPRESSION TREE -syn keyword cmakeKWstring - \ ALPHABET APPEND ASCII CMAKE_MATCH_ COMPARE CONCAT CONFIGURE EQUAL ESCAPE_QUOTES FIND GENEX_STRIP GREATER GUID LENGTH LESS MAKE_C_IDENTIFIER MATCH MATCHALL MATCHES NAME NAMESPACE NOTEQUAL ONLY RANDOM RANDOM_SEED REGEX REPLACE REVERSE STRIP SUBSTRING SZ TIMESTAMP TOLOWER TOUPPER TYPE UPPER UTC UUID - \ contained +syn keyword cmakeKWstring contained + \ ALPHABET APPEND ASCII CMAKE_MATCH_ COMPARE CONCAT CONFIGURE EQUAL ESCAPE_QUOTES FIND GENEX_STRIP GREATER GREATER_EQUAL GUID HASH LENGTH LESS LESS_EQUAL MAKE_C_IDENTIFIER MATCH MATCHALL MATCHES NAMESPACE NOTEQUAL ONLY RANDOM RANDOM_SEED REGEX REPLACE REVERSE RFC SHA SOURCE_DATE_EPOCH STRIP SUBSTRING SZ TIMESTAMP TOLOWER TOUPPER TYPE US UTC UUID -syn keyword cmakeKWsubdirs +syn keyword cmakeKWsubdirs contained \ EXCLUDE_FROM_ALL PREORDER - \ contained -syn keyword cmakeKWtarget_compile_definitions +syn keyword cmakeKWtarget_compile_definitions contained \ COMPILE_DEFINITIONS INTERFACE INTERFACE_COMPILE_DEFINITIONS PRIVATE PUBLIC - \ contained -syn keyword cmakeKWtarget_compile_features +syn keyword cmakeKWtarget_compile_features contained \ COMPILE_FEATURES IMPORTED INTERFACE INTERFACE_COMPILE_FEATURES PRIVATE PUBLIC - \ contained -syn keyword cmakeKWtarget_compile_options +syn keyword cmakeKWtarget_compile_options contained \ BEFORE COMPILE_OPTIONS IMPORTED INTERFACE INTERFACE_COMPILE_OPTIONS PRIVATE PUBLIC - \ contained -syn keyword cmakeKWtarget_include_directories +syn keyword cmakeKWtarget_include_directories contained \ BEFORE BUILD_INTERFACE IMPORTED INCLUDE_DIRECTORIES INSTALL_INTERFACE INTERFACE INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES PRIVATE PUBLIC SYSTEM - \ contained -syn keyword cmakeKWtarget_link_libraries - \ ALIAS DAG DEBUG_CONFIGURATIONS IMPORTED IMPORTED_NO_SONAME INTERFACE INTERFACE_LINK_LIBRARIES LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_MULTIPLICITY LINK_PRIVATE LINK_PUBLIC NEW OLD OSX PRIVATE PUBLIC SONAME STATIC - \ contained +syn keyword cmakeKWtarget_link_libraries contained + \ ALIAS DAG DEBUG_CONFIGURATIONS IMPORTED IMPORTED_NO_SONAME INTERFACE INTERFACE_LINK_LIBRARIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_MULTIPLICITY LINK_PRIVATE LINK_PUBLIC OLD OSX PRIVATE PUBLIC STATIC -syn keyword cmakeKWtarget_sources +syn keyword cmakeKWtarget_sources contained \ IMPORTED INTERFACE INTERFACE_SOURCES PRIVATE PUBLIC SOURCES - \ contained -syn keyword cmakeKWtry_compile - \ ALL_BUILD CMAKE_FLAGS COMPILE_DEFINITIONS COPY_FILE COPY_FILE_ERROR DEFINED DLINK_LIBRARIES DVAR FALSE INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES NEW NOT OUTPUT_VARIABLE RESULT_VAR SOURCES TRUE TYPE VALUE - \ contained +syn keyword cmakeKWtry_compile contained + \ ALL_BUILD CMAKE_FLAGS COMPILE_DEFINITIONS COPY_FILE COPY_FILE_ERROR CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEFINED DLINK_LIBRARIES DVAR FALSE INCLUDE_DIRECTORIES LANG LINK_DIRECTORIES LINK_LIBRARIES NOT OUTPUT_VARIABLE RESULT_VAR SOURCES TRUE TYPE VALUE _EXTENSIONS _STANDARD _STANDARD_REQUIRED -syn keyword cmakeKWtry_run - \ ARGS CMAKE_FLAGS COMPILE_DEFINITIONS COMPILE_OUTPUT_VARIABLE COMPILE_RESULT_VAR DLINK_LIBRARIES DVAR FAILED_TO_RUN FALSE INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES OUTPUT_VARIABLE RUN_OUTPUT_VARIABLE RUN_RESULT_VAR TRUE TYPE VALUE __TRYRUN_OUTPUT - \ contained +syn keyword cmakeKWtry_run contained + \ ARGS CMAKE_FLAGS COMPILE_DEFINITIONS COMPILE_OUTPUT_VARIABLE COMPILE_RESULT_VAR DLINK_LIBRARIES DVAR FAILED_TO_RUN FALSE INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES RUN_OUTPUT_VARIABLE RUN_RESULT_VAR TRUE TYPE VALUE __TRYRUN_OUTPUT -syn keyword cmakeKWunset +syn keyword cmakeKWunset contained \ CACHE LD_LIBRARY_PATH PARENT_SCOPE - \ contained -syn keyword cmakeKWuse_mangled_mesa +syn keyword cmakeKWuse_mangled_mesa contained \ GL OUTPUT_DIRECTORY PATH_TO_MESA - \ contained -syn keyword cmakeKWvariable_requires +syn keyword cmakeKWvariable_requires contained \ RESULT_VARIABLE TEST_VARIABLE - \ contained -syn keyword cmakeKWvariable_watch +syn keyword cmakeKWvariable_watch contained \ COMMAND - \ contained -syn keyword cmakeKWwhile +syn keyword cmakeKWwhile contained \ ARGS - \ contained -syn keyword cmakeKWwrite_file +syn keyword cmakeKWwrite_file contained \ APPEND CONFIGURE_FILE NOTE WRITE - \ contained -syn keyword cmakeGeneratorExpressions - \ LINK_LIBRARIES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS CONFIG DEBUG_MODE DEBUG_MODE BOOL AND OR NOT STREQUAL STREQUAL EQUAL EQUAL CONFIG MAP_IMPORTED_CONFIG_ CONFIG IMPORTED PLATFORM_ID C_COMPILER_ID CXX_COMPILER_ID VERSION_GREATER VERSION_LESS VERSION_EQUAL C_COMPILER_VERSION CXX_COMPILER_VERSION TARGET_POLICY NEW COMPILE_FEATURES C_STANDARD CXX_STANDARD COMPILE_LANGUAGE PRIVATE COMPILE_LANGUAGE PUBLIC PRIVATE COMPILE_LANGUAGE COMPILING_CXX PRIVATE COMPILE_LANGUAGE CXX_COMPILER_ID GNU VERSION_LESS CXX_COMPILER_VERSION OLD_COMPILER OLD_COMPILER CMAKE_CXX_COMPILER_VERSION CONFIGURATION CONFIG CONFIG PLATFORM_ID C_COMPILER_ID CMAKE_ LANG _COMPILER_ID CXX_COMPILER_ID CMAKE_ LANG _COMPILER_ID C_COMPILER_VERSION CMAKE_ LANG _COMPILER_VERSION CXX_COMPILER_VERSION CMAKE_ LANG _COMPILER_VERSION TARGET_FILE TARGET_FILE_NAME TARGET_FILE_DIR TARGET_LINKER_FILE TARGET_LINKER_FILE_NAME TARGET_LINKER_FILE_DIR TARGET_SONAME_FILE TARGET_SONAME_FILE_NAME TARGET_SONAME_FILE_DIR TARGET_PDB_FILE PDB_NAME PDB_OUTPUT_DIRECTORY PDB_NAME_ CONFIG PDB_OUTPUT_DIRECTORY_ CONFIG TARGET_PDB_FILE_NAME TARGET_PDB_FILE_DIR TARGET_PROPERTY TARGET_PROPERTY INSTALL_PREFIX EXPORT COMPILE_LANGUAGE JOIN TARGET_PROPERTY INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES BOOL JOIN TARGET_PROPERTY INCLUDE_DIRECTORIES JOIN ANGLE COMMA SEMICOLON TARGET_NAME LINK_ONLY INTERFACE_LINK_LIBRARIES INSTALL_INTERFACE EXPORT BUILD_INTERFACE LOWER_CASE UPPER_CASE MAKE_C_IDENTIFIER TARGET_OBJECTS OBJECT_LIBRARY SHELL_PATH MSYS - \ contained +syn keyword cmakeGeneratorExpressions contained + \ LINK_LIBRARIES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS CONFIG DEBUG_MODE BOOL AND NOT IF STREQUAL MAP_IMPORTED_CONFIG_ PLATFORM_ID C_COMPILER_ID CXX_COMPILER_ID VERSION_LESS VERSION_GREATER VERSION_EQUAL VERSION_LESS_EQUAL VERSION_GREATER_EQUAL C_COMPILER_VERSION CXX_COMPILER_VERSION TARGET_POLICY COMPILE_FEATURES C_STANDARD CXX_STANDARD COMPILE_LANGUAGE PRIVATE PUBLIC COMPILING_CXX GNU OLD_COMPILER CMAKE_CXX_COMPILER_VERSION CONFIGURATION TARGET_FILE TARGET_FILE_NAME TARGET_FILE_DIR TARGET_LINKER_FILE TARGET_LINKER_FILE_NAME TARGET_LINKER_FILE_DIR TARGET_SONAME_FILE TARGET_SONAME_FILE_NAME TARGET_SONAME_FILE_DIR TARGET_PDB_FILE PDB_NAME PDB_OUTPUT_DIRECTORY PDB_NAME_ PDB_OUTPUT_DIRECTORY_ TARGET_PDB_FILE_NAME TARGET_PDB_FILE_DIR TARGET_BUNDLE_DIR TARGET_BUNDLE_CONTENT_DIR SDK TARGET_PROPERTY INSTALL_PREFIX EXPORT JOIN ANGLE COMMA SEMICOLON TARGET_NAME LINK_ONLY INTERFACE_LINK_LIBRARIES INSTALL_INTERFACE BUILD_INTERFACE LOWER_CASE UPPER_CASE MAKE_C_IDENTIFIER TARGET_OBJECTS OBJECT_LIBRARY SHELL_PATH MSYS syn case ignore + syn keyword cmakeCommand \ add_compile_options add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_host_system_information cmake_minimum_required cmake_parse_arguments cmake_policy configure_file continue create_test_sourcelist ctest_build ctest_configure ctest_coverage ctest_empty_binary_directory ctest_memcheck ctest_read_custom_files ctest_run_script ctest_sleep ctest_start ctest_submit ctest_test ctest_update ctest_upload define_property enable_language enable_testing endfunction endmacro execute_process export file find_file find_library find_package find_path find_program fltk_wrap_ui function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property include include_directories include_external_msproject include_regular_expression install link_directories list load_cache load_command macro mark_as_advanced math message option project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_compile_definitions target_compile_features target_compile_options target_include_directories target_link_libraries target_sources try_compile try_run unset variable_watch \ nextgroup=cmakeArguments + syn keyword cmakeCommandConditional \ else elseif endif if \ nextgroup=cmakeArguments + syn keyword cmakeCommandRepeat \ endforeach endwhile foreach while \ nextgroup=cmakeArguments + syn keyword cmakeCommandDeprecated \ build_name exec_program export_library_dependencies install_files install_programs install_targets link_libraries make_directory output_required_files remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file \ nextgroup=cmakeArguments + syn case match syn keyword cmakeTodo @@ -447,15 +356,15 @@ hi def link cmakeComment Comment hi def link cmakeEnvironment Special hi def link cmakeEscaped Special hi def link cmakeGeneratorExpression WarningMsg -hi def link cmakeGeneratorExpressions ModeMsg +hi def link cmakeGeneratorExpressions Constant hi def link cmakeLuaComment Comment hi def link cmakeModule Include hi def link cmakeProperty Constant hi def link cmakeRegistry Underlined hi def link cmakeString String hi def link cmakeTodo TODO -hi def link cmakeVariable Identifier hi def link cmakeVariableValue Type +hi def link cmakeVariable Identifier hi def link cmakeKWExternalProject ModeMsg hi def link cmakeKWadd_compile_options ModeMsg diff --git a/CMakeLists.txt b/CMakeLists.txt index bec81a38c..ed924eb4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,14 +55,22 @@ if(NOT DEFINED CMAKE_C_STANDARD AND NOT CMake_NO_C_STANDARD) endif() endif() if(NOT DEFINED CMAKE_CXX_STANDARD AND NOT CMake_NO_CXX_STANDARD) - include(${CMake_SOURCE_DIR}/Source/Checks/cm_cxx14_cstdio.cmake) - if(NOT CMake_CXX14_CSTDIO_BROKEN) - set(CMAKE_CXX_STANDARD 14) + if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.14) + set(CMAKE_CXX_STANDARD 98) else() - set(CMAKE_CXX_STANDARD 11) + include(${CMake_SOURCE_DIR}/Source/Checks/cm_cxx14_cstdio.cmake) + if(NOT CMake_CXX14_CSTDIO_BROKEN) + set(CMAKE_CXX_STANDARD 14) + else() + set(CMAKE_CXX_STANDARD 11) + endif() endif() endif() if(NOT CMake_TEST_EXTERNAL_CMAKE) + # include special compile flags for some compilers + include(CompileFlags.cmake) + + # check for available C++ features include(${CMake_SOURCE_DIR}/Source/Checks/cm_cxx_features.cmake) endif() @@ -226,6 +234,31 @@ option(CMAKE_USE_FOLDERS "Enable folder grouping of projects in IDEs." ON) mark_as_advanced(CMAKE_USE_FOLDERS) +option(CMake_RUN_CLANG_TIDY "Run clang-tidy with the compiler." OFF) +if(CMake_RUN_CLANG_TIDY) + if(CMake_SOURCE_DIR STREQUAL CMake_BINARY_DIR) + message(FATAL_ERROR "CMake_RUN_CLANG_TIDY requires an out-of-source build!") + endif() + find_program(CLANG_TIDY_COMMAND NAMES clang-tidy) + if(NOT CLANG_TIDY_COMMAND) + message(FATAL_ERROR "CMake_RUN_CLANG_TIDY is ON but clang-tidy is not found!") + endif() + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}") +endif() +configure_file(.clang-tidy .clang-tidy COPYONLY) + + +option(CMake_RUN_IWYU "Run include-what-you-use with the compiler." OFF) +if(CMake_RUN_IWYU) + find_program(IWYU_COMMAND NAMES include-what-you-use iwyu) + if(NOT IWYU_COMMAND) + message(FATAL_ERROR "CMake_RUN_IWYU is ON but include-what-you-use is not found!") + endif() + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE + "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp") +endif() + + #----------------------------------------------------------------------- # a macro that only sets the FOLDER target property if it's # "appropriate" @@ -421,14 +454,15 @@ macro (CMAKE_BUILD_UTILITIES) if(NOT LIBLZMA_FOUND) message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!") endif() - set(LZMA_INCLUDE_DIR ${LIBLZMA_INCLUDE_DIRS}) - set(LZMA_LIBRARY ${LIBLZMA_LIBRARIES}) else() add_subdirectory(Utilities/cmliblzma) CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty") - set(LZMA_INCLUDE_DIR + set(LIBLZMA_HAS_AUTO_DECODER 1) + set(LIBLZMA_HAS_EASY_ENCODER 1) + set(LIBLZMA_HAS_LZMA_PRESET 1) + set(LIBLZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api") - set(LZMA_LIBRARY cmliblzma) + set(LIBLZMA_LIBRARY cmliblzma) endif() endif() @@ -449,13 +483,14 @@ macro (CMAKE_BUILD_UTILITIES) add_definitions(-DLIBARCHIVE_STATIC) set(ENABLE_NETTLE OFF CACHE INTERNAL "Enable use of Nettle") set(ENABLE_OPENSSL ${CMAKE_USE_OPENSSL} CACHE INTERNAL "Enable use of OpenSSL") - set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system found LZMA library if found") - set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system found ZLIB library if found") - set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system found BZip2 library if found") - set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system found libxml2 library if found") - set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system found EXPAT library if found") - set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system found PCREPOSIX library if found") - set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system found LibGCC library if found") + set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system LZMA library if found") + set(ENABLE_LZO OFF CACHE INTERNAL "Enable the use of the system LZO library if found") + set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system ZLIB library if found") + set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system BZip2 library if found") + set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system libxml2 library if found") + set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system EXPAT library if found") + set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system PCREPOSIX library if found") + set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system LibGCC library if found") set(ENABLE_XATTR OFF CACHE INTERNAL "Enable extended attribute support") set(ENABLE_ACL OFF CACHE INTERNAL "Enable ACL support") set(ENABLE_ICONV OFF CACHE INTERNAL "Enable iconv support") @@ -501,18 +536,9 @@ int main(void) { return 0; } if(NOT HAVE_CoreServices_OS_X_10_5) set(CMAKE_USE_LIBUV 0) endif() - elseif(CYGWIN) - # libuv does not support Cygwin - set(CMAKE_USE_LIBUV 0) elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX") # Disable until it can be ported. set(CMAKE_USE_LIBUV 0) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "sparc") - # Disable until it can be ported. - set(CMAKE_USE_LIBUV 0) - elseif(CMAKE_SYSTEM STREQUAL "SunOS-5.10") - # Disable until it can be ported. - set(CMAKE_USE_LIBUV 0) endif() endif() if(CMAKE_USE_LIBUV) @@ -627,9 +653,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) include(${CMake_SOURCE_DIR}/Tests/CMakeInstall.cmake) endif() - # include special compile flags for some compilers - include(CompileFlags.cmake) - # no clue why we are testing for this here include(CheckSymbolExists) CHECK_SYMBOL_EXISTS(unsetenv "stdlib.h" HAVE_UNSETENV) @@ -810,6 +833,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) PATTERN "*.sh*" PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + REGEX "Help/dev($|/)" EXCLUDE ) # Install auxiliary files integrating with other tools. diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 921ba7c9b..e2197632a 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,6 +1,11 @@ Contributing to CMake ********************* +The following summarizes the process for contributing changes. +See documentation on `CMake Development`_ for more information. + +.. _`CMake Development`: Help/dev/README.rst + Community ========= @@ -19,25 +24,20 @@ CMake uses `Kitware's GitLab Instance`_ to manage development and code review. To contribute patches: #. Fork the upstream `CMake Repository`_ into a personal account. +#. Run `Utilities/SetupForDevelopment.sh`_ for local configuration. +#. See the `CMake Source Code Guide`_ for coding guidelines. #. Base all new work on the upstream ``master`` branch. #. Create commits making incremental, distinct, logically complete changes. #. Push a topic branch to a personal repository fork on GitLab. #. Create a GitLab Merge Request targeting the upstream ``master`` branch. +The merge request will enter the `CMake Review Process`_ for consideration. + .. _`Kitware's GitLab Instance`: https://gitlab.kitware.com .. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake - -Code Style -========== - -We use `clang-format`_ to define our style for C++ code in the CMake source -tree. See the `.clang-format`_ configuration file for our style settings. -Use ``clang-format`` version 3.8 or higher to format source files. -See also the `Utilities/Scripts/clang-format.bash`_ script. - -.. _`clang-format`: http://clang.llvm.org/docs/ClangFormat.html -.. _`.clang-format`: .clang-format -.. _`Utilities/Scripts/clang-format.bash`: Utilities/Scripts/clang-format.bash +.. _`Utilities/SetupForDevelopment.sh`: Utilities/SetupForDevelopment.sh +.. _`CMake Source Code Guide`: Help/dev/source.rst +.. _`CMake Review Process`: Help/dev/review.rst License ======= diff --git a/CompileFlags.cmake b/CompileFlags.cmake index c875e6f1f..7a9d4cdf3 100644 --- a/CompileFlags.cmake +++ b/CompileFlags.cmake @@ -4,10 +4,6 @@ #----------------------------------------------------------------------------- # set some special flags for different compilers # -if(CMAKE_GENERATOR MATCHES "Visual Studio 7") - set(CMAKE_SKIP_COMPATIBILITY_TESTS 1) -endif() - if(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "Intel") set(_INTEL_WINDOWS 1) endif() @@ -63,9 +59,17 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^parisc") endif() endif() -if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro) +if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND + NOT DEFINED CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03") + if (NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD EQUAL 98) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03") + elseif(CMAKE_VERSION VERSION_LESS 3.8.20170502) + # CMake knows how to add this flag for compilation as C++11, + # but has not been taught that SunPro needs it for linking too. + # Add it in a place that will be used for both. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -library=stlport4") endif() diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index bd4d2959d..8a0fc8d74 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -16,8 +16,9 @@ The general signature is: [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] [NO_DEFAULT_PATH] - [NO_CMAKE_ENVIRONMENT_PATH] + [NO_PACKAGE_ROOT_PATH] [NO_CMAKE_PATH] + [NO_CMAKE_ENVIRONMENT_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_SYSTEM_PATH] [CMAKE_FIND_ROOT_PATH_BOTH | @@ -60,6 +61,10 @@ If ``NO_DEFAULT_PATH`` is specified, then no additional paths are added to the search. If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: +.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| replace:: + |prefix_XXX_SUBDIR| for each ```` in ``PackageName_ROOT`` if called + from within a find module + .. |CMAKE_PREFIX_PATH_XXX_SUBDIR| replace:: |prefix_XXX_SUBDIR| for each ```` in :variable:`CMAKE_PREFIX_PATH` @@ -71,33 +76,47 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: |prefix_XXX_SUBDIR| for each ```` in :variable:`CMAKE_SYSTEM_PREFIX_PATH` -1. Search paths specified in cmake-specific cache variables. +1. If called from within a find module, search prefix paths unique to the + current package being found. Specifically look in the ``PackageName_ROOT`` + CMake and environment variables. The package root variables are maintained + as a stack so if called from nested find modules, root paths from the + parent's find module will be searchd after paths from the current module, + i.e. ``CurrentPackage_ROOT``, ``ENV{CurrentPackage_ROOT}``, + ``ParentPackage_ROOT``, ``ENV{ParentPacakge_ROOT}``, etc. + This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed. + + * |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| + +2. Search paths specified in cmake-specific cache variables. These are intended to be used on the command line with a ``-DVAR=value``. + The values are interpreted as :ref:`;-lists `. This can be skipped if ``NO_CMAKE_PATH`` is passed. * |CMAKE_PREFIX_PATH_XXX| * |CMAKE_XXX_PATH| * |CMAKE_XXX_MAC_PATH| -2. Search paths specified in cmake-specific environment variables. - These are intended to be set in the user's shell configuration. +3. Search paths specified in cmake-specific environment variables. + These are intended to be set in the user's shell configuration, + and therefore use the host's native path separator + (``;`` on Windows and ``:`` on UNIX). This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed. * |CMAKE_PREFIX_PATH_XXX| * |CMAKE_XXX_PATH| * |CMAKE_XXX_MAC_PATH| -3. Search the paths specified by the ``HINTS`` option. +4. Search the paths specified by the ``HINTS`` option. These should be paths computed by system introspection, such as a hint provided by the location of another item already found. Hard-coded guesses should be specified with the ``PATHS`` option. -4. Search the standard system environment variables. +5. Search the standard system environment variables. This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is an argument. * |SYSTEM_ENVIRONMENT_PATH_XXX| -5. Search cmake variables defined in the Platform files +6. Search cmake variables defined in the Platform files for the current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is passed. @@ -105,7 +124,7 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: * |CMAKE_SYSTEM_XXX_PATH| * |CMAKE_SYSTEM_XXX_MAC_PATH| -6. Search the paths specified by the PATHS option +7. Search the paths specified by the PATHS option or in the short-hand version of the command. These are typically hard-coded guesses. diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 80e7edfa8..d03840633 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -215,7 +215,7 @@ of the following is specified: ``PRE_BUILD`` Run before any other rules are executed within the target. - This is supported only on Visual Studio 7 or later. + This is supported only on Visual Studio 8 or later. For all other generators ``PRE_BUILD`` will be treated as ``PRE_LINK``. ``PRE_LINK`` diff --git a/Help/command/add_executable.rst b/Help/command/add_executable.rst index 19ca658bd..c088796e4 100644 --- a/Help/command/add_executable.rst +++ b/Help/command/add_executable.rst @@ -40,6 +40,9 @@ 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 :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 +within IDE. -------------------------------------------------------------------------- diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst index af75a3970..de5335eff 100644 --- a/Help/command/add_library.rst +++ b/Help/command/add_library.rst @@ -59,12 +59,16 @@ 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 :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 +within IDE. + Imported Libraries ^^^^^^^^^^^^^^^^^^ :: - add_library( IMPORTED + add_library( IMPORTED [GLOBAL]) An :ref:`IMPORTED library target ` references a library @@ -106,10 +110,9 @@ may contain only sources that compile, header files, and other files that would not affect linking of a normal library (e.g. ``.txt``). They may contain custom commands generating such sources, but not ``PRE_BUILD``, ``PRE_LINK``, or ``POST_BUILD`` commands. Object libraries -cannot be imported, exported, installed, or linked. Some native build -systems may not like targets that have only object files, so consider -adding at least one real source file to any target that references -``$``. +cannot be linked. Some native build systems may not like targets that +have only object files, so consider adding at least one real source file +to any target that references ``$``. Alias Libraries ^^^^^^^^^^^^^^^ @@ -120,7 +123,7 @@ Alias Libraries Creates an :ref:`Alias Target `, such that ```` can be used to refer to ```` in subsequent commands. The ```` does -not appear in the generatedbuildsystem as a make target. The ```` +not appear in the generated buildsystem as a make target. The ```` may not be an :ref:`Imported Target ` or an ``ALIAS``. ``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/ctest_memcheck.rst b/Help/command/ctest_memcheck.rst index a983d6823..288b65a25 100644 --- a/Help/command/ctest_memcheck.rst +++ b/Help/command/ctest_memcheck.rst @@ -13,6 +13,9 @@ Perform the :ref:`CTest MemCheck Step` as a :ref:`Dashboard Client`. [INCLUDE ] [EXCLUDE_LABEL ] [INCLUDE_LABEL ] + [EXCLUDE_FIXTURE ] + [EXCLUDE_FIXTURE_SETUP ] + [EXCLUDE_FIXTURE_CLEANUP ] [PARALLEL_LEVEL ] [TEST_LOAD ] [SCHEDULE_RANDOM ] diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst index a7d970818..6b49da392 100644 --- a/Help/command/ctest_submit.rst +++ b/Help/command/ctest_submit.rst @@ -6,6 +6,7 @@ Perform the :ref:`CTest Submit Step` as a :ref:`Dashboard Client`. :: ctest_submit([PARTS ...] [FILES ...] + [HTTPHEADER
] [RETRY_COUNT ] [RETRY_DELAY ] [RETURN_VALUE ] @@ -36,6 +37,10 @@ The options are: Specify an explicit list of specific files to be submitted. Each individual file must exist at the time of the call. +``HTTPHEADER `` + Specify HTTP header to be included in the request to CDash during submission. + This suboption can be repeated several times. + ``RETRY_COUNT `` Specify how many times to retry a timed-out submission. @@ -57,6 +62,7 @@ Submit to CDash Upload API :: ctest_submit(CDASH_UPLOAD [CDASH_UPLOAD_TYPE ] + [HTTPHEADER
] [RETRY_COUNT ] [RETRY_DELAY ] [QUIET]) @@ -67,5 +73,5 @@ 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 ``RETRY_COUNT``, ``RETRY_DELAY``, and ``QUIET`` -options as described above. +This signature accepts the ``HTTPHEADER``, ``RETRY_COUNT``, ``RETRY_DELAY``, and +``QUIET`` options as described above. diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index ce50d4297..4a69491d5 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -13,6 +13,9 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`. [INCLUDE ] [EXCLUDE_LABEL ] [INCLUDE_LABEL ] + [EXCLUDE_FIXTURE ] + [EXCLUDE_FIXTURE_SETUP ] + [EXCLUDE_FIXTURE_CLEANUP ] [PARALLEL_LEVEL ] [TEST_LOAD ] [SCHEDULE_RANDOM ] @@ -61,6 +64,20 @@ The options are: Specify a regular expression matching test labels to include. Tests not matching this expression are excluded. +``EXCLUDE_FIXTURE `` + 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 + fixtures matching the ````. Note that all other fixture behavior is + retained, including test dependencies and skipping tests that have fixture + setup tests that fail. + +``EXCLUDE_FIXTURE_SETUP `` + Same as ``EXCLUDE_FIXTURE`` except only matching setup tests are excluded. + +``EXCLUDE_FIXTURE_CLEANUP `` + Same as ``EXCLUDE_FIXTURE`` except only matching cleanup tests are excluded. + ``PARALLEL_LEVEL `` Specify a positive number representing the number of tests to be run in parallel. diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst index e56097bea..2a14ad72f 100644 --- a/Help/command/find_file.rst +++ b/Help/command/find_file.rst @@ -8,6 +8,9 @@ find_file .. |prefix_XXX_SUBDIR| replace:: ``/include`` .. |entry_XXX_SUBDIR| replace:: ``/include`` +.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: + ``/include/`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` + is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| .. |CMAKE_PREFIX_PATH_XXX| replace:: ``/include/`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR| diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst index 1eb50f77e..0861d6789 100644 --- a/Help/command/find_library.rst +++ b/Help/command/find_library.rst @@ -8,6 +8,9 @@ find_library .. |prefix_XXX_SUBDIR| replace:: ``/lib`` .. |entry_XXX_SUBDIR| replace:: ``/lib`` +.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: + ``/lib/`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, + and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| .. |CMAKE_PREFIX_PATH_XXX| replace:: ``/lib/`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR| @@ -49,6 +52,14 @@ path to the framework ``/A.framework``. When a full path to a framework is used as a library, CMake will use a ``-framework A``, and a ``-F`` to link the framework to the target. +If the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable is set all +search paths will be tested as normal, with the suffix appended, and with +all matches of ``lib/`` replaced with +``lib${CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX}/``. This variable overrides +the :prop_gbl:`FIND_LIBRARY_USE_LIB32_PATHS`, +:prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS`, +and :prop_gbl:`FIND_LIBRARY_USE_LIB64_PATHS` global properties. + If the :prop_gbl:`FIND_LIBRARY_USE_LIB32_PATHS` global property is set all search paths will be tested as normal, with ``32/`` appended, and with all matches of ``lib/`` replaced with ``lib32/``. This property is @@ -56,6 +67,13 @@ automatically set for the platforms that are known to need it if at least one of the languages supported by the :command:`project` command is enabled. +If the :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS` global property is set +all search paths will be tested as normal, with ``x32/`` appended, and +with all matches of ``lib/`` replaced with ``libx32/``. This property is +automatically set for the platforms that are known to need it if at +least one of the languages supported by the :command:`project` command +is enabled. + If the :prop_gbl:`FIND_LIBRARY_USE_LIB64_PATHS` global property is set all search paths will be tested as normal, with ``64/`` appended, and with all matches of ``lib/`` replaced with ``lib64/``. This property is diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 2cb1e5ffb..08c6ccdef 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -64,8 +64,9 @@ The complete Config mode command signature is:: [PATHS path1 [path2 ... ]] [PATH_SUFFIXES suffix1 [suffix2 ...]] [NO_DEFAULT_PATH] - [NO_CMAKE_ENVIRONMENT_PATH] + [NO_PACAKGE_ROOT_PATH] [NO_CMAKE_PATH] + [NO_CMAKE_ENVIRONMENT_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_PACKAGE_REGISTRY] [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing. @@ -249,16 +250,25 @@ 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 cmake-specific cache variables. These +1. Search paths specified in the ``PackageName_ROOT`` CMake and environment + variables. 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. + +2. Search paths specified in cmake-specific cache variables. These are intended to be used on the command line with a ``-DVAR=value``. + The values are interpreted as :ref:`;-lists `. This can be skipped if ``NO_CMAKE_PATH`` is passed:: CMAKE_PREFIX_PATH CMAKE_FRAMEWORK_PATH CMAKE_APPBUNDLE_PATH -2. Search paths specified in cmake-specific environment variables. - These are intended to be set in the user's shell configuration. +3. Search paths specified in cmake-specific environment variables. + These are intended to be set in the user's shell configuration, + and therefore use the host's native path separator + (``;`` on Windows and ``:`` on UNIX). This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed:: _DIR @@ -266,26 +276,26 @@ enabled. CMAKE_FRAMEWORK_PATH CMAKE_APPBUNDLE_PATH -3. Search paths specified by the ``HINTS`` option. These should be paths +4. Search paths specified by the ``HINTS`` option. These should be paths computed by system introspection, such as a hint provided by the location of another item already found. Hard-coded guesses should be specified with the ``PATHS`` option. -4. Search the standard system environment variables. This can be +5. Search the standard system environment variables. This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed. Path entries ending in ``/bin`` or ``/sbin`` are automatically converted to their parent directories:: PATH -5. Search paths stored in the CMake :ref:`User Package Registry`. +6. Search paths stored in the CMake :ref:`User Package Registry`. This can be skipped if ``NO_CMAKE_PACKAGE_REGISTRY`` is passed or by setting the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` to ``TRUE``. See the :manual:`cmake-packages(7)` manual for details on the user package registry. -6. Search cmake variables defined in the Platform files for the +7. Search cmake variables defined in the Platform files for the current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is passed:: @@ -293,14 +303,14 @@ enabled. CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_SYSTEM_APPBUNDLE_PATH -7. Search paths stored in the CMake :ref:`System Package Registry`. +8. Search paths stored in the CMake :ref:`System Package Registry`. This can be skipped if ``NO_CMAKE_SYSTEM_PACKAGE_REGISTRY`` is passed or by setting the :variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` to ``TRUE``. See the :manual:`cmake-packages(7)` manual for details on the system package registry. -8. Search paths specified by the ``PATHS`` option. These are typically +9. Search paths specified by the ``PATHS`` option. These are typically hard-coded guesses. .. |FIND_XXX| replace:: find_package diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst index 76342d020..988a3fae4 100644 --- a/Help/command/find_path.rst +++ b/Help/command/find_path.rst @@ -8,6 +8,9 @@ find_path .. |prefix_XXX_SUBDIR| replace:: ``/include`` .. |entry_XXX_SUBDIR| replace:: ``/include`` +.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: + ``/include/`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` + is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| .. |CMAKE_PREFIX_PATH_XXX| replace:: ``/include/`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR| diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst index d3430c054..4f00773b3 100644 --- a/Help/command/find_program.rst +++ b/Help/command/find_program.rst @@ -8,6 +8,8 @@ find_program .. |prefix_XXX_SUBDIR| replace:: ``/[s]bin`` .. |entry_XXX_SUBDIR| replace:: ``/[s]bin`` +.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace:: + |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| .. |CMAKE_PREFIX_PATH_XXX| replace:: |CMAKE_PREFIX_PATH_XXX_SUBDIR| .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_PROGRAM_PATH` diff --git a/Help/command/if.rst b/Help/command/if.rst index 2a087d0ac..edd343de2 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -103,7 +103,8 @@ Possible expressions are: ``if( MATCHES regex)`` True if the given string or variable's value matches the given regular - expression. + expression. See :ref:`Regex Specification` for regex format. + ``()`` groups are captured in :variable:`CMAKE_MATCH_` variables. ``if( LESS )`` True if the given string or variable's value is a valid number and less diff --git a/Help/command/include_external_msproject.rst b/Help/command/include_external_msproject.rst index 18a2b5080..335282a30 100644 --- a/Help/command/include_external_msproject.rst +++ b/Help/command/include_external_msproject.rst @@ -20,3 +20,7 @@ command to make things depend on the external project. 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_` +target property to specify the mapping. diff --git a/Help/command/install.rst b/Help/command/install.rst index 70087a42b..58438b763 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -73,7 +73,7 @@ Installing Targets :: install(TARGETS targets... [EXPORT ] - [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE| + [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE| PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE] [DESTINATION ] [PERMISSIONS permissions...] @@ -86,10 +86,10 @@ Installing Targets ) The ``TARGETS`` form specifies rules for installing targets from a -project. There are five kinds of target files that may be installed: -``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``FRAMEWORK``, and ``BUNDLE``. -Executables are treated as ``RUNTIME`` targets, except that those -marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE`` +project. There are six kinds of target files that may be installed: +``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, ``FRAMEWORK``, and +``BUNDLE``. Executables are treated as ``RUNTIME`` targets, except that +those marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE`` targets on OS X. Static libraries are treated as ``ARCHIVE`` targets, except that those marked with the ``FRAMEWORK`` property are treated as ``FRAMEWORK`` targets on OS X. @@ -99,10 +99,11 @@ targets, except that those marked with the ``FRAMEWORK`` property are treated as ``FRAMEWORK`` targets on OS X. For DLL platforms the DLL part of a shared library is treated as a ``RUNTIME`` target and the corresponding import library is treated as an ``ARCHIVE`` target. -All Windows-based systems including Cygwin are DLL platforms. -The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, and ``FRAMEWORK`` arguments -change the type of target to which the subsequent properties apply. -If none is given the installation properties apply to all target +All Windows-based systems including Cygwin are DLL platforms. Object +libraries are always treated as ``OBJECTS`` targets. +The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, and ``FRAMEWORK`` +arguments change the type of target to which the subsequent properties +apply. If none is given the installation properties apply to all target types. If only one is given then only targets of that type will be installed (which can be used to install just a DLL or just an import library). @@ -165,8 +166,8 @@ the ``mySharedLib`` DLL will be installed to ``/bin`` and The ``EXPORT`` option associates the installed target files with an export called ````. It must appear before any ``RUNTIME``, -``LIBRARY``, or ``ARCHIVE`` options. To actually install the export -file itself, call ``install(EXPORT)``, documented below. +``LIBRARY``, ``ARCHIVE``, or ``OBJECTS`` options. To actually install the +export file itself, call ``install(EXPORT)``, documented below. Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property set to ``TRUE`` has undefined behavior. diff --git a/Help/command/project.rst b/Help/command/project.rst index 6c5ace7f1..139f69c9b 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -8,6 +8,7 @@ Set a name, version, and enable languages for the entire project. project( [LANGUAGES] [...]) project( [VERSION [.[.[.]]]] + [DESCRIPTION ] [LANGUAGES ...]) Sets the name of the project and stores the name in the @@ -40,6 +41,10 @@ in variables Variables corresponding to unspecified versions are set to the empty string (if policy :policy:`CMP0048` is set to ``NEW``). +If optional ``DESCRIPTION`` is given, then additional :variable:`PROJECT_DESCRIPTION` +variable will be set to its argument. The argument must be a string with short +description of the project (only a few words). + Optionally you can specify which languages your project supports. Example languages are ``C``, ``CXX`` (i.e. C++), ``Fortran``, etc. By default ``C`` and ``CXX`` are enabled if no language options are diff --git a/Help/command/separate_arguments.rst b/Help/command/separate_arguments.rst index 1fd3cd19a..47982a503 100644 --- a/Help/command/separate_arguments.rst +++ b/Help/command/separate_arguments.rst @@ -5,9 +5,9 @@ Parse space-separated arguments into a semicolon-separated list. :: - separate_arguments( _COMMAND "") + separate_arguments( _COMMAND "") -Parses a unix- or windows-style command-line string "" and +Parses a UNIX- or Windows-style command-line string "" and stores a semicolon-separated list of the arguments in ````. The entire command line must be given in one "" argument. @@ -16,12 +16,15 @@ recognizes both single-quote and double-quote pairs. A backslash escapes the next literal character (``\"`` is ``"``); there are no special escapes (``\n`` is just ``n``). -The ``WINDOWS_COMMAND`` mode parses a windows command-line using the same +The ``WINDOWS_COMMAND`` mode parses a Windows command-line using the same syntax the runtime library uses to construct argv at startup. It separates arguments by whitespace that is not double-quoted. Backslashes are literal unless they precede double-quotes. See the MSDN article `Parsing C Command-Line Arguments`_ for details. +The ``NATIVE_COMMAND`` mode parses a Windows command-line if the host +system is Windows, and a UNIX command-line otherwise. + .. _`Parsing C Command-Line Arguments`: https://msdn.microsoft.com/library/a1y7w461.aspx :: diff --git a/Help/command/string.rst b/Help/command/string.rst index 698a91dca..4f0c45c29 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -77,31 +77,43 @@ The replace expression may refer to paren-delimited subexpressions of the match using ``\1``, ``\2``, ..., ``\9``. Note that two backslashes (``\\1``) are required in CMake code to get a backslash through argument parsing. +.. _`Regex Specification`: + Regex Specification """"""""""""""""""" The following characters have special meaning in regular expressions: -:: - - ^ Matches at beginning of input - $ Matches at end of input - . Matches any single character - [ ] Matches any character(s) inside the brackets - [^ ] Matches any character(s) not inside the brackets - - Inside brackets, specifies an inclusive range between - characters on either side e.g. [a-f] is [abcdef] - To match a literal - using brackets, make it the first - or the last character e.g. [+*/-] matches basic - mathematical operators. - * Matches preceding pattern zero or more times - + Matches preceding pattern one or more times - ? Matches preceding pattern zero or once only - | 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. if( MATCHES ), in the variables CMAKE_MATCH_(0..9). +``^`` + Matches at beginning of input +``$`` + Matches at end of input +``.`` + Matches any single character +``[ ]`` + Matches any character(s) inside the brackets +``[^ ]`` + Matches any character(s) not inside the brackets +``-`` + Inside brackets, specifies an inclusive range between + characters on either side e.g. ``[a-f]`` is ``[abcdef]`` + To match a literal ``-`` using brackets, make it the first + or the last character e.g. ``[+*/-]`` matches basic + mathematical operators. +``*`` + Matches preceding pattern zero or more times +``+`` + Matches preceding pattern one or more times +``?`` + Matches preceding pattern zero or once only +``|`` + 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_` for ```` 0..9. ``*``, ``+`` and ``?`` have higher precedence than concatenation. ``|`` has lower precedence than concatenation. This means that the regular diff --git a/Help/dev/README.rst b/Help/dev/README.rst new file mode 100644 index 000000000..ce62abc4b --- /dev/null +++ b/Help/dev/README.rst @@ -0,0 +1,49 @@ +CMake Development +***************** + +This directory contains documentation about development of CMake itself. +It is not part of the user documentation distributed with CMake. + +Contributor Instructions +======================== + +See `CONTRIBUTING.rst`_ for instructions to contribute changes. + +The process for contributing changes is the same whether or not one +has been invited to participate directly in upstream development. + +.. _`CONTRIBUTING.rst`: ../../CONTRIBUTING.rst + +Upstream Development +==================== + +CMake uses `Kitware's GitLab Instance`_ to manage development, review, and +integration of changes. The `CMake Repository`_ holds the integration +branches and tags. Upstream development processes are covered by the +following documents: + +* The `CMake Review Process`_ manages integration of changes. +* The `CMake Testing Process`_ drives integration testing. + +.. _`Kitware's GitLab Instance`: https://gitlab.kitware.com +.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake +.. _`CMake Review Process`: review.rst +.. _`CMake Testing Process`: testing.rst + +Developer Documentation +======================= + +CMake developer documentation is provided by the following documents: + +* The `CMake Source Code Guide`_. + +.. _`CMake Source Code Guide`: source.rst + +Maintainer Documentation +======================== + +CMake maintainer documentation is provided by the following documents: + +* The `CMake Maintainer Guide`_. + +.. _`CMake Maintainer Guide`: maint.rst diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst new file mode 100644 index 000000000..78c06df65 --- /dev/null +++ b/Help/dev/maint.rst @@ -0,0 +1,171 @@ +CMake Maintainer Guide +********************** + +The following is a guide to CMake maintenance processes. +See documentation on `CMake Development`_ for more information. + +.. _`CMake Development`: README.rst + +.. contents:: Maintainer Processes: + +Branch a New Release +==================== + +This section covers how to start a new ``release`` branch for a major or +minor version bump (patch releases remain on their existing branch). + +In the following we use the placeholder ``$ver`` to represent the +version number of the new release with the form ``$major.$minor``, +and ``$prev`` to represent the version number of the prior release. + +Review Prior Release +-------------------- + +Review the history around the prior release branch: + +.. code-block:: shell + + git log --graph --boundary \ + ^$(git rev-list --grep="Merge topic 'doc-.*-relnotes'" -n 1 master)~1 \ + $(git rev-list --grep="Begin post-.* development" -n 1 master) \ + $(git tag --list *-rc1| tail -1) + +Consolidate Release Notes +------------------------- + +Starting from a clean work tree on ``master``, create a topic branch to +use for consolidating the release notes: + +.. code-block:: shell + + git checkout -b doc-$ver-relnotes + +Run the `consolidate-relnotes.bash`_ script: + +.. code-block:: shell + + Utilities/Release/consolidate-relnotes.bash $ver $prev + +.. _`consolidate-relnotes.bash`: ../../Utilities/Release/consolidate-relnotes.bash + +This moves notes from the ``Help/release/dev/*.rst`` files into a versioned +``Help/release/$ver.rst`` file and updates ``Help/release/index.rst`` to +link to the new document. Commit the changes with a message such as:: + + Help: Consolidate $ver release notes + + Run the `Utilities/Release/consolidate-relnotes.bash` script to move + notes from `Help/release/dev/*` into `Help/release/$ver.rst`. + +Manually edit ``Help/release/$ver.rst`` to add section headers, organize +the notes, and revise wording. Then commit with a message such as:: + + Help: Organize and revise $ver release notes + + Add section headers similar to the $prev release notes and move each + individual bullet into an appropriate section. Revise a few bullets. + +Open a merge request with the ``doc-$ver-relnotes`` branch for review +and integration. Further steps may proceed after this has been merged +to ``master``. + +Update 'release' Branch +----------------------- + +Starting from a clean work tree on ``master``, create a new ``release-$ver`` +branch locally: + +.. code-block:: shell + + git checkout -b release-$ver origin/master + +Remove the development branch release note infrastructure: + +.. code-block:: shell + + git rm Help/release/dev/0-sample-topic.rst + sed -i '/^\.\. include:: dev.txt/ {N;d}' Help/release/index.rst + +Commit with a message such as:: + + Help: Drop development topic notes to prepare release + + Release versions do not have the development topic section of + the CMake Release Notes index page. + +Update ``Source/CMakeVersion.cmake`` to set the version to +``$major.$minor.0-rc1``: + +.. code-block:: cmake + + # CMake version number components. + set(CMake_VERSION_MAJOR $major) + set(CMake_VERSION_MINOR $minor) + set(CMake_VERSION_PATCH 0) + set(CMake_VERSION_RC 1) + +Update ``Utilities/Release/upload_release.cmake``: + +.. code-block:: cmake + + set(VERSION $ver) + +Update uses of ``DEVEL_CMAKE_VERSION`` in the source tree to mention the +actual version number: + +.. code-block:: shell + + $EDITOR $(git grep -l DEVEL_CMAKE_VERSION) + +Commit with a message such as:: + + CMake $major.$minor.0-rc1 version update + +Merge the ``release-$ver`` branch to ``master``: + +.. code-block:: shell + + git checkout master + git pull + git merge --no-ff release-$ver + +Begin post-release development by restoring the development branch release +note infrastructure and the version date from ``origin/master``: + +.. code-block:: shell + + git checkout origin/master -- \ + Source/CMakeVersion.cmake Help/release/dev/0-sample-topic.rst + sed -i $'/^Releases/ i\\\n.. include:: dev.txt\\\n' Help/release/index.rst + +Update ``Source/CMakeVersion.cmake`` to set the version to +``$major.$minor.$date``: + +.. code-block:: cmake + + # CMake version number components. + set(CMake_VERSION_MAJOR $major) + set(CMake_VERSION_MINOR $minor) + set(CMake_VERSION_PATCH $date) + #set(CMake_VERSION_RC 1) + +Commit with a message such as:: + + Begin post-$ver development + +Push the update to the ``master`` and ``release`` branches: + +.. code-block:: shell + + git push --atomic origin master release-$ver:release + +Announce 'release' Branch +------------------------- + +Send email to the ``cmake-developers@cmake.org`` mailing list (perhaps +in reply to a release preparation thread) announcing that post-release +development is open:: + + I've branched 'release' for $ver. The repository is now open for + post-$ver development. Please rebase open merge requests on 'master' + before staging or merging. diff --git a/Help/dev/review.rst b/Help/dev/review.rst new file mode 100644 index 000000000..9450bf081 --- /dev/null +++ b/Help/dev/review.rst @@ -0,0 +1,350 @@ +CMake Review Process +******************** + +The following documents the process for reviewing and integrating changes. +See `CONTRIBUTING.rst`_ for instructions to contribute changes. +See documentation on `CMake Development`_ for more information. + +.. _`CONTRIBUTING.rst`: ../../CONTRIBUTING.rst +.. _`CMake Development`: README.rst + +.. contents:: The review process consists of the following steps: + +Merge Request +============= + +A user initiates the review process for a change by pushing a *topic +branch* to his or her own fork of the `CMake Repository`_ on GitLab and +creating a *merge request* ("MR"). The new MR will appear on the +`CMake Merge Requests Page`_. The rest of the review and integration +process is managed by the merge request page for the change. + +During the review process, the MR submitter should address review comments +or test failures by updating the MR with a (force-)push of the topic +branch. The update initiates a new round of review. + +We recommend that users enable the "Remove source branch when merge +request is accepted" option when creating the MR or by editing it. +This will cause the MR topic branch to be automatically removed from +the user's fork during the `Merge`_ step. + +.. _`CMake Merge Requests Page`: https://gitlab.kitware.com/cmake/cmake/merge_requests +.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake + +Workflow Status +--------------- + +`CMake GitLab Project Developers`_ may set one of the following labels +in GitLab to track the state of a MR: + +* ``workflow:wip`` indicates that the MR needs additional updates from + the MR submitter before further review. Use this label after making + comments that require such updates. + +* ``workflow:in-review`` indicates that the MR awaits feedback from a + human reviewer or from `Topic Testing`_. Use this label after making + comments requesting such feedback. + +* ``workflow:nightly-testing`` indicates that the MR awaits results + of `Integration Testing`_. Use this label after making comments + requesting such staging. + +* ``workflow:expired`` indicates that the MR has been closed due + to a period of inactivity. See the `Expire`_ step. Use this label + after closing a MR for this reason. + +The workflow status labels are intended to be mutually exclusive, +so please remove any existing workflow label when adding one. + +.. _`CMake GitLab Project Developers`: https://gitlab.kitware.com/cmake/cmake/settings/members + +Robot Review +============ + +The "Kitware Robot" (``@kwrobot``) automatically performs basic checks on +the commits proposed in a MR. If all is well the robot silently reports +a successful "build" status to GitLab. Otherwise the robot posts a comment +with its diagnostics. **A topic may not be merged until the automatic +review succeeds.** + +Note that the MR submitter is expected to address the robot's comments by +*rewriting* the commits named by the robot's diagnostics (e.g., via +``git rebase -i``). This is because the robot checks each commit individually, +not the topic as a whole. This is done in order to ensure that commits in the +middle of a topic do not, for example, add a giant file which is then later +removed in the topic. + +Automatic Check +--------------- + +The automatic check is repeated whenever the topic branch is updated. +One may explicitly request a re-check by adding a comment with the +following command among the `comment trailing lines`_:: + + Do: check + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also run its checks again. + +Automatic Format +---------------- + +The automatic check will reject commits introducing source code not +formatted according to ``clang-format``. One may ask the robot to +automatically rewrite the MR topic branch with expected formatting +by adding a comment with the following command among the +`comment trailing lines`_:: + + Do: reformat + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also rewrite the MR topic branch and force-push an +updated version with every commit formatted as expected by the check. + +Human Review +============ + +Anyone is welcome to review merge requests and make comments! + +Please make comments directly on the MR page Discussion and Changes tabs +and not on individual commits. Comments on a commit may disappear +from the MR page if the commit is rewritten in response. + +Reviewers may add comments providing feedback or to acknowledge their +approval. Lines of specific forms will be extracted during the `merge`_ +step and included as trailing lines of the generated merge commit message. +Each review comment consists of up to two parts which must be specified +in the following order: `comment body`_, then `comment trailing lines`_. +Each part is optional, but they must be specified in this order. + +Comment Body +------------ + +The body of a comment may be free-form `GitLab Flavored Markdown`_. +See GitLab documentation on `Special GitLab References`_ to add links to +things like issues, commits, or other merge requests (even across projects). + +Additionally, a line in the comment body may start with one of the +following votes: + +* ``-1`` or ``:-1:`` indicates "the change is not ready for integration". + +* ``+1`` or ``:+1:`` indicates "I like the change". + This adds an ``Acked-by:`` trailer to the `merge`_ commit message. + +* ``+2`` indicates "the change is ready for integration". + This adds a ``Reviewed-by:`` trailer to the `merge`_ commit message. + +* ``+3`` indicates "I have tested the change and verified it works". + This adds a ``Tested-by:`` trailer to the `merge`_ commit message. + +.. _`GitLab Flavored Markdown`: https://gitlab.kitware.com/help/user/markdown.md +.. _`Special GitLab References`: https://gitlab.kitware.com/help/user/markdown.md#special-gitlab-references + +Comment Trailing Lines +---------------------- + +Zero or more *trailing* lines in the last section of a comment may appear +with the form ``Key: Value``. The first such line should be separated +from a preceding `comment body`_ by a blank line. Any key-value pair(s) +may be specified for human reference. A few specific keys have meaning to +``@kwrobot`` as follows. + +Comment Trailer Votes +^^^^^^^^^^^^^^^^^^^^^ + +Among the `comment trailing lines`_ one may cast a vote using one of the +following pairs followed by nothing but whitespace before the end of the line: + +* ``Rejected-by: me`` indicates "the change is not ready for integration". +* ``Acked-by: me`` indicates "I like the change". + This adds an ``Acked-by:`` trailer to the `merge`_ commit message. +* ``Reviewed-by: me`` indicates "the change is ready for integration". + This adds a ``Reviewed-by:`` trailer to the `merge`_ commit message. +* ``Tested-by: me`` indicates "I have tested the change and verified it works". + This adds a ``Tested-by:`` trailer to the `merge`_ commit message. + +Each ``me`` reference may instead be an ``@username`` reference or a full +``Real Name `` reference to credit someone else for performing +the review. References to ``me`` and ``@username`` will automatically be +transformed into a real name and email address according to the user's +GitLab account profile. + +Comment Trailer Commands +^^^^^^^^^^^^^^^^^^^^^^^^ + +Among the `comment trailing lines`_ authorized users may issue special +commands to ``@kwrobot`` using the form ``Do: ...``: + +* ``Do: check`` explicitly re-runs the robot `Automatic Check`_. +* ``Do: reformat`` rewrites the MR topic for `Automatic Format`_. +* ``Do: test`` submits the MR for `Topic Testing`_. +* ``Do: stage`` submits the MR for `Integration Testing`_. +* ``Do: merge`` submits the MR for `Merge`_. + +See the corresponding sections for details on permissions and options +for each command. + +Topic Testing +============= + +CMake has a `buildbot`_ instance watching for merge requests to test. +`CMake GitLab Project Developers`_ may activate buildbot on a MR by +adding a comment with a command among the `comment trailing lines`_:: + + Do: test + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also inform buildbot about the request. The buildbot +user (``@buildbot``) will schedule builds and respond with a comment +linking to the `CMake CDash Page`_ with a filter for results associated +with the topic test request. If the MR topic branch is updated by a +push a new ``Do: test`` command is needed to activate testing again. + +The ``Do: test`` command accepts the following arguments: + +* ``--stop``: clear the list of commands for the merge request +* ``--clear``: clear previous commands before adding this command +* ``--regex-include `` or ``-i ``: only build on builders + matching ```` (a Python regular expression) +* ``--regex-exclude `` or ``-e ``: exclude builds on builders + matching ```` (a Python regular expression) + +Builder names follow the pattern ``project-host-os-buildtype-generator``: + +* ``project``: always ``cmake`` for CMake builds +* ``host``: the buildbot host +* ``os``: one of ``windows``, ``osx``, or ``linux`` +* ``buildtype``: ``release`` or ``debug`` +* ``generator``: ``ninja``, ``makefiles``, ``vs``, + or ``lint-iwyu-tidy`` + +The special ``lint-`` generator name is a builder that builds +CMake using lint tools but does not run the test suite (so the actual +generator does not matter). + +.. _`buildbot`: http://buildbot.net +.. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake + +Integration Testing +=================== + +The above `topic testing`_ tests the MR topic independent of other +merge requests and on only a few key platforms and configurations. +The `CMake Testing Process`_ also has a large number of machines +provided by Kitware and generous volunteers that cover nearly all +supported platforms, generators, and configurations. In order to +avoid overwhelming these resources, they do not test every MR +individually. Instead, these machines follow an *integration branch*, +run tests on a nightly basis (or continuously during the day), and +post to the `CMake CDash Page`_. Some follow ``master``. Most follow +a special integration branch, the *topic stage*. + +The topic stage is a special branch maintained by the "Kitware Robot" +(``@kwrobot``). It consists of the head of the MR target integration +branch (e.g. ``master``) branch followed by a sequence of merges each +integrating changes from an open MR that has been staged for integration +testing. Each time the target integration branch is updated the stage +is rebuilt automatically by merging the staged MR topics again. + +`CMake GitLab Project Developers`_ may stage a MR for integration testing +by adding a comment with a command among the `comment trailing lines`_:: + + Do: stage + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also attempt to add the MR topic branch to the topic +stage. If the MR cannot be added (e.g. due to conflicts) the robot will +post a comment explaining what went wrong. + +Once a MR has been added to the topic stage it will remain on the stage +until one of the following occurs: + +* The MR topic branch is updated by a push. + +* The MR target integration branch (e.g. ``master``) branch is updated + and the MR cannot be merged into the topic stage again due to conflicts. + +* A developer or the submitter posts an explicit ``Do: unstage`` command. + This is useful to remove a MR from the topic stage when one is not ready + to push an update to the MR topic branch. It is unnecessary to explicitly + unstage just before or after pushing an update because the push will cause + the MR to be unstaged automatically. + +* The MR is closed. + +* The MR is merged. + +Once a MR has been removed from the topic stage a new ``Do: stage`` +command is needed to stage it again. + +.. _`CMake Testing Process`: testing.rst + +Resolve +======= + +A MR may be resolved in one of the following ways. + +Merge +----- + +Once review has concluded that the MR topic is ready for integration, +`CMake GitLab Project Masters`_ may merge the topic by adding a comment +with a command among the `comment trailing lines`_:: + + Do: merge + +``@kwrobot`` will add an award emoji to the comment to indicate that it +was processed and also attempt to merge the MR topic branch to the MR +target integration branch (e.g. ``master``). If the MR cannot be merged +(e.g. due to conflicts) the robot will post a comment explaining what +went wrong. If the MR is merged the robot will also remove the source +branch from the user's fork if the corresponding MR option was checked. + +The robot automatically constructs a merge commit message of the following +form:: + + Merge topic 'mr-topic-branch-name' + + 00000000 commit message subject line (one line per commit) + + Acked-by: Kitware Robot + Merge-request: !0000 + +Mention of the commit short sha1s and MR number helps GitLab link the +commits back to the merge request and indicates when they were merged. +The ``Acked-by:`` trailer shown indicates that `Robot Review`_ passed. +Additional ``Acked-by:``, ``Reviewed-by:``, and similar trailers may be +collected from `Human Review`_ comments that have been made since the +last time the MR topic branch was updated with a push. + +The ``Do: merge`` command accepts the following arguments: + +* ``-t ``: substitute ```` for the name of the MR topic + branch in the constructed merge commit message. + +Additionally, ``Do: merge`` extracts configuration from trailing lines +in the MR description: + +* ``Topic-rename: ``: substitute ```` for the name of + the MR topic branch in the constructed merge commit message. + The ``-t`` option overrides this. + +.. _`CMake GitLab Project Masters`: https://gitlab.kitware.com/cmake/cmake/settings/members + +Close +----- + +If review has concluded that the MR should not be integrated then it +may be closed through GitLab. + +Expire +------ + +If progress on a MR has stalled for a while, it may be closed with a +``workflow:expired`` label and a comment indicating that the MR has +been closed due to inactivity. + +Contributors are welcome to re-open an expired MR when they are ready +to continue work. Please re-open *before* pushing an update to the +MR topic branch to ensure GitLab will still act on the association. diff --git a/Help/dev/source.rst b/Help/dev/source.rst new file mode 100644 index 000000000..7e4499559 --- /dev/null +++ b/Help/dev/source.rst @@ -0,0 +1,60 @@ +CMake Source Code Guide +*********************** + +The following is a guide to the CMake source code for developers. +See documentation on `CMake Development`_ for more information. + +.. _`CMake Development`: README.rst + +C++ Code Style +============== + +We use `clang-format`_ version **3.8** to define our style for C++ code in +the CMake source tree. See the `.clang-format`_ configuration file for our +style settings. Use the `Utilities/Scripts/clang-format.bash`_ script to +format source code. It automatically runs ``clang-format`` on the set of +source files for which we enforce style. The script also has options to +format only a subset of files, such as those that are locally modified. + +.. _`clang-format`: http://clang.llvm.org/docs/ClangFormat.html +.. _`.clang-format`: ../../.clang-format +.. _`Utilities/Scripts/clang-format.bash`: ../../Utilities/Scripts/clang-format.bash + +C++ Subset Permitted +==================== + +CMake supports compiling as C++98 in addition to C++11 and C++14. +In order to support building on older toolchains some constructs +need to be handled with care: + +* Use ``CM_AUTO_PTR`` instead of ``std::auto_ptr``. + + The ``std::auto_ptr`` template is deprecated in C++11. We want to use it + so we can build on C++98 compilers but we do not want to turn off compiler + warnings about deprecated interfaces in general. Use the ``CM_AUTO_PTR`` + macro instead. + +* Use ``CM_EQ_DELETE;`` instead of ``= delete;``. + + Defining functions as *deleted* is not supported in C++98. Using + ``CM_EQ_DELETE`` will delete the functions if the compiler supports it and + give them no implementation otherwise. Calling such a function will lead + to compiler errors if the compiler supports *deleted* functions and linker + errors otherwise. + +* Use ``CM_DISABLE_COPY(Class)`` to mark classes as non-copyable. + + The ``CM_DISABLE_COPY`` macro should be used in the private section of a + class to make sure that attempts to copy or assign an instance of the class + lead to compiler errors even if the compiler does not support *deleted* + functions. As a guideline, all polymorphic classes should be made + non-copyable in order to avoid slicing. Classes that are composed of or + derived from non-copyable classes must also be made non-copyable explicitly + with ``CM_DISABLE_COPY``. + +* Use ``size_t`` instead of ``std::size_t``. + + Various implementations have differing implementation of ``size_t``. + When assigning the result of ``.size()`` on a container for example, + the result should be assigned to ``size_t`` not to ``std::size_t``, + ``unsigned int`` or similar types. diff --git a/Help/dev/testing.rst b/Help/dev/testing.rst new file mode 100644 index 000000000..731930c8f --- /dev/null +++ b/Help/dev/testing.rst @@ -0,0 +1,42 @@ +CMake Testing Process +********************* + +The following documents the process for running integration testing builds. +See documentation on `CMake Development`_ for more information. + +.. _`CMake Development`: README.rst + +CMake Dashboard Scripts +======================= + +The *integration testing* step of the `CMake Review Process`_ uses a set of +testing machines that follow an integration branch on their own schedule to +drive testing and submit results to the `CMake CDash Page`_. Anyone is +welcome to provide testing machines in order to help keep support for their +platforms working. + +The `CMake Dashboard Scripts Repository`_ provides CTest scripts to drive +nightly, continous, and experimental testing of CMake. Use the following +commands to set up a new integration testing client: + +.. code-block:: console + + $ mkdir -p ~/Dashboards + $ cd ~/Dashboards + $ git clone https://gitlab.kitware.com/cmake/dashboard-scripts.git CMakeScripts + $ cd CMakeScripts + +The ``cmake_common.cmake`` script contains comments at the top with +instructions to set up a testing client. As it instructs, create a +CTest script with local settings and include ``cmake_common.cmake``. + +.. _`CMake Review Process`: review.rst +.. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake +.. _`CMake Dashboard Scripts Repository`: https://gitlab.kitware.com/cmake/dashboard-scripts + +Nightly Start Time +------------------ + +The ``cmake_common.cmake`` script expects its includer to be run from a +nightly scheduled task (cron job). Schedule such tasks for sometime after +``1:00am UTC``, the time at which our nightly testing branches fast-forward. diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH.txt b/Help/generator/VS_TOOLSET_HOST_ARCH.txt index 58e922349..5d13e7741 100644 --- a/Help/generator/VS_TOOLSET_HOST_ARCH.txt +++ b/Help/generator/VS_TOOLSET_HOST_ARCH.txt @@ -2,9 +2,5 @@ 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). By default Visual Studio chooses the 32-bit variant even on a 64-bit host. One may request use of the -64-bit host tools by adding ``host=x64`` to the toolset specification: - -``host=x64`` - Select the 64-bit variant of the default toolset. -``,host=x64`` - Select the 64-bit variant of the ```` toolset. +64-bit host tools by adding a ``host=x64`` option to the toolset specification. +See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst index a88f8bca4..2ac044968 100644 --- a/Help/generator/Visual Studio 15 2017.rst +++ b/Help/generator/Visual Studio 15 2017.rst @@ -15,6 +15,18 @@ a target platform name optionally at the end of this generator name: ``Visual Studio 15 2017 ARM`` Specify target platform ``ARM``. +Instance Selection +^^^^^^^^^^^^^^^^^^ + +VS 2017 supports multiple installations on the same machine. +CMake queries the Visual Studio Installer to locate VS instances. +If more than one instance is installed we do not define which one +is chosen by default. If the ``VS150COMNTOOLS`` environment variable +is set and points to the ``Common7/Tools`` directory within one of +the instances, that instance will be used. The environment variable +must remain consistently set whenever CMake is re-run within a given +build tree. + Toolset Selection ^^^^^^^^^^^^^^^^^ diff --git a/Help/generator/Visual Studio 7 .NET 2003.rst b/Help/generator/Visual Studio 7 .NET 2003.rst index 1c086a03d..d4c78693f 100644 --- a/Help/generator/Visual Studio 7 .NET 2003.rst +++ b/Help/generator/Visual Studio 7 .NET 2003.rst @@ -1,10 +1,6 @@ Visual Studio 7 .NET 2003 ------------------------- -Deprecated. Generates Visual Studio .NET 2003 project files. - -.. note:: - This generator is deprecated and will be removed - in a future version of CMake. It will still be - possible to build with VS 7.1 tools using the - :generator:`NMake Makefiles` generator. +Removed. This once generated Visual Studio .NET 2003 project files, but +the generator has been removed since CMake 3.9. It is still possible to +build with VS 7.1 tools using the :generator:`NMake Makefiles` generator. diff --git a/Help/generator/Visual Studio 8 2005.rst b/Help/generator/Visual Studio 8 2005.rst index 29012c371..acbbf01ae 100644 --- a/Help/generator/Visual Studio 8 2005.rst +++ b/Help/generator/Visual Studio 8 2005.rst @@ -1,7 +1,14 @@ Visual Studio 8 2005 -------------------- -Generates Visual Studio 8 2005 project files. +Deprecated. Generates Visual Studio 8 2005 project files. + +.. note:: + This generator is deprecated and will be removed in a future version + of CMake. It will still be possible to build with VS 8 2005 tools + using the :generator:`Visual Studio 10 2010` (or above) generator + with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v80``, or by + using the :generator:`NMake Makefiles` generator. The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set to specify a target platform name. diff --git a/Help/generator/Xcode.rst b/Help/generator/Xcode.rst index 25ff4c76f..968c26a70 100644 --- a/Help/generator/Xcode.rst +++ b/Help/generator/Xcode.rst @@ -3,6 +3,8 @@ Xcode Generate Xcode project files. +This supports Xcode 3.0 and above. + Toolset Selection ^^^^^^^^^^^^^^^^^ diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index 9b3f7176b..e8b87c923 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -48,31 +48,19 @@ build system. Possible generator names are specified in the :manual:`cmake-generators(7)` manual. -``-T `` - Specify toolset name if supported by generator. +``-T `` + Toolset specification for the generator, if supported. - Some CMake generators support a toolset name to be given to the - native build system to choose a compiler. - See the :variable:`CMAKE_GENERATOR_TOOLSET` variable. - This is supported only on specific generators: - - * :ref:`Visual Studio Generators` for VS 2010 and above - * The :generator:`Xcode` generator for Xcode 3.0 and above - - See native build system documentation for allowed toolset names. + Some CMake generators support a toolset specification to tell + the native build system how to choose a compiler. See the + :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. ``-A `` Specify platform name if supported by generator. Some CMake generators support a platform name to be given to the native build system to choose a compiler or SDK. See the - :variable:`CMAKE_GENERATOR_PLATFORM` variable. - This is supported only on specific generators: - - * For :ref:`Visual Studio Generators` with VS 2005 and above this - specifies the target architecture. - - See native build system documentation for allowed platform names. + :variable:`CMAKE_GENERATOR_PLATFORM` variable for details. ``-Wno-dev`` Suppress developer warnings. diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index 2e6a80344..95f5b8735 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -125,10 +125,10 @@ The object files collection can be used as source inputs to other targets: add_executable(test_exe $ test.cpp) -``OBJECT`` libraries may only be used locally as sources in a buildsystem -- -they may not be installed, exported, or used in the right hand side of +``OBJECT`` libraries may not be used in the right hand side of :command:`target_link_libraries`. They also may not be used as the ``TARGET`` -in a use of the :command:`add_custom_command(TARGET)` command signature. +in a use of the :command:`add_custom_command(TARGET)` command signature. They +may be installed, and will be exported as an INTERFACE library. Although object libraries may not be named directly in calls to the :command:`target_link_libraries` command, they can be "linked" @@ -136,6 +136,12 @@ indirectly by using an :ref:`Interface Library ` whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name ``$``. +Although object libraries may not be used as the ``TARGET`` +in a use of the :command:`add_custom_command(TARGET)` command signature, +the list of objects can be used by :command:`add_custom_command(OUTPUT)` or +:command:`file(GENERATE)` by using ``$``. + + Build Specification and Usage Requirements ========================================== diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index d0c298659..611c989a0 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -7,91 +7,103 @@ cmake-commands(7) .. contents:: -Normal Commands -=============== +Scripting Commands +================== -These commands may be used freely in CMake projects. +These commands are always available. .. toctree:: :maxdepth: 1 - /command/add_compile_options - /command/add_custom_command - /command/add_custom_target - /command/add_definitions - /command/add_dependencies - /command/add_executable - /command/add_library - /command/add_subdirectory - /command/add_test - /command/aux_source_directory /command/break - /command/build_command /command/cmake_host_system_information /command/cmake_minimum_required /command/cmake_parse_arguments /command/cmake_policy /command/configure_file /command/continue - /command/create_test_sourcelist - /command/define_property /command/elseif /command/else - /command/enable_language - /command/enable_testing /command/endforeach /command/endfunction /command/endif /command/endmacro /command/endwhile /command/execute_process - /command/export /command/file /command/find_file /command/find_library /command/find_package /command/find_path /command/find_program - /command/fltk_wrap_ui /command/foreach /command/function /command/get_cmake_property /command/get_directory_property /command/get_filename_component /command/get_property + /command/if + /command/include + /command/list + /command/macro + /command/mark_as_advanced + /command/math + /command/message + /command/option + /command/return + /command/separate_arguments + /command/set_directory_properties + /command/set_property + /command/set + /command/site_name + /command/string + /command/unset + /command/variable_watch + /command/while + +Project Commands +================ + +These commands are available only in CMake projects. + +.. toctree:: + :maxdepth: 1 + + /command/add_compile_options + /command/add_custom_command + /command/add_custom_target + /command/add_definitions + /command/add_dependencies + /command/add_executable + /command/add_library + /command/add_subdirectory + /command/add_test + /command/aux_source_directory + /command/build_command + /command/create_test_sourcelist + /command/define_property + /command/enable_language + /command/enable_testing + /command/export + /command/fltk_wrap_ui /command/get_source_file_property /command/get_target_property /command/get_test_property - /command/if /command/include_directories /command/include_external_msproject /command/include_regular_expression - /command/include /command/install /command/link_directories /command/link_libraries - /command/list /command/load_cache - /command/macro - /command/mark_as_advanced - /command/math - /command/message - /command/option /command/project /command/qt_wrap_cpp /command/qt_wrap_ui /command/remove_definitions - /command/return - /command/separate_arguments - /command/set_directory_properties - /command/set_property - /command/set /command/set_source_files_properties /command/set_target_properties /command/set_tests_properties - /command/site_name /command/source_group - /command/string /command/target_compile_definitions /command/target_compile_features /command/target_compile_options @@ -100,9 +112,30 @@ These commands may be used freely in CMake projects. /command/target_sources /command/try_compile /command/try_run - /command/unset - /command/variable_watch - /command/while + +.. _`CTest Commands`: + +CTest Commands +============== + +These commands are available only in CTest scripts. + +.. toctree:: + :maxdepth: 1 + + /command/ctest_build + /command/ctest_configure + /command/ctest_coverage + /command/ctest_empty_binary_directory + /command/ctest_memcheck + /command/ctest_read_custom_files + /command/ctest_run_script + /command/ctest_sleep + /command/ctest_start + /command/ctest_submit + /command/ctest_test + /command/ctest_update + /command/ctest_upload Deprecated Commands =================== @@ -129,27 +162,3 @@ versions of CMake. Do not use them in new code. /command/utility_source /command/variable_requires /command/write_file - -.. _`CTest Commands`: - -CTest Commands -============== - -These commands are available only in ctest scripts. - -.. toctree:: - :maxdepth: 1 - - /command/ctest_build - /command/ctest_configure - /command/ctest_coverage - /command/ctest_empty_binary_directory - /command/ctest_memcheck - /command/ctest_read_custom_files - /command/ctest_run_script - /command/ctest_sleep - /command/ctest_start - /command/ctest_submit - /command/ctest_test - /command/ctest_update - /command/ctest_upload diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index 448fe9a13..012439500 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -334,8 +334,8 @@ versions specified for each: * ``AppleClang``: Apple Clang for Xcode versions 4.4 though 6.2. * ``Clang``: Clang compiler versions 2.9 through 3.4. * ``GNU``: GNU compiler versions 4.4 through 5.0. -* ``MSVC``: Microsoft Visual Studio versions 2010 through 2015. -* ``SunPro``: Oracle SolarisStudio version 12.4. +* ``MSVC``: Microsoft Visual Studio versions 2010 through 2017. +* ``SunPro``: Oracle SolarisStudio versions 12.4 through 12.5. * ``Intel``: Intel compiler versions 12.1 through 17.0. CMake is currently aware of the :prop_tgt:`C standards ` @@ -343,9 +343,25 @@ and :prop_gbl:`compile features ` available from the following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: -* all compilers and versions listed above for C++ +* all compilers and versions listed above for C++. * ``GNU``: GNU compiler versions 3.4 through 5.0. +CMake is currently aware of the :prop_tgt:`C++ standards ` and +their associated meta-features (e.g. ``cxx_std_11``) available from the +following :variable:`compiler ids _COMPILER_ID>` as of the +versions specified for each: + +* ``Cray``: Cray Compiler Environment version 8.1 through 8.5.8. +* ``PGI``: PGI version 12.10 through 17.5. +* ``XL``: IBM XL version 10.1 through 13.1.5. + +CMake is currently aware of the :prop_tgt:`C standards ` and +their associated meta-features (e.g. ``c_std_99``) available from the +following :variable:`compiler ids _COMPILER_ID>` as of the +versions specified for each: + +* all compilers and versions listed above with only meta-features for C++. + CMake is currently aware of the :prop_tgt:`CUDA standards ` from the following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst index f77d8c053..cd509ac20 100644 --- a/Help/manual/cmake-developer.7.rst +++ b/Help/manual/cmake-developer.7.rst @@ -13,30 +13,6 @@ Introduction This manual is intended for reference by developers modifying the CMake source tree itself, and by those authoring externally-maintained modules. - -Permitted C++ Subset -==================== - -CMake is required to build with ancient C++ compilers and standard library -implementations. Some common C++ constructs may not be used in CMake in order -to build with such toolchains. - -std::auto_ptr -------------- - -The ``std::auto_ptr`` template is deprecated in C++11. We want to use it -so we can build on C++98 compilers but we do not want to turn off compiler -warnings about deprecated interfaces in general. Use the ``CM_AUTO_PTR`` -macro instead. - -size_t ------- - -Various implementations have differing implementation of ``size_t``. When -assigning the result of ``.size()`` on a container for example, the result -should be assigned to ``size_t`` not to ``std::size_t``, ``unsigned int`` or -similar types. - Adding Compile Features ======================= diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 3a225adb4..bddb17477 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -117,7 +117,7 @@ Available logical expressions are: .. code-block:: cmake add_library(myapp_c foo.c) - add_library(myapp_cxx foo.c) + add_library(myapp_cxx bar.cpp) target_compile_options(myapp_cxx PUBLIC -fno-exceptions) add_executable(myapp main.cpp) target_link_libraries(myapp myapp_c myapp_cxx) @@ -205,6 +205,15 @@ Available informational expressions are: Name of the linker generated program database file (.pdb). ``$`` Directory of the linker generated program database file (.pdb). +``$`` + Full path to the bundle directory (``my.app``, ``my.framework``, or + ``my.bundle``) where ``tgt`` is the name of a target. +``$`` + 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 + ``my.app``, ``my.framework``, or ``my.bundle`` due to the flat bundle + structure. ``$`` Value of the property ``prop`` on the target ``tgt``. @@ -281,9 +290,7 @@ Available output expressions are: Content of ``...`` converted to a C identifier. ``$`` List of objects resulting from build of ``objLib``. ``objLib`` must be an - object of type ``OBJECT_LIBRARY``. This expression may only be used in - the sources of :command:`add_library` and :command:`add_executable` - commands. + object of type ``OBJECT_LIBRARY``. ``$`` Content of ``...`` converted to shell path style. For example, slashes are converted to backslashes in Windows shells and drive letters are converted diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index c478a1b2e..4a03b7a80 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -27,6 +27,7 @@ All Modules /module/CheckFortranFunctionExists /module/CheckFortranSourceCompiles /module/CheckFunctionExists + /module/CheckIPOSupported /module/CheckIncludeFileCXX /module/CheckIncludeFile /module/CheckIncludeFiles @@ -53,6 +54,7 @@ All Modules /module/CMakePrintSystemInformation /module/CMakePushCheckState /module/CMakeVerifyManifest + /module/CPackArchive /module/CPackBundle /module/CPackComponent /module/CPackCygwin @@ -229,6 +231,7 @@ All Modules /module/GenerateExportHeader /module/GetPrerequisites /module/GNUInstallDirs + /module/GoogleTest /module/InstallRequiredSystemLibraries /module/MacroAddFileDependencies /module/ProcessorCount diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 32669587a..7b858176f 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,15 @@ 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.9 +================================ + +.. toctree:: + :maxdepth: 1 + + CMP0069: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. + CMP0068: RPATH settings on macOS do not affect install_name. + Policies Introduced by CMake 3.8 ================================ diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 0e3eb86cb..ec25596f3 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -16,8 +16,11 @@ Properties of Global Scope :maxdepth: 1 /prop_gbl/ALLOW_DUPLICATE_CUSTOM_TARGETS + /prop_gbl/AUTOGEN_SOURCE_GROUP /prop_gbl/AUTOGEN_TARGETS_FOLDER + /prop_gbl/AUTOMOC_SOURCE_GROUP /prop_gbl/AUTOMOC_TARGETS_FOLDER + /prop_gbl/AUTORCC_SOURCE_GROUP /prop_gbl/CMAKE_C_KNOWN_FEATURES /prop_gbl/CMAKE_CXX_KNOWN_FEATURES /prop_gbl/DEBUG_CONFIGURATIONS @@ -26,7 +29,9 @@ Properties of Global Scope /prop_gbl/ENABLED_LANGUAGES /prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS /prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS + /prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS /prop_gbl/FIND_LIBRARY_USE_OPENBSD_VERSIONING + /prop_gbl/GENERATOR_IS_MULTI_CONFIG /prop_gbl/GLOBAL_DEPENDS_DEBUG_MODE /prop_gbl/GLOBAL_DEPENDS_NO_CYCLES /prop_gbl/IN_TRY_COMPILE @@ -114,15 +119,19 @@ Properties on Targets /prop_tgt/ARCHIVE_OUTPUT_DIRECTORY /prop_tgt/ARCHIVE_OUTPUT_NAME_CONFIG /prop_tgt/ARCHIVE_OUTPUT_NAME + /prop_tgt/AUTOGEN_BUILD_DIR /prop_tgt/AUTOGEN_TARGET_DEPENDS + /prop_tgt/AUTOMOC_DEPEND_FILTERS /prop_tgt/AUTOMOC_MOC_OPTIONS /prop_tgt/AUTOMOC /prop_tgt/AUTOUIC /prop_tgt/AUTOUIC_OPTIONS + /prop_tgt/AUTOUIC_SEARCH_PATHS /prop_tgt/AUTORCC /prop_tgt/AUTORCC_OPTIONS /prop_tgt/BINARY_DIR /prop_tgt/BUILD_RPATH + /prop_tgt/BUILD_WITH_INSTALL_NAME_DIR /prop_tgt/BUILD_WITH_INSTALL_RPATH /prop_tgt/BUNDLE_EXTENSION /prop_tgt/BUNDLE @@ -144,7 +153,9 @@ Properties on Targets /prop_tgt/CONFIG_OUTPUT_NAME /prop_tgt/CONFIG_POSTFIX /prop_tgt/CROSSCOMPILING_EMULATOR + /prop_tgt/CUDA_PTX_COMPILATION /prop_tgt/CUDA_SEPARABLE_COMPILATION + /prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS /prop_tgt/CUDA_EXTENSIONS /prop_tgt/CUDA_STANDARD /prop_tgt/CUDA_STANDARD_REQUIRED @@ -186,6 +197,8 @@ Properties on Targets /prop_tgt/IMPORTED_LOCATION /prop_tgt/IMPORTED_NO_SONAME_CONFIG /prop_tgt/IMPORTED_NO_SONAME + /prop_tgt/IMPORTED_OBJECTS_CONFIG + /prop_tgt/IMPORTED_OBJECTS /prop_tgt/IMPORTED /prop_tgt/IMPORTED_SONAME_CONFIG /prop_tgt/IMPORTED_SONAME @@ -318,6 +331,7 @@ Properties on Tests /prop_test/ATTACHED_FILES /prop_test/COST /prop_test/DEPENDS + /prop_test/DISABLED /prop_test/ENVIRONMENT /prop_test/FAIL_REGULAR_EXPRESSION /prop_test/FIXTURES_CLEANUP diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 56d4ca793..00d6e6e9b 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -63,26 +63,37 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc`` will be run on the file. The result will be put into a file named according to ``moc_.cpp``. If the macro is found in a C++ implementation file, the moc output will be put into a file named according to -``.moc``, following the Qt conventions. The ``moc file`` may be -included by the user in the C++ implementation file with a preprocessor -``#include``. If it is not so included, it will be added to a separate file -which is compiled into the target. +``.moc``, following the Qt conventions. The ``.moc`` must +be included by the user in the C++ implementation file with a preprocessor +``#include``. + +Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the +``/include`` directory which is +automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. +(This differs from CMake 3.7 and below; see their documentation for details.) + +* See :prop_tgt:`AUTOGEN_BUILD_DIR`. + +Not included ``moc_.cpp`` files will be generated in custom +folders to avoid name collisions and included in a separate +``/mocs_compilation.cpp`` file which is compiled +into the target. + +* See :prop_tgt:`AUTOGEN_BUILD_DIR`. The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and :prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being invoked for, and for the appropriate build configuration. -The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the -``/_autogen/include`` directory which is -automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. -(This differs from CMake 3.7 and below; see their documentation for details.) - The :prop_tgt:`AUTOMOC` target property may be pre-set for all following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set options to pass to ``moc``. The :variable:`CMAKE_AUTOMOC_MOC_OPTIONS` variable may be populated to pre-set the options for all following targets. +Additional ``moc`` dependency file names can be extracted from source code +by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`. + Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`. @@ -97,13 +108,17 @@ be run, and to create rules to execute ``uic`` at the appropriate time. If a preprocessor ``#include`` directive is found which matches ``ui_.h``, and a ``.ui`` file exists, then ``uic`` will -be executed to generate the appropriate file. +be executed to generate the appropriate file. The ``.ui`` file is +searched for first in the vicinity of including file and afterwards in the +optional :prop_tgt:`AUTOUIC_SEARCH_PATHS` of the target. The generated generated ``ui_*.h`` files are placed in the -``/_autogen/include`` directory which is +``/include`` directory which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. (This differs from CMake 3.7 and below; see their documentation for details.) +* See :prop_tgt:`AUTOGEN_BUILD_DIR`. + The :prop_tgt:`AUTOUIC` target property may be pre-set for all following targets by setting the :variable:`CMAKE_AUTOUIC` variable. The :prop_tgt:`AUTOUIC_OPTIONS` target property may be populated to set options diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst index 64abe9a85..8554e87f9 100644 --- a/Help/manual/cmake-toolchains.7.rst +++ b/Help/manual/cmake-toolchains.7.rst @@ -385,6 +385,11 @@ Configure use of an Android NDK with the following variables: If not specified, a default for this variable will be chosen as specified :ref:`above `. +:variable:`CMAKE_ANDROID_NDK_DEPRECATED_HEADERS` + Set to a true value to use the deprecated per-api-level headers + instead of the unified headers. If not specified, the default will + be false unless using a NDK that does not provide unified headers. + :variable:`CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION` Set to the version of the NDK toolchain to be selected as the compiler. If not specified, the default will be the latest available GCC toolchain. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 38444d125..1a2726dd3 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -13,9 +13,9 @@ Variables that Provide Information .. toctree:: :maxdepth: 1 + /variable/CMAKE_AR /variable/CMAKE_ARGC /variable/CMAKE_ARGV0 - /variable/CMAKE_AR /variable/CMAKE_BINARY_DIR /variable/CMAKE_BUILD_TOOL /variable/CMAKE_CACHEFILE_DIR @@ -48,16 +48,20 @@ Variables that Provide Information /variable/CMAKE_IMPORT_LIBRARY_SUFFIX /variable/CMAKE_JOB_POOL_COMPILE /variable/CMAKE_JOB_POOL_LINK + /variable/CMAKE_LANG_COMPILER_AR + /variable/CMAKE_LANG_COMPILER_RANLIB /variable/CMAKE_LINK_LIBRARY_SUFFIX /variable/CMAKE_LINK_SEARCH_END_STATIC /variable/CMAKE_LINK_SEARCH_START_STATIC /variable/CMAKE_MAJOR_VERSION /variable/CMAKE_MAKE_PROGRAM /variable/CMAKE_MATCH_COUNT + /variable/CMAKE_MATCH_n /variable/CMAKE_MINIMUM_REQUIRED_VERSION /variable/CMAKE_MINOR_VERSION /variable/CMAKE_PARENT_LIST_FILE /variable/CMAKE_PATCH_VERSION + /variable/CMAKE_PROJECT_DESCRIPTION /variable/CMAKE_PROJECT_NAME /variable/CMAKE_RANLIB /variable/CMAKE_ROOT @@ -82,18 +86,21 @@ Variables that Provide Information /variable/CMAKE_VS_NsightTegra_VERSION /variable/CMAKE_VS_PLATFORM_NAME /variable/CMAKE_VS_PLATFORM_TOOLSET + /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION + /variable/CMAKE_XCODE_GENERATE_SCHEME /variable/CMAKE_XCODE_PLATFORM_TOOLSET - /variable/PROJECT_BINARY_DIR /variable/PROJECT-NAME_BINARY_DIR - /variable/PROJECT_NAME /variable/PROJECT-NAME_SOURCE_DIR /variable/PROJECT-NAME_VERSION /variable/PROJECT-NAME_VERSION_MAJOR /variable/PROJECT-NAME_VERSION_MINOR /variable/PROJECT-NAME_VERSION_PATCH /variable/PROJECT-NAME_VERSION_TWEAK + /variable/PROJECT_BINARY_DIR + /variable/PROJECT_DESCRIPTION + /variable/PROJECT_NAME /variable/PROJECT_SOURCE_DIR /variable/PROJECT_VERSION /variable/PROJECT_VERSION_MAJOR @@ -127,9 +134,9 @@ Variables that Change Behavior /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION /variable/CMAKE_EXPORT_COMPILE_COMMANDS /variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY - /variable/CMAKE_SYSROOT /variable/CMAKE_FIND_APPBUNDLE /variable/CMAKE_FIND_FRAMEWORK + /variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX /variable/CMAKE_FIND_LIBRARY_PREFIXES /variable/CMAKE_FIND_LIBRARY_SUFFIXES /variable/CMAKE_FIND_NO_INSTALL_PREFIX @@ -143,9 +150,9 @@ Variables that Change Behavior /variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM /variable/CMAKE_FRAMEWORK_PATH /variable/CMAKE_IGNORE_PATH - /variable/CMAKE_INCLUDE_PATH /variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE /variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE + /variable/CMAKE_INCLUDE_PATH /variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME /variable/CMAKE_INSTALL_MESSAGE /variable/CMAKE_INSTALL_PREFIX @@ -163,6 +170,9 @@ Variables that Change Behavior /variable/CMAKE_STAGING_PREFIX /variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS /variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE + /variable/CMAKE_SYSROOT + /variable/CMAKE_SYSROOT_COMPILE + /variable/CMAKE_SYSROOT_LINK /variable/CMAKE_SYSTEM_APPBUNDLE_PATH /variable/CMAKE_SYSTEM_FRAMEWORK_PATH /variable/CMAKE_SYSTEM_IGNORE_PATH @@ -187,23 +197,24 @@ Variables that Describe the System /variable/CMAKE_COMPILER_2005 /variable/CMAKE_HOST_APPLE /variable/CMAKE_HOST_SOLARIS + /variable/CMAKE_HOST_SYSTEM /variable/CMAKE_HOST_SYSTEM_NAME /variable/CMAKE_HOST_SYSTEM_PROCESSOR - /variable/CMAKE_HOST_SYSTEM /variable/CMAKE_HOST_SYSTEM_VERSION /variable/CMAKE_HOST_UNIX /variable/CMAKE_HOST_WIN32 - /variable/CMAKE_LIBRARY_ARCHITECTURE_REGEX /variable/CMAKE_LIBRARY_ARCHITECTURE + /variable/CMAKE_LIBRARY_ARCHITECTURE_REGEX /variable/CMAKE_OBJECT_PATH_MAX + /variable/CMAKE_SYSTEM /variable/CMAKE_SYSTEM_NAME /variable/CMAKE_SYSTEM_PROCESSOR - /variable/CMAKE_SYSTEM /variable/CMAKE_SYSTEM_VERSION /variable/CYGWIN /variable/ENV /variable/GHS-MULTI /variable/MINGW + /variable/MSVC /variable/MSVC10 /variable/MSVC11 /variable/MSVC12 @@ -214,7 +225,6 @@ Variables that Describe the System /variable/MSVC80 /variable/MSVC90 /variable/MSVC_IDE - /variable/MSVC /variable/MSVC_VERSION /variable/UNIX /variable/WIN32 @@ -245,6 +255,7 @@ Variables that Control the Build /variable/CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES /variable/CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES /variable/CMAKE_ANDROID_NDK + /variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS /variable/CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG /variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION /variable/CMAKE_ANDROID_PROCESS_MAX @@ -256,31 +267,36 @@ Variables that Control the Build /variable/CMAKE_ANDROID_STL_TYPE /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG - /variable/CMAKE_AUTOMOC_MOC_OPTIONS /variable/CMAKE_AUTOMOC + /variable/CMAKE_AUTOMOC_DEPEND_FILTERS + /variable/CMAKE_AUTOMOC_MOC_OPTIONS /variable/CMAKE_AUTORCC /variable/CMAKE_AUTORCC_OPTIONS /variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC_OPTIONS + /variable/CMAKE_AUTOUIC_SEARCH_PATHS /variable/CMAKE_BUILD_RPATH + /variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR /variable/CMAKE_BUILD_WITH_INSTALL_RPATH /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_ENABLE_EXPORTS + /variable/CMAKE_EXE_LINKER_FLAGS /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_EXE_LINKER_FLAGS /variable/CMAKE_EXE_LINKER_FLAGS_INIT /variable/CMAKE_Fortran_FORMAT /variable/CMAKE_Fortran_MODULE_DIRECTORY /variable/CMAKE_GNUtoMS - /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE /variable/CMAKE_INCLUDE_CURRENT_DIR + /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE /variable/CMAKE_INSTALL_NAME_DIR /variable/CMAKE_INSTALL_RPATH /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH + /variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION + /variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG /variable/CMAKE_IOS_INSTALL_COMBINED /variable/CMAKE_LANG_CLANG_TIDY /variable/CMAKE_LANG_COMPILER_LAUNCHER @@ -299,9 +315,9 @@ Variables that Control the Build /variable/CMAKE_MACOSX_BUNDLE /variable/CMAKE_MACOSX_RPATH /variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG + /variable/CMAKE_MODULE_LINKER_FLAGS /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_MODULE_LINKER_FLAGS /variable/CMAKE_MODULE_LINKER_FLAGS_INIT /variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX /variable/CMAKE_NO_BUILTIN_CHRPATH @@ -314,15 +330,15 @@ Variables that Control the Build /variable/CMAKE_POSITION_INDEPENDENT_CODE /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY_CONFIG + /variable/CMAKE_SHARED_LINKER_FLAGS /variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG /variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_SHARED_LINKER_FLAGS /variable/CMAKE_SHARED_LINKER_FLAGS_INIT /variable/CMAKE_SKIP_BUILD_RPATH /variable/CMAKE_SKIP_INSTALL_RPATH + /variable/CMAKE_STATIC_LINKER_FLAGS /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG_INIT - /variable/CMAKE_STATIC_LINKER_FLAGS /variable/CMAKE_STATIC_LINKER_FLAGS_INIT /variable/CMAKE_TRY_COMPILE_CONFIGURATION /variable/CMAKE_TRY_COMPILE_PLATFORM_VARIABLES @@ -331,8 +347,8 @@ Variables that Control the Build /variable/CMAKE_VISIBILITY_INLINES_HIDDEN /variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD /variable/CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD - /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS /variable/CMAKE_WIN32_EXECUTABLE + /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS /variable/CMAKE_XCODE_ATTRIBUTE_an-attribute /variable/EXECUTABLE_OUTPUT_PATH /variable/LIBRARY_OUTPUT_PATH @@ -346,10 +362,6 @@ Variables for Languages /variable/CMAKE_COMPILER_IS_GNUCC /variable/CMAKE_COMPILER_IS_GNUCXX /variable/CMAKE_COMPILER_IS_GNUG77 - /variable/CMAKE_C_COMPILE_FEATURES - /variable/CMAKE_C_EXTENSIONS - /variable/CMAKE_C_STANDARD - /variable/CMAKE_C_STANDARD_REQUIRED /variable/CMAKE_CUDA_EXTENSIONS /variable/CMAKE_CUDA_STANDARD /variable/CMAKE_CUDA_STANDARD_REQUIRED @@ -358,6 +370,10 @@ Variables for Languages /variable/CMAKE_CXX_EXTENSIONS /variable/CMAKE_CXX_STANDARD /variable/CMAKE_CXX_STANDARD_REQUIRED + /variable/CMAKE_C_COMPILE_FEATURES + /variable/CMAKE_C_EXTENSIONS + /variable/CMAKE_C_STANDARD + /variable/CMAKE_C_STANDARD_REQUIRED /variable/CMAKE_Fortran_MODDIR_DEFAULT /variable/CMAKE_Fortran_MODDIR_FLAG /variable/CMAKE_Fortran_MODOUT_FLAG @@ -368,27 +384,27 @@ Variables for Languages /variable/CMAKE_LANG_ARCHIVE_APPEND /variable/CMAKE_LANG_ARCHIVE_CREATE /variable/CMAKE_LANG_ARCHIVE_FINISH - /variable/CMAKE_LANG_COMPILE_OBJECT + /variable/CMAKE_LANG_COMPILER /variable/CMAKE_LANG_COMPILER_ABI + /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN /variable/CMAKE_LANG_COMPILER_ID /variable/CMAKE_LANG_COMPILER_LOADED - /variable/CMAKE_LANG_COMPILER - /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN /variable/CMAKE_LANG_COMPILER_TARGET /variable/CMAKE_LANG_COMPILER_VERSION + /variable/CMAKE_LANG_COMPILE_OBJECT /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY /variable/CMAKE_LANG_CREATE_SHARED_MODULE /variable/CMAKE_LANG_CREATE_STATIC_LIBRARY + /variable/CMAKE_LANG_FLAGS /variable/CMAKE_LANG_FLAGS_DEBUG /variable/CMAKE_LANG_FLAGS_DEBUG_INIT + /variable/CMAKE_LANG_FLAGS_INIT /variable/CMAKE_LANG_FLAGS_MINSIZEREL /variable/CMAKE_LANG_FLAGS_MINSIZEREL_INIT /variable/CMAKE_LANG_FLAGS_RELEASE /variable/CMAKE_LANG_FLAGS_RELEASE_INIT /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO_INIT - /variable/CMAKE_LANG_FLAGS - /variable/CMAKE_LANG_FLAGS_INIT /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE @@ -399,8 +415,8 @@ Variables for Languages /variable/CMAKE_LANG_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES /variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES /variable/CMAKE_LANG_LIBRARY_ARCHITECTURE - /variable/CMAKE_LANG_LINKER_PREFERENCE_PROPAGATES /variable/CMAKE_LANG_LINKER_PREFERENCE + /variable/CMAKE_LANG_LINKER_PREFERENCE_PROPAGATES /variable/CMAKE_LANG_LINK_EXECUTABLE /variable/CMAKE_LANG_OUTPUT_EXTENSION /variable/CMAKE_LANG_PLATFORM_ID diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 37e50d2fa..ba925e8ec 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -227,7 +227,7 @@ Available commands are: ``copy ... `` Copy files to ```` (either file or directory). If multiple files are specified, the ```` must be - directory and it must exist. + directory and it must exist. Wildcards are not supported. ``copy_directory ... `` Copy directories to ```` directory. @@ -317,6 +317,9 @@ The following ``cmake -E`` commands are available only on UNIX: ``create_symlink `` Create a symbolic link ```` naming ````. +.. note:: + Path to where ```` symbolic link will be created has to exist beforehand. + Windows-specific Command-Line Tools ----------------------------------- diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index ce8157863..a89c4e9bb 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -117,6 +117,23 @@ Options This option tells ctest to NOT run the tests whose labels match the given regular expression. +``-FA , --fixture-exclude-any `` + Exclude fixtures matching ```` from automatically adding any tests to + the test set. + + 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 fixtures + matching the ````. Note that all other fixture behavior is retained, + including test dependencies and skipping tests that have fixture setup tests + that fail. + +``-FS , --fixture-exclude-setup `` + Same as ``-FA`` except only matching setup tests are excluded. + +``-FC , --fixture-exclude-cleanup `` + Same as ``-FA`` except only matching cleanup tests are excluded. + ``-D , --dashboard `` Execute dashboard test. diff --git a/Help/module/CPackArchive.rst b/Help/module/CPackArchive.rst new file mode 100644 index 000000000..eb8d9d244 --- /dev/null +++ b/Help/module/CPackArchive.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CPackArchive.cmake diff --git a/Help/module/CheckIPOSupported.rst b/Help/module/CheckIPOSupported.rst new file mode 100644 index 000000000..9c8a77b05 --- /dev/null +++ b/Help/module/CheckIPOSupported.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckIPOSupported.cmake diff --git a/Help/module/GoogleTest.rst b/Help/module/GoogleTest.rst new file mode 100644 index 000000000..3d4cc975d --- /dev/null +++ b/Help/module/GoogleTest.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/GoogleTest.cmake diff --git a/Help/policy/CMP0068.rst b/Help/policy/CMP0068.rst new file mode 100644 index 000000000..978a6e34f --- /dev/null +++ b/Help/policy/CMP0068.rst @@ -0,0 +1,35 @@ +CMP0068 +------- + +``RPATH`` settings on macOS do not affect ``install_name``. + +CMake 3.9 and newer remove any effect the following settings may have on the +``install_name`` of a target on macOS: + +* :prop_tgt:`BUILD_WITH_INSTALL_RPATH` target property +* :prop_tgt:`SKIP_BUILD_RPATH` target property +* :variable:`CMAKE_SKIP_RPATH` variable +* :variable:`CMAKE_SKIP_INSTALL_RPATH` variable + +Previously, setting :prop_tgt:`BUILD_WITH_INSTALL_RPATH` had the effect of +setting both the ``install_name`` of a target to :prop_tgt:`INSTALL_NAME_DIR` +and the ``RPATH`` to :prop_tgt:`INSTALL_RPATH`. In CMake 3.9, it only affects +setting of ``RPATH``. However, if one wants :prop_tgt:`INSTALL_NAME_DIR` to +apply to the target in the build tree, one may set +:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR`. + +If :prop_tgt:`SKIP_BUILD_RPATH`, :variable:`CMAKE_SKIP_RPATH` or +:variable:`CMAKE_SKIP_INSTALL_RPATH` were used to strip the directory portion +of the ``install_name`` of a target, one may set ``INSTALL_NAME_DIR=""`` +instead. + +The ``OLD`` behavior of this policy is to use the ``RPATH`` settings for +``install_name`` on macOS. The ``NEW`` behavior of this policy is to ignore +the ``RPATH`` settings for ``install_name`` on macOS. + +This policy was introduced in CMake version 3.9. 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/CMP0069.rst b/Help/policy/CMP0069.rst new file mode 100644 index 000000000..b8f5d80b2 --- /dev/null +++ b/Help/policy/CMP0069.rst @@ -0,0 +1,92 @@ +CMP0069 +------- + +:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` is enforced when enabled. + +CMake 3.9 and newer prefer to add IPO flags whenever the +:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property is enabled and +produce an error if flags are not known to CMake for the current compiler. +Since a given compiler may not support IPO flags in all environments in which +it is used, it is now the project's responsibility to use the +:module:`CheckIPOSupported` module to check for support before enabling the +:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property. This approach +allows a project to conditionally activate IPO when supported. It also +allows an end user to set the :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` +variable in an environment known to support IPO even if the project does +not enable the property. + +Since CMake 3.8 and lower only honored :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` +for the Intel compiler on Linux, some projects may unconditionally enable the +target property. Policy ``CMP0069`` provides compatibility with such projects. + +This policy takes effect whenever the IPO property is enabled. The ``OLD`` +behavior for this policy is to add IPO flags only for Intel compiler on Linux. +The ``NEW`` behavior for this policy is to add IPO flags for the current +compiler or produce an error if CMake does not know the flags. + +This policy was introduced in CMake version 3.9. 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 + +Examples +^^^^^^^^ + +Behave like CMake 3.8 and do not apply any IPO flags except for Intel compiler +on Linux: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.8) + project(foo) + + # ... + + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + +Use the :module:`CheckIPOSupported` module to detect whether IPO is +supported by the current compiler, environment, and CMake version. +Produce a fatal error if support is not available: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.9) # CMP0069 NEW + project(foo) + + include(CheckIPOSupport) + check_ipo_support() + + # ... + + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + +Apply IPO flags only if compiler supports it: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.9) # CMP0069 NEW + project(foo) + + include(CheckIPOSupport) + + # ... + + check_ipo_support(RESULT result) + if(result) + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + endif() + +Apply IPO flags without any checks. This may lead to build errors if IPO +is not supported by the compiler in the current environment. Produce an +error if CMake does not know IPO flags for the current compiler: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.9) # CMP0069 NEW + project(foo) + + # ... + + set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst b/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst index eb9183288..a316abec9 100644 --- a/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst +++ b/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst @@ -17,7 +17,7 @@ pairs. Each such pair will be transformed into an entry in the solution global section. Whitespace around key and value is ignored. List elements which do not contain an equal sign are skipped. -This property only works for Visual Studio 7 and above; it is ignored +This property only works for Visual Studio 8 and above; it is ignored on other generators. The property only applies when set on a directory whose CMakeLists.txt contains a project() command. @@ -26,4 +26,6 @@ and ExtensibilityAddIns by default. If you set the corresponding property, it will override the default section. For example, setting VS_GLOBAL_SECTION_POST_ExtensibilityGlobals will override the default contents of the ExtensibilityGlobals section, while keeping -ExtensibilityAddIns on its default. +ExtensibilityAddIns on its default. However, CMake will always +add a ``SolutionGuid`` to the ``ExtensibilityGlobals`` section +if it is not specified explicitly. diff --git a/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst b/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst index fbcd9e6f3..200e8e62f 100644 --- a/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst +++ b/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst @@ -17,6 +17,6 @@ pairs. Each such pair will be transformed into an entry in the solution global section. Whitespace around key and value is ignored. List elements which do not contain an equal sign are skipped. -This property only works for Visual Studio 7 and above; it is ignored +This property only works for Visual Studio 8 and above; it is ignored on other generators. The property only applies when set on a directory whose CMakeLists.txt contains a project() command. diff --git a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst new file mode 100644 index 000000000..d294eb170 --- /dev/null +++ b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst @@ -0,0 +1,15 @@ +AUTOGEN_SOURCE_GROUP +-------------------- + +Name of the :command:`source_group` for :prop_tgt:`AUTOMOC` and +:prop_tgt:`AUTORCC` generated files. + +Files generated by :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` are not always +known at configure time and therefore can't be passed to +:command:`source_group`. +:prop_gbl:`AUTOGEN_SOURCE_GROUP` an be used instead to generate or select +a source group for :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` generated files. + +For :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` specific overrides see +:prop_gbl:`AUTOMOC_SOURCE_GROUP` and :prop_gbl:`AUTORCC_SOURCE_GROUP` +respectively. diff --git a/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst b/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst index fae562648..0b747b207 100644 --- a/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst +++ b/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst @@ -1,8 +1,8 @@ AUTOGEN_TARGETS_FOLDER ---------------------- -Name of :prop_tgt:`FOLDER` for ``*_autogen`` targets that are added automatically by -CMake for targets for which :prop_tgt:`AUTOMOC` is enabled. +Name of :prop_tgt:`FOLDER` for ``*_autogen`` targets that are added +automatically by CMake for targets for which :prop_tgt:`AUTOMOC` is enabled. If not set, CMake uses the :prop_tgt:`FOLDER` property of the parent target as a default value for this property. See also the documentation for the diff --git a/Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst new file mode 100644 index 000000000..2455dc763 --- /dev/null +++ b/Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst @@ -0,0 +1,7 @@ +AUTOMOC_SOURCE_GROUP +-------------------- + +Name of the :command:`source_group` for :prop_tgt:`AUTOMOC` generated files. + +When set this is used instead of :prop_gbl:`AUTOGEN_SOURCE_GROUP` for +files generated by :prop_tgt:`AUTOMOC`. diff --git a/Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst b/Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst new file mode 100644 index 000000000..65ea95b17 --- /dev/null +++ b/Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst @@ -0,0 +1,7 @@ +AUTORCC_SOURCE_GROUP +-------------------- + +Name of the :command:`source_group` for :prop_tgt:`AUTORCC` generated files. + +When set this is used instead of :prop_gbl:`AUTOGEN_SOURCE_GROUP` for +files generated by :prop_tgt:`AUTORCC`. diff --git a/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst b/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst index ce18b650d..839602674 100644 --- a/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst +++ b/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst @@ -8,3 +8,5 @@ Whether the :command:`find_library` command should automatically search :command:`find_library` command should automatically search the ``lib32`` variant of directories called ``lib`` in the search path when building 32-bit binaries. + +See also the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable. diff --git a/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst b/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst index e52f8eb34..ed343ba41 100644 --- a/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst +++ b/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst @@ -8,3 +8,5 @@ FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the :command:`find_library` command should automatically search the lib64 variant of directories called lib in the search path when building 64-bit binaries. + +See also the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable. diff --git a/Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst b/Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst new file mode 100644 index 000000000..b87b09be1 --- /dev/null +++ b/Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst @@ -0,0 +1,12 @@ +FIND_LIBRARY_USE_LIBX32_PATHS +----------------------------- + +Whether the :command:`find_library` command should automatically search +``libx32`` directories. + +``FIND_LIBRARY_USE_LIBX32_PATHS`` is a boolean specifying whether the +:command:`find_library` command should automatically search the ``libx32`` +variant of directories called ``lib`` in the search path when building +x32-abi binaries. + +See also the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable. diff --git a/Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst b/Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst new file mode 100644 index 000000000..b8ec8a62c --- /dev/null +++ b/Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst @@ -0,0 +1,9 @@ +GENERATOR_IS_MULTI_CONFIG +------------------------- + +Read-only property that is true on multi-configuration generators. + +True when using a multi-configuration generator +(such as :ref:`Visual Studio Generators` or :generator:`Xcode`). +Multi-config generators use :variable:`CMAKE_CONFIGURATION_TYPES` +as the set of configurations and ignore :variable:`CMAKE_BUILD_TYPE`. diff --git a/Help/prop_sf/HEADER_FILE_ONLY.rst b/Help/prop_sf/HEADER_FILE_ONLY.rst index b4fb2db22..71d62ae80 100644 --- a/Help/prop_sf/HEADER_FILE_ONLY.rst +++ b/Help/prop_sf/HEADER_FILE_ONLY.rst @@ -7,3 +7,18 @@ A property on a source file that indicates if the source file is a header file with no associated implementation. This is set automatically based on the file extension and is used by CMake to determine if certain dependency information should be computed. + +By setting this property to ``ON``, you can disable compilation of +the given source file, even if it should be compiled because it is +part of the library's/executable's sources. + +This is useful if you have some source files which you somehow +pre-process, and then add these pre-processed sources via +:command:`add_library` or :command:`add_executable`. Normally, in IDE, +there would be no reference of the original sources, only of these +pre-processed sources. So by setting this property for all the original +source files to ``ON``, and then either calling :command:`add_library` +or :command:`add_executable` while passing both the pre-processed +sources and the original sources, or by using :command:`target_sources` +to add original source files will do exactly what would one expect, i.e. +the original source files would be visible in IDE, and will not be built. diff --git a/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst b/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst index 69cdcb7ff..a064afa63 100644 --- a/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst +++ b/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst @@ -21,3 +21,10 @@ extension is changed). See the :prop_tgt:`PUBLIC_HEADER`, :prop_tgt:`PRIVATE_HEADER`, and :prop_tgt:`RESOURCE` target properties for specifying files meant for ``Headers``, ``PrivateHeaders``, or ``Resources`` directories. + +If the specified location is equal to ``Resources``, the resulting location +will be the same as if the :prop_tgt:`RESOURCE` property had been used. If +the specified location is a sub-folder of ``Resources``, it will be placed +into the respective sub-folder. Note: For iOS Apple uses a flat bundle layout +where no ``Resources`` folder exist. Therefore CMake strips the ``Resources`` +folder name from the specified location. diff --git a/Help/prop_test/DISABLED.rst b/Help/prop_test/DISABLED.rst new file mode 100644 index 000000000..c18ae7ffa --- /dev/null +++ b/Help/prop_test/DISABLED.rst @@ -0,0 +1,15 @@ +DISABLED +-------- + +If set to true, the test will be skipped and its status will be 'Not Run'. A +DISABLED test will not be counted in the total number of tests and its +completion status will be reported to CDash as 'Disabled'. + +A DISABLED test does not participate in test fixture dependency resolution. +If a DISABLED test has fixture requirements defined in its +:prop_test:`FIXTURES_REQUIRED` property, it will not cause setup or cleanup +tests for those fixtures to be added to the test set. + +If a test with the :prop_test:`FIXTURES_SETUP` property set is DISABLED, the +fixture behavior will be as though that setup test was passing and any test +case requiring that fixture will still run. diff --git a/Help/prop_tgt/AUTOGEN_BUILD_DIR.rst b/Help/prop_tgt/AUTOGEN_BUILD_DIR.rst new file mode 100644 index 000000000..8db6ede91 --- /dev/null +++ b/Help/prop_tgt/AUTOGEN_BUILD_DIR.rst @@ -0,0 +1,17 @@ +AUTOGEN_BUILD_DIR +----------------- + +Directory where :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTOUIC` and :prop_tgt:`AUTORCC` +generate files for the target. + +The directory is created on demand and automatically added to the +:prop_dir:`ADDITIONAL_MAKE_CLEAN_FILES`. + +When unset or empty the directory ``/_autogen`` is used where +```` is :variable:`CMAKE_CURRENT_BINARY_DIR` and ```` +is :prop_tgt:`NAME`. + +By default :prop_tgt:`AUTOGEN_BUILD_DIR` is unset. + +See the :manual:`cmake-qt(7)` manual for more information on using CMake +with Qt. diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index b42643fef..0171d20e7 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -8,31 +8,47 @@ preprocessor automatically, i.e. without having to use the :module:`QT4_WRAP_CPP() ` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are supported. -When this property is set ``ON``, CMake will scan the +When this property is set ``ON``, CMake will scan the header and source files at build time and invoke moc accordingly. -* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found, - the ``Q_OBJECT`` class declaration is expected in the header, and - ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be - generated from the source's header into the - ``/_autogen/include`` - directory which is automatically added to the target's - :prop_tgt:`INCLUDE_DIRECTORIES`. This allows the compiler to find the - included ``moc_foo.cpp`` file regardless of the location the original source. - However, if multiple source files in different directories do this then their - generated moc files would collide. In this case a diagnostic will be issued. - -* If an ``#include`` statement like ``#include "foo.moc"`` is found, - then a ``Q_OBJECT`` is expected in the current source file and ``moc`` - is run on the file itself. Additionally, header files with the same - base name (like ``foo.h``) or ``_p`` appended to the base name (like - ``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc`` - is also executed on those files. ``AUTOMOC`` checks multiple header - alternative extensions, such as ``hpp``, ``hxx`` etc when searching - for headers. The resulting moc files, which are not included as shown - above in any of the source files are included in a generated - ``moc_compilation.cpp`` file, which is compiled as part of the - target. +* If an ``#include`` statement like ``#include "moc_.cpp"`` is found, + the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty + line of the ``.h(xx)`` header file. ``moc`` is run on the header + file to generate ``moc_.cpp`` in the + ``/include`` directory which is automatically added + to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. + This allows the compiler to find the included ``moc_.cpp`` file + regardless of the location the original source. + + * See :prop_tgt:`AUTOGEN_BUILD_DIR`. + +* If an ``#include`` statement like ``#include ".moc"`` is found, + then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source + file and ``moc`` is run on the source file itself. + +* Header files that are not included by an ``#include "moc_.cpp"`` + statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros. + The resulting ``moc_.cpp`` files are generated in custom + directories and automatically included in a generated + ``/mocs_compilation.cpp`` file, + which is compiled as part of the target. + + * The custom directories with checksum + based names help to avoid name collisions for moc files with the same + ````. + + * See :prop_tgt:`AUTOGEN_BUILD_DIR`. + +* Additionally, header files with the same base name as a source file, + (like ``.h``) or ``_p`` appended to the base name (like + ``_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros, + and if found, ``moc`` is also executed on those files. + +* ``AUTOMOC`` always checks multiple header alternative extensions, + such as ``hpp``, ``hxx``, etc. when searching for headers. + +* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the + ``moc`` when the file addressed by the ``FILE`` argument of the macro changes. This property is initialized by the value of the :variable:`CMAKE_AUTOMOC` variable if it is set when a target is created. @@ -47,6 +63,12 @@ See the documentation for this variable for more details. The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the automoc targets together in an IDE, e.g. in MSVS. +The global property :prop_gbl:`AUTOGEN_SOURCE_GROUP` can be used to group +files generated by :prop_tgt:`AUTOMOC` together in an IDE, e.g. in MSVS. + +Additional ``moc`` dependency file names can be extracted from source code +by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`. + Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`. diff --git a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst new file mode 100644 index 000000000..810cbf4ae --- /dev/null +++ b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst @@ -0,0 +1,45 @@ +AUTOMOC_DEPEND_FILTERS +---------------------- + +Filter definitions used by :prop_tgt:`AUTOMOC` to extract file names from +source code as additional dependencies for the ``moc`` file. + +This property is only used if the :prop_tgt:`AUTOMOC` property is ``ON`` +for this target. + +Filters are defined as ``KEYWORD;REGULAR_EXPRESSION`` pairs. First the file +content is searched for ``KEYWORD``. If it is found at least once, then file +names are extracted by successively searching for ``REGULAR_EXPRESSION`` and +taking the first match group. + +Consider a filter extracts the file name ``DEP`` from the content of a file +``FOO``. If ``DEP`` changes, then the ``moc`` file for ``FOO`` gets rebuilt. +The file ``DEP`` is searched for first in the vicinity +of ``FOO`` and afterwards in the target's :prop_tgt:`INCLUDE_DIRECTORIES`. + +By default :prop_tgt:`AUTOMOC_DEPEND_FILTERS` is initialized from +:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`, which is empty by default. + +See the :manual:`cmake-qt(7)` manual for more information on using CMake +with Qt. + + +Example +------- + +Consider a file ``FOO.hpp`` holds a custom macro ``OBJ_JSON_FILE`` and we +want the ``moc`` file to depend on the macro`s file name argument:: + + class My_Class : public QObject + { + Q_OBJECT + OBJ_JSON_FILE ( "DEP.json" ) + ... + }; + +Then we might use :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` to +define a filter like this:: + + set(CMAKE_AUTOMOC_DEPEND_FILTERS + "OBJ_JSON_FILE" "[\n][ \t]*OBJ_JSON_FILE[ \t]*\\([ \t]*\"([^\"]+)\"" + ) diff --git a/Help/prop_tgt/AUTORCC.rst b/Help/prop_tgt/AUTORCC.rst index 1ad089576..c0f6a26b2 100644 --- a/Help/prop_tgt/AUTORCC.rst +++ b/Help/prop_tgt/AUTORCC.rst @@ -19,6 +19,9 @@ Additional command line options for rcc can be set via the The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the autorcc targets together in an IDE, e.g. in MSVS. +The global property :prop_gbl:`AUTOGEN_SOURCE_GROUP` can be used to group +files generated by :prop_tgt:`AUTORCC` together in an IDE, e.g. in MSVS. + When there are multiple ``.qrc`` files with the same name, CMake will generate unspecified unique names for ``rcc``. Therefore if ``Q_INIT_RESOURCE()`` or ``Q_CLEANUP_RESOURCE()`` need to be used the diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst index fbf24c3cf..6493bbc78 100644 --- a/Help/prop_tgt/AUTOUIC.rst +++ b/Help/prop_tgt/AUTOUIC.rst @@ -10,8 +10,15 @@ Qt4 and Qt5 are supported. When this property is ``ON``, CMake will scan the source files at build time and invoke ``uic`` accordingly. If an ``#include`` statement like -``#include "ui_foo.h"`` is found in ``foo.cpp``, a ``foo.ui`` file is -expected next to ``foo.cpp``, and ``uic`` is run on the ``foo.ui`` file. +``#include "ui_foo.h"`` is found in ``source.cpp``, a ``foo.ui`` file is +searched for first in the vicinity of ``source.cpp`` and afterwards in the +optional :prop_tgt:`AUTOUIC_SEARCH_PATHS` of the target. +``uic`` is run on the ``foo.ui`` file to generate ``ui_foo.h`` in the directory +``/include``, +which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. + +* See :prop_tgt:`AUTOGEN_BUILD_DIR`. + This property is initialized by the value of the :variable:`CMAKE_AUTOUIC` variable if it is set when a target is created. diff --git a/Help/prop_tgt/AUTOUIC_OPTIONS.rst b/Help/prop_tgt/AUTOUIC_OPTIONS.rst index dc3bee55f..9fb042ea6 100644 --- a/Help/prop_tgt/AUTOUIC_OPTIONS.rst +++ b/Help/prop_tgt/AUTOUIC_OPTIONS.rst @@ -1,7 +1,7 @@ AUTOUIC_OPTIONS --------------- -Additional options for uic when using :prop_tgt:`AUTOUIC` +Additional options for ``uic`` when using :prop_tgt:`AUTOUIC` This property holds additional command line options which will be used when ``uic`` is executed during the build via :prop_tgt:`AUTOUIC`, i.e. it is diff --git a/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst b/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst new file mode 100644 index 000000000..96d9f8977 --- /dev/null +++ b/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst @@ -0,0 +1,12 @@ +AUTOUIC_SEARCH_PATHS +-------------------- + +Search path list used by :prop_tgt:`AUTOUIC` to find included +``.ui`` files. + +This property is initialized by the value of the +:variable:`CMAKE_AUTOUIC_SEARCH_PATHS` variable if it is set +when a target is created. Otherwise it is empty. + +See the :manual:`cmake-qt(7)` manual for more information on using CMake +with Qt. diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst new file mode 100644 index 000000000..bbb9a24ba --- /dev/null +++ b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst @@ -0,0 +1,13 @@ +BUILD_WITH_INSTALL_NAME_DIR +--------------------------- + +``BUILD_WITH_INSTALL_NAME_DIR`` is a boolean specifying whether the macOS +``install_name`` of a target in the build tree uses the directory given by +:prop_tgt:`INSTALL_NAME_DIR`. This setting only applies to targets on macOS. + +This property is initialized by the value of the variable +:variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` if it is set when a target is +created. + +If this property is not set and policy :policy:`CMP0068` is not ``NEW``, the +value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is used in its place. diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst index abcf28ffd..024435104 100644 --- a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst +++ b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst @@ -1,11 +1,15 @@ BUILD_WITH_INSTALL_RPATH ------------------------ -Should build tree targets have install tree rpaths. +``BUILD_WITH_INSTALL_RPATH`` is a boolean specifying whether to link the target +in the build tree with the :prop_tgt:`INSTALL_RPATH`. This takes precedence +over :prop_tgt:`SKIP_BUILD_RPATH` and avoids the need for relinking before +installation. -BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link the -target in the build tree with the INSTALL_RPATH. This takes -precedence over SKIP_BUILD_RPATH and avoids the need for relinking -before installation. This property is initialized by the value of the -variable CMAKE_BUILD_WITH_INSTALL_RPATH if it is set when a target is -created. +This property is initialized by the value of the +:variable:`CMAKE_BUILD_WITH_INSTALL_RPATH` variable if it is set when a target +is created. + +If policy :policy:`CMP0068` is not ``NEW``, this property also controls use of +:prop_tgt:`INSTALL_NAME_DIR` in the build tree on macOS. Either way, the +:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property takes precedence. diff --git a/Help/prop_tgt/CUDA_PTX_COMPILATION.rst b/Help/prop_tgt/CUDA_PTX_COMPILATION.rst new file mode 100644 index 000000000..0ee372b8b --- /dev/null +++ b/Help/prop_tgt/CUDA_PTX_COMPILATION.rst @@ -0,0 +1,12 @@ +CUDA_PTX_COMPILATION +-------------------- + +Compile CUDA sources to ``.ptx`` files instead of ``.obj`` files +within :ref:`Object Libraries`. + +For example: + +.. code-block:: cmake + + add_library(myptx OBJECT a.cu b.cu) + set_property(TARGET myptx PROPERTY CUDA_PTX_COMPILATION ON) diff --git a/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst b/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst new file mode 100644 index 000000000..127d79fb3 --- /dev/null +++ b/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst @@ -0,0 +1,15 @@ +CUDA_RESOLVE_DEVICE_SYMBOLS +--------------------------- + +CUDA only: Enables device linking for the specific static library target + +If set this will enable device linking on this static library target. Normally +device linking is deferred until a shared library or executable is generated, +allowing for multiple static libraries to resolve device symbols at the same +time. + +For instance: + +.. code-block:: cmake + + set_property(TARGET mystaticlib PROPERTY CUDA_RESOLVE_DEVICE_SYMBOLS ON) diff --git a/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst b/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst index 19270a59d..a14e48c19 100644 --- a/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst +++ b/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst @@ -3,6 +3,6 @@ EXCLUDE_FROM_DEFAULT_BUILD Exclude target from "Build Solution". -This property is only used by Visual Studio generators 7 and above. +This property is only used by Visual Studio generators. When set to TRUE, the target will not be built when you press "Build Solution". diff --git a/Help/prop_tgt/IMPORTED_OBJECTS.rst b/Help/prop_tgt/IMPORTED_OBJECTS.rst new file mode 100644 index 000000000..222e6cc02 --- /dev/null +++ b/Help/prop_tgt/IMPORTED_OBJECTS.rst @@ -0,0 +1,11 @@ +IMPORTED_OBJECTS +---------------- + +:ref:`;-list ` of absolute paths to the object +files on disk for an :ref:`imported ` +:ref:`object library `. + +Ignored for non-imported targets. + +Projects may skip ``IMPORTED_OBJECTS`` if the configuration-specific +property :prop_tgt:`IMPORTED_OBJECTS_` is set instead. diff --git a/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst new file mode 100644 index 000000000..4419ed1d1 --- /dev/null +++ b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst @@ -0,0 +1,7 @@ +IMPORTED_OBJECTS_ +------------------------- + +-specific version of :prop_tgt:`IMPORTED_OBJECTS` property. + +Configuration names correspond to those provided by the project from +which the target is imported. diff --git a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst index effa3b01f..3f68c3128 100644 --- a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst +++ b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst @@ -5,3 +5,7 @@ Enable interprocedural optimization for a target. If set to true, enables interprocedural optimizations if they are known to be supported by the compiler. + +This property is initialized by the +:variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable if it is set when a +target is created. diff --git a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst index 492fee078..782b0f0a6 100644 --- a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst +++ b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst @@ -6,3 +6,7 @@ Per-configuration interprocedural optimization for a target. This is a per-configuration version of INTERPROCEDURAL_OPTIMIZATION. If set, this property overrides the generic property for the named configuration. + +This property is initialized by the +:variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION_` variable if it is set +when a target is created. diff --git a/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst b/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst index 4da855bf4..266ccf078 100644 --- a/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst +++ b/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst @@ -23,3 +23,48 @@ is ignored for non-imported targets. This property is initialized by the value of the :variable:`CMAKE_MAP_IMPORTED_CONFIG_` variable if it is set when a target is created. + +Example +^^^^^^^ + +For example creating imported C++ library ``foo``: + +.. code-block:: cmake + + add_library(foo STATIC IMPORTED) + +Use ``foo_debug`` path for ``Debug`` build type: + +.. code-block:: cmake + + set_property( + TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG + ) + + set_target_properties(foo PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" + IMPORTED_LOCATION_DEBUG "${foo_debug}" + ) + +Use ``foo_release`` path for ``Release`` build type: + +.. code-block:: cmake + + set_property( + TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE + ) + + set_target_properties(foo PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" + IMPORTED_LOCATION_RELEASE "${foo_release}" + ) + +Use ``Release`` version of library for ``MinSizeRel`` and ``RelWithDebInfo`` +build types: + +.. code-block:: cmake + + set_target_properties(foo PROPERTIES + MAP_IMPORTED_CONFIG_MINSIZEREL Release + MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release + ) diff --git a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst index 06c3e6d5f..86711bf29 100644 --- a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst +++ b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst @@ -14,6 +14,13 @@ be automatically exported and imported by callers. This simplifies porting projects to Windows by reducing the need for explicit ``dllexport`` markup, even in ``C++`` classes. +When this property is enabled, zero or more ``.def`` files may also be +specified as source files of the target. The exports named by these files +will be merged with those detected from the object files to generate a +single module definition file to be passed to the linker. This can be +used to export symbols from a ``.dll`` that are not in any of its object +files but are added by the linker from dependencies (e.g. ``msvcrt.lib``). + This property is initialized by the value of the :variable:`CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS` variable if it is set when a target is created. diff --git a/Help/release/3.9.rst b/Help/release/3.9.rst new file mode 100644 index 000000000..14e8699b4 --- /dev/null +++ b/Help/release/3.9.rst @@ -0,0 +1,328 @@ +CMake 3.9 Release Notes +*********************** + +.. only:: html + + .. contents:: + +Changes made since CMake 3.8 include the following. + +New Features +============ + +Languages +--------- + +* ``CUDA`` is now supported by the :ref:`Visual Studio Generators` + for VS 2010 and above. This complements the existing support by the + :ref:`Makefile Generators` and the :generator:`Ninja` generator. + CUDA 8.0.61 or higher is recommended due to known bugs in the VS + integration by earlier versions. + +* CMake is now aware of the :prop_tgt:`C++ standards ` and + :prop_tgt:`C standards ` and their associated meta-features for + the following :variable:`compiler ids _COMPILER_ID>`: ``Cray``, + ``PGI``, and ``XL``. + +Generators +---------- + +* :ref:`Visual Studio Generators` for VS 2010 and above learned to support + the ``ASM_NASM`` language when ``nasm`` is installed. + +* The :generator:`Xcode` generator learned to create Xcode schema files. + This is an experimental feature and can be activated by setting the + :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable to a ``TRUE`` value. + +* The :generator:`Xcode` generator now supports Xcode 9. + +Commands +-------- + +* The :command:`add_library` command ``IMPORTED`` option learned to support + :ref:`Object Libraries`. + +* All ``find_`` commands now have a ``PACKAGE_ROOT`` search path group that + is first in the search heuristics. If a ``find_`` command is called from + inside a find module, then the CMake variable and environment variable named + ``_ROOT`` are used as prefixes and are the first set of paths + to be searched. + +* The :command:`find_library` command learned to search ``libx32`` paths + when the build targets the ``x32`` ABI. See the + :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS` global property. + +* The :command:`include_external_msproject` command learned to use + the :prop_tgt:`MAP_IMPORTED_CONFIG_` target property + to map current configurations to the external configurations. + +* The :command:`install(TARGETS)` command learned a new ``OBJECTS`` option to + specify where to install :ref:`Object Libraries`. + +* The :command:`install(EXPORT)` command learned how to export + :ref:`Object Libraries`. + +* The :command:`project` command learned an optional ``DESCRIPTION`` + parameter to set the :variable:`PROJECT_DESCRIPTION` variable. + +* The :command:`separate_arguments` command gained a ``NATIVE_COMMAND`` mode + that performs argument separation depending on the host operating system. + +Variables +--------- + +* A :variable:`CMAKE_ANDROID_NDK_DEPRECATED_HEADERS` variable was added + for use when :ref:`Cross Compiling for Android with the NDK` to request + use of the deprecated headers even when unified headers are available. + The default is now to use unified headers if available. + +* A :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` variable was introduced to + allow :variable:`CMAKE_AUTOMOC` to extract additional dependency file names + for ``moc`` from the contents of source files. + +* A :variable:`CMAKE_AUTOUIC_SEARCH_PATHS` variable was introduced to + allow :variable:`CMAKE_AUTOUIC` to search for ``foo.ui`` in more + places than the vicinity of the file including ``ui_foo.h``. + +* A :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable was added to + tell the :command:`find_library` command to search in a ``lib`` + directory before each ``lib`` directory that would normally be searched. + +* A :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable was added to + initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` property on all + targets. + +* A :variable:`CMAKE__COMPILER_AR` variable was added to hold + the path to the GCC/Clang wrapper of ``ar``. + +* A :variable:`CMAKE__COMPILER_RANLIB` variable was added to hold + the path to the GCC/Clang wrapper of ``ranlib``. + +* The :variable:`CMAKE_SYSROOT_COMPILE` and :variable:`CMAKE_SYSROOT_LINK` + variables were added to use separate sysroots for compiling and linking. + +Properties +---------- + +* A new :prop_tgt:`AUTOGEN_BUILD_DIR` target property was introduced to set + a custom output directory for :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTOUIC`, + and :prop_tgt:`AUTORCC`. + +* A new :prop_tgt:`AUTOMOC_DEPEND_FILTERS` target property was introduced to + allow :prop_tgt:`AUTOMOC` to extract additional dependency file names + for ``moc`` from the contents of source files. + +* A new :prop_tgt:`AUTOUIC_SEARCH_PATHS` target property was introduced to + allow :prop_tgt:`AUTOUIC` to search for ``foo.ui`` in more + places than the vicinity of the file including ``ui_foo.h``. + +* Global properties :prop_gbl:`AUTOGEN_SOURCE_GROUP`, + :prop_gbl:`AUTOMOC_SOURCE_GROUP` and + :prop_gbl:`AUTORCC_SOURCE_GROUP` were + introduced to allow files generated by :prop_tgt:`AUTOMOC` or + :prop_tgt:`AUTORCC` to be placed in a :command:`source_group`. + +* A :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property and corresponding + :variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` variable were added to + control whether to use the :prop_tgt:`INSTALL_NAME_DIR` target property + value for binaries in the build tree. This is for macOS ``install_name`` + as :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is for ``RPATH``. + +* A :prop_tgt:`CUDA_PTX_COMPILATION` target property was added to + :ref:`Object Libraries` to support compiling to ``.ptx`` files + instead of host object files. + +* A :prop_gbl:`GENERATOR_IS_MULTI_CONFIG` global property was + added to determine whether the current generator is a multi-configuration + generator (such as :ref:`Visual Studio Generators` or :generator:`Xcode`). + +* The :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property is now enforced + when enabled. CMake will add IPO flags unconditionally or produce an error + if it does not know the flags for the current compiler. The project is now + responsible to use the :module:`CheckIPOSupported` module to check for IPO + support before enabling the target property. See policy :policy:`CMP0069`. + +* The :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property may now + be used in combination with explicit ``.def`` files in order to + export all symbols from the object files within a target plus + an explicit list of symbols that the linker finds in dependencies + (e.g. ``msvcrt.lib``). + +Modules +------- + +* A :module:`CheckIPOSupported` module was added to help projects + check whether interprocedural optimization (IPO) is supported by + the current toolchain and CMake version. + +* The :module:`CMakeFindDependencyMacro` module ``find_dependency`` macro + now forwards all arguments to the underlying :command:`find_package` + call. Existing uses will continue to function as before, but callers can + now access the full suite of arguments that ``find_package`` accepts. + +* The :module:`FeatureSummary` module :command:`feature_summary` command now + accepts the new ``DEFAULT_DESCRIPTION`` option that will print the default + title for the selected package type. + +* The :module:`FeatureSummary` module gained a new + :variable:`FeatureSummary__DESCRIPTION` variable that can be defined + for each ```` to replace the type name with the specified string + whenever the package type is used in an output string by the module. + +* The :module:`FindDoxygen` module learned to control Doxygen behavior using + CMake variables and generate documentation via the newly added + :command:`doxygen_add_docs` function. The Doxygen input file (``Doxyfile``) + is automatically generated and doxygen is run as part of a custom target. + Additional components can be specified to find optional tools: ``dot``, + ``mscgen`` and ``dia``. + +* The :module:`FindMPI` module now provides imported targets. + +* The :module:`FindProtobuf` module :command:`protobuf_generate_cpp` + command gained an ``EXPORT_MACRO`` option to specify the name of + a DLL export markup macro. + +* The :module:`FindProtobuf` module now supports usage of static libraries + for Unix via a new ``Protobuf_USE_STATIC_LIBS`` input variable. + +* The :module:`FindProtobuf` module now provides imported targets + when the libraries are found. + +* A new :module:`GoogleTest` module was added to provide the + :command:`gtest_add_tests` function independently of the :module:`FindGTest` + module. The function was also updated to support keyword arguments, with + functionality expanded to allow a test name prefix and suffix to be + specified, the dependency on the source files to be optional and the list of + discovered test cases to be returned to the caller. + +CTest +----- + +* The :command:`ctest_submit` command gained a ``HTTPHEADER`` option + to specify custom headers to send during submission. + +* The :manual:`ctest(1)` executable gained new options which allow the + developer to disable automatically adding tests to the test set to satisfy + fixture dependencies. ``-FS`` prevents adding setup tests for fixtures + matching the provided regular expression, ``-FC`` prevents adding cleanup + tests for matching fixtures and ``-FA`` prevents adding any test for matching + fixtures. + +* A :prop_test:`DISABLED` test property was added to mark tests that + are configured but explicitly disabled so they do not run. + +CPack +----- + +* The :module:`CPackArchive` module learned to modify the filename + per-component. See the :variable:`CPACK_ARCHIVE_FILE_NAME` variable and + its per-component version :variable:`CPACK_ARCHIVE__FILE_NAME`. + +* The :module:`CPackComponent` module :command:`cpack_add_component` command + gained a new ``PLIST `` option to specify the ``pkgbuild`` + ``--component-plist`` argument when using the + :module:`productbuild ` generator. + +* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and + :command:`cpack_ifw_configure_component_group` commands gained + internationalization support for ``DISPLAY_NAME`` and ``DESCRIPTION`` + options. + +* The :module:`CPackIFW` module learned the new hint :variable:`CPACK_IFW_ROOT` + variable for finding the QtIFW tool suite installed in a non-standard place. + +* The :module:`CPackProductBuild` module gained a new + :variable:`CPACK_PRODUCTBUILD_RESOURCES_DIR` variable to + specify resources to be copied into the ``Resources`` + directory. + +* The :module:`CPackRPM` module learned to modify the ``debuginfo`` package + name. See the :variable:`CPACK_RPM_DEBUGINFO_FILE_NAME` variable. + +* The :module:`CPackWIX` module patching system now has the ability to set + additional attributes. This can be done by specifying attributes with + the ``CPackWiXFragment`` XML tag after the ``Id`` attribute. + See the :variable:`CPACK_WIX_PATCH_FILE` variable. + +* The CPack WIX generator implemented a new + :variable:`CPACK_WIX_ROOT_FOLDER_ID` variable which allows + using a custom root folder ID instead of the default + ``ProgramFilesFolder`` / ``ProgramFiles64Folder``. + +Other +----- + +* Interprocedural optimization (IPO) is now supported for GNU and Clang + compilers using link time optimization (LTO) flags. See the + :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property and + :module:`CheckIPOSupported` module. + +* The ``TARGET_OBJECTS`` + :manual:`generator expression ` + is now supported by the :command:`add_custom_command` and + :command:`file(GENERATE)` commands. + +* Two new informational generator expressions to retrieve Apple Bundle + directories have been added. The first one ``$`` + outputs the full path to the Bundle directory, the other one + ``$`` outputs the full path to the + ``Contents`` directory of macOS Bundles and App Bundles. For all other + bundle types and SDKs it is identical with ``$``. + The new expressions are helpful to query Bundle locations independent of + the different Bundle types and layouts on macOS and iOS. + +Deprecated and Removed Features +=============================== + +* An explicit deprecation diagnostic was added for policies ``CMP0036`` + and below. The :manual:`cmake-policies(7)` manual explains that the + OLD behaviors of all policies are deprecated and that projects should + always port to the NEW behaviors as soon as possible. + +* The :generator:`Visual Studio 8 2005` generator is now deprecated + and will be removed in a future version of CMake. + +* The :generator:`Visual Studio 7 .NET 2003` generator has been removed. + +* The :generator:`Xcode` generator dropped support for Xcode versions + older than 3. + +* The :module:`FindDoxygen` module has deprecated several variables. + +* The version of curl bundled with CMake no longer accepts URLs of the form + ``file://c:/...`` on Windows due to a change in upstream curl 7.52. Use + the form ``file:///c:/...`` instead to work on all versions. + +Other Changes +============= + +* When using :prop_tgt:`AUTOMOC`, CMake now scans for the presence of the + ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the + macro's ``FILE`` argument changes. + +* When :prop_tgt:`AUTOMOC` detects an include statement of the form + ``#include "moc_.cpp"`` the search for the respective header file + now looks in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well. + +* When running tests, CTest learned to treat skipped tests (using the + :prop_test:`SKIP_RETURN_CODE` property) the same as tests with the new + :prop_test:`DISABLED` property. Due to this change, CTest will not indicate + failure when all tests are either skipped or pass. + +* The :generator:`Ninja` generator has loosened the dependencies of object + compilation. Object compilation now depends only on custom targets + and custom commands associated with libraries on which the object's target + depends and no longer depends on the libraries themselves. Source files + in dependent targets may now compile without waiting for their targets' + dependencies to link. + +* On macOS, the default application bundle ``Info.plist`` file now enables + Hi-DPI support. + +* On macOS, ``RPATH`` settings such as :prop_tgt:`BUILD_WITH_INSTALL_RPATH` + no longer affect the ``install_name`` field. See policy :policy:`CMP0068`. + +* The :generator:`Visual Studio 14 2015` generator has been taught about + a change to the ``v140`` toolset made by a VS 2015 update. VS changed + the set of values it understands for the ``GenerateDebugInformation`` + linker setting that produces the ``-DEBUG`` linker flag variants. diff --git a/Help/release/index.rst b/Help/release/index.rst index 8f0f2523f..8222d0c33 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -11,6 +11,7 @@ Releases .. toctree:: :maxdepth: 1 + 3.9 <3.9> 3.8 <3.8> 3.7 <3.7> 3.6 <3.6> diff --git a/Help/variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst b/Help/variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst new file mode 100644 index 000000000..8ea12578c --- /dev/null +++ b/Help/variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst @@ -0,0 +1,9 @@ +CMAKE_ANDROID_NDK_DEPRECATED_HEADERS +------------------------------------ + +When :ref:`Cross Compiling for Android with the NDK`, this variable +may be set to specify whether to use the deprecated per-api-level +headers instead of the unified headers. + +If not specified, the default will be *false* if using a NDK version +that provides the unified headers and *true* otherwise. diff --git a/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst new file mode 100644 index 000000000..5c3662d9a --- /dev/null +++ b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst @@ -0,0 +1,12 @@ +CMAKE_AUTOMOC_DEPEND_FILTERS +---------------------------- + +Filter definitions used by :variable:`CMAKE_AUTOMOC` +to extract file names from source code as additional dependencies +for the ``moc`` file. + +This variable is used to initialize the :prop_tgt:`AUTOMOC_DEPEND_FILTERS` +property on all the targets. See that target property for additional +information. + +By default it is empty. diff --git a/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst b/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst new file mode 100644 index 000000000..aa132bf77 --- /dev/null +++ b/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst @@ -0,0 +1,11 @@ +CMAKE_AUTOUIC_SEARCH_PATHS +-------------------------- + +Search path list used by :variable:`CMAKE_AUTOUIC` to find included +``.ui`` files. + +This variable is used to initialize the :prop_tgt:`AUTOUIC_SEARCH_PATHS` +property on all the targets. See that target property for additional +information. + +By default it is empty. diff --git a/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst b/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst new file mode 100644 index 000000000..30d5d3bd6 --- /dev/null +++ b/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst @@ -0,0 +1,7 @@ +CMAKE_BUILD_WITH_INSTALL_NAME_DIR +--------------------------------- + +Whether to use :prop_tgt:`INSTALL_NAME_DIR` on targets in the build tree. + +This variable is used to initialize the :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` +property on all targets. diff --git a/Help/variable/CMAKE_CFG_INTDIR.rst b/Help/variable/CMAKE_CFG_INTDIR.rst index ba25a3513..c36599adf 100644 --- a/Help/variable/CMAKE_CFG_INTDIR.rst +++ b/Help/variable/CMAKE_CFG_INTDIR.rst @@ -12,7 +12,7 @@ Example values: :: - $(ConfigurationName) = Visual Studio 7, 8, 9 + $(ConfigurationName) = Visual Studio 8, 9 $(Configuration) = Visual Studio 10 $(CONFIGURATION) = Xcode . = Make-based tools diff --git a/Help/variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst b/Help/variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst new file mode 100644 index 000000000..ada89559f --- /dev/null +++ b/Help/variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst @@ -0,0 +1,12 @@ +CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX +------------------------------------ + +Specify a ```` to tell the :command:`find_library` command to +search in a ``lib`` directory before each ``lib`` directory that +would normally be searched. + +This overrides the behavior of related global properties: + +* :prop_gbl:`FIND_LIBRARY_USE_LIB32_PATHS` +* :prop_gbl:`FIND_LIBRARY_USE_LIB64_PATHS` +* :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS` diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst index a5c284a87..50412ffff 100644 --- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst +++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst @@ -1,7 +1,7 @@ CMAKE_GENERATOR_PLATFORM ------------------------ -Generator-specific target platform name specified by user. +Generator-specific target platform specification provided by user. Some CMake generators support a target platform name to be given to the native build system to choose a compiler toolchain. @@ -13,3 +13,16 @@ A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE` variable may initialize ``CMAKE_GENERATOR_PLATFORM``. Once a given build tree has been initialized with a particular value for this variable, changing the value has undefined behavior. + +Platform specification is supported only on specific generators: + +* For :ref:`Visual Studio Generators` with VS 2005 and above this + specifies the target architecture. + +See native build system documentation for allowed platform names. + +Visual Studio Platform Selection +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +On :ref:`Visual Studio Generators` the selected platform name +is provided in the :variable:`CMAKE_VS_PLATFORM_NAME` variable. diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst index 89abe5498..11c37d746 100644 --- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst @@ -1,15 +1,50 @@ CMAKE_GENERATOR_TOOLSET ----------------------- -Native build system toolset name specified by user. +Native build system toolset specification provided by user. -Some CMake generators support a toolset name to be given to the native -build system to choose a compiler. If the user specifies a toolset -name (e.g. via the :manual:`cmake(1)` ``-T`` option) the value will be -available in this variable. +Some CMake generators support a toolset specification to tell the +native build system how to choose a compiler. If the user specifies +a toolset (e.g. via the :manual:`cmake(1)` ``-T`` option) the value +will be available in this variable. The value of this variable should never be modified by project code. A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE` variable may initialize ``CMAKE_GENERATOR_TOOLSET``. Once a given build tree has been initialized with a particular value for this variable, changing the value has undefined behavior. + +Toolset specification is supported only on specific generators: + +* :ref:`Visual Studio Generators` for VS 2010 and above +* The :generator:`Xcode` generator for Xcode 3.0 and above + +See native build system documentation for allowed toolset names. + +Visual Studio Toolset Selection +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :ref:`Visual Studio Generators` support toolset specification +using one of these forms: + +* ``toolset`` +* ``toolset[,key=value]*`` +* ``key=value[,key=value]*`` + +The ``toolset`` specifies the toolset name. The selected toolset name +is provided in the :variable:`CMAKE_VS_PLATFORM_TOOLSET` variable. + +The ``key=value`` pairs form a comma-separated list of options to +specify generator-specific details of the toolset selection. +Supported pairs are: + +``cuda=`` + Specify the CUDA toolkit version to use. Supported by VS 2010 + and above with the CUDA toolkit VS integration installed. + See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_CUDA` variable. + +``host=x64`` + Request use of the native ``x64`` toolchain on ``x64`` hosts. + Supported by VS 2013 and above. + See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE` + variable. diff --git a/Help/variable/CMAKE_HOST_WIN32.rst b/Help/variable/CMAKE_HOST_WIN32.rst index 0e4c891a9..876b34c3a 100644 --- a/Help/variable/CMAKE_HOST_WIN32.rst +++ b/Help/variable/CMAKE_HOST_WIN32.rst @@ -1,6 +1,6 @@ CMAKE_HOST_WIN32 ---------------- -``True`` on Windows systems, including Win64. +``True`` if the host system is running Windows, including Windows 64-bit and MSYS. -Set to ``true`` when the host system is Windows and on Cygwin. +Set to ``false`` on Cygwin. diff --git a/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst new file mode 100644 index 000000000..b0cbb62b9 --- /dev/null +++ b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst @@ -0,0 +1,8 @@ +CMAKE_INTERPROCEDURAL_OPTIMIZATION +---------------------------------- + +Default value for :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` of targets. + +This variable is used to initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` +property on all the targets. See that target property for additional +information. diff --git a/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst new file mode 100644 index 000000000..b291102de --- /dev/null +++ b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst @@ -0,0 +1,8 @@ +CMAKE_INTERPROCEDURAL_OPTIMIZATION_ +------------------------------------------- + +Default value for :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION_` of targets. + +This variable is used to initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION_` +property on all the targets. See that target property for additional +information. diff --git a/Help/variable/CMAKE_LANG_COMPILER_AR.rst b/Help/variable/CMAKE_LANG_COMPILER_AR.rst new file mode 100644 index 000000000..b83a1d40c --- /dev/null +++ b/Help/variable/CMAKE_LANG_COMPILER_AR.rst @@ -0,0 +1,7 @@ +CMAKE__COMPILER_AR +------------------------ + +A wrapper around ``ar`` adding the appropriate ``--plugin`` option for the +compiler. + +See also :variable:`CMAKE_AR`. diff --git a/Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst b/Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst new file mode 100644 index 000000000..945160b58 --- /dev/null +++ b/Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst @@ -0,0 +1,7 @@ +CMAKE__COMPILER_RANLIB +---------------------------- + +A wrapper around ``ranlib`` adding the appropriate ``--plugin`` option for the +compiler. + +See also :variable:`CMAKE_RANLIB`. diff --git a/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst b/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst index 50e77eba0..27b0cad0d 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst @@ -6,3 +6,7 @@ Compiler version string. Compiler version in major[.minor[.patch[.tweak]]] format. This variable is not guaranteed to be defined for all compilers or languages. + +For example ``CMAKE_C_COMPILER_VERSION`` and +``CMAKE_CXX_COMPILER_VERSION`` might indicate the respective C and C++ +compiler version. diff --git a/Help/variable/CMAKE_MATCH_COUNT.rst b/Help/variable/CMAKE_MATCH_COUNT.rst index 8b1c0365b..355e83405 100644 --- a/Help/variable/CMAKE_MATCH_COUNT.rst +++ b/Help/variable/CMAKE_MATCH_COUNT.rst @@ -3,6 +3,7 @@ CMAKE_MATCH_COUNT The number of matches with the last regular expression. -When a regular expression match is used, CMake fills in ``CMAKE_MATCH_`` -variables with the match contents. The ``CMAKE_MATCH_COUNT`` variable holds -the number of match expressions when these are filled. +When a regular expression match is used, CMake fills in +:variable:`CMAKE_MATCH_` variables with the match contents. +The ``CMAKE_MATCH_COUNT`` variable holds the number of match +expressions when these are filled. diff --git a/Help/variable/CMAKE_MATCH_n.rst b/Help/variable/CMAKE_MATCH_n.rst new file mode 100644 index 000000000..c7dd62339 --- /dev/null +++ b/Help/variable/CMAKE_MATCH_n.rst @@ -0,0 +1,10 @@ +CMAKE_MATCH_ +--------------- + +Capture group ```` matched by the last regular expression, for groups +0 through 9. Group 0 is the entire match. Groups 1 through 9 are the +subexpressions captured by ``()`` syntax. + +When a regular expression match is used, CMake fills in ``CMAKE_MATCH_`` +variables with the match contents. The :variable:`CMAKE_MATCH_COUNT` +variable holds the number of match expressions when these are filled. diff --git a/Help/variable/CMAKE_MFC_FLAG.rst b/Help/variable/CMAKE_MFC_FLAG.rst index 1543677da..5a392bfbb 100644 --- a/Help/variable/CMAKE_MFC_FLAG.rst +++ b/Help/variable/CMAKE_MFC_FLAG.rst @@ -5,7 +5,7 @@ Tell cmake to use MFC for an executable or dll. This can be set in a ``CMakeLists.txt`` file and will enable MFC in the application. It should be set to ``1`` for the static MFC library, and ``2`` -for the shared MFC library. This is used in Visual Studio 7 +for the shared MFC library. This is used in Visual Studio project files. The CMakeSetup dialog used MFC and the ``CMakeLists.txt`` looks like this: diff --git a/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst b/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst new file mode 100644 index 000000000..f1911eced --- /dev/null +++ b/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst @@ -0,0 +1,7 @@ +CMAKE_PROJECT_DESCRIPTION +------------------------- + +The description of the current project. + +This specifies description of the current project from the closest inherited +:command:`project` command. diff --git a/Help/variable/CMAKE_SYSROOT.rst b/Help/variable/CMAKE_SYSROOT.rst index 7aa04506c..64f81bbc2 100644 --- a/Help/variable/CMAKE_SYSROOT.rst +++ b/Help/variable/CMAKE_SYSROOT.rst @@ -10,3 +10,6 @@ paths searched by the ``find_*`` commands. This variable may only be set in a toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE` variable. + +See also the :variable:`CMAKE_SYSROOT_COMPILE` and +:variable:`CMAKE_SYSROOT_LINK` variables. diff --git a/Help/variable/CMAKE_SYSROOT_COMPILE.rst b/Help/variable/CMAKE_SYSROOT_COMPILE.rst new file mode 100644 index 000000000..e96c62b71 --- /dev/null +++ b/Help/variable/CMAKE_SYSROOT_COMPILE.rst @@ -0,0 +1,9 @@ +CMAKE_SYSROOT_COMPILE +--------------------- + +Path to pass to the compiler in the ``--sysroot`` flag when compiling source +files. This is the same as :variable:`CMAKE_SYSROOT` but is used only for +compiling sources and not linking. + +This variable may only be set in a toolchain file specified by +the :variable:`CMAKE_TOOLCHAIN_FILE` variable. diff --git a/Help/variable/CMAKE_SYSROOT_LINK.rst b/Help/variable/CMAKE_SYSROOT_LINK.rst new file mode 100644 index 000000000..88b48eff0 --- /dev/null +++ b/Help/variable/CMAKE_SYSROOT_LINK.rst @@ -0,0 +1,9 @@ +CMAKE_SYSROOT_LINK +------------------ + +Path to pass to the compiler in the ``--sysroot`` flag when linking. This is +the same as :variable:`CMAKE_SYSROOT` but is used only for linking and not +compiling sources. + +This variable may only be set in a toolchain file specified by +the :variable:`CMAKE_TOOLCHAIN_FILE` variable. diff --git a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst index 14cc50ac6..51b42dd4b 100644 --- a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst +++ b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst @@ -1,7 +1,7 @@ CMAKE_VS_DEVENV_COMMAND ----------------------- -The generators for :generator:`Visual Studio 7` and above set this +The generators for :generator:`Visual Studio 8 2005` and above set this variable to the ``devenv.com`` command installed with the corresponding Visual Studio version. Note that this variable may be empty on Visual Studio Express editions because they do not provide this tool. diff --git a/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst b/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst index 0be10e5a0..6d196f917 100644 --- a/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst +++ b/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst @@ -1,7 +1,7 @@ CMAKE_VS_INTEL_Fortran_PROJECT_VERSION -------------------------------------- -When generating for :generator:`Visual Studio 7` or greater with the Intel +When generating for :generator:`Visual Studio 8 2005` or greater with the Intel Fortran plugin installed, this specifies the ``.vfproj`` project file format version. This is intended for internal use by CMake and should not be used by project code. diff --git a/Help/variable/CMAKE_VS_PLATFORM_NAME.rst b/Help/variable/CMAKE_VS_PLATFORM_NAME.rst index c6f8d411c..a532743fb 100644 --- a/Help/variable/CMAKE_VS_PLATFORM_NAME.rst +++ b/Help/variable/CMAKE_VS_PLATFORM_NAME.rst @@ -5,3 +5,4 @@ Visual Studio target platform name. VS 8 and above allow project files to specify a target platform. CMake provides the name of the chosen platform in this variable. +See the :variable:`CMAKE_GENERATOR_PLATFORM` variable for details. diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst index 144a41dc6..ed2d3f352 100644 --- a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst +++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst @@ -8,3 +8,5 @@ compiler toolchains. CMake may specify a toolset explicitly, such as ``v110`` for VS 11 or ``Windows7.1SDK`` for 64-bit support in VS 10 Express. CMake provides the name of the chosen toolset in this variable. + +See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst new file mode 100644 index 000000000..1604a7667 --- /dev/null +++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst @@ -0,0 +1,12 @@ +CMAKE_VS_PLATFORM_TOOLSET_CUDA +------------------------------ + +NVIDIA CUDA Toolkit version whose Visual Studio toolset to use. + +The :ref:`Visual Studio Generators` for VS 2010 and above support using +a CUDA toolset provided by a CUDA Toolkit. The toolset version number +may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of +the form ``cuda=8.0``. If none is specified CMake will choose a default +version. CMake provides the selected CUDA toolset version in this variable. +The value may be empty if no CUDA Toolkit with Visual Studio integration +is installed. diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst index e0be3a43e..83b9bc1fd 100644 --- a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst +++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst @@ -10,3 +10,8 @@ version. Otherwise CMake computes a default version based on the Windows SDK versions available. The chosen Windows target version number is provided in ``CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION``. If no Windows 10 SDK is available this value will be empty. + +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 +``Include/10.0.*`` directories. diff --git a/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst new file mode 100644 index 000000000..c9fcc92e0 --- /dev/null +++ b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst @@ -0,0 +1,11 @@ +CMAKE_XCODE_GENERATE_SCHEME +--------------------------- + +If enabled, the Xcode generator will generate schema files. Those are +are useful to invoke analyze, archive, build-for-testing and test +actions from the command line. + +.. note:: + + The Xcode Schema Generator is still experimental and subject to + change. diff --git a/Help/variable/PROJECT_DESCRIPTION.rst b/Help/variable/PROJECT_DESCRIPTION.rst new file mode 100644 index 000000000..05ede8fcc --- /dev/null +++ b/Help/variable/PROJECT_DESCRIPTION.rst @@ -0,0 +1,6 @@ +PROJECT_DESCRIPTION +------------------- + +Short project description given to the project command. + +This is the description given to the most recent :command:`project` command. diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3fafaff11..4e85474d3 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,25 +1,32 @@ -set(AM_SOURCES @_moc_uic_sources@) -set(AM_HEADERS @_moc_uic_headers@) -set(AM_SKIP_MOC @_skip_moc@) -set(AM_SKIP_UIC @_skip_uic@) -set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) -set(AM_MOC_INCLUDES @_moc_incs@) -set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") -set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +# Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") -set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_TARGET_NAME @_moc_target_name@) -set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +set(AM_BUILD_DIR @_autogen_build_dir@) +set(AM_SOURCES @_sources@) +set(AM_HEADERS @_headers@) +# Qt environment +set(AM_QT_VERSION_MAJOR @_qt_version_major@) +set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) +set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) +set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) +# MOC settings +set(AM_MOC_SKIP @_moc_skip@) +set(AM_MOC_DEFINITIONS @_moc_compile_defs@) +set(AM_MOC_INCLUDES @_moc_incs@) +set(AM_MOC_OPTIONS @_moc_options@) +set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) +set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@) +set(AM_MOC_PREDEFS_CMD @_moc_predefs_cmd@) +# UIC settings +set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) +set(AM_UIC_SEARCH_PATHS @_uic_search_paths@) +# RCC settings set(AM_RCC_SOURCES @_rcc_files@ ) set(AM_RCC_INPUTS @_rcc_inputs@) set(AM_RCC_OPTIONS_FILES @_rcc_options_files@) diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 5d6f402f1..121a8f015 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -432,6 +432,16 @@ function(get_item_rpaths item rpaths_var) endif() endif() + if(UNIX AND NOT APPLE) + file(READ_ELF ${item} RPATH rpath_var RUNPATH runpath_var CAPTURE_ERROR error_var) + get_filename_component(item_dir ${item} DIRECTORY) + foreach(rpath ${rpath_var} ${runpath_var}) + # Substitute $ORIGIN with the exepath and add to the found rpaths + string(REPLACE "$ORIGIN" "${item_dir}" rpath "${rpath}") + gp_append_unique(${rpaths_var} "${rpath}") + endforeach() + endif() + set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE) endfunction() @@ -998,7 +1008,8 @@ function(verify_bundle_prerequisites bundle result_var info_var) endif() if(NOT ignoreFile) - get_prerequisites("${f}" prereqs 1 1 "${exepath}" "") + get_item_rpaths(${f} _main_exe_rpaths) + get_prerequisites("${f}" prereqs 1 1 "${exepath}" "${_main_exe_rpaths}") # On the Mac, # "embedded" and "system" prerequisites are fine... anything else means diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in index 8e58307e9..7b94d0f6e 100644 --- a/Modules/CMakeASMCompiler.cmake.in +++ b/Modules/CMakeASMCompiler.cmake.in @@ -1,7 +1,9 @@ set(CMAKE_ASM@ASM_DIALECT@_COMPILER "@_CMAKE_ASM_COMPILER@") set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ARG1 "@_CMAKE_ASM_COMPILER_ARG1@") set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_ASM@ASM_DIALECT@_COMPILER_AR "@_CMAKE_ASM_COMPILER_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_ASM@ASM_DIALECT@_COMPILER_RANLIB "@_CMAKE_ASM_COMPILER_RANLIB@") set(CMAKE_LINKER "@CMAKE_LINKER@") set(CMAKE_ASM@ASM_DIALECT@_COMPILER_LOADED 1) set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ID "@_CMAKE_ASM_COMPILER_ID@") diff --git a/Modules/CMakeASMInformation.cmake b/Modules/CMakeASMInformation.cmake index 01355ff10..f7cf900fd 100644 --- a/Modules/CMakeASMInformation.cmake +++ b/Modules/CMakeASMInformation.cmake @@ -75,11 +75,13 @@ set (CMAKE_ASM${ASM_DIALECT}_FLAGS "${CMAKE_ASM${ASM_DIALECT}_FLAGS_INIT}" CACHE "Flags used by the assembler during all build types.") if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) -# default build type is none - if(NOT CMAKE_NO_BUILD_TYPE) + get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + # default build type is none + if(NOT _GENERATOR_IS_MULTI_CONFIG AND NOT CMAKE_NO_BUILD_TYPE) set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING "Choose the type of build, options are: None, Debug Release RelWithDebInfo MinSizeRel.") endif() + unset(_GENERATOR_IS_MULTI_CONFIG) set (CMAKE_ASM${ASM_DIALECT}_FLAGS_DEBUG "${CMAKE_ASM${ASM_DIALECT}_FLAGS_DEBUG_INIT}" CACHE STRING "Flags used by the assembler during debug builds.") set (CMAKE_ASM${ASM_DIALECT}_FLAGS_MINSIZEREL "${CMAKE_ASM${ASM_DIALECT}_FLAGS_MINSIZEREL_INIT}" CACHE STRING diff --git a/Modules/CMakeBackwardCompatibilityC.cmake b/Modules/CMakeBackwardCompatibilityC.cmake index 228e063e1..5d86d7313 100644 --- a/Modules/CMakeBackwardCompatibilityC.cmake +++ b/Modules/CMakeBackwardCompatibilityC.cmake @@ -2,12 +2,6 @@ # file Copyright.txt or https://cmake.org/licensing for details. -# Nothing here yet -if(CMAKE_GENERATOR MATCHES "Visual Studio 7") - include(CMakeVS7BackwardCompatibility) - set(CMAKE_SKIP_COMPATIBILITY_TESTS 1) -endif() - if(NOT CMAKE_SKIP_COMPATIBILITY_TESTS) # Old CMake versions did not support OS X universal binaries anyway, # so just get through this with at least some size for the types. diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 50b12f28a..974a57927 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -13,8 +13,11 @@ set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@") set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@") set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@") @SET_MSVC_C_ARCHITECTURE_ID@ +@SET_CMAKE_XCODE_CURRENT_ARCH@ set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_C_COMPILER_AR "@CMAKE_C_COMPILER_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_C_COMPILER_RANLIB "@CMAKE_C_COMPILER_RANLIB@") set(CMAKE_LINKER "@CMAKE_LINKER@") set(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@) set(CMAKE_C_COMPILER_LOADED 1) diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake index 709e316d0..71aadb474 100644 --- a/Modules/CMakeCInformation.cmake +++ b/Modules/CMakeCInformation.cmake @@ -110,11 +110,13 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_INIT}" CACHE STRING "Flags used by the compiler during all build types.") if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) -# default build type is none - if(NOT CMAKE_NO_BUILD_TYPE) + get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + # default build type is none + if(NOT _GENERATOR_IS_MULTI_CONFIG AND NOT CMAKE_NO_BUILD_TYPE) set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") endif() + unset(_GENERATOR_IS_MULTI_CONFIG) set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT}" CACHE STRING "Flags used by the compiler during debug builds.") set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL_INIT}" CACHE STRING diff --git a/Modules/CMakeCSharpInformation.cmake b/Modules/CMakeCSharpInformation.cmake index dc775bdc1..cd8601627 100644 --- a/Modules/CMakeCSharpInformation.cmake +++ b/Modules/CMakeCSharpInformation.cmake @@ -68,38 +68,38 @@ if(CMAKE_CSharp_STANDARD_LIBRARIES_INIT) mark_as_advanced(CMAKE_CSharp_STANDARD_LIBRARIES) endif() -# set missing flags (if they do not exist). This is needed in the +# set missing flags (if they are not defined). This is needed in the # unlikely case that you have only C# and no C/C++ targets in your # project. -if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS) +if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS) set(CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_DEBUG) +if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_DEBUG) set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_RELEASE) +if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_RELEASE) set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL) +if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL) set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO) +if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO) set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS) +if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS) set(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_DEBUG) +if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_DEBUG) set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_RELEASE) +if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_RELEASE) set(CMAKE_EXE_LINKER_FLAGS_RELEASE "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_MINSIZEREL) +if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_MINSIZEREL) set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "" CACHE STRING "" FORCE) endif() -if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO) +if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO) set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "" CACHE STRING "" FORCE) endif() diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 1c48159dd..9bba847d6 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -104,7 +104,9 @@ include(CMakeCommonLanguageInclude) # now define the following rules: # CMAKE_CUDA_CREATE_SHARED_LIBRARY # CMAKE_CUDA_CREATE_SHARED_MODULE -# CMAKE_CUDA_COMPILE_OBJECT +# CMAKE_CUDA_COMPILE_WHOLE_COMPILATION +# CMAKE_CUDA_COMPILE_PTX_COMPILATION +# CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION # CMAKE_CUDA_LINK_EXECUTABLE if(CMAKE_CUDA_HOST_COMPILER) @@ -186,16 +188,25 @@ if(NOT CMAKE_CUDA_LINK_EXECUTABLE) " -o ${__IMPLICT_LINKS}") endif() +if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") + set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") +else() + set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") +endif() + + #These are used when linking relocatable (dc) cuda code if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY) set(CMAKE_CUDA_DEVICE_LINK_LIBRARY - " ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink -o ") + " ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o ") endif() if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE) set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - " ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink -o ") + " ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o ") endif() +unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS) + mark_as_advanced( CMAKE_CUDA_FLAGS CMAKE_CUDA_FLAGS_RELEASE diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 6d5648895..fda79508b 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -14,8 +14,11 @@ set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@") set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@") set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@") @SET_MSVC_CXX_ARCHITECTURE_ID@ +@SET_CMAKE_XCODE_CURRENT_ARCH@ set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_CXX_COMPILER_AR "@CMAKE_CXX_COMPILER_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_CXX_COMPILER_RANLIB "@CMAKE_CXX_COMPILER_RANLIB@") set(CMAKE_LINKER "@CMAKE_LINKER@") set(CMAKE_COMPILER_IS_GNUCXX @CMAKE_COMPILER_IS_GNUCXX@) set(CMAKE_CXX_COMPILER_LOADED 1) diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake index 1b5178d8a..e60ffe019 100644 --- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake +++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake @@ -22,6 +22,7 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR) FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro FAIL_REGEX "command option .* is not recognized" # XL FAIL_REGEX "command option .* contains an incorrect subargument" # XL + FAIL_REGEX "Option .* is not recognized. Option will be ignored." # XL FAIL_REGEX "not supported in this configuration. ignored" # AIX FAIL_REGEX "File with unknown suffix passed to linker" # PGI FAIL_REGEX "[Uu]nknown switch" # PGI diff --git a/Modules/CMakeCommonLanguageInclude.cmake b/Modules/CMakeCommonLanguageInclude.cmake index 418860ee7..43b5da022 100644 --- a/Modules/CMakeCommonLanguageInclude.cmake +++ b/Modules/CMakeCommonLanguageInclude.cmake @@ -17,11 +17,13 @@ foreach(t EXE SHARED MODULE STATIC) endforeach() if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) -# default build type is none - if(NOT CMAKE_NO_BUILD_TYPE) + get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + # default build type is none + if(NOT _GENERATOR_IS_MULTI_CONFIG AND NOT CMAKE_NO_BUILD_TYPE) set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.") endif() + unset(_GENERATOR_IS_MULTI_CONFIG) set (CMAKE_EXE_LINKER_FLAGS_DEBUG ${CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT} CACHE STRING "Flags used by the linker during debug builds.") diff --git a/Modules/CMakeCompilerABI.h b/Modules/CMakeCompilerABI.h index f2714b4ea..ad481d6f0 100644 --- a/Modules/CMakeCompilerABI.h +++ b/Modules/CMakeCompilerABI.h @@ -25,6 +25,10 @@ const char info_sizeof_dptr[] = { #elif defined(__GNU__) && defined(__ELF__) && defined(__ARMEL__) #define ABI_ID "ELF ARM" +#elif defined(__linux__) && defined(__ELF__) && defined(__amd64__) && \ + defined(__ILP32__) +#define ABI_ID "ELF X32" + #elif defined(__ELF__) #define ABI_ID "ELF" #endif diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index 7ca79bd7a..f2d43b687 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -95,13 +95,13 @@ function(compiler_id_detection outvar lang) if(CID_ID_DEFINE) foreach(Id ${ordered_compilers}) - set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}# define ${CID_PREFIX}COMPILER_IS_${Id} 0\n") + string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "# define ${CID_PREFIX}COMPILER_IS_${Id} 0\n") endforeach() endif() set(pp_if "#if") if (CID_VERSION_STRINGS) - set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}\n/* Version number components: V=Version, R=Revision, P=Patch + string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "\n/* Version number components: V=Version, R=Revision, P=Patch Version date components: YYYY=Year, MM=Month, DD=Day */\n") endif() @@ -126,7 +126,7 @@ function(compiler_id_detection outvar lang) string(CONFIGURE "${_compiler_id_version_compute_${Id}}" VERSION_BLOCK @ONLY) string(APPEND id_content "${VERSION_BLOCK}\n") endif() - set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}\n${id_content}") + string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "\n${id_content}") set(pp_if "#elif") endforeach() @@ -145,7 +145,7 @@ function(compiler_id_detection outvar lang) # define ${CID_PREFIX}COMPILER_ID \"\"") endif() - set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}\n${platform_compiler_detection}\n#endif") + string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "\n${platform_compiler_detection}\n#endif") endif() set(${outvar} ${CMAKE_${lang}_COMPILER_ID_CONTENT} PARENT_SCOPE) diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index 4162726c8..87c6b2872 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -92,9 +92,17 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_ARMCC ) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)") - include(CMakeDetermineCompilerId) - CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT}) + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS NASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_NASM "-v") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_NASM "(NASM version)") + + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS YASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_YASM "--version") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_YASM "(yasm)") + include(CMakeDetermineCompilerId) + set(userflags) + CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}") endif() if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) @@ -149,6 +157,8 @@ set(_CMAKE_ASM_COMPILER "${CMAKE_ASM${ASM_DIALECT}_COMPILER}") set(_CMAKE_ASM_COMPILER_ID "${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}") set(_CMAKE_ASM_COMPILER_ARG1 "${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARG1}") set(_CMAKE_ASM_COMPILER_ENV_VAR "${CMAKE_ASM${ASM_DIALECT}_COMPILER_ENV_VAR}") +set(_CMAKE_ASM_COMPILER_AR "${CMAKE_ASM${ASM_DIALECT}_COMPILER_AR}") +set(_CMAKE_ASM_COMPILER_RANLIB "${CMAKE_ASM${ASM_DIALECT}_COMPILER_RANLIB}") # configure variables set in this file for fast reload later on configure_file(${CMAKE_ROOT}/Modules/CMakeASMCompiler.cmake.in @@ -157,3 +167,5 @@ configure_file(${CMAKE_ROOT}/Modules/CMakeASMCompiler.cmake.in set(_CMAKE_ASM_COMPILER) set(_CMAKE_ASM_COMPILER_ARG1) set(_CMAKE_ASM_COMPILER_ENV_VAR) +set(_CMAKE_ASM_COMPILER_AR) +set(_CMAKE_ASM_COMPILER_RANLIB) diff --git a/Modules/CMakeDetermineASM_NASMCompiler.cmake b/Modules/CMakeDetermineASM_NASMCompiler.cmake index 4c8e42292..dd7531031 100644 --- a/Modules/CMakeDetermineASM_NASMCompiler.cmake +++ b/Modules/CMakeDetermineASM_NASMCompiler.cmake @@ -7,8 +7,21 @@ set(CMAKE_ASM_NASM_COMPILER_LIST nasm yasm) if(NOT CMAKE_ASM_NASM_COMPILER) - find_program(CMAKE_ASM_NASM_COMPILER nasm - "$ENV{ProgramFiles}/NASM") + set(_CMAKE_ENV_VARX86 "ProgramFiles(x86)") + set(_CMAKE_ASM_NASM_COMPILER_PATHS + "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]" + "$ENV{ProgramFiles}/NASM" + "$ENV{${ENV_VARX86}}/NASM" + "$ENV{LOCALAPPDATA}/NASM" + ) + find_program(CMAKE_ASM_NASM_COMPILER + NAMES ${CMAKE_ASM_NASM_COMPILER_LIST} + PATHS ${_CMAKE_ASM_NASM_COMPILER_PATHS} + NO_DEFAULT_PATH + DOC "NASM compiler" + ) + unset(_CMAKE_ENV_VARX86) + unset(_CMAKE_ASM_NASM_COMPILER_PATHS) endif() # Load the generic DetermineASM compiler file with the DIALECT set properly: diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 4a315e0d6..3caccdeab 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -166,11 +166,20 @@ if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX) endif () include(CMakeFindBinUtils) +set(_CMAKE_PROCESSING_LANGUAGE "C") +include(Compiler/${CMAKE_C_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) + if(MSVC_C_ARCHITECTURE_ID) set(SET_MSVC_C_ARCHITECTURE_ID "set(MSVC_C_ARCHITECTURE_ID ${MSVC_C_ARCHITECTURE_ID})") endif() +if(CMAKE_C_XCODE_CURRENT_ARCH) + set(SET_CMAKE_XCODE_CURRENT_ARCH + "set(CMAKE_XCODE_CURRENT_ARCH ${CMAKE_C_XCODE_CURRENT_ARCH})") +endif() + # configure variables set in this file for fast reload later on configure_file(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in ${CMAKE_PLATFORM_INFO_DIR}/CMakeCCompiler.cmake diff --git a/Modules/CMakeDetermineCSharpCompiler.cmake b/Modules/CMakeDetermineCSharpCompiler.cmake index 1b8dd025c..55b2fb303 100644 --- a/Modules/CMakeDetermineCSharpCompiler.cmake +++ b/Modules/CMakeDetermineCSharpCompiler.cmake @@ -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. -if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^789]|[789][0-9])") +if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])") message(FATAL_ERROR "C# is currently only supported for Microsoft Visual Studio 2010 and later.") endif() diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 7b6d17b31..89ac9fa67 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -5,36 +5,40 @@ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) include(${CMAKE_ROOT}/Modules//CMakeParseImplicitLinkInfo.cmake) if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR - ("${CMAKE_GENERATOR}" MATCHES "Ninja") ) ) + ("${CMAKE_GENERATOR}" MATCHES "Ninja") OR + ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[89][0-9])") ) ) message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator") endif() -if(NOT CMAKE_CUDA_COMPILER) - set(CMAKE_CUDA_COMPILER_INIT NOTFOUND) - - # prefer the environment variable CUDACXX - if(NOT $ENV{CUDACXX} STREQUAL "") - get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT) - if(CMAKE_CUDA_FLAGS_ENV_INIT) - set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler") - endif() - if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT}) - message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}") +if(${CMAKE_GENERATOR} MATCHES "Visual Studio") +else() + if(NOT CMAKE_CUDA_COMPILER) + set(CMAKE_CUDA_COMPILER_INIT NOTFOUND) + + # prefer the environment variable CUDACXX + if(NOT $ENV{CUDACXX} STREQUAL "") + get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT) + if(CMAKE_CUDA_FLAGS_ENV_INIT) + set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler") + endif() + if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT}) + message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}") + endif() endif() + + # finally list compilers to try + if(NOT CMAKE_CUDA_COMPILER_INIT) + set(CMAKE_CUDA_COMPILER_LIST nvcc) endif() - # finally list compilers to try - if(NOT CMAKE_CUDA_COMPILER_INIT) - set(CMAKE_CUDA_COMPILER_LIST nvcc) + _cmake_find_compiler(CUDA) + else() + _cmake_find_compiler_path(CUDA) endif() - _cmake_find_compiler(CUDA) -else() - _cmake_find_compiler_path(CUDA) + mark_as_advanced(CMAKE_CUDA_COMPILER) endif() -mark_as_advanced(CMAKE_CUDA_COMPILER) - #Allow the user to specify a host compiler set(CMAKE_CUDA_HOST_COMPILER "" CACHE FILEPATH "Host compiler to be used by nvcc") if(NOT $ENV{CUDAHOSTCXX} STREQUAL "") @@ -75,14 +79,12 @@ if(MSVC_CUDA_ARCHITECTURE_ID) "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})") endif() -#if this compiler vendor is matches NVIDIA we can determine -#what the host compiler is. This only needs to be done if the CMAKE_CUDA_HOST_COMPILER -#has NOT been explicitly set -# -#Find the line from compiler ID that contains a.out ( or last line ) -#We also need to find the implicit link lines. Which can be done by replacing -#the compiler with cuda-fake-ld and pass too CMAKE_PARSE_IMPLICIT_LINK_INFO -if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) +if(${CMAKE_GENERATOR} MATCHES "Visual Studio") + set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}") + set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "") + set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "") + set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") +elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) set(_nvcc_log "") string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n") diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index f2e0bb2b9..9150962d9 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -161,11 +161,20 @@ if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX) endif () include(CMakeFindBinUtils) +set(_CMAKE_PROCESSING_LANGUAGE "CXX") +include(Compiler/${CMAKE_CXX_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) + if(MSVC_CXX_ARCHITECTURE_ID) set(SET_MSVC_CXX_ARCHITECTURE_ID "set(MSVC_CXX_ARCHITECTURE_ID ${MSVC_CXX_ARCHITECTURE_ID})") endif() +if(CMAKE_CXX_XCODE_CURRENT_ARCH) + set(SET_CMAKE_XCODE_CURRENT_ARCH + "set(CMAKE_XCODE_CURRENT_ARCH ${CMAKE_CXX_XCODE_CURRENT_ARCH})") +endif() + # configure all variables set in this file configure_file(${CMAKE_ROOT}/Modules/CMakeCXXCompiler.cmake.in ${CMAKE_PLATFORM_INFO_DIR}/CMakeCXXCompiler.cmake diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index c41a9862c..eeb806fb2 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -24,16 +24,21 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) # Try building with no extra flags and then try each set # of helper flags. Stop when the compiler is identified. - foreach(flags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST} - "" - ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS}) - CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}") - CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}") - 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}") + foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "") + foreach(testflags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST} + "" + ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS}) + CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${testflags}" "${userflags}" "${src}") + CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}") + 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}") + endforeach() + if(CMAKE_${lang}_COMPILER_ID) + break() + endif() endforeach() if(CMAKE_${lang}_COMPILER_ID) break() @@ -42,7 +47,9 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) # If the compiler is still unknown, try to query its vendor. if(CMAKE_${lang}_COMPILER AND NOT CMAKE_${lang}_COMPILER_ID) - CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang}) + foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "") + CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang} "${userflags}") + endforeach() endif() if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") @@ -66,7 +73,9 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif() if(CMAKE_GENERATOR STREQUAL "Ninja" AND MSVC_${lang}_ARCHITECTURE_ID) - CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang}) + foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "") + CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang} "${userflags}") + endforeach() else() set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "") endif() @@ -95,6 +104,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE) set(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}" PARENT_SCOPE) + set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_${lang}_XCODE_CURRENT_ARCH}" PARENT_SCOPE) set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_WRAPPER "${CMAKE_${lang}_COMPILER_WRAPPER}" PARENT_SCOPE) @@ -127,7 +137,7 @@ endfunction() #----------------------------------------------------------------------------- # Function to build the compiler id source file and look for output # files. -function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src) +function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags userflags src) # Create a clean working directory. file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR}) file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}) @@ -137,7 +147,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src) # Construct a description of this test case. set(COMPILER_DESCRIPTION "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1} -Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} +Build flags: ${userflags} Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} ") @@ -226,6 +236,26 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} endif() set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR}) set(id_src "${src}") + set(id_compile "ClCompile") + set(id_PostBuildEvent_Command "for %%i in (${id_cl}) do %40echo CMAKE_${lang}_COMPILER=%%~$PATH:i") + set(id_Import_props "") + set(id_Import_targets "") + set(id_ItemDefinitionGroup_entry "") + set(id_Link_AdditionalDependencies "") + if(lang STREQUAL CUDA) + if(NOT CMAKE_VS_PLATFORM_TOOLSET_CUDA) + message(FATAL_ERROR "No CUDA toolset found.") + endif() + set(cuda_tools "CUDA ${CMAKE_VS_PLATFORM_TOOLSET_CUDA}") + set(id_compile "CudaCompile") + set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]]) + string(CONCAT id_Import_props [[]]) + string(CONCAT id_Import_targets [[]]) + if(CMAKE_VS_PLATFORM_NAME STREQUAL x64) + set(id_ItemDefinitionGroup_entry "64") + endif() + set(id_Link_AdditionalDependencies "cudart.lib") + endif() configure_file(${CMAKE_ROOT}/Modules/CompilerId/VS-${v}.${ext}.in ${id_dir}/CompilerId${lang}.${ext} @ONLY) if(CMAKE_VS_MSBUILD_COMMAND AND NOT lang STREQUAL "Fortran") @@ -294,18 +324,8 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} else() set(id_sdkroot "") endif() - if(NOT ${XCODE_VERSION} VERSION_LESS 3) - set(v 3) - set(ext xcodeproj) - elseif(NOT ${XCODE_VERSION} VERSION_LESS 2) - set(v 2) - set(ext xcodeproj) - else() - set(v 1) - set(ext xcode) - endif() - configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-${v}.pbxproj.in - ${id_dir}/CompilerId${lang}.${ext}/project.pbxproj @ONLY) + configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-3.pbxproj.in + ${id_dir}/CompilerId${lang}.xcodeproj/project.pbxproj @ONLY) unset(_ENV_MACOSX_DEPLOYMENT_TARGET) if(DEFINED ENV{MACOSX_DEPLOYMENT_TARGET}) set(_ENV_MACOSX_DEPLOYMENT_TARGET "$ENV{MACOSX_DEPLOYMENT_TARGET}") @@ -329,11 +349,14 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} endif() endif() endif() + if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "CURRENT_ARCH=([^%\r\n]+)[\r\n]") + set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_MATCH_1}" PARENT_SCOPE) + endif() else() execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" ${CMAKE_${lang}_COMPILER_ID_ARG1} - ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${userflags} ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} "${src}" @@ -621,7 +644,7 @@ endfunction() # set(CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor} "Some Vendor Output") # We try running the compiler with the flag for each vendor and # matching its regular expression in the output. -function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) +function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang userflags) if(NOT CMAKE_${lang}_COMPILER_ID_DIR) # We get here when this function is called not from within CMAKE_DETERMINE_COMPILER_ID() @@ -639,7 +662,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" ${CMAKE_${lang}_COMPILER_ID_ARG1} - ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${userflags} ${flags} WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR} OUTPUT_VARIABLE output ERROR_VARIABLE output @@ -667,7 +690,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) endforeach() endfunction() -function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang) +function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang userflags) # Run this MSVC-compatible compiler to detect what the /showIncludes # option displays. We can use a C source even with the C++ compiler # because MSVC-compatible compilers handle both and show the same output. @@ -677,7 +700,7 @@ function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang) execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" ${CMAKE_${lang}_COMPILER_ID_ARG1} - ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${userflags} /nologo /showIncludes /c main.c WORKING_DIRECTORY ${showdir} OUTPUT_VARIABLE out diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 484fa6641..d5220b4de 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -60,6 +60,7 @@ else() # fort: Compaq (now HP) Fortran 90/95 compiler for Tru64 and Linux/Alpha # ifc: Intel Fortran 95 compiler for Linux/x86 # efc: Intel Fortran 95 compiler for IA64 + # nagfor: NAG Fortran compiler # # The order is 95 or newer compilers first, then 90, # then 77 or older compilers, gnu is always last in the group, @@ -68,7 +69,7 @@ else() ftn ifort ifc af95 af90 efc f95 pathf2003 pathf95 pgf95 pgfortran lf95 xlf95 fort gfortran gfortran-4 g95 f90 pathf90 pgf90 xlf90 epcf90 fort77 - frt pgf77 xlf fl32 af77 g77 f77 + frt pgf77 xlf fl32 af77 g77 f77 nag ) # Vendor-specific compiler names. @@ -79,6 +80,7 @@ else() set(_Fortran_COMPILER_NAMES_PathScale pathf2003 pathf95 pathf90) set(_Fortran_COMPILER_NAMES_XL xlf) set(_Fortran_COMPILER_NAMES_VisualAge xlf95 xlf90 xlf) + set(_Fortran_COMPILER_NAMES_NAG nagfor) endif() _cmake_find_compiler(Fortran) @@ -255,6 +257,9 @@ if (CMAKE_CROSSCOMPILING AND NOT _CMAKE_TOOLCHAIN_PREFIX) endif () include(CMakeFindBinUtils) +set(_CMAKE_PROCESSING_LANGUAGE "Fortran") +include(Compiler/${CMAKE_Fortran_COMPILER_ID}-FindBinUtils OPTIONAL) +unset(_CMAKE_PROCESSING_LANGUAGE) if(MSVC_Fortran_ARCHITECTURE_ID) set(SET_MSVC_Fortran_ARCHITECTURE_ID diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index 867555336..20dcf1bb5 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -35,10 +35,17 @@ if(CMAKE_HOST_UNIX) find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin ) if(CMAKE_UNAME) - exec_program(uname ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_NAME) - exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "AIX") + exec_program(${CMAKE_UNAME} ARGS -v OUTPUT_VARIABLE _CMAKE_HOST_SYSTEM_MAJOR_VERSION) + exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE _CMAKE_HOST_SYSTEM_MINOR_VERSION) + set(CMAKE_HOST_SYSTEM_VERSION "${_CMAKE_HOST_SYSTEM_MAJOR_VERSION}.${_CMAKE_HOST_SYSTEM_MINOR_VERSION}") + unset(_CMAKE_HOST_SYSTEM_MAJOR_VERSION) + unset(_CMAKE_HOST_SYSTEM_MINOR_VERSION) + else() + exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) + endif() if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$") - exec_program(uname ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR + exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "Power Macintosh") @@ -49,10 +56,10 @@ if(CMAKE_HOST_UNIX) exec_program(arch ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) else() - exec_program(uname ARGS -p OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR + exec_program(${CMAKE_UNAME} ARGS -p OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) if("${val}" GREATER 0) - exec_program(uname ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR + exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) endif() endif() @@ -67,7 +74,6 @@ if(CMAKE_HOST_UNIX) endif() else() if(CMAKE_HOST_WIN32) - set (CMAKE_HOST_SYSTEM_NAME "Windows") if (DEFINED ENV{PROCESSOR_ARCHITEW6432}) set (CMAKE_HOST_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITEW6432}") else() diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 4c0486e4d..e4103d0b7 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -26,6 +26,10 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC" OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" OR "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC" + OR (CMAKE_HOST_WIN32 AND ( + "x${CMAKE_C_COMPILER_ID}" STREQUAL "xPGI" + OR "x${CMAKE_Fortran_COMPILER_ID}" STREQUAL "xPGI" + )) OR (CMAKE_GENERATOR MATCHES "Visual Studio" AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")) diff --git a/Modules/CMakeFindDependencyMacro.cmake b/Modules/CMakeFindDependencyMacro.cmake index 61f74ef3b..81606cef6 100644 --- a/Modules/CMakeFindDependencyMacro.cmake +++ b/Modules/CMakeFindDependencyMacro.cmake @@ -7,38 +7,20 @@ # # :: # -# find_dependency( [ [EXACT]]) +# find_dependency( [...]) # # # ``find_dependency()`` wraps a :command:`find_package` call for a package # dependency. It is designed to be used in a Config.cmake file, and it -# forwards the correct parameters for EXACT, QUIET and REQUIRED which were -# passed to the original :command:`find_package` call. It also sets an -# informative diagnostic message if the dependency could not be found. +# forwards the correct parameters for QUIET and REQUIRED which were passed to +# the original :command:`find_package` call. It also sets an informative +# diagnostic message if the dependency could not be found. +# +# Any additional arguments specified are forwarded to :command:`find_package`. # macro(find_dependency dep) if (NOT ${dep}_FOUND) - set(cmake_fd_version) - if (${ARGC} GREATER 1) - if ("${ARGV1}" STREQUAL "") - message(FATAL_ERROR "Invalid arguments to find_dependency. VERSION is empty") - endif() - if ("${ARGV1}" STREQUAL EXACT) - message(FATAL_ERROR "Invalid arguments to find_dependency. EXACT may only be specified if a VERSION is specified") - endif() - set(cmake_fd_version ${ARGV1}) - endif() - set(cmake_fd_exact_arg) - if(${ARGC} GREATER 2) - if (NOT "${ARGV2}" STREQUAL EXACT) - message(FATAL_ERROR "Invalid arguments to find_dependency") - endif() - set(cmake_fd_exact_arg EXACT) - endif() - if(${ARGC} GREATER 3) - message(FATAL_ERROR "Invalid arguments to find_dependency") - endif() set(cmake_fd_quiet_arg) if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) set(cmake_fd_quiet_arg QUIET) @@ -52,10 +34,9 @@ macro(find_dependency dep) _CMAKE_${dep}_TRANSITIVE_DEPENDENCY ) - find_package(${dep} ${cmake_fd_version} - ${cmake_fd_exact_arg} - ${cmake_fd_quiet_arg} - ${cmake_fd_required_arg} + find_package(${dep} ${ARGN} + ${cmake_fd_quiet_arg} + ${cmake_fd_required_arg} ) if(NOT DEFINED cmake_fd_alreadyTransitive OR cmake_fd_alreadyTransitive) @@ -67,7 +48,6 @@ macro(find_dependency dep) set(${CMAKE_FIND_PACKAGE_NAME}_FOUND False) return() endif() - set(cmake_fd_version) set(cmake_fd_required_arg) set(cmake_fd_quiet_arg) set(cmake_fd_exact_arg) diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index 69800d799..d52119050 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/Modules/CMakeFortranCompiler.cmake.in @@ -8,7 +8,9 @@ set(CMAKE_Fortran_SIMULATE_ID "@CMAKE_Fortran_SIMULATE_ID@") set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@") @SET_MSVC_Fortran_ARCHITECTURE_ID@ set(CMAKE_AR "@CMAKE_AR@") +set(CMAKE_Fortran_COMPILER_AR "@CMAKE_Fortran_COMPILER_AR@") set(CMAKE_RANLIB "@CMAKE_RANLIB@") +set(CMAKE_Fortran_COMPILER_RANLIB "@CMAKE_Fortran_COMPILER_RANLIB@") set(CMAKE_COMPILER_IS_GNUG77 @CMAKE_COMPILER_IS_GNUG77@) set(CMAKE_Fortran_COMPILER_LOADED 1) set(CMAKE_Fortran_COMPILER_WORKS @CMAKE_Fortran_COMPILER_WORKS@) diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in index 67cda3b61..26b2ed656 100644 --- a/Modules/CMakeFortranCompilerId.F.in +++ b/Modules/CMakeFortranCompilerId.F.in @@ -103,6 +103,11 @@ PRINT *, 'INFO:compiler[MIPSpro]' #elif defined(__hpux) || defined(__hpux__) PRINT *, 'INFO:compiler[HP]' +#elif defined(NAGFOR) + PRINT *, 'INFO:compiler[NAG]' +#define COMPILER_VERSION_MAJOR DEC(__NAG_COMPILER_RELEASE/10) +#define COMPILER_VERSION_MINOR DEC(__NAG_COMPILER_RELEASE % 10) +#define COMPILER_VERSION_PATCH DEC(__NAG_COMPILER_BUILD) #elif 1 # if 0 ! The above 'elif 1' instead of 'else' is to work around a bug in the diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index 32734437b..3b772784b 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -18,9 +18,13 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj get_filename_component(linker ${CMAKE_LINKER} NAME) string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" linker "${linker}") endif() + set(startfile "CMAKE_LINK_STARTFILE-NOTFOUND") + if(CMAKE_LINK_STARTFILE) + set(startfile "${CMAKE_LINK_STARTFILE}") + endif() # Construct a regex to match linker lines. It must match both the # whole line and just the command (argv[0]). - set(linker_regex "^( *|.*[/\\])(${linker}|([^/\\]+-)?ld|collect2)[^/\\]*( |$)") + set(linker_regex "^( *|.*[/\\])(${linker}|${startfile}|([^/\\]+-)?ld|collect2)[^/\\]*( |$)") set(linker_exclude_regex "collect2 version |^[A-Za-z0-9_]+=|/ldfe ") string(APPEND log " link line regex: [${linker_regex}]\n") string(REGEX REPLACE "\r?\n" ";" output_lines "${text}") @@ -38,11 +42,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj set(line "${xline}") endif() endif() - if(UNIX) - separate_arguments(args UNIX_COMMAND "${line}") - else() - separate_arguments(args WINDOWS_COMMAND "${line}") - endif() + separate_arguments(args NATIVE_COMMAND "${line}") list(GET args 0 cmd) endif() set(is_msvc 0) @@ -59,9 +59,9 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj string(REGEX REPLACE "^-L" "" dir "${arg}") list(APPEND implicit_dirs_tmp ${dir}) string(APPEND log " arg [${arg}] ==> dir [${dir}]\n") - elseif("${arg}" MATCHES "^[-/]LIBPATH:(.+)") + elseif("${arg}" MATCHES "^[-/](LIBPATH|libpath):(.+)") # MSVC search path. - set(dir "${CMAKE_MATCH_1}") + set(dir "${CMAKE_MATCH_2}") list(APPEND implicit_dirs_tmp ${dir}) string(APPEND log " arg [${arg}] ==> dir [${dir}]\n") elseif(is_msvc AND "${arg}" STREQUAL "-link") @@ -83,6 +83,11 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj # Unix library full path. list(APPEND implicit_libs_tmp ${arg}) string(APPEND log " arg [${arg}] ==> lib [${arg}]\n") + elseif("${arg}" MATCHES "^[-/](DEFAULTLIB|defaultlib):(.+)") + # Windows library. + set(lib "${CMAKE_MATCH_2}") + list(APPEND implicit_libs_tmp ${lib}) + string(APPEND log " arg [${arg}] ==> lib [${lib}]\n") elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.o$" AND obj_regex AND "${arg}" MATCHES "${obj_regex}") # Object file full path. @@ -137,7 +142,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj # We remove items that are not language-specific. set(implicit_libs "") foreach(lib IN LISTS implicit_libs_tmp) - if("x${lib}" MATCHES "^x(crt.*\\.o|gcc.*|System.*|.*libclang_rt.*)$") + if("x${lib}" MATCHES "^x(crt.*\\.o|System.*|.*libclang_rt.*|msvcrt.*|libvcruntime.*|libucrt.*|libcmt.*)$") string(APPEND log " remove lib [${lib}]\n") elseif(IS_ABSOLUTE "${lib}") get_filename_component(abs "${lib}" ABSOLUTE) diff --git a/Modules/CMakeVS7BackwardCompatibility.cmake b/Modules/CMakeVS7BackwardCompatibility.cmake deleted file mode 100644 index cf477c80a..000000000 --- a/Modules/CMakeVS7BackwardCompatibility.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - - -# hard code these for fast backwards compatibility tests -set (CMAKE_SIZEOF_INT 4 CACHE INTERNAL "Size of int data type") -set (CMAKE_SIZEOF_LONG 4 CACHE INTERNAL "Size of long data type") -set (CMAKE_SIZEOF_VOID_P 4 CACHE INTERNAL "Size of void* data type") -set (CMAKE_SIZEOF_CHAR 1 CACHE INTERNAL "Size of char data type") -set (CMAKE_SIZEOF_SHORT 2 CACHE INTERNAL "Size of short data type") -set (CMAKE_SIZEOF_FLOAT 4 CACHE INTERNAL "Size of float data type") -set (CMAKE_SIZEOF_DOUBLE 8 CACHE INTERNAL "Size of double data type") -set (CMAKE_NO_ANSI_FOR_SCOPE 0 CACHE INTERNAL - "Does the compiler support ansi for scope.") -set (CMAKE_USE_WIN32_THREADS TRUE CACHE BOOL "Use the win32 thread library.") -set (CMAKE_WORDS_BIGENDIAN 0 CACHE INTERNAL "endianness of bytes") diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 4e7546b98..a63fc8325 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -98,7 +98,12 @@ # # .. variable:: CPACK_PACKAGE_DESCRIPTION_SUMMARY # -# Short description of the project (only a few words). +# Short description of the project (only a few words). Default value is:: +# +# ${PROJECT_DESCRIPTION} +# +# if DESCRIPTION has given to the project() call or +# CMake generated string with PROJECT_NAME otherwise. # # .. variable:: CPACK_PACKAGE_FILE_NAME # @@ -360,8 +365,13 @@ _cpack_set_default(CPACK_PACKAGE_VERSION_PATCH "1") _cpack_set_default(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") _cpack_set_default(CPACK_PACKAGE_VENDOR "Humanity") -_cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY - "${CMAKE_PROJECT_NAME} built using CMake") +if(CMAKE_PROJECT_DESCRIPTION) + _cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY + "${CMAKE_PROJECT_DESCRIPTION}") +else() + _cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY + "${CMAKE_PROJECT_NAME} built using CMake") +endif() _cpack_set_default(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_ROOT}/Templates/CPack.GenericDescription.txt") diff --git a/Modules/CPackArchive.cmake b/Modules/CPackArchive.cmake new file mode 100644 index 000000000..741fb1fdd --- /dev/null +++ b/Modules/CPackArchive.cmake @@ -0,0 +1,39 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# CPackArchive +# ------------ +# +# Archive CPack generator that supports packaging of sources and binaries in +# different formats: +# +# - 7Z - 7zip - (.7z) +# - TBZ2 (.tar.bz2) +# - TGZ (.tar.gz) +# - TXZ (.tar.xz) +# - TZ (.tar.Z) +# - ZIP (.zip) +# +# Variables specific to CPack Archive generator +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# .. variable:: CPACK_ARCHIVE_FILE_NAME +# CPACK_ARCHIVE__FILE_NAME +# +# Package file name without extension which is added automatically depending +# on the archive format. +# +# * Mandatory : YES +# * Default : ``[-].`` with +# spaces replaced by '-' +# +# .. variable:: CPACK_ARCHIVE_COMPONENT_INSTALL +# +# Enable component packaging for CPackArchive +# +# * Mandatory : NO +# * Default : OFF +# +# If enabled (ON) multiple packages are generated. By default a single package +# containing files of all components is generated. diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake index 188dde3f7..3a10b9930 100644 --- a/Modules/CPackComponent.cmake +++ b/Modules/CPackComponent.cmake @@ -105,7 +105,8 @@ # [DEPENDS comp1 comp2 ... ] # [INSTALL_TYPES type1 type2 ... ] # [DOWNLOADED] -# [ARCHIVE_FILE filename]) +# [ARCHIVE_FILE filename] +# [PLIST filename]) # # # @@ -163,6 +164,9 @@ # a file with some name based on CPACK_PACKAGE_FILE_NAME and the name of # the component. See cpack_configure_downloads for more information. # +# PLIST gives a filename that is passed to pkgbuild with the +# ``--component-plist`` argument when using the productbuild generator. +# # .. command:: cpack_add_component_group # # Describes a group of related CPack installation components. @@ -299,49 +303,17 @@ if(NOT CPackComponent_CMake_INCLUDED) set(CPackComponent_CMake_INCLUDED 1) -# Argument-parsing macro from https://cmake.org/Wiki/CMakeMacroParseArguments -macro(cpack_parse_arguments prefix arg_names option_names) - set(${prefix}_DEFAULT_ARGS) - foreach(arg_name ${arg_names}) - set(${prefix}_${arg_name}) - endforeach() - foreach(option ${option_names}) - set(${prefix}_${option} FALSE) - endforeach() - - set(current_arg_name DEFAULT_ARGS) - set(current_arg_list) - foreach(arg ${ARGN}) - set(larg_names ${arg_names}) - list(FIND larg_names "${arg}" is_arg_name) - if (is_arg_name GREATER -1) - set(${prefix}_${current_arg_name} ${current_arg_list}) - set(current_arg_name ${arg}) - set(current_arg_list) - else () - set(loption_names ${option_names}) - list(FIND loption_names "${arg}" is_option) - if (is_option GREATER -1) - set(${prefix}_${arg} TRUE) - else () - set(current_arg_list ${current_arg_list} ${arg}) - endif () - endif () - endforeach() - set(${prefix}_${current_arg_name} ${current_arg_list}) -endmacro() - # Macro that appends a SET command for the given variable name (var) # to the macro named strvar, but only if the variable named "var" # has been defined. The string will eventually be appended to a CPack # configuration file. macro(cpack_append_variable_set_command var strvar) if (DEFINED ${var}) - set(${strvar} "${${strvar}}set(${var}") + string(APPEND ${strvar} "set(${var}") foreach(APPENDVAL ${${var}}) - set(${strvar} "${${strvar}} ${APPENDVAL}") + string(APPEND ${strvar} " ${APPENDVAL}") endforeach() - set(${strvar} "${${strvar}})\n") + string(APPEND ${strvar} ")\n") endif () endmacro() @@ -353,7 +325,7 @@ macro(cpack_append_string_variable_set_command var strvar) if (DEFINED ${var}) list(LENGTH ${var} CPACK_APP_VALUE_LEN) if(${CPACK_APP_VALUE_LEN} EQUAL 1) - set(${strvar} "${${strvar}}set(${var} \"${${var}}\")\n") + string(APPEND ${strvar} "set(${var} \"${${var}}\")\n") endif() endif () endmacro() @@ -380,7 +352,7 @@ macro(cpack_append_option_set_command var strvar) if (${var}) list(LENGTH ${var} CPACK_APP_VALUE_LEN) if(${CPACK_APP_VALUE_LEN} EQUAL 1) - set(${strvar} "${${strvar}}set(${var} TRUE)\n") + string(APPEND ${strvar} "set(${var} TRUE)\n") endif() endif () endmacro() @@ -388,9 +360,10 @@ endmacro() # Macro that adds a component to the CPack installer macro(cpack_add_component compname) string(TOUPPER ${compname} _CPACK_ADDCOMP_UNAME) - cpack_parse_arguments(CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME} - "DISPLAY_NAME;DESCRIPTION;GROUP;DEPENDS;INSTALL_TYPES;ARCHIVE_FILE" + cmake_parse_arguments(CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME} "HIDDEN;REQUIRED;DISABLED;DOWNLOADED" + "DISPLAY_NAME;DESCRIPTION;GROUP;ARCHIVE_FILE;PLIST" + "DEPENDS;INSTALL_TYPES" ${ARGN} ) @@ -445,6 +418,9 @@ macro(cpack_add_component compname) cpack_append_option_set_command( CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}_DOWNLOADED _CPACK_ADDCOMP_STR) + cpack_append_string_variable_set_command( + CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}_PLIST + _CPACK_ADDCOMP_STR) # Backward compatibility issue. # Write to config iff the macros is used after CPack.cmake has been # included, other it's not necessary because the variables @@ -457,9 +433,10 @@ endmacro() # Macro that adds a component group to the CPack installer macro(cpack_add_component_group grpname) string(TOUPPER ${grpname} _CPACK_ADDGRP_UNAME) - cpack_parse_arguments(CPACK_COMPONENT_GROUP_${_CPACK_ADDGRP_UNAME} - "DISPLAY_NAME;DESCRIPTION;PARENT_GROUP" + cmake_parse_arguments(CPACK_COMPONENT_GROUP_${_CPACK_ADDGRP_UNAME} "EXPANDED;BOLD_TITLE" + "DISPLAY_NAME;DESCRIPTION;PARENT_GROUP" + "" ${ARGN} ) @@ -491,7 +468,8 @@ endmacro() # Macro that adds an installation type to the CPack installer macro(cpack_add_install_type insttype) string(TOUPPER ${insttype} _CPACK_INSTTYPE_UNAME) - cpack_parse_arguments(CPACK_INSTALL_TYPE_${_CPACK_INSTTYPE_UNAME} + cmake_parse_arguments(CPACK_INSTALL_TYPE_${_CPACK_INSTTYPE_UNAME} + "" "DISPLAY_NAME" "" ${ARGN} @@ -514,9 +492,10 @@ macro(cpack_add_install_type insttype) endmacro() macro(cpack_configure_downloads site) - cpack_parse_arguments(CPACK_DOWNLOAD - "UPLOAD_DIRECTORY" + cmake_parse_arguments(CPACK_DOWNLOAD "ALL;ADD_REMOVE;NO_ADD_REMOVE" + "UPLOAD_DIRECTORY" + "" ${ARGN} ) diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index deb724c76..c1cb52f16 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -28,8 +28,59 @@ # and Mac OS X. # # You should also install QtIFW_ to use CPack ``IFW`` generator. -# If you don't use a default path for the installation, please set -# the used path in the variable ``QTIFWDIR``. +# +# Hints +# ^^^^^ +# +# Generally, the CPack ``IFW`` generator automatically finds QtIFW_ tools, +# but if you don't use a default path for installation of the QtIFW_ tools, +# the path may be specified in either a CMake or an environment variable: +# +# .. variable:: CPACK_IFW_ROOT +# +# 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 +# CPack runtime. +# +# .. variable:: QTIFWDIR +# +# An environment variable which specifies the location of the QtIFW_ tool +# suite. +# +# .. note:: +# The specified path should not contain "bin" at the end +# (for example: "D:\\DevTools\\QtIFW2.0.5"). +# +# The :variable:`CPACK_IFW_ROOT` variable has a higher priority and overrides +# the value of the :variable:`QTIFWDIR` variable. +# +# Internationalization +# ^^^^^^^^^^^^^^^^^^^^ +# +# Some variables and command arguments support internationalization via +# CMake script. This is an optional feature. +# +# Installers created by QtIFW_ tools have built-in support for +# internationalization and many phrases are localized to many languages, +# but this does not apply to the description of the your components and groups +# that will be distributed. +# +# Localization of the description of your components and groups is useful for +# users of your installers. +# +# A localized variable or argument can contain a single default value, and a +# set of pairs the name of the locale and the localized value. +# +# For example: +# +# .. code-block:: cmake +# +# set(LOCALIZABLE_VARIABLE "Default value" +# en "English value" +# en_US "American value" +# en_GB "Great Britain value" +# ) # # Variables # ^^^^^^^^^ @@ -197,7 +248,7 @@ # dependent components. # # Tools -# """""""" +# """"" # # .. variable:: CPACK_IFW_FRAMEWORK_VERSION # @@ -207,13 +258,25 @@ # # The path to "binarycreator" command line client. # -# This variable is cached and can be configured user if need. +# This variable is cached and may be configured if needed. # # .. variable:: CPACK_IFW_REPOGEN_EXECUTABLE # # The path to "repogen" command line client. # -# This variable is cached and can be configured user if need. +# This variable is cached and may be configured if needed. +# +# .. variable:: CPACK_IFW_INSTALLERBASE_EXECUTABLE +# +# The path to "installerbase" installer executable base. +# +# This variable is cached and may be configured if needed. +# +# .. variable:: CPACK_IFW_DEVTOOL_EXECUTABLE +# +# The path to "devtool" command line client. +# +# This variable is cached and may be configured if needed. # # Commands # ^^^^^^^^^ @@ -229,8 +292,8 @@ # cpack_ifw_configure_component( [COMMON] [ESSENTIAL] [VIRTUAL] # [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS] # [NAME ] -# [DISPLAY_NAME ] -# [DESCRIPTION ] +# [DISPLAY_NAME ] # Note: Internationalization supported +# [DESCRIPTION ] # Note: Internationalization supported # [UPDATE_TEXT ] # [VERSION ] # [RELEASE_DATE ] @@ -332,8 +395,8 @@ # cpack_ifw_configure_component_group( [VIRTUAL] # [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS] # [NAME ] -# [DISPLAY_NAME ] -# [DESCRIPTION ] +# [DISPLAY_NAME ] # Note: Internationalization supported +# [DESCRIPTION ] # Note: Internationalization supported # [UPDATE_TEXT ] # [VERSION ] # [RELEASE_DATE ] @@ -510,8 +573,9 @@ # # cpack_add_component(myapp # DISPLAY_NAME "MyApp" -# DESCRIPTION "My Application") +# DESCRIPTION "My Application") # Default description # cpack_ifw_configure_component(myapp +# DESCRIPTION ru_RU "Мое Приложение" # Localized description # VERSION "1.2.3" # Version of component # SCRIPT "operations.qs") # cpack_add_component(mybigplugin @@ -568,7 +632,7 @@ # Default path -foreach(_CPACK_IFW_PATH_VAR "QTIFWDIR" "QTDIR") +foreach(_CPACK_IFW_PATH_VAR "CPACK_IFW_ROOT" "QTIFWDIR" "QTDIR") if(DEFINED ${_CPACK_IFW_PATH_VAR} AND NOT "${${_CPACK_IFW_PATH_VAR}}" STREQUAL "") list(APPEND _CPACK_IFW_PATHS "${${_CPACK_IFW_PATH_VAR}}") @@ -597,6 +661,10 @@ set(_CPACK_IFW_PREFIXES "QtIFW-") set(_CPACK_IFW_VERSIONS + "3.1" + "3.1.0" + "3.0" + "3.0.0" "2.3" "2.3.0" "2.2" @@ -604,6 +672,7 @@ set(_CPACK_IFW_VERSIONS "2.1" "2.1.0" "2.0" + "2.0.5" "2.0.3" "2.0.2" "2.0.1" @@ -676,21 +745,58 @@ set(CPackIFW_CMake_INCLUDED 1) # Framework version #============================================================================= -if(CPACK_IFW_INSTALLERBASE_EXECUTABLE AND CPACK_IFW_DEVTOOL_EXECUTABLE) - execute_process(COMMAND - "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}" --framework-version - OUTPUT_VARIABLE CPACK_IFW_FRAMEWORK_VERSION) - if(CPACK_IFW_FRAMEWORK_VERSION) - string(REPLACE " " "" - CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}") - string(REPLACE "\t" "" - CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}") - string(REPLACE "\n" "" - CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}") - if(CPACK_IFW_VERBOSE) - message(STATUS "Found QtIFW ${CPACK_IFW_FRAMEWORK_VERSION} version") +set(CPACK_IFW_FRAMEWORK_VERSION_FORCED "" + CACHE STRING "The forced version of used QtIFW tools") +mark_as_advanced(CPACK_IFW_FRAMEWORK_VERSION_FORCED) +set(CPACK_IFW_FRAMEWORK_VERSION_TIMEOUT 1 + CACHE STRING "The timeout to return QtIFW framework version string from \"installerbase\" executable") +mark_as_advanced(CPACK_IFW_FRAMEWORK_VERSION_TIMEOUT) +if(CPACK_IFW_INSTALLERBASE_EXECUTABLE AND NOT CPACK_IFW_FRAMEWORK_VERSION_FORCED) + set(CPACK_IFW_FRAMEWORK_VERSION) + # Invoke version from "installerbase" executable + foreach(_ifw_version_argument --framework-version --version) + if(NOT CPACK_IFW_FRAMEWORK_VERSION) + execute_process(COMMAND + "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}" ${_ifw_version_argument} + TIMEOUT ${CPACK_IFW_FRAMEWORK_VERSION_TIMEOUT} + RESULT_VARIABLE CPACK_IFW_FRAMEWORK_VERSION_RESULT + OUTPUT_VARIABLE CPACK_IFW_FRAMEWORK_VERSION_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ENCODING UTF8) + if(NOT CPACK_IFW_FRAMEWORK_VERSION_RESULT AND CPACK_IFW_FRAMEWORK_VERSION_OUTPUT) + string(REGEX MATCH "[0-9]+(\\.[0-9]+)*" + CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION_OUTPUT}") + if(CPACK_IFW_FRAMEWORK_VERSION) + if("${_ifw_version_argument}" STREQUAL "--framework-version") + set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "INSTALLERBASE_FRAMEWORK_VERSION") + elseif("${_ifw_version_argument}" STREQUAL "--version") + set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "INSTALLERBASE_FRAMEWORK_VERSION") + endif() + endif() + endif() + endif() + endforeach() + # Finaly try to get version from executable path + if(NOT CPACK_IFW_FRAMEWORK_VERSION) + string(REGEX MATCH "[0-9]+(\\.[0-9]+)*" + CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}") + if(CPACK_IFW_FRAMEWORK_VERSION) + set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "INSTALLERBASE_PATH") endif() endif() +elseif(CPACK_IFW_FRAMEWORK_VERSION_FORCED) + set(CPACK_IFW_FRAMEWORK_VERSION ${CPACK_IFW_FRAMEWORK_VERSION_FORCED}) + set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "FORCED") +endif() +if(CPACK_IFW_VERBOSE) + if(CPACK_IFW_FRAMEWORK_VERSION AND CPACK_IFW_FRAMEWORK_VERSION_FORCED) + message(STATUS "Found QtIFW ${CPACK_IFW_FRAMEWORK_VERSION} (forced) version") + elseif(CPACK_IFW_FRAMEWORK_VERSION) + message(STATUS "Found QtIFW ${CPACK_IFW_FRAMEWORK_VERSION} version") + endif() +endif() +if(CPACK_IFW_INSTALLERBASE_EXECUTABLE AND NOT CPACK_IFW_FRAMEWORK_VERSION) + message(WARNING "Could not detect QtIFW tools version. Set used version to variable \"CPACK_IFW_FRAMEWORK_VERSION_FORCED\" manualy.") endif() #============================================================================= @@ -757,8 +863,8 @@ macro(cpack_ifw_configure_component compname) string(TOUPPER ${compname} _CPACK_IFWCOMP_UNAME) set(_IFW_OPT COMMON ESSENTIAL VIRTUAL FORCED_INSTALLATION REQUIRES_ADMIN_RIGHTS) - set(_IFW_ARGS NAME DISPLAY_NAME DESCRIPTION VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT) - set(_IFW_MULTI_ARGS DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS) + set(_IFW_ARGS NAME VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT) + set(_IFW_MULTI_ARGS DISPLAY_NAME DESCRIPTION DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS) cmake_parse_arguments(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN}) _cpack_ifw_resolve_script(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_SCRIPT) @@ -798,8 +904,8 @@ macro(cpack_ifw_configure_component_group grpname) string(TOUPPER ${grpname} _CPACK_IFWGRP_UNAME) set(_IFW_OPT VIRTUAL FORCED_INSTALLATION REQUIRES_ADMIN_RIGHTS) - set(_IFW_ARGS NAME DISPLAY_NAME DESCRIPTION VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT) - set(_IFW_MULTI_ARGS DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS) + set(_IFW_ARGS NAME VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT) + set(_IFW_MULTI_ARGS DISPLAY_NAME DESCRIPTION DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS) cmake_parse_arguments(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN}) _cpack_ifw_resolve_script(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_SCRIPT) diff --git a/Modules/CPackProductBuild.cmake b/Modules/CPackProductBuild.cmake index d545d3e04..4779b95b9 100644 --- a/Modules/CPackProductBuild.cmake +++ b/Modules/CPackProductBuild.cmake @@ -46,3 +46,11 @@ # # Specify a specific keychain to search for the signing identity. # +# +# .. variable:: CPACK_PRODUCTBUILD_RESOURCES_DIR +# +# 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. diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake index e905bc612..fa2a6e409 100644 --- a/Modules/CPackRPM.cmake +++ b/Modules/CPackRPM.cmake @@ -817,6 +817,30 @@ # is set then :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is automatically set to # ``ON`` when :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` is set. # +# .. variable:: CPACK_RPM_DEBUGINFO_FILE_NAME +# CPACK_RPM__DEBUGINFO_FILE_NAME +# +# Debuginfo package file name. +# +# * Mandatory : NO +# * Default : rpmbuild tool generated package file name +# +# Alternatively provided debuginfo package file name must end with ``.rpm`` +# suffix and should differ from file names of other generated packages. +# +# Variable may contain ``@cpack_component@`` placeholder which will be +# replaced by component name if component packaging is enabled otherwise it +# deletes the placeholder. +# +# Setting the variable to ``RPM-DEFAULT`` may be used to explicitly set +# filename generation to default. +# +# .. note:: +# +# :variable:`CPACK_RPM_FILE_NAME` also supports rpmbuild tool generated package +# file name - disabled by default but can be enabled by setting the variable to +# ``RPM-DEFAULT``. +# # Packaging of sources (SRPM) # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ # @@ -887,6 +911,19 @@ # # * Mandatory : YES # * Default : "/" +# +# .. VARIABLE:: CPACK_RPM_BUILDREQUIRES +# +# List of source rpm build dependencies. +# +# * Mandatory : NO +# * Default : - +# +# May be used to set source RPM build dependencies (BuildRequires). Note that +# you must enclose the complete build requirements string between quotes, for +# example:: +# +# set(CPACK_RPM_BUILDREQUIRES "python >= 2.5.0, cmake >= 2.8") # Author: Eric Noulard with the help of Alexander Neundorf. @@ -950,10 +987,20 @@ function(cpack_rpm_prepare_relocation_paths) foreach(RELOCATION_PATH ${RPM_RELOCATION_PATHS}) if(IS_ABSOLUTE "${RELOCATION_PATH}") set(PREPARED_RELOCATION_PATH "${RELOCATION_PATH}") + elseif(PATH_PREFIX STREQUAL "/") + # don't prefix path with a second slash as "//" is treated as network path + # by get_filename_component() so it remains in path even inside rpm + # package where it may cause problems with relocation + set(PREPARED_RELOCATION_PATH "/${RELOCATION_PATH}") else() set(PREPARED_RELOCATION_PATH "${PATH_PREFIX}/${RELOCATION_PATH}") endif() + # handle cases where path contains extra slashes (e.g. /a//b/ instead of + # /a/b) + get_filename_component(PREPARED_RELOCATION_PATH + "${PREPARED_RELOCATION_PATH}" ABSOLUTE) + if(EXISTS "${WDIR}/${PREPARED_RELOCATION_PATH}") string(APPEND TMP_RPM_PREFIXES "Prefix: ${PREPARED_RELOCATION_PATH}\n") list(APPEND RPM_USED_PACKAGE_PREFIXES "${PREPARED_RELOCATION_PATH}") @@ -1036,7 +1083,7 @@ function(cpack_rpm_prepare_content_list) endif() if(NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST) - set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/include) + set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/libx32 /usr/include) if(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION) if(CPACK_RPM_PACKAGE_DEBUG) message("CPackRPM:Debug: Adding ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION} to builtin omit list.") @@ -2122,6 +2169,11 @@ function(cpack_rpm_generate_package) set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/usr/src/debug/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}") endif() + # handle cases where path contains extra slashes (e.g. /a//b/ instead of + # /a/b) + get_filename_component(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX + "${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}" ABSOLUTE) + if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND GENERATE_SPEC_PARTS) file(WRITE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_COMPONENT}.files" "${CPACK_RPM_INSTALL_FILES}") @@ -2625,11 +2677,27 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT unset(expected_filenames_) unset(filenames_) if(CPACK_RPM_DEBUGINFO_PACKAGE AND NOT CPACK_RPM_FILE_NAME STREQUAL "RPM-DEFAULT") - string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" efn_) - list(APPEND expected_filenames_ "${efn_}") + list(APPEND expected_filenames_ + "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm") list(APPEND filenames_ "${CPACK_RPM_FILE_NAME}") endif() + if(CPACK_RPM_DEBUGINFO_PACKAGE) + cpack_rpm_variable_fallback("CPACK_RPM_DEBUGINFO_FILE_NAME" + "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_FILE_NAME" + "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_FILE_NAME" + "CPACK_RPM_DEBUGINFO_FILE_NAME") + + if(CPACK_RPM_DEBUGINFO_FILE_NAME AND + NOT CPACK_RPM_DEBUGINFO_FILE_NAME STREQUAL "RPM-DEFAULT") + list(APPEND expected_filenames_ + "${CPACK_RPM_PACKAGE_NAME}-debuginfo-${CPACK_PACKAGE_VERSION}.*\\.rpm") + string(REPLACE "@cpack_component@" "${CPACK_RPM_PACKAGE_COMPONENT}" + CPACK_RPM_DEBUGINFO_FILE_NAME "${CPACK_RPM_DEBUGINFO_FILE_NAME}") + list(APPEND filenames_ "${CPACK_RPM_DEBUGINFO_FILE_NAME}") + endif() + endif() + # check if other files have to be renamed file(GLOB rename_files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.rpm_name") if(rename_files_) diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 0f2278f84..1dc37d415 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -243,20 +243,20 @@ # # .. variable:: CPACK_WIX_ROOT_FEATURE_TITLE # -# Sets the name of the root install feature in the WIX installer. Same as -# CPACK_COMPONENT__DISPLAY_NAME for components. +# Sets the name of the root install feature in the WIX installer. Same as +# CPACK_COMPONENT__DISPLAY_NAME for components. # # .. variable:: CPACK_WIX_ROOT_FEATURE_DESCRIPTION # -# Sets the description of the root install feature in the WIX installer. Same as -# CPACK_COMPONENT__DESCRIPTION for components. +# Sets the description of the root install feature in the WIX installer. Same as +# CPACK_COMPONENT__DESCRIPTION for components. # # .. variable:: CPACK_WIX_SKIP_PROGRAM_FOLDER # -# 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 -# ProgramFiles or ProgramFiles64. +# 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 +# ProgramFiles or ProgramFiles64. # # .. note:: # Installers created with this feature do not take differences @@ -268,6 +268,25 @@ # follow the localization or convention of the system on which the # installation is performed. # +# .. variable:: CPACK_WIX_ROOT_FOLDER_ID +# +# 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. +# In 32-bit builds the token will expand empty while in 64-bit builds +# it will expand to ``64``. +# +# When unset generated installers will default installing to +# ``ProgramFiles<64>Folder``. +# +# .. variable:: CPACK_WIX_ROOT +# +# This variable can optionally be set to the root directory +# of a custom WiX Toolset installation. +# +# When unspecified CPack will try to locate a WiX Toolset +# installation via the ``WIX`` environment variable instead. +# if(NOT CPACK_WIX_ROOT) file(TO_CMAKE_PATH "$ENV{WIX}" CPACK_WIX_ROOT) diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake index 7aeb5bedb..9370596a8 100644 --- a/Modules/CTest.cmake +++ b/Modules/CTest.cmake @@ -54,15 +54,11 @@ in the ``CTestConfig.cmake`` file. option(BUILD_TESTING "Build the testing tree." ON) # function to turn generator name into a version string -# like vs7 vs71 vs8 vs9 +# like vs8 vs9 function(GET_VS_VERSION_STRING generator var) string(REGEX REPLACE "Visual Studio ([0-9][0-9]?)($|.*)" "\\1" NUMBER "${generator}") - if("${generator}" MATCHES "Visual Studio 7 .NET 2003") - set(ver_string "vs71") - else() set(ver_string "vs${NUMBER}") - endif() set(${var} ${ver_string} PARENT_SCOPE) endfunction() diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake new file mode 100644 index 000000000..e04ab1c54 --- /dev/null +++ b/Modules/CheckIPOSupported.cmake @@ -0,0 +1,232 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +CheckIPOSupported +----------------- + +Check whether the compiler supports an interprocedural optimization (IPO/LTO). +Use this before enabling the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target +property. + +.. command:: check_ipo_supported + + :: + + check_ipo_supported([RESULT ] [OUTPUT ] + [LANGUAGES ...]) + + Options are: + + ``RESULT `` + Set ```` variable to ``YES`` if IPO is supported by the + compiler and ``NO`` otherwise. If this option is not given then + the command will issue a fatal error if IPO is not supported. + ``OUTPUT `` + Set ```` variable with details about any error. + ``LANGUAGES ...`` + Specify languages whose compilers to check. + Languages ``C`` and ``CXX`` are supported. + +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. + +Examples +^^^^^^^^ + +.. code-block:: cmake + + check_ipo_supported() # fatal error if IPO is not supported + set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + +.. code-block:: cmake + + # Optional IPO. Do not use IPO if it's not supported by compiler. + check_ipo_supported(RESULT result OUTPUT output) + if(result) + set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(WARNING "IPO is not supported: ${output}") + endif() + +#]=======================================================================] + +include(CMakeParseArguments) # cmake_parse_arguments + +# X_RESULT - name of the final result variable +# X_OUTPUT - name of the variable with information about error +macro(_ipo_not_supported output) + string(COMPARE EQUAL "${X_RESULT}" "" is_empty) + if(is_empty) + message(FATAL_ERROR "IPO is not supported (${output}).") + endif() + + set("${X_RESULT}" NO PARENT_SCOPE) + set("${X_OUTPUT}" "${output}" PARENT_SCOPE) +endmacro() + +# Run IPO/LTO test +macro(_ipo_run_language_check language) + set(testdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/_CMakeLTOTest-${language}") + + file(REMOVE_RECURSE "${testdir}") + file(MAKE_DIRECTORY "${testdir}") + + set(bindir "${testdir}/bin") + set(srcdir "${testdir}/src") + + file(MAKE_DIRECTORY "${bindir}") + file(MAKE_DIRECTORY "${srcdir}") + + set(TRY_COMPILE_PROJECT_NAME "lto-test") + + set(try_compile_src "${CMAKE_ROOT}/Modules/CheckIPOSupported") + + # Use: + # * TRY_COMPILE_PROJECT_NAME + # * CMAKE_VERSION + configure_file( + "${try_compile_src}/CMakeLists-${language}.txt.in" + "${srcdir}/CMakeLists.txt" + @ONLY + ) + + string(COMPARE EQUAL "${language}" "C" is_c) + string(COMPARE EQUAL "${language}" "CXX" is_cxx) + string(COMPARE EQUAL "${language}" "Fortran" is_fortran) + + if(is_c) + set(copy_sources foo.c main.c) + elseif(is_cxx) + set(copy_sources foo.cpp main.cpp) + elseif(is_fortran) + set(copy_sources foo.f main.f) + else() + message(FATAL_ERROR "Language not supported") + endif() + + foreach(x ${copy_sources}) + configure_file( + "${try_compile_src}/${x}" + "${srcdir}/${x}" + COPYONLY + ) + endforeach() + + try_compile( + result + "${bindir}" + "${srcdir}" + "${TRY_COMPILE_PROJECT_NAME}" + CMAKE_FLAGS + "-DCMAKE_VERBOSE_MAKEFILE=ON" + "-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON" + OUTPUT_VARIABLE output + ) + + if(NOT result) + _ipo_not_supported("${output}") + return() + endif() +endmacro() + +function(check_ipo_supported) + cmake_policy(GET CMP0069 x) + + string(COMPARE EQUAL "${x}" "" not_set) + if(not_set) + message(FATAL_ERROR "Policy CMP0069 is not set") + endif() + + string(COMPARE EQUAL "${x}" "OLD" is_old) + if(is_old) + message(FATAL_ERROR "Policy CMP0069 set to OLD") + endif() + + set(optional) + set(one RESULT OUTPUT) + set(multiple LANGUAGES) + + # Introduce: + # * X_RESULT + # * X_OUTPUT + # * X_LANGUAGES + cmake_parse_arguments(X "${optional}" "${one}" "${multiple}" "${ARGV}") + + string(COMPARE NOTEQUAL "${X_UNPARSED_ARGUMENTS}" "" has_unparsed) + if(has_unparsed) + message(FATAL_ERROR "Unparsed arguments: ${X_UNPARSED_ARGUMENTS}") + endif() + + string(COMPARE EQUAL "${X_LANGUAGES}" "" no_languages) + if(no_languages) + # User did not set any languages, use defaults + get_property(enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES) + string(COMPARE EQUAL "${enabled_languages}" "" no_languages) + if(no_languages) + _ipo_not_supported( + "no languages found in ENABLED_LANGUAGES global property" + ) + return() + endif() + + set(languages "") + list(FIND enabled_languages "CXX" result) + if(NOT result EQUAL -1) + list(APPEND languages "CXX") + endif() + + list(FIND enabled_languages "C" result) + if(NOT result EQUAL -1) + list(APPEND languages "C") + endif() + + list(FIND enabled_languages "Fortran" result) + if(NOT result EQUAL -1) + list(APPEND languages "Fortran") + endif() + + string(COMPARE EQUAL "${languages}" "" no_languages) + if(no_languages) + _ipo_not_supported( + "no C/CXX/Fortran languages found in ENABLED_LANGUAGES global property" + ) + return() + endif() + else() + set(languages "${X_LANGUAGES}") + + set(unsupported_languages "${languages}") + list(REMOVE_ITEM unsupported_languages "C" "CXX" "Fortran") + string(COMPARE NOTEQUAL "${unsupported_languages}" "" has_unsupported) + if(has_unsupported) + _ipo_not_supported( + "language(s) '${unsupported_languages}' not supported" + ) + return() + endif() + endif() + + foreach(lang ${languages}) + if(NOT _CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE) + _ipo_not_supported("CMake doesn't support IPO for current ${lang} compiler") + return() + endif() + + if(NOT _CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER) + _ipo_not_supported("${lang} compiler doesn't support IPO") + return() + endif() + endforeach() + + if(CMAKE_GENERATOR MATCHES "^Visual Studio ") + _ipo_not_supported("CMake doesn't support IPO for current generator") + return() + endif() + + foreach(x ${languages}) + _ipo_run_language_check(${x}) + endforeach() + + set("${X_RESULT}" YES PARENT_SCOPE) +endfunction() diff --git a/Modules/CheckIPOSupported/CMakeLists-C.txt.in b/Modules/CheckIPOSupported/CMakeLists-C.txt.in new file mode 100644 index 000000000..5a3b8ee32 --- /dev/null +++ b/Modules/CheckIPOSupported/CMakeLists-C.txt.in @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION "@CMAKE_VERSION@") +project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES C) + +cmake_policy(SET CMP0069 NEW) + +add_library(foo foo.c) +add_executable(boo main.c) +target_link_libraries(boo PUBLIC foo) diff --git a/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in new file mode 100644 index 000000000..30993fa40 --- /dev/null +++ b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION "@CMAKE_VERSION@") +project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES CXX) + +cmake_policy(SET CMP0069 NEW) + +add_library(foo foo.cpp) +add_executable(boo main.cpp) +target_link_libraries(boo PUBLIC foo) diff --git a/Modules/CheckIPOSupported/CMakeLists-Fortran.txt.in b/Modules/CheckIPOSupported/CMakeLists-Fortran.txt.in new file mode 100644 index 000000000..9fab0772f --- /dev/null +++ b/Modules/CheckIPOSupported/CMakeLists-Fortran.txt.in @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION "@CMAKE_VERSION@") +project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES Fortran) + +cmake_policy(SET CMP0069 NEW) + +add_library(foo foo.f) +add_executable(boo main.f) +target_link_libraries(boo PUBLIC foo) diff --git a/Modules/CheckIPOSupported/foo.c b/Modules/CheckIPOSupported/foo.c new file mode 100644 index 000000000..1e5659789 --- /dev/null +++ b/Modules/CheckIPOSupported/foo.c @@ -0,0 +1,4 @@ +int foo() +{ + return 0x42; +} diff --git a/Modules/CheckIPOSupported/foo.cpp b/Modules/CheckIPOSupported/foo.cpp new file mode 100644 index 000000000..1e5659789 --- /dev/null +++ b/Modules/CheckIPOSupported/foo.cpp @@ -0,0 +1,4 @@ +int foo() +{ + return 0x42; +} diff --git a/Modules/CheckIPOSupported/foo.f b/Modules/CheckIPOSupported/foo.f new file mode 100644 index 000000000..945d2d559 --- /dev/null +++ b/Modules/CheckIPOSupported/foo.f @@ -0,0 +1,2 @@ + SUBROUTINE FOO + END diff --git a/Modules/CheckIPOSupported/main.c b/Modules/CheckIPOSupported/main.c new file mode 100644 index 000000000..5be0864ee --- /dev/null +++ b/Modules/CheckIPOSupported/main.c @@ -0,0 +1,6 @@ +int foo(); + +int main() +{ + return foo(); +} diff --git a/Modules/CheckIPOSupported/main.cpp b/Modules/CheckIPOSupported/main.cpp new file mode 100644 index 000000000..5be0864ee --- /dev/null +++ b/Modules/CheckIPOSupported/main.cpp @@ -0,0 +1,6 @@ +int foo(); + +int main() +{ + return foo(); +} diff --git a/Modules/CheckIPOSupported/main.f b/Modules/CheckIPOSupported/main.f new file mode 100644 index 000000000..9d1de9f8a --- /dev/null +++ b/Modules/CheckIPOSupported/main.f @@ -0,0 +1,3 @@ + PROGRAM BOO + CALL FOO() + END diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake index 6b4a9e424..1ea91d2d0 100644 --- a/Modules/CheckLanguage.cmake +++ b/Modules/CheckLanguage.cmake @@ -46,6 +46,8 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" execute_process( WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang} COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR} + -A "${CMAKE_GENERATOR_PLATFORM}" + -T "${CMAKE_GENERATOR_TOOLSET}" OUTPUT_VARIABLE output ERROR_VARIABLE output RESULT_VARIABLE result diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index 8fecc57da..6f1afcfda 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -1,38 +1,47 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -#.rst: -# CheckSymbolExists -# ----------------- -# -# Check if a symbol exists as a function, variable, or macro -# -# CHECK_SYMBOL_EXISTS( ) -# -# Check that the is available after including given header -# and store the result in a . Specify the list of -# files in one argument as a semicolon-separated list. -# will be created as an internal cache variable. -# -# If the header files define the symbol as a macro it is considered -# available and assumed to work. If the header files declare the symbol -# as a function or variable then the symbol must also be available for -# linking. If the symbol is a type or enum value it will not be -# recognized (consider using CheckTypeSize or CheckCSourceCompiles). If -# the check needs to be done in C++, consider using -# CHECK_CXX_SYMBOL_EXISTS(), which does the same as -# CHECK_SYMBOL_EXISTS(), but in C++. -# -# 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_LIBRARIES = list of libraries to link -# CMAKE_REQUIRED_QUIET = execute quietly without messages +#[=======================================================================[.rst: +CheckSymbolExists +----------------- + +Provides a macro to check if a symbol exists as a function, variable, +or macro in ``C``. + +.. command:: check_symbol_exists + + :: + + check_symbol_exists( ) + + Check that the ```` is available after including given header + ```` and store the result in a ````. Specify the list + of files in one argument as a semicolon-separated list. + ```` will be created as an internal cache variable. + +If the header files define the symbol as a macro it is considered +available and assumed to work. If the header files declare the symbol +as a function or variable then the symbol must also be available for +linking (so intrinsics may not be detected). +If the symbol is a type, enum value, or intrinsic it will not be recognized +(consider using :module:`CheckTypeSize` or :module:`CheckCSourceCompiles`). +If the check needs to be done in C++, consider using +:module:`CheckCXXSymbolExists` instead. + +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_LIBRARIES`` + list of libraries to link +``CMAKE_REQUIRED_QUIET`` + execute quietly without messages +#]=======================================================================] macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE) if(CMAKE_C_COMPILER_LOADED) diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake index 4b3e223ec..fcf1df740 100644 --- a/Modules/CheckTypeSize.cmake +++ b/Modules/CheckTypeSize.cmake @@ -247,10 +247,10 @@ macro(CHECK_TYPE_SIZE TYPE VARIABLE) set(${VARIABLE}_CODE) set(_if if) foreach(key ${${VARIABLE}_KEYS}) - set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#${_if} defined(${key})\n# define ${VARIABLE} ${${VARIABLE}-${key}}\n") + string(APPEND ${VARIABLE}_CODE "#${_if} defined(${key})\n# define ${VARIABLE} ${${VARIABLE}-${key}}\n") set(_if elif) endforeach() - set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#else\n# error ${VARIABLE} unknown\n#endif") + string(APPEND ${VARIABLE}_CODE "#else\n# error ${VARIABLE} unknown\n#endif") set(_if) elseif(${VARIABLE}) set(${VARIABLE}_CODE "#define ${VARIABLE} ${${VARIABLE}}") diff --git a/Modules/Compiler/AppleClang-C.cmake b/Modules/Compiler/AppleClang-C.cmake index f874e74e9..a48adec92 100644 --- a/Modules/Compiler/AppleClang-C.cmake +++ b/Modules/Compiler/AppleClang-C.cmake @@ -12,29 +12,4 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0) - if (NOT CMAKE_C_COMPILER_FORCED) - if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") - endif() - set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - set(CMAKE_C_STANDARD_DEFAULT 99) - endif() -endif() - -macro(cmake_record_c_compile_features) - set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0) - if (_result EQUAL 0) - _record_compiler_features_c(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_c(99) - endif() - if (_result EQUAL 0) - _record_compiler_features_c(90) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(C 4.0 99) diff --git a/Modules/Compiler/AppleClang-CXX.cmake b/Modules/Compiler/AppleClang-CXX.cmake index ee900aed0..e5fd64721 100644 --- a/Modules/Compiler/AppleClang-CXX.cmake +++ b/Modules/Compiler/AppleClang-CXX.cmake @@ -27,33 +27,4 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.1) set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) - if (NOT CMAKE_CXX_COMPILER_FORCED) - if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}") - endif() - set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - set(CMAKE_CXX_STANDARD_DEFAULT 98) - endif() -endif() - - -macro(cmake_record_cxx_compile_features) - set(_result 0) - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) - if(_result EQUAL 0 AND CMAKE_CXX17_STANDARD_COMPILE_OPTION) - _record_compiler_features_cxx(17) - endif() - if(_result EQUAL 0 AND CMAKE_CXX14_STANDARD_COMPILE_OPTION) - _record_compiler_features_cxx(14) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(98) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(CXX 4.0 98) diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake new file mode 100644 index 000000000..684fd30cb --- /dev/null +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -0,0 +1,93 @@ +# 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 and compilers; use include guard +if (__COMPILER_CMAKE_COMMON_COMPILER_MACROS) + return() +endif () +set(__COMPILER_CMAKE_COMMON_COMPILER_MACROS 1) + + +# Check that a compiler's language standard is properly detected +# Parameters: +# lang - Language to check +# stdver1 - Minimum version to set a given default for +# std1 - Default to use for compiler ver >= stdver1 +# stdverN - Minimum version to set a given default for +# stdN - Default to use for compiler ver >= stdverN +# +# The order of stdverN stdN pairs passed as arguments is expected to be in +# monotonically increasing version order. +# +# Note: +# This macro can be called with multiple version / std pairs to convey that +# newer compiler versions may use a newer standard default. +# +# Example: +# To specify that compiler version 6.1 and newer defaults to C++11 while +# 4.8 <= ver < 6.1 default to C++98, you would call: +# +# __compiler_check_default_language_standard(CXX 4.8 98 6.1 11) +# +macro(__compiler_check_default_language_standard lang stdver1 std1) + set(__std_ver_pairs "${stdver1};${std1};${ARGN}") + string(REGEX REPLACE " *; *" " " __std_ver_pairs "${__std_ver_pairs}") + string(REGEX MATCHALL "[^ ]+ [^ ]+" __std_ver_pairs "${__std_ver_pairs}") + + # If the compiler version is below the threshold of even having CMake + # support for language standards, then don't bother. + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "${stdver1}") + if (NOT CMAKE_${lang}_COMPILER_FORCED) + if (NOT CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT) + message(FATAL_ERROR "CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_${lang}_COMPILER_ID} (${CMAKE_${lang}_COMPILER}) version ${CMAKE_${lang}_COMPILER_VERSION}") + endif () + set(CMAKE_${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}) + else () + list(REVERSE __std_ver_pairs) + foreach (__std_ver_pair IN LISTS __std_ver_pairs) + string(REGEX MATCH "([^ ]+) (.+)" __std_ver_pair "${__std_ver_pair}") + set(__stdver ${CMAKE_MATCH_1}) + set(__std ${CMAKE_MATCH_2}) + if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL __stdver AND + NOT DEFINED CMAKE_${lang}_STANDARD_DEFAULT) + # Compiler id was forced so just guess the default standard level. + set(CMAKE_${lang}_STANDARD_DEFAULT ${__std}) + endif () + unset(__std) + unset(__stdver) + endforeach () + endif () + endif () + unset(__std_ver_pairs) +endmacro() + +# Define to allow compile features to be automatically determined +macro(cmake_record_c_compile_features) + set(_result 0) + if(_result EQUAL 0 AND DEFINED CMAKE_C11_STANDARD_COMPILE_OPTION) + _record_compiler_features_c(11) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_C99_STANDARD_COMPILE_OPTION) + _record_compiler_features_c(99) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_C90_STANDARD_COMPILE_OPTION) + _record_compiler_features_c(90) + endif() +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_CXX17_STANDARD_COMPILE_OPTION) + _record_compiler_features_cxx(17) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_CXX14_STANDARD_COMPILE_OPTION) + _record_compiler_features_cxx(14) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_CXX11_STANDARD_COMPILE_OPTION) + _record_compiler_features_cxx(11) + endif() + if(_result EQUAL 0 AND DEFINED CMAKE_CXX98_STANDARD_COMPILE_OPTION) + _record_compiler_features_cxx(98) + endif() +endmacro() diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index bcd921870..b881e2b03 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -17,33 +17,4 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) - if (NOT CMAKE_C_COMPILER_FORCED) - if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") - endif() - set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) - set(CMAKE_C_STANDARD_DEFAULT 11) - else() - set(CMAKE_C_STANDARD_DEFAULT 99) - endif() - endif() -endif() - -macro(cmake_record_c_compile_features) - set(_result 0) - if (UNIX AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) - if (_result EQUAL 0) - _record_compiler_features_c(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_c(99) - endif() - if (_result EQUAL 0) - _record_compiler_features_c(90) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(C 3.4 99 3.6 11) diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index 8ed3695a6..d3707eed8 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -36,32 +36,4 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1) - if (NOT CMAKE_CXX_COMPILER_FORCED) - if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}") - endif() - set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - set(CMAKE_CXX_STANDARD_DEFAULT 98) - endif() -endif() - -macro(cmake_record_cxx_compile_features) - set(_result 0) - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1) - if(_result EQUAL 0 AND CMAKE_CXX17_STANDARD_COMPILE_OPTION) - _record_compiler_features_cxx(17) - endif() - if(_result EQUAL 0 AND CMAKE_CXX14_STANDARD_COMPILE_OPTION) - _record_compiler_features_cxx(14) - endif() - if (_result EQUAL 0 AND CMAKE_CXX11_STANDARD_COMPILE_OPTION) - _record_compiler_features_cxx(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(98) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(CXX 2.1 98) diff --git a/Modules/Compiler/Clang-FindBinUtils.cmake b/Modules/Compiler/Clang-FindBinUtils.cmake new file mode 100644 index 000000000..e2822a1c6 --- /dev/null +++ b/Modules/Compiler/Clang-FindBinUtils.cmake @@ -0,0 +1,27 @@ +if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") + message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") +endif() + +# Try to find tools in the same directory as Clang itself +get_filename_component(__clang_hint_1 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" REALPATH) +get_filename_component(__clang_hint_1 "${__clang_hint_1}" DIRECTORY) + +get_filename_component(__clang_hint_2 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) + +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" + HINTS ${__clang_hints} + DOC "LLVM archiver" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR) + +# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ranlib.1.html +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib" + HINTS ${__clang_hints} + DOC "Generate index for LLVM archive" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB) diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index 96263fc54..7d476f965 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -8,6 +8,8 @@ if(__COMPILER_CLANG) endif() set(__COMPILER_CLANG 1) +include(Compiler/CMakeCommonCompilerMacros) + if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") macro(__compiler_clang lang) @@ -27,5 +29,55 @@ else() set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "--target=") set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=") endif() + + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + + string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "AppleClang" __is_apple_clang) + + # '-flto=thin' available since Clang 3.9 and Xcode 8 + # * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm + # * https://trac.macports.org/wiki/XcodeVersionInfo + set(_CMAKE_LTO_THIN TRUE) + if(__is_apple_clang) + if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 8.0) + set(_CMAKE_LTO_THIN FALSE) + endif() + else() + if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9) + set(_CMAKE_LTO_THIN FALSE) + endif() + endif() + + if(_CMAKE_LTO_THIN) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin") + else() + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto") + endif() + + if(ANDROID) + # https://github.com/android-ndk/ndk/issues/242 + set(CMAKE_${lang}_LINK_OPTIONS_IPO "-fuse-ld=gold") + endif() + + if(ANDROID OR __is_apple_clang) + set(__ar "${CMAKE_AR}") + set(__ranlib "${CMAKE_RANLIB}") + else() + set(__ar "${CMAKE_${lang}_COMPILER_AR}") + set(__ranlib "${CMAKE_${lang}_COMPILER_RANLIB}") + endif() + + set(CMAKE_${lang}_ARCHIVE_CREATE_IPO + "${__ar} cr " + ) + + set(CMAKE_${lang}_ARCHIVE_APPEND_IPO + "${__ar} r " + ) + + set(CMAKE_${lang}_ARCHIVE_FINISH_IPO + "${__ranlib} " + ) endmacro() endif() diff --git a/Modules/Compiler/Cray-C.cmake b/Modules/Compiler/Cray-C.cmake index 675560c2a..87ce20f71 100644 --- a/Modules/Compiler/Cray-C.cmake +++ b/Modules/Compiler/Cray-C.cmake @@ -1 +1,22 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +include(Compiler/Cray) + set(CMAKE_C_VERBOSE_FLAG "-v") + +string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG") +string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG") + +if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1) + set(CMAKE_C90_STANDARD_COMPILE_OPTION -h noc99,conform) + set(CMAKE_C90_EXTENSION_COMPILE_OPTION -h noc99,gnu) + set(CMAKE_C99_STANDARD_COMPILE_OPTION -h c99,conform) + set(CMAKE_C99_EXTENSION_COMPILE_OPTION -h c99,gnu) + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.5) + set(CMAKE_C11_STANDARD_COMPILE_OPTION -h std=c11,conform) + set(CMAKE_C11_EXTENSION_COMPILE_OPTION -h std=c11,gnu) + endif () +endif () + +__compiler_check_default_language_standard(C 8.1 99) diff --git a/Modules/Compiler/Cray-CXX.cmake b/Modules/Compiler/Cray-CXX.cmake index 9fb191c75..8506c0942 100644 --- a/Modules/Compiler/Cray-CXX.cmake +++ b/Modules/Compiler/Cray-CXX.cmake @@ -1 +1,20 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +include(Compiler/Cray) + set(CMAKE_CXX_VERBOSE_FLAG "-v") + +string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG") +string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG") + +if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION -h conform) + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -h gnu) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.4) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION -h std=c++11) + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION -h std=c++11,gnu) + endif () +endif () + +__compiler_check_default_language_standard(CXX 8.1 98) diff --git a/Modules/Compiler/Cray.cmake b/Modules/Compiler/Cray.cmake new file mode 100644 index 000000000..8fe8eebda --- /dev/null +++ b/Modules/Compiler/Cray.cmake @@ -0,0 +1,10 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_CRAY) + return() +endif() +set(__COMPILER_CRAY 1) + +include(Compiler/CMakeCommonCompilerMacros) diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 3f026182b..f072c546a 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -22,33 +22,4 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) - if (NOT CMAKE_C_COMPILER_FORCED) - if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") - endif() - set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0) - set(CMAKE_C_STANDARD_DEFAULT 11) - else() - set(CMAKE_C_STANDARD_DEFAULT 90) - endif() - endif() -endif() - -macro(cmake_record_c_compile_features) - set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) - if(_result EQUAL 0 AND CMAKE_C11_STANDARD_COMPILE_OPTION) - _record_compiler_features_c(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_c(99) - endif() - if (_result EQUAL 0) - _record_compiler_features_c(90) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(C 3.4 90 5.0 11) diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index c007c9837..4f1f30e87 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -11,8 +11,7 @@ else() endif() endif() -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) - # Supported since 4.3 +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") endif() @@ -39,32 +38,4 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1) set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) - if (NOT CMAKE_CXX_COMPILER_FORCED) - if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}") - endif() - set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - set(CMAKE_CXX_STANDARD_DEFAULT 98) - endif() -endif() - -macro(cmake_record_cxx_compile_features) - set(_result 0) - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) - if(_result EQUAL 0 AND CMAKE_CXX17_STANDARD_COMPILE_OPTION) - _record_compiler_features_cxx(17) - endif() - if(_result EQUAL 0 AND CMAKE_CXX14_STANDARD_COMPILE_OPTION) - _record_compiler_features_cxx(14) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(98) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(CXX 3.4 98 6.0 14) diff --git a/Modules/Compiler/GNU-FindBinUtils.cmake b/Modules/Compiler/GNU-FindBinUtils.cmake new file mode 100644 index 000000000..16b7bbda4 --- /dev/null +++ b/Modules/Compiler/GNU-FindBinUtils.cmake @@ -0,0 +1,35 @@ +if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") + message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") +endif() + +# Ubuntu 16.04: +# * /usr/bin/gcc-ar-5 +# * /usr/bin/gcc-ranlib-5 +string(REGEX MATCH "^([0-9]+)" __version_x + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}") + +string(REGEX MATCH "^([0-9]+\\.[0-9]+)" __version_x_y + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}") + +# Try to find tools in the same directory as GCC itself +get_filename_component(__gcc_hints "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) + +# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ar.1.html +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x_y}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar" + HINTS ${__gcc_hints} + DOC "A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR) + +# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ranlib.1.html +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x_y}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x}" + "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib" + HINTS ${__gcc_hints} + DOC "A wrapper around 'ranlib' adding the appropriate '--plugin' option for the GCC compiler" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB) diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake index b67002c4b..675e50534 100644 --- a/Modules/Compiler/GNU.cmake +++ b/Modules/Compiler/GNU.cmake @@ -8,6 +8,8 @@ if(__COMPILER_GNU) endif() set(__COMPILER_GNU 1) +include(Compiler/CMakeCommonCompilerMacros) + macro(__compiler_gnu lang) # Feature flags. set(CMAKE_${lang}_VERBOSE_FLAG "-v") @@ -45,4 +47,43 @@ macro(__compiler_gnu lang) if(NOT APPLE OR NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4) # work around #4462 set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") endif() + + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + + # '-flto' introduced since GCC 4.5: + # * https://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Option-Summary.html (no) + # * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Option-Summary.html (yes) + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.5) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + set(__lto_flags -flto) + + if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.7) + # '-ffat-lto-objects' introduced since GCC 4.7: + # * https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Option-Summary.html (no) + # * https://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/Option-Summary.html (yes) + list(APPEND __lto_flags -fno-fat-lto-objects) + endif() + + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO ${__lto_flags}) + + # Need to use version of 'ar'/'ranlib' with plugin support. + # Quote from [documentation][1]: + # + # To create static libraries suitable for LTO, + # use gcc-ar and gcc-ranlib instead of ar and ranlib + # + # [1]: https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Optimize-Options.html + set(CMAKE_${lang}_ARCHIVE_CREATE_IPO + "${CMAKE_${lang}_COMPILER_AR} cr " + ) + + set(CMAKE_${lang}_ARCHIVE_APPEND_IPO + "${CMAKE_${lang}_COMPILER_AR} r " + ) + + set(CMAKE_${lang}_ARCHIVE_FINISH_IPO + "${CMAKE_${lang}_COMPILER_RANLIB} " + ) + endif() endmacro() diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index f1b6ff769..f65b0c7da 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -7,7 +7,7 @@ set(CMAKE_C_COMPILE_OBJECT " --preprocess=cnl ") set(CMAKE_C_CREATE_ASSEMBLY_SOURCE " -lAH -o .dummy") -set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "-f") +set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "-f ") set(CMAKE_DEPFILE_FLAGS_C "--dependencies=ns ") # The toolchains for ARM and AVR are quite different: diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake index ffb144f79..f49968e90 100644 --- a/Modules/Compiler/IAR-CXX.cmake +++ b/Modules/Compiler/IAR-CXX.cmake @@ -7,7 +7,7 @@ set(CMAKE_CXX_COMPILE_OBJECT " --preprocess=cnl ") set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE " -lAH -o .dummy") -set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "-f") +set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "-f ") set(CMAKE_DEPFILE_FLAGS_CXX "--dependencies=ns ") if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "ARM") diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake index 9c67fbd0b..4e4af2956 100644 --- a/Modules/Compiler/Intel-C.cmake +++ b/Modules/Compiler/Intel-C.cmake @@ -8,61 +8,36 @@ string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG") set(CMAKE_DEPFILE_FLAGS_C "-MD -MT -MF ") if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - set(_std -Qstd) - set(_ext c) + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0) set(CMAKE_C11_STANDARD_COMPILE_OPTION "-Qstd=c11") set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-Qstd=c11") endif() + + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0) + set(CMAKE_C90_STANDARD_COMPILE_OPTION "-Qstd=c89") + set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-Qstd=c89") + set(CMAKE_C99_STANDARD_COMPILE_OPTION "-Qstd=c99") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-Qstd=c99") + endif() + else() - set(_std -std) - set(_ext gnu) + 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") endif() -endif() -if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0) - set(CMAKE_C90_STANDARD_COMPILE_OPTION "${_std}=c89") - set(CMAKE_C90_EXTENSION_COMPILE_OPTION "${_std}=${_ext}89") - set(CMAKE_C99_STANDARD_COMPILE_OPTION "${_std}=c99") - set(CMAKE_C99_EXTENSION_COMPILE_OPTION "${_std}=${_ext}99") -endif() - -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.1) - if (NOT CMAKE_C_COMPILER_FORCED) - if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") - endif() - set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0) - set(CMAKE_C_STANDARD_DEFAULT 11) - else() - set(CMAKE_C_STANDARD_DEFAULT 90) - endif() + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0) + set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") + set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89") + set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") endif() -endif() -unset(_std) -unset(_ext) +endif() -macro(cmake_record_c_compile_features) - set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.1) - if (_result EQUAL 0 AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0) - _record_compiler_features_C(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_C(99) - endif() - if (_result EQUAL 0) - _record_compiler_features_C(90) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(C 12.0 90 15.0.0 11) set(CMAKE_C_CREATE_PREPROCESSED_SOURCE " -E > ") set(CMAKE_C_CREATE_ASSEMBLY_SOURCE " -S -o ") diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake index 9c39236f3..0eb9e1fd7 100644 --- a/Modules/Compiler/Intel-CXX.cmake +++ b/Modules/Compiler/Intel-CXX.cmake @@ -8,16 +8,27 @@ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG") set(CMAKE_DEPFILE_FLAGS_CXX "-MD -MT -MF ") if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - set(_std -Qstd) - set(_ext c++) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0) set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-Qstd=c++14") - # todo: there is no gnu++14 value supported; figure out what to do set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-Qstd=c++14") endif() + + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-Qstd=c++11") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-Qstd=c++11") + elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-Qstd=c++0x") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-Qstd=c++0x") + endif() + + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "") + endif() + else() - set(_std -std) - set(_ext gnu++) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0.2) set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14") # todo: there is no gnu++14 value supported; figure out what to do @@ -27,59 +38,23 @@ else() # todo: there is no gnu++14 value supported; figure out what to do set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=c++1y") endif() -endif() - -if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0) - set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "${_std}=c++11") - set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "${_std}=${_ext}11") -elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) - set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "${_std}=c++0x") - set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "${_std}=${_ext}0x") -endif() -if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) - if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") - set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "") - else() - set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "${_std}=c++98") - set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "${_std}=gnu++98") + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11") + elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x") endif() -endif() -if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) - if (NOT CMAKE_CXX_COMPILER_FORCED) - if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}") - else() - set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}) - endif() - elseif (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT) - # Compiler id was forced so just guess the default standard level. - set(CMAKE_CXX_STANDARD_DEFAULT 98) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") endif() -endif() -unset(_std) -unset(_ext) +endif() -macro(cmake_record_cxx_compile_features) - set(_result 0) - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1) - if (_result EQUAL 0 AND - (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0 - OR (NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC" AND - NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0))) - _record_compiler_features_cxx(14) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(98) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(CXX 12.1 98) set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE " -E > ") set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE " -S -o ") diff --git a/Modules/Compiler/Intel.cmake b/Modules/Compiler/Intel.cmake index 02968b4b7..635ac4d3c 100644 --- a/Modules/Compiler/Intel.cmake +++ b/Modules/Compiler/Intel.cmake @@ -8,6 +8,8 @@ if(__COMPILER_INTEL) endif() set(__COMPILER_INTEL 1) +include(Compiler/CMakeCommonCompilerMacros) + if(CMAKE_HOST_WIN32) # MSVC-like macro(__compiler_intel lang) @@ -22,5 +24,7 @@ else() 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}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-QdM" "-P" "-Za" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp") endmacro() endif() diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 8fcfa0f55..9371301d7 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -1,17 +1,21 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. -if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0) - # MSVC has no specific language level or flags to change it. +include(Compiler/CMakeCommonCompilerMacros) + +if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) + # MSVC has no specific options to set language standards, but set them as + # empty strings anyways so the feature test infrastructure can at least check + # to see if they are defined. + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "") + + # There is no meaningful default for this set(CMAKE_CXX_STANDARD_DEFAULT "") endif() - -macro(cmake_record_cxx_compile_features) - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0) - list(APPEND CMAKE_CXX_COMPILE_FEATURES - cxx_std_98 - cxx_std_11 - cxx_std_14 - cxx_std_17 - ) - _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES) - endif() -endmacro() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index 316cab8d4..785e26998 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -24,4 +24,10 @@ else() set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "") set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "-std=c++11") set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11") + + if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0) + set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "-std=c++14") + set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "-std=c++14") + endif() + endif() diff --git a/Modules/Compiler/PGI-C.cmake b/Modules/Compiler/PGI-C.cmake index 85d6e7e0c..3b3848a2c 100644 --- a/Modules/Compiler/PGI-C.cmake +++ b/Modules/Compiler/PGI-C.cmake @@ -2,3 +2,16 @@ include(Compiler/PGI) __compiler_pgi(C) string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG") string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG") + +if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.10) + set(CMAKE_C90_STANDARD_COMPILE_OPTION -c89) + set(CMAKE_C90_EXTENSION_COMPILE_OPTION -c89) + set(CMAKE_C99_STANDARD_COMPILE_OPTION -c99) + set(CMAKE_C99_EXTENSION_COMPILE_OPTION -c99) + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15.3) + set(CMAKE_C11_STANDARD_COMPILE_OPTION -c11) + set(CMAKE_C11_EXTENSION_COMPILE_OPTION -c11) + endif () +endif () + +__compiler_check_default_language_standard(C 12.10 90) diff --git a/Modules/Compiler/PGI-CXX.cmake b/Modules/Compiler/PGI-CXX.cmake index 896e29877..35076bb38 100644 --- a/Modules/Compiler/PGI-CXX.cmake +++ b/Modules/Compiler/PGI-CXX.cmake @@ -2,3 +2,22 @@ include(Compiler/PGI) __compiler_pgi(CXX) string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG") string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG") + +if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.10) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION -A) + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION --gnu_extensions) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.10) + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION --c++11 -A) + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION --c++11 --gnu_extensions) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.7) + set(CMAKE_CXX14_STANDARD_COMPILE_OPTION --c++14 -A) + set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION --c++14 --gnu_extensions) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 17.1) + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION --c++17 -A) + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION --c++17 --gnu_extensions) + endif() + endif() + endif() +endif() + +__compiler_check_default_language_standard(CXX 12.10 98) diff --git a/Modules/Compiler/PGI.cmake b/Modules/Compiler/PGI.cmake index cc76deb87..0cbfd8a0b 100644 --- a/Modules/Compiler/PGI.cmake +++ b/Modules/Compiler/PGI.cmake @@ -8,6 +8,8 @@ if(__COMPILER_PGI) endif() set(__COMPILER_PGI 1) +include(Compiler/CMakeCommonCompilerMacros) + macro(__compiler_pgi lang) # Feature flags. set(CMAKE_${lang}_VERBOSE_FLAG "-v") @@ -16,9 +18,17 @@ macro(__compiler_pgi lang) string(APPEND CMAKE_${lang}_FLAGS_INIT " ") string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g -O0") string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O2 -s") - string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -fast -O3 -Mipa=fast") + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -fast -O3") + # -Mipa was dropped with PGI 16.3 from Windows versions + if(NOT CMAKE_HOST_WIN32 OR CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 16.3) + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -Mipa=fast") + endif() string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -gopt") + if(CMAKE_HOST_WIN32) + string(APPEND CMAKE_${lang}_FLAGS_INIT " -Bdynamic") + endif() + # Preprocessing and assembly rules. set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE " -E > ") set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE " -S -o ") diff --git a/Modules/Compiler/QCC.cmake b/Modules/Compiler/QCC.cmake index 2d7e881a4..0da7050ba 100644 --- a/Modules/Compiler/QCC.cmake +++ b/Modules/Compiler/QCC.cmake @@ -12,4 +12,12 @@ macro(__compiler_qcc lang) set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-Wp,-isystem,") set(CMAKE_DEPFILE_FLAGS_${lang} "-Wc,-MD,,-MT,,-MF,") + + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE NO) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + + unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO) + unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO) + unset(CMAKE_${lang}_ARCHIVE_APPEND_IPO) + unset(CMAKE_${lang}_ARCHIVE_FINISH_IPO) endmacro() diff --git a/Modules/Compiler/SunPro-C-FeatureTests.cmake b/Modules/Compiler/SunPro-C-FeatureTests.cmake new file mode 100644 index 000000000..cccf3ae54 --- /dev/null +++ b/Modules/Compiler/SunPro-C-FeatureTests.cmake @@ -0,0 +1,14 @@ +set(_cmake_oldestSupported "__SUNPRO_C >= 0x5130") + +set(SunPro_C11 "${_cmake_oldestSupported} && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L || __STDC_VERSION__ >= 199901L && defined(__C11FEATURES__))") +set(_cmake_feature_test_c_static_assert "${SunPro_C11}") +unset(SunPro_C11) + +set(SunPro_C99 "${_cmake_oldestSupported} && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") +set(_cmake_feature_test_c_restrict "${SunPro_C99}") +set(_cmake_feature_test_c_variadic_macros "${SunPro_C99}") +unset(SunPro_C99) + +set(SunPro_C90 "${_cmake_oldestSupported}") +set(_cmake_feature_test_c_function_prototypes "${SunPro_C90}") +unset(SunPro_C90) diff --git a/Modules/Compiler/SunPro-C.cmake b/Modules/Compiler/SunPro-C.cmake index 503684a36..29c2f22f9 100644 --- a/Modules/Compiler/SunPro-C.cmake +++ b/Modules/Compiler/SunPro-C.cmake @@ -1,3 +1,8 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +include(Compiler/SunPro) + set(CMAKE_C_VERBOSE_FLAG "-#") set(CMAKE_C_COMPILE_OPTIONS_PIC -KPIC) @@ -22,5 +27,21 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Bdynamic") endforeach() +if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.13) + set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") + set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=c89") + set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=c99") + set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=c11") +elseif (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.11) + set(CMAKE_C90_STANDARD_COMPILE_OPTION "") + set(CMAKE_C90_EXTENSION_COMPILE_OPTION "") + set(CMAKE_C99_STANDARD_COMPILE_OPTION "-xc99") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-xc99") +endif() + +__compiler_check_default_language_standard(C 5.11 90 5.14 11) + set(CMAKE_C_CREATE_PREPROCESSED_SOURCE " -E > ") set(CMAKE_C_CREATE_ASSEMBLY_SOURCE " -S -o ") diff --git a/Modules/Compiler/SunPro-CXX-FeatureTests.cmake b/Modules/Compiler/SunPro-CXX-FeatureTests.cmake index 8e97e1d05..60280cadc 100644 --- a/Modules/Compiler/SunPro-CXX-FeatureTests.cmake +++ b/Modules/Compiler/SunPro-CXX-FeatureTests.cmake @@ -5,6 +5,10 @@ set(_cmake_oldestSupported "__SUNPRO_CC >= 0x5130") +set(SolarisStudio125_CXX11 "(__SUNPRO_CC >= 0x5140) && __cplusplus >= 201103L") +set(_cmake_feature_test_cxx_binary_literals "${SolarisStudio125_CXX11}") +set(_cmake_feature_test_cxx_reference_qualified_functions "${SolarisStudio125_CXX11}") + set(SolarisStudio124_CXX11 "(__SUNPRO_CC >= 0x5130) && __cplusplus >= 201103L") set(_cmake_feature_test_cxx_alignas "${SolarisStudio124_CXX11}") set(_cmake_feature_test_cxx_alignof "${SolarisStudio124_CXX11}") diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake index f4345b8ec..5cb7edced 100644 --- a/Modules/Compiler/SunPro-CXX.cmake +++ b/Modules/Compiler/SunPro-CXX.cmake @@ -1,3 +1,8 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +include(Compiler/SunPro) + set(CMAKE_CXX_VERBOSE_FLAG "-v") set(CMAKE_CXX_COMPILE_OPTIONS_PIC -KPIC) @@ -32,32 +37,15 @@ set(CMAKE_CXX_CREATE_STATIC_LIBRARY " ") if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) - set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") - set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++03") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=c++03") set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11") set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=c++11") + set(CMAKE_CXX_LINK_WITH_STANDARD_COMPILE_OPTION 1) +else() + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-library=stlport4") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-library=stlport4") + set(CMAKE_CXX_LINK_WITH_STANDARD_COMPILE_OPTION 1) endif() -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) - if (NOT CMAKE_CXX_COMPILER_FORCED) - if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT) - message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}") - endif() - set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}) - elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT) - # Compiler id was forced so just guess the default standard level. - set(CMAKE_CXX_STANDARD_DEFAULT 98) - endif() -endif() - -macro(cmake_record_cxx_compile_features) - set(_result 0) - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13) - if (_result EQUAL 0) - _record_compiler_features_cxx(11) - endif() - if (_result EQUAL 0) - _record_compiler_features_cxx(98) - endif() - endif() -endmacro() +__compiler_check_default_language_standard(CXX 1 98) diff --git a/Modules/Compiler/SunPro-Fortran.cmake b/Modules/Compiler/SunPro-Fortran.cmake index 6607926a9..9b25c0b25 100644 --- a/Modules/Compiler/SunPro-Fortran.cmake +++ b/Modules/Compiler/SunPro-Fortran.cmake @@ -19,7 +19,7 @@ set(CMAKE_Fortran_MODDIR_FLAG "-moddir=") set(CMAKE_Fortran_MODPATH_FLAG "-M") set(CMAKE_Fortran_PREPROCESS_SOURCE - " -F -o ") + " -F -fpp -o ") -set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE " -F -o ") +set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE " -F -fpp -o ") set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE " -S -o ") diff --git a/Modules/Compiler/SunPro.cmake b/Modules/Compiler/SunPro.cmake new file mode 100644 index 000000000..52da39a8b --- /dev/null +++ b/Modules/Compiler/SunPro.cmake @@ -0,0 +1,10 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This module is shared by multiple languages; use include blocker. +if(__COMPILER_SUNPRO) + return() +endif() +set(__COMPILER_SUNPRO 1) + +include(Compiler/CMakeCommonCompilerMacros) diff --git a/Modules/Compiler/XL-C.cmake b/Modules/Compiler/XL-C.cmake index f976c9912..5dc8bc17f 100644 --- a/Modules/Compiler/XL-C.cmake +++ b/Modules/Compiler/XL-C.cmake @@ -3,6 +3,39 @@ __compiler_xl(C) string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG") string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG") -# -qthreaded = Ensures that all optimizations will be thread-safe -# -qhalt=e = Halt on error messages (rather than just severe errors) -string(APPEND CMAKE_C_FLAGS_INIT " -qthreaded -qhalt=e") +# -qthreaded = Ensures that all optimizations will be thread-safe +string(APPEND CMAKE_C_FLAGS_INIT " -qthreaded") + +# XL v13.1.1 for Linux ppc64 little-endian switched to using a clang based +# front end and accepts the -std= option while only reserving -qlanglevel= for +# compatibility. All other versions (previous versions on Linux ppc64 +# little-endian, all versions on Linux ppc64 big-endian, all versions on AIX +# and BGQ, etc) are derived from the UNIX compiler and only accept the +# -qlanglvl option. +if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.1) + if (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND + 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") + set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.2) + set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") + else () + set(CMAKE_C11_STANDARD_COMPILE_OPTION "-qlanglvl=extc1x") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-qlanglvl=extc1x") + endif () + else () + set(CMAKE_C90_STANDARD_COMPILE_OPTION "-qlanglvl=stdc89") + set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-qlanglvl=extc89") + set(CMAKE_C99_STANDARD_COMPILE_OPTION "-qlanglvl=stdc99") + set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-qlanglvl=extc99") + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.1) + set(CMAKE_C11_STANDARD_COMPILE_OPTION "-qlanglvl=extc1x") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-qlanglvl=extc1x") + endif () + endif () +endif() + +__compiler_check_default_language_standard(C 10.1 90) diff --git a/Modules/Compiler/XL-CXX.cmake b/Modules/Compiler/XL-CXX.cmake index 545d65732..b87e9238b 100644 --- a/Modules/Compiler/XL-CXX.cmake +++ b/Modules/Compiler/XL-CXX.cmake @@ -3,9 +3,47 @@ __compiler_xl(CXX) string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG") string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG") -# -qthreaded = Ensures that all optimizations will be thread-safe -# -qhalt=e = Halt on error messages (rather than just severe errors) -string(APPEND CMAKE_CXX_FLAGS_INIT " -qthreaded -qhalt=e") +# -qthreaded = Ensures that all optimizations will be thread-safe +string(APPEND CMAKE_CXX_FLAGS_INIT " -qthreaded") + +# XL v13.1.1 for Linux ppc64 little-endian switched to using a clang based +# front end and accepts the -std= option while only reserving -qlanglevel= for +# compatibility. All other versions (previous versions on Linux ppc64 +# little-endian, all versions on Linux ppc64 big-endian, all versions on AIX +# and BGQ, etc) are derived from the UNIX compiler and only accept the +# -qlanglvl option. +if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.1) + if (CMAKE_SYSTEM MATCHES "Linux.*ppc64") + if (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.1) + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.2) + 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++1y") + set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-qlanglvl=extended1y") + else () + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-qlanglvl=extended0x") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-qlanglvl=extended0x") + endif () + else () + # The non-clang based Linux ppc64 compiler, both big-endian and + # little-endian lacks, the non-extension language level flags + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-qlanglvl=extended") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-qlanglvl=extended") + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-qlanglvl=extended0x") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-qlanglvl=extended0x") + endif () + else () + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-qlanglvl=strict98") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-qlanglvl=extended") + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-qlanglvl=extended0x") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-qlanglvl=extended0x") + endif () +endif () + +__compiler_check_default_language_standard(CXX 10.1 98) set(CMAKE_CXX_COMPILE_OBJECT " -+ -o -c ") diff --git a/Modules/Compiler/XL.cmake b/Modules/Compiler/XL.cmake index 55f71bd83..478378570 100644 --- a/Modules/Compiler/XL.cmake +++ b/Modules/Compiler/XL.cmake @@ -8,6 +8,8 @@ if(__COMPILER_XL) endif() set(__COMPILER_XL 1) +include(Compiler/CMakeCommonCompilerMacros) + # Find the CreateExportList program that comes with this toolchain. find_program(CMAKE_XL_CreateExportList NAMES CreateExportList diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index 50be9cbcc..6b9b361cc 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -25,6 +25,9 @@ MultiByte + + @id_Import_props@ + <_ProjectFileVersion>10.0.30319.1 .\ @@ -44,16 +47,21 @@ + @id_ItemDefinitionGroup_entry@ false Console + @id_Link_AdditionalDependencies@ - for %%i in (@id_cl@) do %40echo CMAKE_@id_lang@_COMPILER=%%~$PATH:i + @id_PostBuildEvent_Command@ - + <@id_compile@ Include="@id_src@" /> + + @id_Import_targets@ + diff --git a/Modules/CompilerId/Xcode-1.pbxproj.in b/Modules/CompilerId/Xcode-1.pbxproj.in deleted file mode 100644 index 793ad0280..000000000 --- a/Modules/CompilerId/Xcode-1.pbxproj.in +++ /dev/null @@ -1,120 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 39; - objects = { - 014CEA460018CE2711CA2923 = { - buildSettings = { - }; - isa = PBXBuildStyle; - name = Development; - }; - 08FB7793FE84155DC02AAC07 = { - buildSettings = { - }; - buildStyles = ( - 014CEA460018CE2711CA2923, - ); - hasScannedForEncodings = 1; - isa = PBXProject; - mainGroup = 08FB7794FE84155DC02AAC07; - projectDirPath = ""; - targets = ( - 8DD76FA90486AB0100D96B5E, - ); - }; - 08FB7794FE84155DC02AAC07 = { - children = ( - 08FB7795FE84155DC02AAC07, - 1AB674ADFE9D54B511CA2CBB, - ); - isa = PBXGroup; - name = CompilerId@id_lang@; - refType = 4; - sourceTree = ""; - }; - 08FB7795FE84155DC02AAC07 = { - children = ( - 2C18F0B415DC1DC700593670, - ); - isa = PBXGroup; - name = Source; - refType = 4; - sourceTree = ""; - }; - 1AB674ADFE9D54B511CA2CBB = { - children = ( - 8DD76F6C0486A84900D96B5E, - ); - isa = PBXGroup; - name = Products; - refType = 4; - sourceTree = ""; - }; - 2C18F0B415DC1DC700593670 = { - fileEncoding = 30; - isa = PBXFileReference; - explicitFileType = @id_type@; - path = @id_src@; - refType = 4; - sourceTree = ""; - }; - 2C18F0B615DC1E0300593670 = { - fileRef = 2C18F0B415DC1DC700593670; - isa = PBXBuildFile; - settings = { - }; - }; - 2C8FEB8E15DC1A1A00E56A5D = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"GCC_VERSION=$GCC_VERSION\""; - }; - 8DD76FA90486AB0100D96B5E = { - buildPhases = ( - 2C18F0B515DC1DCE00593670, - 2C8FEB8E15DC1A1A00E56A5D, - ); - buildRules = ( - ); - buildSettings = { - PRODUCT_NAME = CompilerId@id_lang@; - SYMROOT = .; - }; - dependencies = ( - ); - isa = PBXNativeTarget; - name = CompilerId@id_lang@; - productName = CompilerId@id_lang@; - productReference = 8DD76F6C0486A84900D96B5E; - productType = "com.apple.product-type.tool"; - }; - 2C18F0B515DC1DCE00593670 = { - buildActionMask = 2147483647; - files = ( - 2C18F0B615DC1E0300593670, - ); - isa = PBXSourcesBuildPhase; - runOnlyForDeploymentPostprocessing = 0; - }; - 8DD76F6C0486A84900D96B5E = { - explicitFileType = "compiled.mach-o.executable"; - includeInIndex = 0; - isa = PBXFileReference; - path = CompilerId@id_lang@; - refType = 3; - sourceTree = BUILT_PRODUCTS_DIR; - }; - }; - rootObject = 08FB7793FE84155DC02AAC07; -} diff --git a/Modules/CompilerId/Xcode-2.pbxproj.in b/Modules/CompilerId/Xcode-2.pbxproj.in deleted file mode 100644 index 226b413fd..000000000 --- a/Modules/CompilerId/Xcode-2.pbxproj.in +++ /dev/null @@ -1,119 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 42; - objects = { - - 2C18F0B615DC1E0300593670 = {isa = PBXBuildFile; fileRef = 2C18F0B415DC1DC700593670; }; - 2C18F0B415DC1DC700593670 = {isa = PBXFileReference; fileEncoding = 4; explicitFileType = @id_type@; path = @id_src@; sourceTree = ""; }; - 8DD76F6C0486A84900D96B5E = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CompilerId@id_lang@; sourceTree = BUILT_PRODUCTS_DIR; }; - - 08FB7794FE84155DC02AAC07 = { - isa = PBXGroup; - children = ( - 08FB7795FE84155DC02AAC07, - 1AB674ADFE9D54B511CA2CBB, - ); - name = CompilerId@id_lang@; - sourceTree = ""; - }; - 08FB7795FE84155DC02AAC07 = { - isa = PBXGroup; - children = ( - 2C18F0B415DC1DC700593670, - ); - name = Source; - sourceTree = ""; - }; - 1AB674ADFE9D54B511CA2CBB = { - isa = PBXGroup; - children = ( - 8DD76F6C0486A84900D96B5E, - ); - name = Products; - sourceTree = ""; - }; - - 8DD76FA90486AB0100D96B5E = { - isa = PBXNativeTarget; - buildConfigurationList = 1DEB928508733DD80010E9CD; - buildPhases = ( - 2C18F0B515DC1DCE00593670, - 2C8FEB8E15DC1A1A00E56A5D, - ); - buildRules = ( - ); - dependencies = ( - ); - name = CompilerId@id_lang@; - productName = CompilerId@id_lang@; - productReference = 8DD76F6C0486A84900D96B5E; - productType = "com.apple.product-type.tool"; - }; - 08FB7793FE84155DC02AAC07 = { - isa = PBXProject; - buildConfigurationList = 1DEB928908733DD80010E9CD; - hasScannedForEncodings = 1; - mainGroup = 08FB7794FE84155DC02AAC07; - projectDirPath = ""; - targets = ( - 8DD76FA90486AB0100D96B5E, - ); - }; - 2C8FEB8E15DC1A1A00E56A5D = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"GCC_VERSION=$GCC_VERSION\""; - }; - 2C18F0B515DC1DCE00593670 = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2C18F0B615DC1E0300593670, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1DEB928608733DD80010E9CD = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = CompilerId@id_lang@; - }; - name = Debug; - }; - 1DEB928A08733DD80010E9CD = { - isa = XCBuildConfiguration; - buildSettings = { - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; - SYMROOT = .; - }; - name = Debug; - }; - 1DEB928508733DD80010E9CD = { - isa = XCConfigurationList; - buildConfigurations = ( - 1DEB928608733DD80010E9CD, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 1DEB928908733DD80010E9CD = { - isa = XCConfigurationList; - buildConfigurations = ( - 1DEB928A08733DD80010E9CD, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - }; - rootObject = 08FB7793FE84155DC02AAC07; -} diff --git a/Modules/CompilerId/Xcode-3.pbxproj.in b/Modules/CompilerId/Xcode-3.pbxproj.in index 22ad4f689..84f48ae65 100644 --- a/Modules/CompilerId/Xcode-3.pbxproj.in +++ b/Modules/CompilerId/Xcode-3.pbxproj.in @@ -58,7 +58,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "echo \"GCC_VERSION=$GCC_VERSION\""; + shellScript = "echo \"GCC_VERSION=$GCC_VERSION\" ; echo \"CURRENT_ARCH=$CURRENT_ARCH\""; showEnvVarsInLog = 0; }; 2C18F0B515DC1DCE00593670 = { diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 873f88d05..7331fb2b4 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -1111,7 +1111,7 @@ if("${ExternalData_ACTION}" STREQUAL "fetch") list(GET algo_list ${ii} algo) _ExternalData_download_object("${name}" "${hash}" "${algo}" obj succeeded algoErrorMsg) - set(errorMsg "${errorMsg}\n${algoErrorMsg}") + string(APPEND errorMsg "\n${algoErrorMsg}") if(succeeded) break() endif() diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index b42d2ddcc..24957363e 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -415,7 +415,7 @@ file(STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines foreach(line IN LISTS lines) if("${line}" MATCHES "^\\.\\. command:: ([A-Za-z0-9_]+)") if(_ep_func) - set(_ep_keywords_${_ep_func} "${_ep_keywords_${_ep_func}})$") + string(APPEND _ep_keywords_${_ep_func} ")$") endif() set(_ep_func "${CMAKE_MATCH_1}") #message("function [${_ep_func}]") @@ -424,13 +424,13 @@ foreach(line IN LISTS lines) elseif("${line}" MATCHES "^ ``([A-Z0-9_]+) .*``$") set(_ep_key "${CMAKE_MATCH_1}") #message(" keyword [${_ep_key}]") - set(_ep_keywords_${_ep_func} - "${_ep_keywords_${_ep_func}}${_ep_keyword_sep}${_ep_key}") + string(APPEND _ep_keywords_${_ep_func} + "${_ep_keyword_sep}${_ep_key}") set(_ep_keyword_sep "|") endif() endforeach() if(_ep_func) - set(_ep_keywords_${_ep_func} "${_ep_keywords_${_ep_func}})$") + string(APPEND _ep_keywords_${_ep_func} ")$") endif() # Save regex matching supported hash algorithm names. @@ -531,6 +531,15 @@ function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git else() set(git_clone_shallow_options "--depth 1") endif() + if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5) + # Use `git checkout --` to avoid ambiguity with a local path. + set(git_checkout_explicit-- "--") + else() + # Use `git checkout ` even though this risks ambiguity with a + # local path. Unfortunately we cannot use `git checkout --` + # because that will not search for remote branch names, a common use case. + set(git_checkout_explicit-- "") + endif() file(WRITE ${script_filename} "if(\"${git_tag}\" STREQUAL \"\") message(FATAL_ERROR \"Tag for git checkout should not be empty.\") @@ -600,11 +609,8 @@ if(error_code) message(FATAL_ERROR \"Failed to clone repository: '${git_repository}'\") endif() -# Use `git checkout ` even though this risks ambiguity with a -# local path. Unfortunately we cannot use `git checkout --` -# because that will not search for remote branch names, a common use case. execute_process( - COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag} + COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag} ${git_checkout_explicit--} WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) @@ -1990,11 +1996,10 @@ function(_ep_add_download_command name) set(comment "Performing download step (${steps}) for '${name}'") _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}") endif() - list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake - COMMAND) + list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake) if (NOT no_extract) _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}") - list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake) + list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake) else () set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file}) endif () diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake index f29a5f043..1b93304bb 100644 --- a/Modules/FeatureSummary.cmake +++ b/Modules/FeatureSummary.cmake @@ -63,6 +63,16 @@ is set for all the packages. The default value for this global property is ``OPTIONAL``. + +.. variable:: FeatureSummary__DESCRIPTION + +The global property :variable:`FeatureSummary__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. + +If not set, the string "```` packages" is used. + + #]=======================================================================] get_property(_fsPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_PKG_TYPES SET) @@ -196,7 +206,7 @@ endfunction() [VAR ] [INCLUDE_QUIET_PACKAGES] [FATAL_ON_MISSING_REQUIRED_PACKAGES] - [DESCRIPTION ""] + [DESCRIPTION "" | DEFAULT_DESCRIPTION] [QUIET_ON_EMPTY] WHAT (ALL | PACKAGES_FOUND | PACKAGES_NOT_FOUND @@ -247,7 +257,10 @@ endfunction() information is "printed" into the specified variable. If ``FILENAME`` is not used, the information is printed to the terminal. Using the ``DESCRIPTION`` option a description or headline can be set which will be - printed above the actual content. + printed above the actual content. If only one type of + package was requested, no title is printed, unless it is explicitly set using + either ``DESCRIPTION`` to use a custom string, or ``DEFAULT_DESCRIPTION`` to + use a default title for the requested type. If ``INCLUDE_QUIET_PACKAGES`` is given, packages which have been searched with ``find_package(... QUIET)`` will also be listed. By default they are skipped. If ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` is given, CMake will abort if a @@ -306,8 +319,14 @@ endfunction() function(FEATURE_SUMMARY) # CMAKE_PARSE_ARGUMENTS( args...) - set(options APPEND INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES QUIET_ON_EMPTY) - set(oneValueArgs FILENAME VAR DESCRIPTION) + set(options APPEND + INCLUDE_QUIET_PACKAGES + FATAL_ON_MISSING_REQUIRED_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) + set(oneValueArgs FILENAME + VAR + DESCRIPTION) set(multiValueArgs WHAT) CMAKE_PARSE_ARGUMENTS(_FS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) @@ -320,6 +339,11 @@ function(FEATURE_SUMMARY) message(FATAL_ERROR "The call to FEATURE_SUMMARY() doesn't set the required WHAT argument.") endif() + if(_FS_DEFAULT_DESCRIPTION AND DEFINED _FS_DESCRIPTION) + message(WARNING "DEFAULT_DESCRIPTION option discarded since DESCRIPTION is set.") + set(_FS_DEFAULT_DESCRIPTION 0) + endif() + set(validWhatParts "ENABLED_FEATURES" "DISABLED_FEATURES" "PACKAGES_FOUND" @@ -332,11 +356,29 @@ function(FEATURE_SUMMARY) "${_fsPkgType}_PACKAGES_NOT_FOUND") endforeach() + set(title_ENABLED_FEATURES "The following features have been enabled:") + set(title_DISABLED_FEATURES "The following features have been disabled:") + set(title_PACKAGES_FOUND "The following packages have been found:") + set(title_PACKAGES_NOT_FOUND "The following packages have not been found:") + foreach(_fsPkgType ${_fsPkgTypes}) + set(_fsPkgTypeDescription "${_fsPkgType} packages") + get_property(_fsPkgTypeDescriptionIsSet GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION SET) + if(_fsPkgTypeDescriptionIsSet) + get_property(_fsPkgTypeDescription GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION ) + endif() + set(title_${_fsPkgType}_PACKAGES_FOUND "The following ${_fsPkgTypeDescription} have been found:") + set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgTypeDescription} have not been found:") + endforeach() + list(FIND validWhatParts "${_FS_WHAT}" indexInList) if(NOT "${indexInList}" STREQUAL "-1") _FS_GET_FEATURE_SUMMARY( ${_FS_WHAT} _featureSummary ${_FS_INCLUDE_QUIET_PACKAGES} ) if(_featureSummary OR NOT _FS_QUIET_ON_EMPTY) - set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n") + if(_FS_DEFAULT_DESCRIPTION) + set(_fullText "${title_${_FS_WHAT}}\n${_featureSummary}\n") + else() + set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n") + endif() endif() if(_featureSummary) @@ -375,15 +417,6 @@ function(FEATURE_SUMMARY) endforeach() endif() - set(title_ENABLED_FEATURES "The following features have been enabled:") - set(title_DISABLED_FEATURES "The following features have been disabled:") - set(title_PACKAGES_FOUND "The following packages have been found:") - set(title_PACKAGES_NOT_FOUND "The following packages have not been found:") - foreach(_fsPkgType ${_fsPkgTypes}) - set(title_${_fsPkgType}_PACKAGES_FOUND "The following ${_fsPkgType} packages have been found:") - set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgType} packages have not been found:") - endforeach() - set(_fullText "${_FS_DESCRIPTION}") foreach(part ${allWhatParts}) set(_tmp) diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index 2dd08e10a..cc273e085 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -127,7 +127,10 @@ # ('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. +# 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_THREADAPI - Suffix for "thread" component library name, # such as "pthread" or "win32". Names with # and without this suffix will both be tried. @@ -205,6 +208,10 @@ # # Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. +# Save project's policies +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST + #------------------------------------------------------------------------------- # Before we go searching, check whether boost-cmake is available, unless the # user specifically asked NOT to search for boost-cmake. @@ -428,7 +435,7 @@ function(_Boost_GUESS_COMPILER_PREFIX _ret) set(_boost_COMPILER "-ghs") elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) - set(_boost_COMPILER "-vc141") + set(_boost_COMPILER "-vc141;-vc140") elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) set(_boost_COMPILER "-vc140") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18) @@ -862,14 +869,12 @@ function(_Boost_MISSING_DEPENDENCIES componentvar extravar) list(APPEND _boost_processed_components ${_boost_unprocessed_components}) foreach(component ${_boost_unprocessed_components}) string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) + set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) _Boost_COMPONENT_DEPENDENCIES("${component}" _Boost_${uppercomponent}_DEPENDENCIES) set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES}) - list(FIND _boost_processed_components "${componentdep}" _boost_component_found) - list(FIND _boost_new_components "${componentdep}" _boost_component_new) - if (_boost_component_found EQUAL -1 AND _boost_component_new EQUAL -1) + if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components)) list(APPEND _boost_new_components ${componentdep}) endif() endforeach() @@ -885,6 +890,33 @@ function(_Boost_MISSING_DEPENDENCIES componentvar extravar) set(${extravar} ${_boost_extra_components} PARENT_SCOPE) endfunction() +# +# Some boost libraries may require particular set of compler features. +# The very first one was `boost::fiber` introduced in Boost 1.62. +# One can check required compiler features of it in +# `${Boost_ROOT}/libs/fiber/build/Jamfile.v2`. +# +function(_Boost_COMPILER_FEATURES component _ret) + # Boost >= 1.62 and < 1.65 + if(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106500) + set(_Boost_FIBER_COMPILER_FEATURES + cxx_alias_templates + cxx_auto_type + cxx_constexpr + cxx_defaulted_functions + cxx_final + cxx_lambdas + cxx_noexcept + cxx_nullptr + cxx_rvalue_references + cxx_thread_local + cxx_variadic_templates + ) + endif() + string(TOUPPER ${component} uppercomponent) + set(${_ret} ${_Boost_${uppercomponent}_COMPILER_FEATURES} PARENT_SCOPE) +endfunction() + # # Update library search directory hint variable with paths used by prebuilt boost binaries. # @@ -893,7 +925,7 @@ endfunction() # This function would append corresponding directories if MSVC is a current compiler, # so having `BOOST_ROOT` would be enough to specify to find everything. # -macro(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) +function(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_arch_suffix 64) @@ -901,7 +933,8 @@ macro(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlib set(_arch_suffix 32) endif() if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-15.0) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.1) + list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18) @@ -915,8 +948,9 @@ macro(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlib elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-8.0) endif() + set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE) endif() -endmacro() +endfunction() # # End functions/macros @@ -1119,6 +1153,12 @@ if(NOT Boost_INCLUDE_DIR) if( Boost_NO_SYSTEM_PATHS) list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) else() + if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") + foreach(ver ${_Boost_KNOWN_VERSIONS}) + string(REPLACE "." "_" ver "${ver}") + list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS "C:/local/boost_${ver}") + endforeach() + endif() list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS C:/boost/include C:/boost @@ -1392,12 +1432,16 @@ foreach(c DEBUG RELEASE) if( Boost_NO_SYSTEM_PATHS ) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) else() + foreach(ver ${_Boost_KNOWN_VERSIONS}) + string(REPLACE "." "_" ver "${ver}") + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/local/boost_${ver}") + endforeach() + _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS C:/boost/lib C:/boost /sw/local/lib ) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") endif() endif() endforeach() @@ -1457,8 +1501,7 @@ endif() _Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS) # If thread is required, get the thread libs as a dependency -list(FIND Boost_FIND_COMPONENTS thread _Boost_THREAD_DEPENDENCY_LIBS) -if(NOT _Boost_THREAD_DEPENDENCY_LIBS EQUAL -1) +if("thread" IN_LIST Boost_FIND_COMPONENTS) include(CMakeFindDependencyMacro) find_dependency(Threads) endif() @@ -1524,17 +1567,24 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) # # Find RELEASE libraries # - set(_boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} + unset(_boost_RELEASE_NAMES) + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ) + endforeach() + list(APPEND _boost_RELEASE_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) if(_boost_STATIC_RUNTIME_WORKAROUND) set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) + endforeach() list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) endif() @@ -1565,18 +1615,25 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) # # Find DEBUG libraries # - set(_boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} + unset(_boost_DEBUG_NAMES) + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ) + endforeach() + list(APPEND _boost_DEBUG_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) if(_boost_STATIC_RUNTIME_WORKAROUND) set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") + foreach(compiler IN LISTS _boost_COMPILER) + list(APPEND _boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) + endforeach() list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) endif() @@ -1611,6 +1668,9 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) + # Check if component requires some compiler features + _Boost_COMPILER_FEATURES(${COMPONENT} _Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) + endforeach() # Restore the original find library ordering @@ -1782,6 +1842,10 @@ if(Boost_FOUND) set_target_properties(Boost::${COMPONENT} PROPERTIES INTERFACE_LINK_LIBRARIES "${_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES}") endif() + if(_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) + set_target_properties(Boost::${COMPONENT} PROPERTIES + INTERFACE_COMPILE_FEATURES "${_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES}") + endif() endif() endif() endforeach() @@ -1862,3 +1926,6 @@ list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) list(SORT _Boost_COMPONENTS_SEARCHED) set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" CACHE INTERNAL "Components requested for this build tree.") + +# Restore project's policies +cmake_policy(POP) diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 6b76c25ba..a4dca5433 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -67,6 +67,13 @@ # -- 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 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. @@ -1740,12 +1747,12 @@ macro(CUDA_ADD_LIBRARY cuda_target) # variable will have been defined. CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS("${link_file}" ${cuda_target} "${_options}" "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}") - target_link_libraries(${cuda_target} + target_link_libraries(${cuda_target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_LIBRARIES} ) if(CUDA_SEPARABLE_COMPILATION) - target_link_libraries(${cuda_target} + target_link_libraries(${cuda_target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cudadevrt_LIBRARY} ) endif() @@ -1790,7 +1797,7 @@ macro(CUDA_ADD_EXECUTABLE cuda_target) # variable will have been defined. CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS("${link_file}" ${cuda_target} "${_options}" "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}") - target_link_libraries(${cuda_target} + target_link_libraries(${cuda_target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_LIBRARIES} ) @@ -1818,7 +1825,7 @@ macro(cuda_compile_base cuda_target format generated_files) else() set(_counter 1) endif() - set(_cuda_target "${_cuda_target}_${_counter}") + string(APPEND _cuda_target "_${_counter}") set_property(DIRECTORY PROPERTY _cuda_internal_phony_counter ${_counter}) # Separate the sources from the options @@ -1876,9 +1883,9 @@ endmacro() ############################################################################### macro(CUDA_ADD_CUFFT_TO_TARGET target) if (CUDA_BUILD_EMULATION) - target_link_libraries(${target} ${CUDA_cufftemu_LIBRARY}) + target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cufftemu_LIBRARY}) else() - target_link_libraries(${target} ${CUDA_cufft_LIBRARY}) + target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cufft_LIBRARY}) endif() endmacro() @@ -1889,9 +1896,9 @@ endmacro() ############################################################################### macro(CUDA_ADD_CUBLAS_TO_TARGET target) if (CUDA_BUILD_EMULATION) - target_link_libraries(${target} ${CUDA_cublasemu_LIBRARY}) + target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cublasemu_LIBRARY}) else() - target_link_libraries(${target} ${CUDA_cublas_LIBRARY} ${CUDA_cublas_device_LIBRARY}) + target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cublas_LIBRARY} ${CUDA_cublas_device_LIBRARY}) endif() endmacro() diff --git a/Modules/FindCygwin.cmake b/Modules/FindCygwin.cmake index 90cbd5208..b2ed70333 100644 --- a/Modules/FindCygwin.cmake +++ b/Modules/FindCygwin.cmake @@ -8,13 +8,13 @@ # this module looks for Cygwin if (WIN32) - find_path(CYGWIN_INSTALL_PATH + find_program(CYGWIN_INSTALL_PATH cygwin.bat "C:/Cygwin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Cygwin\\setup;rootdir]" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/;native]" ) - + get_filename_component(CYGWIN_INSTALL_PATH "${CYGWIN_INSTALL_PATH}" DIRECTORY) mark_as_advanced( CYGWIN_INSTALL_PATH ) diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake index 45fab829c..f6c8e3f24 100644 --- a/Modules/FindDevIL.cmake +++ b/Modules/FindDevIL.cmake @@ -25,7 +25,7 @@ # library interfaces with OpenGL. It is not strictly needed # in applications. # IL_INCLUDE_DIR - where to find the il.h, ilu.h and ilut.h files. -# IL_FOUND - this is set to TRUE if all the above variables were set. +# DevIL_FOUND - this is set to TRUE if all the above variables were set. # This will be set to false if ILU or ILUT are not found, # even if they are not needed. In most systems, if one # library is found all the others are as well. That's the @@ -45,7 +45,7 @@ find_path(IL_INCLUDE_DIR il.h find_library(IL_LIBRARIES NAMES IL DEVIL - PATH_SUFFIXES lib64 lib lib32 + PATH_SUFFIXES libx32 lib64 lib lib32 DOC "The file that corresponds to the base il library." ) @@ -53,7 +53,7 @@ find_library(IL_LIBRARIES find_library(ILUT_LIBRARIES NAMES ILUT - PATH_SUFFIXES lib64 lib lib32 + PATH_SUFFIXES libx32 lib64 lib lib32 DOC "The file that corresponds to the il (system?) utility library." ) @@ -61,7 +61,7 @@ find_library(ILUT_LIBRARIES find_library(ILU_LIBRARIES NAMES ILU - PATH_SUFFIXES lib64 lib lib32 + PATH_SUFFIXES libx32 lib64 lib lib32 DOC "The file that corresponds to the il utility library." ) @@ -70,3 +70,5 @@ find_library(ILU_LIBRARIES FIND_PACKAGE_HANDLE_STANDARD_ARGS(DevIL DEFAULT_MSG IL_LIBRARIES ILU_LIBRARIES IL_INCLUDE_DIR) +# provide legacy variable for compatiblity +set(IL_FOUND ${DevIL_FOUND}) diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake index 8275ac80c..46bf340dd 100644 --- a/Modules/FindDoxygen.cmake +++ b/Modules/FindDoxygen.cmake @@ -1,161 +1,1050 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -#.rst: -# FindDoxygen -# ----------- -# -# This module looks for Doxygen and the path to Graphviz's dot -# -# Doxygen is a documentation generation tool. Please see -# http://www.doxygen.org -# -# This module accepts the following optional variables: -# -# :: -# -# DOXYGEN_SKIP_DOT = If true this module will skip trying to find Dot -# (an optional component often used by Doxygen) -# -# -# -# This modules defines the following variables: -# -# :: -# -# DOXYGEN_EXECUTABLE = The path to the doxygen command. -# DOXYGEN_FOUND = Was Doxygen found or not? -# DOXYGEN_VERSION = The version reported by doxygen --version -# -# -# -# :: -# -# DOXYGEN_DOT_EXECUTABLE = The path to the dot program used by doxygen. -# DOXYGEN_DOT_FOUND = Was Dot found or not? -# -# For compatibility with older versions of CMake, the now-deprecated -# variable ``DOXYGEN_DOT_PATH`` is set to the path to the directory -# containing ``dot`` as reported in ``DOXYGEN_DOT_EXECUTABLE``. -# The path may have forward slashes even on Windows and is not -# suitable for direct substitution into a ``Doxyfile.in`` template. -# If you need this value, use :command:`get_filename_component` -# to compute it from ``DOXYGEN_DOT_EXECUTABLE`` directly, and -# perhaps the :command:`file(TO_NATIVE_PATH)` command to prepare -# the path for a Doxygen configuration file. +#[=======================================================================[.rst: +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: + +``dot`` + `Graphviz `_ ``dot`` utility used to render various + graphs. +``mscgen`` + `Message Chart Generator `_ utility used + by Doxygen's ``\msc`` and ``\mscfile`` commands. +``dia`` + `Dia `_ the diagram editor used by Doxygen's + ``\diafile`` command. + +Examples: + +.. code-block:: cmake + + # Require dot, treat the other components as optional + find_package(Doxygen + REQUIRED dot + OPTIONAL_COMPONENTS mscgen dia) + +The following variables are defined by this module: + +.. variable:: DOXYGEN_FOUND + + True if the ``doxygen`` executable was found. + +.. variable:: DOXYGEN_VERSION + + 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): + +:: + + Doxygen::doxygen + Doxygen::dot + Doxygen::mscgen + Doxygen::dia + + +Functions +^^^^^^^^^ + +.. command:: doxygen_add_docs + + 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 + will be sufficient to give sensible results. The function supports the + ability to customize the Doxygen configuration used to build the + documentation. + + :: + + doxygen_add_docs(targetName + [filesOrDirs...] + [WORKING_DIRECTORY dir] + [COMMENT comment]) + + The function constructs a ``Doxyfile`` and defines a custom target that runs + Doxygen on that generated file. The listed files and directories are used as + the ``INPUT`` of the generated ``Doxyfile`` and they can contain wildcards. + Any files that are listed explicitly will also be added as ``SOURCES`` of the + custom target so they will show up in an IDE project's source list. + + So that relative input paths work as expected, by default the working + directory of the Doxygen command will be the current source directory (i.e. + :variable:`CMAKE_CURRENT_SOURCE_DIR`). This can be overridden with the + ``WORKING_DIRECTORY`` option to change the directory used as the relative + base point. Note also that Doxygen's default behavior is to strip the working + directory from relative paths in the generated documentation (see the + ``STRIP_FROM_PATH`` `Doxygen config option + `_ for details). + + If provided, the optional ``comment`` will be passed as the ``COMMENT`` for + the :command:`add_custom_target` command used to create the custom target + internally. + + The contents of the generated ``Doxyfile`` can be customized by setting CMake + variables before calling ``doxygen_add_docs()``. Any variable with a name of + the form ``DOXYGEN_`` will have its value substituted for the + corresponding ```` configuration option in the ``Doxyfile``. See the + `Doxygen documentation `_ for the + full list of supported configuration options. + + Some of Doxygen's defaults are overridden to provide more appropriate + behavior for a CMake project. Each of the following will be explicitly set + unless the variable already has a value before ``doxygen_add_docs()`` is + called (with some exceptions noted): + + .. variable:: DOXYGEN_HAVE_DOT + + Set to ``YES`` if the ``dot`` component was requested and it was found, + ``NO`` otherwise. Any existing value of ``DOXYGEN_HAVE_DOT`` is ignored. + + .. variable:: DOXYGEN_DOT_MULTI_TARGETS + + Set to ``YES`` by this module (note that this requires a ``dot`` version + newer than 1.8.10). This option is only meaningful if ``DOXYGEN_HAVE_DOT`` + is also set to ``YES``. + + .. variable:: DOXYGEN_GENERATE_LATEX + + Set to ``NO`` by this module. + + .. variable:: DOXYGEN_WARN_FORMAT + + For Visual Studio based generators, this is set to the form recognized by + the Visual Studio IDE: ``$file($line) : $text``. For all other generators, + Doxygen's default value is not overridden. + + .. variable:: DOXYGEN_PROJECT_NAME + + Populated with the name of the current project (i.e. + :variable:`PROJECT_NAME`). + + .. variable:: DOXYGEN_PROJECT_NUMBER + + Populated with the version of the current project (i.e. + :variable:`PROJECT_VERSION`). + + .. variable:: DOXYGEN_PROJECT_BRIEF + + Populated with the description of the current project (i.e. + :variable:`PROJECT_DESCRIPTION`). + + .. variable:: DOXYGEN_INPUT + + Projects should not set this variable. It will be populated with the set of + files and directories passed to ``doxygen_add_docs()``, thereby providing + consistent behavior with the other built-in commands like + :command:`add_executable`, :command:`add_library` and + :command:`add_custom_target`. If a variable named ``DOXYGEN_INPUT`` is set + by the project, it will be ignored and a warning will be issued. + + .. variable:: DOXYGEN_RECURSIVE + + Set to ``YES`` by this module. + + .. variable:: DOXYGEN_EXCLUDE_PATTERNS + + If the set of inputs includes directories, this variable will specify + patterns used to exclude files from them. The following patterns are added + by ``doxygen_add_docs()`` to ensure CMake-specific files and directories + are not included in the input. If the project sets + ``DOXYGEN_EXCLUDE_PATTERNS``, those contents are merged with these + additional patterns rather than replacing them: + + :: + + */.git/* + */.svn/* + */.hg/* + */CMakeFiles/* + */_CPack_Packages/* + DartConfiguration.tcl + CMakeLists.txt + CMakeCache.txt + + .. variable:: DOXYGEN_OUTPUT_DIRECTORY + + Set to :variable:`CMAKE_CURRENT_BINARY_DIR` by this module. Note that if + the project provides its own value for this and it is a relative path, it + will be converted to an absolute path relative to the current binary + directory. This is necessary because doxygen will normally be run from a + directory within the source tree so that relative source paths work as + expected. If this directory does not exist, it will be recursively created + prior to executing the doxygen commands. + +To change any of these defaults or override any other Doxygen config option, +set relevant variables before calling ``doxygen_add_docs()``. For example: + + .. code-block:: cmake + + set(DOXYGEN_GENERATE_HTML NO) + set(DOXYGEN_GENERATE_MAN YES) + + doxygen_add_docs( + doxygen + ${PROJECT_SOURCE_DIR} + COMMENT "Generate man pages" + ) + +A number of Doxygen config options accept lists of values, but Doxygen requires +them to be separated by whitespace. CMake variables hold lists as a string with +items separated by semi-colons, so a conversion needs to be performed. The +``doxygen_add_docs()`` command specifically checks the following Doxygen config +options and will convert their associated CMake variable's contents into the +required form if set. + +:: + + ABBREVIATE_BRIEF + ALIASES + CITE_BIB_FILES + DIAFILE_DIRS + DOTFILE_DIRS + DOT_FONTPATH + ENABLED_SECTIONS + EXAMPLE_PATH + EXAMPLE_PATTERNS + EXCLUDE + EXCLUDE_PATTERNS + EXCLUDE_SYMBOLS + EXPAND_AS_DEFINED + EXTENSION_MAPPING + EXTRA_PACKAGES + EXTRA_SEARCH_MAPPINGS + FILE_PATTERNS + FILTER_PATTERNS + FILTER_SOURCE_PATTERNS + HTML_EXTRA_FILES + HTML_EXTRA_STYLESHEET + IGNORE_PREFIX + IMAGE_PATH + INCLUDE_FILE_PATTERNS + INCLUDE_PATH + INPUT + LATEX_EXTRA_FILES + LATEX_EXTRA_STYLESHEET + MATHJAX_EXTENSIONS + MSCFILE_DIRS + PLANTUML_INCLUDE_PATH + PREDEFINED + QHP_CUST_FILTER_ATTRS + QHP_SECT_FILTER_ATTRS + STRIP_FROM_INC_PATH + STRIP_FROM_PATH + TAGFILES + TCL_SUBST + +The following single value Doxygen options would be quoted automatically +if they contain at least one space: + +:: + + CHM_FILE + DIA_PATH + DOCBOOK_OUTPUT + DOCSET_FEEDNAME + DOCSET_PUBLISHER_NAME + DOT_FONTNAME + DOT_PATH + EXTERNAL_SEARCH_ID + FILE_VERSION_FILTER + GENERATE_TAGFILE + HHC_LOCATION + HTML_FOOTER + HTML_HEADER + HTML_OUTPUT + HTML_STYLESHEET + INPUT_FILTER + LATEX_FOOTER + LATEX_HEADER + LATEX_OUTPUT + LAYOUT_FILE + MAN_OUTPUT + MAN_SUBDIR + MATHJAX_CODEFILE + MSCGEN_PATH + OUTPUT_DIRECTORY + PERL_PATH + PLANTUML_JAR_PATH + PROJECT_BRIEF + PROJECT_LOGO + PROJECT_NAME + QCH_FILE + QHG_LOCATION + QHP_CUST_FILTER_NAME + QHP_VIRTUAL_FOLDER + RTF_EXTENSIONS_FILE + RTF_OUTPUT + RTF_STYLESHEET_FILE + SEARCHDATA_FILE + USE_MDFILE_AS_MAINPAGE + WARN_FORMAT + WARN_LOGFILE + XML_OUTPUT + +Deprecated Result Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For compatibility with previous versions of CMake, the following variables +are also defined but they are deprecated and should no longer be used: + +.. variable:: DOXYGEN_EXECUTABLE + + The path to the ``doxygen`` command. If projects need to refer to the + ``doxygen`` executable directly, they should use the ``Doxygen::doxygen`` + import target instead. + +.. variable:: DOXYGEN_DOT_FOUND + + True if the ``dot`` executable was found. + +.. variable:: DOXYGEN_DOT_EXECUTABLE + + The path to the ``dot`` command. If projects need to refer to the ``dot`` + executable directly, they should use the ``Doxygen::dot`` import target + instead. + +.. variable:: DOXYGEN_DOT_PATH + + The path to the directory containing the ``dot`` executable as reported in + ``DOXYGEN_DOT_EXECUTABLE``. The path may have forward slashes even on Windows + and is not suitable for direct substitution into a ``Doxyfile.in`` template. + If you need this value, get the :prop_tgt:`IMPORTED_LOCATION` property of the + ``Doxygen::dot`` target and use :command:`get_filename_component` to extract + the directory part of that path. You may also want to consider using + :command:`file(TO_NATIVE_PATH)` to prepare the path for a Doxygen + configuration file. + + +Deprecated Hint Variables +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. variable:: DOXYGEN_SKIP_DOT + + This variable has no any effect for component form of ``find_package``. + In backward compatibility mode (i.e. without components list) it prevents + the finder module from searching for Graphviz's ``dot`` utility. + +#]=======================================================================] # For backwards compatibility support if(Doxygen_FIND_QUIETLY) - set(DOXYGEN_FIND_QUIETLY TRUE) + set(DOXYGEN_FIND_QUIETLY TRUE) endif() # ===== Rationale for OS X AppBundle mods below ===== -# With the OS X GUI version, Doxygen likes to be installed to /Applications and -# it contains the doxygen executable in the bundle. In the versions I've -# seen, it is located in Resources, but in general, more often binaries are -# located in MacOS. -# -# NOTE: The official Doxygen.app that is distributed for OS X uses non-standard -# conventions. Instead of the command-line "doxygen" tool being placed in -# Doxygen.app/Contents/MacOS, "Doxywizard" is placed there instead and -# "doxygen" is placed in Contents/Resources. This is most likely done -# so that something happens when people double-click on the Doxygen.app -# package. Unfortunately, CMake gets confused by this as when it sees the -# bundle it uses "Doxywizard" as the executable to use instead of -# "doxygen". Therefore to work-around this issue we temporarily disable -# the app-bundle feature, just for this CMake module: +# With the OS X GUI version, Doxygen likes to be installed to /Applications +# and it contains the doxygen executable in the bundle. In the versions I've +# seen, it is located in Resources, but in general, more often binaries are +# located in MacOS. +# +# NOTE: The official Doxygen.app distributed for OS X uses non-standard +# conventions. Instead of the command-line "doxygen" tool being placed in +# Doxygen.app/Contents/MacOS, "Doxywizard" is placed there instead and +# "doxygen" is placed in Contents/Resources. This is most likely done +# so that something happens when people double-click on the Doxygen.app +# package. Unfortunately, CMake gets confused by this as when it sees the +# bundle it uses "Doxywizard" as the executable to use instead of +# "doxygen". Therefore to work-around this issue we temporarily disable +# the app-bundle feature, just for this CMake module: +# if(APPLE) - # Save the old setting + # Save the old setting set(TEMP_DOXYGEN_SAVE_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE}) # Disable the App-bundle detection feature set(CMAKE_FIND_APPBUNDLE "NEVER") endif() -# FYI: -# In the older versions of OS X Doxygen, dot was included with the -# Doxygen bundle. But the new versions require you to download -# Graphviz.app which contains "dot" in it's bundle. +# FYI: +# In older versions of OS X Doxygen, dot was included with the Doxygen bundle, +# but newer versions require you to download Graphviz.app which contains "dot" +# or use something like homebrew. # ============== End OSX stuff ================ # # Find Doxygen... # +macro(_Doxygen_find_doxygen) + find_program( + DOXYGEN_EXECUTABLE + NAMES doxygen + PATHS + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\doxygen_is1;Inno Setup: App Path]/bin" + /Applications/Doxygen.app/Contents/Resources + /Applications/Doxygen.app/Contents/MacOS + DOC "Doxygen documentation generation tool (http://www.doxygen.org)" + ) + mark_as_advanced(DOXYGEN_EXECUTABLE) -find_program(DOXYGEN_EXECUTABLE - NAMES doxygen - PATHS - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\doxygen_is1;Inno Setup: App Path]/bin" - /Applications/Doxygen.app/Contents/Resources - /Applications/Doxygen.app/Contents/MacOS - DOC "Doxygen documentation generation tool (http://www.doxygen.org)" -) + if(DOXYGEN_EXECUTABLE) + execute_process( + COMMAND "${DOXYGEN_EXECUTABLE}" --version + OUTPUT_VARIABLE DOXYGEN_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _Doxygen_version_result + ) + if(_Doxygen_version_result) + message(WARNING "Unable to determine doxygen version: ${_Doxygen_version_result}") + endif() -if(DOXYGEN_EXECUTABLE) - execute_process(COMMAND ${DOXYGEN_EXECUTABLE} "--version" OUTPUT_VARIABLE DOXYGEN_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) -endif() + # Create an imported target for Doxygen + if(NOT TARGET Doxygen::doxygen) + add_executable(Doxygen::doxygen IMPORTED GLOBAL) + set_target_properties(Doxygen::doxygen PROPERTIES + IMPORTED_LOCATION "${DOXYGEN_EXECUTABLE}" + ) + endif() + endif() +endmacro() -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Doxygen REQUIRED_VARS DOXYGEN_EXECUTABLE VERSION_VAR DOXYGEN_VERSION) - -# -# Find Dot... -# - -set(_x86 "(x86)") -file(GLOB _Doxygen_GRAPHVIZ_BIN_DIRS - "$ENV{ProgramFiles}/Graphviz*/bin" - "$ENV{ProgramFiles${_x86}}/Graphviz*/bin" - ) -unset(_x86) - -if(NOT DOXYGEN_SKIP_DOT) - find_program(DOXYGEN_DOT_EXECUTABLE - NAMES dot - PATHS - ${_Doxygen_GRAPHVIZ_BIN_DIRS} - "$ENV{ProgramFiles}/ATT/Graphviz/bin" - "C:/Program Files/ATT/Graphviz/bin" - [HKEY_LOCAL_MACHINE\\SOFTWARE\\ATT\\Graphviz;InstallPath]/bin - /Applications/Graphviz.app/Contents/MacOS - /Applications/Doxygen.app/Contents/Resources - /Applications/Doxygen.app/Contents/MacOS - DOC "Graphviz Dot tool for using Doxygen" - ) - - if(DOXYGEN_DOT_EXECUTABLE) - set(DOXYGEN_DOT_FOUND TRUE) - # The Doxyfile wants the path to Dot, not the entire path and executable - get_filename_component(DOXYGEN_DOT_PATH "${DOXYGEN_DOT_EXECUTABLE}" PATH) - endif() +# +# Find Diagram Editor... +# +macro(_Doxygen_find_dia) + set(_x86 "(x86)") + find_program( + DOXYGEN_DIA_EXECUTABLE + NAMES dia + PATHS + "$ENV{ProgramFiles}/Dia" + "$ENV{ProgramFiles${_x86}}/Dia" + DOC "Diagram Editor tool for use with Doxygen" + ) + mark_as_advanced(DOXYGEN_DIA_EXECUTABLE) + + if(DOXYGEN_DIA_EXECUTABLE) + # The Doxyfile wants the path to the utility, not the entire path + # including file name + get_filename_component(DOXYGEN_DIA_PATH + "${DOXYGEN_DIA_EXECUTABLE}" + DIRECTORY) + if(WIN32) + file(TO_NATIVE_PATH "${DOXYGEN_DIA_PATH}" DOXYGEN_DIA_PATH) + endif() + + # Create an imported target for component + if(NOT TARGET Doxygen::dia) + add_executable(Doxygen::dia IMPORTED GLOBAL) + set_target_properties(Doxygen::dia PROPERTIES + IMPORTED_LOCATION "${DOXYGEN_DIA_EXECUTABLE}" + ) + endif() + endif() + + unset(_x86) +endmacro() + +# +# Find Graphviz Dot... +# +macro(_Doxygen_find_dot) + set(_x86 "(x86)") + file( + GLOB _Doxygen_GRAPHVIZ_BIN_DIRS + "$ENV{ProgramFiles}/Graphviz*/bin" + "$ENV{ProgramFiles${_x86}}/Graphviz*/bin" + ) + find_program( + DOXYGEN_DOT_EXECUTABLE + NAMES dot + PATHS + ${_Doxygen_GRAPHVIZ_BIN_DIRS} + "$ENV{ProgramFiles}/ATT/Graphviz/bin" + "C:/Program Files/ATT/Graphviz/bin" + [HKEY_LOCAL_MACHINE\\SOFTWARE\\ATT\\Graphviz;InstallPath]/bin + /Applications/Graphviz.app/Contents/MacOS + /Applications/Doxygen.app/Contents/Resources + /Applications/Doxygen.app/Contents/MacOS + DOC "Dot tool for use with Doxygen" + ) + mark_as_advanced(DOXYGEN_DOT_EXECUTABLE) + + if(DOXYGEN_DOT_EXECUTABLE) + # The Doxyfile wants the path to the utility, not the entire path + # including file name + get_filename_component(DOXYGEN_DOT_PATH + "${DOXYGEN_DOT_EXECUTABLE}" + DIRECTORY) + if(WIN32) + file(TO_NATIVE_PATH "${DOXYGEN_DOT_PATH}" DOXYGEN_DOT_PATH) + endif() + + # Create an imported target for component + if(NOT TARGET Doxygen::dot) + add_executable(Doxygen::dot IMPORTED GLOBAL) + set_target_properties(Doxygen::dot PROPERTIES + IMPORTED_LOCATION "${DOXYGEN_DOT_EXECUTABLE}" + ) + endif() + endif() + + unset(_Doxygen_GRAPHVIZ_BIN_DIRS) + unset(_x86) +endmacro() +# +# Find Message Sequence Chart... +# +macro(_Doxygen_find_mscgen) + set(_x86 "(x86)") + find_program( + DOXYGEN_MSCGEN_EXECUTABLE + NAMES mscgen + PATHS + "$ENV{ProgramFiles}/Mscgen" + "$ENV{ProgramFiles${_x86}}/Mscgen" + DOC "Message sequence chart tool for use with Doxygen" + ) + mark_as_advanced(DOXYGEN_MSCGEN_EXECUTABLE) + + if(DOXYGEN_MSCGEN_EXECUTABLE) + # The Doxyfile wants the path to the utility, not the entire path + # including file name + get_filename_component(DOXYGEN_MSCGEN_PATH + "${DOXYGEN_MSCGEN_EXECUTABLE}" + DIRECTORY) + if(WIN32) + file(TO_NATIVE_PATH "${DOXYGEN_MSCGEN_PATH}" DOXYGEN_MSCGEN_PATH) + endif() + + # Create an imported target for component + if(NOT TARGET Doxygen::mscgen) + add_executable(Doxygen::mscgen IMPORTED GLOBAL) + set_target_properties(Doxygen::mscgen PROPERTIES + IMPORTED_LOCATION "${DOXYGEN_MSCGEN_EXECUTABLE}" + ) + endif() + endif() + + unset(_x86) +endmacro() + +# Make sure `doxygen` is one of the components to find +set(_Doxygen_keep_backward_compat FALSE) +if(NOT Doxygen_FIND_COMPONENTS) + # Search at least for `doxygen` executable + set(Doxygen_FIND_COMPONENTS doxygen) + # Preserve backward compatibility: + # search for `dot` also if `DOXYGEN_SKIP_DOT` is not explicitly disable this. + if(NOT DOXYGEN_SKIP_DOT) + list(APPEND Doxygen_FIND_COMPONENTS dot) + endif() + set(_Doxygen_keep_backward_compat TRUE) +elseif(NOT doxygen IN_LIST Doxygen_FIND_COMPONENTS) + list(INSERT Doxygen_FIND_COMPONENTS 0 doxygen) endif() # -# Backwards compatibility... +# Find all requested components of Doxygen... # +foreach(_comp IN LISTS Doxygen_FIND_COMPONENTS) + if(_comp STREQUAL "doxygen") + _Doxygen_find_doxygen() + elseif(_comp STREQUAL "dia") + _Doxygen_find_dia() + elseif(_comp STREQUAL "dot") + _Doxygen_find_dot() + elseif(_comp STREQUAL "mscgen") + _Doxygen_find_mscgen() + else() + message(WARNING "${_comp} is not a valid Doxygen component") + set(Doxygen_${_comp}_FOUND FALSE) + continue() + endif() + + if(TARGET Doxygen::${_comp}) + set(Doxygen_${_comp}_FOUND TRUE) + else() + set(Doxygen_${_comp}_FOUND FALSE) + endif() +endforeach() +unset(_comp) + +# Verify find results +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +find_package_handle_standard_args( + Doxygen + REQUIRED_VARS DOXYGEN_EXECUTABLE + VERSION_VAR DOXYGEN_VERSION + HANDLE_COMPONENTS +) +# +# Backwards compatibility... +# if(APPLE) - # Restore the old app-bundle setting setting - set(CMAKE_FIND_APPBUNDLE ${TEMP_DOXYGEN_SAVE_CMAKE_FIND_APPBUNDLE}) + # Restore the old app-bundle setting + set(CMAKE_FIND_APPBUNDLE ${TEMP_DOXYGEN_SAVE_CMAKE_FIND_APPBUNDLE}) endif() -# Maintain the _FOUND variables as "YES" or "NO" for backwards compatibility -# (allows people to stuff them directly into Doxyfile with configure_file()) +# Maintain the _FOUND variables as "YES" or "NO" for backwards +# compatibility. This allows people to substitute them directly into +# Doxyfile with configure_file(). if(DOXYGEN_FOUND) - set(DOXYGEN_FOUND "YES") + set(DOXYGEN_FOUND "YES") else() - set(DOXYGEN_FOUND "NO") + set(DOXYGEN_FOUND "NO") endif() -if(DOXYGEN_DOT_FOUND) - set(DOXYGEN_DOT_FOUND "YES") -else() - set(DOXYGEN_DOT_FOUND "NO") +if(_Doxygen_keep_backward_compat) + if(Doxygen_dot_FOUND) + set(DOXYGEN_DOT_FOUND "YES") + else() + set(DOXYGEN_DOT_FOUND "NO") + endif() + + # For backwards compatibility support for even older CMake versions + set(DOXYGEN ${DOXYGEN_EXECUTABLE}) + set(DOT ${DOXYGEN_DOT_EXECUTABLE}) + + # No need to keep any backward compatibility for `DOXYGEN_MSCGEN_XXX` + # and `DOXYGEN_DIA_XXX` since they were not supported before component + # support was added endif() +unset(_Doxygen_keep_backward_compat) -# For backwards compatibility support -set (DOXYGEN ${DOXYGEN_EXECUTABLE} ) -set (DOT ${DOXYGEN_DOT_EXECUTABLE} ) +# +# Allow full control of Doxygen from CMakeLists.txt +# + +# Prepare a template Doxyfile and Doxygen's default values CMake file +if(TARGET Doxygen::doxygen) + # If doxygen was found, use it to generate a minimal default Doxyfile. + # We will delete this file after we have finished using it below to + # generate the other files that doxygen_add_docs() will use. + set(_Doxygen_tpl "${CMAKE_BINARY_DIR}/CMakeDoxyfile.tpl") + execute_process( + COMMAND "${DOXYGEN_EXECUTABLE}" -s -g "${_Doxygen_tpl}" + OUTPUT_QUIET + RESULT_VARIABLE _Doxygen_tpl_result + ) + if(_Doxygen_tpl_result) + message(FATAL_ERROR + "Unable to generate Doxyfile template: ${_Doxygen_tpl_result}") + elseif(NOT EXISTS "${_Doxygen_tpl}") + message(FATAL_ERROR + "Doxygen has failed to generate a Doxyfile template") + endif() + + # Write a do-not-edit header to files we are going to generate... + set(_Doxygen_dne_header +[[ +# +# DO NOT EDIT! THIS FILE WAS GENERATED BY CMAKE! +# + +]] + ) + # We only need one copy of these across the whole build, since their + # content is only dependent on the version of Doxygen being used. Therefore + # we always put them at the top of the build tree so that they are in a + # predictable location. + set(_doxyfile_in "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in") + set(_doxyfile_defaults "${CMAKE_BINARY_DIR}/CMakeDoxygenDefaults.cmake") + + file(WRITE "${_doxyfile_in}" ${_Doxygen_dne_header}) + file(WRITE "${_doxyfile_defaults}" ${_Doxygen_dne_header}) + + # Get strings containing a configuration key from the template Doxyfile + # we obtained from this version of Doxygen. Because some options are split + # across multiple lines by ending lines with backslashes, we cannot just + # use file(STRINGS...) with a REGEX. Instead, read lines without a REGEX + # so that file(STRINGS...) handles the trailing backslash as a line + # continuation. It stores multi-lines as lists, so we then have to replace + # the ";" list separator with backslashed newlines again so that we get the + # original content stored back as the value part. + file(STRINGS "${_Doxygen_tpl}" _file_lines) + unset(_Doxygen_tpl_params) + foreach(_line IN LISTS _file_lines) + if(_line MATCHES "([A-Z][A-Z0-9_]+)( *=)(.*)") + set(_key "${CMAKE_MATCH_1}") + set(_eql "${CMAKE_MATCH_2}") + string(REPLACE ";" "\\\n" _value "${CMAKE_MATCH_3}") + list(APPEND _Doxygen_tpl_params "${_key}${_eql}${_value}") + endif() + endforeach() + + # Build up a Doxyfile that provides @configVar@ substitutions for each + # Doxygen config option as well as a separate CMake script which provides + # the default value for each of those options if the project doesn't supply + # them. Each config option will support substitution of a CMake variable + # of the same name except with DOXYGEN_ prepended. + foreach(_Doxygen_param IN LISTS _Doxygen_tpl_params) + if(_Doxygen_param MATCHES "([A-Z][A-Z0-9_]+)( *)=( (.*))?") + # Ok, this is a config key with a value + if(CMAKE_MATCH_COUNT EQUAL 4) + file(APPEND "${_doxyfile_in}" + "${CMAKE_MATCH_1}${CMAKE_MATCH_2}= @DOXYGEN_${CMAKE_MATCH_1}@\n") + # Remove the backslashes we had to preserve to handle newlines + string(REPLACE "\\\n" "\n" _value "${CMAKE_MATCH_4}") + file(APPEND "${_doxyfile_defaults}" +"if(NOT DEFINED DOXYGEN_${CMAKE_MATCH_1}) + set(DOXYGEN_${CMAKE_MATCH_1} ${_value}) +endif() +") + # Ok, this is a config key with empty default value + elseif(CMAKE_MATCH_COUNT EQUAL 2) + file(APPEND "${_doxyfile_in}" + "${CMAKE_MATCH_1}${CMAKE_MATCH_2}= @DOXYGEN_${CMAKE_MATCH_1}@\n") + else() + message(AUTHOR_WARNING +"Unexpected line format! Code review required!\nFault line: ${_Doxygen_param}") + endif() + else() + message(AUTHOR_WARNING +"Unexpected line format! Code review required!\nFault line: ${_Doxygen_param}") + endif() + endforeach() + + # Ok, dumped defaults are not needed anymore... + file(REMOVE "${_Doxygen_tpl}") + + unset(_Doxygen_param) + unset(_Doxygen_tpl_params) + unset(_Doxygen_dne_header) + unset(_Doxygen_tpl) + +endif() + +function(doxygen_quote_value VARIABLE) + # Quote a value of the given variable if: + # - variable parameter was really given + # - a variable it points is defined + # - a value doesn't quoted already + # - and it has spaces + if(VARIABLE AND DEFINED ${VARIABLE} AND + NOT ${VARIABLE} MATCHES "^\".* .*\"$" AND ${VARIABLE} MATCHES " ") + set(${VARIABLE} "\"${${VARIABLE}}\"" PARENT_SCOPE) + endif() +endfunction() + +function(doxygen_list_to_quoted_strings LIST_VARIABLE) + if(LIST_VARIABLE AND DEFINED ${LIST_VARIABLE}) + unset(_inputs) + unset(_sep) + foreach(_in IN LISTS ${LIST_VARIABLE}) + doxygen_quote_value(_in) + string(APPEND _inputs "${_sep}${_in}") + set(_sep " ") + endforeach() + set(${LIST_VARIABLE} "${_inputs}" PARENT_SCOPE) + endif() +endfunction() + +function(doxygen_add_docs targetName) + set(_options) + set(_one_value_args WORKING_DIRECTORY COMMENT) + set(_multi_value_args) + cmake_parse_arguments(_args + "${_options}" + "${_one_value_args}" + "${_multi_value_args}" + ${ARGN}) + + if(NOT _args_COMMENT) + set(_args_COMMENT "Generate API documentation for ${targetName}") + endif() + + if(NOT _args_WORKING_DIRECTORY) + set(_args_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") + endif() + + if(DEFINED DOXYGEN_INPUT) + message(WARNING +"DOXYGEN_INPUT is set but it will be ignored. Pass the files and directories \ +directly to the doxygen_add_docs() command instead.") + endif() + set(DOXYGEN_INPUT ${_args_UNPARSED_ARGUMENTS}) + + if(NOT TARGET Doxygen::doxygen) + message(FATAL_ERROR "Doxygen was not found, needed by \ +doxygen_add_docs() for target ${targetName}") + endif() + + # If not already defined, set some relevant defaults based on the + # assumption that the documentation is for the whole project. Details + # specified in the project() command will be used to populate a number of + # these defaults. + + if(NOT DEFINED DOXYGEN_PROJECT_NAME) + # The PROJECT_NAME tag is a single word (or a sequence of words + # surrounded by double-quotes, unless you are using Doxywizard) that + # should identify the project for which the documentation is generated. + # This name is used in the title of most generated pages and in a few + # other places. The default value is: My Project. + set(DOXYGEN_PROJECT_NAME ${PROJECT_NAME}) + endif() + + if(NOT DEFINED DOXYGEN_PROJECT_NUMBER) + # The PROJECT_NUMBER tag can be used to enter a project or revision + # number. This could be handy for archiving the generated documentation + # or if some version control system is used. + set(DOXYGEN_PROJECT_NUMBER ${PROJECT_VERSION}) + endif() + + if(NOT DEFINED DOXYGEN_PROJECT_BRIEF) + # Using the PROJECT_BRIEF tag one can provide an optional one line + # description for a project that appears at the top of each page and + # should give viewer a quick idea about the purpose of the project. + # Keep the description short. + set(DOXYGEN_PROJECT_BRIEF "${PROJECT_DESCRIPTION}") + endif() + + if(NOT DEFINED DOXYGEN_RECURSIVE) + # The RECURSIVE tag can be used to specify whether or not + # subdirectories should be searched for input files as well. CMake + # projects generally evolve to span multiple directories, so it makes + # more sense for this to be on by default. Doxygen's default value + # has this setting turned off, so we override it. + set(DOXYGEN_RECURSIVE YES) + endif() + + if(NOT DEFINED DOXYGEN_OUTPUT_DIRECTORY) + # The OUTPUT_DIRECTORY tag is used to specify the (relative or + # absolute) path into which the generated documentation will be + # written. If a relative path is used, Doxygen will interpret it as + # being relative to the location where doxygen was started, but we need + # to run Doxygen in the source tree so that relative input paths work + # intuitively. Therefore, we ensure that the output directory is always + # an absolute path and if the project provided a relative path, we + # treat it as relative to the current BINARY directory so that output + # is not generated inside the source tree. + set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + elseif(NOT IS_ABSOLUTE "${DOXYGEN_OUTPUT_DIRECTORY}") + get_filename_component(DOXYGEN_OUTPUT_DIRECTORY + "${DOXYGEN_OUTPUT_DIRECTORY}" + ABSOLUTE + BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") + endif() + + if(NOT DEFINED DOXYGEN_HAVE_DOT) + # If you set the HAVE_DOT tag to YES then doxygen will assume the dot + # tool is available from the path. This tool is part of Graphviz (see: + # http://www.graphviz.org/), a graph visualization toolkit from AT&T + # and Lucent Bell Labs. The other options in this section have no + # effect if this option is set to NO. + # Doxygen's default value is: NO. + set(DOXYGEN_HAVE_DOT ${DOXYGEN_DOT_FOUND}) + endif() + + if(NOT DEFINED DOXYGEN_DOT_MULTI_TARGETS) + # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate + # multiple output files in one run (i.e. multiple -o and -T options on + # the command line). This makes dot run faster, but since only newer + # versions of dot (>1.8.10) support this, Doxygen disables this feature + # by default. + # This tag requires that the tag HAVE_DOT is set to YES. + set(DOXYGEN_DOT_MULTI_TARGETS YES) + endif() + + if(NOT DEFINED DOXYGEN_GENERATE_LATEX) + # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX + # output. We only want the HTML output enabled by default, so we turn + # this off if the project hasn't specified it. + set(DOXYGEN_GENERATE_LATEX NO) + endif() + + if(NOT DEFINED DOXYGEN_WARN_FORMAT) + if(CMAKE_VS_MSBUILD_COMMAND OR CMAKE_VS_DEVENV_COMMAND) + # The WARN_FORMAT tag determines the format of the warning messages + # that doxygen can produce. The string should contain the $file, + # $line and $text tags, which will be replaced by the file and line + # number from which the warning originated and the warning text. + # Optionally, the format may contain $version, which will be + # replaced by the version of the file (if it could be obtained via + # FILE_VERSION_FILTER). + # Doxygen's default value is: $file:$line: $text + set(DOXYGEN_WARN_FORMAT "$file($line) : $text ") + endif() + endif() + + if(DEFINED DOXYGEN_WARN_LOGFILE AND NOT IS_ABSOLUTE "${DOXYGEN_WARN_LOGFILE}") + # The WARN_LOGFILE tag can be used to specify a file to which warning and error + # messages should be written. If left blank the output is written to standard + # error (stderr). + get_filename_component(DOXYGEN_WARN_LOGFILE + "${DOXYGEN_WARN_LOGFILE}" + ABSOLUTE + BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") + endif() + + # Any files from the INPUT that match any of the EXCLUDE_PATTERNS will be + # excluded from the set of input files. We provide some additional patterns + # to prevent commonly unwanted things from CMake builds being pulled in. + # + # Note that the wildcards are matched against the file with absolute path, + # so to exclude all test directories for example use the pattern */test/* + list( + APPEND + DOXYGEN_EXCLUDE_PATTERNS + "*/.git/*" + "*/.svn/*" + "*/.hg/*" + "*/CMakeFiles/*" + "*/_CPack_Packages/*" + "DartConfiguration.tcl" + "CMakeLists.txt" + "CMakeCache.txt" + ) + + # Now bring in Doxgen's defaults for those things the project has not + # already set and we have not provided above + include("${CMAKE_BINARY_DIR}/CMakeDoxygenDefaults.cmake" OPTIONAL) + + # Cleanup built HTMLs on "make clean" + # TODO Any other dirs? + if(DOXYGEN_GENERATE_HTML) + if(IS_ABSOLUTE "${DOXYGEN_HTML_OUTPUT}") + set(_args_clean_html_dir "${DOXYGEN_HTML_OUTPUT}") + else() + set(_args_clean_html_dir + "${DOXYGEN_OUTPUT_DIRECTORY}/${DOXYGEN_HTML_OUTPUT}") + endif() + set_property(DIRECTORY APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES "${_args_clean_html_dir}") + endif() + + # Build up a list of files we can identify from the inputs so we can list + # them as SOURCES in the custom target (makes them display in IDEs). We + # must do this before we transform the various DOXYGEN_... variables below + # because we need to process DOXYGEN_INPUT as a list first. + unset(_sources) + foreach(_item IN LISTS DOXYGEN_INPUT) + get_filename_component(_abs_item "${_item}" ABSOLUTE + BASE_DIR "${_args_WORKING_DIRECTORY}") + if(EXISTS "${_abs_item}" AND + NOT IS_DIRECTORY "${_abs_item}" AND + NOT IS_SYMLINK "${_abs_item}") + list(APPEND _sources "${_abs_item}") + endif() + endforeach() + if(_sources) + list(INSERT _sources 0 SOURCES) + endif() + + # Transform known list type options into space separated strings. + set(_doxygen_list_options + ABBREVIATE_BRIEF + ALIASES + CITE_BIB_FILES + DIAFILE_DIRS + DOTFILE_DIRS + DOT_FONTPATH + ENABLED_SECTIONS + EXAMPLE_PATH + EXAMPLE_PATTERNS + EXCLUDE + EXCLUDE_PATTERNS + EXCLUDE_SYMBOLS + EXPAND_AS_DEFINED + EXTENSION_MAPPING + EXTRA_PACKAGES + EXTRA_SEARCH_MAPPINGS + FILE_PATTERNS + FILTER_PATTERNS + FILTER_SOURCE_PATTERNS + HTML_EXTRA_FILES + HTML_EXTRA_STYLESHEET + IGNORE_PREFIX + IMAGE_PATH + INCLUDE_FILE_PATTERNS + INCLUDE_PATH + INPUT + LATEX_EXTRA_FILES + LATEX_EXTRA_STYLESHEET + MATHJAX_EXTENSIONS + MSCFILE_DIRS + PLANTUML_INCLUDE_PATH + PREDEFINED + QHP_CUST_FILTER_ATTRS + QHP_SECT_FILTER_ATTRS + STRIP_FROM_INC_PATH + STRIP_FROM_PATH + TAGFILES + TCL_SUBST + ) + foreach(_item IN LISTS _doxygen_list_options) + doxygen_list_to_quoted_strings(DOXYGEN_${_item}) + endforeach() + + # Transform known single value variables which may contain spaces, such as + # paths or description strings. + set(_doxygen_quoted_options + CHM_FILE + DIA_PATH + DOCBOOK_OUTPUT + DOCSET_FEEDNAME + DOCSET_PUBLISHER_NAME + DOT_FONTNAME + DOT_PATH + EXTERNAL_SEARCH_ID + FILE_VERSION_FILTER + GENERATE_TAGFILE + HHC_LOCATION + HTML_FOOTER + HTML_HEADER + HTML_OUTPUT + HTML_STYLESHEET + INPUT_FILTER + LATEX_FOOTER + LATEX_HEADER + LATEX_OUTPUT + LAYOUT_FILE + MAN_OUTPUT + MAN_SUBDIR + MATHJAX_CODEFILE + MSCGEN_PATH + OUTPUT_DIRECTORY + PERL_PATH + PLANTUML_JAR_PATH + PROJECT_BRIEF + PROJECT_LOGO + PROJECT_NAME + QCH_FILE + QHG_LOCATION + QHP_CUST_FILTER_NAME + QHP_VIRTUAL_FOLDER + RTF_EXTENSIONS_FILE + RTF_OUTPUT + RTF_STYLESHEET_FILE + SEARCHDATA_FILE + USE_MDFILE_AS_MAINPAGE + WARN_FORMAT + WARN_LOGFILE + XML_OUTPUT + ) + + # Store the unmodified value of DOXYGEN_OUTPUT_DIRECTORY prior to invoking + # doxygen_quote_value() below. This will mutate the string specifically for + # consumption by Doxygen's config file, which we do not want when we use it + # later in the custom target's commands. + set( _original_doxygen_output_dir ${DOXYGEN_OUTPUT_DIRECTORY} ) + + foreach(_item IN LISTS _doxygen_quoted_options) + doxygen_quote_value(DOXYGEN_${_item}) + endforeach() + + # Prepare doxygen configuration file + set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in") + set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.${targetName}") + configure_file("${_doxyfile_template}" "${_target_doxyfile}") + + # Add the target + add_custom_target( ${targetName} VERBATIM + COMMAND ${CMAKE_COMMAND} -E make_directory ${_original_doxygen_output_dir} + COMMAND "${DOXYGEN_EXECUTABLE}" "${_target_doxyfile}" + WORKING_DIRECTORY "${_args_WORKING_DIRECTORY}" + DEPENDS "${_target_doxyfile}" + COMMENT "${_args_COMMENT}" + ${_sources} + ) -mark_as_advanced( - DOXYGEN_EXECUTABLE - DOXYGEN_DOT_EXECUTABLE - ) +endfunction() diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake index d8609e64d..11e872446 100644 --- a/Modules/FindGLEW.cmake +++ b/Modules/FindGLEW.cmake @@ -27,7 +27,7 @@ find_path(GLEW_INCLUDE_DIR GL/glew.h) if(NOT GLEW_LIBRARY) - find_library(GLEW_LIBRARY_RELEASE NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64) + find_library(GLEW_LIBRARY_RELEASE NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64 libx32) find_library(GLEW_LIBRARY_DEBUG NAMES GLEWd glew32d glewd PATH_SUFFIXES lib64) include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index 02e6df037..88d4b2918 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -120,10 +120,12 @@ if (GLUT_FOUND) # If not, we need some way to figure out what platform we are on. set( GLUT_LIBRARIES ${GLUT_glut_LIBRARY} - ${GLUT_Xmu_LIBRARY} - ${GLUT_Xi_LIBRARY} - ${GLUT_cocoa_LIBRARY} ) + foreach(v GLUT_Xmu_LIBRARY GLUT_Xi_LIBRARY GLUT_cocoa_LIBRARY) + if(${v}) + list(APPEND GLUT_LIBRARIES ${${v}}) + endif() + endforeach() if(NOT TARGET GLUT::GLUT) add_library(GLUT::GLUT UNKNOWN IMPORTED) diff --git a/Modules/FindGSL.cmake b/Modules/FindGSL.cmake index 76059b33a..8d10b6ce5 100644 --- a/Modules/FindGSL.cmake +++ b/Modules/FindGSL.cmake @@ -37,9 +37,10 @@ # # This script expects to find libraries at ``$GSL_ROOT_DIR/lib`` and the GSL # headers at ``$GSL_ROOT_DIR/include/gsl``. The library directory may -# optionally provide Release and Debug folders. For Unix-like systems, this -# script will use ``$GSL_ROOT_DIR/bin/gsl-config`` (if found) to aid in the -# discovery GSL. +# optionally provide Release and Debug folders. If available, the libraries +# named ``gsld``, ``gslblasd`` or ``cblasd`` are recognized as debug libraries. +# For Unix-like systems, this script will use ``$GSL_ROOT_DIR/bin/gsl-config`` +# (if found) to aid in the discovery of GSL. # # Cache Variables # ^^^^^^^^^^^^^^^ @@ -105,12 +106,12 @@ find_library( GSL_CBLAS_LIBRARY ) # Do we also have debug versions? find_library( GSL_LIBRARY_DEBUG - NAMES gsl + NAMES gsld gsl HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} PATH_SUFFIXES Debug ) find_library( GSL_CBLAS_LIBRARY_DEBUG - NAMES gslcblas cblas + NAMES gslcblasd cblasd gslcblas cblas HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} PATH_SUFFIXES Debug ) diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index fd179a8a8..b87b9f3ab 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -292,8 +292,10 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr) find_path(GTK2_${_var}_INCLUDE_DIR ${_hdr} PATHS ${_gtk2_arch_dir} + /usr/local/libx32 /usr/local/lib64 /usr/local/lib + /usr/libx32 /usr/lib64 /usr/lib /usr/X11R6/include diff --git a/Modules/FindGTest.cmake b/Modules/FindGTest.cmake index 65401710d..c4b4535ff 100644 --- a/Modules/FindGTest.cmake +++ b/Modules/FindGTest.cmake @@ -70,64 +70,10 @@ # Deeper integration with CTest # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # -# If you would like each Google test to show up in CTest as a test you -# may use the following macro:: -# -# GTEST_ADD_TESTS(executable extra_args files...) -# -# ``executable`` -# the path to the test executable -# ``extra_args`` -# a list of extra arguments to be passed to executable enclosed in -# quotes (or ``""`` for none) -# ``files...`` -# a list of source files to search for tests and test fixtures. Or -# ``AUTO`` to find them from executable target -# -# However, note that this macro will slow down your tests by running -# an executable for each test and test fixture. -# -# Example usage:: -# -# set(FooTestArgs --foo 1 --bar 2) -# add_executable(FooTest FooUnitTest.cc) -# GTEST_ADD_TESTS(FooTest "${FooTestArgs}" AUTO) - -# -# Thanks to Daniel Blezek for the GTEST_ADD_TESTS code - -function(GTEST_ADD_TESTS executable extra_args) - if(NOT ARGN) - message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS") - endif() - if(ARGN STREQUAL "AUTO") - # obtain sources used for building that executable - get_property(ARGN TARGET ${executable} PROPERTY SOURCES) - endif() - set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*") - set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)") - foreach(source ${ARGN}) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) - file(READ "${source}" contents) - string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents}) - foreach(hit ${found_tests}) - string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit}) +# See :module:`GoogleTest` for information on the :command:`gtest_add_tests` +# command. - # Parameterized tests have a different signature for the filter - if("x${test_type}" STREQUAL "xTEST_P") - string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" test_name ${hit}) - elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST") - string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" test_name ${hit}) - elseif("x${test_type}" STREQUAL "xTYPED_TEST") - string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" test_name ${hit}) - else() - message(WARNING "Could not parse GTest ${hit} for adding to CTest.") - continue() - endif() - add_test(NAME ${test_name} COMMAND ${executable} --gtest_filter=${test_name} ${extra_args}) - endforeach() - endforeach() -endfunction() +include(${CMAKE_CURRENT_LIST_DIR}/GoogleTest.cmake) function(_gtest_append_debugs _endvar _library) if(${_library} AND ${_library}_DEBUG) diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 2a81da6f7..5962c5bd4 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -59,12 +59,19 @@ # bindings, if the HL component is enabled # # Available components are: C CXX Fortran and HL. For each enabled language -# binding, a corresponding HDF5_${LANG}_LIBRARIES variable will be defined. +# binding, a corresponding HDF5_${LANG}_LIBRARIES variable, and potentially +# HDF5_${LANG}_DEFINITIONS, will be defined. # If the HL component is enabled, then an HDF5_${LANG}_HL_LIBRARIES will # also be defined. With all components enabled, the following variables will be defined: # # :: # +# HDF5_C_DEFINITIONS -- Required compiler definitions for HDF5 C bindings +# HDF5_CXX_DEFINITIONS -- Required compiler definitions for HDF5 C++ bindings +# HDF5_Fortran_DEFINITIONS -- Required compiler definitions for HDF5 Fortran bindings +# HDF5_C_INCLUDE_DIRS -- Required include directories for HDF5 C bindings +# HDF5_CXX_INCLUDE_DIRS -- Required include directories for HDF5 C++ bindings +# HDF5_Fortran_INCLUDE_DIRS -- Required include directories for HDF5 Fortran bindings # HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings # HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings # HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings @@ -92,6 +99,9 @@ # ``HDF5_ROOT`` # Specify the path to the HDF5 installation to use. # +# ``HDF5_FIND_DEBUG`` +# Set to a true value to get some extra debugging output. +# # ``HDF5_NO_FIND_PACKAGE_CONFIG_FILE`` # Set to a true value to skip trying to find ``hdf5-config.cmake``. @@ -344,11 +354,7 @@ macro( _HDF5_parse_compile_line libraries libraries_hl) - if(UNIX) - separate_arguments(_HDF5_COMPILE_ARGS UNIX_COMMAND "${${compile_line_var}}") - else() - separate_arguments(_HDF5_COMPILE_ARGS WINDOWS_COMMAND "${${compile_line_var}}") - endif() + separate_arguments(_HDF5_COMPILE_ARGS NATIVE_COMMAND "${${compile_line_var}}") foreach(arg IN LISTS _HDF5_COMPILE_ARGS) if("${arg}" MATCHES "^-I(.*)$") @@ -400,15 +406,23 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE) ${_HDF5_SEARCH_OPTS} ) if( HDF5_FOUND) + if(HDF5_FIND_DEBUG) + message(STATUS "Found HDF5 at ${HDF5_DIR} via NO_MODULE. Now trying to extract locations etc.") + endif() set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL}) set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR}) set(HDF5_LIBRARIES) - set(HDF5_C_TARGET hdf5) - set(HDF5_C_HL_TARGET hdf5_hl) - set(HDF5_CXX_TARGET hdf5_cpp) - set(HDF5_CXX_HL_TARGET hdf5_hl_cpp) - set(HDF5_Fortran_TARGET hdf5_fortran) - set(HDF5_Fortran_HL_TARGET hdf5_hl_fortran) + if (NOT TARGET hdf5 AND NOT TARGET hdf5-static AND NOT TARGET hdf5-shared) + # Some HDF5 versions (e.g. 1.8.18) used hdf5::hdf5 etc + set(_target_prefix "hdf5::") + endif() + set(HDF5_C_TARGET ${_target_prefix}hdf5) + set(HDF5_C_HL_TARGET ${_target_prefix}hdf5_hl) + set(HDF5_CXX_TARGET ${_target_prefix}hdf5_cpp) + set(HDF5_CXX_HL_TARGET ${_target_prefix}hdf5_hl_cpp) + set(HDF5_Fortran_TARGET ${_target_prefix}hdf5_fortran) + set(HDF5_Fortran_HL_TARGET ${_target_prefix}hdf5_hl_fortran) + set(HDF5_DEFINITIONS "") if(HDF5_USE_STATIC_LIBRARIES) set(_suffix "-static") else() @@ -420,7 +434,7 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE) #if we detect that occurrence clear the suffix if(_suffix AND NOT TARGET ${HDF5_${_lang}_TARGET}${_suffix}) if(NOT TARGET ${HDF5_${_lang}_TARGET}) - #cant find this component with our without the suffix + #cant find this component with or without the suffix #so bail out, and let the following locate HDF5 set(HDF5_FOUND FALSE) break() @@ -428,21 +442,29 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE) set(_suffix "") endif() - get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION) + if(HDF5_FIND_DEBUG) + message(STATUS "Trying to get properties of target ${HDF5_${_lang}_TARGET}${_suffix}") + endif() + # Find library for this target. Complicated as on Windows with a DLL, we need to search for the import-lib. + get_target_property(_imported_conf ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_CONFIGURATIONS) + get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_IMPLIB_${_imported_conf} ) + if (NOT _lang_location) + # no import lib, just try LOCATION + get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION) + endif() if( _lang_location ) - set(HDF5_${_lang}_LIBRARY ${_lang_location} CACHE PATH - "HDF5 ${_lang} library" ) - mark_as_advanced(HDF5_${_lang}_LIBRARY) + set(HDF5_${_lang}_LIBRARY ${_lang_location}) list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) set(HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) set(HDF5_${_lang}_FOUND True) endif() if(FIND_HL) - get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION) + get_target_property(__lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_imported_conf} ) + if (NOT _lang_hl_location) + get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION) + endif() if( _lang_hl_location ) - set(HDF5_${_lang}_HL_LIBRARY ${_lang_hl_location} CACHE PATH - "HDF5 ${_lang} HL library" ) - mark_as_advanced(HDF5_${_lang}_HL_LIBRARY) + set(HDF5_${_lang}_HL_LIBRARY ${_lang_hl_location}) list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) set(HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) set(HDF5_HL_FOUND True) @@ -487,10 +509,6 @@ if(NOT HDF5_FOUND) set(HDF5_${__lang}_HL_LIBRARIES) mark_as_advanced(HDF5_${__lang}_COMPILER_EXECUTABLE_NO_INTERROGATE) - mark_as_advanced(HDF5_${__lang}_DEFINITIONS) - mark_as_advanced(HDF5_${__lang}_INCLUDE_DIRS) - mark_as_advanced(HDF5_${__lang}_LIBRARIES) - mark_as_advanced(HDF5_${__lang}_HL_LIBRARIES) set(HDF5_${__lang}_FOUND True) set(HDF5_HL_FOUND True) @@ -580,9 +598,6 @@ if(NOT HDF5_FOUND) endif() set(HDF5_${__lang}_FOUND True) - mark_as_advanced(HDF5_${__lang}_DEFINITIONS) - mark_as_advanced(HDF5_${__lang}_INCLUDE_DIRS) - mark_as_advanced(HDF5_${__lang}_LIBRARIES) _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) @@ -685,6 +700,8 @@ if( NOT HDF5_FOUND ) ${_HDF5_SEARCH_OPTS} ) mark_as_advanced(HDF5_${__lang}_INCLUDE_DIR) + # set the _DIRS variable as this is what the user will normally use + set(HDF5_${__lang}_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) # find the HDF5 libraries @@ -826,3 +843,23 @@ find_package_handle_standard_args(HDF5 ) unset(_HDF5_SEARCH_OPTS) + +if( HDF5_FOUND AND NOT HDF5_DIR) + # hide HDF5_DIR for the non-advanced user to avoid confusion with + # HDF5_DIR-NOT_FOUND while HDF5 was found. + mark_as_advanced(HDF5_DIR) +endif() + +if (HDF5_FIND_DEBUG) + message(STATUS "HDF5_DIR: ${HDF5_DIR}") + message(STATUS "HDF5_DEFINITIONS: ${HDF5_DEFINITIONS}") + message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}") + message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}") + foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS) + message(STATUS "HDF5_${__lang}_DEFINITIONS: ${HDF5_${__lang}_DEFINITIONS}") + message(STATUS "HDF5_${__lang}_INCLUDE_DIR: ${HDF5_${__lang}_INCLUDE_DIR}") + message(STATUS "HDF5_${__lang}_INCLUDE_DIRS: ${HDF5_${__lang}_INCLUDE_DIRS}") + message(STATUS "HDF5_${__lang}_LIBRARY: ${HDF5_${__lang}_LIBRARY}") + message(STATUS "HDF5_${__lang}_LIBRARIES: ${HDF5_${__lang}_LIBRARIES}") + endforeach() +endif() diff --git a/Modules/FindIce.cmake b/Modules/FindIce.cmake index a61d4a804..e0286ee2c 100644 --- a/Modules/FindIce.cmake +++ b/Modules/FindIce.cmake @@ -198,7 +198,7 @@ function(_Ice_FIND) endif() # Generic 64-bit and 32-bit directories list(APPEND ice_binary_suffixes "bin${_x64}" "bin") - list(APPEND ice_library_suffixes "${_lib64}" "lib${_x64}" "lib") + list(APPEND ice_library_suffixes "libx32" "${_lib64}" "lib${_x64}" "lib") list(APPEND ice_include_suffixes "include") list(APPEND ice_slice_suffixes "slice") diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake index 0561a3d9d..7d5534bc2 100644 --- a/Modules/FindImageMagick.cmake +++ b/Modules/FindImageMagick.cmake @@ -102,7 +102,7 @@ function(FIND_IMAGEMAGICK_API component header) ${ImageMagick_INCLUDE_DIRS} "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include" PATH_SUFFIXES - ImageMagick ImageMagick-6 + ImageMagick ImageMagick-6 ImageMagick-7 DOC "Path to the ImageMagick arch-independent include dir." ) find_path(ImageMagick_${component}_ARCH_INCLUDE_DIR @@ -114,7 +114,7 @@ function(FIND_IMAGEMAGICK_API component header) ${ImageMagick_INCLUDE_DIRS} "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include" PATH_SUFFIXES - ImageMagick ImageMagick-6 + ImageMagick ImageMagick-6 ImageMagick-7 DOC "Path to the ImageMagick arch-specific include dir." ) find_library(ImageMagick_${component}_LIBRARY @@ -195,17 +195,26 @@ foreach(component ${ImageMagick_FIND_COMPONENTS} ) if(component STREQUAL "Magick++") FIND_IMAGEMAGICK_API(Magick++ Magick++.h - Magick++ CORE_RL_Magick++_ Magick++-6.Q16 Magick++-Q16 Magick++-6.Q8 Magick++-Q8 Magick++-6.Q16HDRI Magick++-Q16HDRI Magick++-6.Q8HDRI Magick++-Q8HDRI + Magick++ CORE_RL_Magick++_ + Magick++-Q8 Magick++-Q16 Magick++-Q16HDRI Magick++-Q8HDRI + Magick++-6.Q16 Magick++-6.Q8 Magick++-6.Q16HDRI Magick++-6.Q8HDRI + Magick++-7.Q16 Magick++-7.Q8 Magick++-7.Q16HDRI Magick++-7.Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY) elseif(component STREQUAL "MagickWand") - FIND_IMAGEMAGICK_API(MagickWand wand/MagickWand.h - Wand MagickWand CORE_RL_wand_ MagickWand-6.Q16 MagickWand-Q16 MagickWand-6.Q8 MagickWand-Q8 MagickWand-6.Q16HDRI MagickWand-Q16HDRI MagickWand-6.Q8HDRI MagickWand-Q8HDRI + FIND_IMAGEMAGICK_API(MagickWand "wand/MagickWand.h;MagickWand/MagickWand.h" + Wand MagickWand CORE_RL_wand_ + MagickWand-Q16 MagickWand-Q8 MagickWand-Q16HDRI MagickWand-Q8HDRI + MagickWand-6.Q16 MagickWand-6.Q8 MagickWand-6.Q16HDRI MagickWand-6.Q8HDRI + MagickWand-7.Q16 MagickWand-7.Q8 MagickWand-7.Q16HDRI MagickWand-7.Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY) elseif(component STREQUAL "MagickCore") - FIND_IMAGEMAGICK_API(MagickCore magick/MagickCore.h - Magick MagickCore CORE_RL_magick_ MagickCore-6.Q16 MagickCore-Q16 MagickCore-6.Q8 MagickCore-Q8 MagickCore-6.Q16HDRI MagickCore-Q16HDRI MagickCore-6.Q8HDRI MagickCore-Q8HDRI + FIND_IMAGEMAGICK_API(MagickCore "magick/MagickCore.h;MagickCore/MagickCore.h" + Magick MagickCore CORE_RL_magick_ + MagickCore-Q16 MagickCore-Q8 MagickCore-Q16HDRI MagickCore-Q8HDRI + MagickCore-6.Q16 MagickCore-6.Q8 MagickCore-6.Q16HDRI MagickCore-6.Q8HDRI + MagickCore-7.Q16 MagickCore-7.Q8 MagickCore-7.Q16HDRI MagickCore-7.Q8HDRI ) list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickCore_LIBRARY) else() diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake index 4265a9783..3d3256030 100644 --- a/Modules/FindJava.cmake +++ b/Modules/FindJava.cmake @@ -143,6 +143,9 @@ if(Java_JAVA_EXECUTABLE) if(var MATCHES "java version \"([0-9]+\\.[0-9]+\\.[0-9_.]+.*)\"") # This is most likely Sun / OpenJDK, or maybe GCJ-java compat layer set(Java_VERSION_STRING "${CMAKE_MATCH_1}") + elseif(var MATCHES "openjdk version \"([0-9]+)-[a-z]+\"") + # OpenJDK 9 early access builds or locally built + set(Java_VERSION_STRING "1.${CMAKE_MATCH_1}.0") elseif(var MATCHES "java full version \"kaffe-([0-9]+\\.[0-9]+\\.[0-9_]+)\"") # Kaffe style set(Java_VERSION_STRING "${CMAKE_MATCH_1}") diff --git a/Modules/FindKDE3.cmake b/Modules/FindKDE3.cmake index 62e2a50b6..03216a5c1 100644 --- a/Modules/FindKDE3.cmake +++ b/Modules/FindKDE3.cmake @@ -221,6 +221,8 @@ get_filename_component(KDE3_LIB_DIR ${KDE3_KDECORE_LIBRARY} PATH ) if(NOT KDE3_LIBTOOL_DIR) if(KDE3_KDECORE_LIBRARY MATCHES lib64) set(KDE3_LIBTOOL_DIR /lib64/kde3) + elseif(KDE3_KDECORE_LIBRARY MATCHES libx32) + set(KDE3_LIBTOOL_DIR /libx32/kde3) else() set(KDE3_LIBTOOL_DIR /lib/kde3) endif() diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index ff2c4dec7..37f325572 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -10,71 +10,78 @@ # The Message Passing Interface (MPI) is a library used to write # 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. All -# of them have somewhat different include paths, libraries to link -# against, etc., and this module tries to smooth out those differences. +# by the MPI forum) for which many implementations are available. # # Variables # ^^^^^^^^^ # # This module will set the following variables per language in your -# project, where is one of C, CXX, or Fortran: -# -# :: -# -# MPI__FOUND TRUE if FindMPI found MPI flags for -# MPI__COMPILER MPI Compiler wrapper for -# MPI__COMPILE_FLAGS Compilation flags for MPI programs -# MPI__INCLUDE_PATH Include path(s) for MPI header -# MPI__LINK_FLAGS Linking flags for MPI programs -# MPI__LIBRARIES All libraries to link MPI programs against +# project, where ```` is one of C, CXX, or Fortran: +# +# ``MPI__FOUND`` +# Variable indicating the MPI settings for ```` were found. +# ``MPI__COMPILER`` +# MPI Compiler wrapper for ````. +# ``MPI__COMPILE_FLAGS`` +# Compilation flags for MPI programs, separated by spaces. +# This is *not* a :ref:`;-list `. +# ``MPI__INCLUDE_PATH`` +# Include path(s) for MPI header. +# ``MPI__LINK_FLAGS`` +# Linker flags for MPI programs. +# ``MPI__LIBRARIES`` +# All libraries to link MPI programs against. +# +# Additionally, the following :prop_tgt:`IMPORTED` targets are defined: +# +# ``MPI::MPI_`` +# Target for using MPI from ````. # # Additionally, FindMPI sets the following variables for running MPI # programs from the command line: # -# :: -# -# MPIEXEC Executable for running MPI programs -# MPIEXEC_NUMPROC_FLAG Flag to pass to MPIEXEC before giving -# it the number of processors to run on -# MPIEXEC_PREFLAGS Flags to pass to MPIEXEC directly -# before the executable to run. -# MPIEXEC_POSTFLAGS Flags to pass to MPIEXEC after other flags +# ``MPIEXEC`` +# Executable for running MPI programs, if provided. +# ``MPIEXEC_NUMPROC_FLAG`` +# Flag to pass to ``MPIEXEC`` before giving it the number of processors to run on. +# ``MPIEXEC_MAX_NUMPROCS`` +# Number of MPI processors to utilize. Defaults to the number +# of processors detected on the host system. +# ``MPIEXEC_PREFLAGS`` +# Flags to pass to ``MPIEXEC`` directly before the executable to run. +# ``MPIEXEC_POSTFLAGS`` +# Flags to pass to ``MPIEXEC`` after other flags. # # Usage # ^^^^^ # -# To use this module, simply call FindMPI from a CMakeLists.txt file, or -# run ``find_package(MPI)``, then run CMake. If you are happy with the +# To use this module, call ``find_package(MPI)``. If you are happy with the # auto-detected configuration for your language, then you're done. If # not, you have two options: # -# :: -# -# 1. Set MPI__COMPILER to the MPI wrapper (mpicc, etc.) of your -# choice and reconfigure. FindMPI will attempt to determine all the -# necessary variables using THAT compiler's compile and link flags. -# 2. If this fails, or if your MPI implementation does not come with -# a compiler wrapper, then set both MPI__LIBRARIES and -# MPI__INCLUDE_PATH. You may also set any other variables -# listed above, but these two are required. This will circumvent -# autodetection entirely. +# 1. Set ``MPI__COMPILER`` to the MPI wrapper (e.g. ``mpicc``) of your +# choice and reconfigure. FindMPI will attempt to determine all the +# necessary variables using *that* compiler's compile and link flags. +# 2. If this fails, or if your MPI implementation does not come with +# a compiler wrapper, then set both ``MPI__LIBRARIES`` and +# ``MPI__INCLUDE_PATH``. You may also set any other variables +# listed above, but these two are required. This will circumvent +# autodetection entirely. # # When configuration is successful, ``MPI__COMPILER`` will be set to -# the compiler wrapper for , if it was found. ``MPI__FOUND`` +# the compiler wrapper for ````, if it was found. ``MPI__FOUND`` # and other variables above will be set if any MPI implementation was -# found for , regardless of whether a compiler was found. +# found for ````, regardless of whether a compiler was found. # # When using ``MPIEXEC`` to execute MPI applications, you should typically # use all of the ``MPIEXEC`` flags as follows: # # :: # -# ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} PROCS +# ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_MAX_NUMPROCS} # ${MPIEXEC_PREFLAGS} EXECUTABLE ${MPIEXEC_POSTFLAGS} ARGS # -# where ``PROCS`` is the number of processors on which to execute the -# program, ``EXECUTABLE`` is the MPI program, and ``ARGS`` are the arguments to +# where ``EXECUTABLE`` is the MPI program, and ``ARGS`` are the arguments to # pass to the MPI program. # # Backward Compatibility @@ -100,12 +107,12 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) # The compilers are detected in this order: # # 1. Try to find the most generic available MPI compiler, as this is usually set up by -# cluster admins. e.g., if plain old mpicc is available, we'll use it and assume it's +# cluster admins, e.g. if plain old mpicc is available, we'll use it and assume it's # the right compiler. # # 2. If a generic mpicc is NOT found, then we attempt to find one that matches # CMAKE__COMPILER_ID. e.g. if you are using XL compilers, we'll try to find mpixlc -# and company, but not mpiicc. This hopefully prevents toolchain mismatches. +# and company, but not mpiicc. This hopefully prevents toolchain mismatches. # # If you want to force a particular MPI compiler other than what we autodetect (e.g. if you # want to compile regular stuff with GNU and parallel stuff with Intel), you can always set @@ -476,7 +483,7 @@ function (interrogate_mpi_compiler lang try_libs) set(MPI_${lang}_LIBRARIES ${MPI_LIBRARIES_WORK} CACHE STRING "MPI ${lang} libraries to link against" FORCE) mark_as_advanced(MPI_${lang}_COMPILE_FLAGS MPI_${lang}_INCLUDE_PATH MPI_${lang}_LINK_FLAGS MPI_${lang}_LIBRARIES) - # clear out our temporary lib/header detectionv variable here. + # clear out our temporary lib/header detection variable here. set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI lib detection" FORCE) set(MPI_HEADER_PATH "MPI_HEADER_PATH-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI header detection" FORCE) endif() @@ -546,10 +553,21 @@ find_program(MPIEXEC get_filename_component(_MPI_BASE_DIR "${MPIEXEC}" PATH) get_filename_component(_MPI_BASE_DIR "${_MPI_BASE_DIR}" PATH) -set(MPIEXEC_NUMPROC_FLAG "-np" CACHE STRING "Flag used by MPI to specify the number of processes for MPIEXEC; the next option will be the number of processes.") +# According to the MPI standard, section 8.8 -n is a guaranteed, and the only guaranteed way to +# launch an MPI process using mpiexec if such a program exists. +set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "Flag used by MPI to specify the number of processes for MPIEXEC; the next option will be the number of processes.") set(MPIEXEC_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by MPIEXEC.") set(MPIEXEC_POSTFLAGS "" CACHE STRING "These flags will come after all flags given to MPIEXEC.") -set(MPIEXEC_MAX_NUMPROCS "2" CACHE STRING "Maximum number of processors available to run MPI applications.") + +# Set the number of processes to the processor count and the previous default +# of 2 if that couldn't be determined. +include(${CMAKE_CURRENT_LIST_DIR}/ProcessorCount.cmake) +ProcessorCount(_MPIEXEC_NUMPROCS) +if("${_MPIEXEC_NUMPROCS}" EQUAL "0") + set(_MPIEXEC_NUMPROCS 2) +endif() +set(MPIEXEC_MAX_NUMPROCS "${_MPIEXEC_NUMPROCS}" CACHE STRING "Maximum number of processors available to run MPI applications.") +unset(_MPIEXEC_NUMPROCS) mark_as_advanced(MPIEXEC MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS) @@ -621,6 +639,28 @@ foreach (lang C CXX Fortran) else() find_package_handle_standard_args(MPI_${lang} DEFAULT_MSG MPI_${lang}_LIBRARIES MPI_${lang}_INCLUDE_PATH) endif() + + if(MPI_${lang}_FOUND) + if(NOT TARGET MPI::MPI_${lang}) + add_library(MPI::MPI_${lang} INTERFACE IMPORTED) + endif() + if(MPI_${lang}_COMPILE_FLAGS) + separate_arguments(_MPI_${lang}_COMPILE_OPTIONS NATIVE_COMMAND "${MPI_${lang}_COMPILE_FLAGS}") + set_property(TARGET MPI::MPI_${lang} PROPERTY + INTERFACE_COMPILE_OPTIONS "${_MPI_${lang}_COMPILE_OPTIONS}") + endif() + + unset(_MPI_${lang}_LINK_LINE) + if(MPI_${lang}_LINK_FLAGS) + list(APPEND _MPI_${lang}_LINK_LINE "${MPI_${lang}_LINK_FLAGS}") + endif() + list(APPEND _MPI_${lang}_LINK_LINE "${MPI_${lang}_LIBRARIES}") + set_property(TARGET MPI::MPI_${lang} PROPERTY + INTERFACE_LINK_LIBRARIES "${_MPI_${lang}_LINK_LINE}") + + set_property(TARGET MPI::MPI_${lang} PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${MPI_${lang}_INCLUDE_PATH}") + endif() endif() endforeach() @@ -660,6 +700,7 @@ if (MPI_NUMLIBS GREATER 1) else() set(MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND" CACHE STRING "Extra MPI libraries to link against" FORCE) endif() +mark_as_advanced(MPI_LIBRARY MPI_EXTRA_LIBRARY) #============================================================================= # unset these vars to cleanup namespace diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index eae158535..80bcda36b 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -225,6 +225,7 @@ if(NOT MATLAB_ADDITIONAL_VERSIONS) endif() set(MATLAB_VERSIONS_MAPPING + "R2017a=9.2" "R2016b=9.1" "R2016a=9.0" "R2015b=8.6" diff --git a/Modules/FindOpenAL.cmake b/Modules/FindOpenAL.cmake index 8622b4c1f..c3d202ee8 100644 --- a/Modules/FindOpenAL.cmake +++ b/Modules/FindOpenAL.cmake @@ -79,7 +79,7 @@ find_library(OPENAL_LIBRARY NAMES OpenAL al openal OpenAL32 HINTS ENV OPENALDIR - PATH_SUFFIXES lib64 lib libs64 libs ${_OpenAL_ARCH_DIR} + PATH_SUFFIXES libx32 lib64 lib libs64 libs ${_OpenAL_ARCH_DIR} PATHS ~/Library/Frameworks /Library/Frameworks diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake index 3eca5e1ae..b8a7d822f 100644 --- a/Modules/FindOpenCL.cmake +++ b/Modules/FindOpenCL.cmake @@ -117,7 +117,12 @@ if(WIN32) endif() else() find_library(OpenCL_LIBRARY - NAMES OpenCL) + NAMES OpenCL + PATHS + ENV AMDAPPSDKROOT + PATH_SUFFIXES + lib/x86_64 + lib/x64) endif() set(OpenCL_LIBRARIES ${OpenCL_LIBRARY}) diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake index 503d9559c..af83fb735 100644 --- a/Modules/FindOpenGL.cmake +++ b/Modules/FindOpenGL.cmake @@ -178,7 +178,7 @@ if(OPENGL_FOUND) if(OPENGL_gl_LIBRARY MATCHES "/([^/]+)\\.framework$") set(_gl_fw "${OPENGL_gl_LIBRARY}/${CMAKE_MATCH_1}") if(EXISTS "${_gl_fw}.tbd") - set(_gl_fw "${_gl_fw}.tbd") + string(APPEND _gl_fw ".tbd") endif() set_target_properties(OpenGL::GL PROPERTIES IMPORTED_LOCATION "${_gl_fw}") @@ -201,7 +201,7 @@ if(OPENGL_FOUND) if(OPENGL_glu_LIBRARY MATCHES "/([^/]+)\\.framework$") set(_glu_fw "${OPENGL_glu_LIBRARY}/${CMAKE_MATCH_1}") if(EXISTS "${_glu_fw}.tbd") - set(_glu_fw "${_glu_fw}.tbd") + string(APPEND _glu_fw ".tbd") endif() set_target_properties(OpenGL::GLU PROPERTIES IMPORTED_LOCATION "${_glu_fw}") diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index 2ee9439d0..1093be0f4 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -13,111 +13,219 @@ # The variables may be empty if the compiler does not need a special # flag to support OpenMP. # -# The following variables are set: +# Variables +# ^^^^^^^^^ # -# ``OpenMP_C_FLAGS`` -# Flags to add to the C compiler for OpenMP support. -# ``OpenMP_CXX_FLAGS`` -# Flags to add to the CXX compiler for OpenMP support. -# ``OpenMP_Fortran_FLAGS`` -# Flags to add to the Fortran compiler for OpenMP support. -# ``OPENMP_FOUND`` -# True if openmp is detected. +# This module will set the following variables per language in your +# project, where ```` is one of C, CXX, or Fortran: # -# The following internal variables are set, if detected: +# ``OpenMP__FOUND`` +# Variable indicating if OpenMP support for ```` was detected. +# ``OpenMP__FLAGS`` +# OpenMP compiler flags for ````, separated by spaces. # -# ``OpenMP_C_SPEC_DATE`` -# Specification date of OpenMP version of C compiler. -# ``OpenMP_CXX_SPEC_DATE`` -# Specification date of OpenMP version of CXX compiler. -# ``OpenMP_Fortran_SPEC_DATE`` -# Specification date of OpenMP version of Fortran compiler. +# For linking with OpenMP code written in ````, the following +# variables are provided: # -# The specification dates are formatted as integers of the form -# ``CCYYMM`` where these represent the decimal digits of the century, -# year, and month. +# ``OpenMP__LIB_NAMES`` +# :ref:`;-list ` of libraries for OpenMP programs for ````. +# ``OpenMP__LIBRARY`` +# Location of the individual libraries needed for OpenMP support in ````. +# ``OpenMP__LIBRARIES`` +# A list of libraries needed to link with OpenMP code written in ````. +# +# Additionally, the module provides :prop_tgt:`IMPORTED` targets: +# +# ``OpenMP::OpenMP_`` +# Target for using OpenMP from ````. +# +# Specifically for Fortran, the module sets the following variables: +# +# ``OpenMP_Fortran_HAVE_OMPLIB_HEADER`` +# Boolean indicating if OpenMP is accessible through ``omp_lib.h``. +# ``OpenMP_Fortran_HAVE_OMPLIB_MODULE`` +# Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module. +# +# The module will also try to provide the OpenMP version variables: +# +# ``OpenMP__SPEC_DATE`` +# Date of the OpenMP specification implemented by the ```` compiler. +# ``OpenMP__VERSION_MAJOR`` +# Major version of OpenMP implemented by the ```` compiler. +# ``OpenMP__VERSION_MINOR`` +# Minor version of OpenMP implemented by the ```` compiler. +# ``OpenMP__VERSION`` +# OpenMP version implemented by the ```` compiler. +# +# The specification date is formatted as given in the OpenMP standard: +# ``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of +# the OpenMP specification implemented by the ```` compiler. +# +# Backward Compatibility +# ^^^^^^^^^^^^^^^^^^^^^^ +# +# For backward compatibility with older versions of FindOpenMP, these +# variables are set, but deprecated:: +# +# OpenMP_FOUND +# +# In new projects, please use the ``OpenMP__XXX`` equivalents. -set(_OPENMP_REQUIRED_VARS) -set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) -set(CMAKE_REQUIRED_QUIET ${OpenMP_FIND_QUIETLY}) +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST function(_OPENMP_FLAG_CANDIDATES LANG) - set(OpenMP_FLAG_CANDIDATES - #Empty, if compiler automatically accepts openmp - " " - #GNU - "-fopenmp" - #Clang - "-fopenmp=libomp" - #Microsoft Visual Studio - "/openmp" - #Intel windows - "-Qopenmp" - #PathScale, Intel - "-openmp" - #Sun - "-xopenmp" - #HP - "+Oopenmp" - #IBM XL C/c++ - "-qsmp" - #Portland Group, MIPSpro - "-mp" - ) - - set(OMP_FLAG_GNU "-fopenmp") - set(OMP_FLAG_Clang "-fopenmp=libomp") - set(OMP_FLAG_HP "+Oopenmp") - if(WIN32) - set(OMP_FLAG_Intel "-Qopenmp") - elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND - "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528") - set(OMP_FLAG_Intel "-openmp") + if(NOT OpenMP_${LANG}_FLAG) + unset(OpenMP_FLAG_CANDIDATES) + + set(OMP_FLAG_GNU "-fopenmp") + set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp") + set(OMP_FLAG_HP "+Oopenmp") + if(WIN32) + set(OMP_FLAG_Intel "-Qopenmp") + elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND + "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528") + set(OMP_FLAG_Intel "-openmp") + else() + set(OMP_FLAG_Intel "-qopenmp") + endif() + set(OMP_FLAG_MIPSpro "-mp") + set(OMP_FLAG_MSVC "-openmp") + set(OMP_FLAG_PathScale "-openmp") + set(OMP_FLAG_NAG "-openmp") + set(OMP_FLAG_Absoft "-openmp") + set(OMP_FLAG_PGI "-mp") + set(OMP_FLAG_SunPro "-xopenmp") + set(OMP_FLAG_XL "-qsmp=omp") + # Cray compiles with OpenMP automatically + set(OMP_FLAG_Cray " ") + + # If we know the correct flags, use those + if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}) + set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}") + # Fall back to reasonable default tries otherwise + else() + set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ") + endif() + set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE) else() - set(OMP_FLAG_Intel "-qopenmp") - endif() - set(OMP_FLAG_MIPSpro "-mp") - set(OMP_FLAG_MSVC "/openmp") - set(OMP_FLAG_PathScale "-openmp") - set(OMP_FLAG_PGI "-mp") - set(OMP_FLAG_SunPro "-xopenmp") - set(OMP_FLAG_XL "-qsmp") - set(OMP_FLAG_Cray " ") - - # Move the flag that matches the compiler to the head of the list, - # this is faster and doesn't clutter the output that much. If that - # flag doesn't work we will still try all. - if(OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}) - list(REMOVE_ITEM OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}") - list(INSERT OpenMP_FLAG_CANDIDATES 0 "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}") + set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE) endif() - - set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE) endfunction() # sample openmp source code to test -set(OpenMP_C_TEST_SOURCE +set(OpenMP_C_CXX_TEST_SOURCE " #include int main() { -#ifdef _OPENMP - return 0; -#else +#ifndef _OPENMP breaks_on_purpose #endif } ") -# same in Fortran +# in Fortran, an implementation may provide an omp_lib.h header +# or omp_lib module, or both (OpenMP standard, section 3.1) +# Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2) +# Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code +# while not actually enabling OpenMP, building code sequentially set(OpenMP_Fortran_TEST_SOURCE " program test - use omp_lib - integer :: n + @OpenMP_Fortran_INCLUDE_LINE@ + !$ integer :: n n = omp_get_num_threads() end program test " - ) +) + +function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH) + set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP) + if("${LANG}" STREQUAL "C") + set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c") + file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") + elseif("${LANG}" STREQUAL "CXX") + set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp") + file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") + elseif("${LANG}" STREQUAL "Fortran") + set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90") + file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}") + configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY) + endif() + set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE) +endfunction() + +include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake) + +function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) + _OPENMP_FLAG_CANDIDATES("${LANG}") + _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC) + + foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES) + set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}") + if(CMAKE_${LANG}_VERBOSE_FLAG) + string(APPEND OPENMP_FLAGS_TEST " ${CMAKE_${LANG}_VERBOSE_FLAG}") + endif() + string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" + OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT + ) + + if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) + set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) + + if(CMAKE_${LANG}_VERBOSE_FLAG) + unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES) + unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS) + unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS) + unset(OpenMP_${LANG}_LOG_VAR) + + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n") + + cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}" + OpenMP_${LANG}_IMPLICIT_LIBRARIES + OpenMP_${LANG}_IMPLICIT_LINK_DIRS + OpenMP_${LANG}_IMPLICIT_FWK_DIRS + OpenMP_${LANG}_LOG_VAR + "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}" + ) + + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n") + + unset(_OPENMP_LIB_NAMES) + foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES) + if(NOT "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES) + find_library(OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY + NAMES "${_OPENMP_IMPLICIT_LIB}" + HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS} + ) + mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY) + list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB}) + endif() + endforeach() + set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE) + else() + # The Intel compiler on windows has no verbose mode, so we need to treat it explicitly + if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Intel" AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + set("${OPENMP_LIB_NAMES_VAR}" "libiomp5md" PARENT_SCOPE) + find_library(OpenMP_libiomp5md_LIBRARY + NAMES "libiomp5md" + HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES} + ) + mark_as_advanced(OpenMP_libiomp5md_LIBRARY) + else() + set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE) + endif() + endif() + break() + endif() + set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE) + set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE) + endforeach() +endfunction() set(OpenMP_C_CXX_CHECK_VERSION_SOURCE " @@ -132,17 +240,16 @@ const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', ('0' + ((_OPENMP/10)%10)), ('0' + ((_OPENMP/1)%10)), ']', '\\0' }; -int main(int argc, char *argv[]) +int main() { - printf(\"%s\\n\", ompver_str); - return 0; + puts(ompver_str); } ") set(OpenMP_Fortran_CHECK_VERSION_SOURCE " program omp_ver - use omp_lib + @OpenMP_Fortran_INCLUDE_LINE@ integer, parameter :: zero = ichar('0') integer, parameter :: ompv = openmp_version character, dimension(24), parameter :: ompver_str =& @@ -159,172 +266,186 @@ set(OpenMP_Fortran_CHECK_VERSION_SOURCE ") function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE) - set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP) - if("${LANG}" STREQUAL "C") - set(SRC_FILE ${WORK_DIR}/ompver.c) - file(WRITE ${SRC_FILE} "${OpenMP_C_CXX_CHECK_VERSION_SOURCE}") - elseif("${LANG}" STREQUAL "CXX") - set(SRC_FILE ${WORK_DIR}/ompver.cpp) - file(WRITE ${SRC_FILE} "${OpenMP_C_CXX_CHECK_VERSION_SOURCE}") - else() # ("${LANG}" STREQUAL "Fortran") - set(SRC_FILE ${WORK_DIR}/ompver.f90) - file(WRITE ${SRC_FILE} "${OpenMP_Fortran_CHECK_VERSION_SOURCE}") - endif() + _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC) - set(BIN_FILE ${WORK_DIR}/ompver_${LANG}.bin) - try_compile(OpenMP_TRY_COMPILE_RESULT ${CMAKE_BINARY_DIR} ${SRC_FILE} + set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin") + string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") + try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}" CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" COPY_FILE ${BIN_FILE}) - if(${OpenMP_TRY_COMPILE_RESULT}) + if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}}) file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date") set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*") if("${specstr}" MATCHES "${regex_spec_date}") set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE) endif() endif() - - unset(OpenMP_TRY_COMPILE_RESULT CACHE) endfunction() +macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG) + set(OpenMP_SPEC_DATE_MAP + # Combined versions, 2.5 onwards + "201511=4.5" + "201307=4.0" + "201107=3.1" + "200805=3.0" + "200505=2.5" + # C/C++ version 2.0 + "200203=2.0" + # Fortran version 2.0 + "200011=2.0" + # Fortran version 1.1 + "199911=1.1" + # C/C++ version 1.0 (there's no 1.1 for C/C++) + "199810=1.0" + # Fortran version 1.0 + "199710=1.0" + ) -# check c compiler -if(CMAKE_C_COMPILER_LOADED) - # if these are set then do not try to find them again, - # by avoiding any try_compiles for the flags - if(OpenMP_C_FLAGS) - unset(OpenMP_C_FLAG_CANDIDATES) + string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}") + if(NOT _version_match STREQUAL "") + set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1}) + set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2}) + set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}") else() - _OPENMP_FLAG_CANDIDATES("C") - include(${CMAKE_CURRENT_LIST_DIR}/CheckCSourceCompiles.cmake) + unset(OpenMP_${LANG}_VERSION_MAJOR) + unset(OpenMP_${LANG}_VERSION_MINOR) + unset(OpenMP_${LANG}_VERSION) endif() - - foreach(FLAG IN LISTS OpenMP_C_FLAG_CANDIDATES) - set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") - set(CMAKE_REQUIRED_FLAGS "${FLAG}") - unset(OpenMP_FLAG_DETECTED CACHE) - if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Try OpenMP C flag = [${FLAG}]") + unset(_version_match) + unset(OpenMP_SPEC_DATE_MAP) +endmacro() + +foreach(LANG IN ITEMS C CXX) + if(CMAKE_${LANG}_COMPILER_LOADED) + if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") + _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK) endif() - check_c_source_compiles("${OpenMP_C_TEST_SOURCE}" OpenMP_FLAG_DETECTED) - set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") - if(OpenMP_FLAG_DETECTED) - set(OpenMP_C_FLAGS_INTERNAL "${FLAG}") - break() - endif() - endforeach() - - set(OpenMP_C_FLAGS "${OpenMP_C_FLAGS_INTERNAL}" - CACHE STRING "C compiler flags for OpenMP parallization") - - list(APPEND _OPENMP_REQUIRED_VARS OpenMP_C_FLAGS) - unset(OpenMP_C_FLAG_CANDIDATES) - if (NOT OpenMP_C_SPEC_DATE) - _OPENMP_GET_SPEC_DATE("C" OpenMP_C_SPEC_DATE_INTERNAL) - set(OpenMP_C_SPEC_DATE "${OpenMP_C_SPEC_DATE_INTERNAL}" CACHE - INTERNAL "C compiler's OpenMP specification date") + set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}" + CACHE STRING "${LANG} compiler flags for OpenMP parallelization") + set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}" + CACHE STRING "${LANG} compiler libraries for OpenMP parallelization") + mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES) endif() -endif() +endforeach() -# check cxx compiler -if(CMAKE_CXX_COMPILER_LOADED) - # if these are set then do not try to find them again, - # by avoiding any try_compiles for the flags - if(OpenMP_CXX_FLAGS) - unset(OpenMP_CXX_FLAG_CANDIDATES) - else() - _OPENMP_FLAG_CANDIDATES("CXX") - include(${CMAKE_CURRENT_LIST_DIR}/CheckCXXSourceCompiles.cmake) +if(CMAKE_Fortran_COMPILER_LOADED) + if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE) + set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none") + _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK) + if(OpenMP_Fortran_FLAGS_WORK) + set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "") + endif() - # use the same source for CXX as C for now - set(OpenMP_CXX_TEST_SOURCE ${OpenMP_C_TEST_SOURCE}) + set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" + CACHE STRING "Fortran compiler flags for OpenMP parallelization") + set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}" + CACHE STRING "Fortran compiler libraries for OpenMP parallelization") + mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES) endif() - foreach(FLAG IN LISTS OpenMP_CXX_FLAG_CANDIDATES) - set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") - set(CMAKE_REQUIRED_FLAGS "${FLAG}") - unset(OpenMP_FLAG_DETECTED CACHE) - if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Try OpenMP CXX flag = [${FLAG}]") + if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER) + set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'") + _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK) + if(OpenMP_Fortran_FLAGS_WORK) + set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "") endif() - check_cxx_source_compiles("${OpenMP_CXX_TEST_SOURCE}" OpenMP_FLAG_DETECTED) - set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") - if(OpenMP_FLAG_DETECTED) - set(OpenMP_CXX_FLAGS_INTERNAL "${FLAG}") - break() - endif() - endforeach() - set(OpenMP_CXX_FLAGS "${OpenMP_CXX_FLAGS_INTERNAL}" - CACHE STRING "C++ compiler flags for OpenMP parallization") + set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" + CACHE STRING "Fortran compiler flags for OpenMP parallelization") - list(APPEND _OPENMP_REQUIRED_VARS OpenMP_CXX_FLAGS) - unset(OpenMP_CXX_FLAG_CANDIDATES) - - if (NOT OpenMP_CXX_SPEC_DATE) - _OPENMP_GET_SPEC_DATE("CXX" OpenMP_CXX_SPEC_DATE_INTERNAL) - set(OpenMP_CXX_SPEC_DATE "${OpenMP_CXX_SPEC_DATE_INTERNAL}" CACHE - INTERNAL "C++ compiler's OpenMP specification date") + set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}" + CACHE STRING "Fortran compiler libraries for OpenMP parallelization") endif() -endif() -# check Fortran compiler -if(CMAKE_Fortran_COMPILER_LOADED) - # if these are set then do not try to find them again, - # by avoiding any try_compiles for the flags - if(OpenMP_Fortran_FLAGS) - unset(OpenMP_Fortran_FLAG_CANDIDATES) + if(OpenMP_Fortran_HAVE_OMPLIB_MODULE) + set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none") else() - _OPENMP_FLAG_CANDIDATES("Fortran") - include(${CMAKE_CURRENT_LIST_DIR}/CheckFortranSourceCompiles.cmake) + set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'") endif() +endif() - foreach(FLAG IN LISTS OpenMP_Fortran_FLAG_CANDIDATES) - set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") - set(CMAKE_REQUIRED_FLAGS "${FLAG}") - unset(OpenMP_FLAG_DETECTED CACHE) - if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Try OpenMP Fortran flag = [${FLAG}]") - endif() - check_fortran_source_compiles("${OpenMP_Fortran_TEST_SOURCE}" OpenMP_FLAG_DETECTED) - set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") - if(OpenMP_FLAG_DETECTED) - set(OpenMP_Fortran_FLAGS_INTERNAL "${FLAG}") - break() - endif() - endforeach() +set(OPENMP_FOUND TRUE) - set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_INTERNAL}" - CACHE STRING "Fortran compiler flags for OpenMP parallization") +foreach(LANG IN ITEMS C CXX Fortran) + if(CMAKE_${LANG}_COMPILER_LOADED) + if (NOT OpenMP_${LANG}_SPEC_DATE) + _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL) + set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE + INTERNAL "${LANG} compiler's OpenMP specification date") + _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}") + endif() - list(APPEND _OPENMP_REQUIRED_VARS OpenMP_Fortran_FLAGS) - unset(OpenMP_Fortran_FLAG_CANDIDATES) + include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) - if (NOT OpenMP_Fortran_SPEC_DATE) - _OPENMP_GET_SPEC_DATE("Fortran" OpenMP_Fortran_SPEC_DATE_INTERNAL) - set(OpenMP_Fortran_SPEC_DATE "${OpenMP_Fortran_SPEC_DATE_INTERNAL}" CACHE - INTERNAL "Fortran compiler's OpenMP specification date") - endif() -endif() + set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY}) + set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED}) + set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION}) + set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT}) -set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) - -if(_OPENMP_REQUIRED_VARS) - include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS) + if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") + set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES) + else() + foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES) + list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY) + endforeach() + endif() - find_package_handle_standard_args(OpenMP - REQUIRED_VARS ${_OPENMP_REQUIRED_VARS}) + find_package_handle_standard_args(OpenMP_${LANG} + REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS} + VERSION_VAR OpenMP_${LANG}_VERSION + ) + + if(OpenMP_${LANG}_FOUND) + set(OpenMP_${LANG}_LIBRARIES "") + foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES) + list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}") + endforeach() + + if(NOT TARGET OpenMP::OpenMP_${LANG}) + add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED) + endif() + if(OpenMP_${LANG}_FLAGS) + separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}") + set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY + INTERFACE_COMPILE_OPTIONS "${_OpenMP_${LANG}_OPTIONS}") + unset(_OpenMP_${LANG}_OPTIONS) + endif() + if(OpenMP_${LANG}_LIBRARIES) + set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY + INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}") + endif() + else() + set(OPENMP_FOUND FALSE) + endif() + endif() +endforeach() - mark_as_advanced(${_OPENMP_REQUIRED_VARS}) +if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND) + if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE) + set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "") + endif() + if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER) + set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "") + endif() +endif() - unset(_OPENMP_REQUIRED_VARS) -else() - message(SEND_ERROR "FindOpenMP requires C or CXX language to be enabled") +if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED )) + message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled") endif() -unset(OpenMP_C_TEST_SOURCE) -unset(OpenMP_CXX_TEST_SOURCE) +unset(OpenMP_C_CXX_TEST_SOURCE) unset(OpenMP_Fortran_TEST_SOURCE) unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE) unset(OpenMP_Fortran_CHECK_VERSION_SOURCE) +unset(OpenMP_Fortran_INCLUDE_LINE) + +cmake_policy(POP) diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 6259ce107..f32eb501d 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -145,6 +145,7 @@ if(WIN32 AND NOT CYGWIN) find_library(LIB_EAY_DEBUG NAMES libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d + libcrypto${_OPENSSL_MSVC_RT_MODE}d libcryptod libeay32${_OPENSSL_MSVC_RT_MODE}d libeay32d @@ -157,9 +158,11 @@ if(WIN32 AND NOT CYGWIN) find_library(LIB_EAY_RELEASE NAMES libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE} + libcrypto${_OPENSSL_MSVC_RT_MODE} libcrypto libeay32${_OPENSSL_MSVC_RT_MODE} libeay32 + crypto NAMES_PER_DIR ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES @@ -169,6 +172,7 @@ if(WIN32 AND NOT CYGWIN) find_library(SSL_EAY_DEBUG NAMES libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d + libssl${_OPENSSL_MSVC_RT_MODE}d libssld ssleay32${_OPENSSL_MSVC_RT_MODE}d ssleay32d @@ -181,6 +185,7 @@ if(WIN32 AND NOT CYGWIN) find_library(SSL_EAY_RELEASE NAMES libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE} + libssl${_OPENSSL_MSVC_RT_MODE} libssl ssleay32${_OPENSSL_MSVC_RT_MODE} ssleay32 @@ -371,7 +376,7 @@ set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ) if (OPENSSL_VERSION) find_package_handle_standard_args(OpenSSL REQUIRED_VARS - OPENSSL_SSL_LIBRARY + #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request? OPENSSL_CRYPTO_LIBRARY OPENSSL_INCLUDE_DIR VERSION_VAR @@ -381,7 +386,7 @@ if (OPENSSL_VERSION) ) else () find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR" - OPENSSL_SSL_LIBRARY + #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request? OPENSSL_CRYPTO_LIBRARY OPENSSL_INCLUDE_DIR ) diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake index b77925dc3..b851a90ff 100644 --- a/Modules/FindPackageHandleStandardArgs.cmake +++ b/Modules/FindPackageHandleStandardArgs.cmake @@ -147,7 +147,7 @@ endmacro() macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: if(${_NAME}_CONFIG) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") else() # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. # List them all in the error message: @@ -374,7 +374,7 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) if(NOT VERSION_OK) _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") else() - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}") endif() endif() diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 1958f4b43..a5357fa1c 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -65,7 +65,7 @@ macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp) set(_pkgconfig_${_varname} "") _pkgconfig_unset(${_prefix}_${_varname}) else() - string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") + string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") if (NOT ${_regexp} STREQUAL "") string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") @@ -86,6 +86,9 @@ endmacro() pkg_get_variable( ) + If multiple values are returned variable will contain a + :ref:`;-list `. + For example: .. code-block:: cmake @@ -190,10 +193,12 @@ function(_pkg_create_imp_target _prefix _no_cmake_path _no_cmake_environment_pat string(APPEND _find_opts " NO_CMAKE_ENVIRONMENT_PATH") endif() + unset(_search_paths) foreach (flag IN LISTS ${_prefix}_LDFLAGS) if (flag MATCHES "^-L(.*)") # only look into the given paths from now on - set(_find_opts HINTS ${CMAKE_MATCH_1} NO_DEFAULT_PATH) + list(APPEND _search_paths ${CMAKE_MATCH_1}) + set(_find_opts HINTS ${_search_paths} NO_DEFAULT_PATH) continue() endif() if (flag MATCHES "^-l(.*)") @@ -312,6 +317,10 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma if(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND _lib_dirs "lib64/pkgconfig") endif() + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + list(APPEND _lib_dirs "libx32/pkgconfig") + endif() endif() endif() list(APPEND _lib_dirs "lib/pkgconfig") @@ -360,38 +369,25 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma set(_pkg_check_modules_pkg_ver) endif() - # handle the operands - if (_pkg_check_modules_pkg_op STREQUAL ">=") - list(APPEND _pkg_check_modules_exist_query --atleast-version) - endif() - - if (_pkg_check_modules_pkg_op STREQUAL "=") - list(APPEND _pkg_check_modules_exist_query --exact-version) - endif() + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION) + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX) + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR) + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR) - if (_pkg_check_modules_pkg_op STREQUAL "<=") - list(APPEND _pkg_check_modules_exist_query --max-version) - endif() + list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}") # create the final query which is of the format: - # * --atleast-version - # * --exact-version - # * --max-version + # * >= + # * = + # * <= # * --exists + list(APPEND _pkg_check_modules_exist_query --print-errors --short-errors) if (_pkg_check_modules_pkg_op) - list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}") + list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name} ${_pkg_check_modules_pkg_op} ${_pkg_check_modules_pkg_ver}") else() list(APPEND _pkg_check_modules_exist_query --exists) + list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}") endif() - list(APPEND _pkg_check_modules_exist_query --print-errors --short-errors) - - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR) - - list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}") - list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}") # execute the query execute_process( @@ -531,6 +527,9 @@ endmacro() = for common case = _STATIC for static linking + Every variable containing multiple values will be a + :ref:`;-list `. + There are some special variables whose prefix depends on the count of given modules. When there is only one module, stays unchanged. When there are multiple modules, the prefix will be diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake index 3ffd5a794..33262f3d6 100644 --- a/Modules/FindProtobuf.cmake +++ b/Modules/FindProtobuf.cmake @@ -20,6 +20,9 @@ # imported .proto files. # ``Protobuf_DEBUG`` # Show debug messages. +# ``Protobuf_USE_STATIC_LIBS`` +# Set to ON to force the use of the static libraries. +# Default is OFF. # # Defines the following variables: # @@ -37,6 +40,15 @@ # ``Protobuf_LITE_LIBRARIES`` # The protobuf-lite libraries # +# The following :prop_tgt:`IMPORTED` targets are also defined: +# +# ``protobuf::libprotobuf`` +# The protobuf library. +# ``protobuf::libprotobuf-lite`` +# The protobuf lite library. +# ``protobuf::libprotoc`` +# The protoc library. +# # The following cache variables are also available to set or use: # # ``Protobuf_LIBRARY`` @@ -64,6 +76,7 @@ # include_directories(${Protobuf_INCLUDE_DIRS}) # include_directories(${CMAKE_CURRENT_BINARY_DIR}) # protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto) +# protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto) # protobuf_generate_python(PROTO_PY foo.proto) # add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS}) # target_link_libraries(bar ${Protobuf_LIBRARIES}) @@ -77,12 +90,15 @@ # # Add custom commands to process ``.proto`` files to C++:: # -# protobuf_generate_cpp ( [...]) +# protobuf_generate_cpp ( [EXPORT_MACRO ] [...]) # # ``SRCS`` # Variable to define with autogenerated source files # ``HDRS`` # Variable to define with autogenerated header files +# ``EXPORT_MACRO`` +# is a macro which should expand to ``__declspec(dllexport)`` or +# ``__declspec(dllimport)`` depending on what is being compiled. # ``ARGN`` # ``.proto`` files # @@ -98,14 +114,21 @@ # ``.proto`` filess function(PROTOBUF_GENERATE_CPP SRCS HDRS) - if(NOT ARGN) + cmake_parse_arguments(protobuf "" "EXPORT_MACRO" "" ${ARGN}) + + set(PROTO_FILES "${protobuf_UNPARSED_ARGUMENTS}") + if(NOT PROTO_FILES) message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files") return() endif() + if(protobuf_EXPORT_MACRO) + set(DLL_EXPORT_DECL "dllexport_decl=${protobuf_EXPORT_MACRO}:") + endif() + if(PROTOBUF_GENERATE_CPP_APPEND_PATH) # Create an include path for each file specified - foreach(FIL ${ARGN}) + foreach(FIL ${PROTO_FILES}) get_filename_component(ABS_FIL ${FIL} ABSOLUTE) get_filename_component(ABS_PATH ${ABS_FIL} PATH) list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) @@ -133,7 +156,7 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS) set(${SRCS}) set(${HDRS}) - foreach(FIL ${ARGN}) + foreach(FIL ${PROTO_FILES}) get_filename_component(ABS_FIL ${FIL} ABSOLUTE) get_filename_component(FIL_WE ${FIL} NAME_WE) if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH) @@ -150,7 +173,7 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS) OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc" "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h" COMMAND ${Protobuf_PROTOC_EXECUTABLE} - ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL} + ARGS "--cpp_out=${DLL_EXPORT_DECL}${CMAKE_CURRENT_BINARY_DIR}" ${_protobuf_include_path} ${ABS_FIL} DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE} COMMENT "Running C++ protocol buffer compiler on ${FIL}" VERBATIM ) @@ -218,6 +241,14 @@ function(PROTOBUF_GENERATE_PYTHON SRCS) set(${SRCS} ${${SRCS}} PARENT_SCOPE) endfunction() + +if(Protobuf_DEBUG) + # Output some of their choices + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Protobuf_USE_STATIC_LIBS = ${Protobuf_USE_STATIC_LIBS}") +endif() + + # Backwards compatibility # Define camel case versions of input variables foreach(UPPER @@ -245,6 +276,17 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_PROTOBUF_ARCH_DIR x64/) endif() + +# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES +if( Protobuf_USE_STATIC_LIBS ) + set( _protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) + endif() +endif() + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) # Internal function: search for normal library as well as a debug one @@ -387,6 +429,78 @@ if(Protobuf_INCLUDE_DIR) message(WARNING "Protobuf compiler version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" " doesn't match library version ${Protobuf_VERSION}") endif() + + if(Protobuf_LIBRARY) + if(NOT TARGET protobuf::libprotobuf) + add_library(protobuf::libprotobuf UNKNOWN IMPORTED) + set_target_properties(protobuf::libprotobuf PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}") + if(EXISTS "${Protobuf_LIBRARY}") + set_target_properties(protobuf::libprotobuf PROPERTIES + IMPORTED_LOCATION "${Protobuf_LIBRARY}") + endif() + if(EXISTS "${Protobuf_LIBRARY_RELEASE}") + set_property(TARGET protobuf::libprotobuf APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(protobuf::libprotobuf PROPERTIES + IMPORTED_LOCATION_RELEASE "${Protobuf_LIBRARY_RELEASE}") + endif() + if(EXISTS "${Protobuf_LIBRARY_DEBUG}") + set_property(TARGET protobuf::libprotobuf APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(protobuf::libprotobuf PROPERTIES + IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}") + endif() + endif() + endif() + + if(Protobuf_LITE_LIBRARY) + if(NOT TARGET protobuf::libprotobuf-lite) + add_library(protobuf::libprotobuf-lite UNKNOWN IMPORTED) + set_target_properties(protobuf::libprotobuf-lite PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}") + if(EXISTS "${Protobuf_LITE_LIBRARY}") + set_target_properties(protobuf::libprotobuf-lite PROPERTIES + IMPORTED_LOCATION "${Protobuf_LITE_LIBRARY}") + endif() + if(EXISTS "${Protobuf_LITE_LIBRARY_RELEASE}") + set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(protobuf::libprotobuf-lite PROPERTIES + IMPORTED_LOCATION_RELEASE "${Protobuf_LITE_LIBRARY_RELEASE}") + endif() + if(EXISTS "${Protobuf_LITE_LIBRARY_DEBUG}") + set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(protobuf::libprotobuf-lite PROPERTIES + IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}") + endif() + endif() + endif() + + if(Protobuf_PROTOC_LIBRARY) + if(NOT TARGET protobuf::libprotoc) + add_library(protobuf::libprotoc UNKNOWN IMPORTED) + set_target_properties(protobuf::libprotoc PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}") + if(EXISTS "${Protobuf_PROTOC_LIBRARY}") + set_target_properties(protobuf::libprotoc PROPERTIES + IMPORTED_LOCATION "${Protobuf_PROTOC_LIBRARY}") + endif() + if(EXISTS "${Protobuf_PROTOC_LIBRARY_RELEASE}") + set_property(TARGET protobuf::libprotoc APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(protobuf::libprotoc PROPERTIES + IMPORTED_LOCATION_RELEASE "${Protobuf_PROTOC_LIBRARY_RELEASE}") + endif() + if(EXISTS "${Protobuf_PROTOC_LIBRARY_DEBUG}") + set_property(TARGET protobuf::libprotoc APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(protobuf::libprotoc PROPERTIES + IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}") + endif() + endif() + endif() endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) @@ -399,6 +513,11 @@ if(Protobuf_FOUND) set(Protobuf_INCLUDE_DIRS ${Protobuf_INCLUDE_DIR}) endif() +# Restore the original find library ordering +if( Protobuf_USE_STATIC_LIBS ) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +endif() + # Backwards compatibility # Define upper case versions of output variables foreach(Camel diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake index f25524612..64b98a879 100644 --- a/Modules/FindPythonInterp.cmake +++ b/Modules/FindPythonInterp.cmake @@ -91,12 +91,15 @@ unset(_PYTHON3_VERSIONS) if(NOT PYTHON_EXECUTABLE) foreach(_CURRENT_VERSION IN LISTS _Python_VERSIONS) set(_Python_NAMES python${_CURRENT_VERSION}) - if(WIN32) + if(CMAKE_HOST_WIN32) list(APPEND _Python_NAMES python) endif() find_program(PYTHON_EXECUTABLE NAMES ${_Python_NAMES} - PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath] + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-32\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-64\\InstallPath] ) endforeach() endif() diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake index a97bb1b2a..ffdf677cc 100644 --- a/Modules/FindXCTest.cmake +++ b/Modules/FindXCTest.cmake @@ -123,6 +123,10 @@ function(xctest_add_bundle target testee) # testee is a Framework target_link_libraries(${target} PRIVATE ${testee}) + elseif(_testee_type STREQUAL "STATIC_LIBRARY") + # testee is a static library + target_link_libraries(${target} PRIVATE ${testee}) + elseif(_testee_type STREQUAL "EXECUTABLE" AND _testee_macosx_bundle) # testee is an App Bundle add_dependencies(${target} ${testee}) diff --git a/Modules/FindXMLRPC.cmake b/Modules/FindXMLRPC.cmake index dd9dffc9a..f0b258397 100644 --- a/Modules/FindXMLRPC.cmake +++ b/Modules/FindXMLRPC.cmake @@ -36,13 +36,13 @@ find_program(XMLRPC_C_CONFIG NAMES xmlrpc-c-config) # Check whether we found anything. if(XMLRPC_C_CONFIG) - set(XMLRPC_FOUND 1) + set(XMLRPC_C_FOUND 1) else() - set(XMLRPC_FOUND 0) + set(XMLRPC_C_FOUND 0) endif() # Lookup the include directories needed for the components requested. -if(XMLRPC_FOUND) +if(XMLRPC_C_FOUND) # Use the newer EXECUTE_PROCESS command if it is available. if(COMMAND EXECUTE_PROCESS) execute_process( @@ -74,12 +74,12 @@ if(XMLRPC_FOUND) endforeach() else() message("Error running ${XMLRPC_C_CONFIG}: [${XMLRPC_C_CONFIG_RESULT}]") - set(XMLRPC_FOUND 0) + set(XMLRPC_C_FOUND 0) endif() endif() # Lookup the libraries needed for the components requested. -if(XMLRPC_FOUND) +if(XMLRPC_C_FOUND) # Use the newer EXECUTE_PROCESS command if it is available. if(COMMAND EXECUTE_PROCESS) execute_process( @@ -123,7 +123,7 @@ if(XMLRPC_FOUND) # If any library is not found then the whole package is not found. if(NOT XMLRPC_${name}_LIBRARY) - set(XMLRPC_FOUND 0) + set(XMLRPC_C_FOUND 0) endif() # Build an ordered list of all the libraries needed. @@ -131,19 +131,13 @@ if(XMLRPC_FOUND) endforeach() else() message("Error running ${XMLRPC_C_CONFIG}: [${XMLRPC_C_CONFIG_RESULT}]") - set(XMLRPC_FOUND 0) + set(XMLRPC_C_FOUND 0) endif() endif() # Report the results. -if(NOT XMLRPC_FOUND) - set(XMLRPC_DIR_MESSAGE - "XMLRPC was not found. Make sure the entries XMLRPC_* are set.") - if(NOT XMLRPC_FIND_QUIETLY) - message(STATUS "${XMLRPC_DIR_MESSAGE}") - else() - if(XMLRPC_FIND_REQUIRED) - message(FATAL_ERROR "${XMLRPC_DIR_MESSAGE}") - endif() - endif() -endif() +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( + XMLRPC + REQUIRED_VARS XMLRPC_C_FOUND XMLRPC_LIBRARIES XMLRPC_INCLUDE_DIRS + FAIL_MESSAGE "XMLRPC was not found. Make sure the entries XMLRPC_* are set.") diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake index bc906e59a..af4daf061 100644 --- a/Modules/FindwxWidgets.cmake +++ b/Modules/FindwxWidgets.cmake @@ -893,6 +893,28 @@ else() endif() endif() +# Check that all libraries are present, as wx-config does not check it +set(_wx_lib_missing "") +foreach(_wx_lib_ ${wxWidgets_LIBRARIES}) + if("${_wx_lib_}" MATCHES "^-l(.*)") + set(_wx_lib_name "${CMAKE_MATCH_1}") + unset(_wx_lib_found CACHE) + find_library(_wx_lib_found NAMES ${_wx_lib_name} HINTS ${wxWidgets_LIBRARY_DIRS}) + if(_wx_lib_found STREQUAL _wx_lib_found-NOTFOUND) + list(APPEND _wx_lib_missing ${_wx_lib_name}) + endif() + unset(_wx_lib_found CACHE) + endif() +endforeach() + +if (_wx_lib_missing) + string(REPLACE ";" " " _wx_lib_missing "${_wx_lib_missing}") + DBG_MSG_V("wxWidgets not found due to following missing libraries: ${_wx_lib_missing}") + set(wxWidgets_FOUND FALSE) + unset(wxWidgets_LIBRARIES) +endif() +unset(_wx_lib_missing) + # Check if a specfic version was requested by find_package(). if(wxWidgets_FOUND) find_file(_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH) diff --git a/Modules/FortranCInterface/CMakeLists.txt b/Modules/FortranCInterface/CMakeLists.txt index 3a66f680a..e3b81d7c3 100644 --- a/Modules/FortranCInterface/CMakeLists.txt +++ b/Modules/FortranCInterface/CMakeLists.txt @@ -15,11 +15,11 @@ int main() { return 0; } # List manglings of global symbol names to try. set(global_symbols my_sub # VisualAge - my_sub_ # GNU, Intel, HP, SunPro, MIPSpro + my_sub_ # GNU, Intel, HP, SunPro, MIPSpro, PGI my_sub__ # GNU g77 MY_SUB # Intel on Windows mysub # VisualAge - mysub_ # GNU, Intel, HP, SunPro, MIPSpro + mysub_ # GNU, Intel, HP, SunPro, MIPSpro, PGI MYSUB # Intel on Windows ${FortranCInterface_GLOBAL_SYMBOLS} ) @@ -71,7 +71,7 @@ if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "^(PathScale|Cray)$") # use '.in.' so we cannot provide them anyway. # - Cray Fortran >= 7.3.2 uses module init symbols but module symbols # use 'mysub$mymodule_' so we cannot provide them anyway. - list(APPEND symbol_sources mymodule_.c my_module_.c) + list(APPEND symbol_sources mymodule_.c my_module_.c MY_MODULE.c MYMODULE.c) endif() foreach(symbol IN LISTS global_symbols module_symbols) # Skip symbols with '$' if C cannot handle them. @@ -93,11 +93,12 @@ add_library(myfort STATIC mysub.f my_sub.f ${myfort_modules}) # Provide symbols through C but fall back to Fortran. add_library(symbols STATIC ${symbol_sources}) -target_link_libraries(symbols myfort) +target_link_libraries(symbols PUBLIC myfort) + # In case the Fortran compiler produces PIC by default make sure # the C compiler produces PIC even if it is not its default. set_property(TARGET symbols PROPERTY POSITION_INDEPENDENT_CODE 1) # Require symbols through Fortran. add_executable(FortranCInterface main.F call_sub.f ${call_mod}) -target_link_libraries(FortranCInterface symbols) +target_link_libraries(FortranCInterface PUBLIC symbols) diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index 76128902f..778978533 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -27,6 +27,7 @@ unset(FortranCInterface_VERIFIED_CXX CACHE) set(_result) # Build a sample project which reports symbols. +set(CMAKE_TRY_COMPILE_CONFIGURATION Release) try_compile(FortranCInterface_COMPILED ${FortranCInterface_BINARY_DIR} ${FortranCInterface_SOURCE_DIR} @@ -35,6 +36,8 @@ try_compile(FortranCInterface_COMPILED CMAKE_FLAGS "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" "-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}" OUTPUT_VARIABLE FortranCInterface_OUTPUT) set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED}) unset(FortranCInterface_COMPILED CACHE) @@ -43,7 +46,7 @@ unset(FortranCInterface_COMPILED CACHE) if(FortranCInterface_COMPILED) find_program(FortranCInterface_EXE NAMES FortranCInterface${CMAKE_EXECUTABLE_SUFFIX} - PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Debug + PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Release NO_DEFAULT_PATH ) set(FortranCInterface_EXE ${FortranCInterface_EXE}) diff --git a/Modules/FortranCInterface/MYMODULE.c b/Modules/FortranCInterface/MYMODULE.c new file mode 100644 index 000000000..19b51fbad --- /dev/null +++ b/Modules/FortranCInterface/MYMODULE.c @@ -0,0 +1,3 @@ +void MYMODULE(void) +{ +} diff --git a/Modules/FortranCInterface/MY_MODULE.c b/Modules/FortranCInterface/MY_MODULE.c new file mode 100644 index 000000000..87b30717c --- /dev/null +++ b/Modules/FortranCInterface/MY_MODULE.c @@ -0,0 +1,3 @@ +void MY_MODULE(void) +{ +} diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake index 9599f270c..64bd09e68 100644 --- a/Modules/GNUInstallDirs.cmake +++ b/Modules/GNUInstallDirs.cmake @@ -45,6 +45,8 @@ # modifiable architecture-independent data (``com``) # ``LOCALSTATEDIR`` # modifiable single-machine data (``var``) +# ``RUNSTATEDIR`` +# run-time variable data (``LOCALSTATEDIR/run``) # ``LIBDIR`` # object code libraries (``lib`` or ``lib64`` # or ``lib/`` on Debian) @@ -75,10 +77,10 @@ # # ``/`` # -# For ```` other than the ``SYSCONFDIR`` and ``LOCALSTATEDIR``, -# the value of ``CMAKE_INSTALL_`` is prefixed with ``usr/`` if -# it is not user-specified as an absolute path. For example, the -# ``INCLUDEDIR`` value ``include`` becomes ``usr/include``. +# For ```` other than the ``SYSCONFDIR``, ``LOCALSTATEDIR`` and +# ``RUNSTATEDIR``, the value of ``CMAKE_INSTALL_`` is prefixed +# with ``usr/`` if it is not user-specified as an absolute path. +# For example, the ``INCLUDEDIR`` value ``include`` becomes ``usr/include``. # This is required by the `GNU Coding Standards`_, which state: # # When building the complete GNU system, the prefix will be empty @@ -86,20 +88,21 @@ # # ``/usr`` # -# For ```` equal to ``SYSCONFDIR`` or ``LOCALSTATEDIR``, the -# ``CMAKE_INSTALL_FULL_`` is computed by prepending just ``/`` -# to the value of ``CMAKE_INSTALL_`` if it is not user-specified -# as an absolute path. For example, the ``SYSCONFDIR`` value ``etc`` -# becomes ``/etc``. This is required by the `GNU Coding Standards`_. +# For ```` equal to ``SYSCONFDIR``, ``LOCALSTATEDIR`` or +# ``RUNSTATEDIR``, the ``CMAKE_INSTALL_FULL_`` is computed by +# prepending just ``/`` to the value of ``CMAKE_INSTALL_`` +# if it is not user-specified as an absolute path. +# For example, the ``SYSCONFDIR`` value ``etc`` becomes ``/etc``. +# This is required by the `GNU Coding Standards`_. # # ``/opt/...`` # -# For ```` equal to ``SYSCONFDIR`` or ``LOCALSTATEDIR``, the -# ``CMAKE_INSTALL_FULL_`` is computed by *appending* the prefix -# to the value of ``CMAKE_INSTALL_`` if it is not user-specified -# as an absolute path. For example, the ``SYSCONFDIR`` value ``etc`` -# becomes ``/etc/opt/...``. This is defined by the -# `Filesystem Hierarchy Standard`_. +# For ```` equal to ``SYSCONFDIR``, ``LOCALSTATEDIR`` or +# ``RUNSTATEDIR``, the ``CMAKE_INSTALL_FULL_`` is computed by +# *appending* the prefix to the value of ``CMAKE_INSTALL_`` +# if it is not user-specified as an absolute path. +# For example, the ``SYSCONFDIR`` value ``etc`` becomes ``/etc/opt/...``. +# This is defined by the `Filesystem Hierarchy Standard`_. # # .. _`Filesystem Hierarchy Standard`: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html # @@ -287,6 +290,9 @@ _GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DAT _GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}" "Documentation root (DATAROOTDIR/doc/PROJECT_NAME)") +_GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_RUNSTATEDIR "${CMAKE_INSTALL_LOCALSTATEDIR}/run" + "Run-time variable data (LOCALSTATEDIR/run)") + #----------------------------------------------------------------------------- mark_as_advanced( @@ -296,6 +302,7 @@ mark_as_advanced( CMAKE_INSTALL_SYSCONFDIR CMAKE_INSTALL_SHAREDSTATEDIR CMAKE_INSTALL_LOCALSTATEDIR + CMAKE_INSTALL_RUNSTATEDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_OLDINCLUDEDIR @@ -314,7 +321,7 @@ macro(GNUInstallDirs_get_absolute_install_dir absvar var) # - CMAKE_INSTALL_PREFIX == /usr # - CMAKE_INSTALL_PREFIX == /opt/... if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/") - if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR") + if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR") set(${absvar} "/${${var}}") else() if (NOT "${${var}}" MATCHES "^usr/") @@ -323,13 +330,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") + if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${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") + if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR") set(${absvar} "/${${var}}${CMAKE_INSTALL_PREFIX}") else() set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}") @@ -351,6 +358,7 @@ foreach(dir SYSCONFDIR SHAREDSTATEDIR LOCALSTATEDIR + RUNSTATEDIR LIBDIR INCLUDEDIR OLDINCLUDEDIR diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake index 6d1b4ed9b..4573c2e77 100644 --- a/Modules/GenerateExportHeader.cmake +++ b/Modules/GenerateExportHeader.cmake @@ -215,9 +215,6 @@ macro(_test_compiler_hidden_visibility) check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) check_cxx_compiler_flag(-fvisibility-inlines-hidden COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) - option(USE_COMPILER_HIDDEN_VISIBILITY - "Use HIDDEN visibility support if available." ON) - mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) endif() endmacro() @@ -267,7 +264,7 @@ macro(_DO_SET_MACRO_VALUES TARGET_LIBRARY) if(WIN32 OR CYGWIN) set(DEFINE_EXPORT "__declspec(dllexport)") set(DEFINE_IMPORT "__declspec(dllimport)") - elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY) + elseif(COMPILER_HAS_HIDDEN_VISIBILITY) set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))") set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))") set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") @@ -388,6 +385,9 @@ function(add_compiler_export_flags) _test_compiler_hidden_visibility() _test_compiler_has_deprecated() + option(USE_COMPILER_HIDDEN_VISIBILITY + "Use HIDDEN visibility support if available." ON) + mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY)) # Just return if there are no flags to add. return() diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 1b23800c4..4e52cb300 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -399,6 +399,11 @@ function(gp_resolve_item context item exepath dirs resolved_item_var) set(ri "ri-NOTFOUND") find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) find_file(ri "${item}" ${exepath} ${dirs} /usr/lib) + + get_filename_component(basename_item "${item}" NAME) + find_file(ri "${basename_item}" PATHS ${exepath} ${dirs} NO_DEFAULT_PATH) + find_file(ri "${basename_item}" PATHS /usr/lib) + if(ri) #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") set(resolved 1) @@ -516,7 +521,7 @@ function(gp_resolved_file_type original_file file exepath dirs type_var) string(TOLOWER "${resolved_file}" lower) if(UNIX) - if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)") + if(resolved_file MATCHES "^(/lib/|/lib32/|/libx32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/libx32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)") set(is_system 1) endif() endif() @@ -604,7 +609,7 @@ function(gp_resolved_file_type original_file file exepath dirs type_var) if(NOT is_embedded) if(NOT IS_ABSOLUTE "${resolved_file}") - if(lower MATCHES "^msvc[^/]+dll" AND is_system) + if(lower MATCHES "^(msvc|api-ms-win-)[^/]+dll" AND is_system) message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'") else() message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect") @@ -938,7 +943,11 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa # if(NOT list_length_before_append EQUAL list_length_after_append) gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item "${rpaths}") - set(unseen_prereqs ${unseen_prereqs} "${resolved_item}") + if(EXISTS "${resolved_item}") + # Recurse only if we could resolve the item. + # Otherwise the prerequisites_var list will be cleared + set(unseen_prereqs ${unseen_prereqs} "${resolved_item}") + endif() endif() endif() endif() diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake new file mode 100644 index 000000000..7415e0681 --- /dev/null +++ b/Modules/GoogleTest.cmake @@ -0,0 +1,226 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +GoogleTest +---------- + +This module defines functions to help use the Google Test infrastructure. + +.. command:: gtest_add_tests + + Automatically add tests with CTest by scanning source code for Google Test + macros:: + + gtest_add_tests(TARGET target + [SOURCES src1...] + [EXTRA_ARGS arg1...] + [WORKING_DIRECTORY dir] + [TEST_PREFIX prefix] + [TEST_SUFFIX suffix] + [SKIP_DEPENDENCY] + [TEST_LIST outVar] + ) + + ``TARGET target`` + This must be a known CMake target. CMake will substitute the location of + the built executable when running the test. + + ``SOURCES src1...`` + When provided, only the listed files will be scanned for test cases. If + this option is not given, the :prop_tgt:`SOURCES` property of the + specified ``target`` will be used to obtain the list of sources. + + ``EXTRA_ARGS arg1...`` + Any extra arguments to pass on the command line to each test case. + + ``WORKING_DIRECTORY dir`` + Specifies the directory in which to run the discovered test cases. If this + option is not provided, the current binary directory is used. + + ``TEST_PREFIX prefix`` + Allows the specified ``prefix`` to be prepended to the name of each + discovered test case. This can be useful when the same source files are + being used in multiple calls to ``gtest_add_test()`` but with different + ``EXTRA_ARGS``. + + ``TEST_SUFFIX suffix`` + Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of + every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` can be + specified. + + ``SKIP_DEPENDENCY`` + Normally, the function creates a dependency which will cause CMake to be + re-run if any of the sources being scanned are changed. This is to ensure + that the list of discovered tests is updated. If this behavior is not + desired (as may be the case while actually writing the test cases), this + option can be used to prevent the dependency from being added. + + ``TEST_LIST outVar`` + The variable named by ``outVar`` will be populated in the calling scope + with the list of discovered test cases. This allows the caller to do things + like manipulate test properties of the discovered tests. + + .. code-block:: cmake + + include(GoogleTest) + add_executable(FooTest FooUnitTest.cxx) + gtest_add_tests(TARGET FooTest + TEST_SUFFIX .noArgs + TEST_LIST noArgsTests + ) + gtest_add_tests(TARGET FooTest + EXTRA_ARGS --someArg someValue + TEST_SUFFIX .withArgs + TEST_LIST withArgsTests + ) + set_tests_properties(${noArgsTests} PROPERTIES TIMEOUT 10) + set_tests_properties(${withArgsTests} PROPERTIES TIMEOUT 20) + + For backward compatibility reasons, the following form is also supported:: + + gtest_add_tests(exe args files...) + + ``exe`` + The path to the test executable or the name of a CMake target. + ``args`` + A ;-list of extra arguments to be passed to executable. The entire + list must be passed as a single argument. Enclose it in quotes, + or pass ``""`` for no arguments. + ``files...`` + A list of source files to search for tests and test fixtures. + Alternatively, use ``AUTO`` to specify that ``exe`` is the name + of a CMake executable target whose sources should be scanned. + + .. code-block:: cmake + + include(GoogleTest) + set(FooTestArgs --foo 1 --bar 2) + add_executable(FooTest FooUnitTest.cxx) + gtest_add_tests(FooTest "${FooTestArgs}" AUTO) + +#]=======================================================================] + +function(gtest_add_tests) + + if (ARGC LESS 1) + message(FATAL_ERROR "No arguments supplied to gtest_add_tests()") + endif() + + set(options + SKIP_DEPENDENCY + ) + set(oneValueArgs + TARGET + WORKING_DIRECTORY + TEST_PREFIX + TEST_SUFFIX + TEST_LIST + ) + set(multiValueArgs + SOURCES + EXTRA_ARGS + ) + set(allKeywords ${options} ${oneValueArgs} ${multiValueArgs}) + + unset(sources) + if("${ARGV0}" IN_LIST allKeywords) + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(autoAddSources YES) + else() + # Non-keyword syntax, convert to keyword form + if (ARGC LESS 3) + message(FATAL_ERROR "gtest_add_tests() without keyword options requires at least 3 arguments") + endif() + set(ARGS_TARGET "${ARGV0}") + set(ARGS_EXTRA_ARGS "${ARGV1}") + if(NOT "${ARGV2}" STREQUAL "AUTO") + set(ARGS_SOURCES "${ARGV}") + list(REMOVE_AT ARGS_SOURCES 0 1) + endif() + endif() + + # The non-keyword syntax allows the first argument to be an arbitrary + # executable rather than a target if source files are also provided. In all + # other cases, both forms require a target. + if(NOT TARGET "${ARGS_TARGET}" AND NOT ARGS_SOURCES) + message(FATAL_ERROR "${ARGS_TARGET} does not define an existing CMake target") + endif() + if(NOT ARGS_WORKING_DIRECTORY) + unset(workDir) + else() + set(workDir WORKING_DIRECTORY "${ARGS_WORKING_DIRECTORY}") + endif() + + if(NOT ARGS_SOURCES) + get_property(ARGS_SOURCES TARGET ${ARGS_TARGET} PROPERTY SOURCES) + endif() + + unset(testList) + + set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*") + set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)") + + foreach(source IN LISTS ARGS_SOURCES) + if(NOT ARGS_SKIP_DEPENDENCY) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) + endif() + file(READ "${source}" contents) + string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents}) + foreach(hit ${found_tests}) + string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit}) + + # Parameterized tests have a different signature for the filter + if("x${test_type}" STREQUAL "xTEST_P") + string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" gtest_test_name ${hit}) + elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST") + string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" gtest_test_name ${hit}) + elseif("x${test_type}" STREQUAL "xTYPED_TEST") + string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" gtest_test_name ${hit}) + else() + message(WARNING "Could not parse GTest ${hit} for adding to CTest.") + continue() + endif() + + # Make sure tests disabled in GTest get disabled in CTest + if(gtest_test_name MATCHES "(^|\\.)DISABLED_") + # Add the disabled test if CMake is new enough + # Note that this check is to allow backwards compatibility so this + # module can be copied locally in projects to use with older CMake + # versions + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.8.20170401) + string(REGEX REPLACE + "(^|\\.)DISABLED_" "\\1" + orig_test_name "${gtest_test_name}" + ) + set(ctest_test_name + ${ARGS_TEST_PREFIX}${orig_test_name}${ARGS_TEST_SUFFIX} + ) + add_test(NAME ${ctest_test_name} + ${workDir} + COMMAND ${ARGS_TARGET} + --gtest_also_run_disabled_tests + --gtest_filter=${gtest_test_name} + ${ARGS_EXTRA_ARGS} + ) + set_tests_properties(${ctest_test_name} PROPERTIES DISABLED TRUE) + list(APPEND testList ${ctest_test_name}) + endif() + else() + set(ctest_test_name ${ARGS_TEST_PREFIX}${gtest_test_name}${ARGS_TEST_SUFFIX}) + add_test(NAME ${ctest_test_name} + ${workDir} + COMMAND ${ARGS_TARGET} + --gtest_filter=${gtest_test_name} + ${ARGS_EXTRA_ARGS} + ) + list(APPEND testList ${ctest_test_name}) + endif() + endforeach() + endforeach() + + if(ARGS_TEST_LIST) + set(${ARGS_TEST_LIST} ${testList} PARENT_SCOPE) + endif() + +endfunction() diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake index a3478a387..6d33fc6ec 100644 --- a/Modules/InstallRequiredSystemLibraries.cmake +++ b/Modules/InstallRequiredSystemLibraries.cmake @@ -31,6 +31,11 @@ # 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. +# # ``CMAKE_INSTALL_MFC_LIBRARIES`` # Set to TRUE to install the MSVC MFC runtime libraries. # @@ -258,6 +263,7 @@ if(MSVC) set(programfilesx86 "ProgramFiles(x86)") find_path(WINDOWS_KITS_DIR NAMES Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll PATHS + $ENV{CMAKE_WINDOWS_KITS_10_DIR} "${windows_kits_dir}" "$ENV{ProgramFiles}/Windows Kits/10" "$ENV{${programfilesx86}}/Windows Kits/10" diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake index 50b8526f2..de336e708 100644 --- a/Modules/Internal/FeatureTesting.cmake +++ b/Modules/Internal/FeatureTesting.cmake @@ -22,9 +22,18 @@ macro(_record_compiler_features lang compile_flags feature_list) file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "\n};\n\nint main(int argc, char** argv) { (void)argv; return features[argc]; }\n") + if(CMAKE_${lang}_LINK_WITH_STANDARD_COMPILE_OPTION) + # This toolchain requires use of the language standard flag + # when linking in order to use the matching standard library. + set(compile_flags_for_link "${compile_flags}") + else() + set(compile_flags_for_link "") + endif() + try_compile(CMAKE_${lang}_FEATURE_TEST ${CMAKE_BINARY_DIR} "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" COMPILE_DEFINITIONS "${compile_flags}" + LINK_LIBRARIES "${compile_flags_for_link}" OUTPUT_VARIABLE _output COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin" COPY_FILE_ERROR _copy_error @@ -35,6 +44,7 @@ macro(_record_compiler_features lang compile_flags feature_list) set(_result 255) endif() unset(CMAKE_${lang}_FEATURE_TEST CACHE) + unset(compile_flags_for_link) if (_result EQUAL 0) file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log diff --git a/Modules/MacOSXBundleInfo.plist.in b/Modules/MacOSXBundleInfo.plist.in index a4009bce3..e06b17ecf 100644 --- a/Modules/MacOSXBundleInfo.plist.in +++ b/Modules/MacOSXBundleInfo.plist.in @@ -30,5 +30,9 @@ NSHumanReadableCopyright ${MACOSX_BUNDLE_COPYRIGHT} + NSPrincipalClass + NSApplication + NSHighResolutionCapable + True diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake index ca6e97cde..7f08c4a35 100644 --- a/Modules/Platform/AIX-GNU.cmake +++ b/Modules/Platform/AIX-GNU.cmake @@ -19,7 +19,7 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,-brtl") macro(__aix_compiler_gnu lang) set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-blibpath:") set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":") - set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,-G,-bnoipath") + string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-G,-bnoipath") set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall") set(CMAKE_${lang}_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH 1) diff --git a/Modules/Platform/AIX-XL-C.cmake b/Modules/Platform/AIX-XL-C.cmake index 5e437fafd..cbfd58b3d 100644 --- a/Modules/Platform/AIX-XL-C.cmake +++ b/Modules/Platform/AIX-XL-C.cmake @@ -1,2 +1,5 @@ include(Platform/AIX-XL) __aix_compiler_xl(C) + +# -qhalt=e = Halt on error messages (rather than just severe errors) +string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e") diff --git a/Modules/Platform/AIX-XL-CXX.cmake b/Modules/Platform/AIX-XL-CXX.cmake index ef38a5f23..78baef5df 100644 --- a/Modules/Platform/AIX-XL-CXX.cmake +++ b/Modules/Platform/AIX-XL-CXX.cmake @@ -1,2 +1,5 @@ include(Platform/AIX-XL) __aix_compiler_xl(CXX) + +# -qhalt=s = Halt on severe error messages +string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s") diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake index cf2785a97..5faada3b0 100644 --- a/Modules/Platform/Android-Common.cmake +++ b/Modules/Platform/Android-Common.cmake @@ -156,6 +156,17 @@ macro(__android_compiler_common lang) # necessary so that Android API-version-specific headers are preferred # over those in the toolchain's `include-fixed` directory (which cannot # possibly match all versions). - list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_SYSROOT}/usr/include") - list(REMOVE_ITEM CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include") + # + # Do not do this for a standalone toolchain because it is already + # tied to a specific API version. + if(CMAKE_ANDROID_NDK) + if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) + list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES + "${CMAKE_SYSROOT_COMPILE}/usr/include" + "${CMAKE_SYSROOT_COMPILE}/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}" + ) + else() + list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_SYSROOT}/usr/include") + endif() + endif() endmacro() diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake index 6d370ab27..add1dc1f7 100644 --- a/Modules/Platform/Android-Determine.cmake +++ b/Modules/Platform/Android-Determine.cmake @@ -100,11 +100,34 @@ endif() set(_ANDROID_STANDALONE_TOOLCHAIN_API "") if(CMAKE_ANDROID_STANDALONE_TOOLCHAIN) - set(_ANDROID_API_LEVEL_H_REGEX "^[\t ]*#[\t ]*define[\t ]+__ANDROID_API__[\t ]+([0-9]+)") - file(STRINGS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" - _ANDROID_API_LEVEL_H_CONTENT REGEX "${_ANDROID_API_LEVEL_H_REGEX}") - if(_ANDROID_API_LEVEL_H_CONTENT MATCHES "${_ANDROID_API_LEVEL_H_REGEX}") - set(_ANDROID_STANDALONE_TOOLCHAIN_API "${CMAKE_MATCH_1}") + # Try to read the API level from the toolchain launcher. + if(EXISTS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/bin/clang") + set(_ANDROID_API_LEVEL_CLANG_REGEX "__ANDROID_API__=([0-9]+)") + file(STRINGS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/bin/clang" _ANDROID_STANDALONE_TOOLCHAIN_BIN_CLANG + REGEX "${_ANDROID_API_LEVEL_CLANG_REGEX}" LIMIT_COUNT 1 LIMIT_INPUT 65536) + if(_ANDROID_STANDALONE_TOOLCHAIN_BIN_CLANG MATCHES "${_ANDROID_API_LEVEL_CLANG_REGEX}") + set(_ANDROID_STANDALONE_TOOLCHAIN_API "${CMAKE_MATCH_1}") + endif() + unset(_ANDROID_STANDALONE_TOOLCHAIN_BIN_CLANG) + unset(_ANDROID_API_LEVEL_CLANG_REGEX) + endif() + if(NOT _ANDROID_STANDALONE_TOOLCHAIN_API) + # The compiler launcher does not know __ANDROID_API__. Assume this + # is not unified headers and look for it in the api-level.h header. + set(_ANDROID_API_LEVEL_H_REGEX "^[\t ]*#[\t ]*define[\t ]+__ANDROID_API__[\t ]+([0-9]+)") + file(STRINGS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" + _ANDROID_API_LEVEL_H_CONTENT REGEX "${_ANDROID_API_LEVEL_H_REGEX}") + if(_ANDROID_API_LEVEL_H_CONTENT MATCHES "${_ANDROID_API_LEVEL_H_REGEX}") + set(_ANDROID_STANDALONE_TOOLCHAIN_API "${CMAKE_MATCH_1}") + endif() + endif() + if(NOT _ANDROID_STANDALONE_TOOLCHAIN_API) + message(WARNING + "Android: Did not detect API level from\n" + " ${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/bin/clang\n" + "or\n" + " ${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h\n" + ) endif() endif() @@ -174,22 +197,30 @@ 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_armeabi-v7a_PROC "armv7-a") -set(_ANDROID_ABI_armeabi-v7a_ARCH "arm") -set(_ANDROID_ABI_armeabi-v6_PROC "armv6") -set(_ANDROID_ABI_armeabi-v6_ARCH "arm") -set(_ANDROID_ABI_armeabi_PROC "armv5te") -set(_ANDROID_ABI_armeabi_ARCH "arm") -set(_ANDROID_ABI_mips_PROC "mips") -set(_ANDROID_ABI_mips_ARCH "mips") -set(_ANDROID_ABI_mips64_PROC "mips64") -set(_ANDROID_ABI_mips64_ARCH "mips64") -set(_ANDROID_ABI_x86_PROC "i686") -set(_ANDROID_ABI_x86_ARCH "x86") -set(_ANDROID_ABI_x86_64_PROC "x86_64") -set(_ANDROID_ABI_x86_64_ARCH "x86_64") +set(_ANDROID_ABI_arm64-v8a_PROC "aarch64") +set(_ANDROID_ABI_arm64-v8a_ARCH "arm64") +set(_ANDROID_ABI_arm64-v8a_HEADER "aarch64-linux-android") +set(_ANDROID_ABI_armeabi-v7a_PROC "armv7-a") +set(_ANDROID_ABI_armeabi-v7a_ARCH "arm") +set(_ANDROID_ABI_armeabi-v7a_HEADER "arm-linux-androideabi") +set(_ANDROID_ABI_armeabi-v6_PROC "armv6") +set(_ANDROID_ABI_armeabi-v6_ARCH "arm") +set(_ANDROID_ABI_armeabi-v6_HEADER "arm-linux-androideabi") +set(_ANDROID_ABI_armeabi_PROC "armv5te") +set(_ANDROID_ABI_armeabi_ARCH "arm") +set(_ANDROID_ABI_armeabi_HEADER "arm-linux-androideabi") +set(_ANDROID_ABI_mips_PROC "mips") +set(_ANDROID_ABI_mips_ARCH "mips") +set(_ANDROID_ABI_mips_HEADER "mipsel-linux-android") +set(_ANDROID_ABI_mips64_PROC "mips64") +set(_ANDROID_ABI_mips64_ARCH "mips64") +set(_ANDROID_ABI_mips64_HEADER "mips64el-linux-android") +set(_ANDROID_ABI_x86_PROC "i686") +set(_ANDROID_ABI_x86_ARCH "x86") +set(_ANDROID_ABI_x86_HEADER "i686-linux-android") +set(_ANDROID_ABI_x86_64_PROC "x86_64") +set(_ANDROID_ABI_x86_64_ARCH "x86_64") +set(_ANDROID_ABI_x86_64_HEADER "x86_64-linux-android") set(_ANDROID_PROC_aarch64_ARCH_ABI "arm64-v8a") set(_ANDROID_PROC_armv7-a_ARCH_ABI "armeabi-v7a") @@ -241,6 +272,7 @@ 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_HEADER_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_HEADER}") # Select a processor. if(NOT CMAKE_SYSTEM_PROCESSOR) @@ -252,6 +284,16 @@ if(NOT _ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC STREQUAL CMAKE_SYSTEM_PROCESS 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() +if(CMAKE_ANDROID_NDK AND NOT DEFINED CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) + if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}") + # Unified headers exist so we use them by default. + set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS 0) + else() + # Unified headers do not exist so use the deprecated headers. + set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS 1) + endif() +endif() + # Save the Android-specific information in CMakeSystem.cmake. set(CMAKE_SYSTEM_CUSTOM_CODE " set(CMAKE_ANDROID_NDK \"${CMAKE_ANDROID_NDK}\") @@ -260,6 +302,13 @@ set(CMAKE_ANDROID_ARCH \"${CMAKE_ANDROID_ARCH}\") set(CMAKE_ANDROID_ARCH_ABI \"${CMAKE_ANDROID_ARCH_ABI}\") ") +if(CMAKE_ANDROID_NDK) + string(APPEND CMAKE_SYSTEM_CUSTOM_CODE + "set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE \"${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}\")\n" + "set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS \"${CMAKE_ANDROID_NDK_DEPRECATED_HEADERS}\")\n" + ) +endif() + # Select an ARM variant. if(CMAKE_ANDROID_ARCH_ABI MATCHES "^armeabi") if(CMAKE_ANDROID_ARM_MODE) diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake index a327223a8..a434f90ea 100644 --- a/Modules/Platform/Android-Initialize.cmake +++ b/Modules/Platform/Android-Initialize.cmake @@ -20,6 +20,9 @@ endif() if(NOT CMAKE_SYSROOT) if(CMAKE_ANDROID_NDK) set(CMAKE_SYSROOT "${CMAKE_ANDROID_NDK}/platforms/android-${CMAKE_SYSTEM_VERSION}/arch-${CMAKE_ANDROID_ARCH}") + if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) + set(CMAKE_SYSROOT_COMPILE "${CMAKE_ANDROID_NDK}/sysroot") + endif() elseif(CMAKE_ANDROID_STANDALONE_TOOLCHAIN) set(CMAKE_SYSROOT "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot") endif() diff --git a/Modules/Platform/Android/abi-common.cmake b/Modules/Platform/Android/abi-common.cmake index 3b0eb018e..10fb8972d 100644 --- a/Modules/Platform/Android/abi-common.cmake +++ b/Modules/Platform/Android/abi-common.cmake @@ -3,6 +3,10 @@ string(APPEND _ANDROID_ABI_INIT_CFLAGS " -no-canonical-prefixes" ) +if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) + string(APPEND _ANDROID_ABI_INIT_CFLAGS " -D__ANDROID_API__=${CMAKE_SYSTEM_VERSION}") +endif() + if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE AND NOT CMAKE_SYSTEM_VERSION VERSION_LESS 16) set(CMAKE_POSITION_INDEPENDENT_CODE ON) diff --git a/Modules/Platform/Android/ndk-stl-c++_shared.cmake b/Modules/Platform/Android/ndk-stl-c++_shared.cmake index f585adbbe..33894082c 100644 --- a/Modules/Platform/Android/ndk-stl-c++_shared.cmake +++ b/Modules/Platform/Android/ndk-stl-c++_shared.cmake @@ -1,4 +1,5 @@ include(Platform/Android/ndk-stl-c++) macro(__android_stl lang) __android_stl_cxx(${lang} libc++_shared.so) + __android_stl_lib(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${CMAKE_ANDROID_ARCH_ABI}/libandroid_support.a" 0) endmacro() diff --git a/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake b/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake index f13b51750..918ee7090 100644 --- a/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake +++ b/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake @@ -3,3 +3,6 @@ __BlueGeneP_set_dynamic_flags(XL C) + +# -qhalt=e = Halt on error messages (rather than just severe errors) +string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e") diff --git a/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake b/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake index 80c05a1db..cfefb0b33 100644 --- a/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake +++ b/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake @@ -3,3 +3,6 @@ __BlueGeneP_set_dynamic_flags(XL CXX) + +# -qhalt=s = Halt on severe error messages +string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s") diff --git a/Modules/Platform/BlueGeneP-static-XL-C.cmake b/Modules/Platform/BlueGeneP-static-XL-C.cmake index a990b5c58..7d4fc13e2 100644 --- a/Modules/Platform/BlueGeneP-static-XL-C.cmake +++ b/Modules/Platform/BlueGeneP-static-XL-C.cmake @@ -3,3 +3,6 @@ __BlueGeneP_set_static_flags(XL C) + +# -qhalt=e = Halt on error messages (rather than just severe errors) +string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e") diff --git a/Modules/Platform/BlueGeneP-static-XL-CXX.cmake b/Modules/Platform/BlueGeneP-static-XL-CXX.cmake index 116c0bbb8..1df276ef5 100644 --- a/Modules/Platform/BlueGeneP-static-XL-CXX.cmake +++ b/Modules/Platform/BlueGeneP-static-XL-CXX.cmake @@ -3,3 +3,6 @@ __BlueGeneP_set_static_flags(XL CXX) + +# -qhalt=s = Halt on severe error messages +string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s") diff --git a/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake b/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake index f46fa95ee..c51dacb63 100644 --- a/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake +++ b/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake @@ -3,3 +3,6 @@ __BlueGeneQ_setup_dynamic(XL C) + +# -qhalt=e = Halt on error messages (rather than just severe errors) +string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e") diff --git a/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake b/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake index c463379ee..5dbc8363c 100644 --- a/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake +++ b/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake @@ -3,3 +3,6 @@ __BlueGeneQ_setup_dynamic(XL CXX) + +# -qhalt=s = Halt on severe error messages +string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s") diff --git a/Modules/Platform/BlueGeneQ-static-XL-C.cmake b/Modules/Platform/BlueGeneQ-static-XL-C.cmake index 465128fc4..67cd57d80 100644 --- a/Modules/Platform/BlueGeneQ-static-XL-C.cmake +++ b/Modules/Platform/BlueGeneQ-static-XL-C.cmake @@ -3,3 +3,6 @@ __BlueGeneQ_setup_static(XL C) + +# -qhalt=e = Halt on error messages (rather than just severe errors) +string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e") diff --git a/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake b/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake index abd4ebf1a..a171e7fec 100644 --- a/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake +++ b/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake @@ -3,3 +3,6 @@ __BlueGeneQ_setup_static(XL CXX) + +# -qhalt=s = Halt on severe error messages +string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s") diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake index d08dc812f..784c8c676 100644 --- a/Modules/Platform/CYGWIN-GNU.cmake +++ b/Modules/Platform/CYGWIN-GNU.cmake @@ -40,7 +40,7 @@ macro(__cygwin_compiler_gnu lang) set(CMAKE_EXE_EXPORTS_${lang}_FLAG "-Wl,--export-all-symbols") # TODO: Is -Wl,--enable-auto-import now always default? - set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,--enable-auto-import") + string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,--enable-auto-import") set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS}") if(NOT CMAKE_RC_COMPILER_INIT) diff --git a/Modules/Platform/CYGWIN.cmake b/Modules/Platform/CYGWIN.cmake index 22816e77a..9b897bd47 100644 --- a/Modules/Platform/CYGWIN.cmake +++ b/Modules/Platform/CYGWIN.cmake @@ -62,3 +62,13 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a") set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 1) include(Platform/UnixPaths) + +# Windows API on Cygwin +list(APPEND CMAKE_SYSTEM_INCLUDE_PATH + /usr/include/w32api + ) + +# Windows API on Cygwin +list(APPEND CMAKE_SYSTEM_LIBRARY_PATH + /usr/lib/w32api + ) diff --git a/Modules/Platform/Darwin-XL-C.cmake b/Modules/Platform/Darwin-XL-C.cmake index 42e94a9d6..2aeb132d1 100644 --- a/Modules/Platform/Darwin-XL-C.cmake +++ b/Modules/Platform/Darwin-XL-C.cmake @@ -3,3 +3,6 @@ set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle") # Enable shared library versioning. set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-install_name") + +# -qhalt=e = Halt on error messages (rather than just severe errors) +string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e") diff --git a/Modules/Platform/Darwin-XL-CXX.cmake b/Modules/Platform/Darwin-XL-CXX.cmake index 65c76f8b7..f8e1906a8 100644 --- a/Modules/Platform/Darwin-XL-CXX.cmake +++ b/Modules/Platform/Darwin-XL-CXX.cmake @@ -3,3 +3,6 @@ set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "-bundle") # Enable shared library versioning. set(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG "-Wl,-install_name") + +# -qhalt=e = Halt on error messages (rather than just severe errors) +string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e") diff --git a/Modules/Platform/HP-UX-GNU.cmake b/Modules/Platform/HP-UX-GNU.cmake index 7ac804bb4..699c4aa25 100644 --- a/Modules/Platform/HP-UX-GNU.cmake +++ b/Modules/Platform/HP-UX-GNU.cmake @@ -9,7 +9,7 @@ endif() set(__HPUX_COMPILER_GNU 1) macro(__hpux_compiler_gnu lang) - set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,-E,-b,+nodefaultrpath") + string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-E,-b,+nodefaultrpath") set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-E") set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,+b") set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":") diff --git a/Modules/Platform/Linux-GNU.cmake b/Modules/Platform/Linux-GNU.cmake index 6878254ee..ce30a26a5 100644 --- a/Modules/Platform/Linux-GNU.cmake +++ b/Modules/Platform/Linux-GNU.cmake @@ -12,4 +12,5 @@ macro(__linux_compiler_gnu lang) # 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}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp") endmacro() diff --git a/Modules/Platform/Linux-Intel.cmake b/Modules/Platform/Linux-Intel.cmake index 85a07728e..ee9aac26a 100644 --- a/Modules/Platform/Linux-Intel.cmake +++ b/Modules/Platform/Linux-Intel.cmake @@ -30,12 +30,18 @@ macro(__linux_compiler_intel lang) # executables that use dlopen but do not set ENABLE_EXPORTS. set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic") + 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 " "${XIAR} -s ") + 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() if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 12.0) diff --git a/Modules/Platform/Linux-PGI.cmake b/Modules/Platform/Linux-PGI.cmake index a407e436f..db032c292 100644 --- a/Modules/Platform/Linux-PGI.cmake +++ b/Modules/Platform/Linux-PGI.cmake @@ -14,4 +14,5 @@ macro(__linux_compiler_pgi lang) set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "") set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") + set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS " ") endmacro() diff --git a/Modules/Platform/Linux-TinyCC-C.cmake b/Modules/Platform/Linux-TinyCC-C.cmake index f78e708f9..9409d8bc2 100644 --- a/Modules/Platform/Linux-TinyCC-C.cmake +++ b/Modules/Platform/Linux-TinyCC-C.cmake @@ -2,3 +2,4 @@ set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "") set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP "") set(CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "") set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-soname ") +set(CMAKE_EXE_EXPORTS_C_FLAG "-rdynamic ") diff --git a/Modules/Platform/SunOS.cmake b/Modules/Platform/SunOS.cmake index 58398c06f..e19e89a27 100644 --- a/Modules/Platform/SunOS.cmake +++ b/Modules/Platform/SunOS.cmake @@ -9,6 +9,11 @@ endif() include(Platform/UnixPaths) +list(APPEND CMAKE_SYSTEM_PREFIX_PATH + /opt/csw + /opt/openwin + ) + # The Sun linker needs to find transitive shared library dependencies # in the -L path. set(CMAKE_LINK_DEPENDENT_LIBRARY_DIRS 1) diff --git a/Modules/Platform/UnixPaths.cmake b/Modules/Platform/UnixPaths.cmake index b216d03db..5687653cf 100644 --- a/Modules/Platform/UnixPaths.cmake +++ b/Modules/Platform/UnixPaths.cmake @@ -41,35 +41,22 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX) endif() endif() +# Non "standard" but common install prefixes +list(APPEND CMAKE_SYSTEM_PREFIX_PATH + /usr/X11R6 + /usr/pkg + /opt + ) + # List common include file locations not under the common prefixes. list(APPEND CMAKE_SYSTEM_INCLUDE_PATH - # Windows API on Cygwin - /usr/include/w32api - # X11 - /usr/X11R6/include /usr/include/X11 - - # Other - /usr/pkg/include - /opt/csw/include /opt/include - /usr/openwin/include + /usr/include/X11 ) list(APPEND CMAKE_SYSTEM_LIBRARY_PATH - # Windows API on Cygwin - /usr/lib/w32api - # X11 - /usr/X11R6/lib /usr/lib/X11 - - # Other - /usr/pkg/lib - /opt/csw/lib /opt/lib - /usr/openwin/lib - ) - -list(APPEND CMAKE_SYSTEM_PROGRAM_PATH - /usr/pkg/bin + /usr/lib/X11 ) list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES @@ -86,3 +73,4 @@ list(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES # Enable use of lib32 and lib64 search path variants by default. set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE) set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE) +set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS TRUE) diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index 22daa6294..cfb325b9d 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -144,10 +144,24 @@ macro(__windows_compiler_gnu_abi lang) if(CMAKE_GNUtoMS AND NOT CMAKE_GNUtoMS_LIB) # Find MS development environment setup script for this architecture. + # We need to use the MS Librarian tool (lib.exe). + # Find the most recent version available. + + # Query the VS Installer tool for locations of VS 2017 and above. + set(_vs_installer_paths "") + foreach(vs RANGE 15 15 -1) # change the first number to the largest supported version + cmake_host_system_information(RESULT _vs_dir QUERY VS_${vs}_DIR) + if(_vs_dir) + list(APPEND _vs_installer_paths "${_vs_dir}/VC/Auxiliary/Build") + endif() + endforeach(vs) + if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4) find_program(CMAKE_GNUtoMS_VCVARS NAMES vcvars32.bat DOC "Visual Studio vcvars32.bat" PATHS + ${_vs_installer_paths} + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\Setup\\VC;ProductDir]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0\\Setup\\VC;ProductDir]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0\\Setup\\VC;ProductDir]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\Setup\\VC;ProductDir]/bin" @@ -161,6 +175,8 @@ macro(__windows_compiler_gnu_abi lang) find_program(CMAKE_GNUtoMS_VCVARS NAMES vcvars64.bat vcvarsamd64.bat DOC "Visual Studio vcvarsamd64.bat" PATHS + ${_vs_installer_paths} + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\Setup\\VC;ProductDir]/bin/amd64" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0\\Setup\\VC;ProductDir]/bin/amd64" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0\\Setup\\VC;ProductDir]/bin/amd64" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\Setup\\VC;ProductDir]/bin/amd64" @@ -169,6 +185,7 @@ macro(__windows_compiler_gnu_abi lang) ) set(CMAKE_GNUtoMS_ARCH amd64) endif() + unset(_vs_installer_paths) set_property(CACHE CMAKE_GNUtoMS_VCVARS PROPERTY ADVANCED 1) if(CMAKE_GNUtoMS_VCVARS) # Create helper script to run lib.exe from MS environment. diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index e4aca6eb2..cfe6e1c21 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -152,9 +152,9 @@ if(WINCE) foreach(lang C CXX) if(_MSVC_${lang}_ARCHITECTURE_FAMILY STREQUAL "ARM") - set(_PLATFORM_DEFINES_${lang} "${_PLATFORM_DEFINES_${lang}} /D${MSVC_${lang}_ARCHITECTURE_ID}") + string(APPEND _PLATFORM_DEFINES_${lang} " /D${MSVC_${lang}_ARCHITECTURE_ID}") if(MSVC_${lang}_ARCHITECTURE_ID MATCHES "^ARMV([45])I$") - set(_FLAGS_${lang} "${_FLAGS_${lang}} /QRarch${CMAKE_MATCH_1}T") + string(APPEND _FLAGS_${lang} " /QRarch${CMAKE_MATCH_1}T") endif() endif() endforeach() diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index 845fa4b6f..970c2c6d1 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -30,10 +30,18 @@ set(CMAKE_CUDA_LINK_EXECUTABLE unset(_CMAKE_VS_LINK_EXE) unset(_CMAKE_VS_LINK_EXE) +if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") + set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") +else() + set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") +endif() + set(CMAKE_CUDA_DEVICE_LINK_LIBRARY - " -shared -dlink -o -Xcompiler=-Fd,-FS") + " ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o -Xcompiler=-Fd,-FS") set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - " -shared -dlink -o -Xcompiler=-Fd,-FS") + " ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink -o -Xcompiler=-Fd,-FS") + +unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS) string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") diff --git a/Modules/Platform/Windows-PGI-C.cmake b/Modules/Platform/Windows-PGI-C.cmake new file mode 100644 index 000000000..0495b93bd --- /dev/null +++ b/Modules/Platform/Windows-PGI-C.cmake @@ -0,0 +1,2 @@ +include(Platform/Windows-PGI) +__windows_compiler_pgi(C) diff --git a/Modules/Platform/Windows-PGI-Fortran.cmake b/Modules/Platform/Windows-PGI-Fortran.cmake new file mode 100644 index 000000000..2222e3320 --- /dev/null +++ b/Modules/Platform/Windows-PGI-Fortran.cmake @@ -0,0 +1,2 @@ +include(Platform/Windows-PGI) +__windows_compiler_pgi(Fortran) diff --git a/Modules/Platform/Windows-PGI.cmake b/Modules/Platform/Windows-PGI.cmake new file mode 100644 index 000000000..ad77e8ad7 --- /dev/null +++ b/Modules/Platform/Windows-PGI.cmake @@ -0,0 +1,48 @@ +# 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_COMPILER_PGI) + return() +endif() +set(__WINDOWS_COMPILER_PGI 1) + +# PGI on Windows doesn't support parallel compile processes +if(NOT DEFINED CMAKE_JOB_POOL_LINK OR NOT DEFINED CMAKE_JOB_POOL_COMPILE) + set(CMAKE_JOB_POOL_LINK PGITaskPool) + set(CMAKE_JOB_POOL_COMPILE PGITaskPool) + get_property(_pgijp GLOBAL PROPERTY JOB_POOLS) + if(NOT _pgijp MATCHES "PGITaskPool=") + set_property(GLOBAL APPEND PROPERTY JOB_POOLS PGITaskPool=1) + endif() + unset(_pgijp) +endif() + +set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1) +set(CMAKE_LINK_DEF_FILE_FLAG "-def:") +# The link flags for PGI are the raw filename to add a file +# and the UNIX -L syntax to link directories. +set(CMAKE_LINK_LIBRARY_FLAG "") +set(CMAKE_LINK_STARTFILE "pgimain[mx][xpt]+[.]obj") + +# Default to Debug builds, mirroring Windows-MSVC behavior +set(CMAKE_BUILD_TYPE_INIT Debug) + +if(CMAKE_VERBOSE_MAKEFILE) + set(CMAKE_CL_NOLOGO) +else() + set(CMAKE_CL_NOLOGO "/nologo") +endif() + +macro(__windows_compiler_pgi lang) + # Shared library compile and link rules. + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "lib ${CMAKE_CL_NOLOGO} /out: ") + set(CMAKE_${lang}_CREATE_SHARED_LIBRARY " ${CMAKE_START_TEMP_FILE} -Mmakedll -implib: -Xlinker -pdb: -Xlinker -version:. -o ${CMAKE_END_TEMP_FILE}") + set(CMAKE_${lang}_CREATE_SHARED_MODULE "${CMAKE_${lang}_CREATE_SHARED_LIBRARY}") + set(CMAKE_${lang}_LINK_EXECUTABLE " ${CMAKE_START_TEMP_FILE} -implib: -Xlinker -pdb: -Xlinker -version:. -o ${CMAKE_END_TEMP_FILE}") + + if("${lang}" MATCHES "C|CXX") + set(CMAKE_${lang}_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib") + endif() +endmacro() diff --git a/Modules/Platform/Windows-df.cmake b/Modules/Platform/Windows-df.cmake index b31cb11cf..c59be457e 100644 --- a/Modules/Platform/Windows-df.cmake +++ b/Modules/Platform/Windows-df.cmake @@ -30,7 +30,7 @@ set(CMAKE_Fortran_LINK_EXECUTABLE set(CMAKE_CREATE_WIN32_EXE /winapp) set(CMAKE_CREATE_CONSOLE_EXE ) -if(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR CMAKE_GENERATOR MATCHES "Visual Studio 8") +if(CMAKE_GENERATOR MATCHES "Visual Studio 8") set (CMAKE_NO_BUILD_TYPE 1) endif() # does the compiler support pdbtype and is it the newer compiler diff --git a/Modules/TestBigEndian.cmake b/Modules/TestBigEndian.cmake index 085be22d6..cc627d016 100644 --- a/Modules/TestBigEndian.cmake +++ b/Modules/TestBigEndian.cmake @@ -19,21 +19,29 @@ macro(TEST_BIG_ENDIAN VARIABLE) message(STATUS "Check if the system is big endian") message(STATUS "Searching 16 bit integer") + if(CMAKE_C_COMPILER_LOADED) + set(_test_language "C") + elseif(CMAKE_CXX_COMPILER_LOADED) + set(_test_language "CXX") + else() + message(FATAL_ERROR "TEST_BIG_ENDIAN needs either C or CXX language enabled") + endif() + include(CheckTypeSize) - CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT) + CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_SHORT EQUAL 2) message(STATUS "Using unsigned short") set(CMAKE_16BIT_TYPE "unsigned short") else() - CHECK_TYPE_SIZE("unsigned int" CMAKE_SIZEOF_UNSIGNED_INT) + CHECK_TYPE_SIZE("unsigned int" CMAKE_SIZEOF_UNSIGNED_INT LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_INT) message(STATUS "Using unsigned int") set(CMAKE_16BIT_TYPE "unsigned int") else() - CHECK_TYPE_SIZE("unsigned long" CMAKE_SIZEOF_UNSIGNED_LONG) + CHECK_TYPE_SIZE("unsigned long" CMAKE_SIZEOF_UNSIGNED_LONG LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_LONG) message(STATUS "Using unsigned long") set(CMAKE_16BIT_TYPE "unsigned long") @@ -45,17 +53,21 @@ macro(TEST_BIG_ENDIAN VARIABLE) endif() + if(_test_language STREQUAL "CXX") + set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.cpp") + else() + set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c") + endif() configure_file("${CMAKE_ROOT}/Modules/TestEndianess.c.in" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c" + ${_test_file} @ONLY) - file(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c" - TEST_ENDIANESS_FILE_CONTENT) + file(READ ${_test_file} TEST_ENDIANESS_FILE_CONTENT) try_compile(HAVE_${VARIABLE} "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c" + ${_test_file} OUTPUT_VARIABLE OUTPUT COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin" ) diff --git a/Modules/UseEcos.cmake b/Modules/UseEcos.cmake index be1dfd1d3..942bc38bb 100644 --- a/Modules/UseEcos.cmake +++ b/Modules/UseEcos.cmake @@ -184,8 +184,8 @@ macro(ECOS_ADD_EXECUTABLE _exe_NAME ) # when using nmake makefiles, the custom buildtype supresses the default cl.exe flags # and the rules for creating objects are adjusted for gcc set(CMAKE_BUILD_TYPE CUSTOM_ECOS_BUILD) - set(CMAKE_C_COMPILE_OBJECT " -o -c ") - set(CMAKE_CXX_COMPILE_OBJECT " -o -c ") + set(CMAKE_C_COMPILE_OBJECT " -o -c ") + set(CMAKE_CXX_COMPILE_OBJECT " -o -c ") # special link commands for ecos-executables set(CMAKE_CXX_LINK_EXECUTABLE " -o ${_ecos_EXTRA_LIBS} -nostdlib -nostartfiles -L${CMAKE_CURRENT_BINARY_DIR}/ecos/install/lib -Ttarget.ld ${ECOS_LD_MCPU}") set(CMAKE_C_LINK_EXECUTABLE " -o ${_ecos_EXTRA_LIBS} -nostdlib -nostartfiles -L${CMAKE_CURRENT_BINARY_DIR}/ecos/install/lib -Ttarget.ld ${ECOS_LD_MCPU}") diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 93255ae43..11828757b 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -244,21 +244,23 @@ # # :: # -# install_jar_exports(TARGETS jar1 [jar2 ...] -# FILE export_filename -# DESTINATION destination [COMPONENT component]) +# install_jar_exports(TARGETS jars... +# [NAMESPACE ] +# FILE +# DESTINATION [COMPONENT ]) # -# This command installs a target export file export_filename for the named jar -# targets to the given DESTINATION. Its function is similar to that of -# install(EXPORTS). +# This command installs a target export file ```` for the named jar +# targets to the given ``DESTINATION``. Its function is similar to that of +# :command:`install(EXPORTS ...)`. # # :: # -# export_jars(TARGETS jar1 [jar2 ...] -# FILE export_filename) +# export_jars(TARGETS jars... +# [NAMESPACE ] +# FILE ) # -# This command writes a target export file export_filename for the named jar -# targets. Its function is similar to that of export(). +# This command writes a target export file ```` for the named jar +# targets. Its function is similar to that of :command:`export(...)`. # # :: # @@ -415,7 +417,7 @@ endfunction () function(__java_lcat VAR) foreach(_line ${ARGN}) - set(${VAR} "${${VAR}}${_line}\n") + string(APPEND ${VAR} "${_line}\n") endforeach() set(${VAR} "${${VAR}}" PARENT_SCOPE) @@ -424,10 +426,12 @@ endfunction() function(__java_export_jar VAR TARGET PATH) get_target_property(_jarpath ${TARGET} JAR_FILE) get_filename_component(_jarname ${_jarpath} NAME) + set(_target "${_jar_NAMESPACE}${TARGET}") __java_lcat(${VAR} - "# Create imported target ${TARGET}" - "add_custom_target(${TARGET})" - "set_target_properties(${TARGET} PROPERTIES" + "# Create imported target ${_target}" + "add_library(${_target} IMPORTED STATIC)" + "set_target_properties(${_target} PROPERTIES" + " IMPORTED_LOCATION \"${PATH}/${_jarname}\"" " JAR_FILE \"${PATH}/${_jarname}\")" "" ) @@ -1341,7 +1345,7 @@ function(export_jars) # Parse and validate arguments cmake_parse_arguments(_export_jars "" - "FILE" + "FILE;NAMESPACE" "TARGETS" ${ARGN} ) @@ -1351,6 +1355,7 @@ function(export_jars) if (NOT _export_jars_TARGETS) message(SEND_ERROR "export_jars: TARGETS must be specified.") endif() + set(_jar_NAMESPACE "${_export_jars_NAMESPACE}") # Set content of generated exports file string(REPLACE ";" " " __targets__ "${_export_jars_TARGETS}") @@ -1373,7 +1378,7 @@ function(install_jar_exports) # Parse and validate arguments cmake_parse_arguments(_install_jar_exports "" - "FILE;DESTINATION;COMPONENT" + "FILE;DESTINATION;COMPONENT;NAMESPACE" "TARGETS" ${ARGN} ) @@ -1386,6 +1391,7 @@ function(install_jar_exports) if (NOT _install_jar_exports_TARGETS) message(SEND_ERROR "install_jar_exports: TARGETS must be specified.") endif() + set(_jar_NAMESPACE "${_install_jar_exports_NAMESPACE}") if (_install_jar_exports_COMPONENT) set (_COMPONENT COMPONENT ${_install_jar_exports_COMPONENT}) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 277f4ca28..bfe1a6f75 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -326,6 +326,9 @@ macro(SWIG_ADD_LIBRARY name) if (APPLE) set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".bundle") endif () + else() + # assume empty prefix because we expect the module to be dynamically loaded + set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "") endif () endmacro() diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake index 0b16aa421..e7f991249 100644 --- a/Modules/WriteCompilerDetectionHeader.cmake +++ b/Modules/WriteCompilerDetectionHeader.cmake @@ -447,7 +447,7 @@ function(write_compiler_detection_header endif() if(NOT _WCD_ALLOW_UNKNOWN_COMPILER_VERSIONS) - set(${compiler_file_content} "${${compiler_file_content}} + string(APPEND ${compiler_file_content} " # if !(${_cmake_oldestSupported_${compiler}}) # error Unsupported compiler version # endif\n") @@ -462,7 +462,7 @@ function(write_compiler_detection_header set(MACRO_HEX) endif() string(CONFIGURE "${_compiler_id_version_compute_${compiler}}" VERSION_BLOCK @ONLY) - set(${compiler_file_content} "${${compiler_file_content}}${VERSION_BLOCK}\n") + string(APPEND ${compiler_file_content} "${VERSION_BLOCK}\n") set(PREFIX) set(MACRO_DEC) set(MACRO_HEX) @@ -478,7 +478,7 @@ function(write_compiler_detection_header set(_define_item "\n# define ${prefix_arg}_${feature_PP} 0\n") set(_define_item "\n# if ${_cmake_feature_test_${compiler}_${feature}}\n# define ${prefix_arg}_${feature_PP} 1\n# else${_define_item}# endif\n") endif() - set(${compiler_file_content} "${${compiler_file_content}}${_define_item}") + string(APPEND ${compiler_file_content} "${_define_item}") endforeach() endforeach() if(pp_if STREQUAL "elif") @@ -503,10 +503,19 @@ function(write_compiler_detection_header if (feature STREQUAL cxx_static_assert) set(def_value "${prefix_arg}_STATIC_ASSERT(X)") set(def_value_msg "${prefix_arg}_STATIC_ASSERT_MSG(X, MSG)") - set(static_assert_struct "template struct ${prefix_arg}StaticAssert;\ntemplate<> struct ${prefix_arg}StaticAssert{};\n") - set(def_standard "# define ${def_value} static_assert(X, #X)\n# define ${def_value_msg} static_assert(X, MSG)") - set(def_alternative "${static_assert_struct}# define ${def_value} sizeof(${prefix_arg}StaticAssert)\n# define ${def_value_msg} sizeof(${prefix_arg}StaticAssert)") - string(APPEND file_content "# if defined(${def_name}) && ${def_name}\n${def_standard}\n# else\n${def_alternative}\n# endif\n\n") + set(def_fallback "enum { ${prefix_arg}_STATIC_ASSERT_JOIN(${prefix_arg}StaticAssertEnum, __LINE__) = sizeof(${prefix_arg}StaticAssert) }") + string(APPEND file_content "# if defined(${def_name}) && ${def_name} +# define ${def_value} static_assert(X, #X) +# define ${def_value_msg} static_assert(X, MSG) +# else +# define ${prefix_arg}_STATIC_ASSERT_JOIN(X, Y) ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y) +# define ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y) X##Y +template struct ${prefix_arg}StaticAssert; +template<> struct ${prefix_arg}StaticAssert{}; +# define ${def_value} ${def_fallback} +# define ${def_value_msg} ${def_fallback} +# endif +\n") endif() if (feature STREQUAL cxx_alignas) set(def_value "${prefix_arg}_ALIGNAS(X)") diff --git a/README.rst b/README.rst index 4188ea04c..d5acd4a7c 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,13 @@ Building CMake Supported Platforms ------------------- -MS Windows, Mac OS X, Linux, FreeBSD, Solaris, HP-UX, IRIX, BeOS, QNX +* Microsoft Windows +* Apple macOS +* Linux +* FreeBSD +* OpenBSD +* Solaris +* HP-UX Other UNIX-like operating systems may work too out of the box, if not it should not be a major problem to port CMake to this platform. diff --git a/Source/.gitattributes b/Source/.gitattributes index 1cec8a338..0f829a368 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -1,21 +1,2 @@ -/cmCommandArgumentLexer.cxx generated -/cmCommandArgumentLexer.h generated -/cmCommandArgumentParser.cxx generated -/cmCommandArgumentParserTokens.h generated -/cmDependsJavaLexer.cxx generated -/cmDependsJavaLexer.h generated -/cmDependsJavaParser.cxx generated -/cmDependsJavaParserTokens.h generated -/cmExprLexer.cxx generated -/cmExprLexer.h generated -/cmExprParser.cxx generated -/cmExprParserTokens.h generated -/cmFortranLexer.cxx generated -/cmFortranLexer.h generated -/cmFortranParser.cxx generated -/cmFortranParserTokens.h generated -/cmListFileLexer.c generated - # Do not format third-party sources. -/bindexplib.* -format.clang-format /kwsys/** -format.clang-format diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 2835ee65a..40403ca25 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -78,6 +78,7 @@ configure_file( include_directories( "${CMake_BINARY_DIR}/Source" "${CMake_SOURCE_DIR}/Source" + "${CMake_SOURCE_DIR}/Source/LexerParser" ${CMAKE_ZLIB_INCLUDES} ${CMAKE_EXPAT_INCLUDES} ${CMAKE_TAR_INCLUDES} @@ -88,61 +89,6 @@ include_directories( # let cmake know it is supposed to use it add_definitions(-DCMAKE_BUILD_WITH_CMAKE) -option(CMAKE_REGENERATE_YACCLEX - "Regenerate YACC and LEXX files" OFF) -mark_as_advanced(CMAKE_REGENERATE_YACCLEX) -if(CMAKE_REGENERATE_YACCLEX) - set(parsersLexers cmFortran cmCommandArgument cmExpr) - find_program(YACC_EXECUTABLE - NAMES yacc bison - PATHS /usr/bin - DOC "Yacc or Bison executable") - find_program(FLEX_EXECUTABLE - NAMES flex - PATHS /usr/bin - DOC "Flex executable") - mark_as_advanced(YACC_EXECUTABLE FLEX_EXECUTABLE) - if(YACC_EXECUTABLE) - set(BISON_FLAGS) - if(YACC_EXECUTABLE MATCHES "bison") - set(BISON_FLAGS "--yacc") - endif() - set(yacc_files) - foreach(name ${parsersLexers}) - set(src "${CMAKE_CURRENT_SOURCE_DIR}/${name}Parser.y") - set(dst "${CMAKE_CURRENT_BINARY_DIR}/${name}Parser.cxx") - set(hdr "${CMAKE_CURRENT_BINARY_DIR}/${name}ParserTokens.h") - add_custom_command( - OUTPUT "${dst}" - DEPENDS "${src}" - COMMAND - ${YACC_EXECUTABLE} - --name-prefix=${name}_yy --defines=${hdr} -o${dst} ${src} - ) - set(yacc_files ${yacc_files} "${dst}") - endforeach() - add_custom_target(RerunYacc DEPENDS ${yacc_files}) - endif() - if(FLEX_EXECUTABLE) - set(lex_files) - foreach(name ${parsersLexers}) - set(src "${CMAKE_CURRENT_SOURCE_DIR}/${name}Lexer.in.l") - set(dst "${CMAKE_CURRENT_BINARY_DIR}/${name}Lexer.cxx") - set(hdr "${CMAKE_CURRENT_BINARY_DIR}/${name}Lexer.h") - add_custom_command( - OUTPUT "${dst}" - DEPENDS "${src}" - COMMAND - ${FLEX_EXECUTABLE} - --prefix=${name}_yy --header-file=${hdr} -o${dst} ${src} - ) - set(lex_files ${lex_files} "${dst}") - endforeach() - add_custom_target(RerunLex DEPENDS ${lex_files}) - endif() - -endif() - # Check if we can build the ELF parser. if(CMAKE_USE_ELF_PARSER) set(ELF_SRCS cmELF.h cmELF.cxx) @@ -157,14 +103,40 @@ endif() # Sources for CMakeLib # set(SRCS + # Lexers/Parsers + LexerParser/cmCommandArgumentLexer.cxx + LexerParser/cmCommandArgumentLexer.h + LexerParser/cmCommandArgumentLexer.in.l + LexerParser/cmCommandArgumentParser.cxx + LexerParser/cmCommandArgumentParserTokens.h + LexerParser/cmCommandArgumentParser.y + LexerParser/cmDependsJavaLexer.cxx + LexerParser/cmDependsJavaLexer.h + LexerParser/cmDependsJavaLexer.in.l + LexerParser/cmDependsJavaParser.cxx + LexerParser/cmDependsJavaParserTokens.h + LexerParser/cmDependsJavaParser.y + LexerParser/cmExprLexer.cxx + LexerParser/cmExprLexer.h + LexerParser/cmExprLexer.in.l + LexerParser/cmExprParser.cxx + LexerParser/cmExprParserTokens.h + LexerParser/cmExprParser.y + LexerParser/cmFortranLexer.cxx + LexerParser/cmFortranLexer.h + LexerParser/cmFortranLexer.in.l + LexerParser/cmFortranParser.cxx + LexerParser/cmFortranParserTokens.h + LexerParser/cmFortranParser.y + LexerParser/cmListFileLexer.c + LexerParser/cmListFileLexer.in.l + cmArchiveWrite.cxx cmBase32.cxx cmCacheManager.cxx cmCacheManager.h cmCLocaleEnvironmentScope.h cmCLocaleEnvironmentScope.cxx - cmCommandArgumentLexer.cxx - cmCommandArgumentParser.cxx cmCommandArgumentParserHelper.cxx cmCommonTargetGenerator.cxx cmCommonTargetGenerator.h @@ -196,8 +168,6 @@ set(SRCS cmDependsFortran.h cmDependsJava.cxx cmDependsJava.h - cmDependsJavaLexer.cxx - cmDependsJavaParser.cxx cmDependsJavaParserHelper.cxx cmDependsJavaParserHelper.h cmDocumentation.cxx @@ -206,8 +176,6 @@ set(SRCS cmDynamicLoader.cxx cmDynamicLoader.h ${ELF_SRCS} - cmExprLexer.cxx - cmExprParser.cxx cmExprParserHelper.cxx cmExportBuildAndroidMKGenerator.h cmExportBuildAndroidMKGenerator.cxx @@ -247,10 +215,6 @@ set(SRCS cmFilePathChecksum.h cmFileTimeComparison.cxx cmFileTimeComparison.h - cmFortranLexer.cxx - cmFortranLexer.h - cmFortranParser.cxx - cmFortranParser.h cmFortranParserImpl.cxx cmGeneratedFileStream.cxx cmGeneratorExpressionContext.cxx @@ -302,7 +266,6 @@ set(SRCS cmLinkLineDeviceComputer.h cmListFileCache.cxx cmListFileCache.h - cmListFileLexer.c cmLocalCommonGenerator.cxx cmLocalCommonGenerator.h cmLocalGenerator.cxx @@ -344,6 +307,8 @@ set(SRCS cmPropertyDefinitionMap.h cmPropertyMap.cxx cmPropertyMap.h + cmQtAutoGeneratorCommon.cxx + cmQtAutoGeneratorCommon.h cmQtAutoGeneratorInitializer.cxx cmQtAutoGeneratorInitializer.h cmQtAutoGenerators.cxx @@ -381,6 +346,8 @@ set(SRCS cmVariableWatch.h cmVersion.cxx cmVersion.h + cmWorkingDirectory.cxx + cmWorkingDirectory.h cmXMLParser.cxx cmXMLParser.h cmXMLSafe.cxx @@ -440,6 +407,8 @@ set(SRCS cmCreateTestSourceList.h cmDefinePropertyCommand.cxx cmDefinePropertyCommand.h + cmDisallowedCommand.cxx + cmDisallowedCommand.h cmEnableLanguageCommand.cxx cmEnableLanguageCommand.h cmEnableTestingCommand.cxx @@ -637,6 +606,7 @@ if(APPLE) set(SRCS ${SRCS} cmXCodeObject.cxx cmXCode21Object.cxx + cmXCodeScheme.cxx cmGlobalXCodeGenerator.cxx cmGlobalXCodeGenerator.h cmLocalXCodeGenerator.cxx @@ -881,6 +851,12 @@ set(CTEST_SRCS cmCTest.cxx add_library(CTestLib ${CTEST_SRCS}) target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES} ${CMAKE_XMLRPC_LIBRARIES}) +# +# CPack +# +include_directories( + "${CMake_SOURCE_DIR}/Source/CPack" + ) # # Sources for CPack # @@ -891,10 +867,6 @@ set(CPACK_SRCS CPack/cmCPackGenerator.cxx CPack/cmCPackLog.cxx CPack/cmCPackNSISGenerator.cxx - CPack/IFW/cmCPackIFWPackage.cxx - CPack/IFW/cmCPackIFWInstaller.cxx - CPack/IFW/cmCPackIFWRepository.cxx - CPack/IFW/cmCPackIFWGenerator.cxx CPack/cmCPackSTGZGenerator.cxx CPack/cmCPackTGZGenerator.cxx CPack/cmCPackTXZGenerator.cxx @@ -903,6 +875,19 @@ set(CPACK_SRCS CPack/cmCPackZIPGenerator.cxx CPack/cmCPack7zGenerator.cxx ) +# CPack IFW generator +set(CPACK_SRCS ${CPACK_SRCS} + CPack/IFW/cmCPackIFWCommon.cxx + CPack/IFW/cmCPackIFWCommon.h + CPack/IFW/cmCPackIFWGenerator.cxx + CPack/IFW/cmCPackIFWGenerator.h + CPack/IFW/cmCPackIFWInstaller.cxx + CPack/IFW/cmCPackIFWInstaller.h + CPack/IFW/cmCPackIFWPackage.cxx + CPack/IFW/cmCPackIFWPackage.h + CPack/IFW/cmCPackIFWRepository.cxx + CPack/IFW/cmCPackIFWRepository.h + ) if(CYGWIN) set(CPACK_SRCS ${CPACK_SRCS} diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 65e7b5dc0..0f5201b40 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 8) +set(CMake_VERSION_MINOR 9) set(CMake_VERSION_PATCH 0) #set(CMake_VERSION_RC 0) diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx new file mode 100644 index 000000000..e8f05bd50 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -0,0 +1,137 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCPackIFWCommon.h" + +#include "cmCPackGenerator.h" +#include "cmCPackIFWGenerator.h" +#include "cmCPackLog.h" // IWYU pragma: keep +#include "cmSystemTools.h" +#include "cmTimestamp.h" +#include "cmVersionConfig.h" +#include "cmXMLWriter.h" + +#include +#include +#include + +cmCPackIFWCommon::cmCPackIFWCommon() + : Generator(CM_NULLPTR) +{ +} + +const char* cmCPackIFWCommon::GetOption(const std::string& op) const +{ + return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op) + : CM_NULLPTR; +} + +bool cmCPackIFWCommon::IsOn(const std::string& op) const +{ + return this->Generator ? this->Generator->cmCPackGenerator::IsOn(op) : false; +} + +bool cmCPackIFWCommon::IsSetToOff(const std::string& op) const +{ + return this->Generator ? this->Generator->cmCPackGenerator::IsSetToOff(op) + : false; +} + +bool cmCPackIFWCommon::IsSetToEmpty(const std::string& op) const +{ + return this->Generator ? this->Generator->cmCPackGenerator::IsSetToEmpty(op) + : false; +} + +bool cmCPackIFWCommon::IsVersionLess(const char* version) +{ + if (!this->Generator) { + return false; + } + + return cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->Generator->FrameworkVersion.data(), version); +} + +bool cmCPackIFWCommon::IsVersionGreater(const char* version) +{ + if (!this->Generator) { + return false; + } + + return cmSystemTools::VersionCompare( + cmSystemTools::OP_GREATER, this->Generator->FrameworkVersion.data(), + version); +} + +bool cmCPackIFWCommon::IsVersionEqual(const char* version) +{ + if (!this->Generator) { + return false; + } + + return cmSystemTools::VersionCompare( + cmSystemTools::OP_EQUAL, this->Generator->FrameworkVersion.data(), + version); +} + +void cmCPackIFWCommon::ExpandListArgument( + const std::string& arg, std::map& argsOut) +{ + std::vector args; + cmSystemTools::ExpandListArgument(arg, args, false); + if (args.empty()) { + return; + } + + std::size_t i = 0; + std::size_t c = args.size(); + if (c % 2) { + argsOut[""] = args[i]; + ++i; + } + + --c; + for (; i < c; i += 2) { + argsOut[args[i]] = args[i + 1]; + } +} + +void cmCPackIFWCommon::ExpandListArgument( + const std::string& arg, std::multimap& argsOut) +{ + std::vector args; + cmSystemTools::ExpandListArgument(arg, args, false); + if (args.empty()) { + return; + } + + std::size_t i = 0; + std::size_t c = args.size(); + if (c % 2) { + argsOut.insert(std::pair("", args[i])); + ++i; + } + + --c; + for (; i < c; i += 2) { + argsOut.insert(std::pair(args[i], args[i + 1])); + } +} + +void cmCPackIFWCommon::WriteGeneratedByToStrim(cmXMLWriter& xout) +{ + if (!this->Generator) { + return; + } + + std::ostringstream comment; + comment << "Generated by CPack " << CMake_VERSION << " IFW generator " + << "for QtIFW "; + if (this->IsVersionEqual("1.9.9")) { + comment << "less 2.0"; + } else { + comment << this->Generator->FrameworkVersion; + } + comment << " tools at " << cmTimestamp().CurrentTime("", true); + xout.Comment(comment.str().c_str()); +} diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h new file mode 100644 index 000000000..354d84966 --- /dev/null +++ b/Source/CPack/IFW/cmCPackIFWCommon.h @@ -0,0 +1,81 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCPackIFWCommon_h +#define cmCPackIFWCommon_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include + +class cmCPackIFWGenerator; +class cmXMLWriter; + +/** \class cmCPackIFWCommon + * \brief A base class for CPack IFW generator implementation subclasses + */ +class cmCPackIFWCommon +{ +public: + // Constructor + + /** + * Construct Part + */ + cmCPackIFWCommon(); + +public: + // Internal implementation + + const char* GetOption(const std::string& op) const; + bool IsOn(const std::string& op) const; + bool IsSetToOff(const std::string& op) const; + bool IsSetToEmpty(const std::string& op) const; + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionLess(const char* version); + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionGreater(const char* version); + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionEqual(const char* version); + + /** 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 + * default value with an empty key. + * Any values with the same keys will be permanently overwritten. + */ + static void ExpandListArgument(const std::string& arg, + std::map& argsOut); + + /** Expand the list argument containing the multimap of the key-value pairs. + * If the number of elements is odd, then the first value is used as the + * default value with an empty key. + */ + static void ExpandListArgument( + const std::string& arg, std::multimap& argsOut); + + cmCPackIFWGenerator* Generator; + +protected: + void WriteGeneratedByToStrim(cmXMLWriter& xout); +}; + +#define cmCPackIFWLogger(logType, msg) \ + do { \ + std::ostringstream cmCPackLog_msg; \ + cmCPackLog_msg << msg; \ + if (Generator) { \ + Generator->Logger->Log(cmCPackLog::LOG_##logType, __FILE__, __LINE__, \ + cmCPackLog_msg.str().c_str()); \ + } \ + } while (false) + +#endif // cmCPackIFWCommon_h diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index ee46d869c..226ea0a29 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -2,94 +2,76 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackIFWGenerator.h" -#include "CPack/cmCPackComponentGroup.h" -#include "CPack/cmCPackGenerator.h" -#include "CPack/cmCPackLog.h" +#include "cmCPackComponentGroup.h" +#include "cmCPackGenerator.h" +#include "cmCPackIFWCommon.h" #include "cmCPackIFWInstaller.h" #include "cmCPackIFWPackage.h" #include "cmCPackIFWRepository.h" +#include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" -#include "cmTimestamp.h" -#include "cmVersionConfig.h" -#include "cmXMLWriter.h" #include #include cmCPackIFWGenerator::cmCPackIFWGenerator() { + this->Generator = this; } cmCPackIFWGenerator::~cmCPackIFWGenerator() { } -bool cmCPackIFWGenerator::IsVersionLess(const char* version) -{ - return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, - FrameworkVersion.data(), version); -} - -bool cmCPackIFWGenerator::IsVersionGreater(const char* version) -{ - return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, - FrameworkVersion.data(), version); -} - -bool cmCPackIFWGenerator::IsVersionEqual(const char* version) -{ - return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, - FrameworkVersion.data(), version); -} - int cmCPackIFWGenerator::PackageFiles() { - cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl); + cmCPackIFWLogger(OUTPUT, "- Configuration" << std::endl); // Installer configuragion - Installer.GenerateInstallerFile(); + this->Installer.GenerateInstallerFile(); // Packages configuration - Installer.GeneratePackageFiles(); + this->Installer.GeneratePackageFiles(); std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); std::string ifwTmpFile = ifwTLD; ifwTmpFile += "/IFWOutput.log"; // Run repogen - if (!Installer.RemoteRepositories.empty()) { - std::string ifwCmd = RepoGen; + if (!this->Installer.RemoteRepositories.empty()) { + std::string ifwCmd = this->RepoGen; - if (IsVersionLess("2.0.0")) { + if (this->IsVersionLess("2.0.0")) { ifwCmd += " -c " + this->toplevel + "/config/config.xml"; } ifwCmd += " -p " + this->toplevel + "/packages"; - if (!PkgsDirsVector.empty()) { - for (std::vector::iterator it = PkgsDirsVector.begin(); - it != PkgsDirsVector.end(); ++it) { + if (!this->PkgsDirsVector.empty()) { + for (std::vector::iterator it = + this->PkgsDirsVector.begin(); + it != this->PkgsDirsVector.end(); ++it) { ifwCmd += " -p " + *it; } } - if (!OnlineOnly && !DownloadedPackages.empty()) { + if (!this->OnlineOnly && !this->DownloadedPackages.empty()) { ifwCmd += " -i "; - std::set::iterator it = DownloadedPackages.begin(); + std::set::iterator it = + this->DownloadedPackages.begin(); ifwCmd += (*it)->Name; ++it; - while (it != DownloadedPackages.end()) { + while (it != this->DownloadedPackages.end()) { ifwCmd += "," + (*it)->Name; ++it; } } ifwCmd += " " + this->toplevel + "/repository"; - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl); + cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl); std::string output; int retVal = 1; - cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate repository" - << std::endl); + cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl); bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output, &output, &retVal, CM_NULLPTR, this->GeneratorVerbose, 0); @@ -98,36 +80,39 @@ int cmCPackIFWGenerator::PackageFiles() ofs << "# Run command: " << ifwCmd << std::endl << "# Output:" << std::endl << output << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " - << ifwCmd << std::endl - << "Please check " << ifwTmpFile << " for errors" - << std::endl); + cmCPackIFWLogger(ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); return 0; } - if (!Repository.RepositoryUpdate.empty() && - !Repository.PatchUpdatesXml()) { - cmCPackLogger(cmCPackLog::LOG_WARNING, "Problem patch IFW \"Updates\" " - << "file: " << this->toplevel + "/repository/Updates.xml" - << std::endl); + if (!this->Repository.RepositoryUpdate.empty() && + !this->Repository.PatchUpdatesXml()) { + cmCPackIFWLogger(WARNING, "Problem patch IFW \"Updates\" " + << "file: " + << this->toplevel + "/repository/Updates.xml" + << std::endl); } - cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- repository: " - << this->toplevel << "/repository generated" << std::endl); + cmCPackIFWLogger(OUTPUT, "- repository: " << this->toplevel + << "/repository generated" + << std::endl); } // Run binary creator { - std::string ifwCmd = BinCreator; + std::string ifwCmd = this->BinCreator; ifwCmd += " -c " + this->toplevel + "/config/config.xml"; - if (!Installer.Resources.empty()) { + if (!this->Installer.Resources.empty()) { ifwCmd += " -r "; - std::vector::iterator it = Installer.Resources.begin(); + std::vector::iterator it = + this->Installer.Resources.begin(); std::string path = this->toplevel + "/resources/"; ifwCmd += path + *it; ++it; - while (it != Installer.Resources.end()) { + while (it != this->Installer.Resources.end()) { ifwCmd += "," + path + *it; ++it; } @@ -135,52 +120,55 @@ int cmCPackIFWGenerator::PackageFiles() ifwCmd += " -p " + this->toplevel + "/packages"; - if (!PkgsDirsVector.empty()) { - for (std::vector::iterator it = PkgsDirsVector.begin(); - it != PkgsDirsVector.end(); ++it) { + if (!this->PkgsDirsVector.empty()) { + for (std::vector::iterator it = + this->PkgsDirsVector.begin(); + it != this->PkgsDirsVector.end(); ++it) { ifwCmd += " -p " + *it; } } - if (OnlineOnly) { + if (this->OnlineOnly) { ifwCmd += " --online-only"; - } else if (!DownloadedPackages.empty() && - !Installer.RemoteRepositories.empty()) { + } else if (!this->DownloadedPackages.empty() && + !this->Installer.RemoteRepositories.empty()) { ifwCmd += " -e "; - std::set::iterator it = DownloadedPackages.begin(); + std::set::iterator it = + this->DownloadedPackages.begin(); ifwCmd += (*it)->Name; ++it; - while (it != DownloadedPackages.end()) { + while (it != this->DownloadedPackages.end()) { ifwCmd += "," + (*it)->Name; ++it; } - } else if (!DependentPackages.empty()) { + } else if (!this->DependentPackages.empty()) { ifwCmd += " -i "; // Binary - std::set::iterator bit = BinaryPackages.begin(); - while (bit != BinaryPackages.end()) { + std::set::iterator bit = + this->BinaryPackages.begin(); + while (bit != this->BinaryPackages.end()) { ifwCmd += (*bit)->Name + ","; ++bit; } // Depend - DependenceMap::iterator it = DependentPackages.begin(); + DependenceMap::iterator it = this->DependentPackages.begin(); ifwCmd += it->second.Name; ++it; - while (it != DependentPackages.end()) { + while (it != this->DependentPackages.end()) { ifwCmd += "," + it->second.Name; ++it; } } // TODO: set correct name for multipackages if (!this->packageFileNames.empty()) { - ifwCmd += " " + packageFileNames[0]; + ifwCmd += " " + this->packageFileNames[0]; } else { ifwCmd += " installer"; } - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl); + cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl); std::string output; int retVal = 1; - cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl); + cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl); bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output, &output, &retVal, CM_NULLPTR, this->GeneratorVerbose, 0); @@ -189,10 +177,10 @@ int cmCPackIFWGenerator::PackageFiles() ofs << "# Run command: " << ifwCmd << std::endl << "# Output:" << std::endl << output << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: " - << ifwCmd << std::endl - << "Please check " << ifwTmpFile << " for errors" - << std::endl); + cmCPackIFWLogger(ERROR, "Problem running IFW command: " + << ifwCmd << std::endl + << "Please check " << ifwTmpFile << " for errors" + << std::endl); return 0; } } @@ -202,12 +190,12 @@ int cmCPackIFWGenerator::PackageFiles() const char* cmCPackIFWGenerator::GetPackagingInstallPrefix() { - const char* defPrefix = cmCPackGenerator::GetPackagingInstallPrefix(); + const char* defPrefix = this->cmCPackGenerator::GetPackagingInstallPrefix(); std::string tmpPref = defPrefix ? defPrefix : ""; if (this->Components.empty()) { - tmpPref += "packages/" + GetRootPackageName() + "/data"; + tmpPref += "packages/" + this->GetRootPackageName() + "/data"; } this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str()); @@ -217,7 +205,7 @@ const char* cmCPackIFWGenerator::GetPackagingInstallPrefix() const char* cmCPackIFWGenerator::GetOutputExtension() { - return ExecutableSuffix.c_str(); + return this->ExecutableSuffix.c_str(); } int cmCPackIFWGenerator::InitializeInternal() @@ -237,16 +225,15 @@ int cmCPackIFWGenerator::InitializeInternal() const char* BinCreatorStr = this->GetOption(BinCreatorOpt); if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) { - BinCreator = ""; + this->BinCreator = ""; } else { - BinCreator = BinCreatorStr; + this->BinCreator = BinCreatorStr; } - if (BinCreator.empty()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find QtIFW compiler \"binarycreator\": " - "likely it is not installed, or not in your PATH" - << std::endl); + if (this->BinCreator.empty()) { + cmCPackIFWLogger(ERROR, "Cannot find QtIFW compiler \"binarycreator\": " + "likely it is not installed, or not in your PATH" + << std::endl); return 0; } @@ -254,39 +241,40 @@ int cmCPackIFWGenerator::InitializeInternal() const char* RepoGenStr = this->GetOption(RepoGenOpt); if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) { - RepoGen = ""; + this->RepoGen = ""; } else { - RepoGen = RepoGenStr; + this->RepoGen = RepoGenStr; } // Framework version if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) { - FrameworkVersion = FrameworkVersionSrt; + this->FrameworkVersion = FrameworkVersionSrt; } else { - FrameworkVersion = "1.9.9"; + this->FrameworkVersion = "1.9.9"; } // Variables that Change Behavior // Resolve duplicate names - ResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES"); + this->ResolveDuplicateNames = + this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES"); // Additional packages dirs - PkgsDirsVector.clear(); + this->PkgsDirsVector.clear(); if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { - cmSystemTools::ExpandListArgument(dirs, PkgsDirsVector); + cmSystemTools::ExpandListArgument(dirs, this->PkgsDirsVector); } // Installer - Installer.Generator = this; - Installer.ConfigureFromOptions(); + this->Installer.Generator = this; + this->Installer.ConfigureFromOptions(); // Repository - Repository.Generator = this; - Repository.Name = "Unspecified"; + this->Repository.Generator = this; + this->Repository.Name = "Unspecified"; if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) { - Repository.Url = site; - Installer.RemoteRepositories.push_back(&Repository); + this->Repository.Url = site; + this->Installer.RemoteRepositories.push_back(&this->Repository); } // Repositories @@ -295,38 +283,38 @@ int cmCPackIFWGenerator::InitializeInternal() cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector); for (std::vector::iterator rit = RepoAllVector.begin(); rit != RepoAllVector.end(); ++rit) { - GetRepository(*rit); + this->GetRepository(*rit); } } if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { - OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll); + this->OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll); } else if (const char* cpackDownloadAll = this->GetOption("CPACK_DOWNLOAD_ALL")) { - OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll); + this->OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll); } else { - OnlineOnly = false; + this->OnlineOnly = false; } - if (!Installer.RemoteRepositories.empty() && RepoGen.empty()) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot find QtIFW repository generator \"repogen\": " - "likely it is not installed, or not in your PATH" - << std::endl); + if (!this->Installer.RemoteRepositories.empty() && this->RepoGen.empty()) { + cmCPackIFWLogger(ERROR, + "Cannot find QtIFW repository generator \"repogen\": " + "likely it is not installed, or not in your PATH" + << std::endl); return 0; } // Executable suffix if (const char* optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) { - ExecutableSuffix = optExeSuffix; - if (ExecutableSuffix.empty()) { + this->ExecutableSuffix = optExeSuffix; + if (this->ExecutableSuffix.empty()) { std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME")); if (sysName == "Linux") { - ExecutableSuffix = ".run"; + this->ExecutableSuffix = ".run"; } } } else { - ExecutableSuffix = cmCPackGenerator::GetOutputExtension(); + this->ExecutableSuffix = this->cmCPackGenerator::GetOutputExtension(); } return this->Superclass::InitializeInternal(); @@ -338,52 +326,53 @@ std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix( const std::string prefix = "packages/"; const std::string suffix = "/data"; - if (componentPackageMethod == ONE_PACKAGE) { - return std::string(prefix + GetRootPackageName() + suffix); + if (this->componentPackageMethod == this->ONE_PACKAGE) { + return std::string(prefix + this->GetRootPackageName() + suffix); } - return prefix + GetComponentPackageName(&Components[componentName]) + suffix; + return prefix + + this->GetComponentPackageName(&this->Components[componentName]) + suffix; } cmCPackComponent* cmCPackIFWGenerator::GetComponent( const std::string& projectName, const std::string& componentName) { - ComponentsMap::iterator cit = Components.find(componentName); - if (cit != Components.end()) { + ComponentsMap::iterator cit = this->Components.find(componentName); + if (cit != this->Components.end()) { return &(cit->second); } cmCPackComponent* component = - cmCPackGenerator::GetComponent(projectName, componentName); + this->cmCPackGenerator::GetComponent(projectName, componentName); if (!component) { return component; } - std::string name = GetComponentPackageName(component); - PackagesMap::iterator pit = Packages.find(name); - if (pit != Packages.end()) { + std::string name = this->GetComponentPackageName(component); + PackagesMap::iterator pit = this->Packages.find(name); + if (pit != this->Packages.end()) { return component; } - cmCPackIFWPackage* package = &Packages[name]; + cmCPackIFWPackage* package = &this->Packages[name]; package->Name = name; package->Generator = this; if (package->ConfigureFromComponent(component)) { - package->Installer = &Installer; - Installer.Packages.insert( + package->Installer = &this->Installer; + this->Installer.Packages.insert( std::pair(name, package)); - ComponentPackages.insert( + this->ComponentPackages.insert( std::pair(component, package)); if (component->IsDownloaded) { - DownloadedPackages.insert(package); + this->DownloadedPackages.insert(package); } else { - BinaryPackages.insert(package); + this->BinaryPackages.insert(package); } } else { - Packages.erase(name); - cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \"" - << name << "\" for component \"" << component->Name << "\"" - << std::endl); + this->Packages.erase(name); + cmCPackIFWLogger(ERROR, "Cannot configure package \"" + << name << "\" for component \"" << component->Name + << "\"" << std::endl); } return component; @@ -393,32 +382,32 @@ cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup( const std::string& projectName, const std::string& groupName) { cmCPackComponentGroup* group = - cmCPackGenerator::GetComponentGroup(projectName, groupName); + this->cmCPackGenerator::GetComponentGroup(projectName, groupName); if (!group) { return group; } - std::string name = GetGroupPackageName(group); - PackagesMap::iterator pit = Packages.find(name); - if (pit != Packages.end()) { + std::string name = this->GetGroupPackageName(group); + PackagesMap::iterator pit = this->Packages.find(name); + if (pit != this->Packages.end()) { return group; } - cmCPackIFWPackage* package = &Packages[name]; + cmCPackIFWPackage* package = &this->Packages[name]; package->Name = name; package->Generator = this; if (package->ConfigureFromGroup(group)) { - package->Installer = &Installer; - Installer.Packages.insert( + package->Installer = &this->Installer; + this->Installer.Packages.insert( std::pair(name, package)); - GroupPackages.insert( + this->GroupPackages.insert( std::pair(group, package)); - BinaryPackages.insert(package); + this->BinaryPackages.insert(package); } else { - Packages.erase(name); - cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \"" - << name << "\" for component group \"" << group->Name - << "\"" << std::endl); + this->Packages.erase(name); + cmCPackIFWLogger(ERROR, "Cannot configure package \"" + << name << "\" for component group \"" << group->Name + << "\"" << std::endl); } return group; } @@ -441,7 +430,7 @@ bool cmCPackIFWGenerator::SupportsComponentInstallation() const bool cmCPackIFWGenerator::IsOnePackage() const { - return componentPackageMethod == ONE_PACKAGE; + return this->componentPackageMethod == cmCPackGenerator::ONE_PACKAGE; } std::string cmCPackIFWGenerator::GetRootPackageName() @@ -474,16 +463,16 @@ std::string cmCPackIFWGenerator::GetGroupPackageName( if (!group) { return name; } - if (cmCPackIFWPackage* package = GetGroupPackage(group)) { + if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) { return package->Name; } const char* option = - GetOption("CPACK_IFW_COMPONENT_GROUP_" + - cmsys::SystemTools::UpperCase(group->Name) + "_NAME"); + this->GetOption("CPACK_IFW_COMPONENT_GROUP_" + + cmsys::SystemTools::UpperCase(group->Name) + "_NAME"); name = option ? option : group->Name; if (group->ParentGroup) { - cmCPackIFWPackage* package = GetGroupPackage(group->ParentGroup); - bool dot = !ResolveDuplicateNames; + cmCPackIFWPackage* package = this->GetGroupPackage(group->ParentGroup); + bool dot = !this->ResolveDuplicateNames; if (dot && name.substr(0, package->Name.size()) == package->Name) { dot = false; } @@ -501,20 +490,21 @@ std::string cmCPackIFWGenerator::GetComponentPackageName( if (!component) { return name; } - if (cmCPackIFWPackage* package = GetComponentPackage(component)) { + if (cmCPackIFWPackage* package = this->GetComponentPackage(component)) { return package->Name; } std::string prefix = "CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_"; - const char* option = GetOption(prefix + "NAME"); + const char* option = this->GetOption(prefix + "NAME"); name = option ? option : component->Name; if (component->Group) { - cmCPackIFWPackage* package = GetGroupPackage(component->Group); - if ((componentPackageMethod == ONE_PACKAGE_PER_GROUP) || - IsOn(prefix + "COMMON")) { + cmCPackIFWPackage* package = this->GetGroupPackage(component->Group); + if ((this->componentPackageMethod == + cmCPackGenerator::ONE_PACKAGE_PER_GROUP) || + this->IsOn(prefix + "COMMON")) { return package->Name; } - bool dot = !ResolveDuplicateNames; + bool dot = !this->ResolveDuplicateNames; if (dot && name.substr(0, package->Name.size()) == package->Name) { dot = false; } @@ -529,56 +519,42 @@ cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage( cmCPackComponentGroup* group) const { std::map::const_iterator pit = - GroupPackages.find(group); - return pit != GroupPackages.end() ? pit->second : CM_NULLPTR; + this->GroupPackages.find(group); + return pit != this->GroupPackages.end() ? pit->second : CM_NULLPTR; } cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage( cmCPackComponent* component) const { std::map::const_iterator pit = - ComponentPackages.find(component); - return pit != ComponentPackages.end() ? pit->second : CM_NULLPTR; + this->ComponentPackages.find(component); + return pit != this->ComponentPackages.end() ? pit->second : CM_NULLPTR; } cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository( const std::string& repositoryName) { - RepositoriesMap::iterator rit = Repositories.find(repositoryName); - if (rit != Repositories.end()) { + RepositoriesMap::iterator rit = this->Repositories.find(repositoryName); + if (rit != this->Repositories.end()) { return &(rit->second); } - cmCPackIFWRepository* repository = &Repositories[repositoryName]; + cmCPackIFWRepository* repository = &this->Repositories[repositoryName]; repository->Name = repositoryName; repository->Generator = this; if (repository->ConfigureFromOptions()) { if (repository->Update == cmCPackIFWRepository::None) { - Installer.RemoteRepositories.push_back(repository); + this->Installer.RemoteRepositories.push_back(repository); } else { - Repository.RepositoryUpdate.push_back(repository); + this->Repository.RepositoryUpdate.push_back(repository); } } else { - Repositories.erase(repositoryName); + this->Repositories.erase(repositoryName); repository = CM_NULLPTR; - cmCPackLogger(cmCPackLog::LOG_WARNING, "Invalid repository \"" - << repositoryName << "\"" - << " configuration. Repository will be skipped." - << std::endl); + cmCPackIFWLogger(WARNING, "Invalid repository \"" + << repositoryName << "\"" + << " configuration. Repository will be skipped." + << std::endl); } return repository; } - -void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmXMLWriter& xout) -{ - std::ostringstream comment; - comment << "Generated by CPack " << CMake_VERSION << " IFW generator " - << "for QtIFW "; - if (IsVersionLess("2.0")) { - comment << "less 2.0"; - } else { - comment << FrameworkVersion; - } - comment << " tools at " << cmTimestamp().CurrentTime("", true); - xout.Comment(comment.str().c_str()); -} diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h index d65606352..8348ceeec 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.h +++ b/Source/CPack/IFW/cmCPackIFWGenerator.h @@ -3,10 +3,11 @@ #ifndef cmCPackIFWGenerator_h #define cmCPackIFWGenerator_h -#include +#include "cmConfigure.h" // IWYU pragma: keep -#include "CPack/cmCPackComponentGroup.h" -#include "CPack/cmCPackGenerator.h" +#include "cmCPackComponentGroup.h" +#include "cmCPackGenerator.h" +#include "cmCPackIFWCommon.h" #include "cmCPackIFWInstaller.h" #include "cmCPackIFWPackage.h" #include "cmCPackIFWRepository.h" @@ -16,14 +17,12 @@ #include #include -class cmXMLWriter; - /** \class cmCPackIFWGenerator * \brief A generator for Qt Installer Framework tools * * http://qt-project.org/doc/qtinstallerframework/index.html */ -class cmCPackIFWGenerator : public cmCPackGenerator +class cmCPackIFWGenerator : public cmCPackGenerator, public cmCPackIFWCommon { public: cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator); @@ -35,6 +34,11 @@ public: typedef std::map DependenceMap; + using cmCPackIFWCommon::GetOption; + using cmCPackIFWCommon::IsOn; + using cmCPackIFWCommon::IsSetToOff; + using cmCPackIFWCommon::IsSetToEmpty; + /** * Construct IFW generator */ @@ -45,21 +49,6 @@ public: */ ~cmCPackIFWGenerator() CM_OVERRIDE; - /** - * Compare \a version with QtIFW framework version - */ - bool IsVersionLess(const char* version); - - /** - * Compare \a version with QtIFW framework version - */ - bool IsVersionGreater(const char* version); - - /** - * Compare \a version with QtIFW framework version - */ - bool IsVersionEqual(const char* version); - protected: // cmCPackGenerator reimplementation @@ -124,12 +113,11 @@ protected: cmCPackIFWRepository* GetRepository(const std::string& repositoryName); - void WriteGeneratedByToStrim(cmXMLWriter& xout); - protected: // Data friend class cmCPackIFWPackage; + friend class cmCPackIFWCommon; friend class cmCPackIFWInstaller; friend class cmCPackIFWRepository; diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index d8bafeec6..288e924e5 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -2,69 +2,29 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackIFWInstaller.h" -#include -#include -#include -#include - -#include "CPack/cmCPackGenerator.h" -#include "CPack/cmCPackLog.h" +#include "cmCPackIFWCommon.h" #include "cmCPackIFWGenerator.h" #include "cmCPackIFWPackage.h" #include "cmCPackIFWRepository.h" +#include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" -#ifdef cmCPackLogger -#undef cmCPackLogger -#endif -#define cmCPackLogger(logType, msg) \ - do { \ - std::ostringstream cmCPackLog_msg; \ - cmCPackLog_msg << msg; \ - if (Generator) { \ - Generator->Logger->Log(logType, __FILE__, __LINE__, \ - cmCPackLog_msg.str().c_str()); \ - } \ - } while (false) +#include +#include +#include cmCPackIFWInstaller::cmCPackIFWInstaller() - : Generator(CM_NULLPTR) -{ -} - -const char* cmCPackIFWInstaller::GetOption(const std::string& op) const -{ - return Generator ? Generator->GetOption(op) : CM_NULLPTR; -} - -bool cmCPackIFWInstaller::IsOn(const std::string& op) const -{ - return Generator ? Generator->IsOn(op) : false; -} - -bool cmCPackIFWInstaller::IsVersionLess(const char* version) -{ - return Generator ? Generator->IsVersionLess(version) : false; -} - -bool cmCPackIFWInstaller::IsVersionGreater(const char* version) { - return Generator ? Generator->IsVersionGreater(version) : false; -} - -bool cmCPackIFWInstaller::IsVersionEqual(const char* version) -{ - return Generator ? Generator->IsVersionEqual(version) : false; } void cmCPackIFWInstaller::printSkippedOptionWarning( const std::string& optionName, const std::string& optionValue) { - cmCPackLogger( - cmCPackLog::LOG_WARNING, "Option " + cmCPackIFWLogger( + WARNING, "Option " << optionName << " is set to \"" << optionValue << "\" but will be skipped because the specified file does not exist." << std::endl); @@ -75,198 +35,199 @@ void cmCPackIFWInstaller::ConfigureFromOptions() // Name; if (const char* optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) { - Name = optIFW_PACKAGE_NAME; + this->Name = optIFW_PACKAGE_NAME; } else if (const char* optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { - Name = optPACKAGE_NAME; + this->Name = optPACKAGE_NAME; } else { - Name = "Your package"; + this->Name = "Your package"; } // Title; if (const char* optIFW_PACKAGE_TITLE = - GetOption("CPACK_IFW_PACKAGE_TITLE")) { - Title = optIFW_PACKAGE_TITLE; + this->GetOption("CPACK_IFW_PACKAGE_TITLE")) { + this->Title = optIFW_PACKAGE_TITLE; } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY = - GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { - Title = optPACKAGE_DESCRIPTION_SUMMARY; + this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { + this->Title = optPACKAGE_DESCRIPTION_SUMMARY; } else { - Title = "Your package description"; + this->Title = "Your package description"; } // Version; - if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) { - Version = option; + if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = option; } else { - Version = "1.0.0"; + this->Version = "1.0.0"; } // Publisher if (const char* optIFW_PACKAGE_PUBLISHER = - GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) { - Publisher = optIFW_PACKAGE_PUBLISHER; + this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) { + this->Publisher = optIFW_PACKAGE_PUBLISHER; } else if (const char* optPACKAGE_VENDOR = GetOption("CPACK_PACKAGE_VENDOR")) { - Publisher = optPACKAGE_VENDOR; + this->Publisher = optPACKAGE_VENDOR; } // ProductUrl - if (const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) { - ProductUrl = option; + if (const char* option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { + this->ProductUrl = option; } // ApplicationIcon - if (const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) { + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { if (cmSystemTools::FileExists(option)) { - InstallerApplicationIcon = option; + this->InstallerApplicationIcon = option; } else { - printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option); + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option); } } // WindowIcon - if (const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { if (cmSystemTools::FileExists(option)) { - InstallerWindowIcon = option; + this->InstallerWindowIcon = option; } else { - printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option); + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option); } } // Logo - if (const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) { + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { if (cmSystemTools::FileExists(option)) { - Logo = option; + this->Logo = option; } else { - printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option); + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option); } } // Watermark - if (const char* option = GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { if (cmSystemTools::FileExists(option)) { - Watermark = option; + this->Watermark = option; } else { - printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option); + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option); } } // Banner - if (const char* option = GetOption("CPACK_IFW_PACKAGE_BANNER")) { + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { if (cmSystemTools::FileExists(option)) { - Banner = option; + this->Banner = option; } else { - printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option); + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option); } } // Background - if (const char* option = GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { if (cmSystemTools::FileExists(option)) { - Background = option; + this->Background = option; } else { - printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option); + this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option); } } // WizardStyle - if (const char* option = GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { - if (WizardStyle.compare("Modern") == 0 && - WizardStyle.compare("Aero") == 0 && WizardStyle.compare("Mac") == 0 && - WizardStyle.compare("Classic") == 0) { - cmCPackLogger( - cmCPackLog::LOG_WARNING, - "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \"" + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { + // Setting the user value in any case + this->WizardStyle = option; + // Check known values + if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" && + this->WizardStyle != "Mac" && this->WizardStyle != "Classic") { + cmCPackIFWLogger( + WARNING, "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \"" << option << "\". Expected values are: Modern, Aero, Mac, Classic." << std::endl); } - - WizardStyle = option; } // WizardDefaultWidth if (const char* option = - GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) { - WizardDefaultWidth = option; + this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) { + this->WizardDefaultWidth = option; } // WizardDefaultHeight if (const char* option = - GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) { - WizardDefaultHeight = option; + this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) { + this->WizardDefaultHeight = option; } // TitleColor - if (const char* option = GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { - TitleColor = option; + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { + this->TitleColor = option; } // Start menu if (const char* optIFW_START_MENU_DIR = this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) { - StartMenuDir = optIFW_START_MENU_DIR; + this->StartMenuDir = optIFW_START_MENU_DIR; } else { - StartMenuDir = Name; + this->StartMenuDir = Name; } // Default target directory for installation if (const char* optIFW_TARGET_DIRECTORY = - GetOption("CPACK_IFW_TARGET_DIRECTORY")) { - TargetDir = optIFW_TARGET_DIRECTORY; + this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) { + this->TargetDir = optIFW_TARGET_DIRECTORY; } else if (const char* optPACKAGE_INSTALL_DIRECTORY = - GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { - TargetDir = "@ApplicationsDir@/"; - TargetDir += optPACKAGE_INSTALL_DIRECTORY; + this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { + this->TargetDir = "@ApplicationsDir@/"; + this->TargetDir += optPACKAGE_INSTALL_DIRECTORY; } else { - TargetDir = "@RootDir@/usr/local"; + this->TargetDir = "@RootDir@/usr/local"; } // Default target directory for installation with administrator rights - if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { - AdminTargetDir = option; + if (const char* option = + this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { + this->AdminTargetDir = option; } // Maintenance tool if (const char* optIFW_MAINTENANCE_TOOL = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) { - MaintenanceToolName = optIFW_MAINTENANCE_TOOL; + this->MaintenanceToolName = optIFW_MAINTENANCE_TOOL; } // Maintenance tool ini file if (const char* optIFW_MAINTENANCE_TOOL_INI = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) { - MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI; + this->MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI; } // Allow non-ASCII characters if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) { - if (IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) { - AllowNonAsciiCharacters = "true"; + if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) { + this->AllowNonAsciiCharacters = "true"; } else { - AllowNonAsciiCharacters = "false"; + this->AllowNonAsciiCharacters = "false"; } } // Space in path if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { - if (IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { - AllowSpaceInPath = "true"; + if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) { + this->AllowSpaceInPath = "true"; } else { - AllowSpaceInPath = "false"; + this->AllowSpaceInPath = "false"; } } // Control script if (const char* optIFW_CONTROL_SCRIPT = this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) { - ControlScript = optIFW_CONTROL_SCRIPT; + this->ControlScript = optIFW_CONTROL_SCRIPT; } // Resources if (const char* optIFW_PACKAGE_RESOURCES = this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) { - Resources.clear(); - cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, Resources); + this->Resources.clear(); + cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, + this->Resources); } } @@ -280,19 +241,20 @@ public: : installer(i) , file(false) { - path = i->Directory + "/resources"; + this->path = i->Directory + "/resources"; } bool ParseResource(size_t r) { - hasFiles = false; - hasErrors = false; + this->hasFiles = false; + this->hasErrors = false; - basePath = cmSystemTools::GetFilenamePath(installer->Resources[r].data()); + this->basePath = + cmSystemTools::GetFilenamePath(this->installer->Resources[r]); - ParseFile(installer->Resources[r].data()); + this->ParseFile(this->installer->Resources[r].data()); - return hasFiles && !hasErrors; + return this->hasFiles && !this->hasErrors; } cmCPackIFWInstaller* installer; @@ -302,22 +264,22 @@ public: protected: void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE { - file = name == "file"; + this->file = name == "file"; if (file) { - hasFiles = true; + this->hasFiles = true; } } void CharacterDataHandler(const char* data, int length) CM_OVERRIDE { - if (file) { + if (this->file) { std::string content(data, data + length); content = cmSystemTools::TrimWhitespace(content); - std::string source = basePath + "/" + content; - std::string destination = path + "/" + content; + std::string source = this->basePath + "/" + content; + std::string destination = this->path + "/" + content; if (!cmSystemTools::CopyFileIfDifferent(source.data(), destination.data())) { - hasErrors = true; + this->hasErrors = true; } } } @@ -328,12 +290,12 @@ protected: void cmCPackIFWInstaller::GenerateInstallerFile() { // Lazy directory initialization - if (Directory.empty() && Generator) { - Directory = Generator->toplevel; + if (this->Directory.empty() && this->Generator) { + this->Directory = this->Generator->toplevel; } // Output stream - cmGeneratedFileStream fout((Directory + "/config/config.xml").data()); + cmGeneratedFileStream fout((this->Directory + "/config/config.xml").data()); cmXMLWriter xout(fout); xout.StartDocument(); @@ -342,166 +304,165 @@ void cmCPackIFWInstaller::GenerateInstallerFile() xout.StartElement("Installer"); - xout.Element("Name", Name); - xout.Element("Version", Version); - xout.Element("Title", Title); + xout.Element("Name", this->Name); + xout.Element("Version", this->Version); + xout.Element("Title", this->Title); - if (!Publisher.empty()) { - xout.Element("Publisher", Publisher); + if (!this->Publisher.empty()) { + xout.Element("Publisher", this->Publisher); } - if (!ProductUrl.empty()) { - xout.Element("ProductUrl", ProductUrl); + if (!this->ProductUrl.empty()) { + xout.Element("ProductUrl", this->ProductUrl); } // ApplicationIcon - if (!InstallerApplicationIcon.empty()) { + if (!this->InstallerApplicationIcon.empty()) { std::string name = - cmSystemTools::GetFilenameName(InstallerApplicationIcon); - std::string path = Directory + "/config/" + name; + cmSystemTools::GetFilenameName(this->InstallerApplicationIcon); + std::string path = this->Directory + "/config/" + name; name = cmSystemTools::GetFilenameWithoutExtension(name); - cmsys::SystemTools::CopyFileIfDifferent(InstallerApplicationIcon.data(), - path.data()); + cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon, + path); xout.Element("InstallerApplicationIcon", name); } // WindowIcon - if (!InstallerWindowIcon.empty()) { - std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon); - std::string path = Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(InstallerWindowIcon.data(), - path.data()); + if (!this->InstallerWindowIcon.empty()) { + std::string name = + cmSystemTools::GetFilenameName(this->InstallerWindowIcon); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path); xout.Element("InstallerWindowIcon", name); } // Logo - if (!Logo.empty()) { - std::string name = cmSystemTools::GetFilenameName(Logo); - std::string path = Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data()); + if (!this->Logo.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Logo); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path); xout.Element("Logo", name); } // Banner - if (!Banner.empty()) { - std::string name = cmSystemTools::GetFilenameName(Banner); - std::string path = Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(Banner.data(), path.data()); + if (!this->Banner.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Banner); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Banner, path); xout.Element("Banner", name); } // Watermark - if (!Watermark.empty()) { - std::string name = cmSystemTools::GetFilenameName(Watermark); - std::string path = Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(Watermark.data(), path.data()); + if (!this->Watermark.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Watermark); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Watermark, path); xout.Element("Watermark", name); } // Background - if (!Background.empty()) { - std::string name = cmSystemTools::GetFilenameName(Background); - std::string path = Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(Background.data(), path.data()); + if (!this->Background.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Background); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Background, path); xout.Element("Background", name); } // WizardStyle - if (!WizardStyle.empty()) { - xout.Element("WizardStyle", WizardStyle); + if (!this->WizardStyle.empty()) { + xout.Element("WizardStyle", this->WizardStyle); } // WizardDefaultWidth - if (!WizardDefaultWidth.empty()) { - xout.Element("WizardDefaultWidth", WizardDefaultWidth); + if (!this->WizardDefaultWidth.empty()) { + xout.Element("WizardDefaultWidth", this->WizardDefaultWidth); } // WizardDefaultHeight - if (!WizardDefaultHeight.empty()) { - xout.Element("WizardDefaultHeight", WizardDefaultHeight); + if (!this->WizardDefaultHeight.empty()) { + xout.Element("WizardDefaultHeight", this->WizardDefaultHeight); } // TitleColor - if (!TitleColor.empty()) { - xout.Element("TitleColor", TitleColor); + if (!this->TitleColor.empty()) { + xout.Element("TitleColor", this->TitleColor); } // Start menu - if (!IsVersionLess("2.0")) { - xout.Element("StartMenuDir", StartMenuDir); + if (!this->IsVersionLess("2.0")) { + xout.Element("StartMenuDir", this->StartMenuDir); } // Target dir - if (!TargetDir.empty()) { - xout.Element("TargetDir", TargetDir); + if (!this->TargetDir.empty()) { + xout.Element("TargetDir", this->TargetDir); } // Admin target dir - if (!AdminTargetDir.empty()) { - xout.Element("AdminTargetDir", AdminTargetDir); + if (!this->AdminTargetDir.empty()) { + xout.Element("AdminTargetDir", this->AdminTargetDir); } // Remote repositories - if (!RemoteRepositories.empty()) { + if (!this->RemoteRepositories.empty()) { xout.StartElement("RemoteRepositories"); - for (RepositoriesVector::iterator rit = RemoteRepositories.begin(); - rit != RemoteRepositories.end(); ++rit) { + for (RepositoriesVector::iterator rit = this->RemoteRepositories.begin(); + rit != this->RemoteRepositories.end(); ++rit) { (*rit)->WriteRepositoryConfig(xout); } xout.EndElement(); } // Maintenance tool - if (!IsVersionLess("2.0") && !MaintenanceToolName.empty()) { - xout.Element("MaintenanceToolName", MaintenanceToolName); + if (!this->IsVersionLess("2.0") && !this->MaintenanceToolName.empty()) { + xout.Element("MaintenanceToolName", this->MaintenanceToolName); } // Maintenance tool ini file - if (!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) { - xout.Element("MaintenanceToolIniFile", MaintenanceToolIniFile); + if (!this->IsVersionLess("2.0") && !this->MaintenanceToolIniFile.empty()) { + xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile); } // Different allows - if (IsVersionLess("2.0")) { + if (this->IsVersionLess("2.0")) { // CPack IFW default policy xout.Comment("CPack IFW default policy for QtIFW less 2.0"); xout.Element("AllowNonAsciiCharacters", "true"); xout.Element("AllowSpaceInPath", "true"); } else { - if (!AllowNonAsciiCharacters.empty()) { - xout.Element("AllowNonAsciiCharacters", AllowNonAsciiCharacters); + if (!this->AllowNonAsciiCharacters.empty()) { + xout.Element("AllowNonAsciiCharacters", this->AllowNonAsciiCharacters); } - if (!AllowSpaceInPath.empty()) { - xout.Element("AllowSpaceInPath", AllowSpaceInPath); + if (!this->AllowSpaceInPath.empty()) { + xout.Element("AllowSpaceInPath", this->AllowSpaceInPath); } } // Control script (copy to config dir) - if (!IsVersionLess("2.0") && !ControlScript.empty()) { - std::string name = cmSystemTools::GetFilenameName(ControlScript); - std::string path = Directory + "/config/" + name; - cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data()); + if (!this->IsVersionLess("2.0") && !this->ControlScript.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->ControlScript); + std::string path = this->Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->ControlScript, path); xout.Element("ControlScript", name); } // Resources (copy to resources dir) - if (!Resources.empty()) { + if (!this->Resources.empty()) { std::vector resources; cmCPackIFWResourcesParser parser(this); - for (size_t i = 0; i < Resources.size(); i++) { + for (size_t i = 0; i < this->Resources.size(); i++) { if (parser.ParseResource(i)) { - std::string name = cmSystemTools::GetFilenameName(Resources[i]); - std::string path = Directory + "/resources/" + name; - cmsys::SystemTools::CopyFileIfDifferent(Resources[i].data(), - path.data()); + std::string name = cmSystemTools::GetFilenameName(this->Resources[i]); + std::string path = this->Directory + "/resources/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Resources[i], path); resources.push_back(name); } else { - cmCPackLogger(cmCPackLog::LOG_WARNING, "Can't copy resources from \"" - << Resources[i] << "\". Resource will be skipped." - << std::endl); + cmCPackIFWLogger(WARNING, "Can't copy resources from \"" + << this->Resources[i] + << "\". Resource will be skipped." << std::endl); } } - Resources = resources; + this->Resources = resources; } xout.EndElement(); @@ -510,13 +471,13 @@ void cmCPackIFWInstaller::GenerateInstallerFile() void cmCPackIFWInstaller::GeneratePackageFiles() { - if (Packages.empty() || Generator->IsOnePackage()) { + if (this->Packages.empty() || this->Generator->IsOnePackage()) { // Generate default package cmCPackIFWPackage package; - package.Generator = Generator; + package.Generator = this->Generator; package.Installer = this; // Check package group - if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) { + if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { package.ConfigureFromGroup(option); std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION"; @@ -531,16 +492,9 @@ void cmCPackIFWInstaller::GeneratePackageFiles() } // Generate packages meta information - for (PackagesMap::iterator pit = Packages.begin(); pit != Packages.end(); - ++pit) { + for (PackagesMap::iterator pit = this->Packages.begin(); + pit != this->Packages.end(); ++pit) { cmCPackIFWPackage* package = pit->second; package->GeneratePackageFile(); } } - -void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmXMLWriter& xout) -{ - if (Generator) { - Generator->WriteGeneratedByToStrim(xout); - } -} diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h index 4ec3e7013..b635f4222 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.h +++ b/Source/CPack/IFW/cmCPackIFWInstaller.h @@ -3,21 +3,21 @@ #ifndef cmCPackIFWInstaller_h #define cmCPackIFWInstaller_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmCPackIFWCommon.h" #include #include #include -class cmCPackIFWGenerator; class cmCPackIFWPackage; class cmCPackIFWRepository; -class cmXMLWriter; /** \class cmCPackIFWInstaller * \brief A binary installer to be created CPack IFW generator */ -class cmCPackIFWInstaller +class cmCPackIFWInstaller : public cmCPackIFWCommon { public: // Types @@ -111,28 +111,17 @@ public: public: // Internal implementation - const char* GetOption(const std::string& op) const; - bool IsOn(const std::string& op) const; - - bool IsVersionLess(const char* version); - bool IsVersionGreater(const char* version); - bool IsVersionEqual(const char* version); - void ConfigureFromOptions(); void GenerateInstallerFile(); void GeneratePackageFiles(); - cmCPackIFWGenerator* Generator; PackagesMap Packages; RepositoriesVector RemoteRepositories; std::string Directory; protected: - void WriteGeneratedByToStrim(cmXMLWriter& xout); - -private: void printSkippedOptionWarning(const std::string& optionName, const std::string& optionValue); }; diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index e23b1b991..c5311c31c 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -2,38 +2,24 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackIFWPackage.h" -#include "CPack/cmCPackComponentGroup.h" -#include "CPack/cmCPackGenerator.h" -#include "CPack/cmCPackLog.h" +#include "cmCPackComponentGroup.h" +#include "cmCPackIFWCommon.h" #include "cmCPackIFWGenerator.h" #include "cmCPackIFWInstaller.h" +#include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cmXMLWriter.h" -#include #include #include #include - -//----------------------------------------------------------------- Logger --- -#ifdef cmCPackLogger -#undef cmCPackLogger -#endif -#define cmCPackLogger(logType, msg) \ - do { \ - std::ostringstream cmCPackLog_msg; \ - cmCPackLog_msg << msg; \ - if (Generator) { \ - Generator->Logger->Log(logType, __FILE__, __LINE__, \ - cmCPackLog_msg.str().c_str()); \ - } \ - } while (false) +#include //---------------------------------------------------------- CompareStruct --- cmCPackIFWPackage::CompareStruct::CompareStruct() - : Type(CompareNone) + : Type(cmCPackIFWPackage::CompareNone) { } @@ -48,101 +34,66 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct( // Search compare section size_t pos = std::string::npos; if ((pos = dependence.find("<=")) != std::string::npos) { - Compare.Type = CompareLessOrEqual; - Compare.Value = dependence.substr(pos + 2); + this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual; + this->Compare.Value = dependence.substr(pos + 2); } else if ((pos = dependence.find(">=")) != std::string::npos) { - Compare.Type = CompareGreaterOrEqual; - Compare.Value = dependence.substr(pos + 2); + this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual; + this->Compare.Value = dependence.substr(pos + 2); } else if ((pos = dependence.find('<')) != std::string::npos) { - Compare.Type = CompareLess; - Compare.Value = dependence.substr(pos + 1); + this->Compare.Type = cmCPackIFWPackage::CompareLess; + this->Compare.Value = dependence.substr(pos + 1); } else if ((pos = dependence.find('=')) != std::string::npos) { - Compare.Type = CompareEqual; - Compare.Value = dependence.substr(pos + 1); + this->Compare.Type = cmCPackIFWPackage::CompareEqual; + this->Compare.Value = dependence.substr(pos + 1); } else if ((pos = dependence.find('>')) != std::string::npos) { - Compare.Type = CompareGreater; - Compare.Value = dependence.substr(pos + 1); + this->Compare.Type = cmCPackIFWPackage::CompareGreater; + this->Compare.Value = dependence.substr(pos + 1); } else if ((pos = dependence.find('-')) != std::string::npos) { - Compare.Type = CompareNone; - Compare.Value = dependence.substr(pos + 1); + this->Compare.Type = cmCPackIFWPackage::CompareNone; + this->Compare.Value = dependence.substr(pos + 1); } size_t dashPos = dependence.find('-'); if (dashPos != std::string::npos) { pos = dashPos; } - Name = pos == std::string::npos ? dependence : dependence.substr(0, pos); + this->Name = + pos == std::string::npos ? dependence : dependence.substr(0, pos); } std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const { - if (Compare.Type == CompareNone) { - return Name; + if (this->Compare.Type == cmCPackIFWPackage::CompareNone) { + return this->Name; } - std::string result = Name; + std::string result = this->Name; - if (Compare.Type != CompareNone || !Compare.Value.empty()) { + if (this->Compare.Type != cmCPackIFWPackage::CompareNone || + !this->Compare.Value.empty()) { result += "-"; } - if (Compare.Type == CompareLessOrEqual) { + if (this->Compare.Type == cmCPackIFWPackage::CompareLessOrEqual) { result += "<="; - } else if (Compare.Type == CompareGreaterOrEqual) { + } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreaterOrEqual) { result += ">="; - } else if (Compare.Type == CompareLess) { + } else if (this->Compare.Type == cmCPackIFWPackage::CompareLess) { result += "<"; - } else if (Compare.Type == CompareEqual) { + } else if (this->Compare.Type == cmCPackIFWPackage::CompareEqual) { result += "="; - } else if (Compare.Type == CompareGreater) { + } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreater) { result += ">"; } - result += Compare.Value; + result += this->Compare.Value; return result; } //------------------------------------------------------ cmCPackIFWPackage --- cmCPackIFWPackage::cmCPackIFWPackage() - : Generator(CM_NULLPTR) - , Installer(CM_NULLPTR) -{ -} - -const char* cmCPackIFWPackage::GetOption(const std::string& op) const -{ - const char* option = Generator ? Generator->GetOption(op) : CM_NULLPTR; - return option && *option ? option : CM_NULLPTR; -} - -bool cmCPackIFWPackage::IsOn(const std::string& op) const -{ - return Generator ? Generator->IsOn(op) : false; -} - -bool cmCPackIFWPackage::IsSetToOff(const std::string& op) const -{ - return Generator ? Generator->IsSetToOff(op) : false; -} - -bool cmCPackIFWPackage::IsSetToEmpty(const std::string& op) const -{ - return Generator ? Generator->IsSetToEmpty(op) : false; -} - -bool cmCPackIFWPackage::IsVersionLess(const char* version) -{ - return Generator ? Generator->IsVersionLess(version) : false; -} - -bool cmCPackIFWPackage::IsVersionGreater(const char* version) -{ - return Generator ? Generator->IsVersionGreater(version) : false; -} - -bool cmCPackIFWPackage::IsVersionEqual(const char* version) + : Installer(CM_NULLPTR) { - return Generator ? Generator->IsVersionEqual(version) : false; } std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component) @@ -151,62 +102,62 @@ std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component) return ""; } const char* option = - GetOption("CPACK_IFW_COMPONENT_" + - cmsys::SystemTools::UpperCase(component->Name) + "_NAME"); + this->GetOption("CPACK_IFW_COMPONENT_" + + cmsys::SystemTools::UpperCase(component->Name) + "_NAME"); return option ? option : component->Name; } void cmCPackIFWPackage::DefaultConfiguration() { - DisplayName = ""; - Description = ""; - Version = ""; - ReleaseDate = ""; - Script = ""; - Licenses.clear(); - UserInterfaces.clear(); - Translations.clear(); - SortingPriority = ""; - UpdateText = ""; - Default = ""; - Essential = ""; - Virtual = ""; - ForcedInstallation = ""; - RequiresAdminRights = ""; + this->DisplayName.clear(); + this->Description.clear(); + this->Version = ""; + this->ReleaseDate = ""; + this->Script = ""; + this->Licenses.clear(); + this->UserInterfaces.clear(); + this->Translations.clear(); + this->SortingPriority = ""; + this->UpdateText = ""; + this->Default = ""; + this->Essential = ""; + this->Virtual = ""; + this->ForcedInstallation = ""; + this->RequiresAdminRights = ""; } // Defaul configuration (all in one package) int cmCPackIFWPackage::ConfigureFromOptions() { // Restore defaul configuration - DefaultConfiguration(); + this->DefaultConfiguration(); // Name - Name = Generator->GetRootPackageName(); + this->Name = this->Generator->GetRootPackageName(); // Display name if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) { - DisplayName = option; + this->DisplayName[""] = option; } else { - DisplayName = "Your package"; + this->DisplayName[""] = "Your package"; } // Description if (const char* option = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { - Description = option; + this->Description[""] = option; } else { - Description = "Your package description"; + this->Description[""] = "Your package description"; } // Version - if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) { - Version = option; + if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = option; } else { - Version = "1.0.0"; + this->Version = "1.0.0"; } - ForcedInstallation = "true"; + this->ForcedInstallation = "true"; return 1; } @@ -218,36 +169,36 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Restore defaul configuration - DefaultConfiguration(); + this->DefaultConfiguration(); std::string prefix = "CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_"; // Display name - DisplayName = component->DisplayName; + this->DisplayName[""] = component->DisplayName; // Description - Description = component->Description; + this->Description[""] = component->Description; // Version - if (const char* optVERSION = GetOption(prefix + "VERSION")) { - Version = optVERSION; + if (const char* optVERSION = this->GetOption(prefix + "VERSION")) { + this->Version = optVERSION; } else if (const char* optPACKAGE_VERSION = - GetOption("CPACK_PACKAGE_VERSION")) { - Version = optPACKAGE_VERSION; + this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = optPACKAGE_VERSION; } else { - Version = "1.0.0"; + this->Version = "1.0.0"; } // Script - if (const char* option = GetOption(prefix + "SCRIPT")) { - Script = option; + if (const char* option = this->GetOption(prefix + "SCRIPT")) { + this->Script = option; } // User interfaces if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { - UserInterfaces.clear(); - cmSystemTools::ExpandListArgument(option, UserInterfaces); + this->UserInterfaces.clear(); + cmSystemTools::ExpandListArgument(option, this->UserInterfaces); } // CMake dependencies @@ -255,49 +206,49 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) std::vector::iterator dit; for (dit = component->Dependencies.begin(); dit != component->Dependencies.end(); ++dit) { - Dependencies.insert(Generator->ComponentPackages[*dit]); + this->Dependencies.insert(this->Generator->ComponentPackages[*dit]); } } // Licenses if (const char* option = this->GetOption(prefix + "LICENSES")) { - Licenses.clear(); - cmSystemTools::ExpandListArgument(option, Licenses); - if (Licenses.size() % 2 != 0) { - cmCPackLogger( - cmCPackLog::LOG_WARNING, prefix - << "LICENSES" - << " should contain pairs of and ." - << std::endl); - Licenses.clear(); + this->Licenses.clear(); + cmSystemTools::ExpandListArgument(option, this->Licenses); + if (this->Licenses.size() % 2 != 0) { + cmCPackIFWLogger( + WARNING, + prefix << "LICENSES" + << " should contain pairs of and ." + << std::endl); + this->Licenses.clear(); } } // Priority if (const char* option = this->GetOption(prefix + "PRIORITY")) { - SortingPriority = option; - cmCPackLogger( - cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set " + this->SortingPriority = option; + cmCPackIFWLogger( + WARNING, "The \"PRIORITY\" option is set " << "for component \"" << component->Name << "\", but there option is " << "deprecated. Please use \"SORTING_PRIORITY\" option instead." << std::endl); } // Default - Default = component->IsDisabledByDefault ? "false" : "true"; + this->Default = component->IsDisabledByDefault ? "false" : "true"; // Essential if (this->IsOn(prefix + "ESSENTIAL")) { - Essential = "true"; + this->Essential = "true"; } // Virtual - Virtual = component->IsHidden ? "true" : ""; + this->Virtual = component->IsHidden ? "true" : ""; // ForcedInstallation - ForcedInstallation = component->IsRequired ? "true" : "false"; + this->ForcedInstallation = component->IsRequired ? "true" : "false"; - return ConfigureFromPrefix(prefix); + return this->ConfigureFromPrefix(prefix); } int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) @@ -307,61 +258,61 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) } // Restore defaul configuration - DefaultConfiguration(); + this->DefaultConfiguration(); std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(group->Name) + "_"; - DisplayName = group->DisplayName; - Description = group->Description; + this->DisplayName[""] = group->DisplayName; + this->Description[""] = group->Description; // Version - if (const char* optVERSION = GetOption(prefix + "VERSION")) { - Version = optVERSION; + if (const char* optVERSION = this->GetOption(prefix + "VERSION")) { + this->Version = optVERSION; } else if (const char* optPACKAGE_VERSION = - GetOption("CPACK_PACKAGE_VERSION")) { - Version = optPACKAGE_VERSION; + this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = optPACKAGE_VERSION; } else { - Version = "1.0.0"; + this->Version = "1.0.0"; } // Script - if (const char* option = GetOption(prefix + "SCRIPT")) { - Script = option; + if (const char* option = this->GetOption(prefix + "SCRIPT")) { + this->Script = option; } // User interfaces if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { - UserInterfaces.clear(); - cmSystemTools::ExpandListArgument(option, UserInterfaces); + this->UserInterfaces.clear(); + cmSystemTools::ExpandListArgument(option, this->UserInterfaces); } // Licenses if (const char* option = this->GetOption(prefix + "LICENSES")) { - Licenses.clear(); - cmSystemTools::ExpandListArgument(option, Licenses); - if (Licenses.size() % 2 != 0) { - cmCPackLogger( - cmCPackLog::LOG_WARNING, prefix - << "LICENSES" - << " should contain pairs of and ." - << std::endl); - Licenses.clear(); + this->Licenses.clear(); + cmSystemTools::ExpandListArgument(option, this->Licenses); + if (this->Licenses.size() % 2 != 0) { + cmCPackIFWLogger( + WARNING, + prefix << "LICENSES" + << " should contain pairs of and ." + << std::endl); + this->Licenses.clear(); } } // Priority if (const char* option = this->GetOption(prefix + "PRIORITY")) { - SortingPriority = option; - cmCPackLogger( - cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set " + this->SortingPriority = option; + cmCPackIFWLogger( + WARNING, "The \"PRIORITY\" option is set " << "for component group \"" << group->Name << "\", but there option is " << "deprecated. Please use \"SORTING_PRIORITY\" option instead." << std::endl); } - return ConfigureFromPrefix(prefix); + return this->ConfigureFromPrefix(prefix); } int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName) @@ -372,29 +323,29 @@ int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName) std::string prefix = "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_"; - if (const char* option = GetOption(prefix + "DISPLAY_NAME")) { + if (const char* option = this->GetOption(prefix + "DISPLAY_NAME")) { group.DisplayName = option; } else { group.DisplayName = group.Name; } - if (const char* option = GetOption(prefix + "DESCRIPTION")) { + if (const char* option = this->GetOption(prefix + "DESCRIPTION")) { group.Description = option; } - group.IsBold = IsOn(prefix + "BOLD_TITLE"); - group.IsExpandedByDefault = IsOn(prefix + "EXPANDED"); + group.IsBold = this->IsOn(prefix + "BOLD_TITLE"); + group.IsExpandedByDefault = this->IsOn(prefix + "EXPANDED"); // Package configuration group.Name = groupName; if (Generator) { - Name = Generator->GetGroupPackageName(&group); + this->Name = this->Generator->GetGroupPackageName(&group); } else { - Name = group.Name; + this->Name = group.Name; } - return ConfigureFromGroup(&group); + return this->ConfigureFromGroup(&group); } // Common options for components and groups @@ -405,51 +356,51 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) // Display name option = prefix + "DISPLAY_NAME"; - if (IsSetToEmpty(option)) { - DisplayName.clear(); - } else if (const char* value = GetOption(option)) { - DisplayName = value; + if (this->IsSetToEmpty(option)) { + this->DisplayName.clear(); + } else if (const char* value = this->GetOption(option)) { + this->ExpandListArgument(value, this->DisplayName); } // Description option = prefix + "DESCRIPTION"; - if (IsSetToEmpty(option)) { - Description.clear(); - } else if (const char* value = GetOption(option)) { - Description = value; + if (this->IsSetToEmpty(option)) { + this->Description.clear(); + } else if (const char* value = this->GetOption(option)) { + this->ExpandListArgument(value, this->Description); } // Release date option = prefix + "RELEASE_DATE"; - if (IsSetToEmpty(option)) { - ReleaseDate.clear(); - } else if (const char* value = GetOption(option)) { - ReleaseDate = value; + if (this->IsSetToEmpty(option)) { + this->ReleaseDate.clear(); + } else if (const char* value = this->GetOption(option)) { + this->ReleaseDate = value; } // Sorting priority option = prefix + "SORTING_PRIORITY"; - if (IsSetToEmpty(option)) { - SortingPriority.clear(); - } else if (const char* value = GetOption(option)) { - SortingPriority = value; + if (this->IsSetToEmpty(option)) { + this->SortingPriority.clear(); + } else if (const char* value = this->GetOption(option)) { + this->SortingPriority = value; } // Update text option = prefix + "UPDATE_TEXT"; - if (IsSetToEmpty(option)) { - UpdateText.clear(); - } else if (const char* value = GetOption(option)) { - UpdateText = value; + if (this->IsSetToEmpty(option)) { + this->UpdateText.clear(); + } else if (const char* value = this->GetOption(option)) { + this->UpdateText = value; } // Translations option = prefix + "TRANSLATIONS"; - if (IsSetToEmpty(option)) { - Translations.clear(); + if (this->IsSetToEmpty(option)) { + this->Translations.clear(); } else if (const char* value = this->GetOption(option)) { - Translations.clear(); - cmSystemTools::ExpandListArgument(value, Translations); + this->Translations.clear(); + cmSystemTools::ExpandListArgument(value, this->Translations); } // QtIFW dependencies @@ -465,84 +416,84 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) for (std::vector::iterator dit = deps.begin(); dit != deps.end(); ++dit) { DependenceStruct dep(*dit); - if (Generator->Packages.count(dep.Name)) { - cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name]; + if (this->Generator->Packages.count(dep.Name)) { + cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name]; dep.Name = depPkg.Name; } - bool hasDep = Generator->DependentPackages.count(dep.Name) > 0; - DependenceStruct& depRef = Generator->DependentPackages[dep.Name]; + bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0; + DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name]; if (!hasDep) { depRef = dep; } - AlienDependencies.insert(&depRef); + this->AlienDependencies.insert(&depRef); } // Automatic dependency on option = prefix + "AUTO_DEPEND_ON"; - if (IsSetToEmpty(option)) { - AlienAutoDependOn.clear(); + if (this->IsSetToEmpty(option)) { + this->AlienAutoDependOn.clear(); } else if (const char* value = this->GetOption(option)) { std::vector depsOn; cmSystemTools::ExpandListArgument(value, depsOn); for (std::vector::iterator dit = depsOn.begin(); dit != depsOn.end(); ++dit) { DependenceStruct dep(*dit); - if (Generator->Packages.count(dep.Name)) { - cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name]; + if (this->Generator->Packages.count(dep.Name)) { + cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name]; dep.Name = depPkg.Name; } - bool hasDep = Generator->DependentPackages.count(dep.Name) > 0; - DependenceStruct& depRef = Generator->DependentPackages[dep.Name]; + bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0; + DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name]; if (!hasDep) { depRef = dep; } - AlienAutoDependOn.insert(&depRef); + this->AlienAutoDependOn.insert(&depRef); } } // Visibility option = prefix + "VIRTUAL"; - if (IsSetToEmpty(option)) { - Virtual.clear(); - } else if (IsOn(option)) { - Virtual = "true"; + if (this->IsSetToEmpty(option)) { + this->Virtual.clear(); + } else if (this->IsOn(option)) { + this->Virtual = "true"; } // Default selection option = prefix + "DEFAULT"; - if (IsSetToEmpty(option)) { - Default.clear(); - } else if (const char* value = GetOption(option)) { + if (this->IsSetToEmpty(option)) { + this->Default.clear(); + } else if (const char* value = this->GetOption(option)) { std::string lowerValue = cmsys::SystemTools::LowerCase(value); - if (lowerValue.compare("true") == 0) { - Default = "true"; - } else if (lowerValue.compare("false") == 0) { - Default = "false"; - } else if (lowerValue.compare("script") == 0) { - Default = "script"; + if (lowerValue == "true") { + this->Default = "true"; + } else if (lowerValue == "false") { + this->Default = "false"; + } else if (lowerValue == "script") { + this->Default = "script"; } else { - Default = value; + this->Default = value; } } // Forsed installation option = prefix + "FORCED_INSTALLATION"; - if (IsSetToEmpty(option)) { - ForcedInstallation.clear(); - } else if (IsOn(option)) { - ForcedInstallation = "true"; - } else if (IsSetToOff(option)) { - ForcedInstallation = "false"; + if (this->IsSetToEmpty(option)) { + this->ForcedInstallation.clear(); + } else if (this->IsOn(option)) { + this->ForcedInstallation = "true"; + } else if (this->IsSetToOff(option)) { + this->ForcedInstallation = "false"; } // Requires admin rights option = prefix + "REQUIRES_ADMIN_RIGHTS"; - if (IsSetToEmpty(option)) { - RequiresAdminRights.clear(); - } else if (IsOn(option)) { - RequiresAdminRights = "true"; - } else if (IsSetToOff(option)) { - RequiresAdminRights = "false"; + if (this->IsSetToEmpty(option)) { + this->RequiresAdminRights.clear(); + } else if (this->IsOn(option)) { + this->RequiresAdminRights = "true"; + } else if (this->IsSetToOff(option)) { + this->RequiresAdminRights = "false"; } return 1; @@ -551,16 +502,16 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) void cmCPackIFWPackage::GeneratePackageFile() { // Lazy directory initialization - if (Directory.empty()) { - if (Installer) { - Directory = Installer->Directory + "/packages/" + Name; - } else if (Generator) { - Directory = Generator->toplevel + "/packages/" + Name; + if (this->Directory.empty()) { + if (this->Installer) { + this->Directory = this->Installer->Directory + "/packages/" + this->Name; + } else if (this->Generator) { + this->Directory = this->Generator->toplevel + "/packages/" + this->Name; } } // Output stream - cmGeneratedFileStream fout((Directory + "/meta/package.xml").data()); + cmGeneratedFileStream fout((this->Directory + "/meta/package.xml").data()); cmXMLWriter xout(fout); xout.StartDocument(); @@ -569,28 +520,49 @@ void cmCPackIFWPackage::GeneratePackageFile() xout.StartElement("Package"); - xout.Element("DisplayName", DisplayName); - xout.Element("Description", Description); + // DisplayName (with translations) + for (std::map::iterator it = + this->DisplayName.begin(); + it != this->DisplayName.end(); ++it) { + xout.StartElement("DisplayName"); + if (!it->first.empty()) { + xout.Attribute("xml:lang", it->first); + } + xout.Content(it->second); + xout.EndElement(); + } + + // Description (with translations) + for (std::map::iterator it = + this->Description.begin(); + it != this->Description.end(); ++it) { + xout.StartElement("Description"); + if (!it->first.empty()) { + xout.Attribute("xml:lang", it->first); + } + xout.Content(it->second); + xout.EndElement(); + } // Update text - if (!UpdateText.empty()) { - xout.Element("UpdateText", UpdateText); + if (!this->UpdateText.empty()) { + xout.Element("UpdateText", this->UpdateText); } - xout.Element("Name", Name); - xout.Element("Version", Version); + xout.Element("Name", this->Name); + xout.Element("Version", this->Version); - if (!ReleaseDate.empty()) { - xout.Element("ReleaseDate", ReleaseDate); + if (!this->ReleaseDate.empty()) { + xout.Element("ReleaseDate", this->ReleaseDate); } else { xout.Element("ReleaseDate", cmTimestamp().CurrentTime("%Y-%m-%d", true)); } // Script (copy to meta dir) - if (!Script.empty()) { - std::string name = cmSystemTools::GetFilenameName(Script); - std::string path = Directory + "/meta/" + name; - cmsys::SystemTools::CopyFileIfDifferent(Script.data(), path.data()); + if (!this->Script.empty()) { + std::string name = cmSystemTools::GetFilenameName(this->Script); + std::string path = this->Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(this->Script, path); xout.Element("Script", name); } @@ -598,9 +570,8 @@ void cmCPackIFWPackage::GeneratePackageFile() std::vector userInterfaces = UserInterfaces; for (size_t i = 0; i < userInterfaces.size(); i++) { std::string name = cmSystemTools::GetFilenameName(userInterfaces[i]); - std::string path = Directory + "/meta/" + name; - cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i].data(), - path.data()); + std::string path = this->Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i], path); userInterfaces[i] = name; } if (!userInterfaces.empty()) { @@ -615,9 +586,8 @@ void cmCPackIFWPackage::GeneratePackageFile() std::vector translations = Translations; for (size_t i = 0; i < translations.size(); i++) { std::string name = cmSystemTools::GetFilenameName(translations[i]); - std::string path = Directory + "/meta/" + name; - cmsys::SystemTools::CopyFileIfDifferent(translations[i].data(), - path.data()); + std::string path = this->Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(translations[i], path); translations[i] = name; } if (!translations.empty()) { @@ -630,12 +600,13 @@ void cmCPackIFWPackage::GeneratePackageFile() // Dependencies std::set compDepSet; - for (std::set::iterator ait = AlienDependencies.begin(); - ait != AlienDependencies.end(); ++ait) { + for (std::set::iterator ait = + this->AlienDependencies.begin(); + ait != this->AlienDependencies.end(); ++ait) { compDepSet.insert(*(*ait)); } - for (std::set::iterator it = Dependencies.begin(); - it != Dependencies.end(); ++it) { + for (std::set::iterator it = this->Dependencies.begin(); + it != this->Dependencies.end(); ++it) { compDepSet.insert(DependenceStruct((*it)->Name)); } // Write dependencies @@ -653,8 +624,9 @@ void cmCPackIFWPackage::GeneratePackageFile() // Automatic dependency on std::set compAutoDepSet; - for (std::set::iterator ait = AlienAutoDependOn.begin(); - ait != AlienAutoDependOn.end(); ++ait) { + for (std::set::iterator ait = + this->AlienAutoDependOn.begin(); + ait != this->AlienAutoDependOn.end(); ++ait) { compAutoDepSet.insert(*(*ait)); } // Write automatic dependency on @@ -671,11 +643,11 @@ void cmCPackIFWPackage::GeneratePackageFile() } // Licenses (copy to meta dir) - std::vector licenses = Licenses; + std::vector licenses = this->Licenses; for (size_t i = 1; i < licenses.size(); i += 2) { std::string name = cmSystemTools::GetFilenameName(licenses[i]); - std::string path = Directory + "/meta/" + name; - cmsys::SystemTools::CopyFileIfDifferent(licenses[i].data(), path.data()); + std::string path = this->Directory + "/meta/" + name; + cmsys::SystemTools::CopyFileIfDifferent(licenses[i], path); licenses[i] = name; } if (!licenses.empty()) { @@ -689,37 +661,30 @@ void cmCPackIFWPackage::GeneratePackageFile() xout.EndElement(); } - if (!ForcedInstallation.empty()) { - xout.Element("ForcedInstallation", ForcedInstallation); + if (!this->ForcedInstallation.empty()) { + xout.Element("ForcedInstallation", this->ForcedInstallation); } - if (!RequiresAdminRights.empty()) { - xout.Element("RequiresAdminRights", RequiresAdminRights); + if (!this->RequiresAdminRights.empty()) { + xout.Element("RequiresAdminRights", this->RequiresAdminRights); } - if (!Virtual.empty()) { - xout.Element("Virtual", Virtual); - } else if (!Default.empty()) { - xout.Element("Default", Default); + if (!this->Virtual.empty()) { + xout.Element("Virtual", this->Virtual); + } else if (!this->Default.empty()) { + xout.Element("Default", this->Default); } // Essential - if (!Essential.empty()) { - xout.Element("Essential", Essential); + if (!this->Essential.empty()) { + xout.Element("Essential", this->Essential); } // Priority - if (!SortingPriority.empty()) { - xout.Element("SortingPriority", SortingPriority); + if (!this->SortingPriority.empty()) { + xout.Element("SortingPriority", this->SortingPriority); } xout.EndElement(); xout.EndDocument(); } - -void cmCPackIFWPackage::WriteGeneratedByToStrim(cmXMLWriter& xout) -{ - if (Generator) { - Generator->WriteGeneratedByToStrim(xout); - } -} diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h index bd1d6c59c..cec59b03c 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.h +++ b/Source/CPack/IFW/cmCPackIFWPackage.h @@ -3,22 +3,23 @@ #ifndef cmCPackIFWPackage_h #define cmCPackIFWPackage_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep +#include "cmCPackIFWCommon.h" + +#include #include #include #include class cmCPackComponent; class cmCPackComponentGroup; -class cmCPackIFWGenerator; class cmCPackIFWInstaller; -class cmXMLWriter; /** \class cmCPackIFWPackage * \brief A single component to be installed by CPack IFW generator */ -class cmCPackIFWPackage +class cmCPackIFWPackage : public cmCPackIFWCommon { public: // Types @@ -69,10 +70,10 @@ public: // Configuration /// Human-readable name of the component - std::string DisplayName; + std::map DisplayName; /// Human-readable description of the component - std::string Description; + std::map Description; /// Version number of the component std::string Version; @@ -119,15 +120,6 @@ public: public: // Internal implementation - const char* GetOption(const std::string& op) const; - bool IsOn(const std::string& op) const; - bool IsSetToOff(const std::string& op) const; - bool IsSetToEmpty(const std::string& op) const; - - bool IsVersionLess(const char* version); - bool IsVersionGreater(const char* version); - bool IsVersionEqual(const char* version); - std::string GetComponentName(cmCPackComponent* component); void DefaultConfiguration(); @@ -140,8 +132,6 @@ public: void GeneratePackageFile(); - // Pointer to generator - cmCPackIFWGenerator* Generator; // Pointer to installer cmCPackIFWInstaller* Installer; // Collection of dependencies @@ -152,9 +142,6 @@ public: std::set AlienAutoDependOn; // Patch to package directory std::string Directory; - -protected: - void WriteGeneratedByToStrim(cmXMLWriter& xout); }; #endif // cmCPackIFWPackage_h diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx index cc204e828..b115db057 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.cxx +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -2,32 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackIFWRepository.h" -#include "CPack/cmCPackGenerator.h" #include "cmCPackIFWGenerator.h" #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" -#include #include -#ifdef cmCPackLogger -#undef cmCPackLogger -#endif -#define cmCPackLogger(logType, msg) \ - do { \ - std::ostringstream cmCPackLog_msg; \ - cmCPackLog_msg << msg; \ - if (Generator) { \ - Generator->Logger->Log(logType, __FILE__, __LINE__, \ - cmCPackLog_msg.str().c_str()); \ - } \ - } while (false) - cmCPackIFWRepository::cmCPackIFWRepository() - : Update(None) - , Generator(CM_NULLPTR) + : Update(cmCPackIFWRepository::None) { } @@ -35,120 +19,95 @@ bool cmCPackIFWRepository::IsValid() const { bool valid = true; - switch (Update) { - case None: - valid = !Url.empty(); + switch (this->Update) { + case cmCPackIFWRepository::None: + valid = !this->Url.empty(); break; - case Add: - valid = !Url.empty(); + case cmCPackIFWRepository::Add: + valid = !this->Url.empty(); break; - case Remove: - valid = !Url.empty(); + case cmCPackIFWRepository::Remove: + valid = !this->Url.empty(); break; - case Replace: - valid = !OldUrl.empty() && !NewUrl.empty(); + case cmCPackIFWRepository::Replace: + valid = !this->OldUrl.empty() && !this->NewUrl.empty(); break; } return valid; } -const char* cmCPackIFWRepository::GetOption(const std::string& op) const -{ - return Generator ? Generator->GetOption(op) : CM_NULLPTR; -} - -bool cmCPackIFWRepository::IsOn(const std::string& op) const -{ - return Generator ? Generator->IsOn(op) : false; -} - -bool cmCPackIFWRepository::IsVersionLess(const char* version) -{ - return Generator ? Generator->IsVersionLess(version) : false; -} - -bool cmCPackIFWRepository::IsVersionGreater(const char* version) -{ - return Generator ? Generator->IsVersionGreater(version) : false; -} - -bool cmCPackIFWRepository::IsVersionEqual(const char* version) -{ - return Generator ? Generator->IsVersionEqual(version) : false; -} - bool cmCPackIFWRepository::ConfigureFromOptions() { // Name; - if (Name.empty()) { + if (this->Name.empty()) { return false; } std::string prefix = - "CPACK_IFW_REPOSITORY_" + cmsys::SystemTools::UpperCase(Name) + "_"; + "CPACK_IFW_REPOSITORY_" + cmsys::SystemTools::UpperCase(this->Name) + "_"; // Update - if (IsOn(prefix + "ADD")) { - Update = Add; + if (this->IsOn(prefix + "ADD")) { + this->Update = cmCPackIFWRepository::Add; } else if (IsOn(prefix + "REMOVE")) { - Update = Remove; + this->Update = cmCPackIFWRepository::Remove; } else if (IsOn(prefix + "REPLACE")) { - Update = Replace; + this->Update = cmCPackIFWRepository::Replace; } else { - Update = None; + this->Update = cmCPackIFWRepository::None; } // Url - if (const char* url = GetOption(prefix + "URL")) { - Url = url; + if (const char* url = this->GetOption(prefix + "URL")) { + this->Url = url; } else { - Url = ""; + this->Url = ""; } // Old url - if (const char* oldUrl = GetOption(prefix + "OLD_URL")) { - OldUrl = oldUrl; + if (const char* oldUrl = this->GetOption(prefix + "OLD_URL")) { + this->OldUrl = oldUrl; } else { - OldUrl = ""; + this->OldUrl = ""; } // New url - if (const char* newUrl = GetOption(prefix + "NEW_URL")) { - NewUrl = newUrl; + if (const char* newUrl = this->GetOption(prefix + "NEW_URL")) { + this->NewUrl = newUrl; } else { - NewUrl = ""; + this->NewUrl = ""; } // Enabled - if (IsOn(prefix + "DISABLED")) { - Enabled = "0"; + if (this->IsOn(prefix + "DISABLED")) { + this->Enabled = "0"; } else { - Enabled = ""; + this->Enabled = ""; } // Username - if (const char* username = GetOption(prefix + "USERNAME")) { - Username = username; + if (const char* username = this->GetOption(prefix + "USERNAME")) { + this->Username = username; } else { - Username = ""; + this->Username = ""; } // Password - if (const char* password = GetOption(prefix + "PASSWORD")) { - Password = password; + if (const char* password = this->GetOption(prefix + "PASSWORD")) { + this->Password = password; } else { - Password = ""; + this->Password = ""; } // DisplayName - if (const char* displayName = GetOption(prefix + "DISPLAY_NAME")) { - DisplayName = displayName; + if (const char* displayName = this->GetOption(prefix + "DISPLAY_NAME")) { + this->DisplayName = displayName; } else { - DisplayName = ""; + this->DisplayName = ""; } - return IsValid(); + return this->IsValid(); } /** \class cmCPackeIFWUpdatesPatcher @@ -171,8 +130,8 @@ public: protected: void StartElement(const std::string& name, const char** atts) CM_OVERRIDE { - xout.StartElement(name); - StartFragment(atts); + this->xout.StartElement(name); + this->StartFragment(atts); } void StartFragment(const char** atts) @@ -180,23 +139,23 @@ protected: for (size_t i = 0; atts[i]; i += 2) { const char* key = atts[i]; const char* value = atts[i + 1]; - xout.Attribute(key, value); + this->xout.Attribute(key, value); } } void EndElement(const std::string& name) CM_OVERRIDE { - if (name == "Updates" && !patched) { - repository->WriteRepositoryUpdates(xout); - patched = true; + if (name == "Updates" && !this->patched) { + this->repository->WriteRepositoryUpdates(this->xout); + this->patched = true; } - xout.EndElement(); - if (patched) { + this->xout.EndElement(); + if (this->patched) { return; } if (name == "Checksum") { - repository->WriteRepositoryUpdates(xout); - patched = true; + this->repository->WriteRepositoryUpdates(this->xout); + this->patched = true; } } @@ -207,20 +166,21 @@ protected: content == "\n") { return; } - xout.Content(content); + this->xout.Content(content); } }; bool cmCPackIFWRepository::PatchUpdatesXml() { // Lazy directory initialization - if (Directory.empty() && Generator) { - Directory = Generator->toplevel; + if (this->Directory.empty() && this->Generator) { + this->Directory = this->Generator->toplevel; } // Filenames - std::string updatesXml = Directory + "/repository/Updates.xml"; - std::string updatesPatchXml = Directory + "/repository/UpdatesPatch.xml"; + std::string updatesXml = this->Directory + "/repository/Updates.xml"; + std::string updatesPatchXml = + this->Directory + "/repository/UpdatesPatch.xml"; // Output stream cmGeneratedFileStream fout(updatesPatchXml.data()); @@ -228,7 +188,7 @@ bool cmCPackIFWRepository::PatchUpdatesXml() xout.StartDocument(); - WriteGeneratedByToStrim(xout); + this->WriteGeneratedByToStrim(xout); // Patch { @@ -248,22 +208,22 @@ void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout) xout.StartElement("Repository"); // Url - xout.Element("Url", Url); + xout.Element("Url", this->Url); // Enabled - if (!Enabled.empty()) { - xout.Element("Enabled", Enabled); + if (!this->Enabled.empty()) { + xout.Element("Enabled", this->Enabled); } // Username - if (!Username.empty()) { - xout.Element("Username", Username); + if (!this->Username.empty()) { + xout.Element("Username", this->Username); } // Password - if (!Password.empty()) { - xout.Element("Password", Password); + if (!this->Password.empty()) { + xout.Element("Password", this->Password); } // DisplayName - if (!DisplayName.empty()) { - xout.Element("DisplayName", DisplayName); + if (!this->DisplayName.empty()) { + xout.Element("DisplayName", this->DisplayName); } xout.EndElement(); @@ -273,42 +233,43 @@ void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout) { xout.StartElement("Repository"); - switch (Update) { - case None: + switch (this->Update) { + case cmCPackIFWRepository::None: break; - case Add: + case cmCPackIFWRepository::Add: xout.Attribute("action", "add"); break; - case Remove: + case cmCPackIFWRepository::Remove: xout.Attribute("action", "remove"); break; - case Replace: + case cmCPackIFWRepository::Replace: xout.Attribute("action", "replace"); break; } // Url - if (Update == Add || Update == Remove) { - xout.Attribute("url", Url); - } else if (Update == Replace) { - xout.Attribute("oldUrl", OldUrl); - xout.Attribute("newUrl", NewUrl); + if (this->Update == cmCPackIFWRepository::Add || + this->Update == cmCPackIFWRepository::Remove) { + xout.Attribute("url", this->Url); + } else if (Update == cmCPackIFWRepository::Replace) { + xout.Attribute("oldUrl", this->OldUrl); + xout.Attribute("newUrl", this->NewUrl); } // Enabled - if (!Enabled.empty()) { - xout.Attribute("enabled", Enabled); + if (!this->Enabled.empty()) { + xout.Attribute("enabled", this->Enabled); } // Username - if (!Username.empty()) { - xout.Attribute("username", Username); + if (!this->Username.empty()) { + xout.Attribute("username", this->Username); } // Password - if (!Password.empty()) { - xout.Attribute("password", Password); + if (!this->Password.empty()) { + xout.Attribute("password", this->Password); } // DisplayName - if (!DisplayName.empty()) { - xout.Attribute("displayname", DisplayName); + if (!this->DisplayName.empty()) { + xout.Attribute("displayname", this->DisplayName); } xout.EndElement(); @@ -316,19 +277,12 @@ void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout) void cmCPackIFWRepository::WriteRepositoryUpdates(cmXMLWriter& xout) { - if (!RepositoryUpdate.empty()) { + if (!this->RepositoryUpdate.empty()) { xout.StartElement("RepositoryUpdate"); - for (RepositoriesVector::iterator rit = RepositoryUpdate.begin(); - rit != RepositoryUpdate.end(); ++rit) { + for (RepositoriesVector::iterator rit = this->RepositoryUpdate.begin(); + rit != this->RepositoryUpdate.end(); ++rit) { (*rit)->WriteRepositoryUpdate(xout); } xout.EndElement(); } } - -void cmCPackIFWRepository::WriteGeneratedByToStrim(cmXMLWriter& xout) -{ - if (Generator) { - Generator->WriteGeneratedByToStrim(xout); - } -} diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h index 36f46da48..227cfae7a 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.h +++ b/Source/CPack/IFW/cmCPackIFWRepository.h @@ -3,18 +3,19 @@ #ifndef cmCPackIFWRepository_h #define cmCPackIFWRepository_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmCPackIFWCommon.h" #include #include -class cmCPackIFWGenerator; class cmXMLWriter; /** \class cmCPackIFWRepository * \brief A remote repository to be created CPack IFW generator */ -class cmCPackIFWRepository +class cmCPackIFWRepository : public cmCPackIFWCommon { public: // Types @@ -72,13 +73,6 @@ public: bool IsValid() const; - const char* GetOption(const std::string& op) const; - bool IsOn(const std::string& op) const; - - bool IsVersionLess(const char* version); - bool IsVersionGreater(const char* version); - bool IsVersionEqual(const char* version); - bool ConfigureFromOptions(); bool PatchUpdatesXml(); @@ -87,12 +81,8 @@ public: void WriteRepositoryUpdate(cmXMLWriter& xout); void WriteRepositoryUpdates(cmXMLWriter& xout); - cmCPackIFWGenerator* Generator; RepositoriesVector RepositoryUpdate; std::string Directory; - -protected: - void WriteGeneratedByToStrim(cmXMLWriter& xout); }; #endif // cmCPackIFWRepository_h diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx index b159e64f3..b48bf1214 100644 --- a/Source/CPack/OSXScriptLauncher.cxx +++ b/Source/CPack/OSXScriptLauncher.cxx @@ -1,8 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/Process.h" +#include "cmsys/SystemTools.hxx" #include #include #include @@ -20,7 +20,6 @@ int main(int argc, char* argv[]) { // if ( cmsys::SystemTools::FileExists( - std::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory(); cmsys::ofstream ofs("/tmp/output.txt"); CFStringRef fileName; @@ -86,8 +85,6 @@ int main(int argc, char* argv[]) int length; while (cmsysProcess_WaitForData(cp, &data, &length, 0)) { // Translate NULL characters in the output into valid text. - // Visual Studio 7 puts these characters in the output of its - // build process. for (int i = 0; i < length; ++i) { if (data[i] == '\0') { data[i] = ' '; diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 2bccf2eea..274dfd0ce 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -2,14 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackWIXGenerator.h" -#include -#include +#include "cmCPackComponentGroup.h" +#include "cmCPackLog.h" +#include "cmCryptoHash.h" +#include "cmGeneratedFileStream.h" +#include "cmInstalledFile.h" +#include "cmSystemTools.h" +#include "cmUuid.h" #include -#include -#include -#include -#include -#include #include "cmWIXDirectoriesSourceWriter.h" #include "cmWIXFeaturesSourceWriter.h" @@ -17,10 +17,10 @@ #include "cmWIXRichTextFormatWriter.h" #include "cmWIXSourceWriter.h" -#include -#include -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/Encoding.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/SystemTools.hxx" #include // for GUID generation @@ -437,8 +437,8 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() directoryDefinitions.AddAttribute("Name", "SourceDir"); size_t installRootSize = - directoryDefinitions.BeginInstallationPrefixDirectory( - GetProgramFilesFolderId(), installRoot); + directoryDefinitions.BeginInstallationPrefixDirectory(GetRootFolderId(), + installRoot); std::string fileDefinitionsFilename = this->CPackTopLevel + "/files.wxs"; @@ -570,16 +570,26 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return this->Patch->CheckForUnappliedFragments(); } -std::string cmCPackWIXGenerator::GetProgramFilesFolderId() const +std::string cmCPackWIXGenerator::GetRootFolderId() const { if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) { return ""; } + + std::string result = "ProgramFiles<64>Folder"; + + const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); + if (rootFolderId) { + result = rootFolderId; + } + if (GetArchitecture() == "x86") { - return "ProgramFilesFolder"; + cmSystemTools::ReplaceString(result, "<64>", ""); } else { - return "ProgramFiles64Folder"; + cmSystemTools::ReplaceString(result, "<64>", "64"); } + + return result; } bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() @@ -667,10 +677,10 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( cpackPackageDesktopLinksList); } - AddDirectoryAndFileDefinitons(rootPath, "INSTALL_ROOT", directoryDefinitions, - fileDefinitions, featureDefinitions, - cpackPackageExecutablesList, - cpackPackageDesktopLinksList, shortcuts); + AddDirectoryAndFileDefinitions( + rootPath, "INSTALL_ROOT", directoryDefinitions, fileDefinitions, + featureDefinitions, cpackPackageExecutablesList, + cpackPackageDesktopLinksList, shortcuts); featureDefinitions.EndElement("FeatureRef"); @@ -831,7 +841,7 @@ bool cmCPackWIXGenerator::CreateLicenseFile() return true; } -void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( +void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions( std::string const& topdir, std::string const& directoryId, cmWIXDirectoriesSourceWriter& directoryDefinitions, cmWIXFilesSourceWriter& fileDefinitions, @@ -896,12 +906,12 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons( directoryDefinitions.BeginElement("Directory"); directoryDefinitions.AddAttribute("Id", subDirectoryId); directoryDefinitions.AddAttribute("Name", fileName); + this->Patch->ApplyFragment(subDirectoryId, directoryDefinitions); - AddDirectoryAndFileDefinitons( + AddDirectoryAndFileDefinitions( fullPath, subDirectoryId, directoryDefinitions, fileDefinitions, featureDefinitions, packageExecutables, desktopExecutables, shortcuts); - this->Patch->ApplyFragment(subDirectoryId, directoryDefinitions); directoryDefinitions.EndElement("Directory"); } else { cmInstalledFile const* installedFile = this->GetInstalledFile( diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index fc0994c2f..b2633a7f9 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackWIXGenerator_h #define cmCPackWIXGenerator_h -#include +#include "cmCPackGenerator.h" #include "cmWIXPatch.h" #include "cmWIXShortcut.h" @@ -65,7 +65,7 @@ private: bool CreateWiXSourceFiles(); - std::string GetProgramFilesFolderId() const; + std::string GetRootFolderId() const; bool GenerateMainSourceFileFromTemplate(); @@ -104,7 +104,7 @@ private: bool RunLightCommand(std::string const& objectFiles); - void AddDirectoryAndFileDefinitons( + void AddDirectoryAndFileDefinitions( std::string const& topdir, std::string const& directoryId, cmWIXDirectoriesSourceWriter& directoryDefinitions, cmWIXFilesSourceWriter& fileDefinitions, diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx index 9f9b39cc6..744a93298 100644 --- a/Source/CPack/WiX/cmWIXAccessControlList.cxx +++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXAccessControlList.h" -#include +#include "cmCPackGenerator.h" -#include +#include "cmSystemTools.h" cmWIXAccessControlList::cmWIXAccessControlList( cmCPackLog* logger, cmInstalledFile const& installedFile, diff --git a/Source/CPack/WiX/cmWIXAccessControlList.h b/Source/CPack/WiX/cmWIXAccessControlList.h index 0a25ee51c..2a23f2f37 100644 --- a/Source/CPack/WiX/cmWIXAccessControlList.h +++ b/Source/CPack/WiX/cmWIXAccessControlList.h @@ -5,8 +5,8 @@ #include "cmWIXSourceWriter.h" -#include -#include +#include "cmCPackLog.h" +#include "cmInstalledFile.h" class cmWIXAccessControlList { diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h index 062efe30b..8233331a3 100644 --- a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h +++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h @@ -5,7 +5,7 @@ #include "cmWIXSourceWriter.h" -#include +#include "cmCPackGenerator.h" #include diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx index 79a9fddef..0be43776e 100644 --- a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx @@ -44,6 +44,8 @@ void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup( AddAttributeUnlessEmpty("Title", group.DisplayName); AddAttributeUnlessEmpty("Description", group.Description); + patch.ApplyFragment("CM_G_" + group.Name, *this); + for (std::vector::const_iterator i = group.Subgroups.begin(); i != group.Subgroups.end(); ++i) { @@ -56,8 +58,6 @@ void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup( EmitFeatureForComponent(**i, patch); } - patch.ApplyFragment("CM_G_" + group.Name, *this); - EndElement("Feature"); } diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h index 368b250f3..e751ca719 100644 --- a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h +++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h @@ -6,7 +6,7 @@ #include "cmWIXPatch.h" #include "cmWIXSourceWriter.h" -#include +#include "cmCPackGenerator.h" /** \class cmWIXFeaturesSourceWriter * \brief Helper class to generate features.wxs diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx index a471d264d..b4cd1a3d6 100644 --- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx @@ -4,14 +4,12 @@ #include "cmWIXAccessControlList.h" -#include +#include "cmInstalledFile.h" -#include -#include +#include "cmSystemTools.h" +#include "cmUuid.h" -#include -// include sys/stat.h after sys/types.h -#include +#include "cm_sys_stat.h" cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger, std::string const& filename, @@ -138,6 +136,7 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile( } } + patch.ApplyFragment(componentId, *this); BeginElement("File"); AddAttribute("Id", fileId); AddAttribute("Source", filePath); @@ -149,16 +148,15 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile( if (!(fileMode & S_IWRITE)) { AddAttribute("ReadOnly", "yes"); } + patch.ApplyFragment(fileId, *this); if (installedFile) { cmWIXAccessControlList acl(Logger, *installedFile, *this); acl.Apply(); } - patch.ApplyFragment(fileId, *this); EndElement("File"); - patch.ApplyFragment(componentId, *this); EndElement("Component"); EndElement("DirectoryRef"); diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h index d7a642dd4..dc9c636d3 100644 --- a/Source/CPack/WiX/cmWIXFilesSourceWriter.h +++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h @@ -8,7 +8,7 @@ #include "cmWIXPatch.h" #include "cmWIXShortcut.h" -#include +#include "cmCPackGenerator.h" /** \class cmWIXFilesSourceWriter * \brief Helper class to generate files.wxs diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx index 7c4865324..287a644bb 100644 --- a/Source/CPack/WiX/cmWIXPatch.cxx +++ b/Source/CPack/WiX/cmWIXPatch.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXPatch.h" -#include +#include "cmCPackGenerator.h" cmWIXPatch::cmWIXPatch(cmCPackLog* logger) : Logger(logger) @@ -29,7 +29,11 @@ void cmWIXPatch::ApplyFragment(std::string const& id, return; const cmWIXPatchElement& fragment = i->second; - + for (cmWIXPatchElement::attributes_t::const_iterator attr_i = + fragment.attributes.begin(); + attr_i != fragment.attributes.end(); ++attr_i) { + writer.AddAttribute(attr_i->first, attr_i->second); + } this->ApplyElementChildren(fragment, writer); Fragments.erase(i); diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx index 47f98d1cd..0dcc74ae0 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.cxx +++ b/Source/CPack/WiX/cmWIXPatchParser.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXPatchParser.h" -#include +#include "cmCPackGenerator.h" -#include +#include "cm_expat.h" cmWIXPatchNode::Type cmWIXPatchText::type() { @@ -72,9 +72,11 @@ void cmWIXPatchParser::StartElement(const std::string& name, const char** atts) void cmWIXPatchParser::StartFragment(const char** attributes) { + cmWIXPatchElement* new_element = CM_NULLPTR; + /* find the id of for fragment */ for (size_t i = 0; attributes[i]; i += 2) { - std::string key = attributes[i]; - std::string value = attributes[i + 1]; + const std::string key = attributes[i]; + const std::string value = attributes[i + 1]; if (key == "Id") { if (Fragments.find(value) != Fragments.end()) { @@ -83,10 +85,22 @@ void cmWIXPatchParser::StartFragment(const char** attributes) ReportValidationError(tmp.str()); } - ElementStack.push_back(&Fragments[value]); - } else { - ReportValidationError( - "The only allowed 'CPackWixFragment' attribute is 'Id'"); + new_element = &Fragments[value]; + ElementStack.push_back(new_element); + } + } + + /* add any additional attributes for the fragement */ + if (!new_element) { + ReportValidationError("No 'Id' specified for 'CPackWixFragment' element"); + } else { + for (size_t i = 0; attributes[i]; i += 2) { + const std::string key = attributes[i]; + const std::string value = attributes[i + 1]; + + if (key != "Id") { + new_element->attributes[key] = value; + } } } } diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h index a2f0a3cd5..52c7e3524 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.h +++ b/Source/CPack/WiX/cmWIXPatchParser.h @@ -3,12 +3,12 @@ #ifndef cmCPackWIXPatchParser_h #define cmCPackWIXPatchParser_h -#include +#include "cmCPackLog.h" -#include +#include "cmXMLParser.h" -#include #include +#include struct cmWIXPatchNode { @@ -36,7 +36,7 @@ struct cmWIXPatchElement : cmWIXPatchNode ~cmWIXPatchElement(); - typedef std::list child_list_t; + typedef std::vector child_list_t; typedef std::map attributes_t; std::string name; @@ -84,7 +84,7 @@ private: fragment_map_t& Fragments; - std::list ElementStack; + std::vector ElementStack; }; #endif diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx index d8193470c..2c99a2284 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXRichTextFormatWriter.h" -#include +#include "cmVersion.h" cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( std::string const& filename) diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h index a3c8394b2..30df87814 100644 --- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h @@ -3,9 +3,9 @@ #ifndef cmWIXRichTextFormatWriter_h #define cmWIXRichTextFormatWriter_h -#include +#include "cmConfigure.h" -#include +#include "cmsys/FStream.hxx" #include /** \class cmWIXRichtTextFormatWriter diff --git a/Source/CPack/WiX/cmWIXShortcut.h b/Source/CPack/WiX/cmWIXShortcut.h index cba3b345c..23ddc6a3f 100644 --- a/Source/CPack/WiX/cmWIXShortcut.h +++ b/Source/CPack/WiX/cmWIXShortcut.h @@ -3,7 +3,7 @@ #ifndef cmWIXShortcut_h #define cmWIXShortcut_h -#include +#include "cmInstalledFile.h" #include #include diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx index b4343344c..a86e28d1c 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXSourceWriter.h" -#include +#include "cmCPackGenerator.h" -#include +#include "cmUuid.h" #include diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 45aefe509..4af1ed6ed 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -3,9 +3,9 @@ #ifndef cmWIXSourceWriter_h #define cmWIXSourceWriter_h -#include +#include "cmCPackLog.h" -#include +#include "cmsys/FStream.hxx" #include #include diff --git a/Source/CPack/cmCPack7zGenerator.h b/Source/CPack/cmCPack7zGenerator.h index a617d9b6a..42a47810c 100644 --- a/Source/CPack/cmCPack7zGenerator.h +++ b/Source/CPack/cmCPack7zGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPack7zGenerator_h #define cmCPack7zGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackArchiveGenerator.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 9d9cd66da..575c94924 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -7,6 +7,7 @@ #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include #include @@ -24,6 +25,28 @@ cmCPackArchiveGenerator::~cmCPackArchiveGenerator() { } +std::string cmCPackArchiveGenerator::GetArchiveComponentFileName( + const std::string& component, bool isGroupName) +{ + std::string componentUpper(cmSystemTools::UpperCase(component)); + std::string packageFileName; + + if (this->IsSet("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME")) { + packageFileName += + this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME"); + } else if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) { + packageFileName += GetComponentPackageFileName( + this->GetOption("CPACK_ARCHIVE_FILE_NAME"), component, isGroupName); + } else { + packageFileName += GetComponentPackageFileName( + this->GetOption("CPACK_PACKAGE_FILE_NAME"), component, isGroupName); + } + + packageFileName += this->GetOutputExtension(); + + return packageFileName; +} + int cmCPackArchiveGenerator::InitializeInternal() { this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); @@ -37,9 +60,8 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( // Add the files of this component to the archive std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); localToplevel += "/" + component->Name; - std::string dir = cmSystemTools::GetCurrentWorkingDirectory(); // Change to local toplevel - cmSystemTools::ChangeDirectory(localToplevel); + cmWorkingDirectory workdir(localToplevel); std::string filePrefix; if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME"); @@ -64,8 +86,6 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( return 0; } } - // Go back to previous dir - cmSystemTools::ChangeDirectory(dir); return 1; } @@ -103,11 +123,9 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " << compGIt->first << std::endl); // Begin the archive for this group - std::string packageFileName = std::string(toplevel); - packageFileName += "/" + - GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), - compGIt->first, true) + - this->GetOutputExtension(); + std::string packageFileName = std::string(toplevel) + "/" + + this->GetArchiveComponentFileName(compGIt->first, true); + // open a block in order to automatically close archive // at the end of the block { @@ -139,10 +157,9 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) std::string packageFileName = std::string(toplevel); localToplevel += "/" + compIt->first; - packageFileName += "/" + GetComponentPackageFileName( - this->GetOption("CPACK_PACKAGE_FILE_NAME"), - compIt->first, false) + - this->GetOutputExtension(); + packageFileName += + "/" + this->GetArchiveComponentFileName(compIt->first, false); + { DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive); // Add the files of this component to the archive @@ -163,10 +180,9 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup) std::string packageFileName = std::string(toplevel); localToplevel += "/" + compIt->first; - packageFileName += "/" + - GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"), - compIt->first, false) + - this->GetOutputExtension(); + packageFileName += + "/" + this->GetArchiveComponentFileName(compIt->first, false); + { DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive); // Add the files of this component to the archive @@ -184,9 +200,16 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne() // reset the package file names packageFileNames.clear(); packageFileNames.push_back(std::string(toplevel)); - packageFileNames[0] += "/" + - std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + - this->GetOutputExtension(); + packageFileNames[0] += "/"; + + if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) { + packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME"); + } else { + packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + } + + packageFileNames[0] += this->GetOutputExtension(); + cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging all groups in one package..." "(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE is set)" @@ -227,8 +250,7 @@ int cmCPackArchiveGenerator::PackageFiles() // CASE 3 : NON COMPONENT package. DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive); std::vector::const_iterator fileIt; - std::string dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(toplevel); + cmWorkingDirectory workdir(toplevel); for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) { // Get the relative path to the file std::string rp = @@ -241,7 +263,6 @@ int cmCPackArchiveGenerator::PackageFiles() return 0; } } - cmSystemTools::ChangeDirectory(dir); // The destructor of cmArchiveWrite will close and finish the write return 1; } diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h index df02ae8a8..e7116c466 100644 --- a/Source/CPack/cmCPackArchiveGenerator.h +++ b/Source/CPack/cmCPackArchiveGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackArchiveGenerator_h #define cmCPackArchiveGenerator_h -#include +#include "cmConfigure.h" #include "cmArchiveWrite.h" #include "cmCPackGenerator.h" @@ -34,6 +34,11 @@ public: // component support bool SupportsComponentInstallation() const CM_OVERRIDE; +private: + // get archive component filename + std::string GetArchiveComponentFileName(const std::string& component, + bool isGroupName); + protected: int InitializeInternal() CM_OVERRIDE; /** diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h index c9200c135..861fe4b09 100644 --- a/Source/CPack/cmCPackBundleGenerator.h +++ b/Source/CPack/cmCPackBundleGenerator.h @@ -3,7 +3,8 @@ #ifndef cmCPackBundleGenerator_h #define cmCPackBundleGenerator_h -#include +#include "cmConfigure.h" + #include #include "cmCPackDragNDropGenerator.h" diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h index f955dafbb..26d69ba68 100644 --- a/Source/CPack/cmCPackComponentGroup.h +++ b/Source/CPack/cmCPackComponentGroup.h @@ -3,7 +3,7 @@ #ifndef cmCPackComponentGroup_h #define cmCPackComponentGroup_h -#include +#include "cmConfigure.h" #include #include @@ -78,6 +78,10 @@ public: /// contains the files that are part of this component. std::string ArchiveFile; + /// The file to pass to --component-plist when using the + /// productbuild generator. + std::string Plist; + /// The components that this component depends on. std::vector Dependencies; diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx index e67811d51..2119f782b 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx @@ -9,7 +9,7 @@ #include "cmSystemTools.h" #include "cmake.h" -#include +#include "cmsys/SystemTools.hxx" cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator() { diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx index 92475d996..2c289f668 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx +++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx @@ -9,13 +9,13 @@ #include "cmSystemTools.h" #include "cmake.h" -#include +#include "cmsys/SystemTools.hxx" // Includes needed for implementation of RenameFile. This is not in // system tools because it is not implemented robustly enough to move // files across directories. #ifdef _WIN32 -#include +#include "cm_sys_stat.h" #include #endif diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 5c50da8e6..af54fce33 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -8,15 +8,15 @@ #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" +#include "cm_sys_stat.h" -#include +#include "cmsys/Glob.hxx" #include #include #include #include #include #include -#include #include // NOTE: diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h index 7db933e36..e7cde1145 100644 --- a/Source/CPack/cmCPackDebGenerator.h +++ b/Source/CPack/cmCPackDebGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackDebGenerator_h #define cmCPackDebGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index fd67df968..9864cf354 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -7,8 +7,8 @@ #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -390,6 +390,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, bool remount_image = !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty(); + std::string temp_image_format = "UDZO"; + // Create 1 MB dummy padding file in staging area when we need to remount // image, so we have enough space for storing changes ... if (remount_image) { @@ -401,6 +403,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, return 0; } + temp_image_format = "UDRW"; } // Create a temporary read-write disk image ... @@ -413,7 +416,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, temp_image_command << " -ov"; temp_image_command << " -srcfolder \"" << staging.str() << "\""; temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\""; - temp_image_command << " -format UDRW"; + temp_image_command << " -format " << temp_image_format; temp_image_command << " \"" << temp_image << "\""; if (!this->RunCommand(temp_image_command)) { @@ -632,29 +635,33 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, return 0; } - // convert to UDCO - std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - temp_udco += "/temp-udco.dmg"; + if (temp_image_format != "UDZO") { + temp_image_format = "UDZO"; + // convert to UDZO to enable unflatten/flatten + std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + temp_udzo += "/temp-udzo.dmg"; - std::ostringstream udco_image_command; - udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); - udco_image_command << " convert \"" << temp_image << "\""; - udco_image_command << " -format UDCO"; - udco_image_command << " -ov -o \"" << temp_udco << "\""; + std::ostringstream udco_image_command; + udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + udco_image_command << " convert \"" << temp_image << "\""; + udco_image_command << " -format UDZO"; + udco_image_command << " -ov -o \"" << temp_udzo << "\""; - if (!this->RunCommand(udco_image_command, &error)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error converting to UDCO dmg for adding SLA." - << std::endl - << error << std::endl); - return 0; + if (!this->RunCommand(udco_image_command, &error)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error converting to UDCO dmg for adding SLA." + << std::endl + << error << std::endl); + return 0; + } + temp_image = temp_udzo; } // unflatten dmg std::ostringstream unflatten_command; unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); unflatten_command << " unflatten "; - unflatten_command << "\"" << temp_udco << "\""; + unflatten_command << "\"" << temp_image << "\""; if (!this->RunCommand(unflatten_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -673,7 +680,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } embed_sla_command << " \"" << sla_r << "\""; embed_sla_command << " -a -o "; - embed_sla_command << "\"" << temp_udco << "\""; + embed_sla_command << "\"" << temp_image << "\""; if (!this->RunCommand(embed_sla_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding SLA." << std::endl @@ -686,7 +693,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::ostringstream flatten_command; flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); flatten_command << " flatten "; - flatten_command << "\"" << temp_udco << "\""; + flatten_command << "\"" << temp_image << "\""; if (!this->RunCommand(flatten_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -695,8 +702,6 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, << std::endl); return 0; } - - temp_image = temp_udco; } // Create the final compressed read-only disk image ... diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h index 876eab7a8..ae2cc173f 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.h +++ b/Source/CPack/cmCPackDragNDropGenerator.h @@ -3,7 +3,8 @@ #ifndef cmCPackDragNDropGenerator_h #define cmCPackDragNDropGenerator_h -#include +#include "cmConfigure.h" + #include #include #include diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 21eda790c..d8e2753cf 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -2,11 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackGenerator.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" #include -#include -#include -#include -#include #include #include "cmCPackComponentGroup.h" @@ -16,6 +15,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmStateSnapshot.h" +#include "cmWorkingDirectory.h" #include "cmXMLSafe.h" #include "cm_auto_ptr.hxx" #include "cmake.h" @@ -313,7 +313,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( const std::string& tempDir = tempInstallDirectory; for (it = installDirectoriesVector.begin(); it != installDirectoriesVector.end(); ++it) { - std::list > symlinkedFiles; + std::vector > symlinkedFiles; cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl); cmsys::Glob gl; std::string top = *it; @@ -377,13 +377,14 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( } /* rebuild symlinks in the installed tree */ if (!symlinkedFiles.empty()) { - std::list >::iterator symlinkedIt; + std::vector >::iterator + symlinkedIt; std::string curDir = cmSystemTools::GetCurrentWorkingDirectory(); std::string goToDir = tempDir; goToDir += "/" + subdir; cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir << std::endl); - cmSystemTools::ChangeDirectory(goToDir); + cmWorkingDirectory workdir(goToDir); for (symlinkedIt = symlinkedFiles.begin(); symlinkedIt != symlinkedFiles.end(); ++symlinkedIt) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: " @@ -408,7 +409,6 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir << std::endl); - cmSystemTools::ChangeDirectory(curDir); } } } @@ -620,7 +620,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( << installComponent << std::endl); } - cmake cm; + cmake cm(cmake::RoleScript); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -795,6 +795,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cmsys::Glob glA; glA.RecurseOn(); glA.SetRecurseListDirs(true); + glA.SetRecurseThroughSymlinks(false); glA.FindFiles(findExpr); std::vector filesAfter = glA.GetFiles(); std::sort(filesAfter.begin(), filesAfter.end()); @@ -810,8 +811,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( for (fit = result.begin(); fit != diff; ++fit) { localFileName = cmSystemTools::RelativePath(InstallPrefix, fit->c_str()); - localFileName = localFileName.substr( - localFileName.find_first_not_of('/'), std::string::npos); + localFileName = + localFileName.substr(localFileName.find_first_not_of('/')); Components[installComponent].Files.push_back(localFileName); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file <" << localFileName << "> to component <" @@ -1396,6 +1397,11 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->ArchiveFile = archiveFile; } + const char* plist = this->GetOption(macroPrefix + "_PLIST"); + if (plist && *plist) { + component->Plist = plist; + } + const char* groupName = this->GetOption(macroPrefix + "_GROUP"); if (groupName && *groupName) { component->Group = GetComponentGroup(projectName, groupName); diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 5354fca08..45777fa05 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackGenerator_h #define cmCPackGenerator_h -#include +#include "cmConfigure.h" #include #include @@ -13,25 +13,10 @@ #include "cmCPackComponentGroup.h" #include "cmSystemTools.h" -class cmCPackGenerator; class cmCPackLog; class cmInstalledFile; class cmMakefile; -#define cmCPackTypeMacro(klass, superclass) \ - typedef superclass Superclass; \ - const char* GetNameOfClass() CM_OVERRIDE { return #klass; } \ - static cmCPackGenerator* CreateGenerator() { return new klass; } \ - class cmCPackTypeMacro_UseTrailingSemicolon - -#define cmCPackLogger(logType, msg) \ - do { \ - std::ostringstream cmCPackLog_msg; \ - cmCPackLog_msg << msg; \ - this->Logger->Log(logType, __FILE__, __LINE__, \ - cmCPackLog_msg.str().c_str()); \ - } while (false) - /** \class cmCPackGenerator * \brief A superclass of all CPack Generators * @@ -312,4 +297,18 @@ private: cmMakefile* MakefileMap; }; +#define cmCPackTypeMacro(klass, superclass) \ + typedef superclass Superclass; \ + const char* GetNameOfClass() CM_OVERRIDE { return #klass; } \ + static cmCPackGenerator* CreateGenerator() { return new klass; } \ + class cmCPackTypeMacro_UseTrailingSemicolon + +#define cmCPackLogger(logType, msg) \ + do { \ + std::ostringstream cmCPackLog_msg; \ + cmCPackLog_msg << msg; \ + this->Logger->Log(logType, __FILE__, __LINE__, \ + cmCPackLog_msg.str().c_str()); \ + } while (false) + #endif diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index b012f01f1..31f48c7e3 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackGeneratorFactory.h" -#include +#include "cmConfigure.h" #include #include diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h index 4ee0bc14d..7f633e473 100644 --- a/Source/CPack/cmCPackGeneratorFactory.h +++ b/Source/CPack/cmCPackGeneratorFactory.h @@ -3,7 +3,7 @@ #ifndef cmCPackGeneratorFactory_h #define cmCPackGeneratorFactory_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CPack/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx index 7d5c19245..5c7123959 100644 --- a/Source/CPack/cmCPackLog.cxx +++ b/Source/CPack/cmCPackLog.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackLog.h" -#include +#include "cmConfigure.h" #include #include "cmGeneratedFileStream.h" diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h index a988ccc67..10deda450 100644 --- a/Source/CPack/cmCPackLog.h +++ b/Source/CPack/cmCPackLog.h @@ -3,7 +3,7 @@ #ifndef cmCPackLog_h #define cmCPackLog_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -85,12 +85,12 @@ public: //! Set the various prefixes for the logging. SetPrefix sets the generic // prefix that overwrittes missing ones. - void SetPrefix(std::string pfx) { this->Prefix = pfx; } - void SetOutputPrefix(std::string pfx) { this->OutputPrefix = pfx; } - void SetVerbosePrefix(std::string pfx) { this->VerbosePrefix = pfx; } - void SetDebugPrefix(std::string pfx) { this->DebugPrefix = pfx; } - void SetWarningPrefix(std::string pfx) { this->WarningPrefix = pfx; } - void SetErrorPrefix(std::string pfx) { this->ErrorPrefix = pfx; } + void SetPrefix(std::string const& pfx) { this->Prefix = pfx; } + void SetOutputPrefix(std::string const& pfx) { this->OutputPrefix = pfx; } + void SetVerbosePrefix(std::string const& pfx) { this->VerbosePrefix = pfx; } + void SetDebugPrefix(std::string const& pfx) { this->DebugPrefix = pfx; } + void SetWarningPrefix(std::string const& pfx) { this->WarningPrefix = pfx; } + void SetErrorPrefix(std::string const& pfx) { this->ErrorPrefix = pfx; } private: bool Verbose; diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 194095378..9697a3832 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -8,9 +8,9 @@ #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" +#include "cmsys/Directory.hxx" +#include "cmsys/RegularExpression.hxx" #include -#include -#include #include #include #include @@ -76,7 +76,7 @@ int cmCPackNSISGenerator::PackageFiles() } // Strip off the component part of the path. - fileN = fileN.substr(pos + 1, std::string::npos); + fileN = fileN.substr(pos + 1); } std::replace(fileN.begin(), fileN.end(), '/', '\\'); @@ -106,7 +106,7 @@ int cmCPackNSISGenerator::PackageFiles() componentName = fileN.substr(0, slash); // Strip off the component part of the path. - fileN = fileN.substr(slash + 1, std::string::npos); + fileN = fileN.substr(slash + 1); } } std::replace(fileN.begin(), fileN.end(), '/', '\\'); diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h index b4bf2d4b9..77be3256d 100644 --- a/Source/CPack/cmCPackNSISGenerator.h +++ b/Source/CPack/cmCPackNSISGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackNSISGenerator_h #define cmCPackNSISGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 0d8dc4862..8ea88a87a 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -3,12 +3,12 @@ #include "cmCPackOSXX11Generator.h" #include -#include #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" +#include "cm_sys_stat.h" cmCPackOSXX11Generator::cmCPackOSXX11Generator() { diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h index 1918e210a..0eebc6dd1 100644 --- a/Source/CPack/cmCPackOSXX11Generator.h +++ b/Source/CPack/cmCPackOSXX11Generator.h @@ -3,7 +3,8 @@ #ifndef cmCPackOSXX11Generator_h #define cmCPackOSXX11Generator_h -#include +#include "cmConfigure.h" + #include #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h index 1e96a62b8..f873c5936 100644 --- a/Source/CPack/cmCPackPKGGenerator.h +++ b/Source/CPack/cmCPackPKGGenerator.h @@ -3,7 +3,8 @@ #ifndef cmCPackPKGGenerator_h #define cmCPackPKGGenerator_h -#include +#include "cmConfigure.h" + #include #include #include diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index 8000d6e52..8db7cfb3d 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackPackageMakerGenerator.h" +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #include -#include -#include #include #include #include diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h index d4c674450..62745152b 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.h +++ b/Source/CPack/cmCPackPackageMakerGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackPackageMakerGenerator_h #define cmCPackPackageMakerGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackGenerator.h" #include "cmCPackPKGGenerator.h" diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index a5a18dcce..1389eaa5a 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -59,12 +59,25 @@ int cmCPackProductBuildGenerator::PackageFiles() } } - // Copy or create all of the resource files we need. std::string resDir = packageDirFileName + "/Contents"; + + if (this->IsSet("CPACK_PRODUCTBUILD_RESOURCES_DIR")) { + std::string userResDir = + this->GetOption("CPACK_PRODUCTBUILD_RESOURCES_DIR"); + + if (!cmSystemTools::CopyADirectory(userResDir, resDir)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files" + << std::endl); + return 0; + } + } + + // Copy or create all of the resource files we need. if (!this->CopyCreateResourceFile("License", resDir) || !this->CopyCreateResourceFile("ReadMe", resDir) || !this->CopyCreateResourceFile("Welcome", resDir)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files" + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem copying the License, ReadMe and Welcome files" << std::endl); return 0; } @@ -223,6 +236,10 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( : " --keychain \"" + keychainPath + "\"") << " \"" << packageFile << "\""; + if (component && !component->Plist.empty()) { + pkgCmd << " --component-plist \"" << component->Plist << "\""; + } + // Run ProductBuild return RunProductBuild(pkgCmd.str()); } diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h index b6da470ee..12093a0e8 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.h +++ b/Source/CPack/cmCPackProductBuildGenerator.h @@ -3,7 +3,8 @@ #ifndef cmCPackProductBuildGenerator_h #define cmCPackProductBuildGenerator_h -#include +#include "cmConfigure.h" + #include #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h index 4d48bd8fb..52cfc13ed 100644 --- a/Source/CPack/cmCPackRPMGenerator.h +++ b/Source/CPack/cmCPackRPMGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackRPMGenerator_h #define cmCPackRPMGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index 682394e4b..c54161426 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -2,19 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackSTGZGenerator.h" -#include +#include "cmsys/FStream.hxx" #include #include #include #include -#include -// include sys/stat.h after sys/types.h -#include - #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmSystemTools.h" +#include "cm_sys_stat.h" cmCPackSTGZGenerator::cmCPackSTGZGenerator() { diff --git a/Source/CPack/cmCPackSTGZGenerator.h b/Source/CPack/cmCPackSTGZGenerator.h index 4b9c1c671..8304e8076 100644 --- a/Source/CPack/cmCPackSTGZGenerator.h +++ b/Source/CPack/cmCPackSTGZGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackSTGZGenerator_h #define cmCPackSTGZGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackGenerator.h" #include "cmCPackTGZGenerator.h" diff --git a/Source/CPack/cmCPackTGZGenerator.h b/Source/CPack/cmCPackTGZGenerator.h index ee2e975a4..9426b3a01 100644 --- a/Source/CPack/cmCPackTGZGenerator.h +++ b/Source/CPack/cmCPackTGZGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackTGZGenerator_h #define cmCPackTGZGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackArchiveGenerator.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackTXZGenerator.h b/Source/CPack/cmCPackTXZGenerator.h index 876ca7d82..3b96e2d78 100644 --- a/Source/CPack/cmCPackTXZGenerator.h +++ b/Source/CPack/cmCPackTXZGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackTXZGenerator_h #define cmCPackTXZGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackArchiveGenerator.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackTarBZip2Generator.h b/Source/CPack/cmCPackTarBZip2Generator.h index 42214fdf3..9b4b8f4ff 100644 --- a/Source/CPack/cmCPackTarBZip2Generator.h +++ b/Source/CPack/cmCPackTarBZip2Generator.h @@ -3,7 +3,7 @@ #ifndef cmCPackTarBZip2Generator_h #define cmCPackTarBZip2Generator_h -#include +#include "cmConfigure.h" #include "cmCPackArchiveGenerator.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackTarCompressGenerator.h b/Source/CPack/cmCPackTarCompressGenerator.h index 1476642a8..381d6eb2f 100644 --- a/Source/CPack/cmCPackTarCompressGenerator.h +++ b/Source/CPack/cmCPackTarCompressGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackTarCompressGenerator_h #define cmCPackTarCompressGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackArchiveGenerator.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackZIPGenerator.h b/Source/CPack/cmCPackZIPGenerator.h index 95b648910..00c872029 100644 --- a/Source/CPack/cmCPackZIPGenerator.h +++ b/Source/CPack/cmCPackZIPGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackZIPGenerator_h #define cmCPackZIPGenerator_h -#include +#include "cmConfigure.h" #include "cmCPackArchiveGenerator.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index af80cbf76..a44bc3d68 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -1,9 +1,9 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include +#include "cmConfigure.h" -#include -#include +#include "cmsys/CommandLineArguments.hxx" +#include "cmsys/Encoding.hxx" #include #include #include @@ -13,7 +13,7 @@ #include #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cmsys/ConsoleBuf.hxx" #endif #include "cmCPackGenerator.h" @@ -23,7 +23,6 @@ #include "cmDocumentationEntry.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cm_auto_ptr.hxx" @@ -189,11 +188,10 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Read CPack config file: " << cpackConfigFile << std::endl); - cmake cminst; + cmake cminst(cmake::RoleScript); cminst.SetHomeDirectory(""); cminst.SetHomeOutputDirectory(""); cminst.GetCurrentSnapshot().SetDefaultDefinitions(); - cminst.GetState()->RemoveUnscriptableCommands(); cmGlobalGenerator cmgg(&cminst); CM_AUTO_PTR globalMF( new cmMakefile(&cmgg, cminst.GetCurrentSnapshot())); diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index b42953b2e..94f39c265 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -8,8 +8,8 @@ #include "cmSystemTools.h" #include "cmXMLParser.h" -#include -#include +#include "cm_expat.h" +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -151,22 +151,24 @@ std::string cmCTestBZR::LoadInfo() return rev; } -void cmCTestBZR::NoteOldRevision() +bool cmCTestBZR::NoteOldRevision() { this->OldRevision = this->LoadInfo(); this->Log << "Revision before update: " << this->OldRevision << "\n"; cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestBZR::NoteNewRevision() +bool cmCTestBZR::NoteNewRevision() { this->NewRevision = this->LoadInfo(); this->Log << "Revision after update: " << this->NewRevision << "\n"; cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); this->Log << "URL = " << this->URL << "\n"; + return true; } class cmCTestBZR::LogParser : public cmCTestVC::OutputLogger, @@ -386,7 +388,7 @@ bool cmCTestBZR::UpdateImpl() return this->RunUpdateCommand(&bzr_update[0], &out, &err); } -void cmCTestBZR::LoadRevisions() +bool cmCTestBZR::LoadRevisions() { cmCTestLog(this->CTest, HANDLER_OUTPUT, " Gathering version information (one . per revision):\n" @@ -400,7 +402,7 @@ void cmCTestBZR::LoadRevisions() // DoRevision takes care of discarding the information about OldRevision revs = this->OldRevision + ".." + this->NewRevision; } else { - return; + return true; } // Run "bzr log" to get all global revisions of interest. @@ -415,6 +417,7 @@ void cmCTestBZR::LoadRevisions() this->RunChild(bzr_log, &out, &err); } cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl); + return true; } class cmCTestBZR::StatusParser : public cmCTestVC::LineParser @@ -460,7 +463,7 @@ private: } }; -void cmCTestBZR::LoadModifications() +bool cmCTestBZR::LoadModifications() { // Run "bzr status" which reports local modifications. const char* bzr = this->CommandLineTool.c_str(); @@ -468,4 +471,5 @@ void cmCTestBZR::LoadModifications() StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunChild(bzr_status, &out, &err); + return true; } diff --git a/Source/CTest/cmCTestBZR.h b/Source/CTest/cmCTestBZR.h index e7af90b35..2e8e88f95 100644 --- a/Source/CTest/cmCTestBZR.h +++ b/Source/CTest/cmCTestBZR.h @@ -3,7 +3,7 @@ #ifndef cmCTestBZR_h #define cmCTestBZR_h -#include +#include "cmConfigure.h" #include "cmCTestGlobalVC.h" @@ -26,16 +26,16 @@ public: private: // Implement cmCTestVC internal API. - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; // URL of repository directory checked out in the working tree. std::string URL; std::string LoadInfo(); - void LoadModifications() CM_OVERRIDE; - void LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; // Parsing helper classes. class InfoParser; diff --git a/Source/CTest/cmCTestBatchTestHandler.h b/Source/CTest/cmCTestBatchTestHandler.h index 44db2528b..4a5dac1d6 100644 --- a/Source/CTest/cmCTestBatchTestHandler.h +++ b/Source/CTest/cmCTestBatchTestHandler.h @@ -3,10 +3,10 @@ #ifndef cmCTestBatchTestHandler_h #define cmCTestBatchTestHandler_h -#include +#include "cmConfigure.h" -#include -#include +#include "cmCTestMultiProcessHandler.h" +#include "cmsys/FStream.hxx" #include /** \class cmCTestBatchTestHandler diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 6780a0e91..cc290715c 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -6,9 +6,10 @@ #include "cmCTestTestHandler.h" #include "cmGlobalGenerator.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmake.h" -#include +#include "cmsys/Process.h" #include cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler() @@ -42,7 +43,7 @@ int cmCTestBuildAndTestHandler::ProcessHandler() int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, std::ostringstream& out, std::string& cmakeOutString, - std::string& cwd, cmake* cm) + cmake* cm) { unsigned int k; std::vector args; @@ -85,8 +86,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, if (cm->Run(args) != 0) { out << "Error: cmake execution failed\n"; out << cmakeOutString << "\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); if (outstring) { *outstring = out.str(); } else { @@ -99,8 +98,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, if (cm->Run(args) != 0) { out << "Error: cmake execution failed\n"; out << cmakeOutString << "\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); if (outstring) { *outstring = out.str(); } else { @@ -170,7 +167,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) return 1; } - cmake cm; + cmake cm(cmake::RoleProject); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); std::string cmakeOutString; @@ -199,13 +196,12 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) double clock_start = cmSystemTools::GetTime(); // make sure the binary dir is there - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); out << "Internal cmake changing into directory: " << this->BinaryDir << std::endl; if (!cmSystemTools::FileIsDirectory(this->BinaryDir)) { cmSystemTools::MakeDirectory(this->BinaryDir.c_str()); } - cmSystemTools::ChangeDirectory(this->BinaryDir); + cmWorkingDirectory workdir(this->BinaryDir); if (this->BuildNoCMake) { // Make the generator available for the Build call below. @@ -217,7 +213,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) cm.LoadCache(this->BinaryDir); } else { // do the cmake step, no timeout here since it is not a sub process - if (this->RunCMake(outstring, out, cmakeOutString, cwd, &cm)) { + if (this->RunCMake(outstring, out, cmakeOutString, &cm)) { return 1; } } @@ -304,8 +300,6 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) } else { cmCTestLog(this->CTest, ERROR_MESSAGE, out.str()); } - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); return 1; } diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h index 5885738e4..2e85e9fed 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.h +++ b/Source/CTest/cmCTestBuildAndTestHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestBuildAndTestHandler_h #define cmCTestBuildAndTestHandler_h -#include +#include "cmConfigure.h" #include "cmCTestGenericHandler.h" @@ -46,7 +46,7 @@ protected: ///! Run CMake and build a test and then run it as a single test. int RunCMakeAndTest(std::string* output); int RunCMake(std::string* outstring, std::ostringstream& out, - std::string& cmakeOutString, std::string& cwd, cmake* cm); + std::string& cmakeOutString, cmake* cm); std::string Output; diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index 9cc6f7e8f..9cf6a9652 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestBuildCommand_h #define cmCTestBuildCommand_h -#include +#include "cmConfigure.h" #include "cmCTestHandlerCommand.h" diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 1868a1ee7..18ef05c67 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -11,9 +11,9 @@ #include "cmSystemTools.h" #include "cmXMLWriter.h" -#include -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/Process.h" #include #include #include @@ -596,10 +596,10 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml) // At this point we need to make this->SourceFile relative to // the source root of the project, so cvs links will work cmSystemTools::ConvertToUnixSlashes(cm->SourceFile); - if (cm->SourceFile.find("/.../") != cm->SourceFile.npos) { + if (cm->SourceFile.find("/.../") != std::string::npos) { cmSystemTools::ReplaceString(cm->SourceFile, "/.../", ""); std::string::size_type p = cm->SourceFile.find('/'); - if (p != cm->SourceFile.npos) { + if (p != std::string::npos) { cm->SourceFile = cm->SourceFile.substr(p + 1, cm->SourceFile.size() - p); } diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index a2f611295..ef3cddf1b 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -3,12 +3,12 @@ #ifndef cmCTestBuildHandler_h #define cmCTestBuildHandler_h -#include +#include "cmConfigure.h" #include "cmCTestGenericHandler.h" -#include -#include +#include "cmProcessOutput.h" +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx index 98bb678f5..fad360ba4 100644 --- a/Source/CTest/cmCTestCVS.cxx +++ b/Source/CTest/cmCTestCVS.cxx @@ -7,8 +7,8 @@ #include "cmSystemTools.h" #include "cmXMLWriter.h" -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #include cmCTestCVS::cmCTestCVS(cmCTest* ct, std::ostream& log) diff --git a/Source/CTest/cmCTestCVS.h b/Source/CTest/cmCTestCVS.h index d921b1abc..1208cfad6 100644 --- a/Source/CTest/cmCTestCVS.h +++ b/Source/CTest/cmCTestCVS.h @@ -3,7 +3,7 @@ #ifndef cmCTestCVS_h #define cmCTestCVS_h -#include +#include "cmConfigure.h" #include "cmCTestVC.h" diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h index 22d12179c..917f5ab8b 100644 --- a/Source/CTest/cmCTestConfigureCommand.h +++ b/Source/CTest/cmCTestConfigureCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestConfigureCommand_h #define cmCTestConfigureCommand_h -#include +#include "cmConfigure.h" #include "cmCTestHandlerCommand.h" diff --git a/Source/CTest/cmCTestConfigureHandler.h b/Source/CTest/cmCTestConfigureHandler.h index 7fa95edea..2b452829c 100644 --- a/Source/CTest/cmCTestConfigureHandler.h +++ b/Source/CTest/cmCTestConfigureHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestConfigureHandler_h #define cmCTestConfigureHandler_h -#include +#include "cmConfigure.h" #include "cmCTestGenericHandler.h" diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h index bf42aa132..78c4f61f6 100644 --- a/Source/CTest/cmCTestCoverageCommand.h +++ b/Source/CTest/cmCTestCoverageCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestCoverageCommand_h #define cmCTestCoverageCommand_h -#include +#include "cmConfigure.h" #include "cmCTestHandlerCommand.h" diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 989c09657..877cd2445 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -12,14 +12,15 @@ #include "cmParseJacocoCoverage.h" #include "cmParsePHPCoverage.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cmake.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/Process.h" +#include "cmsys/RegularExpression.hxx" #include -#include -#include -#include -#include #include #include #include @@ -102,6 +103,7 @@ public: return this->PipeState; } int GetProcessState() { return this->PipeState; } + private: int PipeState; cmsysProcess* Process; @@ -895,7 +897,7 @@ int cmCTestCoverageHandler::HandleBlanketJSCoverage( cmsys::ifstream in(files[fileEntry].c_str()); cmSystemTools::GetLineFromStream(in, line); cmSystemTools::GetLineFromStream(in, line); - if (line.find("node-jscoverage") != line.npos) { + if (line.find("node-jscoverage") != std::string::npos) { blanketFiles.push_back(files[fileEntry]); } } @@ -969,9 +971,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage( std::string testingDir = this->CTest->GetBinaryDir() + "/Testing"; std::string tempDir = testingDir + "/CoverageInfo"; - std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory(); cmSystemTools::MakeDirectory(tempDir.c_str()); - cmSystemTools::ChangeDirectory(tempDir); + cmWorkingDirectory workdir(tempDir); int gcovStyle = 0; @@ -1222,7 +1223,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( // Initially all entries are -1 (not used). If we get coverage // information, increment it to 0 first. if (vec[lineIdx] < 0) { - if (cov > 0 || prefix.find('#') != prefix.npos) { + if (cov > 0 || prefix.find('#') != std::string::npos) { vec[lineIdx] = 0; } } @@ -1294,7 +1295,6 @@ int cmCTestCoverageHandler::HandleGCovCoverage( } } - cmSystemTools::ChangeDirectory(currentDirectory); return file_count; } @@ -1340,7 +1340,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage( return 0; } std::string testingDir = this->CTest->GetBinaryDir(); - std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory(); std::set missingFiles; @@ -1362,7 +1361,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage( cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "." << std::flush, this->Quiet); std::string fileDir = cmSystemTools::GetFilenamePath(*it); - cmSystemTools::ChangeDirectory(fileDir); + cmWorkingDirectory workdir(fileDir); std::string command = "\"" + lcovCommand + "\" " + lcovExtraFlags + " "; cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, @@ -1526,7 +1525,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage( // Initially all entries are -1 (not used). If we get coverage // information, increment it to 0 first. if (vec[lineIdx] < 0) { - if (cov > 0 || prefix.find('#') != prefix.npos) { + if (cov > 0 || prefix.find('#') != std::string::npos) { vec[lineIdx] = 0; } } @@ -1552,7 +1551,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage( } } - cmSystemTools::ChangeDirectory(currentDirectory); return file_count; } @@ -1591,13 +1589,8 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector& files) gl.RecurseOff(); // No need of recurse if -prof_dir${BUILD_DIR} flag is // used while compiling. gl.RecurseThroughSymlinksOff(); - std::string prevBinaryDir; std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory"); - if (cmSystemTools::ChangeDirectory(buildDir)) { - cmCTestLog(this->CTest, ERROR_MESSAGE, "Error changing directory to " - << buildDir << std::endl); - return false; - } + cmWorkingDirectory workdir(buildDir); // Run profmerge to merge all *.dyn files into dpi files if (!cmSystemTools::RunSingleCommand("profmerge")) { @@ -1605,11 +1598,9 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector& files) return false; } - prevBinaryDir = cmSystemTools::GetCurrentWorkingDirectory(); - // DPI file should appear in build directory std::string daGlob; - daGlob = prevBinaryDir; + daGlob = buildDir; daGlob += "/*.dpi"; cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " looking for dpi files in: " << daGlob << std::endl, @@ -1646,11 +1637,7 @@ int cmCTestCoverageHandler::HandleTracePyCoverage( std::string testingDir = this->CTest->GetBinaryDir() + "/Testing"; std::string tempDir = testingDir + "/CoverageInfo"; - std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory(); cmSystemTools::MakeDirectory(tempDir.c_str()); - cmSystemTools::ChangeDirectory(tempDir); - - cmSystemTools::ChangeDirectory(currentDirectory); std::vector::iterator fileIt; int file_count = 0; @@ -1737,7 +1724,6 @@ int cmCTestCoverageHandler::HandleTracePyCoverage( } ++file_count; } - cmSystemTools::ChangeDirectory(currentDirectory); return file_count; } @@ -2142,7 +2128,7 @@ bool cmCTestCoverageHandler::GetNextInt(std::string const& inputLine, std::string::size_type start = pos; pos = inputLine.find(',', start); value = atoi(inputLine.substr(start, pos).c_str()); - if (pos == inputLine.npos) { + if (pos == std::string::npos) { return true; } pos++; @@ -2156,7 +2142,7 @@ bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine( { // find the first comma std::string::size_type pos = inputLine.find(','); - if (pos == inputLine.npos) { + if (pos == std::string::npos) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing string : " << inputLine << "\n"); return false; @@ -2183,7 +2169,7 @@ bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine( return false; } // should be at the end now - if (pos != inputLine.npos) { + if (pos != std::string::npos) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing input : " << inputLine << " last pos not npos = " << pos << "\n"); } @@ -2237,7 +2223,8 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir) if (line.empty() || line[0] == '#') { // Ignore blank and comment lines. continue; - } else if (line[0] == ' ') { + } + if (line[0] == ' ') { // Label lines appear indented by one space. std::string label = line.substr(1); int id = this->GetLabelId(label); diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h index 339b5d709..933f60660 100644 --- a/Source/CTest/cmCTestCoverageHandler.h +++ b/Source/CTest/cmCTestCoverageHandler.h @@ -3,11 +3,11 @@ #ifndef cmCTestCoverageHandler_h #define cmCTestCoverageHandler_h -#include +#include "cmConfigure.h" #include "cmCTestGenericHandler.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index ab1412d59..b80ea5ade 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -5,7 +5,7 @@ #include "cmCTest.h" #include "cmSystemTools.h" -#include +#include "cmConfigure.h" #include #include @@ -143,9 +143,17 @@ bool cmCTestCurl::UploadFile(std::string const& local_file, ::curl_easy_setopt(this->Curl, CURLOPT_WRITEFUNCTION, curlWriteMemoryCallback); ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGFUNCTION, curlDebugCallback); - // Be sure to set Content-Type to satisfy fussy modsecurity rules + // Set Content-Type to satisfy fussy modsecurity rules. struct curl_slist* headers = ::curl_slist_append(CM_NULLPTR, "Content-Type: text/xml"); + // Add any additional headers that the user specified. + for (std::vector::const_iterator h = this->HttpHeaders.begin(); + h != this->HttpHeaders.end(); ++h) { + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Add HTTP Header: \"" << *h << "\"" << std::endl, + this->Quiet); + headers = ::curl_slist_append(headers, h->c_str()); + } ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, headers); std::vector responseData; std::vector debugData; @@ -203,7 +211,22 @@ bool cmCTestCurl::HttpRequest(std::string const& url, ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, (void*)&debugData); ::curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1); + // Add headers if any were specified. + struct curl_slist* headers = CM_NULLPTR; + if (!this->HttpHeaders.empty()) { + for (std::vector::const_iterator h = + this->HttpHeaders.begin(); + h != this->HttpHeaders.end(); ++h) { + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Add HTTP Header: \"" << *h << "\"" << std::endl, + this->Quiet); + headers = ::curl_slist_append(headers, h->c_str()); + } + } + + ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, headers); CURLcode res = ::curl_easy_perform(this->Curl); + ::curl_slist_free_all(headers); if (!responseData.empty()) { response = std::string(responseData.begin(), responseData.end()); diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h index cdce39338..427a39232 100644 --- a/Source/CTest/cmCTestCurl.h +++ b/Source/CTest/cmCTestCurl.h @@ -3,9 +3,9 @@ #ifndef cmCTestCurl_h #define cmCTestCurl_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep -#include +#include "cm_curl.h" #include #include @@ -23,6 +23,10 @@ public: // currently only supports CURLOPT_SSL_VERIFYPEER_OFF // and CURLOPT_SSL_VERIFYHOST_OFF void SetCurlOptions(std::vector const& args); + void SetHttpHeaders(std::vector const& v) + { + this->HttpHeaders = v; + } void SetUseHttp10On() { this->UseHttp10 = true; } void SetTimeOutSeconds(int s) { this->TimeOutSeconds = s; } void SetQuiet(bool b) { this->Quiet = b; } @@ -35,6 +39,7 @@ protected: private: cmCTest* CTest; CURL* Curl; + std::vector HttpHeaders; std::string HTTPProxyAuth; std::string HTTPProxy; curl_proxytype HTTPProxyType; diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h index 4c1438b8b..503ed234d 100644 --- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h +++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestEmptyBinaryDirectoryCommand_h #define cmCTestEmptyBinaryDirectoryCommand_h -#include +#include "cmConfigure.h" #include "cmCTestCommand.h" @@ -42,14 +42,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "ctest_empty_binary_directory"; - } }; #endif diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index d30f6b31e..230aedf3b 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestGIT.h" -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/Process.h" #include #include #include @@ -67,19 +67,21 @@ std::string cmCTestGIT::GetWorkingRevision() return rev; } -void cmCTestGIT::NoteOldRevision() +bool cmCTestGIT::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestGIT::NoteNewRevision() +bool cmCTestGIT::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); + return true; } std::string cmCTestGIT::FindGitDir() @@ -189,9 +191,9 @@ bool cmCTestGIT::UpdateByFetchAndReset() std::string line; while (sha1.empty() && cmSystemTools::GetLineFromStream(fin, line)) { this->Log << "FETCH_HEAD> " << line << "\n"; - if (line.find("\tnot-for-merge\t") == line.npos) { + if (line.find("\tnot-for-merge\t") == std::string::npos) { std::string::size_type pos = line.find('\t'); - if (pos != line.npos) { + if (pos != std::string::npos) { sha1 = line.substr(0, pos); } } @@ -607,7 +609,7 @@ private: char const cmCTestGIT::CommitParser::SectionSep[SectionCount] = { '\n', '\n', '\0' }; -void cmCTestGIT::LoadRevisions() +bool cmCTestGIT::LoadRevisions() { // Use 'git rev-list ... | git diff-tree ...' to get revisions. std::string range = this->OldRevision + ".." + this->NewRevision; @@ -634,9 +636,10 @@ void cmCTestGIT::LoadRevisions() out.Process("", 1); cmsysProcess_Delete(cp); + return true; } -void cmCTestGIT::LoadModifications() +bool cmCTestGIT::LoadModifications() { const char* git = this->CommandLineTool.c_str(); @@ -660,4 +663,5 @@ void cmCTestGIT::LoadModifications() ci != out.Changes.end(); ++ci) { this->DoModification(PathModified, ci->Path); } + return true; } diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h index a65550222..4bf8294e6 100644 --- a/Source/CTest/cmCTestGIT.h +++ b/Source/CTest/cmCTestGIT.h @@ -3,7 +3,7 @@ #ifndef cmCTestGIT_h #define cmCTestGIT_h -#include +#include "cmConfigure.h" #include "cmCTestGlobalVC.h" @@ -28,8 +28,8 @@ private: unsigned int CurrentGitVersion; unsigned int GetGitVersion(); std::string GetWorkingRevision(); - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; std::string FindGitDir(); @@ -39,8 +39,8 @@ private: bool UpdateByCustom(std::string const& custom); bool UpdateInternal(); - void LoadRevisions() CM_OVERRIDE; - void LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; // "public" needed by older Sun compilers public: diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 7638f45c9..19034c01b 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestGenericHandler.h" -#include +#include "cmConfigure.h" #include #include diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 2ebbe70c2..e881252c9 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestGenericHandler_h #define cmCTestGenericHandler_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx index 08af179cf..25294b5ae 100644 --- a/Source/CTest/cmCTestGlobalVC.cxx +++ b/Source/CTest/cmCTestGlobalVC.cxx @@ -102,14 +102,15 @@ void cmCTestGlobalVC::WriteXMLGlobal(cmXMLWriter& xml) bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml) { + bool result = true; cmCTestLog(this->CTest, HANDLER_OUTPUT, " Gathering version information (one . per revision):\n" " " << std::flush); - this->LoadRevisions(); + result = this->LoadRevisions() && result; cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl); - this->LoadModifications(); + result = this->LoadModifications() && result; this->WriteXMLGlobal(xml); @@ -119,5 +120,5 @@ bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml) this->WriteXMLDirectory(xml, di->first, di->second); } - return true; + return result; } diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h index 9a3757d49..a5273d3dd 100644 --- a/Source/CTest/cmCTestGlobalVC.h +++ b/Source/CTest/cmCTestGlobalVC.h @@ -3,7 +3,7 @@ #ifndef cmCTestGlobalVC_h #define cmCTestGlobalVC_h -#include +#include "cmConfigure.h" #include "cmCTestVC.h" @@ -64,8 +64,8 @@ protected: virtual void DoRevision(Revision const& revision, std::vector const& changes); virtual void DoModification(PathStatus status, std::string const& path); - virtual void LoadModifications() = 0; - virtual void LoadRevisions() = 0; + virtual bool LoadModifications() = 0; + virtual bool LoadRevisions() = 0; virtual void WriteXMLGlobal(cmXMLWriter& xml); void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path, diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index 8443c9335..49f9a6500 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -8,7 +8,7 @@ #include "cmSystemTools.h" #include "cmXMLParser.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include @@ -104,19 +104,21 @@ std::string cmCTestHG::GetWorkingRevision() return rev; } -void cmCTestHG::NoteOldRevision() +bool cmCTestHG::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestHG::NoteNewRevision() +bool cmCTestHG::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); + return true; } bool cmCTestHG::UpdateImpl() @@ -262,7 +264,7 @@ private: } }; -void cmCTestHG::LoadRevisions() +bool cmCTestHG::LoadRevisions() { // Use 'hg log' to get revisions in a xml format. // @@ -293,9 +295,10 @@ void cmCTestHG::LoadRevisions() OutputLogger err(this->Log, "log-err> "); this->RunChild(hg_log, &out, &err); out.Process("\n"); + return true; } -void cmCTestHG::LoadModifications() +bool cmCTestHG::LoadModifications() { // Use 'hg status' to get modified files. const char* hg = this->CommandLineTool.c_str(); @@ -303,4 +306,5 @@ void cmCTestHG::LoadModifications() StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunChild(hg_status, &out, &err); + return true; } diff --git a/Source/CTest/cmCTestHG.h b/Source/CTest/cmCTestHG.h index a81c34760..ec9eaffe8 100644 --- a/Source/CTest/cmCTestHG.h +++ b/Source/CTest/cmCTestHG.h @@ -3,7 +3,7 @@ #ifndef cmCTestHG_h #define cmCTestHG_h -#include +#include "cmConfigure.h" #include "cmCTestGlobalVC.h" @@ -26,12 +26,12 @@ public: private: std::string GetWorkingRevision(); - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; - void LoadRevisions() CM_OVERRIDE; - void LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; // Parsing helper classes. class IdentifyParser; diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index a989b1213..c99e450d0 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -6,6 +6,7 @@ #include "cmCTestGenericHandler.h" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmake.h" #include @@ -123,8 +124,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, if (capureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); - const char* err = this->GetError(); - if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + std::string const err = this->GetName() + " " + this->GetError(); + if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); } // return success because failure is recorded in CAPTURE_CMAKE_ERROR @@ -216,8 +217,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX])); } } - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory( + cmWorkingDirectory workdir( this->CTest->GetCTestConfiguration("BuildDirectory")); int res = handler->ProcessHandler(); if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) { @@ -243,7 +243,6 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], returnString); } - cmSystemTools::ChangeDirectory(current_dir); return true; } diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h index c86841f64..0ea061225 100644 --- a/Source/CTest/cmCTestHandlerCommand.h +++ b/Source/CTest/cmCTestHandlerCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestHandlerCommand_h #define cmCTestHandlerCommand_h -#include +#include "cmConfigure.h" #include "cmCTestCommand.h" @@ -24,6 +24,11 @@ class cmCTestHandlerCommand : public cmCTestCommand public: cmCTestHandlerCommand(); + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual std::string GetName() const = 0; + /** * This is called when the command is first encountered in * the CMakeLists.txt file. diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 03e031943..5b213518a 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -2,11 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestLaunch.h" -#include +#include "cmConfigure.h" -#include -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/Process.h" +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -306,7 +306,8 @@ void cmCTestLaunch::LoadLabels() if (line.empty() || line[0] == '#') { // Ignore blank and comment lines. continue; - } else if (line[0] == ' ') { + } + if (line[0] == ' ') { // Label lines appear indented by one space. if (inTarget || inSource) { this->Labels.insert(line.c_str() + 1); @@ -622,7 +623,7 @@ int cmCTestLaunch::Main(int argc, const char* const argv[]) void cmCTestLaunch::LoadConfig() { - cmake cm; + cmake cm(cmake::RoleScript); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index fbc9e2bc1..29986ff60 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -3,9 +3,9 @@ #ifndef cmCTestLaunch_h #define cmCTestLaunch_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep -#include +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index fd7c3a9a5..b9cae3bfe 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -3,6 +3,7 @@ #include "cmCTestMemCheckCommand.h" #include +#include #include #include "cmCTest.h" diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h index 458ebb090..fa595594a 100644 --- a/Source/CTest/cmCTestMemCheckCommand.h +++ b/Source/CTest/cmCTestMemCheckCommand.h @@ -3,12 +3,10 @@ #ifndef cmCTestMemCheckCommand_h #define cmCTestMemCheckCommand_h -#include +#include "cmConfigure.h" #include "cmCTestTestCommand.h" -#include - class cmCTestGenericHandler; class cmCommand; @@ -33,11 +31,6 @@ public: return ni; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "ctest_memcheck"; } - protected: cmCTestGenericHandler* InitializeActualHandler() CM_OVERRIDE; diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 620e23724..c35f0bc70 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -7,9 +7,9 @@ #include "cmXMLParser.h" #include "cmXMLWriter.h" -#include -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -801,7 +801,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( std::vector lines; cmSystemTools::Split(str.c_str(), lines); bool unlimitedOutput = false; - if (str.find("CTEST_FULL_OUTPUT") != str.npos || + if (str.find("CTEST_FULL_OUTPUT") != std::string::npos || this->CustomMaximumFailedTestOutputSize == 0) { unlimitedOutput = true; } @@ -953,7 +953,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( std::string& theLine = lines[cc]; // check for command line arguments that are not escaped // correctly by BC - if (theLine.find("TargetArgs=") != theLine.npos) { + if (theLine.find("TargetArgs=") != std::string::npos) { // skip this because BC gets it wrong and we can't parse it } else if (!parser.ParseChunk(theLine.c_str(), theLine.size())) { cmCTestLog(this->CTest, ERROR_MESSAGE, diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index ff8b593ad..333c2e2dd 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestMemCheckHandler_h #define cmCTestMemCheckHandler_h -#include +#include "cmConfigure.h" #include "cmCTestTestHandler.h" diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index c1724ab79..2c16a0d1e 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -7,11 +7,12 @@ #include "cmCTestScriptHandler.h" #include "cmCTestTestHandler.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" +#include "cmsys/FStream.hxx" +#include "cmsys/String.hxx" +#include "cmsys/SystemInformation.hxx" #include -#include -#include -#include #include #include #include @@ -138,8 +139,7 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test) } } - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(this->Properties[test]->Directory); + cmWorkingDirectory workdir(this->Properties[test]->Directory); // Lock the resources we'll be using this->LockResources(test); @@ -163,10 +163,11 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test) this->TestRunningMap[test] = false; this->RunningCount -= GetProcessorsUsed(test); testRun->EndTest(this->Completed, this->Total, false); - this->Failed->push_back(this->Properties[test]->Name); + if (!this->Properties[test]->Disabled) { + this->Failed->push_back(this->Properties[test]->Name); + } delete testRun; } - cmSystemTools::ChangeDirectory(current_dir); } void cmCTestMultiProcessHandler::LockResources(int index) @@ -560,7 +561,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList() // In parallel test runs repeatedly move dependencies of the tests on // the current dependency level to the next level until no // further dependencies exist. - while (priorityStack.back().size()) { + while (!priorityStack.back().empty()) { TestSet& previousSet = priorityStack.back(); priorityStack.push_back(TestSet()); TestSet& currentSet = priorityStack.back(); @@ -683,9 +684,7 @@ void cmCTestMultiProcessHandler::PrintTestList() count++; cmCTestTestHandler::cmCTestTestProperties& p = *it->second; - // push working dir - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(p.Directory); + cmWorkingDirectory workdir(p.Directory); cmCTestRunTest testRun(this->TestHandler); testRun.SetIndex(p.Index); @@ -721,11 +720,13 @@ void cmCTestMultiProcessHandler::PrintTestList() std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex())) << indexStr.str(), this->Quiet); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, p.Name << std::endl, + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " " << p.Name, this->Quiet); - // pop working dir - cmSystemTools::ChangeDirectory(current_dir); + if (p.Disabled) { + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " (Disabled)", + this->Quiet); + } + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet); } cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index fe32e15d0..dccc2c896 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -3,9 +3,9 @@ #ifndef cmCTestMultiProcessHandler_h #define cmCTestMultiProcessHandler_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep -#include +#include "cmCTestTestHandler.h" #include #include #include diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 41b45a8df..c80221634 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -7,8 +7,8 @@ #include "cmProcessTools.h" #include "cmSystemTools.h" +#include "cmsys/RegularExpression.hxx" #include -#include #include #include #include @@ -369,24 +369,26 @@ std::string cmCTestP4::GetWorkingRevision() return rev; } -void cmCTestP4::NoteOldRevision() +bool cmCTestP4::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestP4::NoteNewRevision() +bool cmCTestP4::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); + return true; } -void cmCTestP4::LoadRevisions() +bool cmCTestP4::LoadRevisions() { std::vector p4_changes; SetP4Options(p4_changes); @@ -399,7 +401,7 @@ void cmCTestP4::LoadRevisions() if (this->OldRevision == "" || this->NewRevision == "") { cmCTestLog(this->CTest, HANDLER_OUTPUT, " At least one of the revisions " << "is unknown. No repository changes will be reported.\n"); - return; + return false; } range.append("@") @@ -418,7 +420,7 @@ void cmCTestP4::LoadRevisions() this->RunChild(&p4_changes[0], &out, &err); if (ChangeLists.empty()) { - return; + return true; } // p4 describe -s ...@1111111,2222222 @@ -435,9 +437,10 @@ void cmCTestP4::LoadRevisions() OutputLogger errDescribe(this->Log, "p4_describe-err> "); this->RunChild(&p4_describe[0], &outDescribe, &errDescribe); } + return true; } -void cmCTestP4::LoadModifications() +bool cmCTestP4::LoadModifications() { std::vector p4_diff; SetP4Options(p4_diff); @@ -453,6 +456,7 @@ void cmCTestP4::LoadModifications() DiffParser out(this, "p4_diff-out> "); OutputLogger err(this->Log, "p4_diff-err> "); this->RunChild(&p4_diff[0], &out, &err); + return true; } bool cmCTestP4::UpdateCustom(const std::string& custom) diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h index eadc4fbce..e234efbfb 100644 --- a/Source/CTest/cmCTestP4.h +++ b/Source/CTest/cmCTestP4.h @@ -3,7 +3,7 @@ #ifndef cmCTestP4_h #define cmCTestP4_h -#include +#include "cmConfigure.h" #include "cmCTestGlobalVC.h" @@ -51,13 +51,13 @@ private: void SetP4Options(std::vector& options); std::string GetWorkingRevision(); - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; bool UpdateCustom(const std::string& custom); - void LoadRevisions() CM_OVERRIDE; - void LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; class ChangesParser; class DescribeParser; diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.h b/Source/CTest/cmCTestReadCustomFilesCommand.h index e15559574..5989fa0fc 100644 --- a/Source/CTest/cmCTestReadCustomFilesCommand.h +++ b/Source/CTest/cmCTestReadCustomFilesCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestReadCustomFilesCommand_h #define cmCTestReadCustomFilesCommand_h -#include +#include "cmConfigure.h" #include "cmCTestCommand.h" @@ -40,11 +40,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "ctest_read_custom_files"; } }; #endif diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h index 01ed62ebc..9bd09659d 100644 --- a/Source/CTest/cmCTestRunScriptCommand.h +++ b/Source/CTest/cmCTestRunScriptCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestRunScriptCommand_h #define cmCTestRunScriptCommand_h -#include +#include "cmConfigure.h" #include "cmCTestCommand.h" @@ -41,11 +41,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "ctest_run_script"; } }; #endif diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index ac1644f0d..0c4269e3d 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -7,13 +7,14 @@ #include "cmCTestTestHandler.h" #include "cmProcess.h" #include "cmSystemTools.h" - -#include -#include -#include -#include -#include -#include +#include "cmWorkingDirectory.h" + +#include "cmConfigure.h" +#include "cm_curl.h" +#include "cm_zlib.h" +#include "cmsys/Base64.h" +#include "cmsys/Process.h" +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -166,6 +167,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) std::vector >::iterator passIt; bool forceFail = false; + bool skipped = false; bool outputTestErrorsToConsole = false; if (!this->TestProperties->RequiredRegularExpressions.empty() && this->FailedDependencies.empty()) { @@ -214,7 +216,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) if (this->TestProperties->SkipReturnCode >= 0 && this->TestProperties->SkipReturnCode == retVal) { this->TestResult.Status = cmCTestTestHandler::NOT_RUN; + std::ostringstream s; + s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode; + this->TestResult.CompletionStatus = s.str(); cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Skipped "); + skipped = true; } else if ((success && !this->TestProperties->WillFail) || (!success && this->TestProperties->WillFail)) { this->TestResult.Status = cmCTestTestHandler::COMPLETED; @@ -252,6 +258,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other"); this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT; } + } else if ("Disabled" == this->TestResult.CompletionStatus) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run (Disabled) "); } else // cmsysProcess_State_Error { cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run "); @@ -270,14 +278,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) *this->TestHandler->LogFile << "Test time = " << buf << std::endl; } - // Set the working directory to the tests directory - std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(this->TestProperties->Directory); - - this->DartProcessing(); - - // restore working directory - cmSystemTools::ChangeDirectory(oldpath); + // Set the working directory to the tests directory to process Dart files. + { + cmWorkingDirectory workdir(this->TestProperties->Directory); + this->DartProcessing(); + } // if this is doing MemCheck then all the output needs to be put into // Output since that is what is parsed by cmCTestMemCheckHandler @@ -335,7 +340,9 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) compress ? this->CompressedOutput : this->ProcessOutput; this->TestResult.CompressOutput = compress; this->TestResult.ReturnValue = this->TestProcess->GetExitValue(); - this->TestResult.CompletionStatus = "Completed"; + if (!skipped) { + this->TestResult.CompletionStatus = "Completed"; + } this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime(); this->MemCheckPostProcess(); this->ComputeWeightedCost(); @@ -346,7 +353,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) this->TestHandler->TestResults.push_back(this->TestResult); } delete this->TestProcess; - return passed; + return passed || skipped; } bool cmCTestRunTest::StartAgain() @@ -356,11 +363,8 @@ bool cmCTestRunTest::StartAgain() } this->RunAgain = false; // reset // change to tests directory - std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(this->TestProperties->Directory); + cmWorkingDirectory workdir(this->TestProperties->Directory); this->StartTest(this->TotalNumberOfTests); - // change back - cmSystemTools::ChangeDirectory(current_dir); return true; } @@ -418,6 +422,24 @@ bool cmCTestRunTest::StartTest(size_t total) << this->TestProperties->Index << ": " << this->TestProperties->Name << std::endl); this->ProcessOutput.clear(); + + // Return immediately if test is disabled + if (this->TestProperties->Disabled) { + this->TestResult.Properties = this->TestProperties; + this->TestResult.ExecutionTime = 0; + this->TestResult.CompressOutput = false; + this->TestResult.ReturnValue = -1; + this->TestResult.CompletionStatus = "Disabled"; + this->TestResult.Status = cmCTestTestHandler::NOT_RUN; + this->TestResult.TestCount = this->TestProperties->Index; + this->TestResult.Name = this->TestProperties->Name; + this->TestResult.Path = this->TestProperties->Directory; + this->TestProcess = new cmProcess; + this->TestResult.Output = "Disabled"; + this->TestResult.FullCommandLine = ""; + return false; + } + this->ComputeArguments(); std::vector& args = this->TestProperties->Args; this->TestResult.Properties = this->TestProperties; @@ -442,7 +464,7 @@ bool cmCTestRunTest::StartTest(size_t total) cmCTestLog(this->CTest, HANDLER_OUTPUT, msg << std::endl); this->TestResult.Output = msg; this->TestResult.FullCommandLine = ""; - this->TestResult.CompletionStatus = "Not Run"; + this->TestResult.CompletionStatus = "Fixture dependency failed"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; } @@ -462,7 +484,7 @@ bool cmCTestRunTest::StartTest(size_t total) cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl); this->TestResult.Output = msg; this->TestResult.FullCommandLine = ""; - this->TestResult.CompletionStatus = "Not Run"; + this->TestResult.CompletionStatus = "Missing Configuration"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; } @@ -482,7 +504,7 @@ bool cmCTestRunTest::StartTest(size_t total) "Unable to find required file: " << file << std::endl); this->TestResult.Output = "Unable to find required file: " + file; this->TestResult.FullCommandLine = ""; - this->TestResult.CompletionStatus = "Not Run"; + this->TestResult.CompletionStatus = "Required Files Missing"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; } @@ -498,7 +520,7 @@ bool cmCTestRunTest::StartTest(size_t total) "Unable to find executable: " << args[1] << std::endl); this->TestResult.Output = "Unable to find executable: " + args[1]; this->TestResult.FullCommandLine = ""; - this->TestResult.CompletionStatus = "Not Run"; + this->TestResult.CompletionStatus = "Unable to find executable"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; } @@ -574,8 +596,7 @@ void cmCTestRunTest::ComputeArguments() void cmCTestRunTest::DartProcessing() { if (!this->ProcessOutput.empty() && - this->ProcessOutput.find("ProcessOutput.npos) { + this->ProcessOutput.find("TestHandler->DartStuff.find(this->ProcessOutput.c_str())) { this->TestResult.DartString = this->TestHandler->DartStuff.match(1); // keep searching and replacing until none are left diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index ee4630a2c..d3bb2296f 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -3,7 +3,7 @@ #ifndef cmCTestRunTest_h #define cmCTestRunTest_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 410e0d45f..f60f78c21 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -9,7 +9,7 @@ #include "cmXMLParser.h" #include "cmXMLWriter.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -97,12 +97,14 @@ std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo) return rev; } -void cmCTestSVN::NoteOldRevision() +bool cmCTestSVN::NoteOldRevision() { - this->LoadRepositories(); + if (!this->LoadRepositories()) { + return false; + } - std::list::iterator itbeg = this->Repositories.begin(); - std::list::iterator itend = this->Repositories.end(); + std::vector::iterator itbeg = this->Repositories.begin(); + std::vector::iterator itend = this->Repositories.end(); for (; itbeg != itend; itbeg++) { SVNInfo& svninfo = *itbeg; svninfo.OldRevision = this->LoadInfo(svninfo); @@ -116,14 +118,17 @@ void cmCTestSVN::NoteOldRevision() // Set the global old revision to the one of the root this->OldRevision = this->RootInfo->OldRevision; this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestSVN::NoteNewRevision() +bool cmCTestSVN::NoteNewRevision() { - this->LoadRepositories(); + if (!this->LoadRepositories()) { + return false; + } - std::list::iterator itbeg = this->Repositories.begin(); - std::list::iterator itend = this->Repositories.end(); + std::vector::iterator itbeg = this->Repositories.begin(); + std::vector::iterator itend = this->Repositories.end(); for (; itbeg != itend; itbeg++) { SVNInfo& svninfo = *itbeg; svninfo.NewRevision = this->LoadInfo(svninfo); @@ -153,6 +158,7 @@ void cmCTestSVN::NoteNewRevision() // Set the global new revision to the one of the root this->NewRevision = this->RootInfo->NewRevision; + return true; } void cmCTestSVN::GuessBase(SVNInfo& svninfo, @@ -370,18 +376,20 @@ private: } }; -void cmCTestSVN::LoadRevisions() +bool cmCTestSVN::LoadRevisions() { + bool result = true; // Get revisions for all the external repositories - std::list::iterator itbeg = this->Repositories.begin(); - std::list::iterator itend = this->Repositories.end(); + std::vector::iterator itbeg = this->Repositories.begin(); + std::vector::iterator itend = this->Repositories.end(); for (; itbeg != itend; itbeg++) { SVNInfo& svninfo = *itbeg; - LoadRevisions(svninfo); + result = this->LoadRevisions(svninfo) && result; } + return result; } -void cmCTestSVN::LoadRevisions(SVNInfo& svninfo) +bool cmCTestSVN::LoadRevisions(SVNInfo& svninfo) { // We are interested in every revision included in the update. std::string revs; @@ -400,7 +408,7 @@ void cmCTestSVN::LoadRevisions(SVNInfo& svninfo) svn_log.push_back(svninfo.LocalPath.c_str()); LogParser out(this, "log-out> ", svninfo); OutputLogger err(this->Log, "log-err> "); - this->RunSVNCommand(svn_log, &out, &err); + return this->RunSVNCommand(svn_log, &out, &err); } void cmCTestSVN::DoRevisionSVN(Revision const& revision, @@ -468,7 +476,7 @@ private: } }; -void cmCTestSVN::LoadModifications() +bool cmCTestSVN::LoadModifications() { // Run "svn status" which reports local modifications. std::vector svn_status; @@ -476,6 +484,7 @@ void cmCTestSVN::LoadModifications() StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunSVNCommand(svn_status, &out, &err); + return true; } void cmCTestSVN::WriteXMLGlobal(cmXMLWriter& xml) @@ -521,10 +530,10 @@ private: } }; -void cmCTestSVN::LoadRepositories() +bool cmCTestSVN::LoadRepositories() { if (!this->Repositories.empty()) { - return; + return true; } // Info for root repository @@ -536,7 +545,7 @@ void cmCTestSVN::LoadRepositories() svn_status.push_back("status"); ExternalParser out(this, "external-out> "); OutputLogger err(this->Log, "external-err> "); - this->RunSVNCommand(svn_status, &out, &err); + return this->RunSVNCommand(svn_status, &out, &err); } std::string cmCTestSVN::SVNInfo::BuildLocalPath(std::string const& path) const diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index c0348c2c2..46b077835 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -3,12 +3,11 @@ #ifndef cmCTestSVN_h #define cmCTestSVN_h -#include +#include "cmConfigure.h" #include "cmCTestGlobalVC.h" #include -#include #include #include @@ -30,8 +29,8 @@ public: private: // Implement cmCTestVC internal API. void CleanupImpl() CM_OVERRIDE; - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; bool RunSVNCommand(std::vector const& parameters, @@ -71,16 +70,16 @@ private: friend struct Revision; // Info of all the repositories (root, externals and nested ones). - std::list Repositories; + std::vector Repositories; // Pointer to the infos of the root repository. SVNInfo* RootInfo; std::string LoadInfo(SVNInfo& svninfo); - void LoadRepositories(); - void LoadModifications() CM_OVERRIDE; - void LoadRevisions() CM_OVERRIDE; - void LoadRevisions(SVNInfo& svninfo); + bool LoadRepositories(); + bool LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; + bool LoadRevisions(SVNInfo& svninfo); void GuessBase(SVNInfo& svninfo, std::vector const& changes); diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index b537242aa..1d29dfac2 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestScriptHandler.h" -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/Process.h" #include #include #include @@ -166,12 +166,12 @@ void cmCTestScriptHandler::UpdateElapsedTime() } } -void cmCTestScriptHandler::AddCTestCommand(cmCTestCommand* command) +void cmCTestScriptHandler::AddCTestCommand(std::string const& name, + cmCTestCommand* command) { - cmCTestCommand* newCom = command; - newCom->CTest = this->CTest; - newCom->CTestScriptHandler = this; - this->CMake->GetState()->AddCommand(newCom); + command->CTest = this->CTest; + command->CTestScriptHandler = this; + this->CMake->GetState()->AddBuiltinCommand(name, command); } int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) @@ -275,7 +275,7 @@ void cmCTestScriptHandler::CreateCMake() delete this->GlobalGenerator; delete this->Makefile; } - this->CMake = new cmake; + this->CMake = new cmake(cmake::RoleScript); this->CMake->SetHomeDirectory(""); this->CMake->SetHomeOutputDirectory(""); this->CMake->GetCurrentSnapshot().SetDefaultDefinitions(); @@ -290,26 +290,21 @@ void cmCTestScriptHandler::CreateCMake() this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest); - // remove all cmake commands which are not scriptable, since they can't be - // used in ctest scripts - this->CMake->GetState()->RemoveUnscriptableCommands(); - - // add any ctest specific commands, probably should have common superclass - // for ctest commands to clean this up. If a couple more commands are - // created with the same format lets do that - ken - this->AddCTestCommand(new cmCTestBuildCommand); - this->AddCTestCommand(new cmCTestConfigureCommand); - this->AddCTestCommand(new cmCTestCoverageCommand); - this->AddCTestCommand(new cmCTestEmptyBinaryDirectoryCommand); - this->AddCTestCommand(new cmCTestMemCheckCommand); - this->AddCTestCommand(new cmCTestReadCustomFilesCommand); - this->AddCTestCommand(new cmCTestRunScriptCommand); - this->AddCTestCommand(new cmCTestSleepCommand); - this->AddCTestCommand(new cmCTestStartCommand); - this->AddCTestCommand(new cmCTestSubmitCommand); - this->AddCTestCommand(new cmCTestTestCommand); - this->AddCTestCommand(new cmCTestUpdateCommand); - this->AddCTestCommand(new cmCTestUploadCommand); + this->AddCTestCommand("ctest_build", new cmCTestBuildCommand); + this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand); + this->AddCTestCommand("ctest_coverage", new cmCTestCoverageCommand); + this->AddCTestCommand("ctest_empty_binary_directory", + new cmCTestEmptyBinaryDirectoryCommand); + this->AddCTestCommand("ctest_memcheck", new cmCTestMemCheckCommand); + this->AddCTestCommand("ctest_read_custom_files", + new cmCTestReadCustomFilesCommand); + this->AddCTestCommand("ctest_run_script", new cmCTestRunScriptCommand); + this->AddCTestCommand("ctest_sleep", new cmCTestSleepCommand); + this->AddCTestCommand("ctest_start", new cmCTestStartCommand); + this->AddCTestCommand("ctest_submit", new cmCTestSubmitCommand); + this->AddCTestCommand("ctest_test", new cmCTestTestCommand); + this->AddCTestCommand("ctest_update", new cmCTestUpdateCommand); + this->AddCTestCommand("ctest_upload", new cmCTestUploadCommand); } // this sets up some variables for the script to use, creates the required diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index 47644be02..667870260 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestScriptHandler_h #define cmCTestScriptHandler_h -#include +#include "cmConfigure.h" #include "cmCTestGenericHandler.h" @@ -126,7 +126,7 @@ private: int RunConfigurationDashboard(); // Add ctest command - void AddCTestCommand(cmCTestCommand* command); + void AddCTestCommand(std::string const& name, cmCTestCommand* command); // Try to remove the binary directory once static bool TryToRemoveBinaryDirectoryOnce(const std::string& directoryPath); diff --git a/Source/CTest/cmCTestSleepCommand.h b/Source/CTest/cmCTestSleepCommand.h index 1052f76d5..f0b5f1eeb 100644 --- a/Source/CTest/cmCTestSleepCommand.h +++ b/Source/CTest/cmCTestSleepCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestSleepCommand_h #define cmCTestSleepCommand_h -#include +#include "cmConfigure.h" #include "cmCTestCommand.h" @@ -41,11 +41,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "ctest_sleep"; } }; #endif diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h index cc72d0c6b..b4943f92d 100644 --- a/Source/CTest/cmCTestStartCommand.h +++ b/Source/CTest/cmCTestStartCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestStartCommand_h #define cmCTestStartCommand_h -#include +#include "cmConfigure.h" #include "cmCTestCommand.h" @@ -54,11 +54,6 @@ public: */ bool ShouldBeQuiet() { return this->Quiet; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "ctest_start"; } - private: bool InitialCheckout(std::ostream& ofs, std::string const& sourceDir); bool CreateNewTag; diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index 5cf4ddcbc..409eb51fc 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -129,6 +129,12 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() static_cast(handler)->SelectParts(this->Parts); } + // Pass along any HTTPHEADER to the handler if this option was given. + if (!this->HttpHeaders.empty()) { + static_cast(handler)->SetHttpHeaders( + this->HttpHeaders); + } + static_cast(handler)->SetOption( "RetryDelay", this->RetryDelay.c_str()); static_cast(handler)->SetOption( @@ -182,6 +188,11 @@ bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg) } } // Arguments used by both modes. + if (arg == "HTTPHEADER") { + this->ArgumentDoing = ArgumentDoingHttpHeader; + return true; + } + if (arg == "RETRY_COUNT") { this->ArgumentDoing = ArgumentDoingRetryCount; return true; @@ -230,6 +241,11 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg) return true; } + if (this->ArgumentDoing == ArgumentDoingHttpHeader) { + this->HttpHeaders.push_back(arg); + return true; + } + if (this->ArgumentDoing == ArgumentDoingRetryCount) { this->RetryCount = arg; return true; diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index f5b52c178..cf65cdc8d 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestSubmitCommand_h #define cmCTestSubmitCommand_h -#include +#include "cmConfigure.h" #include "cmCTest.h" #include "cmCTestHandlerCommand.h" @@ -70,6 +70,7 @@ protected: ArgumentDoingRetryCount, ArgumentDoingCDashUpload, ArgumentDoingCDashUploadType, + ArgumentDoingHttpHeader, ArgumentDoingLast2 }; @@ -83,6 +84,7 @@ protected: bool CDashUpload; std::string CDashUploadFile; std::string CDashUploadType; + std::vector HttpHeaders; }; #endif diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 5e5119d50..8d62fa156 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -2,10 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestSubmitHandler.h" -#include -#include -#include -#include +#include "cm_curl.h" +#include "cm_jsoncpp_reader.h" +#include "cm_jsoncpp_value.h" +#include "cmsys/Process.h" #include #include #include @@ -19,13 +19,14 @@ #include "cmState.h" #include "cmSystemTools.h" #include "cmThirdParty.h" +#include "cmWorkingDirectory.h" #include "cmXMLParser.h" #include "cmake.h" #if defined(CTEST_USE_XMLRPC) #include "cmVersion.h" -#include -#include +#include "cm_sys_stat.h" +#include "cm_xmlrpc.h" #endif #define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120 @@ -300,9 +301,19 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, CURLcode res; FILE* ftpfile; char error_buffer[1024]; + // Set Content-Type to satisfy fussy modsecurity rules. struct curl_slist* headers = ::curl_slist_append(CM_NULLPTR, "Content-Type: text/xml"); + // Add any additional headers that the user specified. + for (std::vector::const_iterator h = this->HttpHeaders.begin(); + h != this->HttpHeaders.end(); ++h) { + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + " Add HTTP Header: \"" << *h << "\"" << std::endl, + this->Quiet); + headers = ::curl_slist_append(headers, h->c_str()); + } + /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod")); @@ -375,7 +386,6 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, ::curl_easy_setopt(curl, CURLOPT_PUT, 1); ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); - // Be sure to set Content-Type to satisfy fussy modsecurity rules ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); std::string local_file = *file; @@ -585,7 +595,7 @@ void cmCTestSubmitHandler::ParseResponse( std::string output; output.append(chunk.begin(), chunk.end()); - if (output.find("HttpHeaders); std::string dropMethod; std::string url; this->ConstructCDashURL(dropMethod, url); @@ -1519,7 +1530,6 @@ int cmCTestSubmitHandler::ProcessHandler() #endif } else if (dropMethod == "scp") { std::string url; - std::string oldWorkingDirectory; if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) { url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@"; } @@ -1528,19 +1538,16 @@ int cmCTestSubmitHandler::ProcessHandler() // change to the build directory so that we can uses a relative path // on windows since scp dosn't support "c:" a drive in the path - oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(buildDirectory); + cmWorkingDirectory workdir(buildDirectory); if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"), "Testing/" + this->CTest->GetCurrentTag(), files, prefix, url)) { - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestLog(this->CTest, ERROR_MESSAGE, " Problems when submitting via SCP" << std::endl); ofs << " Problems when submitting via SCP" << std::endl; return -1; } - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Submission successful" << std::endl, this->Quiet); ofs << " Submission successful" << std::endl; @@ -1550,22 +1557,18 @@ int cmCTestSubmitHandler::ProcessHandler() // change to the build directory so that we can uses a relative path // on windows since scp dosn't support "c:" a drive in the path - std::string oldWorkingDirectory = - cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(buildDirectory); + cmWorkingDirectory workdir(buildDirectory); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Change directory: " << buildDirectory << std::endl, this->Quiet); if (!this->SubmitUsingCP("Testing/" + this->CTest->GetCurrentTag(), files, prefix, location)) { - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestLog(this->CTest, ERROR_MESSAGE, " Problems when submitting via CP" << std::endl); ofs << " Problems when submitting via cp" << std::endl; return -1; } - cmSystemTools::ChangeDirectory(oldWorkingDirectory); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Submission successful" << std::endl, this->Quiet); ofs << " Submission successful" << std::endl; diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h index baaf8af14..2923f4f3d 100644 --- a/Source/CTest/cmCTestSubmitHandler.h +++ b/Source/CTest/cmCTestSubmitHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestSubmitHandler_h #define cmCTestSubmitHandler_h -#include +#include "cmConfigure.h" #include "cmCTest.h" #include "cmCTestGenericHandler.h" @@ -43,6 +43,11 @@ public: // handle the cdash file upload protocol int HandleCDashUploadFile(std::string const& file, std::string const& type); + void SetHttpHeaders(std::vector const& v) + { + this->HttpHeaders = v; + } + void ConstructCDashURL(std::string& dropMethod, std::string& url); private: @@ -95,6 +100,7 @@ private: bool HasWarnings; bool HasErrors; cmCTest::SetOfStrings Files; + std::vector HttpHeaders; }; #endif diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index a756188d3..075b1403a 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -20,6 +20,9 @@ cmCTestTestCommand::cmCTestTestCommand() this->Arguments[ctt_INCLUDE] = "INCLUDE"; this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL"; this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL"; + this->Arguments[ctt_EXCLUDE_FIXTURE] = "EXCLUDE_FIXTURE"; + this->Arguments[ctt_EXCLUDE_FIXTURE_SETUP] = "EXCLUDE_FIXTURE_SETUP"; + this->Arguments[ctt_EXCLUDE_FIXTURE_CLEANUP] = "EXCLUDE_FIXTURE_CLEANUP"; this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL"; this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM"; this->Arguments[ctt_STOP_TIME] = "STOP_TIME"; @@ -33,10 +36,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() const char* ctestTimeout = this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT"); - double timeout = this->CTest->GetTimeOut(); + double timeout; if (ctestTimeout) { timeout = atof(ctestTimeout); } else { + timeout = this->CTest->GetTimeOut(); if (timeout <= 0) { // By default use timeout of 10 minutes timeout = 600; @@ -75,6 +79,18 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() handler->SetOption("LabelRegularExpression", this->Values[ctt_INCLUDE_LABEL]); } + if (this->Values[ctt_EXCLUDE_FIXTURE]) { + handler->SetOption("ExcludeFixtureRegularExpression", + this->Values[ctt_EXCLUDE_FIXTURE]); + } + if (this->Values[ctt_EXCLUDE_FIXTURE_SETUP]) { + handler->SetOption("ExcludeFixtureSetupRegularExpression", + this->Values[ctt_EXCLUDE_FIXTURE_SETUP]); + } + if (this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]) { + handler->SetOption("ExcludeFixtureCleanupRegularExpression", + this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]); + } if (this->Values[ctt_PARALLEL_LEVEL]) { handler->SetOption("ParallelLevel", this->Values[ctt_PARALLEL_LEVEL]); } diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index 3250d9370..be7e7831f 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestTestCommand_h #define cmCTestTestCommand_h -#include +#include "cmConfigure.h" #include "cmCTestHandlerCommand.h" @@ -53,6 +53,9 @@ protected: ctt_INCLUDE, ctt_EXCLUDE_LABEL, ctt_INCLUDE_LABEL, + ctt_EXCLUDE_FIXTURE, + ctt_EXCLUDE_FIXTURE_SETUP, + ctt_EXCLUDE_FIXTURE_CLEANUP, ctt_PARALLEL_LEVEL, ctt_SCHEDULE_RANDOM, ctt_STOP_TIME, diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 6175e5026..674be6052 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -2,11 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestTestHandler.h" +#include "cmsys/Base64.h" +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #include -#include -#include -#include -#include #include #include #include @@ -17,6 +17,7 @@ #include #include +#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestBatchTestHandler.h" #include "cmCTestMultiProcessHandler.h" @@ -27,6 +28,7 @@ #include "cmState.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" #include "cmXMLWriter.h" #include "cm_auto_ptr.hxx" #include "cm_utf8.h" @@ -54,11 +56,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& /*unused*/) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "subdirs"; } - cmCTestTestHandler* TestHandler; }; @@ -86,22 +83,24 @@ bool cmCTestSubdirCommand::InitialPass(std::vector const& args, // No subdirectory? So what... continue; } - cmSystemTools::ChangeDirectory(fname); - const char* testFilename; - if (cmSystemTools::FileExists("CTestTestfile.cmake")) { - // does the CTestTestfile.cmake exist ? - testFilename = "CTestTestfile.cmake"; - } else if (cmSystemTools::FileExists("DartTestfile.txt")) { - // does the DartTestfile.txt exist ? - testFilename = "DartTestfile.txt"; - } else { - // No CTestTestfile? Who cares... - continue; + bool readit = false; + { + cmWorkingDirectory workdir(fname); + const char* testFilename; + if (cmSystemTools::FileExists("CTestTestfile.cmake")) { + // does the CTestTestfile.cmake exist ? + testFilename = "CTestTestfile.cmake"; + } else if (cmSystemTools::FileExists("DartTestfile.txt")) { + // does the DartTestfile.txt exist ? + testFilename = "DartTestfile.txt"; + } else { + // No CTestTestfile? Who cares... + continue; + } + fname += "/"; + fname += testFilename; + readit = this->Makefile->ReadDependentFile(fname.c_str()); } - fname += "/"; - fname += testFilename; - bool readit = this->Makefile->ReadDependentFile(fname.c_str()); - cmSystemTools::ChangeDirectory(cwd); if (!readit) { std::string m = "Could not find include file: "; m += fname; @@ -109,7 +108,6 @@ bool cmCTestSubdirCommand::InitialPass(std::vector const& args, return false; } } - cmSystemTools::ChangeDirectory(cwd); return true; } @@ -133,11 +131,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& /*unused*/) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_subdirectory"; } - cmCTestTestHandler* TestHandler; }; @@ -149,9 +142,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( return false; } - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(cwd); - std::string fname = cwd; + std::string fname = cmSystemTools::GetCurrentWorkingDirectory(); fname += "/"; fname += args[0]; @@ -159,23 +150,23 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( // No subdirectory? So what... return true; } - cmSystemTools::ChangeDirectory(fname); - const char* testFilename; - if (cmSystemTools::FileExists("CTestTestfile.cmake")) { - // does the CTestTestfile.cmake exist ? - testFilename = "CTestTestfile.cmake"; - } else if (cmSystemTools::FileExists("DartTestfile.txt")) { - // does the DartTestfile.txt exist ? - testFilename = "DartTestfile.txt"; - } else { - // No CTestTestfile? Who cares... - cmSystemTools::ChangeDirectory(cwd); - return true; + bool readit = false; + { + const char* testFilename; + if (cmSystemTools::FileExists("CTestTestfile.cmake")) { + // does the CTestTestfile.cmake exist ? + testFilename = "CTestTestfile.cmake"; + } else if (cmSystemTools::FileExists("DartTestfile.txt")) { + // does the DartTestfile.txt exist ? + testFilename = "DartTestfile.txt"; + } else { + // No CTestTestfile? Who cares... + return true; + } + fname += "/"; + fname += testFilename; + readit = this->Makefile->ReadDependentFile(fname.c_str()); } - fname += "/"; - fname += testFilename; - bool readit = this->Makefile->ReadDependentFile(fname.c_str()); - cmSystemTools::ChangeDirectory(cwd); if (!readit) { std::string m = "Could not find include file: "; m += fname; @@ -205,11 +196,6 @@ public: bool InitialPass(std::vector const& /*args*/, cmExecutionStatus& /*unused*/) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_test"; } - cmCTestTestHandler* TestHandler; }; @@ -239,15 +225,10 @@ public: /** * This is called when the command is first encountered in * the CMakeLists.txt file. - */ + */ bool InitialPass(std::vector const& /*args*/, cmExecutionStatus& /*unused*/) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "set_tests_properties"; } - cmCTestTestHandler* TestHandler; }; @@ -266,7 +247,7 @@ inline int GetNextNumber(std::string const& in, int& val, std::string::size_type& pos2) { pos2 = in.find(',', pos); - if (pos2 != in.npos) { + if (pos2 != std::string::npos) { if (pos2 - pos == 0) { val = -1; } else { @@ -292,7 +273,7 @@ inline int GetNextRealNumber(std::string const& in, double& val, std::string::size_type& pos2) { pos2 = in.find(',', pos); - if (pos2 != in.npos) { + if (pos2 != std::string::npos) { if (pos2 - pos == 0) { val = -1; } else { @@ -361,6 +342,9 @@ void cmCTestTestHandler::Initialize() this->ExcludeLabelRegularExpression = ""; this->IncludeRegExp = ""; this->ExcludeRegExp = ""; + this->ExcludeFixtureRegExp.clear(); + this->ExcludeFixtureSetupRegExp.clear(); + this->ExcludeFixtureCleanupRegExp.clear(); TestsToRunString = ""; this->UseUnion = false; @@ -438,6 +422,18 @@ int cmCTestTestHandler::ProcessHandler() this->UseExcludeRegExp(); this->SetExcludeRegExp(val); } + val = this->GetOption("ExcludeFixtureRegularExpression"); + if (val) { + this->ExcludeFixtureRegExp = val; + } + val = this->GetOption("ExcludeFixtureSetupRegularExpression"); + if (val) { + this->ExcludeFixtureSetupRegExp = val; + } + val = this->GetOption("ExcludeFixtureCleanupRegularExpression"); + if (val) { + this->ExcludeFixtureCleanupRegExp = val; + } this->SetRerunFailed(cmSystemTools::IsOn(this->GetOption("RerunFailed"))); this->TestResults.clear(); @@ -487,6 +483,20 @@ int cmCTestTestHandler::ProcessHandler() } } + typedef std::set + SetOfTests; + SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end()); + std::vector disabledTests; + + for (SetOfTests::iterator ftit = resultsSet.begin(); + ftit != resultsSet.end(); ++ftit) { + if (cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") || + ftit->CompletionStatus == "Disabled") { + disabledTests.push_back(*ftit); + } + } + float percent = float(passed.size()) * 100.0f / float(total); if (!failed.empty() && percent > 99) { percent = 99; @@ -505,21 +515,39 @@ int cmCTestTestHandler::ProcessHandler() "\nTotal Test time (real) = " << realBuf << "\n", this->Quiet); + if (!disabledTests.empty()) { + cmGeneratedFileStream ofs; + cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl + << "The following tests did not run:" << std::endl); + this->StartLogFile("TestsDisabled", ofs); + + const char* disabled_reason; + for (std::vector::iterator dtit = + disabledTests.begin(); + dtit != disabledTests.end(); ++dtit) { + ofs << dtit->TestCount << ":" << dtit->Name << std::endl; + if (dtit->CompletionStatus == "Disabled") { + disabled_reason = "Disabled"; + } else { + disabled_reason = "Skipped"; + } + cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t" + << std::setw(3) << dtit->TestCount << " - " << dtit->Name + << " (" << disabled_reason << ")" << std::endl); + } + } + if (!failed.empty()) { cmGeneratedFileStream ofs; cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl << "The following tests FAILED:" << std::endl); this->StartLogFile("TestsFailed", ofs); - typedef std::set - SetOfTests; - SetOfTests resultsSet(this->TestResults.begin(), - this->TestResults.end()); - for (SetOfTests::iterator ftit = resultsSet.begin(); ftit != resultsSet.end(); ++ftit) { - if (ftit->Status != cmCTestTestHandler::COMPLETED) { + if (ftit->Status != cmCTestTestHandler::COMPLETED && + !cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") && + ftit->CompletionStatus != "Disabled") { ofs << ftit->TestCount << ":" << ftit->Name << std::endl; cmCTestLog( this->CTest, HANDLER_OUTPUT, "\t" @@ -795,13 +823,35 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const "Updating test list for fixtures" << std::endl, this->Quiet); + // Prepare regular expression evaluators + std::string setupRegExp(this->ExcludeFixtureRegExp); + std::string cleanupRegExp(this->ExcludeFixtureRegExp); + if (!this->ExcludeFixtureSetupRegExp.empty()) { + if (setupRegExp.empty()) { + setupRegExp = this->ExcludeFixtureSetupRegExp; + } else { + setupRegExp.append("(" + setupRegExp + ")|(" + + this->ExcludeFixtureSetupRegExp + ")"); + } + } + if (!this->ExcludeFixtureCleanupRegExp.empty()) { + if (cleanupRegExp.empty()) { + cleanupRegExp = this->ExcludeFixtureCleanupRegExp; + } else { + cleanupRegExp.append("(" + cleanupRegExp + ")|(" + + this->ExcludeFixtureCleanupRegExp + ")"); + } + } + cmsys::RegularExpression excludeSetupRegex(setupRegExp); + cmsys::RegularExpression excludeCleanupRegex(cleanupRegExp); + // Prepare some maps to help us find setup and cleanup tests for // any given fixture typedef ListOfTests::const_iterator TestIterator; typedef std::multimap FixtureDependencies; typedef FixtureDependencies::const_iterator FixtureDepsIterator; FixtureDependencies fixtureSetups; - FixtureDependencies fixtureDeps; + FixtureDependencies fixtureCleanups; for (ListOfTests::const_iterator it = this->TestList.begin(); it != this->TestList.end(); ++it) { @@ -811,13 +861,12 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const for (std::set::const_iterator depsIt = setups.begin(); depsIt != setups.end(); ++depsIt) { fixtureSetups.insert(std::make_pair(*depsIt, it)); - fixtureDeps.insert(std::make_pair(*depsIt, it)); } const std::set& cleanups = p.FixturesCleanup; for (std::set::const_iterator depsIt = cleanups.begin(); depsIt != cleanups.end(); ++depsIt) { - fixtureDeps.insert(std::make_pair(*depsIt, it)); + fixtureCleanups.insert(std::make_pair(*depsIt, it)); } } @@ -841,6 +890,11 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const size_t fixtureTestsAdded = 0; std::set addedFixtures; for (size_t i = 0; i < tests.size(); ++i) { + // Skip disabled tests + if (tests[i].Disabled) { + continue; + } + // There are two things to do for each test: // 1. For every fixture required by this test, record that fixture as // being required and create dependencies on that fixture's setup @@ -886,34 +940,72 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const // added from a previously checked test). A fixture isn't required // to have setup/cleanup tests. if (!addedFixtures.insert(requiredFixtureName).second) { - // Already added this fixture + // Already seen this fixture, no need to check it again continue; } - std::pair fixtureRange = - fixtureDeps.equal_range(requiredFixtureName); - for (FixtureDepsIterator it = fixtureRange.first; - it != fixtureRange.second; ++it) { - ListOfTests::const_iterator lotIt = it->second; - const cmCTestTestProperties& p = *lotIt; - - if (!addedTests.insert(p.Name).second) { - // Already have p in our test list - continue; + + // Only add setup tests if this fixture has not been excluded + if (setupRegExp.empty() || + !excludeSetupRegex.find(requiredFixtureName)) { + std::pair fixtureRange = + fixtureSetups.equal_range(requiredFixtureName); + for (FixtureDepsIterator it = fixtureRange.first; + it != fixtureRange.second; ++it) { + ListOfTests::const_iterator lotIt = it->second; + const cmCTestTestProperties& p = *lotIt; + + if (!addedTests.insert(p.Name).second) { + // Already have p in our test list + continue; + } + + // This is a test not yet in our list, so add it and + // update its index to reflect where it was in the original + // full list of all tests (needed to track individual tests + // across ctest runs for re-run failed, etc.) + tests.push_back(p); + tests.back().Index = + 1 + static_cast(std::distance(this->TestList.begin(), lotIt)); + ++fixtureTestsAdded; + + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Added setup test " + << p.Name << " required by fixture " + << requiredFixtureName << std::endl, + this->Quiet); } + } - // This is a test not yet in our list, so add it and - // update its index to reflect where it was in the original - // full list of all tests (needed to track individual tests - // across ctest runs for re-run failed, etc.) - tests.push_back(p); - tests.back().Index = - 1 + static_cast(std::distance(this->TestList.begin(), lotIt)); - ++fixtureTestsAdded; - - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Added test " - << p.Name << " required by fixture " - << requiredFixtureName << std::endl, - this->Quiet); + // Only add cleanup tests if this fixture has not been excluded + if (cleanupRegExp.empty() || + !excludeCleanupRegex.find(requiredFixtureName)) { + std::pair fixtureRange = + fixtureCleanups.equal_range(requiredFixtureName); + for (FixtureDepsIterator it = fixtureRange.first; + it != fixtureRange.second; ++it) { + ListOfTests::const_iterator lotIt = it->second; + const cmCTestTestProperties& p = *lotIt; + + if (!addedTests.insert(p.Name).second) { + // Already have p in our test list + continue; + } + + // This is a test not yet in our list, so add it and + // update its index to reflect where it was in the original + // full list of all tests (needed to track individual tests + // across ctest runs for re-run failed, etc.) + tests.push_back(p); + tests.back().Index = + 1 + static_cast(std::distance(this->TestList.begin(), lotIt)); + ++fixtureTestsAdded; + + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Added cleanup test " + << p.Name << " required by fixture " + << requiredFixtureName << std::endl, + this->Quiet); + } } } @@ -1200,6 +1292,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) cmCTestTestResult* result = &this->TestResults[cc]; this->WriteTestResultHeader(xml, result); xml.StartElement("Results"); + if (result->Status != cmCTestTestHandler::NOT_RUN) { if (result->Status != cmCTestTestHandler::COMPLETED || result->ReturnValue) { @@ -1208,6 +1301,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Attribute("name", "Exit Code"); xml.Element("Value", this->GetTestStatus(result->Status)); xml.EndElement(); // NamedMeasurement + xml.StartElement("NamedMeasurement"); xml.Attribute("type", "text/string"); xml.Attribute("name", "Exit Value"); @@ -1222,8 +1316,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.EndElement(); // NamedMeasurement if (!result->Reason.empty()) { const char* reasonType = "Pass Reason"; - if (result->Status != cmCTestTestHandler::COMPLETED && - result->Status != cmCTestTestHandler::NOT_RUN) { + if (result->Status != cmCTestTestHandler::COMPLETED) { reasonType = "Fail Reason"; } xml.StartElement("NamedMeasurement"); @@ -1232,12 +1325,14 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Element("Value", result->Reason); xml.EndElement(); // NamedMeasurement } - xml.StartElement("NamedMeasurement"); - xml.Attribute("type", "text/string"); - xml.Attribute("name", "Completion Status"); - xml.Element("Value", result->CompletionStatus); - xml.EndElement(); // NamedMeasurement } + + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", "Completion Status"); + xml.Element("Value", result->CompletionStatus); + xml.EndElement(); // NamedMeasurement + xml.StartElement("NamedMeasurement"); xml.Attribute("type", "text/string"); xml.Attribute("name", "Command Line"); @@ -1535,7 +1630,7 @@ void cmCTestTestHandler::GetListOfTests() } cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Constructing a list of tests" << std::endl, this->Quiet); - cmake cm; + cmake cm(cmake::RoleScript); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -1547,23 +1642,23 @@ void cmCTestTestHandler::GetListOfTests() // Add handler for ADD_TEST cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand; newCom1->TestHandler = this; - cm.GetState()->AddCommand(newCom1); + cm.GetState()->AddBuiltinCommand("add_test", newCom1); // Add handler for SUBDIRS cmCTestSubdirCommand* newCom2 = new cmCTestSubdirCommand; newCom2->TestHandler = this; - cm.GetState()->AddCommand(newCom2); + cm.GetState()->AddBuiltinCommand("subdirs", newCom2); // Add handler for ADD_SUBDIRECTORY cmCTestAddSubdirectoryCommand* newCom3 = new cmCTestAddSubdirectoryCommand; newCom3->TestHandler = this; - cm.GetState()->AddCommand(newCom3); + cm.GetState()->AddBuiltinCommand("add_subdirectory", newCom3); - // Add handler for SET_SOURCE_FILES_PROPERTIES + // Add handler for SET_TESTS_PROPERTIES cmCTestSetTestsPropertiesCommand* newCom4 = new cmCTestSetTestsPropertiesCommand; newCom4->TestHandler = this; - cm.GetState()->AddCommand(newCom4); + cm.GetState()->AddBuiltinCommand("set_tests_properties", newCom4); const char* testFilename; if (cmSystemTools::FileExists("CTestTestfile.cmake")) { @@ -1600,10 +1695,10 @@ void cmCTestTestHandler::UseExcludeRegExp() const char* cmCTestTestHandler::GetTestStatus(int status) { - static const char statuses[][100] = { - "Not Run", "Timeout", "SEGFAULT", "ILLEGAL", "INTERRUPT", - "NUMERICAL", "OTHER_FAULT", "Failed", "BAD_COMMAND", "Completed" - }; + static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT", + "ILLEGAL", "INTERRUPT", "NUMERICAL", + "OTHER_FAULT", "Failed", "BAD_COMMAND", + "Completed" }; if (status < cmCTestTestHandler::NOT_RUN || status > cmCTestTestHandler::COMPLETED) { @@ -1694,7 +1789,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() // bcc crashes if we attempt a normal substring comparison, // hence the following workaround std::string fileNameSubstring = fileName.substr(0, pattern.length()); - if (fileNameSubstring.compare(pattern) != 0) { + if (fileNameSubstring != pattern) { continue; } if (logName == "") { @@ -1728,7 +1823,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() std::string::size_type pos; while (cmSystemTools::GetLineFromStream(ifs, line)) { pos = line.find(':', 0); - if (pos == line.npos) { + if (pos == std::string::npos) { continue; } @@ -1932,7 +2027,7 @@ void cmCTestTestHandler::SetTestsToRunInformation(const char* in) bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length) { if (!length || length >= output.size() || - output.find("CTEST_FULL_OUTPUT") != output.npos) { + output.find("CTEST_FULL_OUTPUT") != std::string::npos) { return true; } @@ -2000,6 +2095,9 @@ bool cmCTestTestHandler::SetTestsProperties( if (key == "WILL_FAIL") { rtit->WillFail = cmSystemTools::IsOn(val.c_str()); } + if (key == "DISABLED") { + rtit->Disabled = cmSystemTools::IsOn(val.c_str()); + } if (key == "ATTACHED_FILES") { cmSystemTools::ExpandListArgument(val, rtit->AttachedFiles); } @@ -2077,7 +2175,7 @@ bool cmCTestTestHandler::SetTestsProperties( } if (key == "MEASUREMENT") { size_t pos = val.find_first_of('='); - if (pos != val.npos) { + if (pos != std::string::npos) { std::string mKey = val.substr(0, pos); const char* mVal = val.c_str() + pos + 1; rtit->Measurements[mKey] = mVal; @@ -2178,6 +2276,7 @@ bool cmCTestTestHandler::AddTest(const std::vector& args) test.IsInBasedOnREOptions = true; test.WillFail = false; + test.Disabled = false; test.RunSerial = false; test.Timeout = 0; test.ExplicitTimeout = false; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 5b07e98c4..0edcb143a 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -3,11 +3,11 @@ #ifndef cmCTestTestHandler_h #define cmCTestTestHandler_h -#include +#include "cmConfigure.h" #include "cmCTestGenericHandler.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -114,6 +114,7 @@ public: std::map Measurements; bool IsInBasedOnREOptions; bool WillFail; + bool Disabled; float Cost; int PreviousRuns; bool RunSerial; @@ -279,6 +280,9 @@ private: std::string ExcludeLabelRegExp; std::string IncludeRegExp; std::string ExcludeRegExp; + std::string ExcludeFixtureRegExp; + std::string ExcludeFixtureSetupRegExp; + std::string ExcludeFixtureCleanupRegExp; cmsys::RegularExpression IncludeLabelRegularExpression; cmsys::RegularExpression ExcludeLabelRegularExpression; cmsys::RegularExpression IncludeTestsRegularExpression; diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h index 5761f50ff..3b8f0a641 100644 --- a/Source/CTest/cmCTestUpdateCommand.h +++ b/Source/CTest/cmCTestUpdateCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestUpdateCommand_h #define cmCTestUpdateCommand_h -#include +#include "cmConfigure.h" #include "cmCTestHandlerCommand.h" diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 0998d5976..e08a9b7bd 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -16,7 +16,7 @@ #include "cmVersion.h" #include "cmXMLWriter.h" -#include +#include "cm_auto_ptr.hxx" #include static const char* cmCTestUpdateHandlerUpdateStrings[] = { @@ -198,7 +198,7 @@ int cmCTestUpdateHandler::ProcessHandler() xml.Element("UpdateType", cmCTestUpdateHandlerUpdateToString(this->UpdateType)); - vc->WriteXML(xml); + bool loadedMods = vc->WriteXML(xml); int localModifications = 0; int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated); @@ -246,7 +246,7 @@ int cmCTestUpdateHandler::ProcessHandler() xml.EndElement(); // UpdateReturnStatus xml.EndElement(); // Update xml.EndDocument(); - return updated ? numUpdated : -1; + return updated && loadedMods ? numUpdated : -1; } int cmCTestUpdateHandler::DetectVCS(const char* dir) diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h index 87781e8f5..0cd284421 100644 --- a/Source/CTest/cmCTestUpdateHandler.h +++ b/Source/CTest/cmCTestUpdateHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestUpdateHandler_h #define cmCTestUpdateHandler_h -#include +#include "cmConfigure.h" #include "cmCTestGenericHandler.h" diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h index 474f6991e..6e721796a 100644 --- a/Source/CTest/cmCTestUploadCommand.h +++ b/Source/CTest/cmCTestUploadCommand.h @@ -3,7 +3,7 @@ #ifndef cmCTestUploadCommand_h #define cmCTestUploadCommand_h -#include +#include "cmConfigure.h" #include "cmCTest.h" #include "cmCTestHandlerCommand.h" diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h index 77c2aec3b..1e8d3c801 100644 --- a/Source/CTest/cmCTestUploadHandler.h +++ b/Source/CTest/cmCTestUploadHandler.h @@ -3,7 +3,7 @@ #ifndef cmCTestUploadHandler_h #define cmCTestUploadHandler_h -#include +#include "cmConfigure.h" #include "cmCTest.h" #include "cmCTestGenericHandler.h" diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 444c43d55..fb2742e08 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -6,7 +6,7 @@ #include "cmSystemTools.h" #include "cmXMLWriter.h" -#include +#include "cmsys/Process.h" #include #include #include @@ -147,23 +147,25 @@ bool cmCTestVC::Update() // just note the current version and finish if (!cmSystemTools::IsOn( this->CTest->GetCTestConfiguration("UpdateVersionOnly").c_str())) { - this->NoteOldRevision(); + result = this->NoteOldRevision() && result; this->Log << "--- Begin Update ---\n"; - result = this->UpdateImpl(); + result = this->UpdateImpl() && result; this->Log << "--- End Update ---\n"; } - this->NoteNewRevision(); + result = this->NoteNewRevision() && result; return result; } -void cmCTestVC::NoteOldRevision() +bool cmCTestVC::NoteOldRevision() { // We do nothing by default. + return true; } -void cmCTestVC::NoteNewRevision() +bool cmCTestVC::NoteNewRevision() { // We do nothing by default. + return true; } bool cmCTestVC::UpdateImpl() diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 2681ba01e..6400bcda3 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -3,7 +3,7 @@ #ifndef cmCTestVC_h #define cmCTestVC_h -#include +#include "cmConfigure.h" #include #include @@ -67,9 +67,9 @@ public: protected: // Internal API to be implemented by subclasses. virtual void CleanupImpl(); - virtual void NoteOldRevision(); + virtual bool NoteOldRevision(); virtual bool UpdateImpl(); - virtual void NoteNewRevision(); + virtual bool NoteNewRevision(); virtual bool WriteXMLUpdates(cmXMLWriter& xml); #if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510 diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx index 6fa982ea2..83a7b75eb 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.cxx +++ b/Source/CTest/cmParseBlanketJSCoverage.cxx @@ -6,7 +6,7 @@ #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" -#include +#include "cmsys/FStream.hxx" #include #include @@ -22,7 +22,7 @@ public: virtual ~JSONParser() {} - std::string getValue(std::string line, int type) + std::string getValue(std::string const& line, int type) { size_t begIndex; size_t endIndex; @@ -35,7 +35,7 @@ public: line.substr(begIndex + 3, endIndex - (begIndex + 4)); return foundFileName; } - return line.substr(begIndex, line.npos); + return line.substr(begIndex); } bool ParseFile(std::string const& file) { @@ -51,13 +51,13 @@ public: return false; } while (cmSystemTools::GetLineFromStream(in, line)) { - if (line.find("filename") != line.npos) { + if (line.find("filename") != std::string::npos) { if (foundFile) { /* - * Upon finding a second file name, generate a - * vector within the total coverage to capture the - * information in the local vector - */ + * Upon finding a second file name, generate a + * vector within the total coverage to capture the + * information in the local vector + */ FileLinesType& CoverageVector = this->Coverage.TotalCoverage[filename]; CoverageVector = localCoverageVector; @@ -66,19 +66,19 @@ public: foundFile = true; inSource = false; filename = getValue(line, 0); - } else if ((line.find("coverage") != line.npos) && foundFile && + } else if ((line.find("coverage") != std::string::npos) && foundFile && inSource) { /* - * two types of "coverage" in the JSON structure - * - * The coverage result over the file or set of files - * and the coverage for each individual line - * - * FoundFile and foundSource ensure that - * only the value of the line coverage is captured - */ + * two types of "coverage" in the JSON structure + * + * The coverage result over the file or set of files + * and the coverage for each individual line + * + * FoundFile and foundSource ensure that + * only the value of the line coverage is captured + */ std::string result = getValue(line, 1); - result = result.substr(2, result.npos); + result = result.substr(2); if (result == "\"\"") { // Empty quotation marks indicate that the // line is not executable @@ -87,7 +87,7 @@ public: // Else, it contains the number of time executed localCoverageVector.push_back(atoi(result.c_str())); } - } else if (line.find("source") != line.npos) { + } else if (line.find("source") != std::string::npos) { inSource = true; } } diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h index 660590d4e..696121f21 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.h +++ b/Source/CTest/cmParseBlanketJSCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParseBlanketJSCoverage_h #define cmParseBlanketJSCoverage_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx index 23176b524..629010cf1 100644 --- a/Source/CTest/cmParseCacheCoverage.cxx +++ b/Source/CTest/cmParseCacheCoverage.cxx @@ -4,8 +4,8 @@ #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" #include #include #include diff --git a/Source/CTest/cmParseCacheCoverage.h b/Source/CTest/cmParseCacheCoverage.h index 645d7103f..005d27258 100644 --- a/Source/CTest/cmParseCacheCoverage.h +++ b/Source/CTest/cmParseCacheCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParseCacheCoverage_h #define cmParseCacheCoverage_h -#include +#include "cmConfigure.h" #include "cmParseMumpsCoverage.h" diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx index db1774846..ba55cd7b2 100644 --- a/Source/CTest/cmParseCoberturaCoverage.cxx +++ b/Source/CTest/cmParseCoberturaCoverage.cxx @@ -5,8 +5,8 @@ #include "cmSystemTools.h" #include "cmXMLParser.h" -#include -#include +#include "cmConfigure.h" +#include "cmsys/FStream.hxx" #include #include diff --git a/Source/CTest/cmParseCoberturaCoverage.h b/Source/CTest/cmParseCoberturaCoverage.h index 077eb80ad..cb6d0976b 100644 --- a/Source/CTest/cmParseCoberturaCoverage.h +++ b/Source/CTest/cmParseCoberturaCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParseCoberturaCoverage_h #define cmParseCoberturaCoverage_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx index 7fe91f4ef..4b781a6db 100644 --- a/Source/CTest/cmParseDelphiCoverage.cxx +++ b/Source/CTest/cmParseDelphiCoverage.cxx @@ -4,8 +4,8 @@ #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" #include #include @@ -42,17 +42,20 @@ public: size_t beginPos = line.find("begin"); // Check that the begin is the first non-space string on the line - if ((beginPos == line.find_first_not_of(' ')) && beginPos != line.npos) { + if ((beginPos == line.find_first_not_of(' ')) && + beginPos != std::string::npos) { beginSet.push_back("begin"); coverageVector.push_back(-1); continue; - } else if (line.find('{') != line.npos) { + } + if (line.find('{') != std::string::npos) { blockComFlag = true; - } else if (line.find('}') != line.npos) { + } else if (line.find('}') != std::string::npos) { blockComFlag = false; coverageVector.push_back(-1); continue; - } else if ((line.find("end;") != line.npos) && !beginSet.empty()) { + } else if ((line.find("end;") != std::string::npos) && + !beginSet.empty()) { beginSet.pop_back(); coverageVector.push_back(-1); continue; @@ -61,7 +64,7 @@ public: // This checks for comments after lines of code, finding the // comment symbol after the ending semicolon. comPos = line.find("//"); - if (comPos != line.npos) { + if (comPos != std::string::npos) { semiPos = line.find(';'); if (comPos < semiPos) { lineComFlag = true; @@ -90,20 +93,20 @@ public: size_t pos = 0; /* - * This first 'while' section goes through the found HTML - * file name and attempts to capture the source file name - * which is set as part of the HTML file name: the name of - * the file is found in parenthesis '()' - * - * See test HTML file name: UTCovTest(UTCovTest.pas).html. - * - * Find the text inside each pair of parenthesis and check - * to see if it ends in '.pas'. If it can't be found, - * exit the function. - */ + * This first 'while' section goes through the found HTML + * file name and attempts to capture the source file name + * which is set as part of the HTML file name: the name of + * the file is found in parenthesis '()' + * + * See test HTML file name: UTCovTest(UTCovTest.pas).html. + * + * Find the text inside each pair of parenthesis and check + * to see if it ends in '.pas'. If it can't be found, + * exit the function. + */ while (true) { lastoffset = line.find('(', pos); - if (lastoffset == line.npos) { + if (lastoffset == std::string::npos) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, endnamepos << "File not found " << lastoffset << std::endl, this->Coverage.Quiet); @@ -111,7 +114,7 @@ public: } endnamepos = line.find(')', lastoffset); filename = line.substr(lastoffset + 1, (endnamepos - 1) - lastoffset); - if (filename.find(".pas") != filename.npos) { + if (filename.find(".pas") != std::string::npos) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Coverage found for file: " << filename << std::endl, @@ -121,9 +124,9 @@ public: pos = lastoffset + 1; } /* - * Glob through the source directory for the - * file found above - */ + * Glob through the source directory for the + * file found above + */ cmsys::Glob gl; gl.RecurseOn(); gl.RecurseThroughSymlinksOff(); @@ -132,9 +135,9 @@ public: std::vector const& files = gl.GetFiles(); if (files.empty()) { /* - * If that doesn't find any matching files - * return a failure. - */ + * If that doesn't find any matching files + * return a failure. + */ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Unable to find file matching" << glob << std::endl, this->Coverage.Quiet); @@ -143,9 +146,9 @@ public: FileLinesType& coverageVector = this->Coverage.TotalCoverage[files[0]]; /* - * Initialize the file to have all code between 'begin' and - * 'end' tags marked as executable - */ + * Initialize the file to have all code between 'begin' and + * 'end' tags marked as executable + */ this->initializeDelphiFile(files[0], coverageVector); @@ -155,19 +158,19 @@ public: } /* - * Now read the HTML file, looking for the lines that have an - * "inline" in it. Then parse out the "class" value of that - * line to determine if the line is executed or not. - * - * Sample HTML line: - * - * 47
-    *     CheckEquals(1,2-1);
- * - */ + * Now read the HTML file, looking for the lines that have an + * "inline" in it. Then parse out the "class" value of that + * line to determine if the line is executed or not. + * + * Sample HTML line: + * + * 47
+     *     CheckEquals(1,2-1);
+ * + */ while (cmSystemTools::GetLineFromStream(in, line)) { - if (line.find("inline") == line.npos) { + if (line.find("inline") == std::string::npos) { continue; } diff --git a/Source/CTest/cmParseDelphiCoverage.h b/Source/CTest/cmParseDelphiCoverage.h index 278fbeb0f..1b374050a 100644 --- a/Source/CTest/cmParseDelphiCoverage.h +++ b/Source/CTest/cmParseDelphiCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParseDelphiCoverage_h #define cmParseDelphiCoverage_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx index 214ce5a17..e4ee699c4 100644 --- a/Source/CTest/cmParseGTMCoverage.cxx +++ b/Source/CTest/cmParseGTMCoverage.cxx @@ -4,8 +4,8 @@ #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" #include #include #include @@ -56,7 +56,7 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file) int lastoffset = 0; while (cmSystemTools::GetLineFromStream(in, line)) { // only look at lines that have coverage data - if (line.find("^ZZCOVERAGE") == line.npos) { + if (line.find("^ZZCOVERAGE") == std::string::npos) { continue; } std::string filepath; @@ -199,7 +199,7 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line, // now parse the right hand side of the = pos = line.find('='); // no = found, this is an error - if (pos == line.npos) { + if (pos == std::string::npos) { return false; } pos++; // move past = diff --git a/Source/CTest/cmParseGTMCoverage.h b/Source/CTest/cmParseGTMCoverage.h index 34721ff50..c4949d416 100644 --- a/Source/CTest/cmParseGTMCoverage.h +++ b/Source/CTest/cmParseGTMCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParseGTMCoverage_h #define cmParseGTMCoverage_h -#include +#include "cmConfigure.h" #include "cmParseMumpsCoverage.h" diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx index 0e36c010d..d15864a79 100644 --- a/Source/CTest/cmParseJacocoCoverage.cxx +++ b/Source/CTest/cmParseJacocoCoverage.cxx @@ -1,15 +1,15 @@ #include "cmParseJacocoCoverage.h" -#include +#include "cmConfigure.h" #include "cmCTest.h" #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" #include "cmXMLParser.h" -#include -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" #include #include diff --git a/Source/CTest/cmParseJacocoCoverage.h b/Source/CTest/cmParseJacocoCoverage.h index 04f194961..f2aec6db9 100644 --- a/Source/CTest/cmParseJacocoCoverage.h +++ b/Source/CTest/cmParseJacocoCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParseJacocoCoverage_h #define cmParseJacocoCoverage_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx index ab8be768e..eb29f55c0 100644 --- a/Source/CTest/cmParseMumpsCoverage.cxx +++ b/Source/CTest/cmParseMumpsCoverage.cxx @@ -4,9 +4,9 @@ #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" -#include -#include -#include +#include "cmConfigure.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" #include #include #include diff --git a/Source/CTest/cmParseMumpsCoverage.h b/Source/CTest/cmParseMumpsCoverage.h index c4ed17553..2c544954b 100644 --- a/Source/CTest/cmParseMumpsCoverage.h +++ b/Source/CTest/cmParseMumpsCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParseMumpsCoverage_h #define cmParseMumpsCoverage_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx index d8bb31bad..761ebec65 100644 --- a/Source/CTest/cmParsePHPCoverage.cxx +++ b/Source/CTest/cmParsePHPCoverage.cxx @@ -4,8 +4,8 @@ #include "cmCTestCoverageHandler.h" #include "cmSystemTools.h" -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" #include #include diff --git a/Source/CTest/cmParsePHPCoverage.h b/Source/CTest/cmParsePHPCoverage.h index 4bcad6df6..ff0e6366d 100644 --- a/Source/CTest/cmParsePHPCoverage.h +++ b/Source/CTest/cmParsePHPCoverage.h @@ -3,7 +3,7 @@ #ifndef cmParsePHPCoverage_h #define cmParsePHPCoverage_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 32ffa6bc5..f4ec6da29 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmProcess.h" -#include -#include -#include +#include "cmConfigure.h" +#include "cmProcessOutput.h" +#include "cmSystemTools.h" #include cmProcess::cmProcess() diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 9d201d196..86e905aca 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -3,9 +3,9 @@ #ifndef cmProcess_h #define cmProcess_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep -#include +#include "cmsys/Process.h" #include #include diff --git a/Source/Checks/cm_cxx_attribute_fallthrough.cxx b/Source/Checks/cm_cxx_attribute_fallthrough.cxx new file mode 100644 index 000000000..df43625a4 --- /dev/null +++ b/Source/Checks/cm_cxx_attribute_fallthrough.cxx @@ -0,0 +1,11 @@ +int main(int argc, char* argv[]) +{ + int i = 3; + switch (argc) { + case 1: + i = 0; + __attribute__((fallthrough)); + default: + return i; + } +} diff --git a/Source/Checks/cm_cxx_eq_delete.cxx b/Source/Checks/cm_cxx_eq_delete.cxx new file mode 100644 index 000000000..809e4cfcf --- /dev/null +++ b/Source/Checks/cm_cxx_eq_delete.cxx @@ -0,0 +1,14 @@ +struct Foo +{ + Foo() {} + ~Foo() {} + Foo(Foo const&) = delete; + Foo& operator=(Foo const&) = delete; + int test() const { return 0; } +}; + +int main() +{ + Foo const foo; + return foo.test(); +} diff --git a/Source/Checks/cm_cxx_fallthrough.cxx b/Source/Checks/cm_cxx_fallthrough.cxx new file mode 100644 index 000000000..7b35a5f29 --- /dev/null +++ b/Source/Checks/cm_cxx_fallthrough.cxx @@ -0,0 +1,11 @@ +int main(int argc, char* argv[]) +{ + int i = 3; + switch (argc) { + case 1: + i = 0; + [[fallthrough]]; + default: + return i; + } +} diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index 80c9f3b7a..3b0802579 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -3,14 +3,21 @@ function(cm_check_cxx_feature name) string(TOUPPER ${name} FEATURE) if(NOT DEFINED CMake_HAVE_CXX_${FEATURE}) message(STATUS "Checking if compiler supports C++ ${name}") + if(CMAKE_CXX_STANDARD) + set(maybe_cxx_standard -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}) + else() + set(maybe_cxx_standard "") + endif() try_compile(CMake_HAVE_CXX_${FEATURE} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm_cxx_${name}.cxx - CMAKE_FLAGS -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} + CMAKE_FLAGS ${maybe_cxx_standard} OUTPUT_VARIABLE OUTPUT ) + # Filter out MSBuild output that looks like a warning. + string(REGEX REPLACE " +0 Warning\\(s\\)" "" check_output "${OUTPUT}") # If using the feature causes warnings, treat it as broken/unavailable. - if(OUTPUT MATCHES "warning") + if(check_output MATCHES "[Ww]arning") set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE) endif() if(CMake_HAVE_CXX_${FEATURE}) @@ -31,15 +38,21 @@ function(cm_check_cxx_feature name) endif() endfunction() -if(CMAKE_CXX_STANDARD) - cm_check_cxx_feature(auto_ptr) - cm_check_cxx_feature(make_unique) - if(CMake_HAVE_CXX_MAKE_UNIQUE) - set(CMake_HAVE_CXX_UNIQUE_PTR 1) +cm_check_cxx_feature(auto_ptr) +cm_check_cxx_feature(eq_delete) +cm_check_cxx_feature(fallthrough) +if(NOT CMake_HAVE_CXX_FALLTHROUGH) + cm_check_cxx_feature(gnu_fallthrough) + if(NOT CMake_HAVE_CXX_GNU_FALLTHROUGH) + cm_check_cxx_feature(attribute_fallthrough) endif() - cm_check_cxx_feature(nullptr) - cm_check_cxx_feature(override) - cm_check_cxx_feature(unique_ptr) - cm_check_cxx_feature(unordered_map) - cm_check_cxx_feature(unordered_set) endif() +cm_check_cxx_feature(make_unique) +if(CMake_HAVE_CXX_MAKE_UNIQUE) + set(CMake_HAVE_CXX_UNIQUE_PTR 1) +endif() +cm_check_cxx_feature(nullptr) +cm_check_cxx_feature(override) +cm_check_cxx_feature(unique_ptr) +cm_check_cxx_feature(unordered_map) +cm_check_cxx_feature(unordered_set) diff --git a/Source/Checks/cm_cxx_gnu_fallthrough.cxx b/Source/Checks/cm_cxx_gnu_fallthrough.cxx new file mode 100644 index 000000000..602109405 --- /dev/null +++ b/Source/Checks/cm_cxx_gnu_fallthrough.cxx @@ -0,0 +1,11 @@ +int main(int argc, char* argv[]) +{ + int i = 3; + switch (argc) { + case 1: + i = 0; + [[gnu::fallthrough]]; + default: + return i; + } +} diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index ff8e010d7..28a0e95b9 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -1,6 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include +#include "cmConfigure.h" #include "cmCursesForm.h" #include "cmCursesMainForm.h" @@ -10,7 +10,7 @@ #include "cmSystemTools.h" #include "cmake.h" -#include +#include "cmsys/Encoding.hxx" #include #include #include @@ -81,7 +81,7 @@ int main(int argc, char const* const* argv) cmDocumentation doc; doc.addCMakeStandardDocSections(); if (doc.CheckOptions(argc, argv)) { - cmake hcm; + cmake hcm(cmake::RoleInternal); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); diff --git a/Source/CursesDialog/cmCursesBoolWidget.h b/Source/CursesDialog/cmCursesBoolWidget.h index f79f7e8ea..90bcc2209 100644 --- a/Source/CursesDialog/cmCursesBoolWidget.h +++ b/Source/CursesDialog/cmCursesBoolWidget.h @@ -3,7 +3,7 @@ #ifndef cmCursesBoolWidget_h #define cmCursesBoolWidget_h -#include +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" #include "cmCursesWidget.h" @@ -12,6 +12,8 @@ class cmCursesMainForm; class cmCursesBoolWidget : public cmCursesWidget { + CM_DISABLE_COPY(cmCursesBoolWidget) + public: cmCursesBoolWidget(int width, int height, int left, int top); @@ -25,10 +27,6 @@ public: // Set/Get the value (on/off). void SetValueAsBool(bool value); bool GetValueAsBool(); - -protected: - cmCursesBoolWidget(const cmCursesBoolWidget& from); - void operator=(const cmCursesBoolWidget&); }; #endif // cmCursesBoolWidget_h diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx index 5539fbe36..d071c9178 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx @@ -15,7 +15,6 @@ #include "cmake.h" #include -#include #include cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h index 59a1fd7e8..3c500785d 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.h +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h @@ -3,7 +3,7 @@ #ifndef cmCursesCacheEntryComposite_h #define cmCursesCacheEntryComposite_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include @@ -13,6 +13,8 @@ class cmake; class cmCursesCacheEntryComposite { + CM_DISABLE_COPY(cmCursesCacheEntryComposite) + public: cmCursesCacheEntryComposite(const std::string& key, int labelwidth, int entrywidth); @@ -24,9 +26,6 @@ public: friend class cmCursesMainForm; protected: - cmCursesCacheEntryComposite(const cmCursesCacheEntryComposite& from); - void operator=(const cmCursesCacheEntryComposite&); - cmCursesLabelWidget* Label; cmCursesLabelWidget* IsNewLabel; cmCursesWidget* Entry; diff --git a/Source/CursesDialog/cmCursesDummyWidget.h b/Source/CursesDialog/cmCursesDummyWidget.h index fe43de599..d9bb6babc 100644 --- a/Source/CursesDialog/cmCursesDummyWidget.h +++ b/Source/CursesDialog/cmCursesDummyWidget.h @@ -3,7 +3,7 @@ #ifndef cmCursesDummyWidget_h #define cmCursesDummyWidget_h -#include +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" #include "cmCursesWidget.h" @@ -12,6 +12,8 @@ class cmCursesMainForm; class cmCursesDummyWidget : public cmCursesWidget { + CM_DISABLE_COPY(cmCursesDummyWidget) + public: cmCursesDummyWidget(int width, int height, int left, int top); @@ -20,10 +22,6 @@ public: // when this widget has focus. Returns true if the input was // handled. bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE; - -protected: - cmCursesDummyWidget(const cmCursesDummyWidget& from); - void operator=(const cmCursesDummyWidget&); }; #endif // cmCursesDummyWidget_h diff --git a/Source/CursesDialog/cmCursesFilePathWidget.h b/Source/CursesDialog/cmCursesFilePathWidget.h index 7df7f00af..6ad535b99 100644 --- a/Source/CursesDialog/cmCursesFilePathWidget.h +++ b/Source/CursesDialog/cmCursesFilePathWidget.h @@ -3,18 +3,16 @@ #ifndef cmCursesFilePathWidget_h #define cmCursesFilePathWidget_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include "cmCursesPathWidget.h" class cmCursesFilePathWidget : public cmCursesPathWidget { + CM_DISABLE_COPY(cmCursesFilePathWidget) + public: cmCursesFilePathWidget(int width, int height, int left, int top); - -protected: - cmCursesFilePathWidget(const cmCursesFilePathWidget& from); - void operator=(const cmCursesFilePathWidget&); }; #endif // cmCursesFilePathWidget_h diff --git a/Source/CursesDialog/cmCursesForm.cxx b/Source/CursesDialog/cmCursesForm.cxx index 0eb16cbfe..06c1e9c70 100644 --- a/Source/CursesDialog/cmCursesForm.cxx +++ b/Source/CursesDialog/cmCursesForm.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCursesForm.h" -#include - cmsys::ofstream cmCursesForm::DebugFile; bool cmCursesForm::Debug = false; diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h index 85a80c2d1..553105c76 100644 --- a/Source/CursesDialog/cmCursesForm.h +++ b/Source/CursesDialog/cmCursesForm.h @@ -3,14 +3,16 @@ #ifndef cmCursesForm_h #define cmCursesForm_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" -#include +#include "cmsys/FStream.hxx" class cmCursesForm { + CM_DISABLE_COPY(cmCursesForm) + public: cmCursesForm(); virtual ~cmCursesForm(); @@ -55,9 +57,6 @@ protected: static cmsys::ofstream DebugFile; static bool Debug; - cmCursesForm(const cmCursesForm& form); - void operator=(const cmCursesForm&); - FORM* Form; }; diff --git a/Source/CursesDialog/cmCursesLabelWidget.h b/Source/CursesDialog/cmCursesLabelWidget.h index 4d63f483b..267de7c8c 100644 --- a/Source/CursesDialog/cmCursesLabelWidget.h +++ b/Source/CursesDialog/cmCursesLabelWidget.h @@ -3,7 +3,7 @@ #ifndef cmCursesLabelWidget_h #define cmCursesLabelWidget_h -#include +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" #include "cmCursesWidget.h" @@ -14,6 +14,8 @@ class cmCursesMainForm; class cmCursesLabelWidget : public cmCursesWidget { + CM_DISABLE_COPY(cmCursesLabelWidget) + public: cmCursesLabelWidget(int width, int height, int left, int top, const std::string& name); @@ -24,10 +26,6 @@ public: // when this widget has focus. Returns true if the input was // handled bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE; - -protected: - cmCursesLabelWidget(const cmCursesLabelWidget& from); - void operator=(const cmCursesLabelWidget&); }; #endif // cmCursesLabelWidget_h diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index d299547d2..7fb065d30 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -159,7 +159,8 @@ void cmCursesLongMessageForm::HandleInput() // quit if (key == 'o' || key == 'e') { break; - } else if (key == KEY_DOWN || key == ctrl('n')) { + } + if (key == KEY_DOWN || key == ctrl('n')) { form_driver(this->Form, REQ_SCR_FLINE); } else if (key == KEY_UP || key == ctrl('p')) { form_driver(this->Form, REQ_SCR_BLINE); diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h index e9eae7c19..cd8e0953a 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.h +++ b/Source/CursesDialog/cmCursesLongMessageForm.h @@ -3,7 +3,7 @@ #ifndef cmCursesLongMessageForm_h #define cmCursesLongMessageForm_h -#include +#include "cmConfigure.h" #include "cmCursesForm.h" #include "cmCursesStandardIncludes.h" @@ -13,6 +13,8 @@ class cmCursesLongMessageForm : public cmCursesForm { + CM_DISABLE_COPY(cmCursesLongMessageForm) + public: cmCursesLongMessageForm(std::vector const& messages, const char* title); @@ -38,9 +40,6 @@ public: void UpdateStatusBar() CM_OVERRIDE; protected: - cmCursesLongMessageForm(const cmCursesLongMessageForm& from); - void operator=(const cmCursesLongMessageForm&); - std::string Messages; std::string Title; diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 939c7365d..026320a1f 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -40,7 +40,7 @@ cmCursesMainForm::cmCursesMainForm(std::vector const& args, "Welcome to ccmake, curses based user interface for CMake."); this->HelpMessage.push_back(""); this->HelpMessage.push_back(s_ConstHelpMessage); - this->CMakeInstance = new cmake; + this->CMakeInstance = new cmake(cmake::RoleProject); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeCursesCommand()); @@ -764,9 +764,8 @@ void cmCursesMainForm::HandleInput() // quit if (key == 'q') { break; - } else { - continue; } + continue; } currentField = current_field(this->Form); @@ -826,7 +825,7 @@ void cmCursesMainForm::HandleInput() // (index always corresponds to the value field) // scroll down with arrow down, ctrl+n (emacs binding), or j (vim // binding) - else if (key == KEY_DOWN || key == ctrl('n') || key == 'j') { + if (key == KEY_DOWN || key == ctrl('n') || key == 'j') { FIELD* cur = current_field(this->Form); size_t findex = field_index(cur); if (findex == 3 * this->NumberOfVisibleEntries - 1) { @@ -1051,7 +1050,7 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr) const char* curField = lbl->GetValue(); if (curField) { std::string cfld = cmSystemTools::LowerCase(curField); - if (cfld.find(str) != cfld.npos && findex != start_index) { + if (cfld.find(str) != std::string::npos && findex != start_index) { break; } } diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h index d891ea03e..e35cf3ed7 100644 --- a/Source/CursesDialog/cmCursesMainForm.h +++ b/Source/CursesDialog/cmCursesMainForm.h @@ -3,7 +3,7 @@ #ifndef cmCursesMainForm_h #define cmCursesMainForm_h -#include +#include "cmConfigure.h" #include "cmCursesForm.h" #include "cmCursesStandardIncludes.h" @@ -23,6 +23,8 @@ class cmake; */ class cmCursesMainForm : public cmCursesForm { + CM_DISABLE_COPY(cmCursesMainForm) + public: cmCursesMainForm(std::vector const& args, int initwidth); ~cmCursesMainForm() CM_OVERRIDE; @@ -103,9 +105,6 @@ public: static void UpdateProgress(const char* msg, float prog, void*); protected: - cmCursesMainForm(const cmCursesMainForm& from); - void operator=(const cmCursesMainForm&); - // Copy the cache values from the user interface to the actual // cache. void FillCacheManagerFromUI(); diff --git a/Source/CursesDialog/cmCursesOptionsWidget.h b/Source/CursesDialog/cmCursesOptionsWidget.h index 75065a248..7f4416f95 100644 --- a/Source/CursesDialog/cmCursesOptionsWidget.h +++ b/Source/CursesDialog/cmCursesOptionsWidget.h @@ -3,7 +3,7 @@ #ifndef cmCursesOptionsWidget_h #define cmCursesOptionsWidget_h -#include +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" #include "cmCursesWidget.h" @@ -15,6 +15,8 @@ class cmCursesMainForm; class cmCursesOptionsWidget : public cmCursesWidget { + CM_DISABLE_COPY(cmCursesOptionsWidget) + public: cmCursesOptionsWidget(int width, int height, int left, int top); @@ -29,8 +31,6 @@ public: void PreviousOption(); protected: - cmCursesOptionsWidget(const cmCursesOptionsWidget& from); - void operator=(const cmCursesOptionsWidget&); std::vector Options; std::vector::size_type CurrentOption; }; diff --git a/Source/CursesDialog/cmCursesPathWidget.h b/Source/CursesDialog/cmCursesPathWidget.h index 63ed05b76..ae6c16d02 100644 --- a/Source/CursesDialog/cmCursesPathWidget.h +++ b/Source/CursesDialog/cmCursesPathWidget.h @@ -3,7 +3,7 @@ #ifndef cmCursesPathWidget_h #define cmCursesPathWidget_h -#include +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" #include "cmCursesStringWidget.h" @@ -14,6 +14,8 @@ class cmCursesMainForm; class cmCursesPathWidget : public cmCursesStringWidget { + CM_DISABLE_COPY(cmCursesPathWidget) + public: cmCursesPathWidget(int width, int height, int left, int top); @@ -26,9 +28,6 @@ public: void OnType(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE; protected: - cmCursesPathWidget(const cmCursesPathWidget& from); - void operator=(const cmCursesPathWidget&); - std::string LastString; std::string LastGlob; bool Cycle; diff --git a/Source/CursesDialog/cmCursesStandardIncludes.h b/Source/CursesDialog/cmCursesStandardIncludes.h index 7818e3e19..5c5950483 100644 --- a/Source/CursesDialog/cmCursesStandardIncludes.h +++ b/Source/CursesDialog/cmCursesStandardIncludes.h @@ -3,7 +3,7 @@ #ifndef cmCursesStandardIncludes_h #define cmCursesStandardIncludes_h -#include +#include "cmConfigure.h" #if defined(__hpux) #define _BOOL_DEFINED diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h index b3c1089b5..5eb33666d 100644 --- a/Source/CursesDialog/cmCursesStringWidget.h +++ b/Source/CursesDialog/cmCursesStringWidget.h @@ -3,7 +3,7 @@ #ifndef cmCursesStringWidget_h #define cmCursesStringWidget_h -#include +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" #include "cmCursesWidget.h" @@ -20,6 +20,8 @@ class cmCursesMainForm; class cmCursesStringWidget : public cmCursesWidget { + CM_DISABLE_COPY(cmCursesStringWidget) + public: cmCursesStringWidget(int width, int height, int left, int top); @@ -60,9 +62,6 @@ public: bool PrintKeys() CM_OVERRIDE; protected: - cmCursesStringWidget(const cmCursesStringWidget& from); - void operator=(const cmCursesStringWidget&); - // true if the widget is in edit mode bool InEdit; char* OriginalString; diff --git a/Source/CursesDialog/cmCursesWidget.cxx b/Source/CursesDialog/cmCursesWidget.cxx index a9918f7e9..054f27e29 100644 --- a/Source/CursesDialog/cmCursesWidget.cxx +++ b/Source/CursesDialog/cmCursesWidget.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCursesWidget.h" -#include - cmCursesWidget::cmCursesWidget(int width, int height, int left, int top) { this->Field = new_field(height, width, top, left, 0, 0); diff --git a/Source/CursesDialog/cmCursesWidget.h b/Source/CursesDialog/cmCursesWidget.h index d226dd731..3470d7096 100644 --- a/Source/CursesDialog/cmCursesWidget.h +++ b/Source/CursesDialog/cmCursesWidget.h @@ -3,7 +3,7 @@ #ifndef cmCursesWidget_h #define cmCursesWidget_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include "cmCursesStandardIncludes.h" #include "cmStateTypes.h" @@ -14,6 +14,8 @@ class cmCursesMainForm; class cmCursesWidget { + CM_DISABLE_COPY(cmCursesWidget) + public: cmCursesWidget(int width, int height, int left, int top); virtual ~cmCursesWidget(); @@ -59,9 +61,6 @@ public: friend class cmCursesMainForm; protected: - cmCursesWidget(const cmCursesWidget& from); - void operator=(const cmCursesWidget&); - cmStateEnums::CacheEntryType Type; std::string Value; FIELD* Field; diff --git a/Source/CursesDialog/form/form.h b/Source/CursesDialog/form/form.h index b65a3cafe..39ed75a7c 100644 --- a/Source/CursesDialog/form/form.h +++ b/Source/CursesDialog/form/form.h @@ -33,7 +33,7 @@ #ifndef FORM_H #define FORM_H -#include +#include "cmFormConfigure.h" /* figure out which curses.h to include */ # if defined(CURSES_HAVE_NCURSES_H) diff --git a/Source/LexerParser/.clang-tidy b/Source/LexerParser/.clang-tidy new file mode 100644 index 000000000..52b11bf91 --- /dev/null +++ b/Source/LexerParser/.clang-tidy @@ -0,0 +1,6 @@ +--- +# We want to disable all checks for generated code. However, clang-tidy will +# assume we did not configure it correctly. Just add one check that will never +# be found. +Checks: '-*,llvm-twine-local' +... diff --git a/Source/LexerParser/.gitattributes b/Source/LexerParser/.gitattributes new file mode 100644 index 000000000..47eedfb4b --- /dev/null +++ b/Source/LexerParser/.gitattributes @@ -0,0 +1,17 @@ +/cmCommandArgumentLexer.cxx generated +/cmCommandArgumentLexer.h generated +/cmCommandArgumentParser.cxx generated +/cmCommandArgumentParserTokens.h generated +/cmDependsJavaLexer.cxx generated +/cmDependsJavaLexer.h generated +/cmDependsJavaParser.cxx generated +/cmDependsJavaParserTokens.h generated +/cmExprLexer.cxx generated +/cmExprLexer.h generated +/cmExprParser.cxx generated +/cmExprParserTokens.h generated +/cmFortranLexer.cxx generated +/cmFortranLexer.h generated +/cmFortranParser.cxx generated +/cmFortranParserTokens.h generated +/cmListFileLexer.c generated diff --git a/Source/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx similarity index 100% rename from Source/cmCommandArgumentLexer.cxx rename to Source/LexerParser/cmCommandArgumentLexer.cxx diff --git a/Source/cmCommandArgumentLexer.h b/Source/LexerParser/cmCommandArgumentLexer.h similarity index 100% rename from Source/cmCommandArgumentLexer.h rename to Source/LexerParser/cmCommandArgumentLexer.h diff --git a/Source/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l similarity index 100% rename from Source/cmCommandArgumentLexer.in.l rename to Source/LexerParser/cmCommandArgumentLexer.in.l diff --git a/Source/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx similarity index 58% rename from Source/cmCommandArgumentParser.cxx rename to Source/LexerParser/cmCommandArgumentParser.cxx index e384f2115..aed0826c0 100644 --- a/Source/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -1,16 +1,13 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/* A Bison parser, made by GNU Bison 2.3. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,9 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -49,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.3" +#define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -57,58 +52,23 @@ /* Pure parsers. */ #define YYPURE 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 - -/* Substitute the variable and function names. */ -#define yyparse cmCommandArgument_yyparse -#define yylex cmCommandArgument_yylex -#define yyerror cmCommandArgument_yyerror -#define yylval cmCommandArgument_yylval -#define yychar cmCommandArgument_yychar -#define yydebug cmCommandArgument_yydebug -#define yynerrs cmCommandArgument_yynerrs - +/* Push parsers. */ +#define YYPUSH 0 -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - 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 +/* Pull parsers. */ +#define YYPULL 1 +/* Substitute the variable and function names. */ +#define yyparse cmCommandArgument_yyparse +#define yylex cmCommandArgument_yylex +#define yyerror cmCommandArgument_yyerror +#define yydebug cmCommandArgument_yydebug +#define yynerrs cmCommandArgument_yynerrs /* Copy the first part of user declarations. */ -#line 1 "cmCommandArgumentParser.y" +#line 1 "cmCommandArgumentParser.y" /* yacc.c:339 */ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -121,19 +81,14 @@ Run bison like this: bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y Modify cmCommandArgumentParser.cxx: - - remove TABs - - put header block at top of file + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ -#include "cmStandardIncludes.h" +#include "cmConfigure.h" // IWYU pragma: keep + +#include -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmCommandArgument_yyerror(x) \ - cmCommandArgumentError(yyscanner, x) #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner)) /* Make sure malloc and free are available on QNX. */ @@ -156,10 +111,9 @@ Modify cmCommandArgumentParser.cxx: /* Forward declare the lexer entry point. */ YY_DECL; -/* Internal utility functions. */ -static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); +/* Helper function to forward error callback from parser. */ +static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); -#define YYDEBUG 1 /* Configure the parser to support large input. */ #define YYMAXDEPTH 100000 #define YYINITDEPTH 10000 @@ -173,39 +127,80 @@ static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4702) /* unreachable code */ #endif +#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339 */ -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else -# define YYERROR_VERBOSE 0 +# define YYERROR_VERBOSE 1 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "cmCommandArgumentParserTokens.h". */ +#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 -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 +/* 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 +/* Value type. */ -/* Copy the second part of user declarations. */ +int cmCommandArgument_yyparse (yyscan_t yyscanner); + +#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */ + +/* Copy the second part of user declarations. */ -/* Line 216 of yacc.c. */ -#line 227 "cmCommandArgumentParser.cxx" +#line 204 "cmCommandArgumentParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -219,11 +214,8 @@ typedef unsigned char yytype_uint8; #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; #else -typedef short int yytype_int8; +typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 @@ -243,8 +235,7 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else @@ -258,39 +249,68 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid +# 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__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) +#if defined __GNUC__ && 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\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") #else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int i) -#else -static int -YYID (i) - int i; +# define YY_INITIAL_VALUE(Value) Value #endif -{ - return i; -} +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -308,11 +328,11 @@ YYID (i) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -320,8 +340,8 @@ YYID (i) # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely @@ -335,25 +355,23 @@ YYID (i) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif @@ -368,9 +386,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss; - YYSTYPE yyvs; - }; + yytype_int16 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) @@ -381,42 +399,46 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack) \ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ - while (YYID (0)) + while (0) #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 25 /* YYLAST -- Last index in YYTABLE. */ @@ -428,17 +450,19 @@ union yyalloc #define YYNNTS 10 /* YYNRULES -- Number of rules. */ #define YYNRULES 24 -/* YYNRULES -- Number of states. */ +/* YYNSTATES -- Number of states. */ #define YYNSTATES 33 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 269 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -471,36 +495,16 @@ static const yytype_uint8 yytranslate[] = }; #if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint8 yyprhs[] = -{ - 0, 0, 3, 5, 7, 10, 11, 14, 16, 18, - 20, 22, 24, 26, 28, 30, 34, 38, 42, 44, - 46, 49, 50, 53, 55 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 16, 0, -1, 17, -1, 18, -1, 18, 10, -1, - -1, 19, 18, -1, 20, -1, 21, -1, 9, -1, - 12, -1, 6, -1, 7, -1, 8, -1, 11, -1, - 3, 22, 8, -1, 4, 23, 8, -1, 5, 23, - 8, -1, 14, -1, 23, -1, 11, 22, -1, -1, - 24, 23, -1, 9, -1, 21, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 116, 116, 123, 128, 134, 138, 144, 149, 155, - 160, 165, 170, 175, 180, 186, 192, 198, 204, 210, - 215, 221, 225, 231, 236 + 0, 96, 96, 102, 105, 110, 113, 118, 121, 126, + 129, 132, 135, 138, 141, 146, 149, 152, 155, 160, + 163, 168, 171, 176, 179 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 1 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -509,13 +513,13 @@ static const char *const yytname[] = "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"", "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start", "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable", - "EnvVarName", "MultipleIds", "ID", 0 + "EnvVarName", "MultipleIds", "ID", YY_NULLPTR }; #endif # ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, @@ -523,25 +527,29 @@ static const yytype_uint16 yytoknum[] = }; # endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 15, 16, 17, 17, 18, 18, 19, 19, 20, - 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, - 22, 23, 23, 24, 24 -}; +#define YYPACT_NINF -3 -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-3))) + +#define YYTABLE_NINF -1 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = { - 0, 2, 1, 1, 2, 0, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, - 2, 0, 2, 1, 1 + 0, 14, 26, 26, -3, -3, -3, -3, -3, -3, + -3, 10, -3, 3, 0, -3, -3, -3, 14, -3, + 7, -3, 26, 13, 16, -3, -3, -3, -3, -3, + -3, -3, -3 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ + /* 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[] = { 5, 21, 21, 21, 11, 12, 13, 9, 14, 10, @@ -550,34 +558,21 @@ static const yytype_uint8 yydefact[] = 22, 16, 17 }; -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int8 yydefgoto[] = -{ - -1, 11, 12, 13, 14, 15, 19, 20, 21, 22 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -3 -static const yytype_int8 yypact[] = + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = { - 0, 14, 26, 26, -3, -3, -3, -3, -3, -3, - -3, 10, -3, 3, 0, -3, -3, -3, 14, -3, - 7, -3, 26, 13, 16, -3, -3, -3, -3, -3, - -3, -3, -3 + -3, -3, -3, 8, -3, -3, 2, 9, -2, -3 }; -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = { - -3, -3, -3, 8, -3, -3, 2, 9, -2, -3 + -1, 11, 12, 13, 14, 15, 19, 20, 21, 22 }; -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -1 + /* 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[] = { 23, 24, 16, 1, 2, 3, 4, 5, 6, 7, @@ -596,8 +591,8 @@ static const yytype_int8 yycheck[] = 14 }; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 4, 5, 6, 7, 8, 9, 11, 12, @@ -606,6 +601,23 @@ static const yytype_uint8 yystos[] = 23, 8, 8 }; + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 15, 16, 17, 17, 18, 18, 19, 19, 20, + 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, + 22, 23, 23, 24, 24 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 2, 0, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, + 2, 0, 2, 1, 1 +}; + + #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) @@ -616,85 +628,30 @@ static const yytype_uint8 yystos[] = #define YYERROR goto yyerrorlab -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ - -#define YYFAIL goto yyerrlab - #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ - if (yychar == YYEMPTY && yylen == 1) \ + if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ - yyerror (YY_("syntax error: cannot back up")); \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ -while (YYID (0)) - +while (0) +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -#else -# define YYLEX yylex (&yylval) -#endif /* Enable debugging if requested. */ #if YYDEBUG @@ -708,7 +665,13 @@ while (YYID (0)) do { \ if (yydebug) \ YYFPRINTF Args; \ -} while (YYID (0)) +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ @@ -716,42 +679,29 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value); \ + Type, Value, yyscanner); \ YYFPRINTF (stderr, "\n"); \ } \ -} while (YYID (0)) +} while (0) -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); # endif - switch (yytype) - { - default: - break; - } + YYUSE (yytype); } @@ -759,24 +709,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) | Print this symbol on YYOUTPUT. | `--------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); YYFPRINTF (yyoutput, ")"); } @@ -785,20 +724,15 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) | TOP (included). | `------------------------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) -#else -static void -yy_stack_print (bottom, top) - yytype_int16 *bottom; - yytype_int16 *top; -#endif +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); - for (; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } YYFPRINTF (stderr, "\n"); } @@ -806,45 +740,38 @@ yy_stack_print (bottom, top) do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) +} while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { + unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - fprintf (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - fprintf (stderr, "\n"); + , yyscanner); + YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) + yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \ +} while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ @@ -873,7 +800,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -882,15 +808,8 @@ int yydebug; # define yystrlen strlen # else /* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) @@ -906,16 +825,8 @@ yystrlen (yystr) # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif { char *yyd = yydest; const char *yys = yysrc; @@ -976,165 +887,159 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; +/* 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. - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + 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) +{ + 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"). */ + 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 + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + 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 yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - 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 yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + 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])) { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; + 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)) + return 2; + yysize = yysize1; + } } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + 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_ + } - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } - if (yysize_overflow) - return YYSIZE_MAXIMUM; + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } - if (yyresult) + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; } - return yysize; - } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner) { YYUSE (yyvaluep); - + YYUSE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - switch (yytype) - { - - default: - break; - } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } - - -/* Prevent warnings from -Wmissing-prototypes. */ - -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - @@ -1143,99 +1048,76 @@ int yyparse (); | yyparse. | `----------*/ -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) int -yyparse (void) -#else -int -yyparse () - -#endif -#endif +yyparse (yyscan_t yyscanner) { - /* The look-ahead symbol. */ +/* The lookahead symbol. */ int yychar; -/* The semantic value of the look-ahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Look-ahead token as an internal (translated) token number. */ - int yytoken = 0; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ + /* Number of syntax errors so far. */ + int yynerrs; - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss = yyssa; - yytype_int16 *yyssp; + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + 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; -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; - YYSIZE_T yystacksize = YYINITDEPTH; + YYSIZE_T yystacksize; + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; /* 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 + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. 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. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss; - yyvsp = yyvs; - + yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. @@ -1262,7 +1144,6 @@ int yynerrs; 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 @@ -1270,7 +1151,6 @@ int yynerrs; yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); yyss = yyss1; @@ -1293,9 +1173,8 @@ int yynerrs; (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1306,7 +1185,6 @@ int yynerrs; yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1316,6 +1194,9 @@ int yynerrs; YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + if (yystate == YYFINAL) + YYACCEPT; + goto yybackup; /*-----------. @@ -1324,20 +1205,20 @@ int yynerrs; yybackup: /* Do appropriate processing given the current state. Read a - look-ahead token if we need one and don't already have one. */ + lookahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to look-ahead token. */ + /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; - /* Not known => get a look-ahead token if don't already have one. */ + /* Not known => get a lookahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + yychar = yylex (&yylval, yyscanner); } if (yychar <= YYEOF) @@ -1359,29 +1240,27 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) + if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } - if (yyn == YYFINAL) - YYACCEPT; - /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the look-ahead token. */ + /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the shifted token unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; + /* Discard the shifted token. */ + yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1404,7 +1283,7 @@ yyreduce: yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. + '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -1418,175 +1297,205 @@ yyreduce: switch (yyn) { case 2: -#line 117 "cmCommandArgumentParser.y" +#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = 0; - yyGetParser->SetResult((yyvsp[(1) - (1)].str)); -} + (yyval.str) = 0; + yyGetParser->SetResult((yyvsp[0].str)); + } +#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 124 "cmCommandArgumentParser.y" +#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 129 "cmCommandArgumentParser.y" +#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); -} + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); + } +#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 134 "cmCommandArgumentParser.y" +#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = 0; -} + (yyval.str) = 0; + } +#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 139 "cmCommandArgumentParser.y" +#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); -} + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); + } +#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 145 "cmCommandArgumentParser.y" +#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 150 "cmCommandArgumentParser.y" +#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 156 "cmCommandArgumentParser.y" +#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 161 "cmCommandArgumentParser.y" +#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 166 "cmCommandArgumentParser.y" +#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 171 "cmCommandArgumentParser.y" +#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 176 "cmCommandArgumentParser.y" +#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 181 "cmCommandArgumentParser.y" +#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 187 "cmCommandArgumentParser.y" +#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str)); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} + (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); + } +#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 193 "cmCommandArgumentParser.y" +#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str)); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} + (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); + } +#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 199 "cmCommandArgumentParser.y" +#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandVariable((yyvsp[(2) - (3)].str)); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} + (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); + } +#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 205 "cmCommandArgumentParser.y" +#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[(1) - (1)].str)); -} + (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); + } +#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 211 "cmCommandArgumentParser.y" +#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 216 "cmCommandArgumentParser.y" +#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (2)].str); -} + (yyval.str) = (yyvsp[-1].str); + } +#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 221 "cmCommandArgumentParser.y" +#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = 0; -} + (yyval.str) = 0; + } +#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 226 "cmCommandArgumentParser.y" +#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); -} + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); + } +#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 232 "cmCommandArgumentParser.y" +#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 237 "cmCommandArgumentParser.y" +#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); -} + (yyval.str) = (yyvsp[0].str); + } +#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; -/* Line 1267 of yacc.c. */ -#line 1606 "cmCommandArgumentParser.cxx" +#line 1486 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + 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); YYPOPSTACK (yylen); @@ -1595,8 +1504,7 @@ yyreduce: *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state + /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -1611,48 +1519,51 @@ yyreduce: goto yynewstate; -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ 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); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); + yyerror (yyscanner, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; } } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + yyerror (yyscanner, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -1660,7 +1571,7 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse look-ahead token after an + /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) @@ -1672,12 +1583,13 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval); + yytoken, &yylval, yyscanner); yychar = YYEMPTY; } } - /* Else will try to reuse look-ahead token after shifting the error +#if 0 + /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; @@ -1693,7 +1605,7 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; - /* Do not reclaim the symbols of the rule which action triggered + /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; @@ -1706,12 +1618,13 @@ yyerrorlab: | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: +#endif yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -1728,16 +1641,15 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp); + yystos[yystate], yyvsp, yyscanner); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } - if (yyn == YYFINAL) - YYACCEPT; - + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -1761,28 +1673,33 @@ yyabortlab: yyresult = 1; goto yyreturn; -#ifndef yyoverflow +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (YY_("memory exhausted")); + yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: - if (yychar != YYEOF && yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, yyscanner); + } + /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); + yystos[*yyssp], yyvsp, yyscanner); YYPOPSTACK (1); } #ifndef yyoverflow @@ -1793,19 +1710,14 @@ yyreturn: if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif - /* Make sure YYID is used. */ - return YYID (yyresult); + return yyresult; } - - -#line 242 "cmCommandArgumentParser.y" +#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906 */ /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmCommandArgumentError(yyscan_t yyscanner, const char* message) +void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } - - diff --git a/Source/cmCommandArgumentParser.y b/Source/LexerParser/cmCommandArgumentParser.y similarity index 54% rename from Source/cmCommandArgumentParser.y rename to Source/LexerParser/cmCommandArgumentParser.y index b2f4b1bb6..55a88dffa 100644 --- a/Source/cmCommandArgumentParser.y +++ b/Source/LexerParser/cmCommandArgumentParser.y @@ -10,20 +10,14 @@ Run bison like this: bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y Modify cmCommandArgumentParser.cxx: - - remove TABs - - remove use of the 'register' storage class specifier - - put header block at top of file + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ -#include "cmStandardIncludes.h" +#include "cmConfigure.h" // IWYU pragma: keep + +#include -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmCommandArgument_yyerror(x) \ - cmCommandArgumentError(yyscanner, x) #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner)) /* Make sure malloc and free are available on QNX. */ @@ -46,10 +40,9 @@ Modify cmCommandArgumentParser.cxx: /* Forward declare the lexer entry point. */ YY_DECL; -/* Internal utility functions. */ -static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); +/* Helper function to forward error callback from parser. */ +static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); -#define YYDEBUG 1 /* Configure the parser to support large input. */ #define YYMAXDEPTH 100000 #define YYINITDEPTH 10000 @@ -65,7 +58,13 @@ static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); %} /* Generate a reentrant parser object. */ -%pure_parser +%define api.pure + +/* Configure the parser to use a lexer object. */ +%lex-param {yyscan_t yyscanner} +%parse-param {yyscan_t yyscanner} + +%define parse.error verbose /* %union { @@ -94,138 +93,99 @@ static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); Start: -GoalWithOptionalBackSlash -{ - $$ = 0; - yyGetParser->SetResult($1); -} + GoalWithOptionalBackSlash { + $$ = 0; + yyGetParser->SetResult($1); + } GoalWithOptionalBackSlash: -Goal -{ - $$ = $1; -} -| -Goal cal_BSLASH -{ - $$ = yyGetParser->CombineUnions($1, $2); -} + Goal { + $$ = $1; + } +| Goal cal_BSLASH { + $$ = yyGetParser->CombineUnions($1, $2); + } Goal: -{ - $$ = 0; -} -| -String Goal -{ - $$ = yyGetParser->CombineUnions($1, $2); -} + { + $$ = 0; + } +| String Goal { + $$ = yyGetParser->CombineUnions($1, $2); + } String: -OuterText -{ - $$ = $1; -} -| -Variable -{ - $$ = $1; -} + OuterText { + $$ = $1; + } +| Variable { + $$ = $1; + } OuterText: -cal_NAME -{ - $$ = $1; -} -| -cal_AT -{ - $$ = $1; -} -| -cal_DOLLAR -{ - $$ = $1; -} -| -cal_LCURLY -{ - $$ = $1; -} -| -cal_RCURLY -{ - $$ = $1; -} -| -cal_SYMBOL -{ - $$ = $1; -} + cal_NAME { + $$ = $1; + } +| cal_AT { + $$ = $1; + } +| cal_DOLLAR { + $$ = $1; + } +| cal_LCURLY { + $$ = $1; + } +| cal_RCURLY { + $$ = $1; + } +| cal_SYMBOL { + $$ = $1; + } Variable: -cal_ENVCURLY EnvVarName cal_RCURLY -{ - $$ = yyGetParser->ExpandSpecialVariable($1,$2); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -| -cal_NCURLY MultipleIds cal_RCURLY -{ - $$ = yyGetParser->ExpandSpecialVariable($1,$2); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -| -cal_DCURLY MultipleIds cal_RCURLY -{ - $$ = yyGetParser->ExpandVariable($2); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -| -cal_ATNAME -{ - $$ = yyGetParser->ExpandVariableForAt($1); -} + cal_ENVCURLY EnvVarName cal_RCURLY { + $$ = yyGetParser->ExpandSpecialVariable($1, $2); + } +| cal_NCURLY MultipleIds cal_RCURLY { + $$ = yyGetParser->ExpandSpecialVariable($1, $2); + } +| cal_DCURLY MultipleIds cal_RCURLY { + $$ = yyGetParser->ExpandVariable($2); + } +| cal_ATNAME { + $$ = yyGetParser->ExpandVariableForAt($1); + } EnvVarName: -MultipleIds -{ - $$ = $1; -} -| -cal_SYMBOL EnvVarName -{ - $$ = $1; -} + MultipleIds { + $$ = $1; + } +| cal_SYMBOL EnvVarName { + $$ = $1; + } MultipleIds: -{ - $$ = 0; -} -| -ID MultipleIds -{ - $$ = yyGetParser->CombineUnions($1, $2); -} + { + $$ = 0; + } +| ID MultipleIds { + $$ = yyGetParser->CombineUnions($1, $2); + } ID: -cal_NAME -{ - $$ = $1; -} -| -Variable -{ - $$ = $1; -} - + cal_NAME { + $$ = $1; + } +| Variable { + $$ = $1; + } +; %% /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmCommandArgumentError(yyscan_t yyscanner, const char* message) +void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } - diff --git a/Source/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h similarity index 52% rename from Source/cmCommandArgumentParserTokens.h rename to Source/LexerParser/cmCommandArgumentParserTokens.h index d162b827c..3172182d7 100644 --- a/Source/cmCommandArgumentParserTokens.h +++ b/Source/LexerParser/cmCommandArgumentParserTokens.h @@ -1,16 +1,13 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/* A Bison parser, made by GNU Bison 2.3. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,9 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -35,25 +30,34 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -/* Tokens. */ +#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 - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - 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 - }; + 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 @@ -69,15 +73,10 @@ #define cal_ERROR 268 #define cal_ATNAME 269 +/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - - +int cmCommandArgument_yyparse (yyscan_t yyscanner); +#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */ diff --git a/Source/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx similarity index 100% rename from Source/cmDependsJavaLexer.cxx rename to Source/LexerParser/cmDependsJavaLexer.cxx diff --git a/Source/cmDependsJavaLexer.h b/Source/LexerParser/cmDependsJavaLexer.h similarity index 100% rename from Source/cmDependsJavaLexer.h rename to Source/LexerParser/cmDependsJavaLexer.h diff --git a/Source/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l similarity index 100% rename from Source/cmDependsJavaLexer.in.l rename to Source/LexerParser/cmDependsJavaLexer.in.l diff --git a/Source/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx similarity index 58% rename from Source/cmDependsJavaParser.cxx rename to Source/LexerParser/cmDependsJavaParser.cxx index b99d63146..bc45d45e1 100644 --- a/Source/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -1,12 +1,13 @@ -/* A Bison parser, made by GNU Bison 1.875d. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, - 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Bison implementation for Yacc-like parsers in C - This program is free software; you can redistribute it and/or modify + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,17 +15,23 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ -/* Written by Richard Stallman by simplifying the original so called - ``semantic'' parser. */ +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local @@ -33,145 +40,223 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ -/* turn off some warning as this is generated code */ -#if defined(_MSC_VER) -# pragma warning ( disable : 4702 ) /* unreachable code */ -#endif - /* Identify Bison output. */ #define YYBISON 1 +/* Bison version. */ +#define YYBISON_VERSION "3.0.4" + /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 +/* Push parsers. */ +#define YYPUSH 0 -/* If NAME_PREFIX is specified substitute the variables and functions - names. */ -#define yyparse cmDependsJava_yyparse -#define yylex cmDependsJava_yylex -#define yyerror cmDependsJava_yyerror -#define yylval cmDependsJava_yylval -#define yychar cmDependsJava_yychar -#define yydebug cmDependsJava_yydebug -#define yynerrs cmDependsJava_yynerrs +/* Pull parsers. */ +#define YYPULL 1 -/* Tokens. */ +/* Substitute the variable and function names. */ +#define yyparse cmDependsJava_yyparse +#define yylex cmDependsJava_yylex +#define yyerror cmDependsJava_yyerror +#define yydebug cmDependsJava_yydebug +#define yynerrs cmDependsJava_yynerrs + + +/* Copy the first part of user declarations. */ +#line 1 "cmDependsJavaParser.y" /* yacc.c:339 */ + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +/* + +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:"] + +*/ + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include +#include + +#define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) + +/*-------------------------------------------------------------------------*/ +#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; + +/* Helper function to forward error callback from parser. */ +static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); + +#define YYMAXDEPTH 1000000 + + +#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); +#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) +#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) +/* Disable some warnings in the generated code. */ +#ifdef _MSC_VER +# pragma warning (disable: 4102) /* Unused goto label. */ +# pragma warning (disable: 4065) /* Switch statement contains default but no case. */ +#endif + +#line 120 "cmDependsJavaParser.cxx" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "cmDependsJavaParserTokens.h". */ +#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 + +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - 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 - }; + 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 @@ -276,141 +361,205 @@ #define jp_TIMESEQUALS 359 #define jp_ERROR 360 +/* Value type. */ -/* Copy the first part of user declarations. */ -#line 1 "cmDependsJavaParser.y" +int cmDependsJava_yyparse (yyscan_t yyscanner); -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/* +#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */ -This file must be translated to C and modified to build everywhere. +/* Copy the second part of user declarations. */ -Run bison like this: +#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358 */ - bison --yacc --name-prefix=cmDependsJava_yy - --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx - cmDependsJavaParser.y +#ifdef short +# undef short +#endif -Modify cmDependsJavaParser.c: - - remove TABs +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif -*/ +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmDependsJava_yyerror(x) \ - cmDependsJavaError(yyscanner, x) -#define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif -/*-------------------------------------------------------------------------*/ -#include "cmDependsJavaParserHelper.h" /* Interface to parser object. */ -#include "cmDependsJavaLexer.h" /* Interface to lexer object. */ -#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL. */ +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif -/* Forward declare the lexer entry point. */ -YY_DECL; +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif -/* Internal utility functions. */ -static void cmDependsJavaError(yyscan_t yyscanner, const char* message); +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) -#define YYDEBUG 1 -#define YYMAXDEPTH 1000000 +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# 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 -#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); -#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) -#define jpStoreClass(str) \ -yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) -/* Disable some warnings in the generated code. */ -#ifdef _MSC_VER -# pragma warning (disable: 4102) /* Unused goto label. */ -# pragma warning (disable: 4065) /* Switch statement contains default but - no case. */ +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) #endif +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif #endif -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) #else -# define YYERROR_VERBOSE 0 +# define YYUSE(E) /* empty */ #endif -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 +#if defined __GNUC__ && 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\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif - -/* Copy the second part of user declarations. */ - - -/* Line 214 of yacc.c. */ -#line 372 "cmDependsJavaParser.cxx" - -#if ! defined (yyoverflow) || YYERROR_VERBOSE - -# ifndef YYFREE -# define YYFREE free -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# endif +#if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca -# endif -# else -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca -# else # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif # endif # endif # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ + /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# else -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif +# else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif # endif -#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - short int yyss; - YYSTYPE yyvs; - }; + yytype_int16 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) @@ -418,74 +567,74 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined (__GNUC__) && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (0) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ while (0) #endif -#if defined (__STDC__) || defined (__cplusplus) - typedef signed char yysigned_char; -#else - typedef short int yysigned_char; -#endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ -/* YYFINAL -- State number of the termination state. */ +/* YYFINAL -- State number of the termination state. */ #define YYFINAL 23 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 2215 -/* YYNTOKENS -- Number of terminals. */ +/* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 106 -/* YYNNTS -- Number of nonterminals. */ +/* YYNNTS -- Number of nonterminals. */ #define YYNNTS 158 -/* YYNRULES -- Number of rules. */ +/* YYNRULES -- Number of rules. */ #define YYNRULES 351 -/* YYNRULES -- Number of states. */ +/* YYNSTATES -- Number of states. */ #define YYNSTATES 575 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 360 -#define YYTRANSLATE(YYX) \ +#define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const unsigned char yytranslate[] = +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -527,201 +676,51 @@ static const unsigned char yytranslate[] = }; #if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const unsigned short int yyprhs[] = -{ - 0, 0, 3, 5, 7, 9, 11, 13, 15, 17, - 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, - 39, 41, 43, 45, 47, 49, 51, 54, 57, 59, - 61, 63, 65, 68, 72, 76, 80, 84, 86, 88, - 92, 93, 95, 96, 99, 100, 103, 107, 109, 111, - 115, 121, 123, 125, 127, 129, 132, 134, 136, 138, - 140, 142, 144, 146, 148, 150, 152, 154, 158, 161, - 165, 169, 174, 175, 177, 180, 183, 185, 189, 193, - 194, 197, 199, 201, 203, 205, 207, 209, 214, 216, - 220, 222, 226, 228, 232, 234, 236, 239, 242, 246, - 251, 256, 257, 259, 264, 268, 269, 271, 273, 277, - 281, 284, 286, 290, 292, 295, 300, 306, 311, 316, - 317, 320, 326, 332, 336, 340, 341, 343, 346, 350, - 354, 355, 358, 360, 362, 364, 367, 369, 372, 374, - 377, 379, 382, 386, 387, 389, 392, 394, 398, 402, - 403, 405, 407, 410, 412, 414, 416, 419, 423, 426, - 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, - 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, - 468, 470, 472, 474, 478, 482, 485, 487, 489, 491, - 493, 495, 497, 499, 505, 513, 521, 527, 532, 533, - 535, 536, 539, 542, 544, 547, 551, 554, 560, 566, - 574, 584, 585, 587, 588, 590, 600, 601, 603, 605, - 607, 609, 611, 615, 619, 625, 629, 630, 632, 636, - 640, 644, 650, 654, 659, 660, 662, 664, 667, 673, - 676, 678, 680, 682, 684, 688, 690, 692, 694, 696, - 703, 704, 706, 707, 709, 711, 715, 720, 725, 730, - 735, 736, 738, 740, 743, 747, 750, 754, 758, 762, - 766, 770, 775, 782, 789, 796, 801, 806, 808, 810, - 814, 816, 818, 821, 824, 826, 828, 831, 834, 836, - 839, 842, 844, 847, 850, 852, 858, 863, 869, 871, - 875, 879, 883, 885, 889, 893, 895, 899, 903, 907, - 909, 913, 917, 921, 925, 929, 931, 935, 939, 941, - 945, 947, 951, 953, 957, 959, 963, 965, 969, 971, - 977, 979, 981, 985, 987, 989, 991, 993, 995, 997, - 999, 1001, 1003, 1005, 1007, 1009, 1011, 1013, 1015, 1017, - 1019, 1021 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const short int yyrhs[] = -{ - 107, 0, -1, 122, -1, 109, -1, 53, -1, 50, - -1, 51, -1, 56, -1, 55, -1, 52, -1, 54, - -1, 111, -1, 112, -1, 7, -1, 36, -1, 26, - -1, 28, -1, 10, -1, 20, -1, 15, -1, 5, - -1, 113, -1, 116, -1, 117, -1, 113, -1, 113, - -1, 111, 234, -1, 117, 234, -1, 118, -1, 120, - -1, 119, -1, 57, -1, 71, 57, -1, 117, 72, - 119, -1, 117, 72, 11, -1, 117, 72, 42, -1, - 121, 72, 11, -1, 111, -1, 47, -1, 123, 124, - 125, -1, -1, 126, -1, -1, 124, 127, -1, -1, - 125, 130, -1, 31, 117, 101, -1, 128, -1, 129, - -1, 24, 117, 101, -1, 24, 117, 72, 103, 101, - -1, 134, -1, 165, -1, 101, -1, 132, -1, 131, - 132, -1, 34, -1, 33, -1, 32, -1, 37, -1, - 3, -1, 18, -1, 29, -1, 41, -1, 45, -1, - 48, -1, 38, -1, 135, 11, 119, -1, 133, 139, - -1, 133, 137, 139, -1, 133, 136, 139, -1, 133, - 136, 137, 139, -1, -1, 131, -1, 17, 114, -1, - 23, 138, -1, 115, -1, 138, 66, 115, -1, 68, - 140, 67, -1, -1, 140, 141, -1, 142, -1, 158, - -1, 159, -1, 130, -1, 143, -1, 148, -1, 135, - 110, 144, 101, -1, 145, -1, 144, 66, 145, -1, - 146, -1, 146, 73, 147, -1, 119, -1, 146, 62, - 61, -1, 261, -1, 174, -1, 149, 101, -1, 149, - 157, -1, 149, 157, 101, -1, 135, 110, 151, 150, - -1, 135, 47, 151, 150, -1, -1, 155, -1, 119, - 91, 152, 90, -1, 151, 62, 61, -1, -1, 153, - -1, 154, -1, 153, 66, 154, -1, 135, 110, 146, - -1, 44, 156, -1, 114, -1, 156, 66, 114, -1, - 177, -1, 37, 177, -1, 135, 160, 150, 161, -1, - 135, 160, 150, 161, 101, -1, 118, 91, 152, 90, - -1, 68, 162, 178, 67, -1, -1, 162, 163, -1, - 42, 91, 228, 90, 101, -1, 39, 91, 228, 90, - 101, -1, 135, 27, 119, -1, 164, 166, 168, -1, - -1, 167, -1, 17, 115, -1, 167, 66, 115, -1, - 68, 169, 67, -1, -1, 169, 170, -1, 171, -1, - 172, -1, 134, -1, 134, 101, -1, 165, -1, 165, - 101, -1, 143, -1, 149, 173, -1, 101, -1, 173, - 101, -1, 68, 175, 67, -1, -1, 176, -1, 176, - 66, -1, 147, -1, 176, 66, 147, -1, 68, 178, - 67, -1, -1, 179, -1, 180, -1, 179, 180, -1, - 181, -1, 183, -1, 134, -1, 182, 101, -1, 131, - 110, 144, -1, 110, 144, -1, 185, -1, 187, -1, - 191, -1, 192, -1, 201, -1, 204, -1, 185, -1, - 188, -1, 193, -1, 202, -1, 207, -1, 177, -1, - 186, -1, 189, -1, 194, -1, 203, -1, 213, -1, - 215, -1, 216, -1, 218, -1, 217, -1, 219, -1, - 212, -1, 101, -1, 119, 65, 183, -1, 119, 65, - 184, -1, 190, 101, -1, 258, -1, 242, -1, 243, - -1, 239, -1, 240, -1, 236, -1, 226, -1, 22, - 91, 261, 90, 183, -1, 22, 91, 261, 90, 184, - 16, 183, -1, 22, 91, 261, 90, 184, 16, 184, - -1, 40, 91, 261, 90, 195, -1, 68, 197, 196, - 67, -1, -1, 199, -1, -1, 197, 198, -1, 199, - 179, -1, 200, -1, 199, 200, -1, 8, 262, 65, - -1, 13, 65, -1, 49, 91, 261, 90, 183, -1, - 49, 91, 261, 90, 184, -1, 14, 183, 49, 91, - 261, 90, 101, -1, 21, 91, 206, 101, 208, 101, - 205, 90, 183, -1, -1, 210, -1, -1, 209, -1, - 21, 91, 206, 101, 208, 101, 205, 90, 184, -1, - -1, 261, -1, 211, -1, 182, -1, 211, -1, 190, - -1, 211, 66, 190, -1, 4, 261, 101, -1, 4, - 261, 65, 261, 101, -1, 6, 214, 101, -1, -1, - 119, -1, 12, 214, 101, -1, 35, 208, 101, -1, - 43, 261, 101, -1, 41, 91, 261, 90, 177, -1, - 46, 177, 221, -1, 46, 177, 220, 223, -1, -1, - 221, -1, 222, -1, 221, 222, -1, 9, 91, 154, - 90, 177, -1, 19, 177, -1, 225, -1, 230, -1, - 108, -1, 42, -1, 91, 261, 90, -1, 226, -1, - 235, -1, 236, -1, 237, -1, 263, 114, 91, 228, - 90, 227, -1, -1, 139, -1, -1, 229, -1, 261, - -1, 229, 66, 261, -1, 263, 111, 232, 231, -1, - 263, 113, 232, 231, -1, 263, 111, 234, 174, -1, - 263, 113, 234, 174, -1, -1, 234, -1, 233, -1, - 232, 233, -1, 62, 261, 61, -1, 62, 61, -1, - 234, 62, 61, -1, 224, 72, 119, -1, 39, 72, - 119, -1, 42, 72, 119, -1, 224, 72, 42, -1, - 117, 91, 228, 90, -1, 224, 72, 119, 91, 228, - 90, -1, 39, 72, 119, 91, 228, 90, -1, 42, - 72, 119, 91, 228, 90, -1, 117, 62, 261, 61, - -1, 225, 62, 261, 61, -1, 224, -1, 117, -1, - 116, 72, 11, -1, 239, -1, 240, -1, 238, 99, - -1, 238, 89, -1, 242, -1, 243, -1, 97, 241, - -1, 87, 241, -1, 244, -1, 99, 241, -1, 89, - 241, -1, 238, -1, 102, 241, -1, 75, 241, -1, - 245, -1, 91, 111, 231, 90, 241, -1, 91, 261, - 90, 244, -1, 91, 117, 234, 90, 244, -1, 241, - -1, 246, 103, 241, -1, 246, 69, 241, -1, 246, - 92, 241, -1, 246, -1, 247, 97, 246, -1, 247, - 87, 246, -1, 247, -1, 248, 86, 247, -1, 248, - 79, 247, -1, 248, 81, 247, -1, 248, -1, 249, - 84, 248, -1, 249, 77, 248, -1, 249, 85, 248, - -1, 249, 78, 248, -1, 249, 25, 112, -1, 249, - -1, 250, 74, 249, -1, 250, 76, 249, -1, 250, - -1, 251, 58, 250, -1, 251, -1, 252, 63, 251, - -1, 252, -1, 253, 94, 252, -1, 253, -1, 254, - 59, 253, -1, 254, -1, 255, 96, 254, -1, 255, - -1, 255, 100, 261, 65, 256, -1, 256, -1, 258, - -1, 259, 260, 257, -1, 117, -1, 235, -1, 237, - -1, 73, -1, 104, -1, 70, -1, 93, -1, 98, - -1, 88, -1, 83, -1, 80, -1, 82, -1, 60, - -1, 64, -1, 95, -1, 257, -1, 261, -1, 30, - -1, 117, 72, 30, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned short int yyrline[] = + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = { - 0, 191, 191, 200, 208, 216, 224, 232, 240, 249, - 257, 266, 274, 283, 288, 293, 298, 303, 308, 313, - 318, 324, 332, 341, 351, 360, 369, 377, 387, 393, - 400, 407, 413, 420, 429, 439, 449, 458, 466, 475, - 484, 490, 499, 505, 514, 520, 529, 541, 549, 558, - 570, 583, 591, 599, 608, 616, 625, 625, 625, 626, - 627, 627, 627, 627, 627, 627, 628, 631, 641, 650, - 659, 668, 678, 684, 693, 702, 711, 719, 728, 737, - 743, 752, 760, 768, 776, 785, 793, 802, 808, 816, - 825, 833, 842, 851, 860, 868, 877, 885, 893, 902, - 911, 921, 928, 938, 948, 955, 962, 965, 971, 981, - 991, 1001, 1007, 1017, 1027, 1037, 1046, 1056, 1067, 1077, - 1084, 1094, 1103, 1113, 1122, 1132, 1138, 1148, 1157, 1167, - 1177, 1184, 1193, 1202, 1211, 1220, 1228, 1237, 1246, 1256, - 1266, 1275, 1285, 1295, 1302, 1311, 1321, 1330, 1340, 1349, - 1356, 1366, 1375, 1385, 1394, 1403, 1413, 1423, 1432, 1442, - 1451, 1460, 1469, 1478, 1487, 1497, 1506, 1515, 1524, 1533, - 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, 1615, 1624, - 1633, 1642, 1652, 1662, 1673, 1683, 1693, 1702, 1711, 1720, - 1729, 1738, 1747, 1757, 1767, 1777, 1787, 1794, 1801, 1808, - 1818, 1825, 1835, 1845, 1854, 1864, 1873, 1883, 1890, 1897, - 1904, 1912, 1919, 1929, 1936, 1946, 1956, 1963, 1973, 1982, - 1992, 2002, 2011, 2021, 2030, 2040, 2051, 2058, 2065, 2076, - 2086, 2096, 2106, 2115, 2125, 2132, 2142, 2151, 2161, 2168, - 2178, 2187, 2197, 2206, 2212, 2221, 2230, 2239, 2248, 2258, - 2268, 2275, 2285, 2292, 2302, 2311, 2321, 2330, 2339, 2348, - 2358, 2365, 2375, 2384, 2394, 2404, 2410, 2417, 2427, 2437, - 2447, 2458, 2468, 2479, 2489, 2500, 2510, 2520, 2529, 2538, - 2547, 2556, 2566, 2576, 2586, 2595, 2604, 2613, 2622, 2632, - 2642, 2652, 2661, 2670, 2679, 2689, 2698, 2707, 2714, 2723, - 2732, 2741, 2751, 2760, 2769, 2779, 2788, 2797, 2806, 2816, - 2825, 2834, 2843, 2852, 2861, 2871, 2880, 2889, 2899, 2908, - 2918, 2927, 2937, 2946, 2956, 2965, 2975, 2984, 2994, 3003, - 3013, 3022, 3032, 3042, 3052, 3061, 3071, 3080, 3089, 3098, - 3107, 3116, 3125, 3134, 3143, 3152, 3161, 3170, 3180, 3190, - 3200, 3209 + 0, 179, 179, 188, 196, 204, 212, 220, 228, 237, + 245, 254, 262, 271, 276, 281, 286, 291, 296, 301, + 306, 312, 320, 329, 339, 348, 357, 365, 375, 381, + 388, 395, 401, 408, 417, 427, 437, 446, 454, 463, + 472, 478, 487, 493, 502, 508, 517, 529, 537, 546, + 558, 571, 579, 587, 596, 604, 613, 613, 613, 614, + 615, 615, 615, 615, 615, 615, 616, 619, 629, 638, + 647, 656, 666, 672, 681, 690, 699, 707, 716, 725, + 731, 740, 748, 756, 764, 773, 781, 790, 796, 804, + 813, 821, 830, 839, 848, 856, 865, 873, 881, 890, + 899, 909, 916, 926, 936, 943, 950, 953, 959, 969, + 979, 989, 995, 1005, 1015, 1025, 1034, 1044, 1055, 1065, + 1072, 1082, 1091, 1101, 1110, 1120, 1126, 1136, 1145, 1155, + 1165, 1172, 1181, 1190, 1199, 1208, 1216, 1225, 1234, 1244, + 1254, 1263, 1273, 1283, 1290, 1299, 1309, 1318, 1328, 1337, + 1344, 1354, 1363, 1373, 1382, 1391, 1401, 1411, 1420, 1430, + 1439, 1448, 1457, 1466, 1475, 1485, 1494, 1503, 1512, 1521, + 1531, 1540, 1549, 1558, 1567, 1576, 1585, 1594, 1603, 1612, + 1621, 1630, 1640, 1650, 1661, 1671, 1681, 1690, 1699, 1708, + 1717, 1726, 1735, 1745, 1755, 1765, 1775, 1782, 1789, 1796, + 1806, 1813, 1823, 1833, 1842, 1852, 1861, 1871, 1878, 1885, + 1892, 1900, 1907, 1917, 1924, 1934, 1944, 1951, 1961, 1970, + 1980, 1990, 1999, 2009, 2018, 2028, 2039, 2046, 2053, 2064, + 2074, 2084, 2094, 2103, 2113, 2120, 2130, 2139, 2149, 2156, + 2166, 2175, 2185, 2194, 2200, 2209, 2218, 2227, 2236, 2246, + 2256, 2263, 2273, 2280, 2290, 2299, 2309, 2318, 2327, 2336, + 2346, 2353, 2363, 2372, 2382, 2392, 2398, 2405, 2415, 2425, + 2435, 2446, 2456, 2467, 2477, 2488, 2498, 2508, 2517, 2526, + 2535, 2544, 2554, 2564, 2574, 2583, 2592, 2601, 2610, 2620, + 2630, 2640, 2649, 2658, 2667, 2677, 2686, 2695, 2702, 2711, + 2720, 2729, 2739, 2748, 2757, 2767, 2776, 2785, 2794, 2804, + 2813, 2822, 2831, 2840, 2849, 2859, 2868, 2877, 2887, 2896, + 2906, 2915, 2925, 2934, 2944, 2953, 2963, 2972, 2982, 2991, + 3001, 3010, 3020, 3030, 3040, 3049, 3059, 3068, 3077, 3086, + 3095, 3104, 3113, 3122, 3131, 3140, 3149, 3158, 3168, 3178, + 3188, 3197 }; #endif -#if YYDEBUG || YYERROR_VERBOSE -/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +#if YYDEBUG || YYERROR_VERBOSE || 1 +/* 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", @@ -798,14 +797,14 @@ static const char *const yytname[] = "ConditionalAndExpression", "ConditionalOrExpression", "ConditionalExpression", "AssignmentExpression", "Assignment", "LeftHandSide", "AssignmentOperator", "Expression", "ConstantExpression", - "New", 0 + "New", YY_NULLPTR }; #endif # ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const unsigned short int yytoknum[] = +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, @@ -821,178 +820,19 @@ static const unsigned short int yytoknum[] = }; # endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const unsigned short int yyr1[] = -{ - 0, 106, 107, 108, 108, 108, 108, 108, 108, 109, - 109, 110, 110, 111, 111, 111, 111, 111, 111, 111, - 111, 112, 112, 113, 114, 115, 116, 116, 117, 117, - 118, 119, 119, 120, 120, 120, 120, 121, 121, 122, - 123, 123, 124, 124, 125, 125, 126, 127, 127, 128, - 129, 130, 130, 130, 131, 131, 132, 132, 132, 132, - 132, 132, 132, 132, 132, 132, 132, 133, 134, 134, - 134, 134, 135, 135, 136, 137, 138, 138, 139, 140, - 140, 141, 141, 141, 141, 142, 142, 143, 144, 144, - 145, 145, 146, 146, 147, 147, 148, 148, 148, 149, - 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, - 155, 156, 156, 157, 158, 159, 159, 160, 161, 162, - 162, 163, 163, 164, 165, 166, 166, 167, 167, 168, - 169, 169, 170, 170, 170, 170, 170, 170, 171, 172, - 173, 173, 174, 175, 175, 175, 176, 176, 177, 178, - 178, 179, 179, 180, 180, 180, 181, 182, 182, 183, - 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, - 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 185, 185, 186, 187, 188, 189, 190, 190, 190, 190, - 190, 190, 190, 191, 192, 193, 194, 195, 196, 196, - 197, 197, 198, 199, 199, 200, 200, 201, 202, 203, - 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, - 210, 211, 211, 212, 212, 213, 214, 214, 215, 216, - 217, 218, 219, 219, 220, 220, 221, 221, 222, 223, - 224, 224, 225, 225, 225, 225, 225, 225, 225, 226, - 227, 227, 228, 228, 229, 229, 230, 230, 230, 230, - 231, 231, 232, 232, 233, 234, 234, 235, 235, 235, - 235, 236, 236, 236, 236, 237, 237, 238, 238, 238, - 238, 238, 239, 240, 241, 241, 241, 241, 241, 242, - 243, 244, 244, 244, 244, 245, 245, 245, 246, 246, - 246, 246, 247, 247, 247, 248, 248, 248, 248, 249, - 249, 249, 249, 249, 249, 250, 250, 250, 251, 251, - 252, 252, 253, 253, 254, 254, 255, 255, 256, 256, - 257, 257, 258, 259, 259, 259, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 261, 262, - 263, 263 -}; +#define YYPACT_NINF -503 -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const unsigned char yyr2[] = -{ - 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, - 1, 1, 2, 3, 3, 3, 3, 1, 1, 3, - 0, 1, 0, 2, 0, 2, 3, 1, 1, 3, - 5, 1, 1, 1, 1, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, - 3, 4, 0, 1, 2, 2, 1, 3, 3, 0, - 2, 1, 1, 1, 1, 1, 1, 4, 1, 3, - 1, 3, 1, 3, 1, 1, 2, 2, 3, 4, - 4, 0, 1, 4, 3, 0, 1, 1, 3, 3, - 2, 1, 3, 1, 2, 4, 5, 4, 4, 0, - 2, 5, 5, 3, 3, 0, 1, 2, 3, 3, - 0, 2, 1, 1, 1, 2, 1, 2, 1, 2, - 1, 2, 3, 0, 1, 2, 1, 3, 3, 0, - 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 3, 2, 1, 1, 1, 1, - 1, 1, 1, 5, 7, 7, 5, 4, 0, 1, - 0, 2, 2, 1, 2, 3, 2, 5, 5, 7, - 9, 0, 1, 0, 1, 9, 0, 1, 1, 1, - 1, 1, 3, 3, 5, 3, 0, 1, 3, 3, - 3, 5, 3, 4, 0, 1, 1, 2, 5, 2, - 1, 1, 1, 1, 3, 1, 1, 1, 1, 6, - 0, 1, 0, 1, 1, 3, 4, 4, 4, 4, - 0, 1, 1, 2, 3, 2, 3, 3, 3, 3, - 3, 4, 6, 6, 6, 4, 4, 1, 1, 3, - 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, - 2, 1, 2, 2, 1, 5, 4, 5, 1, 3, - 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, - 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, - 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3 -}; +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-503))) -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const unsigned short int yydefact[] = -{ - 40, 0, 0, 2, 42, 41, 20, 13, 17, 19, - 18, 15, 16, 14, 38, 31, 0, 37, 0, 28, - 30, 29, 0, 1, 44, 32, 0, 46, 0, 0, - 72, 43, 47, 48, 34, 35, 33, 36, 0, 60, - 61, 62, 58, 57, 56, 59, 66, 63, 64, 65, - 53, 45, 73, 54, 0, 51, 0, 125, 52, 0, - 49, 55, 0, 0, 79, 0, 0, 68, 0, 0, - 0, 0, 126, 0, 24, 74, 23, 25, 76, 75, - 72, 0, 70, 69, 67, 123, 127, 130, 124, 0, - 50, 0, 59, 78, 84, 0, 80, 81, 85, 86, - 0, 82, 83, 71, 72, 128, 77, 72, 114, 38, - 0, 11, 12, 21, 22, 23, 28, 101, 96, 97, - 113, 129, 134, 0, 138, 0, 136, 131, 132, 133, - 0, 226, 226, 0, 0, 0, 350, 216, 0, 0, - 63, 243, 0, 0, 0, 5, 6, 9, 4, 10, - 8, 7, 0, 0, 0, 182, 242, 3, 0, 22, - 333, 30, 73, 155, 0, 170, 0, 72, 151, 153, - 0, 154, 159, 171, 160, 172, 0, 161, 162, 173, - 163, 174, 164, 181, 175, 176, 177, 179, 178, 180, - 277, 240, 245, 241, 246, 247, 248, 0, 189, 190, - 187, 188, 186, 0, 0, 0, 101, 92, 0, 88, - 90, 101, 0, 26, 27, 72, 0, 0, 102, 98, - 135, 140, 139, 137, 0, 0, 0, 0, 0, 37, - 0, 278, 245, 247, 291, 280, 281, 298, 284, 285, - 288, 294, 302, 305, 309, 315, 318, 320, 322, 324, - 326, 328, 330, 348, 331, 0, 227, 0, 0, 0, - 0, 213, 0, 0, 217, 0, 0, 0, 0, 0, - 234, 0, 278, 246, 248, 290, 0, 289, 92, 158, - 0, 0, 0, 252, 0, 0, 148, 152, 156, 185, - 0, 0, 283, 282, 345, 346, 338, 336, 343, 344, - 342, 341, 339, 347, 340, 337, 0, 37, 24, 0, - 72, 0, 100, 0, 87, 0, 0, 99, 265, 0, - 0, 0, 106, 107, 111, 110, 119, 115, 141, 293, - 287, 37, 278, 0, 286, 292, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 223, 225, - 228, 0, 0, 219, 221, 0, 214, 218, 0, 229, - 268, 0, 0, 269, 230, 0, 0, 232, 236, 0, - 244, 279, 0, 351, 0, 253, 254, 183, 157, 270, - 267, 0, 332, 0, 260, 262, 0, 260, 0, 252, - 0, 104, 89, 93, 143, 91, 95, 94, 266, 0, - 117, 72, 0, 72, 116, 0, 26, 27, 244, 300, - 301, 299, 304, 303, 307, 308, 306, 314, 311, 313, - 310, 312, 316, 317, 319, 321, 323, 325, 327, 0, - 0, 0, 216, 0, 0, 252, 0, 0, 252, 72, - 0, 233, 237, 0, 275, 271, 0, 252, 276, 0, - 256, 263, 261, 258, 257, 259, 0, 103, 146, 0, - 144, 109, 108, 112, 0, 243, 120, 0, 0, 0, - 296, 0, 224, 0, 0, 222, 0, 0, 0, 30, - 193, 0, 159, 166, 167, 168, 169, 0, 200, 196, - 231, 0, 0, 239, 207, 255, 0, 264, 250, 142, - 145, 252, 252, 118, 295, 297, 329, 0, 211, 213, - 0, 0, 0, 0, 273, 198, 274, 0, 272, 251, - 249, 147, 0, 0, 209, 0, 212, 220, 0, 0, - 0, 184, 194, 0, 0, 0, 201, 72, 203, 238, - 0, 0, 0, 216, 0, 0, 349, 0, 206, 197, - 202, 204, 122, 121, 210, 0, 0, 208, 205, 211, - 0, 0, 195, 0, 215 -}; +#define YYTABLE_NINF -336 -/* YYDEFGOTO[NTERM-NUM]. */ -static const short int yydefgoto[] = -{ - -1, 2, 156, 157, 158, 229, 112, 113, 75, 78, - 230, 231, 19, 20, 21, 22, 3, 4, 24, 30, - 5, 31, 32, 33, 51, 52, 53, 54, 163, 164, - 65, 66, 79, 67, 80, 96, 97, 98, 208, 209, - 210, 405, 99, 100, 217, 206, 321, 322, 323, 218, - 325, 119, 101, 102, 117, 327, 413, 476, 57, 58, - 71, 72, 88, 104, 127, 128, 129, 222, 406, 469, - 470, 165, 166, 167, 168, 169, 170, 171, 491, 172, - 173, 174, 493, 175, 176, 177, 178, 494, 179, 499, - 545, 525, 546, 547, 548, 180, 495, 181, 182, 535, - 365, 496, 263, 366, 536, 367, 183, 184, 257, 185, - 186, 187, 188, 189, 376, 377, 378, 451, 190, 191, - 232, 530, 384, 385, 193, 415, 394, 395, 214, 194, - 233, 196, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 203, 306, 386, 557, 204 -}; +#define yytable_value_is_error(Yytable_value) \ + 0 -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -503 -static const short int yypact[] = + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = { 159, 1039, 236, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, 186, -503, 56, -503, @@ -1054,8 +894,73 @@ static const short int yypact[] = 1699, 432, -503, 1699, -503 }; -/* YYPGOTO[NTERM-NUM]. */ -static const short int yypgoto[] = + /* 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[] = +{ + 40, 0, 0, 2, 42, 41, 20, 13, 17, 19, + 18, 15, 16, 14, 38, 31, 0, 37, 0, 28, + 30, 29, 0, 1, 44, 32, 0, 46, 0, 0, + 72, 43, 47, 48, 34, 35, 33, 36, 0, 60, + 61, 62, 58, 57, 56, 59, 66, 63, 64, 65, + 53, 45, 73, 54, 0, 51, 0, 125, 52, 0, + 49, 55, 0, 0, 79, 0, 0, 68, 0, 0, + 0, 0, 126, 0, 24, 74, 23, 25, 76, 75, + 72, 0, 70, 69, 67, 123, 127, 130, 124, 0, + 50, 0, 59, 78, 84, 0, 80, 81, 85, 86, + 0, 82, 83, 71, 72, 128, 77, 72, 114, 38, + 0, 11, 12, 21, 22, 23, 28, 101, 96, 97, + 113, 129, 134, 0, 138, 0, 136, 131, 132, 133, + 0, 226, 226, 0, 0, 0, 350, 216, 0, 0, + 63, 243, 0, 0, 0, 5, 6, 9, 4, 10, + 8, 7, 0, 0, 0, 182, 242, 3, 0, 22, + 333, 30, 73, 155, 0, 170, 0, 72, 151, 153, + 0, 154, 159, 171, 160, 172, 0, 161, 162, 173, + 163, 174, 164, 181, 175, 176, 177, 179, 178, 180, + 277, 240, 245, 241, 246, 247, 248, 0, 189, 190, + 187, 188, 186, 0, 0, 0, 101, 92, 0, 88, + 90, 101, 0, 26, 27, 72, 0, 0, 102, 98, + 135, 140, 139, 137, 0, 0, 0, 0, 0, 37, + 0, 278, 245, 247, 291, 280, 281, 298, 284, 285, + 288, 294, 302, 305, 309, 315, 318, 320, 322, 324, + 326, 328, 330, 348, 331, 0, 227, 0, 0, 0, + 0, 213, 0, 0, 217, 0, 0, 0, 0, 0, + 234, 0, 278, 246, 248, 290, 0, 289, 92, 158, + 0, 0, 0, 252, 0, 0, 148, 152, 156, 185, + 0, 0, 283, 282, 345, 346, 338, 336, 343, 344, + 342, 341, 339, 347, 340, 337, 0, 37, 24, 0, + 72, 0, 100, 0, 87, 0, 0, 99, 265, 0, + 0, 0, 106, 107, 111, 110, 119, 115, 141, 293, + 287, 37, 278, 0, 286, 292, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 223, 225, + 228, 0, 0, 219, 221, 0, 214, 218, 0, 229, + 268, 0, 0, 269, 230, 0, 0, 232, 236, 0, + 244, 279, 0, 351, 0, 253, 254, 183, 157, 270, + 267, 0, 332, 0, 260, 262, 0, 260, 0, 252, + 0, 104, 89, 93, 143, 91, 95, 94, 266, 0, + 117, 72, 0, 72, 116, 0, 26, 27, 244, 300, + 301, 299, 304, 303, 307, 308, 306, 314, 311, 313, + 310, 312, 316, 317, 319, 321, 323, 325, 327, 0, + 0, 0, 216, 0, 0, 252, 0, 0, 252, 72, + 0, 233, 237, 0, 275, 271, 0, 252, 276, 0, + 256, 263, 261, 258, 257, 259, 0, 103, 146, 0, + 144, 109, 108, 112, 0, 243, 120, 0, 0, 0, + 296, 0, 224, 0, 0, 222, 0, 0, 0, 30, + 193, 0, 159, 166, 167, 168, 169, 0, 200, 196, + 231, 0, 0, 239, 207, 255, 0, 264, 250, 142, + 145, 252, 252, 118, 295, 297, 329, 0, 211, 213, + 0, 0, 0, 0, 273, 198, 274, 0, 272, 251, + 249, 147, 0, 0, 209, 0, 212, 220, 0, 0, + 0, 184, 194, 0, 0, 0, 201, 72, 203, 238, + 0, 0, 0, 216, 0, 0, 349, 0, 206, 197, + 202, 204, 122, 121, 210, 0, 0, 208, 205, 211, + 0, 0, 195, 0, 215 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = { -503, -503, -503, -503, -85, 2, 181, -41, -198, -45, -87, -1, 431, 14, -503, -503, -503, -503, -503, -503, @@ -1075,12 +980,31 @@ static const short int yypgoto[] = 95, 274, 350, -503, -503, 660, -503, -503 }; -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -336 -static const short int yytable[] = + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 2, 156, 157, 158, 229, 112, 113, 75, 78, + 230, 231, 19, 20, 21, 22, 3, 4, 24, 30, + 5, 31, 32, 33, 51, 52, 53, 54, 163, 164, + 65, 66, 79, 67, 80, 96, 97, 98, 208, 209, + 210, 405, 99, 100, 217, 206, 321, 322, 323, 218, + 325, 119, 101, 102, 117, 327, 413, 476, 57, 58, + 71, 72, 88, 104, 127, 128, 129, 222, 406, 469, + 470, 165, 166, 167, 168, 169, 170, 171, 491, 172, + 173, 174, 493, 175, 176, 177, 178, 494, 179, 499, + 545, 525, 546, 547, 548, 180, 495, 181, 182, 535, + 365, 496, 263, 366, 536, 367, 183, 184, 257, 185, + 186, 187, 188, 189, 376, 377, 378, 451, 190, 191, + 232, 530, 384, 385, 193, 415, 394, 395, 214, 194, + 233, 196, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 203, 306, 386, 557, 204 +}; + + /* 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_int16 yytable[] = { 18, 82, 83, 17, 287, 61, 309, 56, 114, 364, 110, 363, 279, 468, 34, 108, 537, 103, 324, 107, @@ -1306,7 +1230,7 @@ static const short int yytable[] = 0, 0, 0, 0, 0, 305 }; -static const short int yycheck[] = +static const yytype_int16 yycheck[] = { 1, 65, 66, 1, 167, 52, 204, 30, 95, 261, 95, 261, 158, 404, 11, 92, 518, 81, 216, 68, @@ -1532,9 +1456,9 @@ static const short int yycheck[] = -1, -1, -1, -1, -1, 104 }; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const unsigned short int yystos[] = + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint16 yystos[] = { 0, 31, 107, 122, 123, 126, 5, 7, 10, 15, 20, 26, 28, 36, 47, 57, 71, 111, 117, 118, @@ -1596,78 +1520,123 @@ static const unsigned short int yystos[] = 16, 205, 184, 90, 184 }; -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t -#endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -#endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int -#endif - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint16 yyr1[] = +{ + 0, 106, 107, 108, 108, 108, 108, 108, 108, 109, + 109, 110, 110, 111, 111, 111, 111, 111, 111, 111, + 111, 112, 112, 113, 114, 115, 116, 116, 117, 117, + 118, 119, 119, 120, 120, 120, 120, 121, 121, 122, + 123, 123, 124, 124, 125, 125, 126, 127, 127, 128, + 129, 130, 130, 130, 131, 131, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 133, 134, 134, + 134, 134, 135, 135, 136, 137, 138, 138, 139, 140, + 140, 141, 141, 141, 141, 142, 142, 143, 144, 144, + 145, 145, 146, 146, 147, 147, 148, 148, 148, 149, + 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, + 155, 156, 156, 157, 158, 159, 159, 160, 161, 162, + 162, 163, 163, 164, 165, 166, 166, 167, 167, 168, + 169, 169, 170, 170, 170, 170, 170, 170, 171, 172, + 173, 173, 174, 175, 175, 175, 176, 176, 177, 178, + 178, 179, 179, 180, 180, 180, 181, 182, 182, 183, + 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 186, 187, 188, 189, 190, 190, 190, 190, + 190, 190, 190, 191, 192, 193, 194, 195, 196, 196, + 197, 197, 198, 199, 199, 200, 200, 201, 202, 203, + 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, + 210, 211, 211, 212, 212, 213, 214, 214, 215, 216, + 217, 218, 219, 219, 220, 220, 221, 221, 222, 223, + 224, 224, 225, 225, 225, 225, 225, 225, 225, 226, + 227, 227, 228, 228, 229, 229, 230, 230, 230, 230, + 231, 231, 232, 232, 233, 234, 234, 235, 235, 235, + 235, 236, 236, 236, 236, 237, 237, 238, 238, 238, + 238, 238, 239, 240, 241, 241, 241, 241, 241, 242, + 243, 244, 244, 244, 244, 245, 245, 245, 246, 246, + 246, 246, 247, 247, 247, 248, 248, 248, 248, 249, + 249, 249, 249, 249, 249, 250, 250, 250, 251, 251, + 252, 252, 253, 253, 254, 254, 255, 255, 256, 256, + 257, 257, 258, 259, 259, 259, 260, 260, 260, 260, + 260, 260, 260, 260, 260, 260, 260, 260, 261, 262, + 263, 263 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 3, 3, 3, 3, 1, 1, 3, + 0, 1, 0, 2, 0, 2, 3, 1, 1, 3, + 5, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, + 3, 4, 0, 1, 2, 2, 1, 3, 3, 0, + 2, 1, 1, 1, 1, 1, 1, 4, 1, 3, + 1, 3, 1, 3, 1, 1, 2, 2, 3, 4, + 4, 0, 1, 4, 3, 0, 1, 1, 3, 3, + 2, 1, 3, 1, 2, 4, 5, 4, 4, 0, + 2, 5, 5, 3, 3, 0, 1, 2, 3, 3, + 0, 2, 1, 1, 1, 2, 1, 2, 1, 2, + 1, 2, 3, 0, 1, 2, 1, 3, 3, 0, + 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 3, 2, 1, 1, 1, 1, + 1, 1, 1, 5, 7, 7, 5, 4, 0, 1, + 0, 2, 2, 1, 2, 3, 2, 5, 5, 7, + 9, 0, 1, 0, 1, 9, 0, 1, 1, 1, + 1, 1, 3, 3, 5, 3, 0, 1, 3, 3, + 3, 5, 3, 4, 0, 1, 1, 2, 5, 2, + 1, 1, 1, 1, 3, 1, 1, 1, 1, 6, + 0, 1, 0, 1, 1, 3, 4, 4, 4, 4, + 0, 1, 1, 2, 3, 2, 3, 3, 3, 3, + 3, 4, 6, 6, 6, 4, 4, 1, 1, 3, + 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, + 2, 1, 2, 2, 1, 5, 4, 5, 1, 3, + 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, + 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, + 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3 +}; -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab -#define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror ("syntax error: cannot back up");\ - YYERROR; \ - } \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ while (0) -#define YYTERROR 1 -#define YYERRCODE 256 +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). */ -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - ((Current).first_line = (Rhs)[1].first_line, \ - (Current).first_column = (Rhs)[1].first_column, \ - (Current).last_line = (Rhs)[N].last_line, \ - (Current).last_column = (Rhs)[N].last_column) -#endif - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -#else -# define YYLEX yylex (&yylval) -#endif /* Enable debugging if requested. */ #if YYDEBUG @@ -1677,54 +1646,85 @@ while (0) # define YYFPRINTF fprintf # endif -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ } while (0) -# define YYDSYMPRINT(Args) \ -do { \ - if (yydebug) \ - yysymprint Args; \ -} while (0) +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + -# define YYDSYMPRINTF(Title, Token, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yysymprint (stderr, \ - Token, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, yyscanner); \ + YYFPRINTF (stderr, "\n"); \ + } \ } while (0) + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (yyscanner); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); + YYFPRINTF (yyoutput, ")"); +} + /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) static void -yy_stack_print (short int *bottom, short int *top) -#else -static void -yy_stack_print (bottom, top) - short int *bottom; - short int *top; -#endif +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); - for (/* Nothing. */; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } YYFPRINTF (stderr, "\n"); } -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ } while (0) @@ -1732,29 +1732,30 @@ do { \ | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) -static void -yy_reduce_print (int yyrule) -#else static void -yy_reduce_print (yyrule) - int yyrule; -#endif +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; int yyi; - unsigned int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) - YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); - YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); + /* 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); + YYFPRINTF (stderr, "\n"); + } } -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (Rule); \ +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1762,15 +1763,14 @@ do { \ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) -# define YYDSYMPRINT(Args) -# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH +#ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif @@ -1778,58 +1778,40 @@ int yydebug; if the built-in stack extension method is used). Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ -#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 -# undef YYMAXDEPTH -#endif - #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE # ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) +# if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) -# else -yystrlen (yystr) - const char *yystr; -# endif { - const char *yys = yystr; - - while (*yys++ != '\0') + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) continue; - - return yys - yystr - 1; + return yylen; } # endif # endif # ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# 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 * -# if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) -# else -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif { char *yyd = yydest; const char *yys = yysrc; @@ -1842,91 +1824,207 @@ yystpcpy (yydest, yysrc) # endif # endif -#endif /* !YYERROR_VERBOSE */ +# 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 + contains an apostrophe, a comma, or backslash (other than + 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 +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; - + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } -#if YYDEBUG -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ + if (! yyres) + return yystrlen (yystr); -#if defined (__STDC__) || defined (__cplusplus) -static void -yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) -#else -static void -yysymprint (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE *yyvaluep; -#endif + return yystpcpy (yyres, yystr) - yyres; +} +# 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) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; + 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"). */ + 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 + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + 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)) + return 2; + yysize = yysize1; + } + } + } + } - if (yytype < YYNTOKENS) - { - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); -# ifdef YYPRINT - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + 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_ } - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - switch (yytype) + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) { - default: - break; + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; } - YYFPRINTF (yyoutput, ")"); + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } +#endif /* YYERROR_VERBOSE */ -#endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) -static void -yydestruct (int yytype, YYSTYPE *yyvaluep) -#else static void -yydestruct (yytype, yyvaluep) - int yytype; - YYSTYPE *yyvaluep; -#endif +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; - - switch (yytype) - { + YYUSE (yyvaluep); + YYUSE (yyscanner); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - default: - break; - } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } - - -/* Prevent warnings from -Wmissing-prototypes. */ - -#ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM); -# else -int yyparse (); -# endif -#else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - @@ -1935,90 +2033,76 @@ int yyparse (); | yyparse. | `----------*/ -#ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM) -# else -int yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -# endif -#else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) -int -yyparse (void) -#else int -yyparse () - -#endif -#endif +yyparse (yyscan_t yyscanner) { - /* The lookahead symbol. */ +/* The lookahead symbol. */ int yychar; -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ + /* Number of syntax errors so far. */ + int yynerrs; - /* The state stack. */ - short int yyssa[YYINITDEPTH]; - short int *yyss = yyssa; - short int *yyssp; + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + 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; -#define YYPOPSTACK (yyvsp--, yyssp--) + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; - YYSIZE_T yystacksize = YYINITDEPTH; + YYSIZE_T yystacksize; + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; /* 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 + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; + 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. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss; - yyvsp = yyvs; - - + yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. @@ -2026,8 +2110,7 @@ int yynerrs; `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ + have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: @@ -2040,49 +2123,46 @@ int yynerrs; #ifdef 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. */ - YYSTYPE *yyvs1 = yyvs; - short int *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 ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + 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), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE - goto yyoverflowlab; + goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyoverflowlab; + goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; + yystacksize = YYMAXDEPTH; { - short int *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyoverflowlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ @@ -2090,16 +2170,18 @@ int yynerrs; yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) - YYABORT; + YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + if (yystate == YYFINAL) + YYACCEPT; + goto yybackup; /*-----------. @@ -2107,14 +2189,12 @@ int yynerrs; `-----------*/ yybackup: -/* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ -/* yyresume: */ + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -2123,7 +2203,7 @@ yybackup: if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + yychar = yylex (&yylval, yyscanner); } if (yychar <= YYEOF) @@ -2134,7 +2214,7 @@ yybackup: else { yytoken = YYTRANSLATE (yychar); - YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to @@ -2145,31 +2225,28 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } - if (yyn == YYFINAL) - YYACCEPT; - - /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); - - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - *++yyvsp = yylval; - - /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; + /* 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 + goto yynewstate; @@ -2191,7 +2268,7 @@ yyreduce: yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. + '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -2205,3581 +2282,3927 @@ yyreduce: switch (yyn) { case 2: -#line 192 "cmDependsJavaParser.y" +#line 180 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 201 "cmDependsJavaParser.y" +#line 189 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 209 "cmDependsJavaParser.y" +#line 197 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 217 "cmDependsJavaParser.y" +#line 205 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 225 "cmDependsJavaParser.y" +#line 213 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 233 "cmDependsJavaParser.y" +#line 221 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 241 "cmDependsJavaParser.y" +#line 229 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 250 "cmDependsJavaParser.y" +#line 238 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 258 "cmDependsJavaParser.y" +#line 246 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 267 "cmDependsJavaParser.y" +#line 255 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 275 "cmDependsJavaParser.y" +#line 263 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 284 "cmDependsJavaParser.y" +#line 272 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 289 "cmDependsJavaParser.y" +#line 277 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 294 "cmDependsJavaParser.y" +#line 282 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 299 "cmDependsJavaParser.y" +#line 287 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 304 "cmDependsJavaParser.y" +#line 292 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 309 "cmDependsJavaParser.y" +#line 297 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 314 "cmDependsJavaParser.y" +#line 302 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 319 "cmDependsJavaParser.y" +#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 325 "cmDependsJavaParser.y" +#line 313 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 333 "cmDependsJavaParser.y" +#line 321 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 342 "cmDependsJavaParser.y" +#line 330 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - jpStoreClass(yyvsp[0].str); + jpStoreClass((yyvsp[0].str)); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 352 "cmDependsJavaParser.y" +#line 340 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 25: -#line 361 "cmDependsJavaParser.y" +#line 349 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 26: -#line 370 "cmDependsJavaParser.y" +#line 358 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 27: -#line 378 "cmDependsJavaParser.y" +#line 366 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - jpStoreClass(yyvsp[-1].str); + jpStoreClass((yyvsp[-1].str)); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 28: -#line 388 "cmDependsJavaParser.y" +#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 29: -#line 394 "cmDependsJavaParser.y" +#line 382 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 30: -#line 401 "cmDependsJavaParser.y" +#line 389 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 31: -#line 408 "cmDependsJavaParser.y" +#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 32: -#line 414 "cmDependsJavaParser.y" +#line 402 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 33: -#line 421 "cmDependsJavaParser.y" +#line 409 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->AddClassFound(yyvsp[-2].str); - yyGetParser->UpdateCombine(yyvsp[-2].str, yyvsp[0].str); - yyGetParser->DeallocateParserType(&(yyvsp[-2].str)); - yyval.str = const_cast(yyGetParser->GetCurrentCombine()); + yyGetParser->AddClassFound((yyvsp[-2].str)); + yyGetParser->UpdateCombine((yyvsp[-2].str), (yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); + (yyval.str) = const_cast(yyGetParser->GetCurrentCombine()); } +#line 2603 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 34: -#line 430 "cmDependsJavaParser.y" +#line 418 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - jpStoreClass(yyvsp[-2].str); + jpStoreClass((yyvsp[-2].str)); jpCheckEmpty(3); yyGetParser->SetCurrentCombine(""); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 35: -#line 440 "cmDependsJavaParser.y" +#line 428 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - jpStoreClass(yyvsp[-2].str); + jpStoreClass((yyvsp[-2].str)); yyGetParser->SetCurrentCombine(""); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 36: -#line 450 "cmDependsJavaParser.y" +#line 438 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 37: -#line 459 "cmDependsJavaParser.y" +#line 447 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 38: -#line 467 "cmDependsJavaParser.y" +#line 455 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 39: -#line 476 "cmDependsJavaParser.y" +#line 464 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 40: -#line 484 "cmDependsJavaParser.y" +#line 472 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 41: -#line 491 "cmDependsJavaParser.y" +#line 479 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 42: -#line 499 "cmDependsJavaParser.y" +#line 487 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 43: -#line 506 "cmDependsJavaParser.y" +#line 494 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 44: -#line 514 "cmDependsJavaParser.y" +#line 502 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 45: -#line 521 "cmDependsJavaParser.y" +#line 509 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 46: -#line 530 "cmDependsJavaParser.y" +#line 518 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->SetCurrentPackage(yyvsp[-1].str); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->SetCurrentPackage((yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); yyGetParser->SetCurrentCombine(""); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 47: -#line 542 "cmDependsJavaParser.y" +#line 530 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 550 "cmDependsJavaParser.y" +#line 538 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 49: -#line 559 "cmDependsJavaParser.y" +#line 547 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->AddPackagesImport(yyvsp[-1].str); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->AddPackagesImport((yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); yyGetParser->SetCurrentCombine(""); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 50: -#line 571 "cmDependsJavaParser.y" +#line 559 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); - std::string str = yyvsp[-3].str; + std::string str = (yyvsp[-3].str); str += ".*"; yyGetParser->AddPackagesImport(str.c_str()); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); yyGetParser->SetCurrentCombine(""); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 51: -#line 584 "cmDependsJavaParser.y" +#line 572 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 52: -#line 592 "cmDependsJavaParser.y" +#line 580 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 53: -#line 600 "cmDependsJavaParser.y" +#line 588 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 54: -#line 609 "cmDependsJavaParser.y" +#line 597 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 617 "cmDependsJavaParser.y" +#line 605 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 67: -#line 632 "cmDependsJavaParser.y" +#line 620 "cmDependsJavaParser.y" /* yacc.c:1646 */ { - yyGetParser->StartClass(yyvsp[0].str); + yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } +#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 68: -#line 642 "cmDependsJavaParser.y" +#line 630 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 69: -#line 651 "cmDependsJavaParser.y" +#line 639 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 70: -#line 660 "cmDependsJavaParser.y" +#line 648 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 71: -#line 669 "cmDependsJavaParser.y" +#line 657 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 72: -#line 678 "cmDependsJavaParser.y" +#line 666 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 73: -#line 685 "cmDependsJavaParser.y" +#line 673 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 74: -#line 694 "cmDependsJavaParser.y" +#line 682 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 75: -#line 703 "cmDependsJavaParser.y" +#line 691 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 76: -#line 712 "cmDependsJavaParser.y" +#line 700 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 77: -#line 720 "cmDependsJavaParser.y" +#line 708 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 78: -#line 729 "cmDependsJavaParser.y" +#line 717 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 79: -#line 737 "cmDependsJavaParser.y" +#line 725 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 80: -#line 744 "cmDependsJavaParser.y" +#line 732 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 81: -#line 753 "cmDependsJavaParser.y" +#line 741 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 82: -#line 761 "cmDependsJavaParser.y" +#line 749 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 83: -#line 769 "cmDependsJavaParser.y" +#line 757 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 84: -#line 777 "cmDependsJavaParser.y" +#line 765 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 85: -#line 786 "cmDependsJavaParser.y" +#line 774 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 86: -#line 794 "cmDependsJavaParser.y" +#line 782 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 87: -#line 803 "cmDependsJavaParser.y" +#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } +#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 88: -#line 809 "cmDependsJavaParser.y" +#line 797 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 89: -#line 817 "cmDependsJavaParser.y" +#line 805 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 90: -#line 826 "cmDependsJavaParser.y" +#line 814 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 91: -#line 834 "cmDependsJavaParser.y" +#line 822 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 92: -#line 843 "cmDependsJavaParser.y" +#line 831 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 93: -#line 852 "cmDependsJavaParser.y" +#line 840 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 94: -#line 861 "cmDependsJavaParser.y" +#line 849 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 95: -#line 869 "cmDependsJavaParser.y" +#line 857 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 96: -#line 878 "cmDependsJavaParser.y" +#line 866 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 97: -#line 886 "cmDependsJavaParser.y" +#line 874 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 98: -#line 894 "cmDependsJavaParser.y" +#line 882 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 99: -#line 903 "cmDependsJavaParser.y" +#line 891 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 100: -#line 912 "cmDependsJavaParser.y" +#line 900 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 101: -#line 921 "cmDependsJavaParser.y" +#line 909 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 102: -#line 929 "cmDependsJavaParser.y" +#line 917 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 103: -#line 939 "cmDependsJavaParser.y" +#line 927 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 104: -#line 949 "cmDependsJavaParser.y" +#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } +#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 105: -#line 955 "cmDependsJavaParser.y" +#line 943 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 107: -#line 966 "cmDependsJavaParser.y" +#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 108: -#line 972 "cmDependsJavaParser.y" +#line 960 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 109: -#line 982 "cmDependsJavaParser.y" +#line 970 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 110: -#line 992 "cmDependsJavaParser.y" +#line 980 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 111: -#line 1002 "cmDependsJavaParser.y" +#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 112: -#line 1008 "cmDependsJavaParser.y" +#line 996 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 113: -#line 1018 "cmDependsJavaParser.y" +#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 114: -#line 1028 "cmDependsJavaParser.y" +#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 115: -#line 1038 "cmDependsJavaParser.y" +#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 116: -#line 1047 "cmDependsJavaParser.y" +#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 117: -#line 1057 "cmDependsJavaParser.y" +#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 118: -#line 1068 "cmDependsJavaParser.y" +#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 119: -#line 1077 "cmDependsJavaParser.y" +#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 120: -#line 1085 "cmDependsJavaParser.y" +#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 121: -#line 1095 "cmDependsJavaParser.y" +#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 122: -#line 1104 "cmDependsJavaParser.y" +#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 123: -#line 1114 "cmDependsJavaParser.y" +#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646 */ { - yyGetParser->StartClass(yyvsp[0].str); + yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } +#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 124: -#line 1123 "cmDependsJavaParser.y" +#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 125: -#line 1132 "cmDependsJavaParser.y" +#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 126: -#line 1139 "cmDependsJavaParser.y" +#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 127: -#line 1149 "cmDependsJavaParser.y" +#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 128: -#line 1158 "cmDependsJavaParser.y" +#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 129: -#line 1168 "cmDependsJavaParser.y" +#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 130: -#line 1177 "cmDependsJavaParser.y" +#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 131: -#line 1185 "cmDependsJavaParser.y" +#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 132: -#line 1194 "cmDependsJavaParser.y" +#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 133: -#line 1203 "cmDependsJavaParser.y" +#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 134: -#line 1212 "cmDependsJavaParser.y" +#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 135: -#line 1221 "cmDependsJavaParser.y" +#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 136: -#line 1229 "cmDependsJavaParser.y" +#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 137: -#line 1238 "cmDependsJavaParser.y" +#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 138: -#line 1247 "cmDependsJavaParser.y" +#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 139: -#line 1257 "cmDependsJavaParser.y" +#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 140: -#line 1267 "cmDependsJavaParser.y" +#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 141: -#line 1276 "cmDependsJavaParser.y" +#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 142: -#line 1286 "cmDependsJavaParser.y" +#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 143: -#line 1295 "cmDependsJavaParser.y" +#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 144: -#line 1303 "cmDependsJavaParser.y" +#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 145: -#line 1312 "cmDependsJavaParser.y" +#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 146: -#line 1322 "cmDependsJavaParser.y" +#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 147: -#line 1331 "cmDependsJavaParser.y" +#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 148: -#line 1341 "cmDependsJavaParser.y" +#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 149: -#line 1349 "cmDependsJavaParser.y" +#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 150: -#line 1357 "cmDependsJavaParser.y" +#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 151: -#line 1367 "cmDependsJavaParser.y" +#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 152: -#line 1376 "cmDependsJavaParser.y" +#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 153: -#line 1386 "cmDependsJavaParser.y" +#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 154: -#line 1395 "cmDependsJavaParser.y" +#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 155: -#line 1404 "cmDependsJavaParser.y" +#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 156: -#line 1414 "cmDependsJavaParser.y" +#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 157: -#line 1424 "cmDependsJavaParser.y" +#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 158: -#line 1433 "cmDependsJavaParser.y" +#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 159: -#line 1443 "cmDependsJavaParser.y" +#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 160: -#line 1452 "cmDependsJavaParser.y" +#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 161: -#line 1461 "cmDependsJavaParser.y" +#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 162: -#line 1470 "cmDependsJavaParser.y" +#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 163: -#line 1479 "cmDependsJavaParser.y" +#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 164: -#line 1488 "cmDependsJavaParser.y" +#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 165: -#line 1498 "cmDependsJavaParser.y" +#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 166: -#line 1507 "cmDependsJavaParser.y" +#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 167: -#line 1516 "cmDependsJavaParser.y" +#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 168: -#line 1525 "cmDependsJavaParser.y" +#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 169: -#line 1534 "cmDependsJavaParser.y" +#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 170: -#line 1544 "cmDependsJavaParser.y" +#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 171: -#line 1553 "cmDependsJavaParser.y" +#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 172: -#line 1562 "cmDependsJavaParser.y" +#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 173: -#line 1571 "cmDependsJavaParser.y" +#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 174: -#line 1580 "cmDependsJavaParser.y" +#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 175: -#line 1589 "cmDependsJavaParser.y" +#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 176: -#line 1598 "cmDependsJavaParser.y" +#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 177: -#line 1607 "cmDependsJavaParser.y" +#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 178: -#line 1616 "cmDependsJavaParser.y" +#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 179: -#line 1625 "cmDependsJavaParser.y" +#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 180: -#line 1634 "cmDependsJavaParser.y" +#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 181: -#line 1643 "cmDependsJavaParser.y" +#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 182: -#line 1653 "cmDependsJavaParser.y" +#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 183: -#line 1663 "cmDependsJavaParser.y" +#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[-2].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 184: -#line 1674 "cmDependsJavaParser.y" +#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 185: -#line 1684 "cmDependsJavaParser.y" +#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 186: -#line 1694 "cmDependsJavaParser.y" +#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 187: -#line 1703 "cmDependsJavaParser.y" +#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 188: -#line 1712 "cmDependsJavaParser.y" +#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 189: -#line 1721 "cmDependsJavaParser.y" +#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 190: -#line 1730 "cmDependsJavaParser.y" +#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 191: -#line 1739 "cmDependsJavaParser.y" +#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 192: -#line 1748 "cmDependsJavaParser.y" +#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 193: -#line 1758 "cmDependsJavaParser.y" +#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 194: -#line 1768 "cmDependsJavaParser.y" +#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 195: -#line 1778 "cmDependsJavaParser.y" +#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 196: -#line 1788 "cmDependsJavaParser.y" +#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 197: -#line 1795 "cmDependsJavaParser.y" +#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } +#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 198: -#line 1801 "cmDependsJavaParser.y" +#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 199: -#line 1809 "cmDependsJavaParser.y" +#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 200: -#line 1818 "cmDependsJavaParser.y" +#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 201: -#line 1826 "cmDependsJavaParser.y" +#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 202: -#line 1836 "cmDependsJavaParser.y" +#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 203: -#line 1846 "cmDependsJavaParser.y" +#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 204: -#line 1855 "cmDependsJavaParser.y" +#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 205: -#line 1865 "cmDependsJavaParser.y" +#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 206: -#line 1874 "cmDependsJavaParser.y" +#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 207: -#line 1884 "cmDependsJavaParser.y" +#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 208: -#line 1891 "cmDependsJavaParser.y" +#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 209: -#line 1898 "cmDependsJavaParser.y" +#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); } +#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 210: -#line 1906 "cmDependsJavaParser.y" +#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); } +#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 211: -#line 1912 "cmDependsJavaParser.y" +#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 212: -#line 1920 "cmDependsJavaParser.y" +#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 213: -#line 1929 "cmDependsJavaParser.y" +#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 214: -#line 1937 "cmDependsJavaParser.y" +#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 215: -#line 1948 "cmDependsJavaParser.y" +#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 216: -#line 1956 "cmDependsJavaParser.y" +#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 217: -#line 1964 "cmDependsJavaParser.y" +#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 218: -#line 1974 "cmDependsJavaParser.y" +#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 219: -#line 1983 "cmDependsJavaParser.y" +#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 220: -#line 1993 "cmDependsJavaParser.y" +#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 221: -#line 2003 "cmDependsJavaParser.y" +#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 222: -#line 2012 "cmDependsJavaParser.y" +#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 223: -#line 2022 "cmDependsJavaParser.y" +#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 224: -#line 2031 "cmDependsJavaParser.y" +#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 225: -#line 2041 "cmDependsJavaParser.y" +#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 226: -#line 2051 "cmDependsJavaParser.y" +#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 227: -#line 2059 "cmDependsJavaParser.y" +#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 228: -#line 2066 "cmDependsJavaParser.y" +#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 229: -#line 2077 "cmDependsJavaParser.y" +#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 230: -#line 2087 "cmDependsJavaParser.y" +#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 231: -#line 2097 "cmDependsJavaParser.y" +#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 232: -#line 2107 "cmDependsJavaParser.y" +#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 233: -#line 2116 "cmDependsJavaParser.y" +#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 234: -#line 2125 "cmDependsJavaParser.y" +#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 235: -#line 2133 "cmDependsJavaParser.y" +#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 236: -#line 2143 "cmDependsJavaParser.y" +#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 237: -#line 2152 "cmDependsJavaParser.y" +#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 238: -#line 2162 "cmDependsJavaParser.y" +#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 239: -#line 2169 "cmDependsJavaParser.y" +#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 240: -#line 2179 "cmDependsJavaParser.y" +#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 241: -#line 2188 "cmDependsJavaParser.y" +#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 242: -#line 2198 "cmDependsJavaParser.y" +#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 243: -#line 2207 "cmDependsJavaParser.y" +#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 244: -#line 2213 "cmDependsJavaParser.y" +#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 245: -#line 2222 "cmDependsJavaParser.y" +#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 246: -#line 2231 "cmDependsJavaParser.y" +#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 247: -#line 2240 "cmDependsJavaParser.y" +#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 248: -#line 2249 "cmDependsJavaParser.y" +#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 249: -#line 2259 "cmDependsJavaParser.y" +#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 250: -#line 2268 "cmDependsJavaParser.y" +#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 251: -#line 2276 "cmDependsJavaParser.y" +#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 252: -#line 2285 "cmDependsJavaParser.y" +#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 253: -#line 2293 "cmDependsJavaParser.y" +#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 254: -#line 2303 "cmDependsJavaParser.y" +#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 255: -#line 2312 "cmDependsJavaParser.y" +#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 256: -#line 2322 "cmDependsJavaParser.y" +#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 257: -#line 2331 "cmDependsJavaParser.y" +#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 258: -#line 2340 "cmDependsJavaParser.y" +#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 259: -#line 2349 "cmDependsJavaParser.y" +#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 260: -#line 2358 "cmDependsJavaParser.y" +#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 261: -#line 2366 "cmDependsJavaParser.y" +#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 262: -#line 2376 "cmDependsJavaParser.y" +#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 263: -#line 2385 "cmDependsJavaParser.y" +#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 264: -#line 2395 "cmDependsJavaParser.y" +#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 265: -#line 2405 "cmDependsJavaParser.y" +#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); } +#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 266: -#line 2411 "cmDependsJavaParser.y" +#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } +#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 267: -#line 2418 "cmDependsJavaParser.y" +#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 268: -#line 2428 "cmDependsJavaParser.y" +#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 269: -#line 2438 "cmDependsJavaParser.y" +#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 270: -#line 2448 "cmDependsJavaParser.y" +#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 271: -#line 2459 "cmDependsJavaParser.y" +#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 272: -#line 2469 "cmDependsJavaParser.y" +#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); - yyGetParser->DeallocateParserType(&(yyvsp[-5].str)); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 273: -#line 2480 "cmDependsJavaParser.y" +#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 274: -#line 2490 "cmDependsJavaParser.y" +#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 275: -#line 2501 "cmDependsJavaParser.y" +#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 276: -#line 2511 "cmDependsJavaParser.y" +#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 277: -#line 2521 "cmDependsJavaParser.y" +#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 278: -#line 2530 "cmDependsJavaParser.y" +#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); - yyval.str = 0; + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 279: -#line 2539 "cmDependsJavaParser.y" +#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 280: -#line 2548 "cmDependsJavaParser.y" +#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 281: -#line 2557 "cmDependsJavaParser.y" +#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 282: -#line 2567 "cmDependsJavaParser.y" +#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 283: -#line 2577 "cmDependsJavaParser.y" +#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 284: -#line 2587 "cmDependsJavaParser.y" +#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 285: -#line 2596 "cmDependsJavaParser.y" +#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 286: -#line 2605 "cmDependsJavaParser.y" +#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 287: -#line 2614 "cmDependsJavaParser.y" +#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 288: -#line 2623 "cmDependsJavaParser.y" +#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 289: -#line 2633 "cmDependsJavaParser.y" +#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 290: -#line 2643 "cmDependsJavaParser.y" +#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 291: -#line 2653 "cmDependsJavaParser.y" +#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 292: -#line 2662 "cmDependsJavaParser.y" +#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 293: -#line 2671 "cmDependsJavaParser.y" +#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 294: -#line 2680 "cmDependsJavaParser.y" +#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 295: -#line 2690 "cmDependsJavaParser.y" +#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 296: -#line 2699 "cmDependsJavaParser.y" +#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 297: -#line 2708 "cmDependsJavaParser.y" +#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 298: -#line 2715 "cmDependsJavaParser.y" +#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 299: -#line 2724 "cmDependsJavaParser.y" +#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 300: -#line 2733 "cmDependsJavaParser.y" +#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 301: -#line 2742 "cmDependsJavaParser.y" +#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 302: -#line 2752 "cmDependsJavaParser.y" +#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 303: -#line 2761 "cmDependsJavaParser.y" +#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 304: -#line 2770 "cmDependsJavaParser.y" +#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 305: -#line 2780 "cmDependsJavaParser.y" +#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 306: -#line 2789 "cmDependsJavaParser.y" +#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 307: -#line 2798 "cmDependsJavaParser.y" +#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 308: -#line 2807 "cmDependsJavaParser.y" +#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 309: -#line 2817 "cmDependsJavaParser.y" +#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 310: -#line 2826 "cmDependsJavaParser.y" +#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 311: -#line 2835 "cmDependsJavaParser.y" +#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 312: -#line 2844 "cmDependsJavaParser.y" +#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 313: -#line 2853 "cmDependsJavaParser.y" +#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 314: -#line 2862 "cmDependsJavaParser.y" +#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 315: -#line 2872 "cmDependsJavaParser.y" +#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 316: -#line 2881 "cmDependsJavaParser.y" +#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 317: -#line 2890 "cmDependsJavaParser.y" +#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 318: -#line 2900 "cmDependsJavaParser.y" +#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 319: -#line 2909 "cmDependsJavaParser.y" +#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 320: -#line 2919 "cmDependsJavaParser.y" +#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 321: -#line 2928 "cmDependsJavaParser.y" +#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 322: -#line 2938 "cmDependsJavaParser.y" +#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 323: -#line 2947 "cmDependsJavaParser.y" +#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 324: -#line 2957 "cmDependsJavaParser.y" +#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 325: -#line 2966 "cmDependsJavaParser.y" +#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 326: -#line 2976 "cmDependsJavaParser.y" +#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 327: -#line 2985 "cmDependsJavaParser.y" +#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 328: -#line 2995 "cmDependsJavaParser.y" +#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 329: -#line 3004 "cmDependsJavaParser.y" +#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 330: -#line 3014 "cmDependsJavaParser.y" +#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 331: -#line 3023 "cmDependsJavaParser.y" +#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 332: -#line 3033 "cmDependsJavaParser.y" +#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 333: -#line 3043 "cmDependsJavaParser.y" +#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 334: -#line 3053 "cmDependsJavaParser.y" +#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 335: -#line 3062 "cmDependsJavaParser.y" +#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 336: -#line 3072 "cmDependsJavaParser.y" +#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 337: -#line 3081 "cmDependsJavaParser.y" +#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 338: -#line 3090 "cmDependsJavaParser.y" +#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 339: -#line 3099 "cmDependsJavaParser.y" +#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 340: -#line 3108 "cmDependsJavaParser.y" +#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 341: -#line 3117 "cmDependsJavaParser.y" +#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 342: -#line 3126 "cmDependsJavaParser.y" +#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 343: -#line 3135 "cmDependsJavaParser.y" +#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 344: -#line 3144 "cmDependsJavaParser.y" +#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 345: -#line 3153 "cmDependsJavaParser.y" +#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 346: -#line 3162 "cmDependsJavaParser.y" +#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 347: -#line 3171 "cmDependsJavaParser.y" +#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 348: -#line 3181 "cmDependsJavaParser.y" +#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 349: -#line 3191 "cmDependsJavaParser.y" +#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 350: -#line 3201 "cmDependsJavaParser.y" +#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 351: -#line 3210 "cmDependsJavaParser.y" +#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - jpStoreClass(yyvsp[-2].str); + jpStoreClass((yyvsp[-2].str)); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; +#line 6184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ + default: break; } - -/* Line 1010 of yacc.c. */ -#line 5780 "cmDependsJavaParser.cxx" - - yyvsp -= yylen; - yyssp -= yylen; - - + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + 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); + + YYPOPSTACK (yylen); + yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state + /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -5794,74 +6217,52 @@ yyreduce: goto yynewstate; -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ 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); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; -#if YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (YYPACT_NINF < yyn && yyn < YYLAST) - { - YYSIZE_T yysize = 0; - int yytype = YYTRANSLATE (yychar); - const char* yyprefix; - char *yymsg; - int yyx; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 0; - - yyprefix = ", expecting "; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); - yycount += 1; - if (yycount == 5) - { - yysize = 0; - break; - } - } - yysize += (sizeof ("syntax error, unexpected ") - + yystrlen (yytname[yytype])); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) +#if ! YYERROR_VERBOSE + yyerror (yyscanner, YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); - yyp = yystpcpy (yyp, yytname[yytype]); - - if (yycount < 5) - { - yyprefix = ", expecting "; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) { - yyp = yystpcpy (yyp, yyprefix); - yyp = yystpcpy (yyp, yytname[yyx]); - yyprefix = " or "; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } } - } - yyerror (yymsg); - YYSTACK_FREE (yymsg); + yyerror (yyscanner, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } - else - yyerror ("syntax error; also virtual memory exhausted"); - } - else -#endif /* YYERROR_VERBOSE */ - yyerror ("syntax error"); +# undef YYSYNTAX_ERROR +#endif } @@ -5869,31 +6270,23 @@ yyerrlab: if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an - error, discard it. */ + error, discard it. */ if (yychar <= YYEOF) { - /* If at end of input, pop the error token, - then the rest of the stack, then return failure. */ - if (yychar == YYEOF) - for (;;) - { - YYPOPSTACK; - if (yyssp == yyss) - YYABORT; - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[*yyssp], yyvsp); - } + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; } else - { - YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); - yydestruct (yytoken, &yylval); - yychar = YYEMPTY; - - } + { + yydestruct ("Error: discarding", + yytoken, &yylval, yyscanner); + yychar = YYEMPTY; + } } +#if 0 /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; @@ -5904,15 +6297,17 @@ yyerrlab: `---------------------------------------------------*/ yyerrorlab: -#if defined(__GNUC__) || defined(__HP_aCC) - /* Pacify GCC when the user code never invokes YYERROR and the label - yyerrorlab therefore never appears in user code. */ - if (0) + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) goto yyerrorlab; -#endif - yyvsp -= yylen; - yyssp -= yylen; + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; @@ -5921,41 +6316,43 @@ yyerrorlab: | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ +#endif + yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) - YYABORT; + YYABORT; - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[yystate], yyvsp); - YYPOPSTACK; + + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yyscanner); + YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } - if (yyn == YYFINAL) - YYACCEPT; - - YYDPRINTF ((stderr, "Shifting error token, ")); - + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + yystate = yyn; goto yynewstate; @@ -5974,33 +6371,51 @@ yyabortlab: yyresult = 1; goto yyreturn; -#ifndef yyoverflow -/*----------------------------------------------. -| yyoverflowlab -- parser overflow comes here. | -`----------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, yyscanner); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*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 3219 "cmDependsJavaParser.y" +#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906 */ /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmDependsJavaError(yyscan_t yyscanner, const char* message) +void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } - - diff --git a/Source/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y similarity index 98% rename from Source/cmDependsJavaParser.y rename to Source/LexerParser/cmDependsJavaParser.y index 91ee7c808..f7eb22818 100644 --- a/Source/cmDependsJavaParser.y +++ b/Source/LexerParser/cmDependsJavaParser.y @@ -10,18 +10,16 @@ Run bison like this: bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y Modify cmDependsJavaParser.cxx: - - remove TABs - - remove use of the 'register' storage class specifier - - add __HP_aCC to the #if test for yyerrorlab warning suppression + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmDependsJava_yyerror(x) \ - cmDependsJavaError(yyscanner, x) +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include +#include + #define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) /*-------------------------------------------------------------------------*/ @@ -32,10 +30,9 @@ Modify cmDependsJavaParser.cxx: /* Forward declare the lexer entry point. */ YY_DECL; -/* Internal utility functions. */ -static void cmDependsJavaError(yyscan_t yyscanner, const char* message); +/* Helper function to forward error callback from parser. */ +static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); -#define YYDEBUG 1 #define YYMAXDEPTH 1000000 @@ -50,7 +47,13 @@ static void cmDependsJavaError(yyscan_t yyscanner, const char* message); %} /* Generate a reentrant parser object. */ -%pure_parser +%define api.pure + +/* Configure the parser to use a lexer object. */ +%lex-param {yyscan_t yyscanner} +%parse-param {yyscan_t yyscanner} + +%define parse.error verbose /* %union { @@ -239,7 +242,7 @@ jp_DECIMALINTEGERLITERAL yyGetParser->SetCurrentCombine(""); } | -jp_HEXINTEGERLITERAL +jp_HEXINTEGERLITERAL { jpElementStart(1); jpCheckEmpty(1); @@ -3205,8 +3208,7 @@ Name jp_DOT jp_NEW /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmDependsJavaError(yyscan_t yyscanner, const char* message) +void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } - diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h new file mode 100644 index 000000000..7f18f1dd8 --- /dev/null +++ b/Source/LexerParser/cmDependsJavaParserTokens.h @@ -0,0 +1,264 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#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 + +/* 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 */ diff --git a/Source/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx similarity index 100% rename from Source/cmExprLexer.cxx rename to Source/LexerParser/cmExprLexer.cxx diff --git a/Source/cmExprLexer.h b/Source/LexerParser/cmExprLexer.h similarity index 100% rename from Source/cmExprLexer.h rename to Source/LexerParser/cmExprLexer.h diff --git a/Source/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l similarity index 100% rename from Source/cmExprLexer.in.l rename to Source/LexerParser/cmExprLexer.in.l diff --git a/Source/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx similarity index 96% rename from Source/cmExprParser.cxx rename to Source/LexerParser/cmExprParser.cxx index d11d0b664..67664a5f5 100644 --- a/Source/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -85,14 +85,17 @@ Modify cmExprParser.cxx: */ +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include + /*-------------------------------------------------------------------------*/ #define YYDEBUG 1 #include "cmExprParserHelper.h" /* Interface to parser object. */ #include "cmExprLexer.h" /* Interface to lexer object. */ #include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; @@ -105,7 +108,7 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4065) /* Switch statement contains default but no case. */ #endif -#line 109 "cmExprParser.cxx" /* yacc.c:339 */ +#line 112 "cmExprParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -182,7 +185,7 @@ int cmExpr_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 186 "cmExprParser.cxx" /* yacc.c:358 */ +#line 189 "cmExprParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -481,9 +484,9 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 70, 70, 75, 78, 83, 86, 91, 94, 99, - 102, 105, 110, 113, 116, 121, 124, 127, 130, 135, - 138, 141, 146, 149 + 0, 73, 73, 78, 81, 86, 89, 94, 97, 102, + 105, 108, 113, 116, 119, 124, 127, 130, 133, 138, + 141, 144, 149, 152 }; #endif @@ -1278,183 +1281,183 @@ yyreduce: switch (yyn) { case 2: -#line 70 "cmExprParser.y" /* yacc.c:1646 */ +#line 73 "cmExprParser.y" /* yacc.c:1646 */ { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1286 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1289 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 75 "cmExprParser.y" /* yacc.c:1646 */ +#line 78 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1294 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1297 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 78 "cmExprParser.y" /* yacc.c:1646 */ +#line 81 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1302 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1305 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 83 "cmExprParser.y" /* yacc.c:1646 */ +#line 86 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1310 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1313 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 86 "cmExprParser.y" /* yacc.c:1646 */ +#line 89 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1318 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1321 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 91 "cmExprParser.y" /* yacc.c:1646 */ +#line 94 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1326 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1329 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 94 "cmExprParser.y" /* yacc.c:1646 */ +#line 97 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1334 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1337 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 99 "cmExprParser.y" /* yacc.c:1646 */ +#line 102 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1342 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1345 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 102 "cmExprParser.y" /* yacc.c:1646 */ +#line 105 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1350 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1353 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 105 "cmExprParser.y" /* yacc.c:1646 */ +#line 108 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1358 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1361 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 110 "cmExprParser.y" /* yacc.c:1646 */ +#line 113 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1366 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1369 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 113 "cmExprParser.y" /* yacc.c:1646 */ +#line 116 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1374 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1377 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 116 "cmExprParser.y" /* yacc.c:1646 */ +#line 119 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1382 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1385 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 121 "cmExprParser.y" /* yacc.c:1646 */ +#line 124 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1390 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1393 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 124 "cmExprParser.y" /* yacc.c:1646 */ +#line 127 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1398 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1401 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 127 "cmExprParser.y" /* yacc.c:1646 */ +#line 130 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1406 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1409 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 130 "cmExprParser.y" /* yacc.c:1646 */ +#line 133 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1414 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1417 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 135 "cmExprParser.y" /* yacc.c:1646 */ +#line 138 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1422 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1425 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 138 "cmExprParser.y" /* yacc.c:1646 */ +#line 141 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = + (yyvsp[0].Number); } -#line 1430 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1433 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 141 "cmExprParser.y" /* yacc.c:1646 */ +#line 144 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = - (yyvsp[0].Number); } -#line 1438 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1441 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 146 "cmExprParser.y" /* yacc.c:1646 */ +#line 149 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1446 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1449 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 149 "cmExprParser.y" /* yacc.c:1646 */ +#line 152 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-1].Number); } -#line 1454 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1457 "cmExprParser.cxx" /* yacc.c:1646 */ break; -#line 1458 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1461 "cmExprParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1684,7 +1687,7 @@ yyreturn: #endif return yyresult; } -#line 154 "cmExprParser.y" /* yacc.c:1906 */ +#line 157 "cmExprParser.y" /* yacc.c:1906 */ /* End of grammar */ @@ -1693,4 +1696,3 @@ void cmExpr_yyerror(yyscan_t yyscanner, const char* message) { cmExpr_yyget_extra(yyscanner)->Error(message); } - diff --git a/Source/cmExprParser.y b/Source/LexerParser/cmExprParser.y similarity index 97% rename from Source/cmExprParser.y rename to Source/LexerParser/cmExprParser.y index c7c4a7bc9..d1c3a97a7 100644 --- a/Source/cmExprParser.y +++ b/Source/LexerParser/cmExprParser.y @@ -14,14 +14,17 @@ Modify cmExprParser.cxx: */ +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include + /*-------------------------------------------------------------------------*/ #define YYDEBUG 1 #include "cmExprParserHelper.h" /* Interface to parser object. */ #include "cmExprLexer.h" /* Interface to lexer object. */ #include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; @@ -159,4 +162,3 @@ void cmExpr_yyerror(yyscan_t yyscanner, const char* message) { cmExpr_yyget_extra(yyscanner)->Error(message); } - diff --git a/Source/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h similarity index 100% rename from Source/cmExprParserTokens.h rename to Source/LexerParser/cmExprParserTokens.h diff --git a/Source/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx similarity index 100% rename from Source/cmFortranLexer.cxx rename to Source/LexerParser/cmFortranLexer.cxx diff --git a/Source/cmFortranLexer.h b/Source/LexerParser/cmFortranLexer.h similarity index 100% rename from Source/cmFortranLexer.h rename to Source/LexerParser/cmFortranLexer.h diff --git a/Source/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l similarity index 100% rename from Source/cmFortranLexer.in.l rename to Source/LexerParser/cmFortranLexer.in.l diff --git a/Source/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx similarity index 96% rename from Source/cmFortranParser.cxx rename to Source/LexerParser/cmFortranParser.cxx index 896e58934..2b3452f2e 100644 --- a/Source/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -97,13 +97,17 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmsys/String.h" +#include +#include + /*-------------------------------------------------------------------------*/ #define cmFortranParser_cxx #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; @@ -124,7 +128,7 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */ #endif -#line 137 "cmFortranParser.cxx" /* yacc.c:339 */ +#line 132 "cmFortranParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -244,11 +248,11 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 75 "cmFortranParser.y" /* yacc.c:355 */ +#line 70 "cmFortranParser.y" /* yacc.c:355 */ char* string; -#line 261 "cmFortranParser.cxx" /* yacc.c:355 */ +#line 256 "cmFortranParser.cxx" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; @@ -264,7 +268,7 @@ int cmFortran_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 277 "cmFortranParser.cxx" /* yacc.c:358 */ +#line 272 "cmFortranParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -565,13 +569,13 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 103, 103, 103, 106, 110, 115, 124, 130, 137, - 142, 146, 151, 159, 164, 169, 174, 179, 184, 189, - 194, 199, 203, 207, 211, 215, 216, 221, 221, 221, - 222, 222, 223, 223, 224, 224, 225, 225, 226, 226, - 227, 227, 228, 228, 229, 229, 230, 230, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248 + 0, 98, 98, 98, 101, 105, 110, 119, 125, 132, + 137, 141, 146, 154, 159, 164, 169, 174, 179, 184, + 189, 194, 198, 202, 206, 210, 211, 216, 216, 216, + 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, + 222, 222, 223, 223, 224, 224, 225, 225, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243 }; #endif @@ -1523,26 +1527,26 @@ yyreduce: switch (yyn) { case 4: -#line 106 "cmFortranParser.y" /* yacc.c:1646 */ +#line 101 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1541 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1536 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 110 "cmFortranParser.y" /* yacc.c:1646 */ +#line 105 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1551 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1546 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 115 "cmFortranParser.y" /* yacc.c:1646 */ +#line 110 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1552,22 +1556,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1565 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1560 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 124 "cmFortranParser.y" /* yacc.c:1646 */ +#line 119 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-4].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1576 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1571 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 130 "cmFortranParser.y" /* yacc.c:1646 */ +#line 125 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-6].string)); @@ -1575,40 +1579,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1588 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1583 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 137 "cmFortranParser.y" /* yacc.c:1646 */ +#line 132 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1598 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1593 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 142 "cmFortranParser.y" /* yacc.c:1646 */ +#line 137 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1607 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1602 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 146 "cmFortranParser.y" /* yacc.c:1646 */ +#line 141 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1617 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1612 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 151 "cmFortranParser.y" /* yacc.c:1646 */ +#line 146 "cmFortranParser.y" /* yacc.c:1646 */ { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1617,139 +1621,139 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1630 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1625 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 159 "cmFortranParser.y" /* yacc.c:1646 */ +#line 154 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1640 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1635 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 164 "cmFortranParser.y" /* yacc.c:1646 */ +#line 159 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1650 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1645 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 169 "cmFortranParser.y" /* yacc.c:1646 */ +#line 164 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1660 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1655 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 174 "cmFortranParser.y" /* yacc.c:1646 */ +#line 169 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1670 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1665 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 179 "cmFortranParser.y" /* yacc.c:1646 */ +#line 174 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1680 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1675 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 184 "cmFortranParser.y" /* yacc.c:1646 */ +#line 179 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1690 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1685 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 189 "cmFortranParser.y" /* yacc.c:1646 */ +#line 184 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1700 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1695 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 194 "cmFortranParser.y" /* yacc.c:1646 */ +#line 189 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1710 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1705 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 199 "cmFortranParser.y" /* yacc.c:1646 */ +#line 194 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1719 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1714 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 203 "cmFortranParser.y" /* yacc.c:1646 */ +#line 198 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1728 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1723 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 207 "cmFortranParser.y" /* yacc.c:1646 */ +#line 202 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1737 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1732 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 211 "cmFortranParser.y" /* yacc.c:1646 */ +#line 206 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1746 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1741 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 233 "cmFortranParser.y" /* yacc.c:1646 */ +#line 228 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1752 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1747 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 240 "cmFortranParser.y" /* yacc.c:1646 */ +#line 235 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1758 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1753 "cmFortranParser.cxx" /* yacc.c:1646 */ break; -#line 1762 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1757 "cmFortranParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1979,6 +1983,6 @@ yyreturn: #endif return yyresult; } -#line 251 "cmFortranParser.y" /* yacc.c:1906 */ +#line 246 "cmFortranParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y similarity index 98% rename from Source/cmFortranParser.y rename to Source/LexerParser/cmFortranParser.y index 7eb5ef599..acfb40ad8 100644 --- a/Source/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -26,13 +26,17 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmsys/String.h" +#include +#include + /*-------------------------------------------------------------------------*/ #define cmFortranParser_cxx #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; diff --git a/Source/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h similarity index 98% rename from Source/cmFortranParserTokens.h rename to Source/LexerParser/cmFortranParserTokens.h index 18b9e0a18..8d6a5fe5a 100644 --- a/Source/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -130,7 +130,7 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 75 "cmFortranParser.y" /* yacc.c:1909 */ +#line 70 "cmFortranParser.y" /* yacc.c:1909 */ char* string; diff --git a/Source/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c similarity index 99% rename from Source/cmListFileLexer.c rename to Source/LexerParser/cmListFileLexer.c index 56559f67a..3dd3b85b9 100644 --- a/Source/cmListFileLexer.c +++ b/Source/LexerParser/cmListFileLexer.c @@ -558,7 +558,7 @@ Modify cmListFileLexer.c: /* IWYU pragma: no_forward_declare yyguts_t */ #ifdef WIN32 -#include +#include "cmsys/Encoding.h" #endif /* Setup the proper cmListFileLexer_yylex declaration. */ @@ -2559,11 +2559,15 @@ static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f) if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) { return cmListFileLexer_BOM_UTF32LE; } - fsetpos(f, &p); + if (fsetpos(f, &p) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_UTF16LE; } } - rewind(f); + if (fseek(f, 0, SEEK_SET) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_None; } diff --git a/Source/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l similarity index 99% rename from Source/cmListFileLexer.in.l rename to Source/LexerParser/cmListFileLexer.in.l index dd649234f..5152dbf08 100644 --- a/Source/cmListFileLexer.in.l +++ b/Source/LexerParser/cmListFileLexer.in.l @@ -21,7 +21,7 @@ Modify cmListFileLexer.c: /* IWYU pragma: no_forward_declare yyguts_t */ #ifdef WIN32 -#include +#include "cmsys/Encoding.h" #endif /* Setup the proper cmListFileLexer_yylex declaration. */ diff --git a/Source/Modules/FindLibUV.cmake b/Source/Modules/FindLibUV.cmake index b8cb36587..ba13d75f8 100644 --- a/Source/Modules/FindLibUV.cmake +++ b/Source/Modules/FindLibUV.cmake @@ -49,7 +49,7 @@ They may be set by end users to point at libuv components. #----------------------------------------------------------------------------- find_library(LibUV_LIBRARY - NAMES uv + NAMES uv libuv ) mark_as_advanced(LibUV_LIBRARY) diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 10fd718ba..9e9df781e 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -160,6 +160,25 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) +# cmake-gui has not been updated for `include-what-you-use`. +# Block the tool until this is done. +set_target_properties(cmake-gui PROPERTIES + CXX_INCLUDE_WHAT_YOU_USE "" + ) + +# Files generated by MOC, RCC, and UIC may produce clang-tidy warnings. +# We generate a dummy .clang-tidy file in the binary directory that disables +# all clang-tidy checks except one that will never match. This one check is +# necessary; clang-tidy reports an error when no checks are enabled. +# Since the Qt code generators will generate source files in the binary tree, +# clang-tidy will load the configuration from this dummy file when the sources +# are built. +file(WRITE "${QtDialog_BINARY_DIR}/.clang-tidy" " +--- +Checks: '-*,llvm-twine-local' +... +") + if(APPLE) file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware") @@ -198,7 +217,7 @@ if(UNIX AND NOT APPLE) # install a desktop file so CMake appears in the application start menu # with an icon - install(FILES CMake.desktop + install(FILES cmake-gui.desktop DESTINATION "${CMAKE_XDGDATA_DIR}/applications" ${COMPONENT}) install(FILES cmakecache.xml diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 5e03c3939..7fa2ac661 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -8,6 +8,9 @@ #include "cmDocumentationEntry.h" #include "cmVersion.h" #include "cmake.h" +#include "cmsys/CommandLineArguments.hxx" +#include "cmsys/Encoding.hxx" +#include "cmsys/SystemTools.hxx" #include #include #include @@ -15,9 +18,6 @@ #include #include #include -#include -#include -#include #include #include "cmSystemTools.h" // IWYU pragma: keep @@ -59,7 +59,7 @@ int main(int argc, char** argv) doc.addCMakeStandardDocSections(); if (argc2 > 1 && doc.CheckOptions(argc2, argv2)) { // Construct and print requested documentation. - cmake hcm; + cmake hcm(cmake::RoleInternal); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); @@ -184,9 +184,9 @@ int main(int argc, char** argv) } #if defined(Q_OS_MAC) +#include "cm_sys_stat.h" #include #include -#include #include static bool cmOSXInstall(std::string const& dir, std::string const& tool) { diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index 111b28a0a..57f8e107e 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -990,10 +990,10 @@ void CMakeSetupDialog::removeSelectedCacheEntries() { QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows(); QList pidxs; - foreach (QModelIndex i, idxs) { + foreach (QModelIndex const& i, idxs) { pidxs.append(i); } - foreach (QPersistentModelIndex pi, pidxs) { + foreach (QPersistentModelIndex const& pi, pidxs) { this->CacheValues->model()->removeRow(pi.row(), pi.parent()); } } @@ -1152,7 +1152,7 @@ void CMakeSetupDialog::showUserChanges() QString command; QString cache; - foreach (QCMakeProperty prop, changes) { + foreach (QCMakeProperty const& prop, changes) { QString type; switch (prop.Type) { case QCMakeProperty::BOOL: @@ -1175,12 +1175,9 @@ void CMakeSetupDialog::showUserChanges() value = prop.Value.toString(); } - QString line("%1:%2="); - line = line.arg(prop.Key); - line = line.arg(type); - - command += QString("-D%1\"%2\" ").arg(line).arg(value); - cache += QString("%1%2\n").arg(line).arg(value); + QString const line = QString("%1:%2=").arg(prop.Key, type); + command += QString("-D%1\"%2\" ").arg(line, value); + cache += QString("%1%2\n").arg(line, value); } textedit->append(tr("Commandline options:")); diff --git a/Source/QtDialog/Compilers.h b/Source/QtDialog/Compilers.h index 276e2a5d0..6c8c8f52a 100644 --- a/Source/QtDialog/Compilers.h +++ b/Source/QtDialog/Compilers.h @@ -3,7 +3,7 @@ #ifndef COMPILERS_HPP #define COMPILERS_HPP -#include +#include "cmConfigure.h" #include diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index 2f1df4fb3..b193a2782 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -130,7 +130,7 @@ bool StartCompilerSetup::crossCompilerSetup() const void StartCompilerSetup::onSelectionChanged(bool on) { if (on) { - selectionChanged(); + emit selectionChanged(); } } diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index abeff97bb..d473d9b8f 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -27,7 +27,7 @@ QCMake::QCMake(QObject* p) cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this); cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this); - this->CMakeInstance = new cmake; + this->CMakeInstance = new cmake(cmake::RoleProject); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeGUICommand()); this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this); @@ -219,14 +219,14 @@ void QCMake::setProperties(const QCMakePropertyList& newProps) } // remove some properites - foreach (QString s, toremove) { + foreach (QString const& s, toremove) { this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data()); state->RemoveCacheEntry(s.toLocal8Bit().data()); } // add some new properites - foreach (QCMakeProperty s, props) { + foreach (QCMakeProperty const& s, props) { this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data()); if (s.Type == QCMakeProperty::BOOL) { diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index 12f60370d..e14cdf2c9 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -3,7 +3,7 @@ #ifndef QCMake_h #define QCMake_h -#include +#include "cmConfigure.h" #include "cmake.h" diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 9f5208ad6..08c2d58d5 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -47,7 +47,7 @@ protected: } // check all strings for a match - foreach (QString str, strs) { + foreach (QString const& str, strs) { if (str.contains(this->filterRegExp())) { return true; } @@ -236,12 +236,12 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props) qSort(newP); qSort(newP2); int row_count = 0; - foreach (QCMakeProperty p, newP) { + foreach (QCMakeProperty const& p, newP) { this->insertRow(row_count); this->setPropertyData(this->index(row_count, 0), p, true); row_count++; } - foreach (QCMakeProperty p, newP2) { + foreach (QCMakeProperty const& p, newP2) { this->insertRow(row_count); this->setPropertyData(this->index(row_count, 0), p, false); row_count++; @@ -254,8 +254,11 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props) QStandardItem* root = this->invisibleRootItem(); - foreach (QString key, newPropsTree.keys()) { - QCMakePropertyList props2 = newPropsTree[key]; + for (QMap::const_iterator iter = + newPropsTree.begin(); + iter != newPropsTree.end(); ++iter) { + QString const& key = iter.key(); + QCMakePropertyList const& props2 = iter.value(); QList parentItems; parentItems.append( @@ -280,8 +283,11 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props) } } - foreach (QString key, newPropsTree2.keys()) { - QCMakePropertyList props2 = newPropsTree2[key]; + for (QMap::const_iterator iter = + newPropsTree2.begin(); + iter != newPropsTree2.end(); ++iter) { + QString const& key = iter.key(); + QCMakePropertyList const& props2 = iter.value(); QStandardItem* parentItem = new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key); @@ -393,7 +399,7 @@ void QCMakeCacheModel::breakProperties( { QMap tmp; // return a map of properties grouped by prefixes, and sorted - foreach (QCMakeProperty p, props) { + foreach (QCMakeProperty const& p, props) { QString prefix = QCMakeCacheModel::prefix(p.Key); tmp[prefix].append(p); } @@ -423,7 +429,7 @@ QCMakePropertyList QCMakeCacheModel::properties() const return props; } - QList idxs; + QVector idxs; idxs.append(this->index(0, 0)); // walk the entire model for property entries @@ -448,7 +454,7 @@ QCMakePropertyList QCMakeCacheModel::properties() const (idxs.last().row() + 1) >= rowCount(idxs.last().parent()) || #endif !idxs.last().sibling(idxs.last().row() + 1, 0).isValid())) { - idxs.removeLast(); + idxs.remove(idxs.size() - 1); } if (!idxs.isEmpty()) { idxs.last() = idxs.last().sibling(idxs.last().row() + 1, 0); diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx index 6a55a7641..7f0cafa37 100644 --- a/Source/QtDialog/QCMakeWidgets.cxx +++ b/Source/QtDialog/QCMakeWidgets.cxx @@ -54,11 +54,11 @@ void QCMakeFilePathEditor::chooseFile() title = tr("Select File for %1"); title = title.arg(this->Variable); } - this->fileDialogExists(true); + emit this->fileDialogExists(true); path = QFileDialog::getOpenFileName(this, title, info.absolutePath(), QString(), CM_NULLPTR, QFileDialog::DontResolveSymlinks); - this->fileDialogExists(false); + emit this->fileDialogExists(false); if (!path.isEmpty()) { this->setText(QDir::fromNativeSeparators(path)); @@ -76,11 +76,11 @@ void QCMakePathEditor::chooseFile() title = tr("Select Path for %1"); title = title.arg(this->Variable); } - this->fileDialogExists(true); + emit this->fileDialogExists(true); path = QFileDialog::getExistingDirectory(this, title, this->text(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - this->fileDialogExists(false); + emit this->fileDialogExists(false); if (!path.isEmpty()) { this->setText(QDir::fromNativeSeparators(path)); } diff --git a/Source/QtDialog/QCMakeWidgets.h b/Source/QtDialog/QCMakeWidgets.h index 0db810cbc..1ec666ff6 100644 --- a/Source/QtDialog/QCMakeWidgets.h +++ b/Source/QtDialog/QCMakeWidgets.h @@ -3,7 +3,7 @@ #ifndef QCMakeWidgets_h #define QCMakeWidgets_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/QtDialog/RegexExplorer.h b/Source/QtDialog/RegexExplorer.h index caef9753c..867989279 100644 --- a/Source/QtDialog/RegexExplorer.h +++ b/Source/QtDialog/RegexExplorer.h @@ -3,8 +3,8 @@ #ifndef RegexExplorer_h #define RegexExplorer_h +#include "cmsys/RegularExpression.hxx" #include -#include #include #include "ui_RegexExplorer.h" diff --git a/Source/QtDialog/CMake.desktop b/Source/QtDialog/cmake-gui.desktop similarity index 100% rename from Source/QtDialog/CMake.desktop rename to Source/QtDialog/cmake-gui.desktop diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index eded883ea..e96226a4b 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -63,86 +63,93 @@ */ #include "bindexplib.h" -#include -#include +#include "cmsys/Encoding.hxx" +#include "cmsys/FStream.hxx" #include #include -typedef struct cmANON_OBJECT_HEADER_BIGOBJ { - /* same as ANON_OBJECT_HEADER_V2 */ - WORD Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN - WORD Sig2; // Must be 0xffff - WORD Version; // >= 2 (implies the Flags field is present) - WORD Machine; // Actual machine - IMAGE_FILE_MACHINE_xxx - DWORD TimeDateStamp; - CLSID ClassID; // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8} - DWORD SizeOfData; // Size of data that follows the header - DWORD Flags; // 0x1 -> contains metadata - DWORD MetaDataSize; // Size of CLR metadata - DWORD MetaDataOffset; // Offset of CLR metadata +#ifndef IMAGE_FILE_MACHINE_ARMNT +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 +#endif - /* bigobj specifics */ - DWORD NumberOfSections; // extended from WORD - DWORD PointerToSymbolTable; - DWORD NumberOfSymbols; +typedef struct cmANON_OBJECT_HEADER_BIGOBJ +{ + /* same as ANON_OBJECT_HEADER_V2 */ + WORD Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN + WORD Sig2; // Must be 0xffff + WORD Version; // >= 2 (implies the Flags field is present) + WORD Machine; // Actual machine - IMAGE_FILE_MACHINE_xxx + DWORD TimeDateStamp; + CLSID ClassID; // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8} + DWORD SizeOfData; // Size of data that follows the header + DWORD Flags; // 0x1 -> contains metadata + DWORD MetaDataSize; // Size of CLR metadata + DWORD MetaDataOffset; // Offset of CLR metadata + + /* bigobj specifics */ + DWORD NumberOfSections; // extended from WORD + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; } cmANON_OBJECT_HEADER_BIGOBJ; -typedef struct _cmIMAGE_SYMBOL_EX { - union { - BYTE ShortName[8]; - struct { - DWORD Short; // if 0, use LongName - DWORD Long; // offset into string table - } Name; - DWORD LongName[2]; // PBYTE [2] - } N; - DWORD Value; - LONG SectionNumber; - WORD Type; - BYTE StorageClass; - BYTE NumberOfAuxSymbols; +typedef struct _cmIMAGE_SYMBOL_EX +{ + union + { + BYTE ShortName[8]; + struct + { + DWORD Short; // if 0, use LongName + DWORD Long; // offset into string table + } Name; + DWORD LongName[2]; // PBYTE [2] + } N; + DWORD Value; + LONG SectionNumber; + WORD Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; } cmIMAGE_SYMBOL_EX; -typedef cmIMAGE_SYMBOL_EX UNALIGNED *cmPIMAGE_SYMBOL_EX; +typedef cmIMAGE_SYMBOL_EX UNALIGNED* cmPIMAGE_SYMBOL_EX; -PIMAGE_SECTION_HEADER GetSectionHeaderOffset(PIMAGE_FILE_HEADER - pImageFileHeader) +PIMAGE_SECTION_HEADER GetSectionHeaderOffset( + PIMAGE_FILE_HEADER pImageFileHeader) { - return (PIMAGE_SECTION_HEADER) - ((DWORD_PTR)pImageFileHeader + - IMAGE_SIZEOF_FILE_HEADER + - pImageFileHeader->SizeOfOptionalHeader); + return (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageFileHeader + + IMAGE_SIZEOF_FILE_HEADER + + pImageFileHeader->SizeOfOptionalHeader); } -PIMAGE_SECTION_HEADER GetSectionHeaderOffset(cmANON_OBJECT_HEADER_BIGOBJ* - pImageFileHeader) +PIMAGE_SECTION_HEADER GetSectionHeaderOffset( + cmANON_OBJECT_HEADER_BIGOBJ* pImageFileHeader) { - return (PIMAGE_SECTION_HEADER) - ((DWORD_PTR)pImageFileHeader + - sizeof(cmANON_OBJECT_HEADER_BIGOBJ)); + return (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageFileHeader + + sizeof(cmANON_OBJECT_HEADER_BIGOBJ)); } /* + * Utility func, strstr with size + */ -const char* StrNStr(const char* start, const char* find, size_t &size) { - size_t len; - const char* hint; +const char* StrNStr(const char* start, const char* find, size_t& size) +{ + size_t len; + const char* hint; - if (!start || !find || !size) { - size = 0; - return 0; - } - len = strlen(find); + if (!start || !find || !size) { + size = 0; + return 0; + } + len = strlen(find); - while ((hint = (const char*) memchr(start, find[0], size-len+1))) { - size -= (hint - start); - if (!strncmp(hint, find, len)) - return hint; - start = hint + 1; - } + while ((hint = (const char*)memchr(start, find[0], size - len + 1))) { + size -= (hint - start); + if (!strncmp(hint, find, len)) + return hint; + start = hint + 1; + } - size = 0; - return 0; + size = 0; + return 0; } template < @@ -162,68 +169,18 @@ public: *---------------------------------------------------------------------- */ - DumpSymbols(ObjectHeaderType* ih, - std::set& symbols, - std::set& dataSymbols, - bool is64) - :Symbols(symbols), DataSymbols(dataSymbols) - { - this->ObjectImageHeader = ih; - this->SymbolTable = (SymbolTableType*) - ((DWORD_PTR)this->ObjectImageHeader - + this->ObjectImageHeader->PointerToSymbolTable); - this->SectionHeaders = - GetSectionHeaderOffset(this->ObjectImageHeader); - this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols; - this->Is64Bit = is64; - } - - /* - *---------------------------------------------------------------------- - * HaveExportedObjects -- - * - * Returns true if export directives (declspec(dllexport)) exist. - * - *---------------------------------------------------------------------- - */ - - bool HaveExportedObjects() { - WORD i = 0; - size_t size = 0; - const char * rawdata = 0; - PIMAGE_SECTION_HEADER pDirectivesSectionHeader = 0; - PIMAGE_SECTION_HEADER pSectionHeaders = this->SectionHeaders; - for(i = 0; (i < this->ObjectImageHeader->NumberOfSections && - !pDirectivesSectionHeader); i++) - if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8)) - pDirectivesSectionHeader = &pSectionHeaders[i]; - if (!pDirectivesSectionHeader) return 0; - - rawdata=(const char*) - this->ObjectImageHeader+pDirectivesSectionHeader->PointerToRawData; - if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0; - - size = pDirectivesSectionHeader->SizeOfRawData; - const char* posImportFlag = rawdata; - while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) { - const char* lookingForDict = posImportFlag + 9; - if (!strncmp(lookingForDict, "_G__cpp_",8) || - !strncmp(lookingForDict, "_G__set_cpp_",12)) { - posImportFlag = lookingForDict; - continue; - } - - const char* lookingForDATA = posImportFlag + 9; - while (*(++lookingForDATA) && *lookingForDATA != ' '); - lookingForDATA -= 5; - // ignore DATA exports - if (strncmp(lookingForDATA, ",DATA", 5)) break; - posImportFlag = lookingForDATA + 5; - } - if(posImportFlag) { - return true; - } - return false; + DumpSymbols(ObjectHeaderType* ih, std::set& symbols, + std::set& dataSymbols, bool isI386) + : Symbols(symbols) + , DataSymbols(dataSymbols) + { + this->ObjectImageHeader = ih; + this->SymbolTable = + (SymbolTableType*)((DWORD_PTR) this->ObjectImageHeader + + this->ObjectImageHeader->PointerToSymbolTable); + this->SectionHeaders = GetSectionHeaderOffset(this->ObjectImageHeader); + this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols; + this->IsI386 = isI386; } /* @@ -233,9 +190,7 @@ public: * Dump an object file's exported symbols. *---------------------------------------------------------------------- */ - void DumpObjFile() { - this->DumpExternalsObjects(); - } + void DumpObjFile() { this->DumpExternalsObjects(); } /* *---------------------------------------------------------------------- @@ -244,7 +199,8 @@ public: * Dumps a COFF symbol table from an OBJ. *---------------------------------------------------------------------- */ - void DumpExternalsObjects() { + void DumpExternalsObjects() + { unsigned i; PSTR stringTable; std::string symbol; @@ -252,82 +208,65 @@ public: /* * The string table apparently starts right after the symbol table */ - stringTable = (PSTR)&this->SymbolTable[this->SymbolCount]; + stringTable = (PSTR) & this->SymbolTable[this->SymbolCount]; SymbolTableType* pSymbolTable = this->SymbolTable; - for ( i=0; i < this->SymbolCount; i++ ) { + for (i = 0; i < this->SymbolCount; i++) { if (pSymbolTable->SectionNumber > 0 && - ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { - if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { - /* - * The name of the Function entry points - */ - if (pSymbolTable->N.Name.Short != 0) { - symbol = ""; - symbol.insert(0, (const char *)pSymbolTable->N.ShortName, 8); - } else { - symbol = stringTable + pSymbolTable->N.Name.Long; - } + (pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { + if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { + /* + * The name of the Function entry points + */ + if (pSymbolTable->N.Name.Short != 0) { + symbol = ""; + symbol.insert(0, (const char*)pSymbolTable->N.ShortName, 8); + } else { + symbol = stringTable + pSymbolTable->N.Name.Long; + } - // clear out any leading spaces - while (isspace(symbol[0])) symbol.erase(0,1); - // if it starts with _ and has an @ then it is a __cdecl - // so remove the @ stuff for the export - if(symbol[0] == '_') { - std::string::size_type posAt = symbol.find('@'); - if (posAt != std::string::npos) { - symbol.erase(posAt); - } + // clear out any leading spaces + while (isspace(symbol[0])) + symbol.erase(0, 1); + // if it starts with _ and has an @ then it is a __cdecl + // so remove the @ stuff for the export + if (symbol[0] == '_') { + std::string::size_type posAt = symbol.find('@'); + if (posAt != std::string::npos) { + symbol.erase(posAt); } - // For 64 bit builds we don't need to remove _ - if(!this->Is64Bit) - { - if (symbol[0] == '_') - { - symbol.erase(0,1); + } + // For i386 builds we need to remove _ + if (this->IsI386 && symbol[0] == '_') { + symbol.erase(0, 1); + } + + // Check whether it is "Scalar deleting destructor" and "Vector + // deleting destructor" + // if scalarPrefix and vectorPrefix are not found then print + // the symbol + const char* scalarPrefix = "??_G"; + const char* vectorPrefix = "??_E"; + // The original code had a check for + // symbol.find("real@") == std::string::npos) + // but this disallows member functions with the name "real". + if (symbol.compare(0, 4, scalarPrefix) && + symbol.compare(0, 4, vectorPrefix)) { + SectChar = this->SectionHeaders[pSymbolTable->SectionNumber - 1] + .Characteristics; + // skip symbols containing a dot + if (symbol.find('.') == std::string::npos) { + if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) { + // Read only (i.e. constants) must be excluded + this->DataSymbols.insert(symbol); + } else { + if (pSymbolTable->Type || !(SectChar & IMAGE_SCN_MEM_READ) || + (SectChar & IMAGE_SCN_MEM_EXECUTE)) { + this->Symbols.insert(symbol); } } - /* - Check whether it is "Scalar deleting destructor" and - "Vector deleting destructor" - */ - const char *scalarPrefix = "??_G"; - const char *vectorPrefix = "??_E"; - // original code had a check for - // symbol.find("real@") == std::string::npos) - // but if this disallows memmber functions with the name real - // if scalarPrefix and vectorPrefix are not found then print - // the symbol - if (symbol.compare(0, 4, scalarPrefix) && - symbol.compare(0, 4, vectorPrefix) ) - { - SectChar = - this-> - SectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; - if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) { - // Read only (i.e. constants) must be excluded - this->DataSymbols.insert(symbol); - } else { - if ( pSymbolTable->Type || - !(SectChar & IMAGE_SCN_MEM_READ)) { - this->Symbols.insert(symbol); - } else { - // printf(" strange symbol: %s \n",symbol.c_str()); - } - } } - } - } - else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED && - !pSymbolTable->Type && 0) { - /* - * The IMPORT global variable entry points - */ - if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { - symbol = stringTable + pSymbolTable->N.Name.Long; - while (isspace(symbol[0])) symbol.erase(0,1); - if (symbol[0] == '_') symbol.erase(0,1); - this->DataSymbols.insert(symbol); - } + } + } } /* @@ -338,111 +277,129 @@ public: pSymbolTable++; } } + private: std::set& Symbols; std::set& DataSymbols; DWORD_PTR SymbolCount; PIMAGE_SECTION_HEADER SectionHeaders; ObjectHeaderType* ObjectImageHeader; - SymbolTableType* SymbolTable; - bool Is64Bit; + SymbolTableType* SymbolTable; + bool IsI386; }; -bool -DumpFile(const char* filename, - std::set& symbols, - std::set& dataSymbols) +bool DumpFile(const char* filename, std::set& symbols, + std::set& dataSymbols) { - HANDLE hFile; - HANDLE hFileMapping; - LPVOID lpFileBase; - PIMAGE_DOS_HEADER dosHeader; + HANDLE hFile; + HANDLE hFileMapping; + LPVOID lpFileBase; + PIMAGE_DOS_HEADER dosHeader; - hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(), - GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(), GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, 0); - if (hFile == INVALID_HANDLE_VALUE) { - fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename); - return false; - } + if (hFile == INVALID_HANDLE_VALUE) { + fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename); + return false; + } - hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (hFileMapping == 0) { - CloseHandle(hFile); - fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n"); - return false; - } + hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hFileMapping == 0) { + CloseHandle(hFile); + fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n"); + return false; + } - lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); - if (lpFileBase == 0) { - CloseHandle(hFileMapping); - CloseHandle(hFile); - fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n"); - return false; - } + lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); + if (lpFileBase == 0) { + CloseHandle(hFileMapping); + CloseHandle(hFile); + fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n"); + return false; + } - dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; - if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { - fprintf(stderr, "File is an executable. I don't dump those.\n"); - return false; - } - /* Does it look like a i386 COFF OBJ file??? */ - else if ( - ((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) || - (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)) - && (dosHeader->e_sp == 0) - ) { - /* - * The two tests above aren't what they look like. They're - * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C) - * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; - */ - DumpSymbols - symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, symbols, dataSymbols, - (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)); + dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; + if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { + fprintf(stderr, "File is an executable. I don't dump those.\n"); + return false; + } + /* Does it look like a COFF OBJ file??? */ + else if (((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) || + (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64) || + (dosHeader->e_magic == IMAGE_FILE_MACHINE_ARMNT)) && + (dosHeader->e_sp == 0)) { + /* + * The two tests above aren't what they look like. They're + * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C) + * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; + */ + DumpSymbols symbolDumper( + (PIMAGE_FILE_HEADER)lpFileBase, symbols, dataSymbols, + (dosHeader->e_magic == IMAGE_FILE_MACHINE_I386)); + symbolDumper.DumpObjFile(); + } else { + // check for /bigobj format + cmANON_OBJECT_HEADER_BIGOBJ* h = (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase; + if (h->Sig1 == 0x0 && h->Sig2 == 0xffff) { + DumpSymbols symbolDumper( + (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase, symbols, dataSymbols, + (h->Machine == IMAGE_FILE_MACHINE_I386)); symbolDumper.DumpObjFile(); - } else { - // check for /bigobj format - cmANON_OBJECT_HEADER_BIGOBJ* h = - (cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase; - if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) { - DumpSymbols - symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, symbols, - dataSymbols, - (h->Machine == IMAGE_FILE_MACHINE_AMD64)); - symbolDumper.DumpObjFile(); - } else { - printf("unrecognized file format in '%s'\n", filename); - return false; - } - } - UnmapViewOfFile(lpFileBase); - CloseHandle(hFileMapping); - CloseHandle(hFile); - return true; + } else { + printf("unrecognized file format in '%s'\n", filename); + return false; + } + } + UnmapViewOfFile(lpFileBase); + CloseHandle(hFileMapping); + CloseHandle(hFile); + return true; } bool bindexplib::AddObjectFile(const char* filename) { - if(!DumpFile(filename, this->Symbols, this->DataSymbols)) - { + return DumpFile(filename, this->Symbols, this->DataSymbols); +} + +bool bindexplib::AddDefinitionFile(const char* filename) +{ + cmsys::ifstream infile(filename); + if (!infile) { + fprintf(stderr, "Couldn't open definition file '%s'\n", filename); return false; + } + std::string str; + while (std::getline(infile, str)) { + // skip the LIBRAY and EXPORTS lines (if any) + if ((str.compare(0, 7, "LIBRARY") == 0) || + (str.compare(0, 7, "EXPORTS") == 0)) { + continue; + } + // remove leading tabs & spaces + str.erase(0, str.find_first_not_of(" \t")); + std::size_t found = str.find(" \t DATA"); + if (found != std::string::npos) { + str.erase(found, std::string::npos); + this->DataSymbols.insert(str); + } else { + this->Symbols.insert(str); } + } + infile.close(); return true; } void bindexplib::WriteFile(FILE* file) { - fprintf(file,"EXPORTS \n"); - for(std::set::const_iterator i = this->DataSymbols.begin(); - i!= this->DataSymbols.end(); ++i) - { + fprintf(file, "EXPORTS \n"); + for (std::set::const_iterator i = this->DataSymbols.begin(); + i != this->DataSymbols.end(); ++i) { fprintf(file, "\t%s \t DATA\n", i->c_str()); - } - for(std::set::const_iterator i = this->Symbols.begin(); - i!= this->Symbols.end(); ++i) - { + } + for (std::set::const_iterator i = this->Symbols.begin(); + i != this->Symbols.end(); ++i) { fprintf(file, "\t%s\n", i->c_str()); - } + } } diff --git a/Source/bindexplib.h b/Source/bindexplib.h index d6900ba88..bc904e9f8 100644 --- a/Source/bindexplib.h +++ b/Source/bindexplib.h @@ -3,7 +3,7 @@ #ifndef bindexplib_h #define bindexplib_h -#include +#include "cmConfigure.h" #include #include @@ -13,8 +13,10 @@ class bindexplib { public: bindexplib() {} + bool AddDefinitionFile(const char* filename); bool AddObjectFile(const char* filename); void WriteFile(FILE* file); + private: std::set Symbols; std::set DataSymbols; diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h index 71009b423..297f901db 100644 --- a/Source/cmAddCompileOptionsCommand.h +++ b/Source/cmAddCompileOptionsCommand.h @@ -3,7 +3,8 @@ #ifndef cmAddCompileOptionsCommand_h #define cmAddCompileOptionsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -25,11 +26,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_compile_options"; } }; #endif diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index a10061727..b5e7c9ea9 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -369,7 +369,7 @@ bool cmAddCustomCommandCommand::CheckOutputs( // Make sure the output file name has no invalid characters. std::string::size_type pos = o->find_first_of("#<>"); - if (pos != o->npos) { + if (pos != std::string::npos) { std::ostringstream msg; msg << "called with OUTPUT containing a \"" << (*o)[pos] << "\". This character is not allowed."; diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h index ea921630b..c3a91b2a3 100644 --- a/Source/cmAddCustomCommandCommand.h +++ b/Source/cmAddCustomCommandCommand.h @@ -3,7 +3,8 @@ #ifndef cmAddCustomCommandCommand_h #define cmAddCustomCommandCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_custom_command"; } - protected: bool CheckOutputs(const std::vector& outputs); }; diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index 0d0149371..87e114780 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -24,10 +24,10 @@ bool cmAddCustomTargetCommand::InitialPass( return false; } - std::string targetName = args[0]; + std::string const& targetName = args[0]; // Check the target name. - if (targetName.find_first_of("/\\") != targetName.npos) { + if (targetName.find_first_of("/\\") != std::string::npos) { std::ostringstream e; e << "called with invalid target name \"" << targetName << "\". Target names may not contain a slash. " @@ -144,7 +144,7 @@ bool cmAddCustomTargetCommand::InitialPass( } std::string::size_type pos = targetName.find_first_of("#<>"); - if (pos != targetName.npos) { + if (pos != std::string::npos) { std::ostringstream msg; msg << "called with target name containing a \"" << targetName[pos] << "\". This character is not allowed."; diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h index b6792472f..7229c2779 100644 --- a/Source/cmAddCustomTargetCommand.h +++ b/Source/cmAddCustomTargetCommand.h @@ -3,7 +3,8 @@ #ifndef cmAddCustomTargetCommand_h #define cmAddCustomTargetCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_custom_target"; } }; #endif diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h index 735f8cc1e..abf5a5964 100644 --- a/Source/cmAddDefinitionsCommand.h +++ b/Source/cmAddDefinitionsCommand.h @@ -3,7 +3,8 @@ #ifndef cmAddDefinitionsCommand_h #define cmAddDefinitionsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,11 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_definitions"; } }; #endif diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index e49d5d5d9..a73b57e82 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -19,7 +19,7 @@ bool cmAddDependenciesCommand::InitialPass( return false; } - std::string target_name = args[0]; + std::string const& target_name = args[0]; if (this->Makefile->IsAlias(target_name)) { std::ostringstream e; e << "Cannot add target-level dependencies to alias target \"" diff --git a/Source/cmAddDependenciesCommand.h b/Source/cmAddDependenciesCommand.h index 8be546c6c..c7328d63e 100644 --- a/Source/cmAddDependenciesCommand.h +++ b/Source/cmAddDependenciesCommand.h @@ -3,7 +3,8 @@ #ifndef cmDependenciessCommand_h #define cmDependenciessCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,11 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_dependencies"; } }; #endif diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index aae1085ba..1d0376fe0 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -24,7 +24,7 @@ bool cmAddExecutableCommand::InitialPass(std::vector const& args, } std::vector::const_iterator s = args.begin(); - std::string exename = *s; + std::string const& exename = *s; ++s; bool use_win32 = false; diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h index 62583d895..8100da185 100644 --- a/Source/cmAddExecutableCommand.h +++ b/Source/cmAddExecutableCommand.h @@ -3,7 +3,8 @@ #ifndef cmExecutablesCommand_h #define cmExecutablesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,11 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_executable"; } }; #endif diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 9ae4ace4a..ebf17632a 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -37,7 +37,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector const& args, std::vector::const_iterator s = args.begin(); - std::string libName = *s; + std::string const& libName = *s; ++s; @@ -297,10 +297,15 @@ bool cmAddLibraryCommand::InitialPass(std::vector const& args, return false; } if (type == cmStateEnums::OBJECT_LIBRARY) { - this->Makefile->IssueMessage( - cmake::FATAL_ERROR, - "The OBJECT library type may not be used for IMPORTED libraries."); - return true; + std::string reason; + if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation( + &reason)) { + this->Makefile->IssueMessage( + cmake::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)) { diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index c23b2998f..df49fae93 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -3,7 +3,8 @@ #ifndef cmLibrarysCommand_h #define cmLibrarysCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,11 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_library"; } }; #endif diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index 34ec0e35e..1727ca56f 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -20,7 +20,7 @@ bool cmAddSubDirectoryCommand::InitialPass( } // store the binpath - std::string srcArg = args[0]; + std::string const& srcArg = args[0]; std::string binArg; bool excludeFromAll = false; @@ -32,7 +32,8 @@ bool cmAddSubDirectoryCommand::InitialPass( if (*i == "EXCLUDE_FROM_ALL") { excludeFromAll = true; continue; - } else if (binArg.empty()) { + } + if (binArg.empty()) { binArg = *i; } else { this->SetError("called with incorrect number of arguments"); diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h index 85305e6d0..0e71ffd85 100644 --- a/Source/cmAddSubDirectoryCommand.h +++ b/Source/cmAddSubDirectoryCommand.h @@ -3,7 +3,8 @@ #ifndef cmAddSubDirectoryCommand_h #define cmAddSubDirectoryCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_subdirectory"; } }; #endif diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h index 07eff6866..a098a03f1 100644 --- a/Source/cmAddTestCommand.h +++ b/Source/cmAddTestCommand.h @@ -3,7 +3,8 @@ #ifndef cmAddTestCommand_h #define cmAddTestCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,11 +32,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "add_test"; } - private: bool HandleNameMode(std::vector const& args); }; diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index 7c683adf0..4adfe2328 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -3,10 +3,10 @@ #ifndef cmAlgorithms_h #define cmAlgorithms_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep +#include "cm_kwiml.h" #include -#include #include #include #include @@ -101,6 +101,12 @@ FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last) return first; } +template +void cmEraseIf(Container& cont, Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + namespace ContainerAlgorithms { template @@ -354,7 +360,8 @@ std::string cmWrap(std::string const& prefix, Range const& r, } template -std::string cmWrap(char prefix, Range const& r, char suffix, std::string sep) +std::string cmWrap(char prefix, Range const& r, char suffix, + std::string const& sep) { return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep); } diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 879c2ca36..0f13b114f 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -5,10 +5,10 @@ #include "cmLocale.h" #include "cmSystemTools.h" #include "cm_get_date.h" -#include -#include -#include -#include +#include "cm_libarchive.h" +#include "cmsys/Directory.hxx" +#include "cmsys/Encoding.hxx" +#include "cmsys/FStream.hxx" #include #include #include diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 27c62b923..4c85c0d16 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -3,7 +3,7 @@ #ifndef cmArchiveWrite_h #define cmArchiveWrite_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 7cfa4d862..847a41660 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAuxSourceDirectoryCommand.h" +#include "cmsys/Directory.hxx" #include -#include #include #include "cmAlgorithms.h" @@ -18,13 +18,13 @@ class cmExecutionStatus; bool cmAuxSourceDirectoryCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (args.size() < 2 || args.size() > 2) { + if (args.size() != 2) { this->SetError("called with incorrect number of arguments"); return false; } std::string sourceListValue; - std::string templateDirectory = args[0]; + std::string const& templateDirectory = args[0]; std::string tdir; if (!cmSystemTools::FileIsFullPath(templateDirectory.c_str())) { tdir = this->Makefile->GetCurrentSourceDirectory(); @@ -54,7 +54,7 @@ bool cmAuxSourceDirectoryCommand::InitialPass( std::string ext = file.substr(dotpos + 1); std::string base = file.substr(0, dotpos); // Process only source files - std::vector srcExts = + std::vector const& srcExts = this->Makefile->GetCMakeInstance()->GetSourceExtensions(); if (!base.empty() && std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) { diff --git a/Source/cmAuxSourceDirectoryCommand.h b/Source/cmAuxSourceDirectoryCommand.h index d99bf7bd8..e49e86117 100644 --- a/Source/cmAuxSourceDirectoryCommand.h +++ b/Source/cmAuxSourceDirectoryCommand.h @@ -3,7 +3,8 @@ #ifndef cmAuxSourceDirectoryCommand_h #define cmAuxSourceDirectoryCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -34,11 +35,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "aux_source_directory"; } }; #endif diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx index 091d6190c..1dac212c2 100644 --- a/Source/cmBase32.cxx +++ b/Source/cmBase32.cxx @@ -58,7 +58,7 @@ std::string cmBase32Encoder::encodeString(const unsigned char* input, input += blockSize; } - size_t remain(end - input); + size_t remain = static_cast(end - input); if (remain != 0) { // Temporary source buffer filled up with 0s unsigned char extended[blockSize]; diff --git a/Source/cmBase32.h b/Source/cmBase32.h index 44bca2f3c..c6758d4f3 100644 --- a/Source/cmBase32.h +++ b/Source/cmBase32.h @@ -3,7 +3,7 @@ #ifndef cmBase32_h #define cmBase32_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx index 9bb6137c8..3772c6fb6 100644 --- a/Source/cmBreakCommand.cxx +++ b/Source/cmBreakCommand.cxx @@ -41,7 +41,7 @@ bool cmBreakCommand::InitialPass(std::vector const& args, } } - status.SetBreakInvoked(true); + status.SetBreakInvoked(); if (!args.empty()) { bool issueMessage = true; diff --git a/Source/cmBreakCommand.h b/Source/cmBreakCommand.h index 5113e180d..fcca45c31 100644 --- a/Source/cmBreakCommand.h +++ b/Source/cmBreakCommand.h @@ -3,7 +3,8 @@ #ifndef cmBreakCommand_h #define cmBreakCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "break"; } }; #endif diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 683615103..fd876004b 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -32,7 +32,7 @@ bool cmBuildCommand::MainSignature(std::vector const& args) } // The cmake variable in which to store the result. - const char* variable = args[0].c_str(); + std::string const& variable = args[0]; // Parse remaining arguments. std::string configuration; @@ -104,7 +104,7 @@ bool cmBuildCommand::TwoArgsSignature(std::vector const& args) return false; } - const char* define = args[0].c_str(); + std::string const& define = args[0]; const char* cacheValue = this->Makefile->GetDefinition(define); std::string configType; diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h index 62f1fd3b5..1f357a980 100644 --- a/Source/cmBuildCommand.h +++ b/Source/cmBuildCommand.h @@ -3,7 +3,8 @@ #ifndef cmBuildCommand_h #define cmBuildCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -41,11 +42,6 @@ public: */ virtual bool TwoArgsSignature(std::vector const& args); - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "build_command"; } - private: bool IgnoreErrors() const; }; diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 1e1cd2121..9d2c0c642 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -2,11 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmBuildNameCommand.h" +#include "cmsys/RegularExpression.hxx" #include -#include #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -16,11 +15,6 @@ class cmExecutionStatus; bool cmBuildNameCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0036, - "The build_name command should not be called; see CMP0036.")) { - return true; - } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h index 1e1f4b566..ff26c559c 100644 --- a/Source/cmBuildNameCommand.h +++ b/Source/cmBuildNameCommand.h @@ -3,7 +3,8 @@ #ifndef cmBuildNameCommand_h #define cmBuildNameCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -17,8 +18,6 @@ public: cmCommand* Clone() CM_OVERRIDE { return new cmBuildNameCommand; } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "build_name"; } - bool IsScriptable() const CM_OVERRIDE { return true; } }; #endif diff --git a/Source/cmCLocaleEnvironmentScope.h b/Source/cmCLocaleEnvironmentScope.h index 32cc8dfe3..e956cb24d 100644 --- a/Source/cmCLocaleEnvironmentScope.h +++ b/Source/cmCLocaleEnvironmentScope.h @@ -3,13 +3,15 @@ #ifndef cmCLocaleEnvironmentScope_h #define cmCLocaleEnvironmentScope_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include #include class cmCLocaleEnvironmentScope { + CM_DISABLE_COPY(cmCLocaleEnvironmentScope) + public: cmCLocaleEnvironmentScope(); ~cmCLocaleEnvironmentScope(); diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index e135ac690..4475c5a52 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -26,7 +26,7 @@ bool cmCMakeHostSystemInformationCommand::InitialPass( return false; } - std::string variable = args[current_index + 1]; + std::string const& variable = args[current_index + 1]; current_index += 2; if (args.size() < (current_index + 2) || args[current_index] != "QUERY") { @@ -41,7 +41,7 @@ bool cmCMakeHostSystemInformationCommand::InitialPass( std::string result_list; for (size_t i = current_index + 1; i < args.size(); ++i) { - std::string key = args[i]; + std::string const& key = args[i]; if (i != current_index + 1) { result_list += ";"; } diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h index 22f3d54dd..ef6ca3730 100644 --- a/Source/cmCMakeHostSystemInformationCommand.h +++ b/Source/cmCMakeHostSystemInformationCommand.h @@ -3,7 +3,8 @@ #ifndef cmCMakeHostSystemInformationCommand_h #define cmCMakeHostSystemInformationCommand_h -#include +#include "cmConfigure.h" + #include #include #include @@ -39,19 +40,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "cmake_host_system_information"; - } - private: bool GetValue(cmsys::SystemInformation& info, std::string const& key, std::string& value); diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h index 08a5c38e8..45b6b7885 100644 --- a/Source/cmCMakeMinimumRequired.h +++ b/Source/cmCMakeMinimumRequired.h @@ -3,7 +3,8 @@ #ifndef cmCMakeMinimumRequired_h #define cmCMakeMinimumRequired_h -#include +#include "cmConfigure.h" + #include #include @@ -31,16 +32,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "cmake_minimum_required"; } - private: std::vector UnknownArguments; bool EnforceUnknownArguments(); diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h index 409fc59be..0e88243f5 100644 --- a/Source/cmCMakePolicyCommand.h +++ b/Source/cmCMakePolicyCommand.h @@ -3,7 +3,8 @@ #ifndef cmCMakePolicyCommand_h #define cmCMakePolicyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,16 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "cmake_policy"; } - private: bool HandleSetMode(std::vector const& args); bool HandleGetMode(std::vector const& args); diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx index ae6b0a131..57a8b383c 100644 --- a/Source/cmCPackPropertiesGenerator.cxx +++ b/Source/cmCPackPropertiesGenerator.cxx @@ -19,7 +19,7 @@ cmCPackPropertiesGenerator::cmCPackPropertiesGenerator( } void cmCPackPropertiesGenerator::GenerateScriptForConfig( - std::ostream& os, const std::string& config, Indent const& indent) + std::ostream& os, const std::string& config, Indent indent) { std::string const& expandedFileName = this->InstalledFile.GetNameExpression().Evaluate(this->LG, config); diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h index 37c603929..48f4c10f4 100644 --- a/Source/cmCPackPropertiesGenerator.h +++ b/Source/cmCPackPropertiesGenerator.h @@ -3,7 +3,7 @@ #ifndef cmCPackPropertiesGenerator_h #define cmCPackPropertiesGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include "cmScriptGenerator.h" @@ -20,6 +20,8 @@ class cmLocalGenerator; */ class cmCPackPropertiesGenerator : public cmScriptGenerator { + CM_DISABLE_COPY(cmCPackPropertiesGenerator) + public: cmCPackPropertiesGenerator(cmLocalGenerator* lg, cmInstalledFile const& installedFile, @@ -27,7 +29,7 @@ public: protected: void GenerateScriptForConfig(std::ostream& os, const std::string& config, - Indent const& indent) CM_OVERRIDE; + Indent indent) CM_OVERRIDE; cmLocalGenerator* LG; cmInstalledFile const& InstalledFile; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 559275e0e..e2605561a 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2,15 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTest.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "cm_curl.h" +#include "cm_zlib.h" +#include "cmsys/Base64.h" +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/Process.h" +#include "cmsys/String.hxx" +#include "cmsys/SystemInformation.hxx" #include #include #include @@ -119,10 +119,10 @@ std::string cmCTest::CleanString(const std::string& str) { std::string::size_type spos = str.find_first_not_of(" \n\t\r\f\v"); std::string::size_type epos = str.find_last_not_of(" \n\t\r\f\v"); - if (spos == str.npos) { + if (spos == std::string::npos) { return std::string(); } - if (epos != str.npos) { + if (epos != std::string::npos) { epos = epos - spos + 1; } return str.substr(spos, epos); @@ -416,7 +416,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) } } - cmake cm; + cmake cm(cmake::RoleScript); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -669,12 +669,11 @@ bool cmCTest::UpdateCTestConfiguration() continue; } std::string::size_type cpos = line.find_first_of(':'); - if (cpos == line.npos) { + if (cpos == std::string::npos) { continue; } std::string key = line.substr(0, cpos); - std::string value = - cmCTest::CleanString(line.substr(cpos + 1, line.npos)); + std::string value = cmCTest::CleanString(line.substr(cpos + 1)); this->CTestConfiguration[key] = value; } fin.close(); @@ -1122,7 +1121,6 @@ int cmCTest::RunTest(std::vector argv, std::string* output, if (log) { *log << "* Run internal CTest" << std::endl; } - std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory(); CM_AUTO_PTR saveEnv; if (modifyEnv) { @@ -1137,7 +1135,6 @@ int cmCTest::RunTest(std::vector argv, std::string* output, if (log && output) { *log << *output; } - cmSystemTools::ChangeDirectory(oldpath); if (output) { cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Internal cmCTest object used to run test." << std::endl @@ -1243,7 +1240,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value) // const char* disallowed = "\\:*?\"<>|\n\r\t\f\v"; - if (safevalue.find_first_of(disallowed) != value.npos) { + if (safevalue.find_first_of(disallowed) != std::string::npos) { std::string::size_type i = 0; std::string::size_type n = strlen(disallowed); char replace[2]; @@ -1901,6 +1898,34 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, ->SetPersistentOption("ExcludeRegularExpression", args[i].c_str()); } + if (this->CheckArgument(arg, "-FA", "--fixture-exclude-any") && + i < args.size() - 1) { + i++; + this->GetHandler("test")->SetPersistentOption( + "ExcludeFixtureRegularExpression", args[i].c_str()); + this->GetHandler("memcheck") + ->SetPersistentOption("ExcludeFixtureRegularExpression", + args[i].c_str()); + } + if (this->CheckArgument(arg, "-FS", "--fixture-exclude-setup") && + i < args.size() - 1) { + i++; + this->GetHandler("test")->SetPersistentOption( + "ExcludeFixtureSetupRegularExpression", args[i].c_str()); + this->GetHandler("memcheck") + ->SetPersistentOption("ExcludeFixtureSetupRegularExpression", + args[i].c_str()); + } + if (this->CheckArgument(arg, "-FC", "--fixture-exclude-cleanup") && + i < args.size() - 1) { + i++; + this->GetHandler("test")->SetPersistentOption( + "ExcludeFixtureCleanupRegularExpression", args[i].c_str()); + this->GetHandler("memcheck") + ->SetPersistentOption("ExcludeFixtureCleanupRegularExpression", + args[i].c_str()); + } + if (this->CheckArgument(arg, "--rerun-failed")) { this->GetHandler("test")->SetPersistentOption("RerunFailed", "true"); this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true"); @@ -2323,8 +2348,8 @@ std::string cmCTest::GetShortPathToFile(const char* cfname) cmSystemTools::RelativePath(buildDir.c_str(), fname.c_str()); // If any contains "." it is not parent directory - bool inSrc = srcRelpath.find("..") == srcRelpath.npos; - bool inBld = bldRelpath.find("..") == bldRelpath.npos; + bool inSrc = srcRelpath.find("..") == std::string::npos; + bool inBld = bldRelpath.find("..") == std::string::npos; // TODO: Handle files with .. in their name std::string* res = CM_NULLPTR; @@ -2483,7 +2508,7 @@ void cmCTest::AddSubmitFile(Part part, const char* name) void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr) { size_t epos = overStr.find('='); - if (epos == overStr.npos) { + if (epos == std::string::npos) { cmCTestLog(this, ERROR_MESSAGE, "CTest configuration overwrite specified in the wrong format." << std::endl @@ -2492,7 +2517,7 @@ void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr) return; } std::string key = overStr.substr(0, epos); - std::string value = overStr.substr(epos + 1, overStr.npos); + std::string value = overStr.substr(epos + 1); this->CTestConfigurationOverwrites[key] = value; } diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 4d334585f..60f3295e7 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -3,10 +3,10 @@ #ifndef cmCTest_h #define cmCTest_h -#include +#include "cmConfigure.h" -#include -#include +#include "cmProcessOutput.h" +#include "cmsys/String.hxx" #include #include #include @@ -14,29 +14,12 @@ #include #include -class cmCTest; class cmCTestGenericHandler; class cmCTestStartCommand; class cmGeneratedFileStream; class cmMakefile; class cmXMLWriter; -#define cmCTestLog(ctSelf, logType, msg) \ - do { \ - std::ostringstream cmCTestLog_msg; \ - cmCTestLog_msg << msg; \ - (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__, \ - cmCTestLog_msg.str().c_str()); \ - } while (false) - -#define cmCTestOptionalLog(ctSelf, logType, msg, suppress) \ - do { \ - std::ostringstream cmCTestLog_msg; \ - cmCTestLog_msg << msg; \ - (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__, \ - cmCTestLog_msg.str().c_str(), suppress); \ - } while (false) - /** \class cmCTest * \brief Represents a ctest invocation. * @@ -648,4 +631,20 @@ inline std::ostream& operator<<(std::ostream& os, const cmCTestLogWrite& c) return os; } +#define cmCTestLog(ctSelf, logType, msg) \ + do { \ + std::ostringstream cmCTestLog_msg; \ + cmCTestLog_msg << msg; \ + (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__, \ + cmCTestLog_msg.str().c_str()); \ + } while (false) + +#define cmCTestOptionalLog(ctSelf, logType, msg, suppress) \ + do { \ + std::ostringstream cmCTestLog_msg; \ + cmCTestLog_msg << msg; \ + (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__, \ + cmCTestLog_msg.str().c_str(), suppress); \ + } while (false) + #endif diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index cb0ba63a6..0b025ab6f 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCacheManager.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" #include -#include -#include #include #include #include @@ -205,8 +205,7 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, return false; } -void cmCacheManager::WritePropertyEntries(std::ostream& os, - CacheIterator const& i) +void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i) { for (const char** p = this->PersistentProperties; *p; ++p) { if (const char* value = i.GetProperty(*p)) { @@ -387,7 +386,7 @@ void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key) { // support : in key name by double quoting const char* q = - (key.find(':') != key.npos || key.find("//") == 0) ? "\"" : ""; + (key.find(':') != std::string::npos || key.find("//") == 0) ? "\"" : ""; fout << q << key << q; } @@ -490,7 +489,7 @@ void cmCacheManager::AddCacheEntry(const std::string& key, const char* value, e.Type = type; // make sure we only use unix style paths if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) { - if (e.Value.find(';') != e.Value.npos) { + if (e.Value.find(';') != std::string::npos) { std::vector paths; cmSystemTools::ExpandListArgument(e.Value, paths); const char* sep = ""; diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index e82c9ef3e..c464311c6 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -3,7 +3,7 @@ #ifndef cmCacheManager_h #define cmCacheManager_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -228,7 +228,7 @@ private: static const char* PersistentProperties[]; bool ReadPropertyEntry(std::string const& key, CacheEntry& e); - void WritePropertyEntries(std::ostream& os, CacheIterator const& i); + void WritePropertyEntries(std::ostream& os, CacheIterator i); CacheEntryMap Cache; // Only cmake and cmState should be able to add cache values diff --git a/Source/cmCallVisualStudioMacro.h b/Source/cmCallVisualStudioMacro.h index e9d34e56b..ad35d306a 100644 --- a/Source/cmCallVisualStudioMacro.h +++ b/Source/cmCallVisualStudioMacro.h @@ -3,7 +3,7 @@ #ifndef cmCallVisualStudioMacro_h #define cmCallVisualStudioMacro_h -#include +#include "cmConfigure.h" #include diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx index 181b41266..d349c9167 100644 --- a/Source/cmCommand.cxx +++ b/Source/cmCommand.cxx @@ -3,7 +3,6 @@ #include "cmCommand.h" #include "cmMakefile.h" -#include "cmake.h" class cmExecutionStatus; struct cmListFileArgument; @@ -23,32 +22,12 @@ bool cmCommand::InvokeInitialPass(const std::vector& args, const char* cmCommand::GetError() { if (this->Error.empty()) { - this->Error = this->GetName(); - this->Error += " unknown error."; + return "unknown error."; } return this->Error.c_str(); } void cmCommand::SetError(const std::string& e) { - this->Error = this->GetName(); - this->Error += " "; - this->Error += e; -} - -bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e) -{ - switch (this->Makefile->GetPolicyStatus(pol)) { - case cmPolicies::WARN: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - cmPolicies::GetPolicyWarning(pol)); - case cmPolicies::OLD: - return false; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); - break; - } - return true; + this->Error = e; } diff --git a/Source/cmCommand.h b/Source/cmCommand.h index d9fd5a286..ad72fe208 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -3,13 +3,11 @@ #ifndef cmCommand_h #define cmCommand_h -#include +#include "cmConfigure.h" + #include #include -#include "cmCommandArgumentsHelper.h" -#include "cmPolicies.h" - class cmExecutionStatus; class cmMakefile; struct cmListFileArgument; @@ -26,6 +24,8 @@ struct cmListFileArgument; */ class cmCommand { + CM_DISABLE_COPY(cmCommand) + public: /** * Construct the command. By default it has no makefile. @@ -79,22 +79,6 @@ public: */ virtual cmCommand* Clone() = 0; - /** - * This determines if the command is invoked when in script mode. - */ - virtual bool IsScriptable() const { return false; } - - /** - * This determines if the command is defined in a cmake script. - * It is the case for cmMacroHelperCommand and cmFunctionHelperCommand. - */ - virtual bool IsUserDefined() const { return false; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - virtual std::string GetName() const = 0; - /** * Return the last error string. */ @@ -105,12 +89,8 @@ public: */ void SetError(const std::string& e); - /** Check if the command is disallowed by a policy. */ - bool Disallowed(cmPolicies::PolicyID pol, const char* e); - protected: cmMakefile* Makefile; - cmCommandArgumentsHelper Helper; private: std::string Error; diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 2d66344ef..4eb4531f6 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -2,15 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommandArgumentParserHelper.h" -#include - #include "cmCommandArgumentLexer.h" #include "cmMakefile.h" #include "cmState.h" #include "cmSystemTools.h" #include "cmake.h" -#include #include #include #include diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index 95bf0ad7f..465ca9e28 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -3,32 +3,22 @@ #ifndef cmCommandArgumentParserHelper_h #define cmCommandArgumentParserHelper_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include #include -#define YYSTYPE cmCommandArgumentParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmCommandArgumentParserHelper* -#define YY_DECL \ - int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -/** \class cmCommandArgumentParserHelper - * \brief Helper class for parsing java source files - * - * Finds dependencies for java file and list of outputs - */ - class cmMakefile; class cmCommandArgumentParserHelper { + CM_DISABLE_COPY(cmCommandArgumentParserHelper) + public: - typedef struct + struct ParserType { char* str; - } ParserType; + }; cmCommandArgumentParserHelper(); ~cmCommandArgumentParserHelper(); @@ -100,4 +90,10 @@ private: bool RemoveEmpty; }; +#define YYSTYPE cmCommandArgumentParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmCommandArgumentParserHelper* +#define YY_DECL \ + int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif diff --git a/Source/cmCommandArgumentsHelper.h b/Source/cmCommandArgumentsHelper.h index b19b0f928..44db374d6 100644 --- a/Source/cmCommandArgumentsHelper.h +++ b/Source/cmCommandArgumentsHelper.h @@ -3,7 +3,7 @@ #ifndef cmCommandArgumentsHelper_h #define cmCommandArgumentsHelper_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 4c5b09305..e1d8ef143 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -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 "cmCommands.h" +#include "cmPolicies.h" +#include "cmState.h" #include "cmAddCustomCommandCommand.h" #include "cmAddCustomTargetCommand.h" @@ -68,7 +70,6 @@ #include "cmTargetLinkLibrariesCommand.h" #include "cmTryCompileCommand.h" #include "cmTryRunCommand.h" -#include "cmUnexpectedCommand.h" #include "cmUnsetCommand.h" #include "cmWhileCommand.h" @@ -104,138 +105,249 @@ #include "cmWriteFileCommand.h" #endif -std::vector GetPredefinedCommands() +void GetScriptingCommands(cmState* state) { - std::vector commands; + state->AddBuiltinCommand("break", new cmBreakCommand); + state->AddBuiltinCommand("cmake_minimum_required", + new cmCMakeMinimumRequired); + state->AddBuiltinCommand("cmake_policy", new cmCMakePolicyCommand); + state->AddBuiltinCommand("configure_file", new cmConfigureFileCommand); + state->AddBuiltinCommand("continue", new cmContinueCommand); + state->AddBuiltinCommand("exec_program", new cmExecProgramCommand); + state->AddBuiltinCommand("execute_process", new cmExecuteProcessCommand); + state->AddBuiltinCommand("file", new cmFileCommand); + state->AddBuiltinCommand("find_file", new cmFindFileCommand); + state->AddBuiltinCommand("find_library", new cmFindLibraryCommand); + state->AddBuiltinCommand("find_package", new cmFindPackageCommand); + state->AddBuiltinCommand("find_path", new cmFindPathCommand); + state->AddBuiltinCommand("find_program", new cmFindProgramCommand); + state->AddBuiltinCommand("foreach", new cmForEachCommand); + state->AddBuiltinCommand("function", new cmFunctionCommand); + state->AddBuiltinCommand("get_cmake_property", + new cmGetCMakePropertyCommand); + state->AddBuiltinCommand("get_directory_property", + new cmGetDirectoryPropertyCommand); + state->AddBuiltinCommand("get_filename_component", + new cmGetFilenameComponentCommand); + state->AddBuiltinCommand("get_property", new cmGetPropertyCommand); + state->AddBuiltinCommand("if", new cmIfCommand); + state->AddBuiltinCommand("include", new cmIncludeCommand); + state->AddBuiltinCommand("list", new cmListCommand); + state->AddBuiltinCommand("macro", new cmMacroCommand); + state->AddBuiltinCommand("make_directory", new cmMakeDirectoryCommand); + state->AddBuiltinCommand("mark_as_advanced", new cmMarkAsAdvancedCommand); + state->AddBuiltinCommand("math", new cmMathCommand); + state->AddBuiltinCommand("message", new cmMessageCommand); + state->AddBuiltinCommand("option", new cmOptionCommand); + state->AddBuiltinCommand("cmake_parse_arguments", + new cmParseArgumentsCommand); + state->AddBuiltinCommand("return", new cmReturnCommand); + state->AddBuiltinCommand("separate_arguments", + new cmSeparateArgumentsCommand); + state->AddBuiltinCommand("set", new cmSetCommand); + state->AddBuiltinCommand("set_directory_properties", + new cmSetDirectoryPropertiesCommand); + state->AddBuiltinCommand("set_property", new cmSetPropertyCommand); + state->AddBuiltinCommand("site_name", new cmSiteNameCommand); + state->AddBuiltinCommand("string", new cmStringCommand); + state->AddBuiltinCommand("unset", new cmUnsetCommand); + state->AddBuiltinCommand("while", new cmWhileCommand); - commands.push_back(new cmAddCustomCommandCommand); - commands.push_back(new cmAddCustomTargetCommand); - commands.push_back(new cmAddDefinitionsCommand); - commands.push_back(new cmAddDependenciesCommand); - commands.push_back(new cmAddExecutableCommand); - commands.push_back(new cmAddLibraryCommand); - commands.push_back(new cmAddSubDirectoryCommand); - commands.push_back(new cmAddTestCommand); - commands.push_back(new cmBreakCommand); - commands.push_back(new cmBuildCommand); - commands.push_back(new cmCMakeMinimumRequired); - commands.push_back(new cmCMakePolicyCommand); - commands.push_back(new cmConfigureFileCommand); - commands.push_back(new cmContinueCommand); - commands.push_back(new cmCreateTestSourceList); - commands.push_back(new cmDefinePropertyCommand); - commands.push_back(new cmEnableLanguageCommand); - commands.push_back(new cmEnableTestingCommand); - commands.push_back(new cmExecProgramCommand); - commands.push_back(new cmExecuteProcessCommand); - commands.push_back(new cmFileCommand); - commands.push_back(new cmFindFileCommand); - commands.push_back(new cmFindLibraryCommand); - commands.push_back(new cmFindPackageCommand); - commands.push_back(new cmFindPathCommand); - commands.push_back(new cmFindProgramCommand); - commands.push_back(new cmForEachCommand); - commands.push_back(new cmFunctionCommand); - commands.push_back(new cmGetCMakePropertyCommand); - commands.push_back(new cmGetDirectoryPropertyCommand); - commands.push_back(new cmGetFilenameComponentCommand); - commands.push_back(new cmGetPropertyCommand); - commands.push_back(new cmGetSourceFilePropertyCommand); - commands.push_back(new cmGetTargetPropertyCommand); - commands.push_back(new cmGetTestPropertyCommand); - commands.push_back(new cmIfCommand); - commands.push_back(new cmIncludeCommand); - commands.push_back(new cmIncludeDirectoryCommand); - commands.push_back(new cmIncludeRegularExpressionCommand); - commands.push_back(new cmInstallCommand); - commands.push_back(new cmInstallFilesCommand); - commands.push_back(new cmInstallTargetsCommand); - commands.push_back(new cmLinkDirectoriesCommand); - commands.push_back(new cmListCommand); - commands.push_back(new cmMacroCommand); - commands.push_back(new cmMakeDirectoryCommand); - commands.push_back(new cmMarkAsAdvancedCommand); - commands.push_back(new cmMathCommand); - commands.push_back(new cmMessageCommand); - commands.push_back(new cmOptionCommand); - commands.push_back(new cmParseArgumentsCommand); - commands.push_back(new cmProjectCommand); - commands.push_back(new cmReturnCommand); - commands.push_back(new cmSeparateArgumentsCommand); - commands.push_back(new cmSetCommand); - commands.push_back(new cmSetDirectoryPropertiesCommand); - commands.push_back(new cmSetPropertyCommand); - commands.push_back(new cmSetSourceFilesPropertiesCommand); - commands.push_back(new cmSetTargetPropertiesCommand); - commands.push_back(new cmSetTestsPropertiesCommand); - commands.push_back(new cmSiteNameCommand); - commands.push_back(new cmStringCommand); - commands.push_back(new cmSubdirCommand); - commands.push_back(new cmTargetLinkLibrariesCommand); - commands.push_back(new cmTryCompileCommand); - commands.push_back(new cmTryRunCommand); - commands.push_back(new cmUnsetCommand); - commands.push_back(new cmWhileCommand); - - commands.push_back(new cmUnexpectedCommand( + state->AddUnexpectedCommand( "else", "An ELSE command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " - "the opening IF command.")); - commands.push_back(new cmUnexpectedCommand( + "the opening IF command."); + state->AddUnexpectedCommand( "elseif", "An ELSEIF command was found outside of a proper " - "IF ENDIF structure.")); - commands.push_back(new cmUnexpectedCommand( + "IF ENDIF structure."); + state->AddUnexpectedCommand( "endforeach", "An ENDFOREACH command was found outside of a proper " "FOREACH ENDFOREACH structure. Or its arguments did " - "not match the opening FOREACH command.")); - commands.push_back(new cmUnexpectedCommand( + "not match the opening FOREACH command."); + state->AddUnexpectedCommand( "endfunction", "An ENDFUNCTION command was found outside of a proper " "FUNCTION ENDFUNCTION structure. Or its arguments did not " - "match the opening FUNCTION command.")); - commands.push_back(new cmUnexpectedCommand( + "match the opening FUNCTION command."); + state->AddUnexpectedCommand( "endif", "An ENDIF command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " - "the opening IF command.")); - commands.push_back(new cmUnexpectedCommand( + "the opening IF command."); + state->AddUnexpectedCommand( "endmacro", "An ENDMACRO command was found outside of a proper " "MACRO ENDMACRO structure. Or its arguments did not " - "match the opening MACRO command.")); - commands.push_back(new cmUnexpectedCommand( + "match the opening MACRO command."); + state->AddUnexpectedCommand( "endwhile", "An ENDWHILE command was found outside of a proper " "WHILE ENDWHILE structure. Or its arguments did not " - "match the opening WHILE command.")); + "match the opening WHILE command."); #if defined(CMAKE_BUILD_WITH_CMAKE) - commands.push_back(new cmAddCompileOptionsCommand); - commands.push_back(new cmAuxSourceDirectoryCommand); - commands.push_back(new cmBuildNameCommand); - commands.push_back(new cmCMakeHostSystemInformationCommand); - commands.push_back(new cmExportCommand); - commands.push_back(new cmExportLibraryDependenciesCommand); - commands.push_back(new cmFLTKWrapUICommand); - commands.push_back(new cmIncludeExternalMSProjectCommand); - commands.push_back(new cmInstallProgramsCommand); - commands.push_back(new cmLinkLibrariesCommand); - commands.push_back(new cmLoadCacheCommand); - commands.push_back(new cmLoadCommandCommand); - commands.push_back(new cmOutputRequiredFilesCommand); - commands.push_back(new cmQTWrapCPPCommand); - commands.push_back(new cmQTWrapUICommand); - commands.push_back(new cmRemoveCommand); - commands.push_back(new cmRemoveDefinitionsCommand); - commands.push_back(new cmSourceGroupCommand); - commands.push_back(new cmSubdirDependsCommand); - commands.push_back(new cmTargetCompileDefinitionsCommand); - commands.push_back(new cmTargetCompileFeaturesCommand); - commands.push_back(new cmTargetCompileOptionsCommand); - commands.push_back(new cmTargetIncludeDirectoriesCommand); - commands.push_back(new cmTargetSourcesCommand); - commands.push_back(new cmUseMangledMesaCommand); - commands.push_back(new cmUtilitySourceCommand); - commands.push_back(new cmVariableRequiresCommand); - commands.push_back(new cmVariableWatchCommand); - commands.push_back(new cmWriteFileCommand); + state->AddBuiltinCommand("cmake_host_system_information", + new cmCMakeHostSystemInformationCommand); + state->AddBuiltinCommand("remove", new cmRemoveCommand); + state->AddBuiltinCommand("variable_watch", new cmVariableWatchCommand); + state->AddBuiltinCommand("write_file", new cmWriteFileCommand); + + state->AddDisallowedCommand( + "build_name", new cmBuildNameCommand, cmPolicies::CMP0036, + "The build_name command should not be called; see CMP0036."); + state->AddDisallowedCommand( + "use_mangled_mesa", new cmUseMangledMesaCommand, cmPolicies::CMP0030, + "The use_mangled_mesa command should not be called; see CMP0030."); + #endif +} + +void GetProjectCommands(cmState* state) +{ + state->AddBuiltinCommand("add_custom_command", + new cmAddCustomCommandCommand); + state->AddBuiltinCommand("add_custom_target", new cmAddCustomTargetCommand); + state->AddBuiltinCommand("add_definitions", new cmAddDefinitionsCommand); + state->AddBuiltinCommand("add_dependencies", new cmAddDependenciesCommand); + state->AddBuiltinCommand("add_executable", new cmAddExecutableCommand); + state->AddBuiltinCommand("add_library", new cmAddLibraryCommand); + state->AddBuiltinCommand("add_subdirectory", new cmAddSubDirectoryCommand); + state->AddBuiltinCommand("add_test", new cmAddTestCommand); + state->AddBuiltinCommand("build_command", new cmBuildCommand); + state->AddBuiltinCommand("create_test_sourcelist", + new cmCreateTestSourceList); + state->AddBuiltinCommand("define_property", new cmDefinePropertyCommand); + state->AddBuiltinCommand("enable_language", new cmEnableLanguageCommand); + state->AddBuiltinCommand("enable_testing", new cmEnableTestingCommand); + state->AddBuiltinCommand("get_source_file_property", + new cmGetSourceFilePropertyCommand); + state->AddBuiltinCommand("get_target_property", + new cmGetTargetPropertyCommand); + state->AddBuiltinCommand("get_test_property", new cmGetTestPropertyCommand); + state->AddBuiltinCommand("include_directories", + new cmIncludeDirectoryCommand); + state->AddBuiltinCommand("include_regular_expression", + new cmIncludeRegularExpressionCommand); + state->AddBuiltinCommand("install", new cmInstallCommand); + state->AddBuiltinCommand("install_files", new cmInstallFilesCommand); + state->AddBuiltinCommand("install_targets", new cmInstallTargetsCommand); + state->AddBuiltinCommand("link_directories", new cmLinkDirectoriesCommand); + state->AddBuiltinCommand("project", new cmProjectCommand); + state->AddBuiltinCommand("set_source_files_properties", + new cmSetSourceFilesPropertiesCommand); + state->AddBuiltinCommand("set_target_properties", + new cmSetTargetPropertiesCommand); + state->AddBuiltinCommand("set_tests_properties", + new cmSetTestsPropertiesCommand); + state->AddBuiltinCommand("subdirs", new cmSubdirCommand); + state->AddBuiltinCommand("target_link_libraries", + new cmTargetLinkLibrariesCommand); + state->AddBuiltinCommand("try_compile", new cmTryCompileCommand); + state->AddBuiltinCommand("try_run", new cmTryRunCommand); + +#if defined(CMAKE_BUILD_WITH_CMAKE) + state->AddBuiltinCommand("add_compile_options", + new cmAddCompileOptionsCommand); + state->AddBuiltinCommand("aux_source_directory", + new cmAuxSourceDirectoryCommand); + state->AddBuiltinCommand("export", new cmExportCommand); + state->AddBuiltinCommand("fltk_wrap_ui", new cmFLTKWrapUICommand); + state->AddBuiltinCommand("include_external_msproject", + new cmIncludeExternalMSProjectCommand); + state->AddBuiltinCommand("install_programs", new cmInstallProgramsCommand); + state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand); + state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand); + state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand); + state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand); + state->AddBuiltinCommand("remove_definitions", + new cmRemoveDefinitionsCommand); + state->AddBuiltinCommand("source_group", new cmSourceGroupCommand); + state->AddBuiltinCommand("target_compile_definitions", + new cmTargetCompileDefinitionsCommand); + state->AddBuiltinCommand("target_compile_features", + new cmTargetCompileFeaturesCommand); + state->AddBuiltinCommand("target_compile_options", + new cmTargetCompileOptionsCommand); + state->AddBuiltinCommand("target_include_directories", + new cmTargetIncludeDirectoriesCommand); + state->AddBuiltinCommand("target_sources", new cmTargetSourcesCommand); + + state->AddDisallowedCommand( + "export_library_dependencies", new cmExportLibraryDependenciesCommand, + cmPolicies::CMP0033, + "The export_library_dependencies command should not be called; " + "see CMP0033."); + state->AddDisallowedCommand( + "load_command", new cmLoadCommandCommand, cmPolicies::CMP0031, + "The load_command command should not be called; see CMP0031."); + state->AddDisallowedCommand( + "output_required_files", new cmOutputRequiredFilesCommand, + cmPolicies::CMP0032, + "The output_required_files command should not be called; see CMP0032."); + state->AddDisallowedCommand( + "subdir_depends", new cmSubdirDependsCommand, cmPolicies::CMP0029, + "The subdir_depends command should not be called; see CMP0029."); + state->AddDisallowedCommand( + "utility_source", new cmUtilitySourceCommand, cmPolicies::CMP0034, + "The utility_source command should not be called; see CMP0034."); + state->AddDisallowedCommand( + "variable_requires", new cmVariableRequiresCommand, cmPolicies::CMP0035, + "The variable_requires command should not be called; see CMP0035."); +#endif +} + +void GetProjectCommandsInScriptMode(cmState* state) +{ +#define CM_UNEXPECTED_PROJECT_COMMAND(NAME) \ + state->AddUnexpectedCommand(NAME, "command is not scriptable") + + CM_UNEXPECTED_PROJECT_COMMAND("add_compile_options"); + CM_UNEXPECTED_PROJECT_COMMAND("add_custom_command"); + CM_UNEXPECTED_PROJECT_COMMAND("add_custom_target"); + CM_UNEXPECTED_PROJECT_COMMAND("add_definitions"); + CM_UNEXPECTED_PROJECT_COMMAND("add_dependencies"); + CM_UNEXPECTED_PROJECT_COMMAND("add_executable"); + CM_UNEXPECTED_PROJECT_COMMAND("add_library"); + CM_UNEXPECTED_PROJECT_COMMAND("add_subdirectory"); + CM_UNEXPECTED_PROJECT_COMMAND("add_test"); + CM_UNEXPECTED_PROJECT_COMMAND("aux_source_directory"); + CM_UNEXPECTED_PROJECT_COMMAND("build_command"); + CM_UNEXPECTED_PROJECT_COMMAND("create_test_sourcelist"); + CM_UNEXPECTED_PROJECT_COMMAND("define_property"); + CM_UNEXPECTED_PROJECT_COMMAND("enable_language"); + CM_UNEXPECTED_PROJECT_COMMAND("enable_testing"); + CM_UNEXPECTED_PROJECT_COMMAND("export"); + CM_UNEXPECTED_PROJECT_COMMAND("fltk_wrap_ui"); + CM_UNEXPECTED_PROJECT_COMMAND("get_source_file_property"); + CM_UNEXPECTED_PROJECT_COMMAND("get_target_property"); + CM_UNEXPECTED_PROJECT_COMMAND("get_test_property"); + CM_UNEXPECTED_PROJECT_COMMAND("include_directories"); + CM_UNEXPECTED_PROJECT_COMMAND("include_external_msproject"); + CM_UNEXPECTED_PROJECT_COMMAND("include_regular_expression"); + CM_UNEXPECTED_PROJECT_COMMAND("install"); + CM_UNEXPECTED_PROJECT_COMMAND("link_directories"); + CM_UNEXPECTED_PROJECT_COMMAND("link_libraries"); + CM_UNEXPECTED_PROJECT_COMMAND("load_cache"); + CM_UNEXPECTED_PROJECT_COMMAND("project"); + CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_cpp"); + CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_ui"); + CM_UNEXPECTED_PROJECT_COMMAND("remove_definitions"); + CM_UNEXPECTED_PROJECT_COMMAND("set_source_files_properties"); + CM_UNEXPECTED_PROJECT_COMMAND("set_target_properties"); + CM_UNEXPECTED_PROJECT_COMMAND("set_tests_properties"); + CM_UNEXPECTED_PROJECT_COMMAND("source_group"); + CM_UNEXPECTED_PROJECT_COMMAND("target_compile_definitions"); + CM_UNEXPECTED_PROJECT_COMMAND("target_compile_features"); + CM_UNEXPECTED_PROJECT_COMMAND("target_compile_options"); + CM_UNEXPECTED_PROJECT_COMMAND("target_include_directories"); + CM_UNEXPECTED_PROJECT_COMMAND("target_link_libraries"); + CM_UNEXPECTED_PROJECT_COMMAND("target_sources"); + CM_UNEXPECTED_PROJECT_COMMAND("try_compile"); + CM_UNEXPECTED_PROJECT_COMMAND("try_run"); + + // deprected commands + CM_UNEXPECTED_PROJECT_COMMAND("export_library_dependencies"); + CM_UNEXPECTED_PROJECT_COMMAND("load_command"); + CM_UNEXPECTED_PROJECT_COMMAND("output_required_files"); + CM_UNEXPECTED_PROJECT_COMMAND("subdir_depends"); + CM_UNEXPECTED_PROJECT_COMMAND("utility_source"); + CM_UNEXPECTED_PROJECT_COMMAND("variable_requires"); - return commands; +#undef CM_UNEXPECTED_PROJECT_COMMAND } diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 649dea6b5..1f8fafb46 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -3,16 +3,15 @@ #ifndef cmCommands_h #define cmCommands_h -#include // IWYU pragma: keep +class cmState; -#include - -class cmCommand; /** - * Global function to return all compiled in commands. + * Global function to register all compiled in commands. * To add a new command edit cmCommands.cxx and add your command. * It is up to the caller to delete the commands created by this call. */ -std::vector GetPredefinedCommands(); +void GetScriptingCommands(cmState* state); +void GetProjectCommands(cmState* state); +void GetProjectCommandsInScriptMode(cmState* state); #endif diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 239582f83..391d65c40 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommonTargetGenerator.h" -#include +#include "cmConfigure.h" #include #include #include @@ -26,7 +26,6 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) , GlobalGenerator(static_cast( gt->LocalGenerator->GetGlobalGenerator())) , ConfigName(LocalGenerator->GetConfigName()) - , ModuleDefinitionFile(GeneratorTarget->GetModuleDefinitionFile(ConfigName)) { } @@ -44,33 +43,12 @@ const char* cmCommonTargetGenerator::GetFeature(const std::string& feature) return this->GeneratorTarget->GetFeature(feature, this->ConfigName); } -bool cmCommonTargetGenerator::GetFeatureAsBool(const std::string& feature) -{ - return this->GeneratorTarget->GetFeatureAsBool(feature, this->ConfigName); -} - -void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags, - const std::string& lang) -{ - // Add language-specific flags. - this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName); - - if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION")) { - this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO"); - } -} - void cmCommonTargetGenerator::AddModuleDefinitionFlag( cmLinkLineComputer* linkLineComputer, std::string& flags) { - // A module definition file only makes sense on certain target types. - if (this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY && - this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY && - this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) { - return; - } - - if (!this->ModuleDefinitionFile) { + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + if (!mdi || mdi->DefFile.empty()) { return; } @@ -85,8 +63,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag( // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; flag += this->LocalGenerator->ConvertToOutputFormat( - linkLineComputer->ConvertToLinkReference( - this->ModuleDefinitionFile->GetFullPath()), + linkLineComputer->ConvertToLinkReference(mdi->DefFile), cmOutputConverter::SHELL); this->LocalGenerator->AppendFlags(flags, flag); } diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index d67fefbd1..c36145fe2 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -3,7 +3,8 @@ #ifndef cmCommonTargetGenerator_h #define cmCommonTargetGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep + #include #include #include @@ -27,12 +28,8 @@ public: std::string const& GetConfigName() const; protected: - // Add language feature flags. - void AddFeatureFlags(std::string& flags, const std::string& lang); - // Feature query methods. const char* GetFeature(const std::string& feature); - bool GetFeatureAsBool(const std::string& feature); // Helper to add flag for windows .def file. void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer, @@ -44,9 +41,6 @@ protected: cmGlobalCommonGenerator* GlobalGenerator; std::string ConfigName; - // The windows module definition source file (.def), if any. - cmSourceFile const* ModuleDefinitionFile; - void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); diff --git a/Source/cmComputeComponentGraph.h b/Source/cmComputeComponentGraph.h index 608dedc1e..8cd4fe73a 100644 --- a/Source/cmComputeComponentGraph.h +++ b/Source/cmComputeComponentGraph.h @@ -3,7 +3,7 @@ #ifndef cmComputeComponentGraph_h #define cmComputeComponentGraph_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmGraphAdjacencyList.h" diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 3e2cf1875..9c516ee8d 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -333,7 +333,7 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) return index; } -void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) +void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe) { // Get this entry representation. int depender_index = qe.Index; diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 6a4e8e001..84ee9161f 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -3,7 +3,7 @@ #ifndef cmComputeLinkDepends_h #define cmComputeLinkDepends_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmGraphAdjacencyList.h" #include "cmLinkItem.h" @@ -93,7 +93,7 @@ private: const char* LibDepends; }; std::queue BFSQueue; - void FollowLinkEntry(BFSEntry const&); + void FollowLinkEntry(BFSEntry qe); // Shared libraries that are included only because they are // dependencies of other shared libraries, not because they are part diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 80e7e7da1..b2deaaa85 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -500,7 +500,10 @@ bool cmComputeLinkInformation::Compute() cmGeneratorTarget const* tgt = *i; bool implib = (this->UseImportLibrary && (tgt->GetType() == cmStateEnums::SHARED_LIBRARY)); - std::string lib = tgt->GetFullPath(this->Config, implib, true); + cmStateEnums::ArtifactType artifact = implib + ? cmStateEnums::ImportLibraryArtifact + : cmStateEnums::RuntimeBinaryArtifact; + std::string lib = tgt->GetFullPath(this->Config, artifact, true); this->OldLinkDirItems.push_back(lib); } } @@ -596,8 +599,11 @@ void cmComputeLinkInformation::AddItem(std::string const& item, // platform. Add it now. std::string linkItem; linkItem = this->LoaderFlag; + cmStateEnums::ArtifactType artifact = this->UseImportLibrary + ? cmStateEnums::ImportLibraryArtifact + : cmStateEnums::RuntimeBinaryArtifact; - std::string exe = tgt->GetFullPath(config, this->UseImportLibrary, true); + std::string exe = tgt->GetFullPath(config, artifact, true); linkItem += exe; this->Items.push_back(Item(linkItem, true, tgt)); this->Depends.push_back(exe); @@ -617,9 +623,12 @@ void cmComputeLinkInformation::AddItem(std::string const& item, bool implib = (this->UseImportLibrary && (impexe || tgt->GetType() == cmStateEnums::SHARED_LIBRARY)); + cmStateEnums::ArtifactType artifact = implib + ? cmStateEnums::ImportLibraryArtifact + : cmStateEnums::RuntimeBinaryArtifact; // Pass the full path to the target file. - std::string lib = tgt->GetFullPath(config, implib, true); + std::string lib = tgt->GetFullPath(config, artifact, true); if (!this->LinkDependsNoShared || tgt->GetType() != cmStateEnums::SHARED_LIBRARY) { this->Depends.push_back(lib); @@ -689,7 +698,10 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item, // linked will be able to find it. std::string lib; if (tgt) { - lib = tgt->GetFullPath(this->Config, this->UseImportLibrary); + cmStateEnums::ArtifactType artifact = this->UseImportLibrary + ? cmStateEnums::ImportLibraryArtifact + : cmStateEnums::RuntimeBinaryArtifact; + lib = tgt->GetFullPath(this->Config, artifact); this->AddLibraryRuntimeInfo(lib, tgt); } else { lib = item; @@ -1021,8 +1033,8 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item) // See documentation of CMP0008. std::string generator = this->GlobalGenerator->GetName(); if (this->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW && - (generator.find("Visual Studio") != generator.npos || - generator.find("Xcode") != generator.npos)) { + (generator.find("Visual Studio") != std::string::npos || + generator.find("Xcode") != std::string::npos)) { std::string file = cmSystemTools::GetFilenameName(item); if (!this->ExtractAnyLibraryName.find(file.c_str())) { this->HandleBadFullItem(item, file); @@ -1725,7 +1737,13 @@ void cmComputeLinkInformation::GetRPath(std::vector& runtimeDirs, } } if (use_build_rpath || use_link_rpath) { - std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + std::string rootPath; + if (const char* sysrootLink = + this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { + rootPath = sysrootLink; + } else { + rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + } const char* stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); const char* installPrefix = diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 3d26ea797..00e3ad265 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -3,9 +3,9 @@ #ifndef cmComputeLinkInformation_h #define cmComputeLinkInformation_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep -#include +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -36,12 +36,6 @@ public: , Target(CM_NULLPTR) { } - Item(Item const& item) - : Value(item.Value) - , IsPath(item.IsPath) - , Target(item.Target) - { - } Item(std::string const& v, bool p, cmGeneratorTarget const* target = CM_NULLPTR) : Value(v) diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index cfebda2b7..ff19eac63 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -238,7 +238,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Don't emit the same library twice for this target. if (emitted.insert(*lib).second) { this->AddTargetDepend(depender_index, *lib, true); - this->AddInterfaceDepends(depender_index, *lib, emitted); + this->AddInterfaceDepends(depender_index, *lib, *it, emitted); } } } @@ -273,7 +273,7 @@ void cmComputeTargetDepends::AddInterfaceDepends( // Don't emit the same library twice for this target. if (emitted.insert(*lib).second) { this->AddTargetDepend(depender_index, *lib, true); - this->AddInterfaceDepends(depender_index, *lib, emitted); + this->AddInterfaceDepends(depender_index, *lib, config, emitted); } } } @@ -281,7 +281,7 @@ void cmComputeTargetDepends::AddInterfaceDepends( void cmComputeTargetDepends::AddInterfaceDepends( int depender_index, cmLinkItem const& dependee_name, - std::set& emitted) + const std::string& config, std::set& emitted) { cmGeneratorTarget const* depender = this->Targets[depender_index]; cmGeneratorTarget const* dependee = dependee_name.Target; @@ -294,15 +294,9 @@ void cmComputeTargetDepends::AddInterfaceDepends( } if (dependee) { - this->AddInterfaceDepends(depender_index, dependee, "", emitted); - std::vector configs; - depender->Makefile->GetConfigurations(configs); - for (std::vector::const_iterator it = configs.begin(); - it != configs.end(); ++it) { - // A target should not depend on itself. - emitted.insert(depender->GetName()); - this->AddInterfaceDepends(depender_index, dependee, *it, emitted); - } + // A target should not depend on itself. + emitted.insert(depender->GetName()); + this->AddInterfaceDepends(depender_index, dependee, config, emitted); } } diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 2b6591f65..e93e376ce 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -3,7 +3,7 @@ #ifndef cmComputeTargetDepends_h #define cmComputeTargetDepends_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmGraphAdjacencyList.h" @@ -50,6 +50,7 @@ private: bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, + const std::string& config, std::set& emitted); void AddInterfaceDepends(int depender_index, cmGeneratorTarget const* dependee, diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index f2eb6019b..2bacf7321 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmConditionEvaluator.h" +#include "cmConfigure.h" +#include "cmsys/RegularExpression.hxx" #include -#include -#include #include #include #include @@ -285,12 +285,12 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( bool oldResult = this->GetBooleanValueOld(newArg, oneArg); if (newResult != oldResult) { switch (this->Policy12Status) { - case cmPolicies::WARN: { + case cmPolicies::WARN: errorString = "An argument named \"" + newArg.GetValue() + "\" appears in a conditional statement. " + cmPolicies::GetPolicyWarning(cmPolicies::CMP0012); status = cmake::AUTHOR_WARNING; - } + CM_FALLTHROUGH; case cmPolicies::OLD: return oldResult; case cmPolicies::REQUIRED_IF_USED: diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index 5815177d5..50f4edc4f 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -3,7 +3,7 @@ #ifndef cmConditionEvaluator_h #define cmConditionEvaluator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index 26f1df249..524fdf808 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -3,7 +3,7 @@ #ifndef cmConfigure_h #define cmConfigure_h -#include // IWYU pragma: keep +#include "cmsys/Configure.hxx" // IWYU pragma: export #ifdef _MSC_VER #pragma warning(disable : 4786) @@ -21,6 +21,10 @@ #cmakedefine CMAKE_USE_MACH_PARSER #cmakedefine CMAKE_USE_LIBUV #cmakedefine CMake_HAVE_CXX_AUTO_PTR +#cmakedefine CMake_HAVE_CXX_EQ_DELETE +#cmakedefine CMake_HAVE_CXX_FALLTHROUGH +#cmakedefine CMake_HAVE_CXX_GNU_FALLTHROUGH +#cmakedefine CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH #cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE #cmakedefine CMake_HAVE_CXX_NULLPTR #cmakedefine CMake_HAVE_CXX_OVERRIDE @@ -30,6 +34,22 @@ #define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@" #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@" +#ifdef CMake_HAVE_CXX_EQ_DELETE +#define CM_EQ_DELETE = delete +#else +#define CM_EQ_DELETE +#endif + +#if defined(CMake_HAVE_CXX_FALLTHROUGH) +#define CM_FALLTHROUGH [[fallthrough]] +#elif defined(CMake_HAVE_CXX_GNU_FALLTHROUGH) +#define CM_FALLTHROUGH [[gnu::fallthrough]] +elif defined(CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH) +#define CM_FALLTHROUGH __attribute__((fallthrough)) +#else +#define CM_FALLTHROUGH +#endif + #ifdef CMake_HAVE_CXX_NULLPTR #define CM_NULLPTR nullptr #else @@ -42,4 +62,8 @@ #define CM_OVERRIDE #endif +#define CM_DISABLE_COPY(Class) \ + Class(Class const&) CM_EQ_DELETE; \ + Class& operator=(Class const&) CM_EQ_DELETE; + #endif diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index b9c75497a..18005f27c 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -19,7 +19,7 @@ bool cmConfigureFileCommand::InitialPass(std::vector const& args, return false; } - const char* inFile = args[0].c_str(); + std::string const& inFile = args[0]; if (!cmSystemTools::FileIsFullPath(inFile)) { this->InputFile = this->Makefile->GetCurrentSourceDirectory(); this->InputFile += "/"; @@ -38,7 +38,7 @@ bool cmConfigureFileCommand::InitialPass(std::vector const& args, return false; } - const char* outFile = args[1].c_str(); + std::string const& outFile = args[1]; if (!cmSystemTools::FileIsFullPath(outFile)) { this->OutputFile = this->Makefile->GetCurrentBinaryDirectory(); this->OutputFile += "/"; diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h index e558b85ff..6cebbd258 100644 --- a/Source/cmConfigureFileCommand.h +++ b/Source/cmConfigureFileCommand.h @@ -3,7 +3,8 @@ #ifndef cmConfigureFileCommand_h #define cmConfigureFileCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -24,16 +25,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "configure_file"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - private: int ConfigureFile(); diff --git a/Source/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx index 53d035db8..2298a05c5 100644 --- a/Source/cmContinueCommand.cxx +++ b/Source/cmContinueCommand.cxx @@ -19,7 +19,7 @@ bool cmContinueCommand::InitialPass(std::vector const& args, return true; } - status.SetContinueInvoked(true); + status.SetContinueInvoked(); if (!args.empty()) { this->Makefile->IssueMessage(cmake::FATAL_ERROR, diff --git a/Source/cmContinueCommand.h b/Source/cmContinueCommand.h index c5b891937..92bc68e85 100644 --- a/Source/cmContinueCommand.h +++ b/Source/cmContinueCommand.h @@ -3,7 +3,8 @@ #ifndef cmContinueCommand_h #define cmContinueCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "continue"; } }; #endif diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index ff9ffc04e..9a4abf3ca 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -2,12 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCoreTryCompile.h" -#include -#include +#include "cmConfigure.h" +#include "cmsys/Directory.hxx" #include #include #include #include +#include #include "cmAlgorithms.h" #include "cmExportTryCompileFileGenerator.h" @@ -40,6 +41,8 @@ static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT"; static std::string const kCMAKE_POSITION_INDEPENDENT_CODE = "CMAKE_POSITION_INDEPENDENT_CODE"; static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT"; +static std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE"; +static std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK"; static std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES = "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES"; static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = @@ -216,6 +219,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, if (tgt->IsExecutableWithExports()) { break; } + CM_FALLTHROUGH; default: this->Makefile->IssueMessage( cmake::FATAL_ERROR, @@ -513,6 +517,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, this->Makefile->IssueMessage( cmake::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0066)); + CM_FALLTHROUGH; case cmPolicies::NEW: { // NEW behavior is to pass config-specific compiler flags. static std::string const cfgDefault = "DEBUG"; @@ -550,6 +555,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, this->Makefile->IssueMessage( cmake::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056)); + CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior is to pass linker flags. { @@ -608,6 +614,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, vars.insert(kCMAKE_OSX_SYSROOT); vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE); vars.insert(kCMAKE_SYSROOT); + vars.insert(kCMAKE_SYSROOT_COMPILE); + vars.insert(kCMAKE_SYSROOT_LINK); vars.insert(kCMAKE_WARN_DEPRECATED); if (const char* varListStr = this->Makefile->GetDefinition( @@ -667,7 +675,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, fprintf(fout, " \"%s\"", si->c_str()); // Add dependencies on any non-temporary sources. - if (si->find("CMakeTmp") == si->npos) { + if (si->find("CMakeTmp") == std::string::npos) { this->Makefile->AddCMakeDependFile(*si); } } @@ -688,6 +696,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv, case cmPolicies::WARN: warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled( "CMAKE_POLICY_WARNING_CMP0067"); + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to not honor the language standard variables. honorStandard = false; diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index 4b96aedbf..365154dfb 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -3,7 +3,7 @@ #ifndef cmCoreTryCompile_h #define cmCoreTryCompile_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmCreateTestSourceList.h b/Source/cmCreateTestSourceList.h index 5e003cfc1..f1f1e4b8a 100644 --- a/Source/cmCreateTestSourceList.h +++ b/Source/cmCreateTestSourceList.h @@ -3,7 +3,7 @@ #ifndef cmCreateTestSourceList_h #define cmCreateTestSourceList_h -#include +#include "cmConfigure.h" #include #include @@ -31,11 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "create_test_sourcelist"; } }; #endif diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index d5807b179..7995b2cb3 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCryptoHash.h" -#include -#include -#include +#include "cm_kwiml.h" +#include "cm_rhash.h" +#include "cmsys/FStream.hxx" #include static unsigned int const cmCryptoHashAlgoToId[] = { diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index 0b562da8d..c380d85ff 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -3,7 +3,7 @@ #ifndef cmCryptoHash_h #define cmCryptoHash_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include #include @@ -16,6 +16,8 @@ */ class cmCryptoHash { + CM_DISABLE_COPY(cmCryptoHash) + public: enum Algo { diff --git a/Source/cmCurl.h b/Source/cmCurl.h index 60ab9fe20..a2fa4b1c0 100644 --- a/Source/cmCurl.h +++ b/Source/cmCurl.h @@ -3,9 +3,9 @@ #ifndef cmCurl_h #define cmCurl_h -#include +#include "cmConfigure.h" -#include +#include "cm_curl.h" #include std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = CM_NULLPTR); diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx index 050de17bf..5e377b574 100644 --- a/Source/cmCustomCommand.cxx +++ b/Source/cmCustomCommand.cxx @@ -4,7 +4,7 @@ #include "cmMakefile.h" -#include +#include "cmConfigure.h" cmCustomCommand::cmCustomCommand() : Backtrace() diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h index 73d53ff16..9e82f2505 100644 --- a/Source/cmCustomCommand.h +++ b/Source/cmCustomCommand.h @@ -3,7 +3,7 @@ #ifndef cmCustomCommand_h #define cmCustomCommand_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmCustomCommandLines.h" #include "cmListFileCache.h" diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 8f4ff4b2f..67213ecaa 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -13,7 +13,7 @@ #include "cmSystemTools.h" #include "cm_auto_ptr.hxx" -#include +#include "cmConfigure.h" cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, const std::string& config, diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 286aaf332..0a2adb524 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -3,8 +3,8 @@ #ifndef cmCustomCommandGenerator_h #define cmCustomCommandGenerator_h +#include "cmConfigure.h" // IWYU pragma: keep #include "cmCustomCommandLines.h" -#include // IWYU pragma: keep #include #include diff --git a/Source/cmCustomCommandLines.h b/Source/cmCustomCommandLines.h index 87ed4e80a..36838f23f 100644 --- a/Source/cmCustomCommandLines.h +++ b/Source/cmCustomCommandLines.h @@ -3,7 +3,7 @@ #ifndef cmCustomCommandLines_h #define cmCustomCommandLines_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx index 9a097f3d8..86a83dabe 100644 --- a/Source/cmDefinePropertyCommand.cxx +++ b/Source/cmDefinePropertyCommand.cxx @@ -20,23 +20,25 @@ bool cmDefinePropertyCommand::InitialPass(std::vector const& args, // Get the scope in which to define the property. cmProperty::ScopeType scope; - if (args[0] == "GLOBAL") { + std::string const& scope_arg = args[0]; + + if (scope_arg == "GLOBAL") { scope = cmProperty::GLOBAL; - } else if (args[0] == "DIRECTORY") { + } else if (scope_arg == "DIRECTORY") { scope = cmProperty::DIRECTORY; - } else if (args[0] == "TARGET") { + } else if (scope_arg == "TARGET") { scope = cmProperty::TARGET; - } else if (args[0] == "SOURCE") { + } else if (scope_arg == "SOURCE") { scope = cmProperty::SOURCE_FILE; - } else if (args[0] == "TEST") { + } else if (scope_arg == "TEST") { scope = cmProperty::TEST; - } else if (args[0] == "VARIABLE") { + } else if (scope_arg == "VARIABLE") { scope = cmProperty::VARIABLE; - } else if (args[0] == "CACHED_VARIABLE") { + } else if (scope_arg == "CACHED_VARIABLE") { scope = cmProperty::CACHED_VARIABLE; } else { std::ostringstream e; - e << "given invalid scope " << args[0] << ". " + e << "given invalid scope " << scope_arg << ". " << "Valid scopes are " << "GLOBAL, DIRECTORY, TARGET, SOURCE, " << "TEST, VARIABLE, CACHED_VARIABLE."; diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h index 02e5b883f..bc120c564 100644 --- a/Source/cmDefinePropertyCommand.h +++ b/Source/cmDefinePropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmDefinesPropertyCommand_h #define cmDefinesPropertyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -23,11 +24,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "define_property"; } - private: std::string PropertyName; std::string BriefDocs; diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index 47fe76a6b..7aa7641e1 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDefinitions.h" +#include "cmConfigure.h" #include -#include #include #include diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index ad406653d..ddb89188c 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -3,7 +3,7 @@ #ifndef cmDefinitions_h #define cmDefinitions_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -65,12 +65,6 @@ private: , Used(false) { } - Def(Def const& d) - : std_string(d) - , Exists(d.Exists) - , Used(d.Used) - { - } bool Exists; bool Used; }; diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index c189419de..c898d12ba 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -7,8 +7,9 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cmWorkingDirectory.h" -#include +#include "cmsys/FStream.hxx" #include #include #include @@ -75,13 +76,7 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile, std::map& validDeps) { // Dependency checks must be done in proper working directory. - std::string oldcwd = "."; - if (this->CompileDirectory != ".") { - // Get the CWD but do not call CollapseFullPath because - // we only need it to cd back, and the form does not matter - oldcwd = cmSystemTools::GetCurrentWorkingDirectory(false); - cmSystemTools::ChangeDirectory(this->CompileDirectory); - } + cmWorkingDirectory workdir(this->CompileDirectory); // Check whether dependencies must be regenerated. bool okay = true; @@ -93,11 +88,6 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile, okay = false; } - // Restore working directory. - if (oldcwd != ".") { - cmSystemTools::ChangeDirectory(oldcwd); - } - return okay; } diff --git a/Source/cmDepends.h b/Source/cmDepends.h index f677f802d..b33feb902 100644 --- a/Source/cmDepends.h +++ b/Source/cmDepends.h @@ -3,7 +3,7 @@ #ifndef cmDepends_h #define cmDepends_h -#include +#include "cmConfigure.h" #include #include @@ -24,6 +24,8 @@ class cmLocalGenerator; */ class cmDepends { + CM_DISABLE_COPY(cmDepends) + public: /** Instances need to know the build directory name and the relative path from the build directory to the target file. */ @@ -116,10 +118,6 @@ protected: std::vector IncludePath; void SetIncludePathFromLanguage(const std::string& lang); - -private: - cmDepends(cmDepends const&); // Purposely not implemented. - void operator=(cmDepends const&); // Purposely not implemented. }; #endif diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 9d4b9cc10..2c464cc9c 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDependsC.h" -#include +#include "cmsys/FStream.hxx" #include #include "cmAlgorithms.h" @@ -449,11 +449,11 @@ void cmDependsC::ParseTransform(std::string const& xform) // A transform rule is of the form SOME_MACRO(%)=value-with-% // We can simply separate with "(%)=". std::string::size_type pos = xform.find("(%)="); - if (pos == xform.npos || pos == 0) { + if (pos == std::string::npos || pos == 0) { return; } std::string name = xform.substr(0, pos); - std::string value = xform.substr(pos + 4, xform.npos); + std::string value = xform.substr(pos + 4); this->TransformRules[name] = value; } diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index 3b5eb62df..250d40f8a 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -3,11 +3,11 @@ #ifndef cmDependsC_h #define cmDependsC_h -#include +#include "cmConfigure.h" #include "cmDepends.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -22,6 +22,8 @@ class cmLocalGenerator; */ class cmDependsC : public cmDepends { + CM_DISABLE_COPY(cmDependsC) + public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ @@ -93,10 +95,6 @@ protected: void WriteCacheFile() const; void ReadCacheFile(); - -private: - cmDependsC(cmDependsC const&); // Purposely not implemented. - void operator=(cmDependsC const&); // Purposely not implemented. }; #endif diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 7927402af..8b05fab49 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDependsFortran.h" +#include "cmsys/FStream.hxx" #include -#include #include #include #include diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 90b82d44e..ec208af3a 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -3,7 +3,8 @@ #ifndef cmFortran_h #define cmFortran_h -#include +#include "cmConfigure.h" + #include #include #include @@ -20,6 +21,8 @@ class cmLocalGenerator; */ class cmDependsFortran : public cmDepends { + CM_DISABLE_COPY(cmDependsFortran) + public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ @@ -76,9 +79,6 @@ protected: cmDependsFortranInternals* Internal; private: - cmDependsFortran(cmDependsFortran const&); // Purposely not implemented. - void operator=(cmDependsFortran const&); // Purposely not implemented. - std::string MaybeConvertToRelativePath(std::string const& base, std::string const& path); }; diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h index 1b9cca58f..a07bf0979 100644 --- a/Source/cmDependsJava.h +++ b/Source/cmDependsJava.h @@ -3,7 +3,7 @@ #ifndef cmDependsJava_h #define cmDependsJava_h -#include +#include "cmConfigure.h" #include "cmDepends.h" @@ -17,6 +17,8 @@ */ class cmDependsJava : public cmDepends { + CM_DISABLE_COPY(cmDependsJava) + public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ @@ -33,10 +35,6 @@ protected: bool CheckDependencies( std::istream& internalDepends, const char* internalDependsFileName, std::map& validDeps) CM_OVERRIDE; - -private: - cmDependsJava(cmDependsJava const&); // Purposely not implemented. - void operator=(cmDependsJava const&); // Purposely not implemented. }; #endif diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx index f5998ef44..7bc91bfd4 100644 --- a/Source/cmDependsJavaParserHelper.cxx +++ b/Source/cmDependsJavaParserHelper.cxx @@ -2,12 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDependsJavaParserHelper.h" -#include +#include "cmConfigure.h" #include "cmDependsJavaLexer.h" #include "cmSystemTools.h" -#include +#include "cmsys/FStream.hxx" #include #include #include diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h index 71b939ce6..0b445d924 100644 --- a/Source/cmDependsJavaParserHelper.h +++ b/Source/cmDependsJavaParserHelper.h @@ -3,31 +3,23 @@ #ifndef cmDependsJavaParserHelper_h #define cmDependsJavaParserHelper_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include -class cmDependsJavaParserHelper; - -#define YYSTYPE cmDependsJavaParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmDependsJavaParserHelper* -#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - /** \class cmDependsJavaParserHelper * \brief Helper class for parsing java source files * * Finds dependencies for java file and list of outputs */ - class cmDependsJavaParserHelper { public: - typedef struct + struct ParserType { char* str; - } ParserType; + }; cmDependsJavaParserHelper(); ~cmDependsJavaParserHelper(); @@ -96,4 +88,9 @@ private: void CleanupParser(); }; +#define YYSTYPE cmDependsJavaParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmDependsJavaParserHelper* +#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif diff --git a/Source/cmDependsJavaParserTokens.h b/Source/cmDependsJavaParserTokens.h deleted file mode 100644 index c7a414f07..000000000 --- a/Source/cmDependsJavaParserTokens.h +++ /dev/null @@ -1,254 +0,0 @@ -/* A Bison parser, made by GNU Bison 1.875d. */ - -/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, - 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - 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 -#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 - - - - -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - - - - - diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx new file mode 100644 index 000000000..ce1965d30 --- /dev/null +++ b/Source/cmDisallowedCommand.cxx @@ -0,0 +1,31 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmDisallowedCommand.h" + +#include "cmMakefile.h" +#include "cmake.h" + +class cmExecutionStatus; + +bool cmDisallowedCommand::InitialPass(std::vector const& args, + cmExecutionStatus& status) +{ + switch (this->Makefile->GetPolicyStatus(this->Policy)) { + case cmPolicies::WARN: + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(this->Policy)); + break; + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message); + return true; + } + + this->Command->SetMakefile(this->GetMakefile()); + bool const ret = this->Command->InitialPass(args, status); + this->SetError(this->Command->GetError()); + return ret; +} diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h new file mode 100644 index 000000000..0030116b8 --- /dev/null +++ b/Source/cmDisallowedCommand.h @@ -0,0 +1,51 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmDisallowedCommand_h +#define cmDisallowedCommand_h + +#include "cmConfigure.h" + +#include +#include + +#include "cmCommand.h" +#include "cmPolicies.h" + +class cmExecutionStatus; + +class cmDisallowedCommand : public cmCommand +{ +public: + cmDisallowedCommand(cmCommand* command, cmPolicies::PolicyID policy, + const char* message) + : Command(command) + , Policy(policy) + , Message(message) + { + } + + ~cmDisallowedCommand() CM_OVERRIDE { delete this->Command; } + + cmCommand* Clone() CM_OVERRIDE + { + return new cmDisallowedCommand(this->Command->Clone(), this->Policy, + this->Message); + } + + bool InitialPass(std::vector const& args, + cmExecutionStatus& status) CM_OVERRIDE; + + void FinalPass() CM_OVERRIDE { this->Command->FinalPass(); } + + bool HasFinalPass() const CM_OVERRIDE + { + return this->Command->HasFinalPass(); + } + +private: + cmCommand* Command; + cmPolicies::PolicyID Policy; + const char* Message; +}; + +#endif diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index cb24adf85..c6286b35a 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -9,9 +9,9 @@ #include "cmSystemTools.h" #include "cmVersion.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" #include -#include -#include #include #include #include @@ -129,28 +129,19 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os) this->CurrentArgument = i->Argument; // If a file name was given, use it. Otherwise, default to the // given stream. - cmsys::ofstream* fout = CM_NULLPTR; + cmsys::ofstream fout; std::ostream* s = &os; if (!i->Filename.empty()) { - fout = new cmsys::ofstream(i->Filename.c_str()); - if (fout) { - s = fout; - } else { - result = false; - } + fout.open(i->Filename.c_str()); + s = &fout; } else if (++count > 1) { os << "\n\n"; } // Print this documentation type to the stream. - if (!this->PrintDocumentation(i->HelpType, *s) || !*s) { + if (!this->PrintDocumentation(i->HelpType, *s) || s->fail()) { result = false; } - - // Close the file if we wrote one. - if (fout) { - delete fout; - } } return result; } diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 66afd2cc6..2866fef03 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -3,7 +3,7 @@ #ifndef _cmDocumentation_h #define _cmDocumentation_h -#include +#include "cmConfigure.h" #include "cmDocumentationFormatter.h" diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h index 1ccb82db3..ea43b88c3 100644 --- a/Source/cmDocumentationEntry.h +++ b/Source/cmDocumentationEntry.h @@ -3,7 +3,7 @@ #ifndef cmDocumentationEntry_h #define cmDocumentationEntry_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h index ffa80f113..1f04250c9 100644 --- a/Source/cmDocumentationFormatter.h +++ b/Source/cmDocumentationFormatter.h @@ -3,7 +3,7 @@ #ifndef _cmDocumentationFormatter_h #define _cmDocumentationFormatter_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h index c1eb5c8ea..d9e8187f8 100644 --- a/Source/cmDocumentationSection.h +++ b/Source/cmDocumentationSection.h @@ -3,7 +3,7 @@ #ifndef _cmDocumentationSection_h #define _cmDocumentationSection_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmDocumentationEntry.h" diff --git a/Source/cmDynamicLoader.cxx b/Source/cmDynamicLoader.cxx index a30b6423c..7fbe75c7b 100644 --- a/Source/cmDynamicLoader.cxx +++ b/Source/cmDynamicLoader.cxx @@ -2,9 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDynamicLoader.h" -#include - -#include #include #include #include @@ -13,8 +10,7 @@ class cmDynamicLoaderCache { public: ~cmDynamicLoaderCache(); - void CacheFile(const char* path, - const cmsys::DynamicLoader::LibraryHandle& /*p*/); + void CacheFile(const char* path, cmsys::DynamicLoader::LibraryHandle /*p*/); bool GetCacheFile(const char* path, cmsys::DynamicLoader::LibraryHandle& /*p*/); bool FlushCache(const char* path); @@ -32,8 +28,8 @@ cmDynamicLoaderCache::~cmDynamicLoaderCache() { } -void cmDynamicLoaderCache::CacheFile( - const char* path, const cmsys::DynamicLoader::LibraryHandle& p) +void cmDynamicLoaderCache::CacheFile(const char* path, + cmsys::DynamicLoader::LibraryHandle p) { cmsys::DynamicLoader::LibraryHandle h; if (this->GetCacheFile(path, h)) { diff --git a/Source/cmDynamicLoader.h b/Source/cmDynamicLoader.h index d14f81e0b..7c46dd5d4 100644 --- a/Source/cmDynamicLoader.h +++ b/Source/cmDynamicLoader.h @@ -8,12 +8,14 @@ #ifndef cmDynamicLoader_h #define cmDynamicLoader_h -#include // IWYU pragma: keep +#include "cmConfigure.h" -#include +#include "cmsys/DynamicLoader.hxx" // IWYU pragma: export class cmDynamicLoader { + CM_DISABLE_COPY(cmDynamicLoader) + public: // Description: // Load a dynamic library into the current process. @@ -28,10 +30,6 @@ public: protected: cmDynamicLoader() {} ~cmDynamicLoader() {} - -private: - cmDynamicLoader(const cmDynamicLoader&); // Not implemented. - void operator=(const cmDynamicLoader&); // Not implemented. }; #endif diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 0655da964..fc97bf3b3 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmELF.h" -#include -#include -#include +#include "cm_auto_ptr.hxx" +#include "cm_kwiml.h" +#include "cmsys/FStream.hxx" #include #include #include @@ -44,23 +44,26 @@ typedef struct Elf32_Rela Elf32_Rela; #ifdef _SCO_DS #include // For DT_SONAME etc. #endif +#ifndef DT_RUNPATH +#define DT_RUNPATH 29 +#endif // Low-level byte swapping implementation. template struct cmELFByteSwapSize { }; -void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> const& /*unused*/) +void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> /*unused*/) { } -void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const& /*unused*/) +void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/) { char one_byte; one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; } -void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const& /*unused*/) +void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/) { char one_byte; one_byte = data[0]; @@ -70,7 +73,7 @@ void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const& /*unused*/) data[1] = data[2]; data[2] = one_byte; } -void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const& /*unused*/) +void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/) { char one_byte; one_byte = data[0]; @@ -154,11 +157,7 @@ public: // Lookup the RUNPATH in the DYNAMIC section. StringEntry const* GetRunPath() { -#if defined(DT_RUNPATH) return this->GetDynamicSectionString(DT_RUNPATH); -#else - return 0; -#endif } // Return the recorded ELF type. diff --git a/Source/cmELF.h b/Source/cmELF.h index 763a24030..a6e407fe1 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -3,7 +3,7 @@ #ifndef cmELF_h #define cmELF_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h index bafb79e83..33c1c22bf 100644 --- a/Source/cmEnableLanguageCommand.h +++ b/Source/cmEnableLanguageCommand.h @@ -3,7 +3,8 @@ #ifndef cmEnableLanguageCommand_h #define cmEnableLanguageCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -33,11 +34,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "enable_language"; } }; #endif diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h index 67cd237bb..e24966221 100644 --- a/Source/cmEnableTestingCommand.h +++ b/Source/cmEnableTestingCommand.h @@ -3,7 +3,8 @@ #ifndef cmEnableTestingCommand_h #define cmEnableTestingCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -38,11 +39,6 @@ public: */ bool InitialPass(std::vector const&, cmExecutionStatus&) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "enable_testing"; } }; #endif diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index 6a7292d6c..fcc3c45c6 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExecProgramCommand.h" -#include +#include "cmsys/Process.h" #include #include "cmMakefile.h" diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h index 58e948e55..6463c4db5 100644 --- a/Source/cmExecProgramCommand.h +++ b/Source/cmExecProgramCommand.h @@ -3,7 +3,8 @@ #ifndef cmExecProgramCommand_h #define cmExecProgramCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -35,16 +36,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "exec_program"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - private: static bool RunCommand(const char* command, std::string& output, int& retVal, const char* directory = CM_NULLPTR, diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 92cdf647d..8c10dbe29 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExecuteProcessCommand.h" -#include +#include "cmsys/Process.h" #include /* isspace */ #include #include diff --git a/Source/cmExecuteProcessCommand.h b/Source/cmExecuteProcessCommand.h index 9ce4338c6..08fde0adc 100644 --- a/Source/cmExecuteProcessCommand.h +++ b/Source/cmExecuteProcessCommand.h @@ -3,7 +3,8 @@ #ifndef cmExecuteProcessCommand_h #define cmExecuteProcessCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,16 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "execute_process"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } }; #endif diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h index fd3c416af..ac5fe1d72 100644 --- a/Source/cmExecutionStatus.h +++ b/Source/cmExecutionStatus.h @@ -11,16 +11,13 @@ class cmExecutionStatus { public: - cmExecutionStatus() { this->Clear(); } - - void SetReturnInvoked(bool val) { this->ReturnInvoked = val; } - bool GetReturnInvoked() { return this->ReturnInvoked; } - - void SetBreakInvoked(bool val) { this->BreakInvoked = val; } - bool GetBreakInvoked() { return this->BreakInvoked; } - - void SetContinueInvoked(bool val) { this->ContinueInvoked = val; } - bool GetContinueInvoked() { return this->ContinueInvoked; } + cmExecutionStatus() + : ReturnInvoked(false) + , BreakInvoked(false) + , ContinueInvoked(false) + , NestedError(false) + { + } void Clear() { @@ -29,8 +26,18 @@ public: this->ContinueInvoked = false; this->NestedError = false; } - void SetNestedError(bool val) { this->NestedError = val; } - bool GetNestedError() { return this->NestedError; } + + void SetReturnInvoked() { this->ReturnInvoked = true; } + bool GetReturnInvoked() const { return this->ReturnInvoked; } + + void SetBreakInvoked() { this->BreakInvoked = true; } + bool GetBreakInvoked() const { return this->BreakInvoked; } + + void SetContinueInvoked() { this->ContinueInvoked = true; } + bool GetContinueInvoked() const { return this->ContinueInvoked; } + + void SetNestedError() { this->NestedError = true; } + bool GetNestedError() const { return this->NestedError; } private: bool ReturnInvoked; diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h index 9770fe68c..fe86528db 100644 --- a/Source/cmExpandedCommandArgument.h +++ b/Source/cmExpandedCommandArgument.h @@ -3,7 +3,7 @@ #ifndef cmExpandedCommandArgument_h #define cmExpandedCommandArgument_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h index 2a5a42e76..d028ef48d 100644 --- a/Source/cmExportBuildAndroidMKGenerator.h +++ b/Source/cmExportBuildAndroidMKGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExportBuildAndroidMKGenerator_h #define cmExportBuildAndroidMKGenerator_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 0c2526897..a1c424aca 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportBuildFileGenerator.h" +#include "cmAlgorithms.h" #include "cmExportSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -21,6 +22,8 @@ #include #include +class cmSourceFile; + cmExportBuildFileGenerator::cmExportBuildFileGenerator() { this->LG = CM_NULLPTR; @@ -171,29 +174,51 @@ void cmExportBuildFileGenerator::SetImportLocationProperty( // Get the makefile in which to lookup target information. cmMakefile* mf = target->Makefile; - // Add the main target file. - { - std::string prop = "IMPORTED_LOCATION"; + if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + std::string prop = "IMPORTED_OBJECTS"; prop += suffix; - std::string value; - if (target->IsAppBundleOnApple()) { - value = target->GetFullPath(config, false); - } else { - value = target->GetFullPath(config, false, true); + + // Compute all the object files inside this target and setup + // IMPORTED_OBJECTS as a list of object files + std::vector objectSources; + target->GetObjectSources(objectSources, config); + std::string const obj_dir = target->GetObjectDirectory(config); + std::vector objects; + for (std::vector::const_iterator si = + objectSources.begin(); + si != objectSources.end(); ++si) { + const std::string& obj = target->GetObjectName(*si); + objects.push_back(obj_dir + obj); } - properties[prop] = value; - } - // Add the import library for windows DLLs. - if (target->IsDLLPlatform() && - (target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->IsExecutableWithExports()) && - mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { - std::string prop = "IMPORTED_IMPLIB"; - prop += suffix; - std::string value = target->GetFullPath(config, true); - target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); - properties[prop] = value; + // Store the property. + properties[prop] = cmJoin(objects, ";"); + } else { + // Add the main target file. + { + std::string prop = "IMPORTED_LOCATION"; + prop += suffix; + std::string value; + if (target->IsAppBundleOnApple()) { + value = + target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); + } else { + value = target->GetFullPath(config, + cmStateEnums::RuntimeBinaryArtifact, true); + } + properties[prop] = value; + } + + // Add the import library for windows DLLs. + if (target->HasImportLibrary() && + mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + std::string prop = "IMPORTED_IMPLIB"; + prop += suffix; + std::string value = + target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact); + target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); + properties[prop] = value; + } } } diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 0539b6aa4..0556983ac 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExportBuildFileGenerator_h #define cmExportBuildFileGenerator_h -#include +#include "cmConfigure.h" #include "cmExportFileGenerator.h" diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 810227689..38cd511ea 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportCommand.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include @@ -149,11 +149,15 @@ bool cmExportCommand::InitialPass(std::vector const& args, if (cmTarget* target = gg->FindTarget(*currentTarget)) { if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - std::ostringstream e; - e << "given OBJECT library \"" << *currentTarget - << "\" which may not be exported."; - this->SetError(e.str()); - return false; + std::string reason; + if (!this->Makefile->GetGlobalGenerator() + ->HasKnownObjectFileLocation(&reason)) { + std::ostringstream e; + e << "given OBJECT library \"" << *currentTarget + << "\" which may not be exported" << reason << "."; + this->SetError(e.str()); + return false; + } } if (target->GetType() == cmStateEnums::UTILITY) { this->SetError("given custom target \"" + *currentTarget + @@ -279,7 +283,6 @@ bool cmExportCommand::HandlePackage(std::vector const& args) #if defined(_WIN32) && !defined(__CYGWIN__) #include -#undef GetCurrentDirectory void cmExportCommand::ReportRegistryError(std::string const& msg, std::string const& key, long err) { diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index 99dac7df9..c47bc42b9 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -3,7 +3,8 @@ #ifndef cmExportCommand_h #define cmExportCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -35,12 +36,8 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "export"; } - private: + cmCommandArgumentsHelper Helper; cmCommandArgumentGroup ArgumentGroup; cmCAStringVector Targets; cmCAEnabler Append; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 6c21eaf40..972f4b9d1 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -17,9 +17,9 @@ #include "cmTargetExport.h" #include "cmake.h" +#include "cm_auto_ptr.hxx" +#include "cmsys/FStream.hxx" #include -#include -#include #include #include #include @@ -273,6 +273,7 @@ static bool checkInterfaceDirs(const std::string& prepro, << std::endl; target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING, s.str()); + CM_FALLTHROUGH; } case cmPolicies::OLD: shouldContinue = true; @@ -441,6 +442,11 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target, std::set& ifaceProperties, const std::string& config) { + if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + // object libraries have no link information, so nothing to compute + return; + } + cmComputeLinkInformation* info = target->GetLinkInformation(config); if (!info) { @@ -585,16 +591,17 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string::size_type pos = 0; std::string::size_type lastPos = pos; - while ((pos = input.find("$', nameStartPos); std::string::size_type commaPos = input.find(',', nameStartPos); std::string::size_type nextOpenPos = input.find("$<", nameStartPos); - if (commaPos == input.npos // Implied 'this' target - || closePos == input.npos // Imcomplete expression. - || closePos < commaPos // Implied 'this' target - || nextOpenPos < commaPos) // Non-literal + if (commaPos == std::string::npos // Implied 'this' target + || closePos == std::string::npos // Imcomplete expression. + || closePos < commaPos // Implied 'this' target + || nextOpenPos < commaPos) // Non-literal { lastPos = nameStartPos; continue; @@ -612,15 +619,15 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( std::string errorString; pos = 0; lastPos = pos; - while ((pos = input.find("$', nameStartPos); - if (endPos == input.npos) { + if (endPos == std::string::npos) { errorString = "$ expression incomplete"; break; } std::string targetName = input.substr(nameStartPos, endPos - nameStartPos); - if (targetName.find("$<") != input.npos) { + if (targetName.find("$<") != std::string::npos) { errorString = "$ requires its parameter to be a " "literal."; break; @@ -637,10 +644,10 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( pos = 0; lastPos = pos; while (errorString.empty() && - (pos = input.find("$', nameStartPos); - if (endPos == input.npos) { + if (endPos == std::string::npos) { errorString = "$ expression incomplete"; break; } @@ -927,6 +934,9 @@ void cmExportFileGenerator::GenerateImportTargetCode( case cmStateEnums::UNKNOWN_LIBRARY: os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n"; break; + case cmStateEnums::OBJECT_LIBRARY: + os << "add_library(" << targetName << " OBJECT IMPORTED)\n"; + break; case cmStateEnums::INTERFACE_LIBRARY: os << "add_library(" << targetName << " INTERFACE IMPORTED)\n"; break; diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index e7712d24d..985c8f6bc 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExportFileGenerator_h #define cmExportFileGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmGeneratorExpression.h" #include "cmVersion.h" diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h index f2f8927f7..ebef78365 100644 --- a/Source/cmExportInstallAndroidMKGenerator.h +++ b/Source/cmExportInstallAndroidMKGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExportInstallAndroidMKGenerator_h #define cmExportInstallAndroidMKGenerator_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 64ea3c8a0..664a34276 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -195,8 +195,10 @@ void cmExportInstallFileGenerator::GenerateImportPrefix(std::ostream& os) << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"; if (cmHasLiteralPrefix(absDestS.c_str(), "/lib/") || cmHasLiteralPrefix(absDestS.c_str(), "/lib64/") || + cmHasLiteralPrefix(absDestS.c_str(), "/libx32/") || cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib/") || - cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/")) { + cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/") || + cmHasLiteralPrefix(absDestS.c_str(), "/usr/libx32/")) { // Handle "/usr move" symlinks created by some Linux distros. /* clang-format off */ os << @@ -253,7 +255,8 @@ void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input) std::string::size_type pos = 0; std::string::size_type lastPos = pos; - while ((pos = input.find("$", lastPos)) != input.npos) { + while ((pos = input.find("$", lastPos)) != + std::string::npos) { std::string::size_type endPos = pos + sizeof("$") - 1; input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}"); lastPos = endPos; @@ -329,6 +332,8 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig( properties, importedLocations); this->SetImportLocationProperty(config, suffix, te->RuntimeGenerator, properties, importedLocations); + this->SetImportLocationProperty(config, suffix, te->ObjectsGenerator, + properties, importedLocations); this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator, properties, importedLocations); this->SetImportLocationProperty(config, suffix, te->BundleGenerator, @@ -395,6 +400,23 @@ void cmExportInstallFileGenerator::SetImportLocationProperty( // Store the property. properties[prop] = value; importedLocations.insert(prop); + } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) { + // Construct the property name. + std::string prop = "IMPORTED_OBJECTS"; + prop += suffix; + + // Compute all the object files inside this target and setup + // IMPORTED_OBJECTS as a list of object files + std::vector objects; + itgen->GetInstallObjectNames(config, objects); + for (std::vector::iterator i = objects.begin(); + i != objects.end(); ++i) { + *i = value + *i; + } + + // Store the property. + properties[prop] = cmJoin(objects, ";"); + importedLocations.insert(prop); } else { // Construct the property name. std::string prop = "IMPORTED_LOCATION"; diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 3c9777a23..8fa9b7f88 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExportInstallFileGenerator_h #define cmExportInstallFileGenerator_h -#include +#include "cmConfigure.h" #include "cmExportFileGenerator.h" diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index ac4f04072..69150aee4 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -2,14 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportLibraryDependenciesCommand.h" -#include +#include "cmsys/FStream.hxx" #include #include #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -23,12 +22,6 @@ class cmExecutionStatus; bool cmExportLibraryDependenciesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0033, - "The export_library_dependencies command should not be called; " - "see CMP0033.")) { - return true; - } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h index be5334962..5559af94b 100644 --- a/Source/cmExportLibraryDependenciesCommand.h +++ b/Source/cmExportLibraryDependenciesCommand.h @@ -3,7 +3,8 @@ #ifndef cmExportLibraryDependenciesCommand_h #define cmExportLibraryDependenciesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -20,10 +21,6 @@ public: } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE - { - return "export_library_dependencies"; - } void FinalPass() CM_OVERRIDE; bool HasFinalPass() const CM_OVERRIDE { return true; } diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h index 420f472d2..58ad617d4 100644 --- a/Source/cmExportSet.h +++ b/Source/cmExportSet.h @@ -3,7 +3,7 @@ #ifndef cmExportSet_h #define cmExportSet_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h index 509069289..0f71c790c 100644 --- a/Source/cmExportSetMap.h +++ b/Source/cmExportSetMap.h @@ -3,7 +3,7 @@ #ifndef cmExportSetMap_h #define cmExportSetMap_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 88a70a1b6..9671fac8f 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExportTryCompileFileGenerator_h #define cmExportTryCompileFileGenerator_h -#include +#include "cmConfigure.h" #include "cmExportFileGenerator.h" diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx index 1b49def24..c3f026a4e 100644 --- a/Source/cmExprParserHelper.cxx +++ b/Source/cmExprParserHelper.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExprParserHelper.h" -#include +#include "cmConfigure.h" #include "cmExprLexer.h" diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h index 8f00f1dd8..dcdaca967 100644 --- a/Source/cmExprParserHelper.h +++ b/Source/cmExprParserHelper.h @@ -3,28 +3,18 @@ #ifndef cmExprParserHelper_h #define cmExprParserHelper_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include -#define YYSTYPE cmExprParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmExprParserHelper* -#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -/** \class cmExprParserHelper - * \brief Helper class for parsing java source files - * - * Finds dependencies for java file and list of outputs - */ class cmExprParserHelper { public: - typedef struct + struct ParserType { int Number; - } ParserType; + }; cmExprParserHelper(); ~cmExprParserHelper(); @@ -57,4 +47,9 @@ private: std::string ErrorString; }; +#define YYSTYPE cmExprParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmExprParserHelper* +#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index c49d39b5f..6b8903790 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExternalMakefileProjectGenerator_h #define cmExternalMakefileProjectGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 2dffcaa6b..5b7b82762 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -353,7 +353,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( all_files_map_t allFiles; std::vector cFiles; - std::vector srcExts = + std::vector const& srcExts = this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions(); for (std::vector::const_iterator lg = lgs.begin(); @@ -387,7 +387,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( bool isCFile = false; std::string lang = (*si)->GetLanguage(); if (lang == "C" || lang == "CXX") { - std::string srcext = (*si)->GetExtension(); + std::string const& srcext = (*si)->GetExtension(); for (std::vector::const_iterator ext = srcExts.begin(); ext != srcExts.end(); ++ext) { @@ -398,7 +398,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( } } - std::string fullPath = (*si)->GetFullPath(); + std::string const& fullPath = (*si)->GetFullPath(); if (isCFile) { cFiles.push_back(fullPath); @@ -414,7 +414,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( } } - std::vector headerExts = + std::vector const& headerExts = this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions(); // The following loop tries to add header files matching to implementation diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h index 06aadc47c..450a9d02c 100644 --- a/Source/cmExtraCodeBlocksGenerator.h +++ b/Source/cmExtraCodeBlocksGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExtraCodeBlocksGenerator_h #define cmExtraCodeBlocksGenerator_h -#include +#include "cmConfigure.h" #include "cmExternalMakefileProjectGenerator.h" diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index fd7da181f..b478f34fa 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -13,7 +13,7 @@ #include "cmXMLWriter.h" #include "cmake.h" -#include +#include "cmsys/SystemInformation.hxx" #include #include #include @@ -141,6 +141,7 @@ std::vector cmExtraCodeLiteGenerator::CreateProjectsByTarget( case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::MODULE_LIBRARY: visualname = "lib" + visualname; + CM_FALLTHROUGH; case cmStateEnums::EXECUTABLE: xml->StartElement("Project"); xml->Attribute("Name", visualname); @@ -240,7 +241,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( bool isCFile = false; std::string lang = (*si)->GetLanguage(); if (lang == "C" || lang == "CXX") { - std::string srcext = (*si)->GetExtension(); + std::string const& srcext = (*si)->GetExtension(); for (std::vector::const_iterator ext = srcExts.begin(); ext != srcExts.end(); ++ext) { if (srcext == *ext) { @@ -349,6 +350,87 @@ void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles( } } +void cmExtraCodeLiteGenerator::CreateFoldersAndFiles( + std::set& cFiles, cmXMLWriter& xml, + const std::string& projectPath) +{ + std::vector tmp_path; + std::vector components; + size_t numOfEndEl = 0; + + for (std::set::const_iterator it = cFiles.begin(); + it != cFiles.end(); ++it) { + std::string frelapath = + cmSystemTools::RelativePath(projectPath.c_str(), it->c_str()); + cmsys::SystemTools::SplitPath(frelapath, components, false); + components.pop_back(); // erase last member -> it is file, not folder + components.erase(components.begin()); // erase "root" + + size_t sizeOfSkip = 0; + + for (size_t i = 0; i < components.size(); ++i) { + // skip relative path + if (components[i] == ".." || components[i] == ".") { + sizeOfSkip++; + continue; + } + + // same folder + if (tmp_path.size() > i - sizeOfSkip && + tmp_path[i - sizeOfSkip] == components[i]) { + continue; + } + + // delete "old" subfolders + if (tmp_path.size() > i - sizeOfSkip) { + numOfEndEl = tmp_path.size() - i + sizeOfSkip; + tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end()); + for (; numOfEndEl--;) { + xml.EndElement(); + } + } + + // add folder + xml.StartElement("VirtualDirectory"); + xml.Attribute("Name", components[i]); + tmp_path.push_back(components[i]); + } + + // delete "old" subfolders + numOfEndEl = tmp_path.size() - components.size() + sizeOfSkip; + if (numOfEndEl) { + tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end()); + for (; numOfEndEl--;) { + xml.EndElement(); + } + } + + // add file + xml.StartElement("File"); + xml.Attribute("Name", frelapath); + xml.EndElement(); + } + + // end of folders + numOfEndEl = tmp_path.size(); + for (; numOfEndEl--;) { + xml.EndElement(); + } +} + +void cmExtraCodeLiteGenerator::CreateFoldersAndFiles( + std::map& cFiles, cmXMLWriter& xml, + const std::string& projectPath) +{ + std::set s; + for (std::map::const_iterator it = + cFiles.begin(); + it != cFiles.end(); ++it) { + s.insert(it->first); + } + this->CreateFoldersAndFiles(s, xml, projectPath); +} + void cmExtraCodeLiteGenerator::CreateProjectSourceEntries( std::map& cFiles, std::set& otherFiles, cmXMLWriter* _xml, @@ -366,26 +448,12 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries( // insert all source files in the codelite project // first the C/C++ implementation files, then all others - for (std::map::const_iterator sit = - cFiles.begin(); - sit != cFiles.end(); ++sit) { - xml.StartElement("File"); - std::string fpath(sit->first); - std::string frelapath = - cmSystemTools::RelativePath(projectPath.c_str(), sit->first.c_str()); - xml.Attribute("Name", frelapath); - xml.EndElement(); - } + this->CreateFoldersAndFiles(cFiles, xml, projectPath); xml.EndElement(); // VirtualDirectory + xml.StartElement("VirtualDirectory"); xml.Attribute("Name", "include"); - for (std::set::const_iterator sit = otherFiles.begin(); - sit != otherFiles.end(); ++sit) { - xml.StartElement("File"); - xml.Attribute( - "Name", cmSystemTools::RelativePath(projectPath.c_str(), sit->c_str())); - xml.EndElement(); - } + this->CreateFoldersAndFiles(otherFiles, xml, projectPath); xml.EndElement(); // VirtualDirectory // Get the number of CPUs. We use this information for the make -jN @@ -533,9 +601,6 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile( // which may have an acompanying header, one for all other files std::string projectType; - std::vector headerExts = - this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions(); - std::map cFiles; std::set otherFiles; diff --git a/Source/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h index 773515dbf..de330988d 100644 --- a/Source/cmExtraCodeLiteGenerator.h +++ b/Source/cmExtraCodeLiteGenerator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalCodeLiteGenerator_h #define cmGlobalCodeLiteGenerator_h -#include +#include "cmConfigure.h" #include "cmExternalMakefileProjectGenerator.h" @@ -50,6 +50,10 @@ protected: const cmMakefile* mf, const std::string& projectType, const std::string& targetName); + void CreateFoldersAndFiles(std::set& cFiles, cmXMLWriter& xml, + const std::string& projectPath); + void CreateFoldersAndFiles(std::map& cFiles, + cmXMLWriter& xml, const std::string& projectPath); public: cmExtraCodeLiteGenerator(); diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index b4fc771c2..2a6ce98a7 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExtraEclipseCDT4Generator.h" +#include "cmsys/RegularExpression.hxx" #include #include -#include #include #include #include @@ -453,7 +453,7 @@ void cmExtraEclipseCDT4Generator::WriteGroups( for (std::vector::const_iterator fileIt = sFiles.begin(); fileIt != sFiles.end(); ++fileIt) { - std::string fullPath = (*fileIt)->GetFullPath(); + std::string const& fullPath = (*fileIt)->GetFullPath(); if (!cmSystemTools::FileIsDirectory(fullPath)) { std::string linkName4 = linkName3; @@ -508,7 +508,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) for (std::vector::const_iterator sfIt = files.begin(); sfIt != files.end(); sfIt++) { // Add the file to the list of sources. - std::string source = (*sfIt)->GetFullPath(); + std::string const& source = (*sfIt)->GetFullPath(); cmSourceGroup* sourceGroup = makefile->FindSourceGroup(source.c_str(), sourceGroups); sourceGroup->AssignSource(*sfIt); diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index fe7117286..1380d1867 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -3,7 +3,7 @@ #ifndef cmExtraEclipseCDT4Generator_h #define cmExtraEclipseCDT4Generator_h -#include +#include "cmConfigure.h" #include "cmExternalMakefileProjectGenerator.h" diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h index badaca94f..6b9c7af5c 100644 --- a/Source/cmExtraKateGenerator.h +++ b/Source/cmExtraKateGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExtraKateGenerator_h #define cmExtraKateGenerator_h -#include +#include "cmConfigure.h" #include "cmExternalMakefileProjectGenerator.h" diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 36ba520c6..1fd1418de 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExtraSublimeTextGenerator.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h index a860d3408..9022d3754 100644 --- a/Source/cmExtraSublimeTextGenerator.h +++ b/Source/cmExtraSublimeTextGenerator.h @@ -3,7 +3,7 @@ #ifndef cmExtraSublimeTextGenerator_h #define cmExtraSublimeTextGenerator_h -#include +#include "cmConfigure.h" #include "cmExternalMakefileProjectGenerator.h" diff --git a/Source/cmFLTKWrapUICommand.h b/Source/cmFLTKWrapUICommand.h index 835f0a7ee..d8045ab6a 100644 --- a/Source/cmFLTKWrapUICommand.h +++ b/Source/cmFLTKWrapUICommand.h @@ -3,7 +3,8 @@ #ifndef cmFLTKWrapUICommand_h #define cmFLTKWrapUICommand_h -#include +#include "cmConfigure.h" + #include #include @@ -42,11 +43,6 @@ public: void FinalPass() CM_OVERRIDE; bool HasFinalPass() const CM_OVERRIDE { return true; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "fltk_wrap_ui"; } - private: /** * List of produced files. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 91cecb359..5777fb204 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2,23 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFileCommand.h" +#include "cm_kwiml.h" +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" +#include "cmsys/String.hxx" #include #include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include - -#include -// include sys/stat.h after sys/types.h -#include +#include #include "cmAlgorithms.h" #include "cmCommandArgumentsHelper.h" @@ -35,11 +31,21 @@ #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cm_auto_ptr.hxx" +#include "cm_sys_stat.h" #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmCurl.h" #include "cmFileLockResult.h" +#include "cm_curl.h" +#endif + +#if defined(CMAKE_USE_ELF_PARSER) +#include "cmELF.h" +#endif + +#if defined(_WIN32) +#include #endif class cmSystemToolsFileTime; @@ -104,7 +110,7 @@ bool cmFileCommand::InitialPass(std::vector const& args, this->SetError("must be called with at least two arguments."); return false; } - std::string subCommand = args[0]; + std::string const& subCommand = args[0]; if (subCommand == "WRITE") { return this->HandleWriteCommand(args, false); } @@ -166,6 +172,9 @@ bool cmFileCommand::InitialPass(std::vector const& args, if (subCommand == "RPATH_REMOVE") { return this->HandleRPathRemoveCommand(args); } + if (subCommand == "READ_ELF") { + return this->HandleReadElfCommand(args); + } if (subCommand == "RELATIVE_PATH") { return this->HandleRelativePathCommand(args); } @@ -608,8 +617,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector const& args) continue; } - else if ((c >= 0x20 && c < 0x7F) || c == '\t' || - (c == '\n' && newline_consume)) { + if ((c >= 0x20 && c < 0x7F) || c == '\t' || + (c == '\n' && newline_consume)) { // This is an ASCII character that may be part of a string. // Cast added to avoid compiler warning. Cast is ok because // c is guaranteed to fit in char by the above if... @@ -1024,8 +1033,6 @@ protected: { } }; - struct MatchRule; - friend struct MatchRule; struct MatchRule { cmsys::RegularExpression Regex; @@ -1114,9 +1121,9 @@ protected: bool InstallSymlink(const char* fromFile, const char* toFile); bool InstallFile(const char* fromFile, const char* toFile, - MatchProperties const& match_properties); + MatchProperties match_properties); bool InstallDirectory(const char* source, const char* destination, - MatchProperties const& match_properties); + MatchProperties match_properties); virtual bool Install(const char* fromFile, const char* toFile); virtual std::string const& ToName(std::string const& fromName) { @@ -1144,6 +1151,7 @@ protected: bool UseGivenPermissionsDir; bool UseSourcePermissions; std::string Destination; + std::string FilesFromDir; std::vector Files; int Doing; @@ -1153,6 +1161,7 @@ protected: DoingNone, DoingError, DoingDestination, + DoingFilesFromDir, DoingFiles, DoingPattern, DoingRegex, @@ -1248,6 +1257,12 @@ bool cmFileCopier::CheckKeyword(std::string const& arg) } else { this->Doing = DoingDestination; } + } else if (arg == "FILES_FROM_DIR") { + if (this->CurrentMatchRule) { + this->NotAfterMatch(arg); + } else { + this->Doing = DoingFilesFromDir; + } } else if (arg == "PATTERN") { this->Doing = DoingPattern; } else if (arg == "REGEX") { @@ -1311,13 +1326,7 @@ bool cmFileCopier::CheckValue(std::string const& arg) { switch (this->Doing) { case DoingFiles: - if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) { - this->Files.push_back(arg); - } else { - std::string file = this->Makefile->GetCurrentSourceDirectory(); - file += "/" + arg; - this->Files.push_back(file); - } + this->Files.push_back(arg); break; case DoingDestination: if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) { @@ -1328,6 +1337,16 @@ bool cmFileCopier::CheckValue(std::string const& arg) } this->Doing = DoingNone; break; + case DoingFilesFromDir: + if (cmSystemTools::FileIsFullPath(arg.c_str())) { + this->FilesFromDir = arg; + } else { + this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory(); + this->FilesFromDir += "/" + arg; + } + cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir); + this->Doing = DoingNone; + break; case DoingPattern: { // Convert the pattern to a regular expression. Require a // leading slash and trailing end-of-string in the matched @@ -1387,17 +1406,41 @@ bool cmFileCopier::Run(std::vector const& args) return false; } - std::vector const& files = this->Files; - for (std::vector::size_type i = 0; i < files.size(); ++i) { + for (std::vector::const_iterator i = this->Files.begin(); + i != this->Files.end(); ++i) { + std::string file; + if (!i->empty() && !cmSystemTools::FileIsFullPath(*i)) { + if (!this->FilesFromDir.empty()) { + file = this->FilesFromDir; + } else { + file = this->Makefile->GetCurrentSourceDirectory(); + } + file += "/"; + file += *i; + } else if (!this->FilesFromDir.empty()) { + this->FileCommand->SetError("option FILES_FROM_DIR requires all files " + "to be specified as relative paths."); + return false; + } else { + file = *i; + } + // Split the input file into its directory and name components. std::vector fromPathComponents; - cmSystemTools::SplitPath(files[i], fromPathComponents); + cmSystemTools::SplitPath(file, fromPathComponents); std::string fromName = *(fromPathComponents.end() - 1); std::string fromDir = cmSystemTools::JoinPath( fromPathComponents.begin(), fromPathComponents.end() - 1); // Compute the full path to the destination file. std::string toFile = this->Destination; + if (!this->FilesFromDir.empty()) { + std::string dir = cmSystemTools::GetFilenamePath(*i); + if (!dir.empty()) { + toFile += "/"; + toFile += dir; + } + } std::string const& toName = this->ToName(fromName); if (!toName.empty()) { toFile += "/"; @@ -1482,6 +1525,9 @@ bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile) // Remove the destination file so we can always create the symlink. cmSystemTools::RemoveFile(toFile); + // Create destination directory if it doesn't exist + cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile)); + // Create the symlink. if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) { std::ostringstream e; @@ -1496,7 +1542,7 @@ bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile) } bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile, - MatchProperties const& match_properties) + MatchProperties match_properties) { // Determine whether we will copy the file. bool copy = true; @@ -1550,7 +1596,7 @@ bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile, bool cmFileCopier::InstallDirectory(const char* source, const char* destination, - MatchProperties const& match_properties) + MatchProperties match_properties) { // Inform the user about this directory installation. this->ReportCopy(destination, TypeDir, @@ -1724,6 +1770,7 @@ protected: if (this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE")) { break; } + CM_FALLTHROUGH; case cmInstallType_EXECUTABLE: case cmInstallType_PROGRAMS: this->FilePermissions |= mode_owner_execute; @@ -1745,6 +1792,11 @@ bool cmFileInstaller::Parse(std::vector const& args) } if (!this->Rename.empty()) { + if (!this->FilesFromDir.empty()) { + this->FileCommand->SetError("INSTALL option RENAME may not be " + "combined with FILES_FROM_DIR."); + return false; + } if (this->InstallType != cmInstallType_FILES && this->InstallType != cmInstallType_PROGRAMS) { this->FileCommand->SetError("INSTALL option RENAME may be used " @@ -2177,6 +2229,68 @@ bool cmFileCommand::HandleRPathCheckCommand( return true; } +bool cmFileCommand::HandleReadElfCommand(std::vector const& args) +{ + if (args.size() < 4) { + this->SetError("READ_ELF must be called with at least three additional " + "arguments."); + return false; + } + + cmCommandArgumentsHelper argHelper; + cmCommandArgumentGroup group; + + cmCAString readArg(&argHelper, "READ_ELF"); + cmCAString fileNameArg(&argHelper, CM_NULLPTR); + + cmCAString rpathArg(&argHelper, "RPATH", &group); + cmCAString runpathArg(&argHelper, "RUNPATH", &group); + cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group); + + readArg.Follows(CM_NULLPTR); + fileNameArg.Follows(&readArg); + group.Follows(&fileNameArg); + argHelper.Parse(&args, CM_NULLPTR); + + if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) { + std::ostringstream e; + e << "READ_ELF given FILE \"" << fileNameArg.GetString() + << "\" that does not exist."; + this->SetError(e.str()); + return false; + } + +#if defined(CMAKE_USE_ELF_PARSER) + cmELF elf(fileNameArg.GetCString()); + + if (!rpathArg.GetString().empty()) { + if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) { + std::string rpath(se_rpath->Value); + std::replace(rpath.begin(), rpath.end(), ':', ';'); + this->Makefile->AddDefinition(rpathArg.GetString(), rpath.c_str()); + } + } + if (!runpathArg.GetString().empty()) { + if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) { + std::string runpath(se_runpath->Value); + std::replace(runpath.begin(), runpath.end(), ':', ';'); + this->Makefile->AddDefinition(runpathArg.GetString(), runpath.c_str()); + } + } + + return true; +#else + std::string error = "ELF parser not available on this platform."; + if (errorArg.GetString().empty()) { + this->SetError(error); + return false; + } else { + this->Makefile->AddDefinition(errorArg.GetString(), error.c_str()); + return true; + } +#endif +} + bool cmFileCommand::HandleInstallCommand(std::vector const& args) { cmFileInstaller installer(this); @@ -2509,7 +2623,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector const& args) bool showProgress = false; std::string userpwd; - std::list curl_headers; + std::vector curl_headers; while (i != args.end()) { if (*i == "TIMEOUT") { @@ -2753,7 +2867,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector const& args) } struct curl_slist* headers = CM_NULLPTR; - for (std::list::const_iterator h = curl_headers.begin(); + for (std::vector::const_iterator h = curl_headers.begin(); h != curl_headers.end(); ++h) { headers = ::curl_slist_append(headers, h->c_str()); } @@ -2843,7 +2957,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector const& args) bool showProgress = false; std::string userpwd; - std::list curl_headers; + std::vector curl_headers; while (i != args.end()) { if (*i == "TIMEOUT") { @@ -3011,7 +3125,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector const& args) } struct curl_slist* headers = CM_NULLPTR; - for (std::list::const_iterator h = curl_headers.begin(); + for (std::vector::const_iterator h = curl_headers.begin(); h != curl_headers.end(); ++h) { headers = ::curl_slist_append(headers, h->c_str()); } diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 319864c87..d09ef42f1 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -3,7 +3,8 @@ #ifndef cmFileCommand_h #define cmFileCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "file"; } - protected: bool HandleRename(std::vector const& args); bool HandleRemove(std::vector const& args, bool recurse); @@ -53,6 +44,7 @@ protected: bool HandleRelativePathCommand(std::vector const& args); bool HandleCMakePathCommand(std::vector const& args, bool nativePath); + bool HandleReadElfCommand(std::vector const& args); bool HandleRPathChangeCommand(std::vector const& args); bool HandleRPathCheckCommand(std::vector const& args); bool HandleRPathRemoveCommand(std::vector const& args); diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h index ab3cb1fda..ccef50816 100644 --- a/Source/cmFileLock.h +++ b/Source/cmFileLock.h @@ -3,7 +3,7 @@ #ifndef cmFileLock_h #define cmFileLock_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include @@ -21,6 +21,8 @@ class cmFileLockResult; */ class cmFileLock { + CM_DISABLE_COPY(cmFileLock) + public: cmFileLock(); ~cmFileLock(); @@ -44,9 +46,6 @@ public: bool IsLocked(const std::string& filename) const; private: - cmFileLock(const cmFileLock&); - cmFileLock& operator=(const cmFileLock&); - cmFileLockResult OpenFile(); cmFileLockResult LockWithoutTimeout(); cmFileLockResult LockWithTimeout(unsigned long timeoutSec); diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h index fbe01c87e..c96a8c2f8 100644 --- a/Source/cmFileLockPool.h +++ b/Source/cmFileLockPool.h @@ -3,16 +3,18 @@ #ifndef cmFileLockPool_h #define cmFileLockPool_h -#include // IWYU pragma: keep +#include "cmConfigure.h" -#include #include +#include class cmFileLock; class cmFileLockResult; class cmFileLockPool { + CM_DISABLE_COPY(cmFileLockPool) + public: cmFileLockPool(); ~cmFileLockPool(); @@ -52,13 +54,12 @@ public: cmFileLockResult Release(const std::string& filename); private: - cmFileLockPool(const cmFileLockPool&); - cmFileLockPool& operator=(const cmFileLockPool&); - bool IsAlreadyLocked(const std::string& filename) const; class ScopePool { + CM_DISABLE_COPY(ScopePool) + public: ScopePool(); ~ScopePool(); @@ -69,17 +70,14 @@ private: bool IsAlreadyLocked(const std::string& filename) const; private: - ScopePool(const ScopePool&); - ScopePool& operator=(const ScopePool&); - - typedef std::list List; + typedef std::vector List; typedef List::iterator It; typedef List::const_iterator CIt; List Locks; }; - typedef std::list List; + typedef std::vector List; typedef List::iterator It; typedef List::const_iterator CIt; diff --git a/Source/cmFileLockResult.h b/Source/cmFileLockResult.h index 679432a13..4cedc0ae6 100644 --- a/Source/cmFileLockResult.h +++ b/Source/cmFileLockResult.h @@ -3,7 +3,7 @@ #ifndef cmFileLockResult_h #define cmFileLockResult_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx index 909be78ed..80275357c 100644 --- a/Source/cmFileMonitor.cxx +++ b/Source/cmFileMonitor.cxx @@ -2,12 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFileMonitor.h" -#include +#include "cmAlgorithms.h" +#include "cmsys/SystemTools.hxx" #include -#include -#include +#include #include +#include namespace { void on_directory_change(uv_fs_event_t* handle, const char* filename, @@ -36,12 +37,7 @@ public: class cmVirtualDirectoryWatcher : public cmIBaseWatcher { public: - ~cmVirtualDirectoryWatcher() override - { - for (auto i : this->Children) { - delete i.second; - } - } + ~cmVirtualDirectoryWatcher() override { cmDeleteAll(this->Children); } cmIBaseWatcher* Find(const std::string& ps) { @@ -102,9 +98,7 @@ public: void Reset() { - for (auto c : this->Children) { - delete c.second; - } + cmDeleteAll(this->Children); this->Children.clear(); } @@ -236,7 +230,7 @@ public: cmFileMonitor::Callback cb) : Parent(p) , PathSegment(ps) - , CbList({ cb }) + , CbList({ std::move(cb) }) { assert(p); assert(!ps.empty()); diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h index 48169b867..d7ec92a17 100644 --- a/Source/cmFileMonitor.h +++ b/Source/cmFileMonitor.h @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include "cmConfigure.h" + #include #include #include @@ -12,6 +14,8 @@ class cmRootWatcher; class cmFileMonitor { + CM_DISABLE_COPY(cmFileMonitor) + public: cmFileMonitor(uv_loop_t* l); ~cmFileMonitor(); diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx index 3d8b69534..62f52e590 100644 --- a/Source/cmFilePathChecksum.cxx +++ b/Source/cmFilePathChecksum.cxx @@ -45,7 +45,7 @@ void cmFilePathChecksum::setupParentDirs(const std::string& currentSrcDir, parentDirs[3].second = "ProjectBinary"; } -std::string cmFilePathChecksum::get(const std::string& filePath) +std::string cmFilePathChecksum::get(const std::string& filePath) const { std::string relPath; std::string relSeed; @@ -82,7 +82,7 @@ std::string cmFilePathChecksum::get(const std::string& filePath) } std::string cmFilePathChecksum::getPart(const std::string& filePath, - size_t length) + size_t length) const { return get(filePath).substr(0, length); } diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h index df19053fb..9d570eb4d 100644 --- a/Source/cmFilePathChecksum.h +++ b/Source/cmFilePathChecksum.h @@ -3,7 +3,7 @@ #ifndef cmFilePathChecksum_h #define cmFilePathChecksum_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -47,13 +47,13 @@ public: /* @brief Calculates the path checksum for the parent directory of a file * */ - std::string get(const std::string& filePath); + std::string get(const std::string& filePath) const; /* @brief Same as get() but returns only the first length characters * */ std::string getPart(const std::string& filePath, - size_t length = partLengthDefault); + size_t length = partLengthDefault) const; private: /// Size of the parent directory list diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx index 991ebb8c7..f591a8dc7 100644 --- a/Source/cmFileTimeComparison.cxx +++ b/Source/cmFileTimeComparison.cxx @@ -10,10 +10,10 @@ // Use a platform-specific API to get file times efficiently. #if !defined(_WIN32) || defined(__CYGWIN__) -#include +#include "cm_sys_stat.h" #define cmFileTimeComparison_Type struct stat #else -#include +#include "cmsys/Encoding.hxx" #include #define cmFileTimeComparison_Type FILETIME #endif diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h index 6eb150025..b1f8ed636 100644 --- a/Source/cmFileTimeComparison.h +++ b/Source/cmFileTimeComparison.h @@ -3,7 +3,7 @@ #ifndef cmFileTimeComparison_h #define cmFileTimeComparison_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep class cmFileTimeComparisonInternal; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index dce502113..e3782080c 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -2,8 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFindBase.h" -#include +#include "cmConfigure.h" +#include #include +#include #include #include @@ -158,6 +160,9 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) void cmFindBase::ExpandPaths() { if (!this->NoDefaultPath) { + if (!this->NoPackageRootPath) { + this->FillPackageRootPath(); + } if (!this->NoCMakePath) { this->FillCMakeVariablePath(); } @@ -196,6 +201,25 @@ void cmFindBase::FillCMakeEnvironmentPath() paths.AddSuffixes(this->SearchPathSuffixes); } +void cmFindBase::FillPackageRootPath() +{ + cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot]; + + // Add package specific search prefixes + // NOTE: This should be using const_reverse_iterator but HP aCC and + // Oracle sunCC both currently have standard library issues + // with the reverse iterator APIs. + for (std::deque::reverse_iterator pkg = + this->Makefile->FindPackageModuleStack.rbegin(); + pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) { + std::string varName = *pkg + "_ROOT"; + paths.AddCMakePrefixPath(varName); + paths.AddEnvPrefixPath(varName); + } + + paths.AddSuffixes(this->SearchPathSuffixes); +} + void cmFindBase::FillCMakeVariablePath() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake]; diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index 423d4533c..88b5b6c18 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -3,7 +3,7 @@ #ifndef cmFindBase_h #define cmFindBase_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -50,6 +50,7 @@ protected: private: // Add pieces of the search. + void FillPackageRootPath(); void FillCMakeVariablePath(); void FillCMakeEnvironmentPath(); void FillUserHintsPath(); diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 110195c4f..fd0e31701 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -10,6 +10,8 @@ #include "cmSystemTools.h" cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL"); +cmFindCommon::PathLabel cmFindCommon::PathLabel::PackageRoot( + "PackageName_ROOT"); cmFindCommon::PathLabel cmFindCommon::PathLabel::CMake("CMAKE"); cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeEnvironment( "CMAKE_ENVIRONMENT"); @@ -23,6 +25,7 @@ cmFindCommon::cmFindCommon() { this->FindRootPathMode = RootPathModeBoth; this->NoDefaultPath = false; + this->NoPackageRootPath = false; this->NoCMakePath = false; this->NoCMakeEnvironmentPath = false; this->NoSystemEnvironmentPath = false; @@ -57,6 +60,7 @@ void cmFindCommon::InitializeSearchPathGroups() // All search paths labels = &this->PathGroupLabelMap[PathGroup::All]; + labels->push_back(PathLabel::PackageRoot); labels->push_back(PathLabel::CMake); labels->push_back(PathLabel::CMakeEnvironment); labels->push_back(PathLabel::Hints); @@ -68,6 +72,8 @@ void cmFindCommon::InitializeSearchPathGroups() this->PathGroupOrder.push_back(PathGroup::All); // Create the idividual labeld search paths + this->LabeledPaths.insert( + std::make_pair(PathLabel::PackageRoot, cmSearchPath(this))); this->LabeledPaths.insert( std::make_pair(PathLabel::CMake, cmSearchPath(this))); this->LabeledPaths.insert( @@ -154,10 +160,16 @@ void cmFindCommon::RerootPaths(std::vector& paths) } const char* sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT"); + const char* sysrootCompile = + this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE"); + const char* sysrootLink = + this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK"); const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH"); const bool noSysroot = !sysroot || !*sysroot; + const bool noCompileSysroot = !sysrootCompile || !*sysrootCompile; + const bool noLinkSysroot = !sysrootLink || !*sysrootLink; const bool noRootPath = !rootPath || !*rootPath; - if (noSysroot && noRootPath) { + if (noSysroot && noCompileSysroot && noLinkSysroot && noRootPath) { return; } @@ -166,6 +178,12 @@ void cmFindCommon::RerootPaths(std::vector& paths) if (rootPath) { cmSystemTools::ExpandListArgument(rootPath, roots); } + if (sysrootCompile) { + roots.push_back(sysrootCompile); + } + if (sysrootLink) { + roots.push_back(sysrootLink); + } if (sysroot) { roots.push_back(sysroot); } @@ -213,18 +231,6 @@ void cmFindCommon::RerootPaths(std::vector& paths) } } -void cmFindCommon::FilterPaths(const std::vector& inPaths, - const std::set& ignore, - std::vector& outPaths) -{ - for (std::vector::const_iterator i = inPaths.begin(); - i != inPaths.end(); ++i) { - if (ignore.count(*i) == 0) { - outPaths.push_back(*i); - } - } -} - void cmFindCommon::GetIgnoredPaths(std::vector& ignore) { // null-terminated list of paths. @@ -259,10 +265,12 @@ bool cmFindCommon::CheckCommonArgument(std::string const& arg) { if (arg == "NO_DEFAULT_PATH") { this->NoDefaultPath = true; - } else if (arg == "NO_CMAKE_ENVIRONMENT_PATH") { - this->NoCMakeEnvironmentPath = true; + } else if (arg == "NO_PACKAGE_ROOT_PATH") { + this->NoPackageRootPath = true; } else if (arg == "NO_CMAKE_PATH") { this->NoCMakePath = true; + } else if (arg == "NO_CMAKE_ENVIRONMENT_PATH") { + this->NoCMakeEnvironmentPath = true; } else if (arg == "NO_SYSTEM_ENVIRONMENT_PATH") { this->NoSystemEnvironmentPath = true; } else if (arg == "NO_CMAKE_SYSTEM_PATH") { @@ -291,7 +299,7 @@ void cmFindCommon::AddPathSuffix(std::string const& arg) return; } if (suffix[0] == '/') { - suffix = suffix.substr(1, suffix.npos); + suffix = suffix.substr(1); } if (suffix.empty()) { return; @@ -334,15 +342,3 @@ void cmFindCommon::ComputeFinalPaths() std::for_each(this->SearchPaths.begin(), this->SearchPaths.end(), &AddTrailingSlash); } - -void cmFindCommon::SetMakefile(cmMakefile* makefile) -{ - cmCommand::SetMakefile(makefile); - - // If we are building for Apple (OSX or also iphone), make sure - // that frameworks and bundles are searched first. - if (this->Makefile->IsOn("APPLE")) { - this->SearchFrameworkFirst = true; - this->SearchAppBundleFirst = true; - } -} diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 4d6d569c1..79542677d 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -3,7 +3,7 @@ #ifndef cmFindCommon_h #define cmFindCommon_h -#include +#include "cmConfigure.h" #include #include @@ -14,8 +14,6 @@ #include "cmPathLabel.h" #include "cmSearchPath.h" -class cmMakefile; - /** \class cmFindCommon * \brief Base class for FIND_XXX implementations. * @@ -57,6 +55,7 @@ protected: : cmPathLabel(label) { } + static PathLabel PackageRoot; static PathLabel CMake; static PathLabel CMakeEnvironment; static PathLabel Hints; @@ -82,11 +81,6 @@ protected: void GetIgnoredPaths(std::vector& ignore); void GetIgnoredPaths(std::set& ignore); - /** Remove paths in the ignore set from the supplied vector. */ - void FilterPaths(const std::vector& inPaths, - const std::set& ignore, - std::vector& outPaths); - /** Compute final search path list (reroot + trailing slash). */ void ComputeFinalPaths(); @@ -105,9 +99,9 @@ protected: bool CheckCommonArgument(std::string const& arg); void AddPathSuffix(std::string const& arg); - void SetMakefile(cmMakefile* makefile); bool NoDefaultPath; + bool NoPackageRootPath; bool NoCMakePath; bool NoCMakeEnvironmentPath; bool NoSystemEnvironmentPath; diff --git a/Source/cmFindFileCommand.h b/Source/cmFindFileCommand.h index 5c94ebf23..bf57fecd3 100644 --- a/Source/cmFindFileCommand.h +++ b/Source/cmFindFileCommand.h @@ -3,8 +3,7 @@ #ifndef cmFindFileCommand_h #define cmFindFileCommand_h -#include -#include +#include "cmConfigure.h" #include "cmFindPathCommand.h" @@ -26,7 +25,6 @@ public: * This is a virtual constructor for the command. */ cmCommand* Clone() CM_OVERRIDE { return new cmFindFileCommand; } - std::string GetName() const CM_OVERRIDE { return "find_file"; } }; #endif diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index c86f9c181..a6b1a2155 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFindLibraryCommand.h" +#include "cmsys/RegularExpression.hxx" #include -#include #include #include #include @@ -43,20 +43,29 @@ bool cmFindLibraryCommand::InitialPass(std::vector const& argsIn, return true; } - if (this->Makefile->GetState()->GetGlobalPropertyAsBool( - "FIND_LIBRARY_USE_LIB32_PATHS")) { - // add special 32 bit paths if this is a 32 bit compile. - if (this->Makefile->PlatformIs32Bit()) { - this->AddArchitecturePaths("32"); - } + // add custom lib paths instead of using fixed lib32, lib64 or + // libx32 + if (const char* customLib = this->Makefile->GetDefinition( + "CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX")) { + this->AddArchitecturePaths(customLib); } - - if (this->Makefile->GetState()->GetGlobalPropertyAsBool( - "FIND_LIBRARY_USE_LIB64_PATHS")) { - // add special 64 bit paths if this is a 64 bit compile. - if (this->Makefile->PlatformIs64Bit()) { - this->AddArchitecturePaths("64"); - } + // add special 32 bit paths if this is a 32 bit compile. + else if (this->Makefile->PlatformIs32Bit() && + this->Makefile->GetState()->GetGlobalPropertyAsBool( + "FIND_LIBRARY_USE_LIB32_PATHS")) { + this->AddArchitecturePaths("32"); + } + // add special 64 bit paths if this is a 64 bit compile. + else if (this->Makefile->PlatformIs64Bit() && + this->Makefile->GetState()->GetGlobalPropertyAsBool( + "FIND_LIBRARY_USE_LIB64_PATHS")) { + this->AddArchitecturePaths("64"); + } + // add special 32 bit paths if this is an x32 compile. + else if (this->Makefile->PlatformIsx32() && + this->Makefile->GetState()->GetGlobalPropertyAsBool( + "FIND_LIBRARY_USE_LIBX32_PATHS")) { + this->AddArchitecturePaths("x32"); } std::string library = this->FindLibrary(); @@ -294,7 +303,7 @@ bool cmFindLibraryHelper::HasValidSuffix(std::string const& name) // Check if a valid library suffix is somewhere in the name, // this may happen e.g. for versioned shared libraries: libfoo.so.2 suffix += "."; - if (name.find(suffix) != name.npos) { + if (name.find(suffix) != std::string::npos) { return true; } } diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h index aeff62971..9d38eab33 100644 --- a/Source/cmFindLibraryCommand.h +++ b/Source/cmFindLibraryCommand.h @@ -3,7 +3,8 @@ #ifndef cmFindLibraryCommand_h #define cmFindLibraryCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -35,16 +36,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "find_library"; } - protected: void AddArchitecturePaths(const char* suffix); void AddArchitecturePath(std::string const& dir, diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 60de74f41..f291f9d44 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -2,14 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFindPackageCommand.h" +#include "cmSystemTools.h" +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" +#include "cmsys/String.h" #include #include -#include -#include -#include -#include -#include -#include +#include #include #include #include @@ -92,6 +93,7 @@ cmFindPackageCommand::cmFindPackageCommand() this->DebugMode = false; this->UseLib32Paths = false; this->UseLib64Paths = false; + this->UseLibx32Paths = false; this->PolicyScope = true; this->VersionMajor = 0; this->VersionMinor = 0; @@ -173,6 +175,13 @@ bool cmFindPackageCommand::InitialPass(std::vector const& args, this->UseLib64Paths = true; } + // Lookup whether libx32 paths should be used. + if (this->Makefile->PlatformIsx32() && + this->Makefile->GetState()->GetGlobalPropertyAsBool( + "FIND_LIBRARY_USE_LIBX32_PATHS")) { + this->UseLibx32Paths = true; + } + // Check if User Package Registry should be disabled if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) { this->NoUserRegistry = true; @@ -317,7 +326,7 @@ bool cmFindPackageCommand::InitialPass(std::vector const& args, } else if (doing == DoingPathSuffixes) { this->AddPathSuffix(args[i]); } else if (doing == DoingConfigs) { - if (args[i].find_first_of(":/\\") != args[i].npos || + if (args[i].find_first_of(":/\\") != std::string::npos || cmSystemTools::GetFilenameLastExtension(args[i]) != ".cmake") { std::ostringstream e; e << "given CONFIGS option followed by invalid file name \"" << args[i] @@ -414,13 +423,17 @@ bool cmFindPackageCommand::InitialPass(std::vector const& args, &parsed_minor, &parsed_patch, &parsed_tweak); switch (this->VersionCount) { case 4: - this->VersionTweak = parsed_tweak; // no break! + this->VersionTweak = parsed_tweak; + CM_FALLTHROUGH; case 3: - this->VersionPatch = parsed_patch; // no break! + this->VersionPatch = parsed_patch; + CM_FALLTHROUGH; case 2: - this->VersionMinor = parsed_minor; // no break! + this->VersionMinor = parsed_minor; + CM_FALLTHROUGH; case 1: - this->VersionMajor = parsed_major; // no break! + this->VersionMajor = parsed_major; + CM_FALLTHROUGH; default: break; } @@ -577,6 +590,9 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components) exact += "_FIND_VERSION_EXACT"; this->AddFindDefinition(exact, this->VersionExact ? "1" : "0"); } + + // Push on to the pacakge stack + this->Makefile->FindPackageModuleStack.push_back(this->Name); } void cmFindPackageCommand::AddFindDefinition(const std::string& var, @@ -719,104 +735,119 @@ bool cmFindPackageCommand::HandlePackageMode() } } - if (result && !found && (!this->Quiet || this->Required)) { - // The variable is not set. - std::ostringstream e; - std::ostringstream aw; - if (configFileSetFOUNDFalse) { - /* clang-format off */ - e << "Found package configuration file:\n" - " " << this->FileFound << "\n" - "but it set " << foundVar << " to FALSE so package \"" << - this->Name << "\" is considered to be NOT FOUND."; - /* clang-format on */ - if (!notFoundMessage.empty()) { - e << " Reason given by package: \n" << notFoundMessage << "\n"; - } - } - // If there are files in ConsideredConfigs, it means that FooConfig.cmake - // have been found, but they didn't have appropriate versions. - else if (!this->ConsideredConfigs.empty()) { - std::vector::const_iterator duplicate_end = - cmRemoveDuplicates(this->ConsideredConfigs); - e << "Could not find a configuration file for package \"" << this->Name - << "\" that " - << (this->VersionExact ? "exactly matches" : "is compatible with") - << " requested version \"" << this->Version << "\".\n" - << "The following configuration files were considered but not " - "accepted:\n"; - for (std::vector::const_iterator i = - this->ConsideredConfigs.begin(); - i != duplicate_end; ++i) { - e << " " << i->filename << ", version: " << i->version << "\n"; - } - } else { - std::string requestedVersionString; - if (!this->Version.empty()) { - requestedVersionString = " (requested version "; - requestedVersionString += this->Version; - requestedVersionString += ")"; + // package not found + if (result && !found) { + // warn if package required or neither quiet nor in config mode + if (this->Required || + !(this->Quiet || (this->UseConfigFiles && !this->UseFindModules && + this->ConsideredConfigs.empty()))) { + // The variable is not set. + std::ostringstream e; + std::ostringstream aw; + if (configFileSetFOUNDFalse) { + /* clang-format off */ + e << "Found package configuration file:\n" + " " << this->FileFound << "\n" + "but it set " << foundVar << " to FALSE so package \"" << + this->Name << "\" is considered to be NOT FOUND."; + /* clang-format on */ + if (!notFoundMessage.empty()) { + e << " Reason given by package: \n" << notFoundMessage << "\n"; + } } - - if (this->UseConfigFiles) { - if (this->UseFindModules) { - e << "By not providing \"Find" << this->Name - << ".cmake\" in " - "CMAKE_MODULE_PATH this project has asked CMake to find a " - "package configuration file provided by \"" - << this->Name << "\", " - "but CMake did not find one.\n"; + // If there are files in ConsideredConfigs, it means that FooConfig.cmake + // have been found, but they didn't have appropriate versions. + else if (!this->ConsideredConfigs.empty()) { + std::vector::const_iterator duplicate_end = + cmRemoveDuplicates(this->ConsideredConfigs); + e << "Could not find a configuration file for package \"" << this->Name + << "\" that " + << (this->VersionExact ? "exactly matches" : "is compatible with") + << " requested version \"" << this->Version << "\".\n" + << "The following configuration files were considered but not " + "accepted:\n"; + for (std::vector::const_iterator i = + this->ConsideredConfigs.begin(); + i != duplicate_end; ++i) { + e << " " << i->filename << ", version: " << i->version << "\n"; + } + } else { + std::string requestedVersionString; + if (!this->Version.empty()) { + requestedVersionString = " (requested version "; + requestedVersionString += this->Version; + requestedVersionString += ")"; } - if (this->Configs.size() == 1) { - e << "Could not find a package configuration file named \"" - << this->Configs[0] << "\" provided by package \"" << this->Name - << "\"" << requestedVersionString << ".\n"; - } else { - e << "Could not find a package configuration file provided by \"" - << this->Name << "\"" << requestedVersionString - << " with any of the following names:\n" - << cmWrap(" ", this->Configs, "", "\n") << "\n"; + if (this->UseConfigFiles) { + if (this->UseFindModules) { + e << "By not providing \"Find" << this->Name + << ".cmake\" in " + "CMAKE_MODULE_PATH this project has asked CMake to find a " + "package configuration file provided by \"" + << this->Name << "\", " + "but CMake did not find one.\n"; + } + + if (this->Configs.size() == 1) { + e << "Could not find a package configuration file named \"" + << this->Configs[0] << "\" provided by package \"" << this->Name + << "\"" << requestedVersionString << ".\n"; + } else { + e << "Could not find a package configuration file provided by \"" + << this->Name << "\"" << requestedVersionString + << " with any of the following names:\n" + << cmWrap(" ", this->Configs, "", "\n") << "\n"; + } + + e << "Add the installation prefix of \"" << this->Name + << "\" to " + "CMAKE_PREFIX_PATH or set \"" + << this->Variable + << "\" to a " + "directory containing one of the above files. " + "If \"" + << this->Name << "\" provides a separate development " + "package or SDK, be sure it has been installed."; + } else // if(!this->UseFindModules && !this->UseConfigFiles) + { + e << "No \"Find" << this->Name << ".cmake\" found in " + << "CMAKE_MODULE_PATH."; + + aw + << "Find" << this->Name + << ".cmake must either be part of this " + "project itself, in this case adjust CMAKE_MODULE_PATH so that " + "it points to the correct location inside its source tree.\n" + "Or it must be installed by a package which has already been " + "found via find_package(). In this case make sure that " + "package has indeed been found and adjust CMAKE_MODULE_PATH to " + "contain the location where that package has installed " + "Find" + << this->Name + << ".cmake. This must be a location " + "provided by that package. This error in general means that " + "the buildsystem of this project is relying on a Find-module " + "without ensuring that it is actually available.\n"; } + } - e << "Add the installation prefix of \"" << this->Name - << "\" to " - "CMAKE_PREFIX_PATH or set \"" - << this->Variable << "\" to a " - "directory containing one of the above files. " - "If \"" - << this->Name << "\" provides a separate development " - "package or SDK, be sure it has been installed."; - } else // if(!this->UseFindModules && !this->UseConfigFiles) - { - e << "No \"Find" << this->Name << ".cmake\" found in " - << "CMAKE_MODULE_PATH."; - - aw << "Find" << this->Name - << ".cmake must either be part of this " - "project itself, in this case adjust CMAKE_MODULE_PATH so that " - "it points to the correct location inside its source tree.\n" - "Or it must be installed by a package which has already been " - "found via find_package(). In this case make sure that " - "package has indeed been found and adjust CMAKE_MODULE_PATH to " - "contain the location where that package has installed " - "Find" - << this->Name - << ".cmake. This must be a location " - "provided by that package. This error in general means that " - "the buildsystem of this project is relying on a Find-module " - "without ensuring that it is actually available.\n"; + this->Makefile->IssueMessage( + this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str()); + if (this->Required) { + cmSystemTools::SetFatalErrorOccured(); } - } - this->Makefile->IssueMessage( - this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str()); - if (this->Required) { - cmSystemTools::SetFatalErrorOccured(); + if (!aw.str().empty()) { + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str()); + } } - - if (!aw.str().empty()) { - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str()); + // output result if in config mode but not in quiet mode + else if (!this->Quiet) { + std::ostringstream aw; + aw << "Could NOT find " << this->Name << " (missing: " << this->Name + << "_DIR)"; + this->Makefile->DisplayStatus(aw.str().c_str(), -1); } } @@ -912,7 +943,7 @@ bool cmFindPackageCommand::FindConfig() bool cmFindPackageCommand::FindPrefixedConfig() { - std::vector& prefixes = this->SearchPaths; + std::vector const& prefixes = this->SearchPaths; for (std::vector::const_iterator pi = prefixes.begin(); pi != prefixes.end(); ++pi) { if (this->SearchPrefix(*pi)) { @@ -924,7 +955,7 @@ bool cmFindPackageCommand::FindPrefixedConfig() bool cmFindPackageCommand::FindFrameworkConfig() { - std::vector& prefixes = this->SearchPaths; + std::vector const& prefixes = this->SearchPaths; for (std::vector::const_iterator i = prefixes.begin(); i != prefixes.end(); ++i) { if (this->SearchFrameworkPrefix(*i)) { @@ -936,7 +967,7 @@ bool cmFindPackageCommand::FindFrameworkConfig() bool cmFindPackageCommand::FindAppBundleConfig() { - std::vector& prefixes = this->SearchPaths; + std::vector const& prefixes = this->SearchPaths; for (std::vector::const_iterator i = prefixes.begin(); i != prefixes.end(); ++i) { if (this->SearchAppBundlePrefix(*i)) { @@ -1051,6 +1082,9 @@ void cmFindPackageCommand::AppendSuccessInformation() // Restore original state of "_FIND_" variables we set. this->RestoreFindDefinitions(); + + // Pop the package stack + this->Makefile->FindPackageModuleStack.pop_back(); } void cmFindPackageCommand::ComputePrefixes() @@ -1165,7 +1199,6 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry() #if defined(_WIN32) && !defined(__CYGWIN__) #include -#undef GetCurrentDirectory // http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx #if !defined(KEY_WOW64_32KEY) #define KEY_WOW64_32KEY 0x0200 @@ -1514,13 +1547,17 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, &parsed_minor, &parsed_patch, &parsed_tweak); switch (this->VersionFoundCount) { case 4: - this->VersionFoundTweak = parsed_tweak; // no break! + this->VersionFoundTweak = parsed_tweak; + CM_FALLTHROUGH; case 3: - this->VersionFoundPatch = parsed_patch; // no break! + this->VersionFoundPatch = parsed_patch; + CM_FALLTHROUGH; case 2: - this->VersionFoundMinor = parsed_minor; // no break! + this->VersionFoundMinor = parsed_minor; + CM_FALLTHROUGH; case 1: - this->VersionFoundMajor = parsed_major; // no break! + this->VersionFoundMajor = parsed_major; + CM_FALLTHROUGH; default: break; } @@ -1565,6 +1602,7 @@ class cmFileListGeneratorBase { public: virtual ~cmFileListGeneratorBase() {} + protected: bool Consider(std::string const& fullPath, cmFileList& listing); @@ -2002,6 +2040,9 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) if (this->UseLib64Paths) { common.push_back("lib64"); } + if (this->UseLibx32Paths) { + common.push_back("libx32"); + } common.push_back("lib"); common.push_back("share"); diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index d4548928d..318b1dc87 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -3,8 +3,9 @@ #ifndef cmFindPackageCommand_h #define cmFindPackageCommand_h -#include -#include +#include "cmConfigure.h" + +#include "cm_kwiml.h" #include #include #include @@ -59,16 +60,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "find_package"; } - private: class PathLabel : public cmFindCommon::PathLabel { @@ -169,6 +160,7 @@ private: bool DebugMode; bool UseLib32Paths; bool UseLib64Paths; + bool UseLibx32Paths; bool PolicyScope; std::string LibraryArchitecture; std::vector Names; diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 8d4bcf3de..d3541ca94 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFindPathCommand.h" -#include +#include "cmsys/Glob.hxx" #include "cmMakefile.h" #include "cmStateTypes.h" @@ -76,14 +76,14 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file, // if there is a / in the name try to find the header as a framework // For example bar/foo.h would look for: // bar.framework/Headers/foo.h - if (pos != fileName.npos) { + if (pos != std::string::npos) { // remove the name from the slash; fileName = fileName.substr(pos + 1); frameWorkName = file; frameWorkName = frameWorkName.substr(0, frameWorkName.size() - fileName.size() - 1); // if the framework has a path in it then just use the filename - if (frameWorkName.find('/') != frameWorkName.npos) { + if (frameWorkName.find('/') != std::string::npos) { fileName = file; frameWorkName = ""; } diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h index edeeb3a6f..3761145b2 100644 --- a/Source/cmFindPathCommand.h +++ b/Source/cmFindPathCommand.h @@ -3,7 +3,8 @@ #ifndef cmFindPathCommand_h #define cmFindPathCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -35,16 +36,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "find_path"; } - bool IncludeFileInPath; private: diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index ea031cf20..9327c1805 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -212,7 +212,8 @@ std::string cmFindProgramCommand::FindAppBundle() return ""; } -std::string cmFindProgramCommand::GetBundleExecutable(std::string bundlePath) +std::string cmFindProgramCommand::GetBundleExecutable( + std::string const& bundlePath) { std::string executable; (void)bundlePath; diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h index dc17803f0..b0cd42096 100644 --- a/Source/cmFindProgramCommand.h +++ b/Source/cmFindProgramCommand.h @@ -3,7 +3,8 @@ #ifndef cmFindProgramCommand_h #define cmFindProgramCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -36,23 +37,13 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "find_program"; } - private: std::string FindProgram(); std::string FindNormalProgram(); std::string FindNormalProgramDirsPerName(); std::string FindNormalProgramNamesPerDir(); std::string FindAppBundle(); - std::string GetBundleExecutable(std::string bundlePath); + std::string GetBundleExecutable(std::string const& bundlePath); }; #endif diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 6273f6e9f..8346b2309 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -58,7 +58,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, status.Clear(); mf.ExecuteCommand(this->Functions[c], status); if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(true); + inStatus.SetReturnInvoked(); // restore the variable to its prior value mf.AddDefinition(this->Args[0], oldDef.c_str()); return true; diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h index 93c467620..7c8a6d836 100644 --- a/Source/cmForEachCommand.h +++ b/Source/cmForEachCommand.h @@ -3,7 +3,8 @@ #ifndef cmForEachCommand_h #define cmForEachCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -47,16 +48,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "foreach"; } - private: bool HandleInMode(std::vector const& args); }; diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 06985d236..d8b002309 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -4,9 +4,11 @@ #define cmFortranParser_h #if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx) -#include +#include "cmConfigure.h" -#include "cmStandardIncludes.h" +#include +#include +#include #endif #include /* size_t */ @@ -52,8 +54,7 @@ void cmFortranParser_RuleElse(cmFortranParser* parser); void cmFortranParser_RuleEndif(cmFortranParser* parser); /* Define the parser stack element type. */ -typedef union cmFortran_yystype_u cmFortran_yystype; -union cmFortran_yystype_u +struct cmFortran_yystype { char* string; }; diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx index 1a5e6c5ee..4e23f3691 100644 --- a/Source/cmFortranParserImpl.cxx +++ b/Source/cmFortranParserImpl.cxx @@ -1,11 +1,10 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFortranParser.h" -#include "cmFortranLexer.h" #include "cmSystemTools.h" +#include "cmConfigure.h" #include -#include #include #include #include diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 31adcb71b..ee52bde37 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -20,11 +20,6 @@ public: ///! clean up any memory allocated by the function ~cmFunctionHelperCommand() CM_OVERRIDE {} - /** - * This determines if the command is defined in a cmake script. - */ - bool IsUserDefined() const CM_OVERRIDE { return true; } - /** * This is a virtual constructor for the command. */ @@ -39,11 +34,6 @@ public: return newC; } - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - /** * This is called when the command is first encountered in * the CMakeLists.txt file. @@ -57,11 +47,6 @@ public: return false; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return this->Args[0]; } - std::vector Args; std::vector Functions; cmPolicies::PolicyMap Policies; @@ -126,7 +111,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass( // The error message should have already included the call stack // so we do not need to report an error here. functionScope.Quiet(); - inStatus.SetNestedError(true); + inStatus.SetNestedError(); return false; } if (status.GetReturnInvoked()) { @@ -154,11 +139,7 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked( f->Functions = this->Functions; f->FilePath = this->GetStartingContext().FilePath; mf.RecordPolicies(f->Policies); - - std::string newName = "_" + this->Args[0]; - mf.GetState()->RenameCommand(this->Args[0], newName); - mf.GetState()->AddCommand(f); - + mf.GetState()->AddScriptedCommand(this->Args[0], f); // remove the function blocker now that the function is defined mf.RemoveFunctionBlocker(this, lff); return true; diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h index afea6f9c8..f26312632 100644 --- a/Source/cmFunctionCommand.h +++ b/Source/cmFunctionCommand.h @@ -3,7 +3,8 @@ #ifndef cmFunctionCommand_h #define cmFunctionCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -43,16 +44,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "function"; } }; #endif diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 473149374..6aa593cc0 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -8,7 +8,7 @@ #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_codecvt.hxx" -#include +#include "cm_zlib.h" #endif cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding) diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h index a027b01f6..56f9988ff 100644 --- a/Source/cmGeneratedFileStream.h +++ b/Source/cmGeneratedFileStream.h @@ -3,10 +3,10 @@ #ifndef cmGeneratedFileStream_h #define cmGeneratedFileStream_h -#include +#include "cmConfigure.h" -#include -#include +#include "cm_codecvt.hxx" +#include "cmsys/FStream.hxx" #include // This is the first base class of cmGeneratedFileStream. It will be diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index e70bbfed3..00b5ff4ef 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorExpression.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include "assert.h" @@ -126,7 +126,7 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression() std::string cmGeneratorExpression::StripEmptyListElements( const std::string& input) { - if (input.find(';') == input.npos) { + if (input.find(';') == std::string::npos) { return input; } std::string result; @@ -161,7 +161,7 @@ static std::string stripAllGeneratorExpressions(const std::string& input) std::string::size_type pos = 0; std::string::size_type lastPos = pos; int nestingLevel = 0; - while ((pos = input.find("$<", lastPos)) != input.npos) { + while ((pos = input.find("$<", lastPos)) != std::string::npos) { result += input.substr(lastPos, pos - lastPos); pos += 2; nestingLevel = 1; @@ -290,7 +290,7 @@ void cmGeneratorExpression::Split(const std::string& input, { std::string::size_type pos = 0; std::string::size_type lastPos = pos; - while ((pos = input.find("$<", lastPos)) != input.npos) { + while ((pos = input.find("$<", lastPos)) != std::string::npos) { std::string part = input.substr(lastPos, pos - lastPos); std::string preGenex; if (!part.empty()) { diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 8f82a6b4f..34516f5c5 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -3,11 +3,11 @@ #ifndef cmGeneratorExpression_h #define cmGeneratorExpression_h -#include +#include "cmConfigure.h" #include "cmListFileCache.h" -#include +#include "cm_auto_ptr.hxx" #include #include #include @@ -31,6 +31,8 @@ struct cmGeneratorExpressionEvaluator; */ class cmGeneratorExpression { + CM_DISABLE_COPY(cmGeneratorExpression) + public: /** Construct. */ cmGeneratorExpression( @@ -61,14 +63,13 @@ public: static std::string StripEmptyListElements(const std::string& input); private: - cmGeneratorExpression(const cmGeneratorExpression&); - void operator=(const cmGeneratorExpression&); - cmListFileBacktrace Backtrace; }; class cmCompiledGeneratorExpression { + CM_DISABLE_COPY(cmCompiledGeneratorExpression) + public: const char* Evaluate( cmLocalGenerator* lg, const std::string& config, bool quiet = false, @@ -133,9 +134,6 @@ private: friend class cmGeneratorExpression; - cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression&); - void operator=(const cmCompiledGeneratorExpression&); - cmListFileBacktrace Backtrace; std::vector Evaluators; const std::string Input; diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 8f102595f..557a19220 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -3,7 +3,7 @@ #ifndef cmGeneratorExpressionDAGChecker_h #define cmGeneratorExpressionDAGChecker_h -#include +#include "cmConfigure.h" #include "cmListFileCache.h" diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index aeb005fdd..15264545b 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorExpressionEvaluationFile.h" -#include -#include +#include "cmConfigure.h" +#include "cmsys/FStream.hxx" #include #include @@ -64,8 +64,10 @@ void cmGeneratorExpressionEvaluationFile::Generate( return; } std::ostringstream e; - e << "Evaluation file to be written multiple times for different " - "configurations or languages with different content:\n " + e << "Evaluation file to be written multiple times with different " + "content. " + "This is generally caused by the content evaluating the " + "configuration type, language, or location of object files:\n " << outputFileName; lg->IssueMessage(cmake::FATAL_ERROR, e.str()); return; diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h index 26135df21..98727460e 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.h +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -3,7 +3,7 @@ #ifndef cmGeneratorExpressionEvaluationFile_h #define cmGeneratorExpressionEvaluationFile_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -11,12 +11,7 @@ #include "cmGeneratorExpression.h" #include "cm_auto_ptr.hxx" - -#if defined(_MSC_VER) -typedef unsigned short mode_t; -#else -#include -#endif +#include "cm_sys_stat.h" class cmLocalGenerator; diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 41bea9bcb..a0a826ac6 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -3,7 +3,7 @@ #ifndef cmGeneratorExpressionEvaluator_h #define cmGeneratorExpressionEvaluator_h -#include +#include "cmConfigure.h" #include #include @@ -30,8 +30,7 @@ struct cmGeneratorExpressionEvaluator cmGeneratorExpressionDAGChecker*) const = 0; private: - cmGeneratorExpressionEvaluator(const cmGeneratorExpressionEvaluator&); - void operator=(const cmGeneratorExpressionEvaluator&); + CM_DISABLE_COPY(cmGeneratorExpressionEvaluator) }; struct TextContent : public cmGeneratorExpressionEvaluator diff --git a/Source/cmGeneratorExpressionLexer.h b/Source/cmGeneratorExpressionLexer.h index cac255d86..e53f0b547 100644 --- a/Source/cmGeneratorExpressionLexer.h +++ b/Source/cmGeneratorExpressionLexer.h @@ -3,7 +3,7 @@ #ifndef cmGeneratorExpressionLexer_h #define cmGeneratorExpressionLexer_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 66202dfe7..a57d2a0d8 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -14,18 +14,17 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmSourceFile.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cm_auto_ptr.hxx" #include "cmake.h" +#include "cmConfigure.h" +#include "cmsys/RegularExpression.hxx" +#include "cmsys/String.h" #include #include -#include -#include -#include #include #include #include @@ -411,6 +410,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044); context->LG->GetCMakeInstance()->IssueMessage( cmake::AUTHOR_WARNING, e.str(), context->Backtrace); + CM_FALLTHROUGH; } case cmPolicies::OLD: return "1"; @@ -1227,15 +1227,6 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode cmGeneratorExpressionDAGChecker* /*dagChecker*/) const CM_OVERRIDE { - if (!context->EvaluateForBuildsystem) { - std::ostringstream e; - e << "The evaluation of the TARGET_OBJECTS generator expression " - "is only suitable for consumption by CMake. It is not suitable " - "for writing out elsewhere."; - reportError(context, content->GetOriginalExpression(), e.str()); - return std::string(); - } - std::string tgtName = parameters.front(); cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName); if (!gt) { @@ -1252,40 +1243,60 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode reportError(context, content->GetOriginalExpression(), e.str()); return std::string(); } + if (!context->EvaluateForBuildsystem) { + cmGlobalGenerator* gg = context->LG->GetGlobalGenerator(); + std::string reason; + if (!gg->HasKnownObjectFileLocation(&reason)) { + std::ostringstream e; + e << "The evaluation of the TARGET_OBJECTS generator expression " + "is only suitable for consumption by CMake (limited" + << reason << "). " + "It is not suitable for writing out elsewhere."; + reportError(context, content->GetOriginalExpression(), e.str()); + return std::string(); + } + } - std::vector objectSources; - gt->GetObjectSources(objectSources, context->Config); - std::map mapping; - - for (std::vector::const_iterator it = - objectSources.begin(); - it != objectSources.end(); ++it) { - mapping[*it]; - } - - gt->LocalGenerator->ComputeObjectFilenames(mapping, gt); - - std::string obj_dir = gt->ObjectDirectory; - std::string result; - const char* sep = ""; - for (std::vector::const_iterator it = - objectSources.begin(); - it != objectSources.end(); ++it) { - // Find the object file name corresponding to this source file. - std::map::const_iterator map_it = - mapping.find(*it); - // It must exist because we populated the mapping just above. - assert(!map_it->second.empty()); - result += sep; - std::string objFile = obj_dir + map_it->second; - cmSourceFile* sf = - context->LG->GetMakefile()->GetOrCreateSource(objFile, true); - sf->SetObjectLibrary(tgtName); - sf->SetProperty("EXTERNAL_OBJECT", "1"); - result += objFile; - sep = ";"; + std::vector objects; + + if (gt->IsImported()) { + const char* loc = CM_NULLPTR; + const char* imp = CM_NULLPTR; + std::string suffix; + if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) { + cmSystemTools::ExpandListArgument(loc, objects); + } + context->HadContextSensitiveCondition = true; + } else { + gt->GetTargetObjectNames(context->Config, objects); + + std::string obj_dir; + if (context->EvaluateForBuildsystem) { + // Use object file directory with buildsystem placeholder. + obj_dir = gt->ObjectDirectory; + // Here we assume that the set of object files produced + // by an object library does not vary with configuration + // and do not set HadContextSensitiveCondition to true. + } else { + // Use object file directory with per-config location. + obj_dir = gt->GetObjectDirectory(context->Config); + context->HadContextSensitiveCondition = true; + } + + for (std::vector::iterator oi = objects.begin(); + oi != objects.end(); ++oi) { + *oi = obj_dir + *oi; + } } - return result; + + // Create the cmSourceFile instances in the referencing directory. + cmMakefile* mf = context->LG->GetMakefile(); + for (std::vector::iterator oi = objects.begin(); + oi != objects.end(); ++oi) { + mf->AddTargetObject(tgtName, *oi); + } + + return cmJoin(objects, ";"); } } targetObjectsNode; @@ -1449,6 +1460,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode lg->IssueMessage( cmake::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(policyForString(policy))); + CM_FALLTHROUGH; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::OLD: @@ -1504,6 +1516,8 @@ class ArtifactNameTag; class ArtifactPathTag; class ArtifactPdbTag; class ArtifactSonameTag; +class ArtifactBundleDirTag; +class ArtifactBundleContentDirTag; template struct TargetFilesystemArtifactResultCreator @@ -1595,7 +1609,60 @@ struct TargetFilesystemArtifactResultCreator "executables with ENABLE_EXPORTS."); return std::string(); } - return target->GetFullPath(context->Config, target->HasImportLibrary()); + cmStateEnums::ArtifactType artifact = target->HasImportLibrary() + ? cmStateEnums::ImportLibraryArtifact + : cmStateEnums::RuntimeBinaryArtifact; + return target->GetFullPath(context->Config, artifact); + } +}; + +template <> +struct TargetFilesystemArtifactResultCreator +{ + static std::string Create(cmGeneratorTarget* target, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content) + { + if (target->IsImported()) { + ::reportError(context, content->GetOriginalExpression(), + "TARGET_BUNDLE_DIR not allowed for IMPORTED targets."); + return std::string(); + } + if (!target->IsBundleOnApple()) { + ::reportError(context, content->GetOriginalExpression(), + "TARGET_BUNDLE_DIR is allowed only for Bundle targets."); + return std::string(); + } + + std::string outpath = target->GetDirectory(context->Config) + '/'; + return target->BuildBundleDirectory(outpath, context->Config, + cmGeneratorTarget::BundleDirLevel); + } +}; + +template <> +struct TargetFilesystemArtifactResultCreator +{ + static std::string Create(cmGeneratorTarget* target, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content) + { + if (target->IsImported()) { + ::reportError( + context, content->GetOriginalExpression(), + "TARGET_BUNDLE_CONTENT_DIR not allowed for IMPORTED targets."); + return std::string(); + } + if (!target->IsBundleOnApple()) { + ::reportError( + context, content->GetOriginalExpression(), + "TARGET_BUNDLE_CONTENT_DIR is allowed only for Bundle targets."); + return std::string(); + } + + std::string outpath = target->GetDirectory(context->Config) + '/'; + return target->BuildBundleDirectory(outpath, context->Config, + cmGeneratorTarget::ContentLevel); } }; @@ -1606,7 +1673,8 @@ struct TargetFilesystemArtifactResultCreator cmGeneratorExpressionContext* context, const GeneratorExpressionContent* /*unused*/) { - return target->GetFullPath(context->Config, false, true); + return target->GetFullPath(context->Config, + cmStateEnums::RuntimeBinaryArtifact, true); } }; @@ -1716,6 +1784,13 @@ static const TargetFilesystemArtifactNodeGroup static const TargetFilesystemArtifactNodeGroup targetPdbNodeGroup; +static const TargetFilesystemArtifact + targetBundleDirNode; + +static const TargetFilesystemArtifact + targetBundleContentDirNode; + static const struct ShellPathNode : public cmGeneratorExpressionNode { ShellPathNode() {} @@ -1772,6 +1847,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir; nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir; nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir; + nodeMap["TARGET_BUNDLE_DIR"] = &targetBundleDirNode; + nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode; nodeMap["STREQUAL"] = &strEqualNode; nodeMap["EQUAL"] = &equalNode; nodeMap["LOWER_CASE"] = &lowerCaseNode; diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h index ecf745eff..ece1c113c 100644 --- a/Source/cmGeneratorExpressionNode.h +++ b/Source/cmGeneratorExpressionNode.h @@ -3,7 +3,7 @@ #ifndef cmGeneratorExpressionNode_h #define cmGeneratorExpressionNode_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h index e30cb2057..633381c8a 100644 --- a/Source/cmGeneratorExpressionParser.h +++ b/Source/cmGeneratorExpressionParser.h @@ -3,7 +3,7 @@ #ifndef cmGeneratorExpressionParser_h #define cmGeneratorExpressionParser_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 3fe5c83f5..329c7a97f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorTarget.h" +#include "cmsys/RegularExpression.hxx" #include #include -#include #include #include #include @@ -75,199 +75,8 @@ public: }; cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem; -void reportBadObjLib(std::vector const& badObjLib, - cmGeneratorTarget const* target, cmake* cm) -{ - if (!badObjLib.empty()) { - std::ostringstream e; - e << "OBJECT library \"" << target->GetName() << "\" contains:\n"; - for (std::vector::const_iterator i = badObjLib.begin(); - i != badObjLib.end(); ++i) { - e << " " << (*i)->GetLocation().GetName() << "\n"; - } - e << "but may contain only sources that compile, header files, and " - "other files that would not affect linking of a normal library."; - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), target->GetBacktrace()); - } -} - -struct ObjectSourcesTag -{ -}; -struct CustomCommandsTag -{ -}; -struct ExtraSourcesTag -{ -}; -struct HeaderSourcesTag -{ -}; -struct ExternalObjectsTag -{ -}; -struct IDLSourcesTag -{ -}; -struct ResxTag -{ -}; -struct ModuleDefinitionFileTag -{ -}; -struct AppManifestTag -{ -}; -struct ManifestsTag -{ -}; -struct CertificatesTag -{ -}; -struct XamlTag -{ -}; - -template -struct IsSameTag -{ - enum - { - Result = false - }; -}; - -template -struct IsSameTag -{ - enum - { - Result = true - }; -}; - -template -struct DoAccept -{ - template - static void Do(T& /*unused*/, cmSourceFile* /*unused*/) - { - } -}; - -template <> -struct DoAccept -{ - static void Do(std::vector& files, cmSourceFile* f) - { - files.push_back(f); - } - static void Do(cmGeneratorTarget::ResxData& data, cmSourceFile* f) - { - // Build and save the name of the corresponding .h file - // This relationship will be used later when building the project files. - // Both names would have been auto generated from Visual Studio - // where the user supplied the file name and Visual Studio - // appended the suffix. - std::string resx = f->GetFullPath(); - std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h"; - data.ExpectedResxHeaders.insert(hFileName); - data.ResxSources.push_back(f); - } - static void Do(cmGeneratorTarget::XamlData& data, cmSourceFile* f) - { - // Build and save the name of the corresponding .h and .cpp file - // This relationship will be used later when building the project files. - // Both names would have been auto generated from Visual Studio - // where the user supplied the file name and Visual Studio - // appended the suffix. - std::string xaml = f->GetFullPath(); - std::string hFileName = xaml + ".h"; - std::string cppFileName = xaml + ".cpp"; - data.ExpectedXamlHeaders.insert(hFileName); - data.ExpectedXamlSources.insert(cppFileName); - data.XamlSources.push_back(f); - } - static void Do(std::string& data, cmSourceFile* f) - { - data = f->GetFullPath(); - } -}; - -template > -struct TagVisitor -{ - DataType& Data; - std::vector BadObjLibFiles; - cmGeneratorTarget const* Target; - cmGlobalGenerator* GlobalGenerator; - cmsys::RegularExpression Header; - bool IsObjLib; - - TagVisitor(cmGeneratorTarget const* target, DataType& data) - : Data(data) - , Target(target) - , GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator()) - , Header(CM_HEADER_REGEX) - , IsObjLib(target->GetType() == cmStateEnums::OBJECT_LIBRARY) - { - } - - ~TagVisitor() - { - reportBadObjLib(this->BadObjLibFiles, this->Target, - this->GlobalGenerator->GetCMakeInstance()); - } - - void Accept(cmSourceFile* sf) - { - std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - if (sf->GetCustomCommand()) { - DoAccept::Result>::Do(this->Data, sf); - } else if (this->Target->GetType() == cmStateEnums::UTILITY) { - DoAccept::Result>::Do(this->Data, sf); - } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) { - DoAccept::Result>::Do(this->Data, sf); - } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { - DoAccept::Result>::Do(this->Data, sf); - if (this->IsObjLib) { - this->BadObjLibFiles.push_back(sf); - } - } else if (!sf->GetLanguage().empty()) { - DoAccept::Result>::Do(this->Data, sf); - } else if (ext == "def") { - DoAccept::Result>::Do(this->Data, - sf); - if (this->IsObjLib) { - this->BadObjLibFiles.push_back(sf); - } - } else if (ext == "idl") { - DoAccept::Result>::Do(this->Data, sf); - if (this->IsObjLib) { - this->BadObjLibFiles.push_back(sf); - } - } else if (ext == "resx") { - DoAccept::Result>::Do(this->Data, sf); - } else if (ext == "appxmanifest") { - DoAccept::Result>::Do(this->Data, sf); - } else if (ext == "manifest") { - DoAccept::Result>::Do(this->Data, sf); - } else if (ext == "pfx") { - DoAccept::Result>::Do(this->Data, sf); - } else if (ext == "xaml") { - DoAccept::Result>::Do(this->Data, sf); - } else if (this->Header.find(sf->GetFullPath().c_str())) { - DoAccept::Result>::Do(this->Data, sf); - } else if (this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) { - DoAccept::Result>::Do(this->Data, sf); - } else { - DoAccept::Result>::Do(this->Data, sf); - } - } -}; - void CreatePropertyGeneratorExpressions( - cmStringRange const& entries, cmBacktraceRange const& backtraces, + cmStringRange entries, cmBacktraceRange backtraces, std::vector& items, bool evaluateForBuildsystem = false) { @@ -286,6 +95,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) , FortranModuleDirectoryCreated(false) , SourceFileFlagsConstructed(false) , PolicyWarnedCMP0022(false) + , PolicyReportedCMP0069(false) , DebugIncludesDone(false) , DebugCompileOptionsDone(false) , DebugCompileFeaturesDone(false) @@ -406,52 +216,60 @@ const char* cmGeneratorTarget::GetProperty(const std::string& prop) const return this->Target->GetProperty(prop); } -const char* cmGeneratorTarget::GetOutputTargetType(bool implib) const +const char* cmGeneratorTarget::GetOutputTargetType( + cmStateEnums::ArtifactType artifact) const { switch (this->GetType()) { case cmStateEnums::SHARED_LIBRARY: if (this->IsDLLPlatform()) { - if (implib) { - // A DLL import library is treated as an archive target. - return "ARCHIVE"; + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + // A DLL shared library is treated as a runtime target. + return "RUNTIME"; + case cmStateEnums::ImportLibraryArtifact: + // A DLL import library is treated as an archive target. + return "ARCHIVE"; } - // A DLL shared library is treated as a runtime target. - return "RUNTIME"; } else { // For non-DLL platforms shared libraries are treated as // library targets. return "LIBRARY"; } + break; case cmStateEnums::STATIC_LIBRARY: // Static libraries are always treated as archive targets. return "ARCHIVE"; case cmStateEnums::MODULE_LIBRARY: - if (implib) { - // Module libraries are always treated as library targets. - return "ARCHIVE"; - } else { - // Module import libraries are treated as archive targets. - return "LIBRARY"; + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + // Module import libraries are treated as archive targets. + return "LIBRARY"; + case cmStateEnums::ImportLibraryArtifact: + // Module libraries are always treated as library targets. + return "ARCHIVE"; } + break; case cmStateEnums::EXECUTABLE: - if (implib) { - // Executable import libraries are treated as archive targets. - return "ARCHIVE"; - } else { - // Executables are always treated as runtime targets. - return "RUNTIME"; + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + // Executables are always treated as runtime targets. + return "RUNTIME"; + case cmStateEnums::ImportLibraryArtifact: + // Executable import libraries are treated as archive targets. + return "ARCHIVE"; } + break; default: break; } return ""; } -std::string cmGeneratorTarget::GetOutputName(const std::string& config, - bool implib) const +std::string cmGeneratorTarget::GetOutputName( + const std::string& config, cmStateEnums::ArtifactType artifact) const { // Lookup/compute/cache the output name for this configuration. - OutputNameKey key(config, implib); + OutputNameKey key(config, artifact); cmGeneratorTarget::OutputNameMapType::iterator i = this->OutputNameMap.find(key); if (i == this->OutputNameMap.end()) { @@ -461,7 +279,7 @@ std::string cmGeneratorTarget::GetOutputName(const std::string& config, // Compute output name. std::vector props; - std::string type = this->GetOutputTargetType(implib); + std::string type = this->GetOutputTargetType(artifact); std::string configUpper = cmSystemTools::UpperCase(config); if (!type.empty() && !configUpper.empty()) { // _OUTPUT_NAME_ @@ -515,7 +333,7 @@ void cmGeneratorTarget::AddSourceCommon(const std::string& src) CM_AUTO_PTR cge = ge.Parse(src); cge->SetEvaluateForBuildsystem(true); this->SourceEntries.push_back(new TargetPropertyEntry(cge)); - this->SourceFilesMap.clear(); + this->KindedSourcesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; } @@ -587,27 +405,22 @@ static void handleSystemIncludesDep( } /* clang-format off */ -#define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \ +#define IMPLEMENT_VISIT(KIND) \ { \ - std::vector sourceFiles; \ - this->GetSourceFiles(sourceFiles, config); \ - TagVisitor< DATA##Tag DATATYPE > visitor(this, data); \ - for (std::vector::const_iterator si = sourceFiles.begin(); \ - si != sourceFiles.end(); ++si) { \ - visitor.Accept(*si); \ + KindedSources const& kinded = this->GetKindedSources(config); \ + for (std::vector::const_iterator \ + si = kinded.Sources.begin(); si != kinded.Sources.end(); ++si) { \ + if (si->Kind == KIND) { \ + data.push_back(si->Source); \ + } \ } \ } /* clang-format on */ -#define IMPLEMENT_VISIT(DATA) IMPLEMENT_VISIT_IMPL(DATA, EMPTY) - -#define EMPTY -#define COMMA , - void cmGeneratorTarget::GetObjectSources( std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(ObjectSources); + IMPLEMENT_VISIT(SourceKindObjectSource); if (!this->Objects.empty()) { return; @@ -656,10 +469,73 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature, return this->LocalGenerator->GetFeature(feature, config); } -bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature, - const std::string& config) const +bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, + std::string const& config) const { - return cmSystemTools::IsOn(this->GetFeature(feature, config)); + const char* feature = "INTERPROCEDURAL_OPTIMIZATION"; + const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config)); + + if (!result) { + // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies + return false; + } + + if (lang != "C" && lang != "CXX" && lang != "Fortran") { + // We do not define IPO behavior for other languages. + return false; + } + + cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069(); + + if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) { + if (this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_LEGACY_BEHAVIOR")) { + return true; + } + if (this->PolicyReportedCMP0069) { + // problem is already reported, no need to issue a message + return false; + } + const bool in_try_compile = + this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile(); + if (cmp0069 == cmPolicies::WARN && !in_try_compile) { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n"; + w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target " + << "'" << this->GetName() << "'."; + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + + this->PolicyReportedCMP0069 = true; + } + return false; + } + + // Note: check consistency with messages from CheckIPOSupported + const char* message = CM_NULLPTR; + if (!this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_SUPPORTED_BY_CMAKE")) { + message = "CMake doesn't support IPO for current compiler"; + } else if (!this->Makefile->IsOn("_CMAKE_" + lang + + "_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) { + message = "Compiler doesn't support IPO"; + } else if (!this->GlobalGenerator->IsIPOSupported()) { + message = "CMake doesn't support IPO for current generator"; + } + + if (!message) { + // No error/warning messages + return true; + } + + if (this->PolicyReportedCMP0069) { + // problem is already reported, no need to issue a message + return false; + } + + this->PolicyReportedCMP0069 = true; + + this->LocalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, message, this->GetBacktrace()); + return false; } const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) @@ -668,6 +544,18 @@ const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) return this->Objects[file]; } +const char* cmGeneratorTarget::GetCustomObjectExtension() const +{ + static std::string extension; + const bool has_ptx_extension = + this->GetPropertyAsBool("CUDA_PTX_COMPILATION"); + if (has_ptx_extension) { + extension = ".ptx"; + return extension.c_str(); + } + return CM_NULLPTR; +} + void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf) { this->ExplicitObjectName.insert(sf); @@ -681,84 +569,79 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const return it != this->ExplicitObjectName.end(); } -void cmGeneratorTarget::GetIDLSources(std::vector& data, - const std::string& config) const +void cmGeneratorTarget::GetModuleDefinitionSources( + std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(IDLSources); + IMPLEMENT_VISIT(SourceKindModuleDefinition); } void cmGeneratorTarget::GetHeaderSources( std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(HeaderSources); + IMPLEMENT_VISIT(SourceKindHeader); } void cmGeneratorTarget::GetExtraSources(std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(ExtraSources); + IMPLEMENT_VISIT(SourceKindExtra); } void cmGeneratorTarget::GetCustomCommands( std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(CustomCommands); + IMPLEMENT_VISIT(SourceKindCustomCommand); } void cmGeneratorTarget::GetExternalObjects( std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(ExternalObjects); + IMPLEMENT_VISIT(SourceKindExternalObject); } -void cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs, +void cmGeneratorTarget::GetExpectedResxHeaders(std::set& headers, const std::string& config) const { - ResxData data; - IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) - srcs = data.ExpectedResxHeaders; + KindedSources const& kinded = this->GetKindedSources(config); + headers = kinded.ExpectedResxHeaders; } -void cmGeneratorTarget::GetResxSources(std::vector& srcs, +void cmGeneratorTarget::GetResxSources(std::vector& data, const std::string& config) const { - ResxData data; - IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) - srcs = data.ResxSources; + IMPLEMENT_VISIT(SourceKindResx); } void cmGeneratorTarget::GetAppManifest(std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(AppManifest); + IMPLEMENT_VISIT(SourceKindAppManifest); } void cmGeneratorTarget::GetManifests(std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(Manifests); + IMPLEMENT_VISIT(SourceKindManifest); } void cmGeneratorTarget::GetCertificates(std::vector& data, const std::string& config) const { - IMPLEMENT_VISIT(Certificates); + IMPLEMENT_VISIT(SourceKindCertificate); } void cmGeneratorTarget::GetExpectedXamlHeaders(std::set& headers, const std::string& config) const { - XamlData data; - IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) - headers = data.ExpectedXamlHeaders; + KindedSources const& kinded = this->GetKindedSources(config); + headers = kinded.ExpectedXamlHeaders; } void cmGeneratorTarget::GetExpectedXamlSources(std::set& srcs, const std::string& config) const { - XamlData data; - IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) - srcs = data.ExpectedXamlSources; + KindedSources const& kinded = this->GetKindedSources(config); + srcs = kinded.ExpectedXamlSources; } std::set const& cmGeneratorTarget::GetUtilityItems() const @@ -776,21 +659,20 @@ std::set const& cmGeneratorTarget::GetUtilityItems() const return this->UtilityItems; } -void cmGeneratorTarget::GetXamlSources(std::vector& srcs, +void cmGeneratorTarget::GetXamlSources(std::vector& data, const std::string& config) const { - XamlData data; - IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) - srcs = data.XamlSources; + IMPLEMENT_VISIT(SourceKindXaml); } const char* cmGeneratorTarget::GetLocation(const std::string& config) const { static std::string location; if (this->IsImported()) { - location = this->Target->ImportedGetFullPath(config, false); + location = this->Target->ImportedGetFullPath( + config, cmStateEnums::RuntimeBinaryArtifact); } else { - location = this->GetFullPath(config, false); + location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); } return location.c_str(); } @@ -827,7 +709,8 @@ const char* cmGeneratorTarget::GetLocationForBuild() const { static std::string location; if (this->IsImported()) { - location = this->Target->ImportedGetFullPath("", false); + location = this->Target->ImportedGetFullPath( + "", cmStateEnums::RuntimeBinaryArtifact); return location.c_str(); } @@ -840,14 +723,14 @@ const char* cmGeneratorTarget::GetLocationForBuild() const } if (this->IsAppBundleOnApple()) { - std::string macdir = this->BuildMacContentDirectory("", "", false); + std::string macdir = this->BuildBundleDirectory("", "", FullLevel); if (!macdir.empty()) { location += "/"; location += macdir; } } location += "/"; - location += this->GetFullName("", false); + location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact); return location.c_str(); } @@ -1088,24 +971,16 @@ void cmGeneratorTarget::GetSourceFiles(std::vector& files, void cmGeneratorTarget::GetSourceFiles(std::vector& files, const std::string& config) const { - - // Lookup any existing link implementation for this configuration. - std::string key = cmSystemTools::UpperCase(config); - - if (!this->LinkImplementationLanguageIsContextDependent) { - files = this->SourceFilesMap.begin()->second; - return; - } - - SourceFilesMapType::iterator it = this->SourceFilesMap.find(key); - if (it != this->SourceFilesMap.end()) { - files = it->second; - } else { + if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) { + // Since we are still configuring not all sources may exist yet, + // so we need to avoid full source classification because that + // requires the absolute paths to all sources to be determined. + // Since this is only for compatibility with old policies that + // projects should not depend on anymore, just compute the files + // without memoizing them. std::vector srcs; this->GetSourceFiles(srcs, config); - std::set emitted; - for (std::vector::const_iterator i = srcs.begin(); i != srcs.end(); ++i) { cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i); @@ -1113,7 +988,195 @@ void cmGeneratorTarget::GetSourceFiles(std::vector& files, files.push_back(sf); } } - this->SourceFilesMap[key] = files; + return; + } + + KindedSources const& kinded = this->GetKindedSources(config); + files.reserve(kinded.Sources.size()); + for (std::vector::const_iterator si = kinded.Sources.begin(); + si != kinded.Sources.end(); ++si) { + files.push_back(si->Source); + } +} + +void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries( + std::vector& files, const std::string& config) const +{ + KindedSources const& kinded = this->GetKindedSources(config); + files.reserve(kinded.Sources.size()); + for (std::vector::const_iterator si = kinded.Sources.begin(); + si != kinded.Sources.end(); ++si) { + if (si->Source->GetObjectLibrary().empty()) { + files.push_back(si->Source); + } + } +} + +cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources( + std::string const& config) const +{ + // If we already processed one configuration and found no dependenc + // on configuration then always use the one result. + if (!this->LinkImplementationLanguageIsContextDependent) { + return this->KindedSourcesMap.begin()->second; + } + + // Lookup any existing link implementation for this configuration. + std::string const key = cmSystemTools::UpperCase(config); + KindedSourcesMapType::iterator it = this->KindedSourcesMap.find(key); + if (it != this->KindedSourcesMap.end()) { + if (!it->second.Initialized) { + std::ostringstream e; + e << "The SOURCES of \"" << this->GetName() + << "\" use a generator expression that depends on the " + "SOURCES themselves."; + this->GlobalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + static KindedSources empty; + return empty; + } + return it->second; + } + + // Add an entry to the map for this configuration. + KindedSources& files = this->KindedSourcesMap[key]; + this->ComputeKindedSources(files, config); + files.Initialized = true; + return files; +} + +void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, + std::string const& config) const +{ + // Get the source file paths by string. + std::vector srcs; + this->GetSourceFiles(srcs, config); + + cmsys::RegularExpression header_regex(CM_HEADER_REGEX); + std::vector badObjLib; + + std::set emitted; + for (std::vector::const_iterator i = srcs.begin(); + i != srcs.end(); ++i) { + // Create each source at most once. + cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i); + if (!emitted.insert(sf).second) { + continue; + } + + // Compute the kind (classification) of this source file. + SourceKind kind; + std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); + if (sf->GetCustomCommand()) { + kind = SourceKindCustomCommand; + } else if (this->Target->GetType() == cmStateEnums::UTILITY) { + kind = SourceKindExtra; + } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) { + kind = SourceKindHeader; + } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { + kind = SourceKindExternalObject; + if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) { + badObjLib.push_back(sf); + } + } else if (!sf->GetLanguage().empty()) { + kind = SourceKindObjectSource; + } else if (ext == "def") { + kind = SourceKindModuleDefinition; + if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) { + badObjLib.push_back(sf); + } + } else if (ext == "idl") { + kind = SourceKindIDL; + if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) { + badObjLib.push_back(sf); + } + } else if (ext == "resx") { + kind = SourceKindResx; + // Build and save the name of the corresponding .h file + // This relationship will be used later when building the project files. + // Both names would have been auto generated from Visual Studio + // where the user supplied the file name and Visual Studio + // appended the suffix. + std::string resx = sf->GetFullPath(); + std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h"; + files.ExpectedResxHeaders.insert(hFileName); + } else if (ext == "appxmanifest") { + kind = SourceKindAppManifest; + } else if (ext == "manifest") { + kind = SourceKindManifest; + } else if (ext == "pfx") { + kind = SourceKindCertificate; + } else if (ext == "xaml") { + kind = SourceKindXaml; + // Build and save the name of the corresponding .h and .cpp file + // This relationship will be used later when building the project files. + // Both names would have been auto generated from Visual Studio + // where the user supplied the file name and Visual Studio + // appended the suffix. + std::string xaml = sf->GetFullPath(); + std::string hFileName = xaml + ".h"; + std::string cppFileName = xaml + ".cpp"; + files.ExpectedXamlHeaders.insert(hFileName); + files.ExpectedXamlSources.insert(cppFileName); + } else if (header_regex.find(sf->GetFullPath().c_str())) { + kind = SourceKindHeader; + } else { + kind = SourceKindExtra; + } + + // Save this classified source file in the result vector. + SourceAndKind entry = { sf, kind }; + files.Sources.push_back(entry); + } + + if (!badObjLib.empty()) { + std::ostringstream e; + e << "OBJECT library \"" << this->GetName() << "\" contains:\n"; + for (std::vector::const_iterator i = badObjLib.begin(); + i != badObjLib.end(); ++i) { + e << " " << (*i)->GetLocation().GetName() << "\n"; + } + e << "but may contain only sources that compile, header files, and " + "other files that would not affect linking of a normal library."; + this->GlobalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + } +} + +std::vector const& +cmGeneratorTarget::GetAllConfigSources() const +{ + if (this->AllConfigSources.empty()) { + this->ComputeAllConfigSources(); + } + return this->AllConfigSources; +} + +void cmGeneratorTarget::ComputeAllConfigSources() const +{ + std::vector configs; + this->Makefile->GetConfigurations(configs); + + std::map index; + + for (size_t ci = 0; ci < configs.size(); ++ci) { + KindedSources const& sources = this->GetKindedSources(configs[ci]); + for (std::vector::const_iterator si = + sources.Sources.begin(); + si != sources.Sources.end(); ++si) { + std::map::iterator mi = + index.find(si->Source); + if (mi == index.end()) { + AllConfigSource acs; + acs.Source = si->Source; + acs.Kind = si->Kind; + this->AllConfigSources.push_back(acs); + std::map::value_type entry( + si->Source, this->AllConfigSources.size() - 1); + mi = index.insert(entry).first; + } + this->AllConfigSources[mi->second].Configs.push_back(ci); + } } } @@ -1123,7 +1186,8 @@ std::string cmGeneratorTarget::GetCompilePDBName( std::string prefix; std::string base; std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); + this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact, + prefix, base, suffix); // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(config); @@ -1321,8 +1385,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir( return false; } const char* install_name = this->GetProperty("INSTALL_NAME_DIR"); - bool use_install_name = - this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); + bool use_install_name = this->MacOSXUseInstallNameDir(); if (install_name && use_install_name && std::string(install_name) == "@rpath") { install_name_is_rpath = true; @@ -1395,6 +1458,53 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const return cmp0042 == cmPolicies::NEW; } +bool cmGeneratorTarget::MacOSXUseInstallNameDir() const +{ + const char* build_with_install_name = + this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR"); + if (build_with_install_name) { + return cmSystemTools::IsOn(build_with_install_name); + } + + cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068(); + if (cmp0068 == cmPolicies::NEW) { + return false; + } + + bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); + + if (use_install_name && cmp0068 == cmPolicies::WARN) { + this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget( + this->GetName()); + } + + return use_install_name; +} + +bool cmGeneratorTarget::CanGenerateInstallNameDir( + InstallNameType name_type) const +{ + cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068(); + + if (cmp0068 == cmPolicies::NEW) { + return true; + } + + bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH"); + if (name_type == INSTALL_NAME_FOR_INSTALL) { + skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"); + } else { + skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH"); + } + + if (skip && cmp0068 == cmPolicies::WARN) { + this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget( + this->GetName()); + } + + return !skip; +} + std::string cmGeneratorTarget::GetSOName(const std::string& config) const { if (this->IsImported()) { @@ -1424,19 +1534,31 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const return soName; } -std::string cmGeneratorTarget::GetAppBundleDirectory(const std::string& config, - bool contentOnly) const +static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level) { - std::string fpath = this->GetFullName(config, false); + return level == cmGeneratorTarget::FullLevel; +} + +static bool shouldAddContentLevel( + cmGeneratorTarget::BundleDirectoryLevel level) +{ + return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level); +} + +std::string cmGeneratorTarget::GetAppBundleDirectory( + const std::string& config, BundleDirectoryLevel level) const +{ + std::string fpath = + this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact); fpath += "."; const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { ext = "app"; } fpath += ext; - if (!this->Makefile->PlatformIsAppleIos()) { + if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) { fpath += "/Contents"; - if (!contentOnly) { + if (shouldAddFullLevel(level)) { fpath += "/MacOS"; } } @@ -1449,11 +1571,11 @@ bool cmGeneratorTarget::IsBundleOnApple() const this->IsCFBundleOnApple(); } -std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config, - bool contentOnly) const +std::string cmGeneratorTarget::GetCFBundleDirectory( + const std::string& config, BundleDirectoryLevel level) const { std::string fpath; - fpath += this->GetOutputName(config, false); + fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact); fpath += "."; const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { @@ -1464,63 +1586,64 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config, } } fpath += ext; - if (!this->Makefile->PlatformIsAppleIos()) { + if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) { fpath += "/Contents"; - if (!contentOnly) { + if (shouldAddFullLevel(level)) { fpath += "/MacOS"; } } return fpath; } -std::string cmGeneratorTarget::GetFrameworkDirectory(const std::string& config, - bool rootDir) const +std::string cmGeneratorTarget::GetFrameworkDirectory( + const std::string& config, BundleDirectoryLevel level) const { std::string fpath; - fpath += this->GetOutputName(config, false); + fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact); fpath += "."; const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { ext = "framework"; } fpath += ext; - if (!rootDir && !this->Makefile->PlatformIsAppleIos()) { + if (shouldAddFullLevel(level) && !this->Makefile->PlatformIsAppleIos()) { fpath += "/Versions/"; fpath += this->GetFrameworkVersion(); } return fpath; } -std::string cmGeneratorTarget::GetFullName(const std::string& config, - bool implib) const +std::string cmGeneratorTarget::GetFullName( + const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { - return this->GetFullNameImported(config, implib); + return this->GetFullNameImported(config, artifact); } - return this->GetFullNameInternal(config, implib); + return this->GetFullNameInternal(config, artifact); } std::string cmGeneratorTarget::GetInstallNameDirForBuildTree( const std::string& config) const { - // If building directly for installation then the build tree install_name - // is the same as the install tree. - if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) { - return this->GetInstallNameDirForInstallTree(); - } + if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { - // Use the build tree directory for the target. - if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") && - !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) { - std::string dir; - if (this->MacOSXRpathInstallNameDirDefault()) { - dir = "@rpath"; - } else { - dir = this->GetDirectory(config); + // If building directly for installation then the build tree install_name + // is the same as the install tree. + if (this->MacOSXUseInstallNameDir()) { + return this->GetInstallNameDirForInstallTree(); + } + + // Use the build tree directory for the target. + if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_BUILD)) { + std::string dir; + if (this->MacOSXRpathInstallNameDirDefault()) { + dir = "@rpath"; + } else { + dir = this->GetDirectory(config); + } + dir += "/"; + return dir; } - dir += "/"; - return dir; } return ""; } @@ -1531,8 +1654,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const std::string dir; const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); - if (!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) { + if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { if (install_name_dir && *install_name_dir) { dir = install_name_dir; dir += "/"; @@ -1790,44 +1912,43 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config, } } -void cmGeneratorTarget::GetFullNameComponents(std::string& prefix, - std::string& base, - std::string& suffix, - const std::string& config, - bool implib) const +void cmGeneratorTarget::GetFullNameComponents( + std::string& prefix, std::string& base, std::string& suffix, + const std::string& config, cmStateEnums::ArtifactType artifact) const { - this->GetFullNameInternal(config, implib, prefix, base, suffix); + this->GetFullNameInternal(config, artifact, prefix, base, suffix); } -std::string cmGeneratorTarget::BuildMacContentDirectory( - const std::string& base, const std::string& config, bool contentOnly) const +std::string cmGeneratorTarget::BuildBundleDirectory( + const std::string& base, const std::string& config, + BundleDirectoryLevel level) const { std::string fpath = base; if (this->IsAppBundleOnApple()) { - fpath += this->GetAppBundleDirectory(config, contentOnly); + fpath += this->GetAppBundleDirectory(config, level); } if (this->IsFrameworkOnApple()) { - fpath += this->GetFrameworkDirectory(config, contentOnly); + fpath += this->GetFrameworkDirectory(config, level); } if (this->IsCFBundleOnApple()) { - fpath += this->GetCFBundleDirectory(config, contentOnly); + fpath += this->GetCFBundleDirectory(config, level); } return fpath; } std::string cmGeneratorTarget::GetMacContentDirectory( - const std::string& config, bool implib) const + const std::string& config, cmStateEnums::ArtifactType artifact) const { // Start with the output directory for the target. - std::string fpath = this->GetDirectory(config, implib); + std::string fpath = this->GetDirectory(config, artifact); fpath += "/"; - bool contentOnly = true; + BundleDirectoryLevel level = ContentLevel; if (this->IsFrameworkOnApple()) { // additional files with a framework go into the version specific // directory - contentOnly = false; + level = FullLevel; } - fpath = this->BuildMacContentDirectory(fpath, config, contentOnly); + fpath = this->BuildBundleDirectory(fpath, config, level); return fpath; } @@ -1880,57 +2001,51 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( return &i->second; } -cmSourceFile const* cmGeneratorTarget::GetModuleDefinitionFile( - const std::string& config) const +cmGeneratorTarget::ModuleDefinitionInfo const* +cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const { - std::vector data; - IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, - COMMA std::vector) - if (!data.empty()) { - return data.front(); + // A module definition file only makes sense on certain target types. + if (this->GetType() != cmStateEnums::SHARED_LIBRARY && + this->GetType() != cmStateEnums::MODULE_LIBRARY && + !this->IsExecutableWithExports()) { + return CM_NULLPTR; } - return CM_NULLPTR; + // Lookup/compute/cache the compile information for this configuration. + std::string config_upper; + if (!config.empty()) { + config_upper = cmSystemTools::UpperCase(config); + } + ModuleDefinitionInfoMapType::const_iterator i = + this->ModuleDefinitionInfoMap.find(config_upper); + if (i == this->ModuleDefinitionInfoMap.end()) { + ModuleDefinitionInfo info; + this->ComputeModuleDefinitionInfo(config, info); + ModuleDefinitionInfoMapType::value_type entry(config_upper, info); + i = this->ModuleDefinitionInfoMap.insert(entry).first; + } + return &i->second; } -bool cmGeneratorTarget::IsDLLPlatform() const +void cmGeneratorTarget::ComputeModuleDefinitionInfo( + std::string const& config, ModuleDefinitionInfo& info) const { - return this->DLLPlatform; + this->GetModuleDefinitionSources(info.Sources, config); + info.WindowsExportAllSymbols = + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && + this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"); + info.DefFileGenerated = + info.WindowsExportAllSymbols || info.Sources.size() > 1; + if (info.DefFileGenerated) { + info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def"; + } else if (!info.Sources.empty()) { + info.DefFile = info.Sources.front()->GetFullPath(); + } } -void cmGeneratorTarget::UseObjectLibraries(std::vector& objs, - const std::string& config) const +bool cmGeneratorTarget::IsDLLPlatform() const { - std::vector objectFiles; - this->GetExternalObjects(objectFiles, config); - std::vector objectLibraries; - for (std::vector::const_iterator it = - objectFiles.begin(); - it != objectFiles.end(); ++it) { - std::string objLib = (*it)->GetObjectLibrary(); - if (cmGeneratorTarget* tgt = - this->LocalGenerator->FindGeneratorTargetToUse(objLib)) { - objectLibraries.push_back(tgt); - } - } - - std::vector::const_iterator end = - cmRemoveDuplicates(objectLibraries); - - for (std::vector::const_iterator ti = - objectLibraries.begin(); - ti != end; ++ti) { - cmGeneratorTarget* ogt = *ti; - std::vector objectSources; - ogt->GetObjectSources(objectSources, config); - for (std::vector::const_iterator si = - objectSources.begin(); - si != objectSources.end(); ++si) { - std::string obj = ogt->ObjectDirectory; - obj += ogt->Objects[*si]; - objs.push_back(obj); - } - } + return this->DLLPlatform; } void cmGeneratorTarget::GetAutoUicOptions(std::vector& result, @@ -2317,19 +2432,29 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config, } } +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable( + std::string const& var, std::string const& lang, + std::string const& config) const +{ + if (this->IsIPOEnabled(lang, config)) { + std::string varIPO = var + "_IPO"; + if (this->Makefile->IsDefinitionSet(varIPO)) { + return varIPO; + } + } + + return var; +} + +//---------------------------------------------------------------------------- std::string cmGeneratorTarget::GetCreateRuleVariable( std::string const& lang, std::string const& config) const { switch (this->GetType()) { case cmStateEnums::STATIC_LIBRARY: { std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY"; - if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION", config)) { - std::string varIPO = var + "_IPO"; - if (this->Makefile->GetDefinition(varIPO)) { - return varIPO; - } - } - return var; + return this->GetFeatureSpecificLinkRuleVariable(var, lang, config); } case cmStateEnums::SHARED_LIBRARY: return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY"; @@ -2374,6 +2499,7 @@ static void processIncludeDirectories( switch (tgt->GetPolicyStatusCMP0027()) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n"; + CM_FALLTHROUGH; case cmPolicies::OLD: messageType = cmake::AUTHOR_WARNING; break; @@ -2518,18 +2644,6 @@ std::vector cmGeneratorTarget::GetIncludeDirectories( cmDeleteAll(linkInterfaceIncludeDirectoriesEntries); - // Add standard include directories for this language. - std::string const standardIncludesVar = - "CMAKE_" + lang + "_STANDARD_INCLUDE_DIRECTORIES"; - std::string const standardIncludes = - this->Makefile->GetSafeDefinition(standardIncludesVar); - std::vector::size_type const before = includes.size(); - cmSystemTools::ExpandListArgument(standardIncludes, includes); - for (std::vector::iterator i = includes.begin() + before; - i != includes.end(); ++i) { - cmSystemTools::ConvertToUnixSlashes(*i); - } - return includes; } @@ -2730,6 +2844,7 @@ void cmGeneratorTarget::GetCompileDefinitions( std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + CM_FALLTHROUGH; } case cmPolicies::OLD: { cmGeneratorExpression ge; @@ -2777,7 +2892,8 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const } // Get the directory. - std::string dir = this->GetDirectory(config, false); + std::string dir = + this->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact); // Add each name. std::string f; @@ -2806,13 +2922,26 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const gg->AddToManifest(f); } if (!impName.empty()) { - f = this->GetDirectory(config, true); + f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact); f += "/"; f += impName; gg->AddToManifest(f); } } +bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const +{ + std::vector features; + this->GetCompileFeatures(features, config); + for (std::vector::const_iterator it = features.begin(); + it != features.end(); ++it) { + if (!this->Makefile->AddRequiredTargetFeature(this->Target, *it)) { + return false; + } + } + return true; +} + std::string cmGeneratorTarget::GetImportedLibName( std::string const& config) const { @@ -2824,32 +2953,39 @@ std::string cmGeneratorTarget::GetImportedLibName( } std::string cmGeneratorTarget::GetFullPath(const std::string& config, - bool implib, bool realname) const + cmStateEnums::ArtifactType artifact, + bool realname) const { if (this->IsImported()) { - return this->Target->ImportedGetFullPath(config, implib); + return this->Target->ImportedGetFullPath(config, artifact); } - return this->NormalGetFullPath(config, implib, realname); + return this->NormalGetFullPath(config, artifact, realname); } -std::string cmGeneratorTarget::NormalGetFullPath(const std::string& config, - bool implib, - bool realname) const +std::string cmGeneratorTarget::NormalGetFullPath( + const std::string& config, cmStateEnums::ArtifactType artifact, + bool realname) const { - std::string fpath = this->GetDirectory(config, implib); + std::string fpath = this->GetDirectory(config, artifact); fpath += "/"; if (this->IsAppBundleOnApple()) { - fpath = this->BuildMacContentDirectory(fpath, config, false); + fpath = this->BuildBundleDirectory(fpath, config, FullLevel); fpath += "/"; } // Add the full name of the target. - if (implib) { - fpath += this->GetFullName(config, true); - } else if (realname) { - fpath += this->NormalGetRealName(config); - } else { - fpath += this->GetFullName(config, false); + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + if (realname) { + fpath += this->NormalGetRealName(config); + } else { + fpath += + this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact); + } + break; + case cmStateEnums::ImportLibraryArtifact: + fpath += this->GetFullName(config, cmStateEnums::ImportLibraryArtifact); + break; } return fpath; } @@ -2926,7 +3062,8 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName, std::string prefix; std::string base; std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); + this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact, + prefix, base, suffix); // The library name. name = prefix + base + suffix; @@ -2951,7 +3088,8 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName, // The import library name. if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->GetType() == cmStateEnums::MODULE_LIBRARY) { - impName = this->GetFullNameInternal(config, true); + impName = + this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact); } else { impName = ""; } @@ -2992,7 +3130,8 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name, std::string prefix; std::string base; std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); + this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact, + prefix, base, suffix); // The executable name. name = prefix + base + suffix; @@ -3012,19 +3151,20 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name, #endif // The import library name. - impName = this->GetFullNameInternal(config, true); + impName = + this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact); // The program database file name. pdbName = this->GetPDBName(config); } -std::string cmGeneratorTarget::GetFullNameInternal(const std::string& config, - bool implib) const +std::string cmGeneratorTarget::GetFullNameInternal( + const std::string& config, cmStateEnums::ArtifactType artifact) const { std::string prefix; std::string base; std::string suffix; - this->GetFullNameInternal(config, implib, prefix, base, suffix); + this->GetFullNameInternal(config, artifact, prefix, base, suffix); return prefix + base + suffix; } @@ -3033,22 +3173,21 @@ const char* cmGeneratorTarget::ImportedGetLocation( { static std::string location; assert(this->IsImported()); - location = this->Target->ImportedGetFullPath(config, false); + location = this->Target->ImportedGetFullPath( + config, cmStateEnums::RuntimeBinaryArtifact); return location.c_str(); } -std::string cmGeneratorTarget::GetFullNameImported(const std::string& config, - bool implib) const +std::string cmGeneratorTarget::GetFullNameImported( + const std::string& config, cmStateEnums::ArtifactType artifact) const { return cmSystemTools::GetFilenameName( - this->Target->ImportedGetFullPath(config, implib)); + this->Target->ImportedGetFullPath(config, artifact)); } -void cmGeneratorTarget::GetFullNameInternal(const std::string& config, - bool implib, - std::string& outPrefix, - std::string& outBase, - std::string& outSuffix) const +void cmGeneratorTarget::GetFullNameInternal( + const std::string& config, cmStateEnums::ArtifactType artifact, + std::string& outPrefix, std::string& outBase, std::string& outSuffix) const { // Use just the target name for non-main target types. if (this->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -3061,9 +3200,12 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config, return; } + const bool isImportedLibraryArtifact = + (artifact == cmStateEnums::ImportLibraryArtifact); + // Return an empty name for the import library if this platform // does not support import libraries. - if (implib && + if (isImportedLibraryArtifact && !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { outPrefix = ""; outBase = ""; @@ -3076,14 +3218,16 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config, if (this->GetType() != cmStateEnums::SHARED_LIBRARY && this->GetType() != cmStateEnums::MODULE_LIBRARY && this->GetType() != cmStateEnums::EXECUTABLE) { - implib = false; + artifact = cmStateEnums::RuntimeBinaryArtifact; } // Compute the full name for main target types. - const char* targetPrefix = (implib ? this->GetProperty("IMPORT_PREFIX") - : this->GetProperty("PREFIX")); - const char* targetSuffix = (implib ? this->GetProperty("IMPORT_SUFFIX") - : this->GetProperty("SUFFIX")); + const char* targetPrefix = + (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX") + : this->GetProperty("PREFIX")); + const char* targetSuffix = + (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX") + : this->GetProperty("SUFFIX")); const char* configPostfix = CM_NULLPTR; if (!config.empty()) { std::string configProp = cmSystemTools::UpperCase(config); @@ -3095,8 +3239,8 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config, configPostfix = CM_NULLPTR; } } - const char* prefixVar = this->Target->GetPrefixVariableInternal(implib); - const char* suffixVar = this->Target->GetSuffixVariableInternal(implib); + const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact); + const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact); // Check for language-specific default prefix and suffix. std::string ll = this->GetLinkerLanguage(config); @@ -3123,20 +3267,14 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config, // frameworks have directory prefix but no suffix std::string fw_prefix; if (this->IsFrameworkOnApple()) { - fw_prefix = this->GetOutputName(config, false); - fw_prefix += "."; - const char* ext = this->GetProperty("BUNDLE_EXTENSION"); - if (!ext) { - ext = "framework"; - } - fw_prefix += ext; + fw_prefix = this->GetFrameworkDirectory(config, ContentLevel); fw_prefix += "/"; targetPrefix = fw_prefix.c_str(); targetSuffix = CM_NULLPTR; } if (this->IsCFBundleOnApple()) { - fw_prefix = this->GetCFBundleDirectory(config, false); + fw_prefix = this->GetCFBundleDirectory(config, FullLevel); fw_prefix += "/"; targetPrefix = fw_prefix.c_str(); targetSuffix = CM_NULLPTR; @@ -3146,14 +3284,15 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config, outPrefix = targetPrefix ? targetPrefix : ""; // Append the target name or property-specified name. - outBase += this->GetOutputName(config, implib); + outBase += this->GetOutputName(config, artifact); // Append the per-configuration postfix. outBase += configPostfix ? configPostfix : ""; // Name shared libraries with their version number on some platforms. if (const char* soversion = this->GetProperty("SOVERSION")) { - if (this->GetType() == cmStateEnums::SHARED_LIBRARY && !implib && + if (this->GetType() == cmStateEnums::SHARED_LIBRARY && + !isImportedLibraryArtifact && this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) { outBase += "-"; outBase += soversion; @@ -3175,7 +3314,8 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const std::string prefix; std::string base; std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); + this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact, + prefix, base, suffix); std::vector props; std::string configUpper = cmSystemTools::UpperCase(config); @@ -3197,6 +3337,46 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const return prefix + base + ".pdb"; } +std::string cmGeneratorTarget::GetObjectDirectory( + std::string const& config) const +{ + std::string obj_dir = + this->GlobalGenerator->ExpandCFGIntDir(this->ObjectDirectory, config); +#if defined(__APPLE__) + // find and replace $(PROJECT_NAME) xcode placeholder + const std::string projectName = this->LocalGenerator->GetProjectName(); + cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName); +#endif + return obj_dir; +} + +void cmGeneratorTarget::GetTargetObjectNames( + std::string const& config, std::vector& objects) const +{ + std::vector objectSources; + this->GetObjectSources(objectSources, config); + std::map mapping; + + for (std::vector::const_iterator it = + objectSources.begin(); + it != objectSources.end(); ++it) { + mapping[*it]; + } + + this->LocalGenerator->ComputeObjectFilenames(mapping, this); + + for (std::vector::const_iterator it = + objectSources.begin(); + it != objectSources.end(); ++it) { + // Find the object file name corresponding to this source file. + std::map::const_iterator map_it = + mapping.find(*it); + // It must exist because we populated the mapping just above. + assert(!map_it->second.empty()); + objects.push_back(map_it->second); + } +} + bool cmGeneratorTarget::StrictTargetComparison::operator()( cmGeneratorTarget const* t1, cmGeneratorTarget const* t2) const { @@ -3222,8 +3402,18 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const // were not listed in one of the other lists. if (const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) { flags.MacFolder = location; + const bool stripResources = + this->GlobalGenerator->ShouldStripResourcePath(this->Makefile); if (strcmp(location, "Resources") == 0) { flags.Type = cmGeneratorTarget::SourceFileTypeResource; + if (stripResources) { + flags.MacFolder = ""; + } + } else if (cmSystemTools::StringStartsWith(location, "Resources/")) { + flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource; + if (stripResources) { + flags.MacFolder += strlen("Resources/"); + } } else { flags.Type = cmGeneratorTarget::SourceFileTypeMacContent; } @@ -3277,7 +3467,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const if (cmSourceFile* sf = this->Makefile->GetSource(*it)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; flags.MacFolder = ""; - if (!this->Makefile->PlatformIsAppleIos()) { + if (!this->GlobalGenerator->ShouldStripResourcePath(this->Makefile)) { flags.MacFolder = "Resources"; } flags.Type = cmGeneratorTarget::SourceFileTypeResource; @@ -3806,15 +3996,14 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, << theTarget->GetName() << "\".\n"; cmSystemTools::Error(e.str().c_str()); break; - } else { - propContent = consistent.second; - continue; } - } else { - // Explicitly set on target and not set in iface. Can't disagree. + propContent = consistent.second; continue; } - } else if (impliedByUse) { + // Explicitly set on target and not set in iface. Can't disagree. + continue; + } + if (impliedByUse) { propContent = impliedValue(propContent); if (ifaceIsSet) { @@ -3832,43 +4021,36 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, << "\" is in conflict.\n"; cmSystemTools::Error(e.str().c_str()); break; - } else { - propContent = consistent.second; - continue; } - } else { - // Implicitly set on target and not set in iface. Can't disagree. + propContent = consistent.second; continue; } - } else { - if (ifaceIsSet) { - if (propInitialized) { - std::pair consistent = - consistentProperty(propContent, ifacePropContent, t); - report += reportEntry; - report += compatibilityAgree(t, propContent != consistent.second); - if (!consistent.first) { - std::ostringstream e; - e << "The INTERFACE_" << p << " property of \"" - << theTarget->GetName() << "\" does\nnot agree with the value " - "of " - << p << " already determined\nfor \"" << tgt->GetName() - << "\".\n"; - cmSystemTools::Error(e.str().c_str()); - break; - } else { - propContent = consistent.second; - continue; - } - } else { - report += reportEntry + "(Interface set)\n"; - propContent = ifacePropContent; - propInitialized = true; + // Implicitly set on target and not set in iface. Can't disagree. + continue; + } + if (ifaceIsSet) { + if (propInitialized) { + std::pair consistent = + consistentProperty(propContent, ifacePropContent, t); + report += reportEntry; + report += compatibilityAgree(t, propContent != consistent.second); + if (!consistent.first) { + std::ostringstream e; + e << "The INTERFACE_" << p << " property of \"" + << theTarget->GetName() << "\" does\nnot agree with the value of " + << p << " already determined\nfor \"" << tgt->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + break; } - } else { - // Not set. Nothing to agree on. + propContent = consistent.second; continue; } + report += reportEntry + "(Interface set)\n"; + propContent = ifacePropContent; + propInitialized = true; + } else { + // Not set. Nothing to agree on. + continue; } } @@ -3958,11 +4140,14 @@ void cmGeneratorTarget::GetTargetVersion(bool soversion, int& major, switch (sscanf(version, "%d.%d.%d", &parsed_major, &parsed_minor, &parsed_patch)) { case 3: - patch = parsed_patch; // no break! + patch = parsed_patch; + CM_FALLTHROUGH; case 2: - minor = parsed_minor; // no break! + minor = parsed_minor; + CM_FALLTHROUGH; case 1: - major = parsed_major; // no break! + major = parsed_major; + CM_FALLTHROUGH; default: break; } @@ -4277,26 +4462,31 @@ const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries( return iface.Exists ? &iface : CM_NULLPTR; } -std::string cmGeneratorTarget::GetDirectory(const std::string& config, - bool implib) const +std::string cmGeneratorTarget::GetDirectory( + const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { // Return the directory from which the target is imported. return cmSystemTools::GetFilenamePath( - this->Target->ImportedGetFullPath(config, implib)); + this->Target->ImportedGetFullPath(config, artifact)); } if (OutputInfo const* info = this->GetOutputInfo(config)) { // Return the directory in which the target will be built. - return implib ? info->ImpDir : info->OutDir; + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + return info->OutDir; + case cmStateEnums::ImportLibraryArtifact: + return info->ImpDir; + } } return ""; } -bool cmGeneratorTarget::UsesDefaultOutputDir(const std::string& config, - bool implib) const +bool cmGeneratorTarget::UsesDefaultOutputDir( + const std::string& config, cmStateEnums::ArtifactType artifact) const { std::string dir; - return this->ComputeOutputDir(config, implib, dir); + return this->ComputeOutputDir(config, artifact, dir); } cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( @@ -4330,8 +4520,10 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( i = this->OutputInfoMap.insert(entry).first; // Compute output directories. - this->ComputeOutputDir(config, false, info.OutDir); - this->ComputeOutputDir(config, true, info.ImpDir); + this->ComputeOutputDir(config, cmStateEnums::RuntimeBinaryArtifact, + info.OutDir); + this->ComputeOutputDir(config, cmStateEnums::ImportLibraryArtifact, + info.ImpDir); if (!this->ComputePDBOutputDir("PDB", config, info.PdbDir)) { info.PdbDir = info.OutDir; } @@ -4351,14 +4543,15 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( } bool cmGeneratorTarget::ComputeOutputDir(const std::string& config, - bool implib, std::string& out) const + cmStateEnums::ArtifactType artifact, + std::string& out) const { bool usesDefaultOutputDir = false; std::string conf = config; // Look for a target property defining the target output directory // based on the target type. - std::string targetTypeName = this->GetOutputTargetType(implib); + std::string targetTypeName = this->GetOutputTargetType(artifact); const char* propertyName = CM_NULLPTR; std::string propertyNameStr = targetTypeName; if (!propertyNameStr.empty()) { @@ -4883,11 +5076,11 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles( std::vector::const_iterator it = configs.begin(); const std::string& firstConfig = *it; - this->GetSourceFiles(files, firstConfig); + this->GetSourceFilesWithoutObjectLibraries(files, firstConfig); for (; it != configs.end(); ++it) { std::vector configFiles; - this->GetSourceFiles(configFiles, *it); + this->GetSourceFilesWithoutObjectLibraries(configFiles, *it); if (configFiles != files) { std::string firstConfigFiles; const char* sep = ""; @@ -4966,11 +5159,11 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const // do the expansion but users link to libraries like " ${VAR} ". std::string lib = item; std::string::size_type pos = lib.find_first_not_of(" \t\r\n"); - if (pos != lib.npos) { - lib = lib.substr(pos, lib.npos); + if (pos != std::string::npos) { + lib = lib.substr(pos); } pos = lib.find_last_not_of(" \t\r\n"); - if (pos != lib.npos) { + if (pos != std::string::npos) { lib = lib.substr(0, pos + 1); } if (lib != item) { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index f5686995a..52147e319 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -3,7 +3,7 @@ #ifndef cmGeneratorTarget_h #define cmGeneratorTarget_h -#include +#include "cmConfigure.h" #include "cmLinkItem.h" #include "cmListFileCache.h" @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,8 @@ class cmTarget; class cmGeneratorTarget { + CM_DISABLE_COPY(cmGeneratorTarget) + public: cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg); ~cmGeneratorTarget(); @@ -69,18 +72,74 @@ public: bool GetPropertyAsBool(const std::string& prop) const; void GetSourceFiles(std::vector& files, const std::string& config) const; + void GetSourceFilesWithoutObjectLibraries(std::vector& files, + const std::string& config) const; + + /** Source file kinds (classifications). + Generators use this to decide how to treat a source file. */ + enum SourceKind + { + SourceKindAppManifest, + SourceKindCertificate, + SourceKindCustomCommand, + SourceKindExternalObject, + SourceKindExtra, + SourceKindHeader, + SourceKindIDL, + SourceKindManifest, + SourceKindModuleDefinition, + SourceKindObjectSource, + SourceKindResx, + SourceKindXaml + }; + + /** A source file paired with a kind (classification). */ + struct SourceAndKind + { + cmSourceFile* Source; + SourceKind Kind; + }; + + /** All sources needed for a configuration with kinds assigned. */ + struct KindedSources + { + std::vector Sources; + std::set ExpectedResxHeaders; + std::set ExpectedXamlHeaders; + std::set ExpectedXamlSources; + bool Initialized; + KindedSources() + : Initialized(false) + { + } + }; + + /** Get all sources needed for a configuration with kinds assigned. */ + KindedSources const& GetKindedSources(std::string const& config) const; + + struct AllConfigSource + { + cmSourceFile const* Source; + cmGeneratorTarget::SourceKind Kind; + std::vector Configs; + }; + + /** Get all sources needed for all configurations with kinds and + per-source configurations assigned. */ + std::vector const& GetAllConfigSources() const; void GetObjectSources(std::vector&, const std::string& config) const; const std::string& GetObjectName(cmSourceFile const* file); + const char* GetCustomObjectExtension() const; bool HasExplicitObjectName(cmSourceFile const* file) const; void AddExplicitObjectName(cmSourceFile const* sf); + void GetModuleDefinitionSources(std::vector&, + const std::string& config) const; void GetResxSources(std::vector&, const std::string& config) const; - void GetIDLSources(std::vector&, - const std::string& config) const; void GetExternalObjects(std::vector&, const std::string& config) const; void GetHeaderSources(std::vector&, @@ -110,8 +169,8 @@ public: const char* GetFeature(const std::string& feature, const std::string& config) const; - bool GetFeatureAsBool(const std::string& feature, - const std::string& config) const; + + bool IsIPOEnabled(std::string const& lang, std::string const& config) const; bool IsLinkInterfaceDependentBoolProperty(const std::string& p, const std::string& config) const; @@ -152,15 +211,31 @@ public: /** Get the full path to the target according to the settings in its makefile and the configuration type. */ - std::string GetFullPath(const std::string& config = "", bool implib = false, - bool realname = false) const; - std::string NormalGetFullPath(const std::string& config, bool implib, + std::string GetFullPath( + const std::string& config = "", + cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact, + bool realname = false) const; + std::string NormalGetFullPath(const std::string& config, + cmStateEnums::ArtifactType artifact, bool realname) const; std::string NormalGetRealName(const std::string& config) const; + /** Get the names of an object library's object files underneath + its object file directory. */ + void GetTargetObjectNames(std::string const& config, + std::vector& objects) const; + + /** What hierarchy level should the reported directory contain */ + enum BundleDirectoryLevel + { + BundleDirLevel, + ContentLevel, + FullLevel + }; + /** @return the Mac App directory without the base */ std::string GetAppBundleDirectory(const std::string& config, - bool contentOnly) const; + BundleDirectoryLevel level) const; /** Return whether this target is an executable Bundle, a framework or CFBundle on Apple. */ @@ -169,11 +244,12 @@ public: /** Get the full name of the target according to the settings in its makefile. */ std::string GetFullName(const std::string& config = "", - bool implib = false) const; + cmStateEnums::ArtifactType artifact = + cmStateEnums::RuntimeBinaryArtifact) const; /** @return the Mac framework directory without the base. */ std::string GetFrameworkDirectory(const std::string& config, - bool rootDir) const; + BundleDirectoryLevel level) const; /** Return the framework version string. Undefined if IsFrameworkOnApple returns false. */ @@ -181,7 +257,7 @@ public: /** @return the Mac CFBundle directory without the base */ std::string GetCFBundleDirectory(const std::string& config, - bool contentOnly) const; + BundleDirectoryLevel level) const; /** Return the install name directory for the target in the * build tree. For example: "\@rpath/", "\@loader_path/", @@ -214,16 +290,18 @@ public: void GetFullNameComponents(std::string& prefix, std::string& base, std::string& suffix, const std::string& config = "", - bool implib = false) const; + cmStateEnums::ArtifactType artifact = + cmStateEnums::RuntimeBinaryArtifact) const; - /** Append to @a base the mac content directory and return it. */ - std::string BuildMacContentDirectory(const std::string& base, - const std::string& config = "", - bool contentOnly = true) const; + /** Append to @a base the bundle directory hierarchy up to a certain @a level + * and return it. */ + std::string BuildBundleDirectory(const std::string& base, + const std::string& config, + BundleDirectoryLevel level) const; /** @return the mac content directory for this target. */ - std::string GetMacContentDirectory(const std::string& config = CM_NULLPTR, - bool implib = false) const; + std::string GetMacContentDirectory( + const std::string& config, cmStateEnums::ArtifactType artifact) const; /** @return folder prefix for IDEs. */ std::string GetEffectiveFolderName() const; @@ -233,7 +311,15 @@ public: cmLocalGenerator* LocalGenerator; cmGlobalGenerator const* GlobalGenerator; - cmSourceFile const* GetModuleDefinitionFile(const std::string& config) const; + struct ModuleDefinitionInfo + { + std::string DefFile; + bool DefFileGenerated; + bool WindowsExportAllSymbols; + std::vector Sources; + }; + ModuleDefinitionInfo const* GetModuleDefinitionInfo( + std::string const& config) const; /** Return whether or not the target is for a DLL platform. */ bool IsDLLPlatform() const; @@ -282,8 +368,11 @@ public: std::vector& objlibs) const; std::string GetFullNameImported(const std::string& config, - bool implib) const; + cmStateEnums::ArtifactType artifact) const; + /** 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& files) const; bool HaveBuildTreeRPATH(const std::string& config) const; @@ -293,12 +382,17 @@ public: time config name placeholder if needed for the generator. */ std::string ObjectDirectory; - void UseObjectLibraries(std::vector& objs, - const std::string& config) const; + /** Full path with trailing slash to the top-level directory + holding object files for the given configuration. */ + std::string GetObjectDirectory(std::string const& config) const; void GetAppleArchs(const std::string& config, std::vector& archVec) const; + std::string GetFeatureSpecificLinkRuleVariable( + std::string const& var, std::string const& lang, + std::string const& config) const; + /** Return the rule variable used to create this type of target. */ std::string GetCreateRuleVariable(std::string const& lang, std::string const& config) const; @@ -324,6 +418,8 @@ public: /** Add the target output files to the global generator manifest. */ void ComputeTargetManifest(const std::string& config) const; + bool ComputeCompileFeatures(std::string const& config) const; + /** * Trace through the source files in this target and add al source files * that they depend on, used by all generators @@ -335,7 +431,8 @@ public: subdirectory for that configuration. Otherwise just the canonical output directory is given. */ std::string GetDirectory(const std::string& config = "", - bool implib = false) const; + cmStateEnums::ArtifactType artifact = + cmStateEnums::RuntimeBinaryArtifact) const; /** Get the directory in which to place the target compiler .pdb file. If the configuration name is given then the generator will add its @@ -349,7 +446,8 @@ public: /** Return whether this target uses the default value for its output directory. */ - bool UsesDefaultOutputDir(const std::string& config, bool implib) const; + bool UsesDefaultOutputDir(const std::string& config, + cmStateEnums::ArtifactType artifact) const; // Cache target output paths for each configuration. struct OutputInfo @@ -390,7 +488,8 @@ public: std::string GetCompilePDBPath(const std::string& config = "") const; // Get the target base name. - std::string GetOutputName(const std::string& config, bool implib) const; + std::string GetOutputName(const std::string& config, + cmStateEnums::ArtifactType artifact) const; void AddSource(const std::string& src); void AddTracedSources(std::vector const& srcs); @@ -412,7 +511,9 @@ public: SourceFileTypePublicHeader, // is in "PUBLIC_HEADER" target property SourceFileTypeResource, // is in "RESOURCE" target property *or* // has MACOSX_PACKAGE_LOCATION=="Resources" - SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources" + SourceFileTypeDeepResource, // MACOSX_PACKAGE_LOCATION starts with + // "Resources/" + SourceFileTypeMacContent // has MACOSX_PACKAGE_LOCATION!="Resources[/]" }; struct SourceFileFlags { @@ -421,11 +522,6 @@ public: , MacFolder(CM_NULLPTR) { } - SourceFileFlags(SourceFileFlags const& r) - : Type(r.Type) - , MacFolder(r.MacFolder) - { - } SourceFileType Type; const char* MacFolder; // location inside Mac content folders }; @@ -461,7 +557,7 @@ public: std::string GetPDBDirectory(const std::string& config) const; ///! Return the preferred linker language for this target - std::string GetLinkerLanguage(const std::string& config = "") const; + std::string GetLinkerLanguage(const std::string& config) const; /** Does this target have a GNU implib to convert to MS format? */ bool HasImplibGNUtoMS() const; @@ -498,19 +594,6 @@ public: struct SourceFileFlags GetTargetSourceFileFlags( const cmSourceFile* sf) const; - struct ResxData - { - mutable std::set ExpectedResxHeaders; - mutable std::vector ResxSources; - }; - - struct XamlData - { - std::set ExpectedXamlHeaders; - std::set ExpectedXamlSources; - std::vector XamlSources; - }; - void ReportPropertyOrigin(const std::string& p, const std::string& result, const std::string& report, const std::string& compatibilityType) const; @@ -525,6 +608,16 @@ public: /** Whether this library defaults to \@rpath. */ bool MacOSXRpathInstallNameDirDefault() const; + enum InstallNameType + { + INSTALL_NAME_FOR_BUILD, + INSTALL_NAME_FOR_INSTALL + }; + /** Whether to use INSTALL_NAME_DIR. */ + bool MacOSXUseInstallNameDir() const; + /** Whether to generate an install_name. */ + bool CanGenerateInstallNameDir(InstallNameType t) const; + /** Test for special case of a third-party shared library that has no soname at all. */ bool IsImportedSharedLibWithoutSOName(const std::string& config) const; @@ -574,8 +667,9 @@ private: mutable std::map DebugCompatiblePropertiesDone; std::string GetFullNameInternal(const std::string& config, - bool implib) const; - void GetFullNameInternal(const std::string& config, bool implib, + cmStateEnums::ArtifactType artifact) const; + void GetFullNameInternal(const std::string& config, + cmStateEnums::ArtifactType artifact, std::string& outPrefix, std::string& outBase, std::string& outSuffix) const; @@ -583,7 +677,7 @@ private: mutable LinkClosureMapType LinkClosureMap; // Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type. - const char* GetOutputTargetType(bool implib) const; + const char* GetOutputTargetType(cmStateEnums::ArtifactType artifact) const; void ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, std::string const& suffix, @@ -617,9 +711,6 @@ private: void CheckPropertyCompatibility(cmComputeLinkInformation* info, const std::string& config) const; - cmGeneratorTarget(cmGeneratorTarget const&); - void operator=(cmGeneratorTarget const&); - struct LinkImplClosure : public std::vector { LinkImplClosure() @@ -673,9 +764,13 @@ private: const std::string& config, const cmGeneratorTarget* head, bool usage_requirements_only) const; - typedef std::map > - SourceFilesMapType; - mutable SourceFilesMapType SourceFilesMap; + typedef std::map KindedSourcesMapType; + mutable KindedSourcesMapType KindedSourcesMap; + void ComputeKindedSources(KindedSources& files, + std::string const& config) const; + + mutable std::vector AllConfigSources; + void ComputeAllConfigSources() const; std::vector IncludeDirectoriesEntries; std::vector CompileOptionsEntries; @@ -705,18 +800,26 @@ private: cmLinkImplementationLibraries const* GetLinkImplementationLibrariesInternal( const std::string& config, const cmGeneratorTarget* head) const; - bool ComputeOutputDir(const std::string& config, bool implib, + bool ComputeOutputDir(const std::string& config, + cmStateEnums::ArtifactType artifact, std::string& out) const; typedef std::map OutputInfoMapType; mutable OutputInfoMapType OutputInfoMap; - typedef std::pair OutputNameKey; + typedef std::map + ModuleDefinitionInfoMapType; + mutable ModuleDefinitionInfoMapType ModuleDefinitionInfoMap; + void ComputeModuleDefinitionInfo(std::string const& config, + ModuleDefinitionInfo& info) const; + + typedef std::pair OutputNameKey; typedef std::map OutputNameMapType; mutable OutputNameMapType OutputNameMap; mutable std::set UtilityItems; cmPolicies::PolicyMap PolicyMap; mutable bool PolicyWarnedCMP0022; + mutable bool PolicyReportedCMP0069; mutable bool DebugIncludesDone; mutable bool DebugCompileOptionsDone; mutable bool DebugCompileFeaturesDone; diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index 7962da601..5ba3326cb 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -20,7 +20,7 @@ bool cmGetCMakePropertyCommand::InitialPass( return false; } - std::string variable = args[0]; + std::string const& variable = args[0]; std::string output = "NOTFOUND"; if (args[1] == "VARIABLES") { diff --git a/Source/cmGetCMakePropertyCommand.h b/Source/cmGetCMakePropertyCommand.h index 41a51a440..9dfc40fda 100644 --- a/Source/cmGetCMakePropertyCommand.h +++ b/Source/cmGetCMakePropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmGetCMakePropertyCommand_h #define cmGetCMakePropertyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -22,16 +23,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "get_cmake_property"; } }; #endif diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index 920e1a014..1005b1543 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -20,7 +20,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass( } std::vector::const_iterator i = args.begin(); - std::string variable = *i; + std::string const& variable = *i; ++i; // get the directory argument if there is one @@ -78,6 +78,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass( this->Makefile->IssueMessage( cmake::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); + CM_FALLTHROUGH; case cmPolicies::OLD: this->StoreResult(variable, this->Makefile->GetDefineFlagsCMP0059()); return true; diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h index 1ae312539..7d9795065 100644 --- a/Source/cmGetDirectoryPropertyCommand.h +++ b/Source/cmGetDirectoryPropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmGetDirectoryPropertyCommand_h #define cmGetDirectoryPropertyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -23,16 +24,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "get_directory_property"; } - private: void StoreResult(const std::string& variable, const char* prop); }; diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 5915a67fa..c23684c22 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -28,7 +28,7 @@ bool cmGetFilenameComponentCommand::InitialPass( std::string result; std::string filename = args[1]; - if (filename.find("[HKEY") != filename.npos) { + if (filename.find("[HKEY") != std::string::npos) { // Check the registry as the target application would view it. cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; @@ -37,10 +37,10 @@ bool cmGetFilenameComponentCommand::InitialPass( other_view = cmSystemTools::KeyWOW64_32; } cmSystemTools::ExpandRegistryValues(filename, view); - if (filename.find("/registry") != filename.npos) { + if (filename.find("/registry") != std::string::npos) { std::string other = args[1]; cmSystemTools::ExpandRegistryValues(other, other_view); - if (other.find("/registry") == other.npos) { + if (other.find("/registry") == std::string::npos) { filename = other; } } diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h index c0ad903a8..c8a23c70e 100644 --- a/Source/cmGetFilenameComponentCommand.h +++ b/Source/cmGetFilenameComponentCommand.h @@ -3,7 +3,8 @@ #ifndef cmGetFilenameComponentCommand_h #define cmGetFilenameComponentCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,16 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "get_filename_component"; } }; #endif diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index d2056d296..ddecdf621 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -232,6 +232,7 @@ bool cmGetPropertyCommand::HandleDirectoryMode() case cmPolicies::WARN: mf->IssueMessage(cmake::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); + CM_FALLTHROUGH; case cmPolicies::OLD: return this->StoreResult(mf->GetDefineFlagsCMP0059()); case cmPolicies::NEW: diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h index f9a33acd8..649780168 100644 --- a/Source/cmGetPropertyCommand.h +++ b/Source/cmGetPropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmGetPropertyCommand_h #define cmGetPropertyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -25,16 +26,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "get_property"; } - private: enum OutType { diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index 509ef95b1..1a5f08ef8 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -15,8 +15,8 @@ bool cmGetSourceFilePropertyCommand::InitialPass( this->SetError("called with incorrect number of arguments"); return false; } - const char* var = args[0].c_str(); - const char* file = args[1].c_str(); + std::string const& var = args[0]; + std::string const& file = args[1]; cmSourceFile* sf = this->Makefile->GetSource(file); // for the location we must create a source file first diff --git a/Source/cmGetSourceFilePropertyCommand.h b/Source/cmGetSourceFilePropertyCommand.h index 0f7185122..e96bb29ed 100644 --- a/Source/cmGetSourceFilePropertyCommand.h +++ b/Source/cmGetSourceFilePropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmGetSourceFilePropertyCommand_h #define cmGetSourceFilePropertyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -22,14 +23,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "get_source_file_property"; - } }; #endif diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index 23792922d..0910a5324 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -22,8 +22,8 @@ bool cmGetTargetPropertyCommand::InitialPass( this->SetError("called with incorrect number of arguments"); return false; } - std::string var = args[0]; - const std::string& targetName = args[1]; + std::string const& var = args[0]; + std::string const& targetName = args[1]; std::string prop; bool prop_exists = false; diff --git a/Source/cmGetTargetPropertyCommand.h b/Source/cmGetTargetPropertyCommand.h index 32fe803c4..5de322563 100644 --- a/Source/cmGetTargetPropertyCommand.h +++ b/Source/cmGetTargetPropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmGetTargetPropertyCommand_h #define cmGetTargetPropertyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -22,11 +23,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "get_target_property"; } }; #endif diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx index a8a44b712..6424515ec 100644 --- a/Source/cmGetTestPropertyCommand.cxx +++ b/Source/cmGetTestPropertyCommand.cxx @@ -16,8 +16,8 @@ bool cmGetTestPropertyCommand::InitialPass( return false; } - std::string testName = args[0]; - std::string var = args[2]; + std::string const& testName = args[0]; + std::string const& var = args[2]; cmTest* test = this->Makefile->GetTest(testName); if (test) { const char* prop = CM_NULLPTR; diff --git a/Source/cmGetTestPropertyCommand.h b/Source/cmGetTestPropertyCommand.h index 0491cc8b0..b17e7a1cc 100644 --- a/Source/cmGetTestPropertyCommand.h +++ b/Source/cmGetTestPropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmGetTestPropertyCommand_h #define cmGetTestPropertyCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -22,11 +23,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "get_test_property"; } }; #endif diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h index 2c2b12343..7bc7bfc46 100644 --- a/Source/cmGhsMultiGpj.h +++ b/Source/cmGhsMultiGpj.h @@ -3,7 +3,7 @@ #ifndef cmGhsMultiGpj_h #define cmGhsMultiGpj_h -#include +#include "cmConfigure.h" class cmGeneratedFileStream; diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index ba623d57b..7032cd582 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -232,10 +232,12 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, const char* lang = language.c_str(); if (notKernel) { - this->LocalGenerator->AddLanguageFlags(flags, lang, config); + this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, + lang, config); } else { - this->LocalGenerator->AddLanguageFlags( - flags, lang + std::string("_GHS_KERNEL"), config); + this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, + lang + std::string("_GHS_KERNEL"), + config); } this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang, config); diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h index e8e6ad963..f2ad059de 100644 --- a/Source/cmGlobalCommonGenerator.h +++ b/Source/cmGlobalCommonGenerator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalCommonGenerator_h #define cmGlobalCommonGenerator_h -#include +#include "cmConfigure.h" #include "cmGlobalGenerator.h" diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index f11825083..099f705f4 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1,24 +1,21 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#if defined(_WIN32) && !defined(__CYGWIN__) -#include "windows.h" // this must be first to define GetCurrentDirectory -#if defined(_MSC_VER) && _MSC_VER >= 1800 -#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx -#endif -#endif - #include "cmGlobalGenerator.h" +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" #include #include -#include -#include #include #include #include #include #include +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#endif + #include "cmAlgorithms.h" #include "cmCPackPropertiesGenerator.h" #include "cmComputeTargetDepends.h" @@ -42,12 +39,17 @@ #include "cmStateDirectory.h" #include "cmStateTypes.h" #include "cmVersion.h" +#include "cmWorkingDirectory.h" #include "cmake.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmCryptoHash.h" -#include -#include +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1800 +#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx #endif const std::string kCMAKE_PLATFORM_INFO_INITIALIZED = @@ -94,6 +96,7 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm) this->ConfigureDoneCMP0026AndCMP0024 = false; this->FirstTimeProgress = 0.0f; + cm->GetState()->SetIsGeneratorMultiConfig(false); cm->GetState()->SetMinGWMake(false); cm->GetState()->SetMSYSShell(false); cm->GetState()->SetNMake(false); @@ -303,7 +306,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) // if there are spaces in the make program use short path // but do not short path the actual program name, as // this can cause trouble with VSExpress - if (makeProgram.find(' ') != makeProgram.npos) { + if (makeProgram.find(' ') != std::string::npos) { std::string dir; std::string file; cmSystemTools::SplitProgramPath(makeProgram, dir, file); @@ -835,6 +838,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( /* clang-format on */ mf->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to convert AppleClang to Clang. mf->AddDefinition(compilerIdVar, "Clang"); @@ -864,6 +868,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( /* clang-format on */ mf->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to convert QCC to GNU. mf->AddDefinition(compilerIdVar, "GNU"); @@ -878,6 +883,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility( mf->IssueMessage( cmake::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047)); + CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior is to keep QCC. break; @@ -1194,6 +1200,11 @@ void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target) this->CMP0042WarnTargets.insert(target); } +void cmGlobalGenerator::AddCMP0068WarnTarget(const std::string& target) +{ + this->CMP0068WarnTargets.insert(target); +} + bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const { // If the property is not enabled then okay. @@ -1235,6 +1246,8 @@ bool cmGlobalGenerator::Compute() // clear targets to issue warning CMP0042 for this->CMP0042WarnTargets.clear(); + // clear targets to issue warning CMP0068 for + this->CMP0068WarnTargets.clear(); // Check whether this generator is allowed to run. if (!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) { @@ -1262,6 +1275,18 @@ bool cmGlobalGenerator::Compute() this->LocalGenerators[i]->AddHelperCommands(); } + // Finalize the set of compile features for each target. + // FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature + // which actually modifies the _STANDARD target property + // on the original cmTarget instance. It accumulates features + // across all configurations. Some refactoring is needed to + // compute a per-config resulta purely during generation. + for (i = 0; i < this->LocalGenerators.size(); ++i) { + if (!this->LocalGenerators[i]->ComputeTargetCompileFeatures()) { + return false; + } + } + #ifdef CMAKE_BUILD_WITH_CMAKE for (std::vector::iterator it = autogenTargets.begin(); @@ -1337,10 +1362,11 @@ void cmGlobalGenerator::Generate() for (std::map::iterator it = this->BuildExportSets.begin(); it != this->BuildExportSets.end(); ++it) { - if (!it->second->GenerateImportFile() && - !cmSystemTools::GetErrorOccuredFlag()) { - this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, - "Could not write export file."); + if (!it->second->GenerateImportFile()) { + if (!cmSystemTools::GetErrorOccuredFlag()) { + this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, + "Could not write export file."); + } return; } } @@ -1366,6 +1392,24 @@ void cmGlobalGenerator::Generate() this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } + if (!this->CMP0068WarnTargets.empty()) { + std::ostringstream w; + /* clang-format off */ + w << + cmPolicies::GetPolicyWarning(cmPolicies::CMP0068) << "\n" + "For compatibility with older versions of CMake, the install_name " + "fields for the following targets are still affected by RPATH " + "settings:\n" + ; + /* clang-format on */ + for (std::set::iterator iter = + this->CMP0068WarnTargets.begin(); + iter != this->CMP0068WarnTargets.end(); ++iter) { + w << " " << *iter << "\n"; + } + this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + } + this->CMakeInstance->UpdateProgress("Generating done", -1); } @@ -1441,13 +1485,13 @@ cmGlobalGenerator::CreateQtAutoGeneratorsTargets() } cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir) const + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const { return new cmLinkLineComputer(outputConverter, stateDir); } cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir) const + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const { return new cmMSVC60LinkLineComputer(outputConverter, stateDir); } @@ -1738,8 +1782,7 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, /** * Run an executable command and put the stdout in output. */ - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(bindir); + cmWorkingDirectory workdir(bindir); output += "Change Dir: "; output += bindir; output += "\n"; @@ -1779,8 +1822,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, output += *outputPtr; output += "\nGenerator: execution of make clean failed.\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); return 1; } output += *outputPtr; @@ -1803,8 +1844,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, output += "\nGenerator: execution of make failed. Make command was: " + makeCommandStr + "\n"; - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); return 1; } output += *outputPtr; @@ -1817,7 +1856,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/, retVal = 1; } - cmSystemTools::ChangeDirectory(cwd); return retVal; } @@ -2466,6 +2504,11 @@ std::string cmGlobalGenerator::GenerateRuleFile( return ruleFile; } +bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const +{ + return mf->PlatformIsAppleIos(); +} + std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage( std::string const& l) const { @@ -2690,7 +2733,7 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile, } // Get the filename. - fname = line.substr(33, line.npos); + fname = line.substr(33); // Look for a hash for this file's rule. std::map::const_iterator rhi = diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 18e373007..871178be1 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalGenerator_h #define cmGlobalGenerator_h -#include +#include "cmConfigure.h" #include #include @@ -105,10 +105,12 @@ public: virtual void Generate(); virtual cmLinkLineComputer* CreateLinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir) const; + cmOutputConverter* outputConverter, + cmStateDirectory const& stateDir) const; cmLinkLineComputer* CreateMSVC60LinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir) const; + cmOutputConverter* outputConverter, + cmStateDirectory const& stateDir) const; /** * Set/Get and Clear the enabled languages. @@ -331,12 +333,23 @@ public: i.e. "Can I build Debug and Release in the same tree?" */ virtual bool IsMultiConfig() 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. */ + virtual bool HasKnownObjectFileLocation(std::string*) const { return true; } + virtual bool UseFolderProperty() const; + virtual bool IsIPOSupported() const { return false; } + /** Return whether the generator should use EFFECTIVE_PLATFORM_NAME. This is relevant for mixed macOS and iOS builds. */ virtual bool UseEffectivePlatformName(cmMakefile*) const { return false; } + /** Return whether the "Resources" folder prefix should be stripped from + MacFolder. */ + virtual bool ShouldStripResourcePath(cmMakefile*) const; + std::string GetSharedLibFlagsForLanguage(std::string const& lang) const; /** Generate an .rule file path for a given command output. */ @@ -357,6 +370,7 @@ public: cmExportBuildFileGenerator* GetExportedTargetsFile( const std::string& filename) const; void AddCMP0042WarnTarget(const std::string& target); + void AddCMP0068WarnTarget(const std::string& target); virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; @@ -548,12 +562,6 @@ private: : LastDiskTime(-1) { } - DirectoryContent(DirectoryContent const& dc) - : LastDiskTime(dc.LastDiskTime) - , All(dc.All) - , Generated(dc.Generated) - { - } }; std::map DirectoryContentMap; @@ -562,6 +570,8 @@ private: // track targets to issue CMP0042 warning for. std::set CMP0042WarnTargets; + // track targets to issue CMP0068 warning for. + std::set CMP0068WarnTargets; mutable std::map > FilenameTargetDepends; diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index 5e948f760..d5a6db06e 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -3,7 +3,7 @@ #ifndef cmGlobalGeneratorFactory_h #define cmGlobalGeneratorFactory_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 286f37599..42ab4d98a 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalGhsMultiGenerator.h" -#include +#include "cmsys/SystemTools.hxx" #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx index 75209c33e..e72c6e384 100644 --- a/Source/cmGlobalKdevelopGenerator.cxx +++ b/Source/cmGlobalKdevelopGenerator.cxx @@ -14,8 +14,8 @@ #include "cmXMLWriter.h" #include "cmake.h" -#include -#include +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" #include #include #include @@ -101,7 +101,7 @@ bool cmGlobalKdevelopGenerator::CreateFilelistFile( std::set files; std::string tmp; - std::vector hdrExts = + std::vector const& hdrExts = this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions(); for (std::vector::const_iterator it = lgs.begin(); diff --git a/Source/cmGlobalKdevelopGenerator.h b/Source/cmGlobalKdevelopGenerator.h index 8121fa8eb..bdcf8a190 100644 --- a/Source/cmGlobalKdevelopGenerator.h +++ b/Source/cmGlobalKdevelopGenerator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalKdevelopGenerator_h #define cmGlobalKdevelopGenerator_h -#include +#include "cmConfigure.h" #include "cmExternalMakefileProjectGenerator.h" diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index 7e0d0d455..3f223824a 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalMSYSMakefileGenerator.h" -#include +#include "cmsys/FStream.hxx" #include "cmDocumentationEntry.h" #include "cmLocalUnixMakefileGenerator3.h" diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 1bdef5349..2eef9e492 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2,11 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalNinjaGenerator.h" +#include "cm_jsoncpp_reader.h" +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" +#include "cmsys/FStream.hxx" #include -#include -#include -#include -#include #include #include #include @@ -56,7 +56,7 @@ void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count) void cmGlobalNinjaGenerator::WriteDivider(std::ostream& os) { os << "# ======================================" - << "=======================================\n"; + "=======================================\n"; } void cmGlobalNinjaGenerator::WriteComment(std::ostream& os, @@ -77,7 +77,8 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os, } cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory /* stateDir */) const + cmOutputConverter* outputConverter, + cmStateDirectory const& /* stateDir */) const { return new cmNinjaLinkLineComputer( outputConverter, @@ -146,13 +147,6 @@ std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path) return EncodeLiteral(result); } -std::string cmGlobalNinjaGenerator::EncodeDepfileSpace(const std::string& path) -{ - std::string result = path; - cmSystemTools::ReplaceString(result, " ", "\\ "); - return result; -} - void cmGlobalNinjaGenerator::WriteBuild( std::ostream& os, const std::string& comment, const std::string& rule, const cmNinjaDeps& outputs, const cmNinjaDeps& implicitOuts, @@ -216,7 +210,7 @@ void cmGlobalNinjaGenerator::WriteBuild( ++i) { build += " " + EncodeIdent(EncodePath(*i), os); if (this->ComputingUnknownDependencies) { - this->CombinedBuildOutputs.insert(EncodePath(*i)); + this->CombinedBuildOutputs.insert(*i); } } if (!implicitOuts.empty()) { @@ -246,7 +240,7 @@ void cmGlobalNinjaGenerator::WriteBuild( bool useResponseFile = false; if (cmdLineLimit < 0 || (cmdLineLimit > 0 && - (args.size() + buildstr.size() + assignments.size()) > + (args.size() + buildstr.size() + assignments.size() + 1000) > static_cast(cmdLineLimit))) { variable_assignments.str(std::string()); cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE", @@ -318,7 +312,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( // we need to track every dependency that comes in, since we are trying // to find dependencies that are side effects of build commands for (cmNinjaDeps::const_iterator i = deps.begin(); i != deps.end(); ++i) { - this->CombinedCustomCommandExplicitDependencies.insert(EncodePath(*i)); + this->CombinedCustomCommandExplicitDependencies.insert(*i); } } } @@ -898,6 +892,10 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand( this->GetCMakeInstance()->GetHomeOutputDirectory(); if (!this->CompileCommandsStream) { std::string buildFilePath = buildFileDir + "/compile_commands.json"; + if (this->ComputingUnknownDependencies) { + this->CombinedBuildOutputs.insert( + this->NinjaOutputPath("compile_commands.json")); + } // Get a stream where to generate things. this->CompileCommandsStream = @@ -966,8 +964,14 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies() } } +std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target) +{ + return "cmake_object_order_depends_target_" + target->GetName(); +} + void cmGlobalNinjaGenerator::AppendTargetOutputs( - cmGeneratorTarget const* target, cmNinjaDeps& outputs) + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + cmNinjaTargetDepends depends) { std::string configName = target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); @@ -979,15 +983,27 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( bool realname = target->IsFrameworkOnApple(); switch (target->GetType()) { - case cmStateEnums::EXECUTABLE: case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { - outputs.push_back(this->ConvertToNinjaPath( - target->GetFullPath(configName, false, realname))); + if (depends == DependOnTargetOrdering) { + outputs.push_back(OrderDependsTargetForTarget(target)); + break; + } + } + // FALLTHROUGH + case cmStateEnums::EXECUTABLE: { + outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath( + configName, cmStateEnums::RuntimeBinaryArtifact, realname))); break; } - case cmStateEnums::OBJECT_LIBRARY: + case cmStateEnums::OBJECT_LIBRARY: { + if (depends == DependOnTargetOrdering) { + outputs.push_back(OrderDependsTargetForTarget(target)); + break; + } + } + // FALLTHROUGH case cmStateEnums::GLOBAL_TARGET: case cmStateEnums::UTILITY: { std::string path = @@ -1003,7 +1019,8 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs( } void cmGlobalNinjaGenerator::AppendTargetDepends( - cmGeneratorTarget const* target, cmNinjaDeps& outputs) + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + cmNinjaTargetDepends depends) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { // These depend only on other CMake-provided targets, e.g. "all". @@ -1023,7 +1040,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( if ((*i)->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - this->AppendTargetOutputs(*i, outs); + this->AppendTargetOutputs(*i, outs, depends); } std::sort(outs.begin(), outs.end()); outputs.insert(outputs.end(), outs.begin(), outs.end()); @@ -1823,10 +1840,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( int cmcmd_cmake_ninja_dyndep(std::vector::const_iterator argBeg, std::vector::const_iterator argEnd) { + std::vector arg_full = + cmSystemTools::HandleResponseFile(argBeg, argEnd); + std::string arg_dd; std::string arg_tdi; std::vector arg_ddis; - for (std::vector::const_iterator a = argBeg; a != argEnd; ++a) { + for (std::vector::const_iterator a = arg_full.begin(); + a != arg_full.end(); ++a) { std::string const& arg = *a; if (cmHasLiteralPrefix(arg, "--tdi=")) { arg_tdi = arg.substr(6); @@ -1880,7 +1901,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector::const_iterator argBeg, } } - cmake cm; + cmake cm(cmake::RoleInternal); cm.SetHomeDirectory(dir_top_src); cm.SetHomeOutputDirectory(dir_top_bld); CM_AUTO_PTR ggd( diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index a51e91945..b0008f74a 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalNinjaGenerator_h #define cmGlobalNinjaGenerator_h -#include +#include "cmConfigure.h" #include #include @@ -75,11 +75,10 @@ public: static std::string EncodeIdent(const std::string& ident, std::ostream& vars); static std::string EncodeLiteral(const std::string& lit); std::string EncodePath(const std::string& path); - static std::string EncodeDepfileSpace(const std::string& path); cmLinkLineComputer* CreateLinkLineComputer( cmOutputConverter* outputConverter, - cmStateDirectory stateDir) const CM_OVERRIDE; + cmStateDirectory const& stateDir) const CM_OVERRIDE; /** * Write the given @a comment to the output stream @a os. It @@ -99,6 +98,8 @@ public: */ static bool SupportsPlatform() { return false; } + bool IsIPOSupported() const CM_OVERRIDE { return true; } + /** * Write a build statement to @a os with the @a comment using * the @a rule the list of @a outputs files and inputs. @@ -314,10 +315,12 @@ public: ASD.insert(deps.begin(), deps.end()); } - void AppendTargetOutputs(cmGeneratorTarget const* target, - cmNinjaDeps& outputs); - void AppendTargetDepends(cmGeneratorTarget const* target, - cmNinjaDeps& outputs); + void AppendTargetOutputs( + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + cmNinjaTargetDepends depends = DependOnTargetArtifact); + void AppendTargetDepends( + cmGeneratorTarget const* target, cmNinjaDeps& outputs, + cmNinjaTargetDepends depends = DependOnTargetArtifact); void AppendTargetDependsClosure(cmGeneratorTarget const* target, cmNinjaDeps& outputs); void AddDependencyToAll(cmGeneratorTarget* target); diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 67d7bc9ea..a656102fb 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -3,7 +3,7 @@ #ifndef cmGlobalUnixMakefileGenerator3_h #define cmGlobalUnixMakefileGenerator3_h -#include +#include "cmConfigure.h" #include #include @@ -149,6 +149,8 @@ public: /** Does the make tool tolerate .DELETE_ON_ERROR? */ virtual bool AllowDeleteOnError() const { return true; } + bool IsIPOSupported() const CM_OVERRIDE { return true; } + void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE; std::string IncludeDirective; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index e27615a41..e3835ff18 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -10,14 +10,25 @@ #include "cmSourceFile.h" #include "cmVS10CLFlagTable.h" #include "cmVS10CSharpFlagTable.h" +#include "cmVS10CudaFlagTable.h" +#include "cmVS10CudaHostFlagTable.h" #include "cmVS10LibFlagTable.h" #include "cmVS10LinkFlagTable.h" #include "cmVS10MASMFlagTable.h" +#include "cmVS10NASMFlagTable.h" #include "cmVS10RCFlagTable.h" +#include "cmVersion.h" #include "cmVisualStudioSlnData.h" #include "cmVisualStudioSlnParser.h" +#include "cmXMLWriter.h" #include "cmake.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" + +#include + static const char vs10generatorName[] = "Visual Studio 10 2010"; // Map generator name without year to name with year. @@ -94,6 +105,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;" "ProductDir", vc10Express, cmSystemTools::KeyWOW64_32); + this->CudaEnabled = false; this->SystemIsWindowsCE = false; this->SystemIsWindowsPhone = false; this->SystemIsWindowsStore = false; @@ -112,9 +124,13 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( this->DefaultCSharpFlagTable = cmVS10CSharpFlagTable; this->DefaultLibFlagTable = cmVS10LibFlagTable; this->DefaultLinkFlagTable = cmVS10LinkFlagTable; + this->DefaultCudaFlagTable = cmVS10CudaFlagTable; + this->DefaultCudaHostFlagTable = cmVS10CudaHostFlagTable; this->DefaultMasmFlagTable = cmVS10MASMFlagTable; + this->DefaultNasmFlagTable = cmVS10NASMFlagTable; this->DefaultRcFlagTable = cmVS10RCFlagTable; this->Version = VS10; + this->PlatformToolsetNeedsDebugEnum = false; } bool cmGlobalVisualStudio10Generator::MatchesGeneratorName( @@ -153,6 +169,13 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform( return true; } +static void cmCudaToolVersion(std::string& s) +{ + // "CUDA x.y.props" => "x.y" + s = s.substr(5); + s = s.substr(0, s.size() - 6); +} + bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( std::string const& ts, cmMakefile* mf) { @@ -168,36 +191,137 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( if (!this->ParseGeneratorToolset(ts, mf)) { return false; } + + if (!this->FindVCTargetsPath(mf)) { + return false; + } + + if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) { + // The GenerateDebugInformation link setting for the v140 toolset + // in VS 2015 was originally an enum with "No" and "Debug" values, + // differing from the "false" and "true" values used in older toolsets. + // A VS 2015 update changed it back. Parse the "link.xml" file to + // discover which one we need. + std::string const link_xml = this->VCTargetsPath + "/1033/link.xml"; + cmsys::ifstream fin(link_xml.c_str()); + std::string line; + while (fin && cmSystemTools::GetLineFromStream(fin, line)) { + if (line.find(" Switch=\"DEBUG\" ") != std::string::npos) { + this->PlatformToolsetNeedsDebugEnum = + line.find(" Name=\"Debug\" ") != std::string::npos; + break; + } + } + } + + if (this->GeneratorToolsetCuda.empty()) { + // Find the highest available version of the CUDA tools. + std::vector cudaTools; + std::string const bcDir = this->VCTargetsPath + "/BuildCustomizations"; + cmsys::Glob gl; + gl.SetRelative(bcDir.c_str()); + if (gl.FindFiles(bcDir + "/CUDA *.props")) { + cudaTools = gl.GetFiles(); + } + if (!cudaTools.empty()) { + std::for_each(cudaTools.begin(), cudaTools.end(), cmCudaToolVersion); + std::sort(cudaTools.begin(), cudaTools.end(), + cmSystemTools::VersionCompareGreater); + this->GeneratorToolsetCuda = cudaTools.at(0); + } + } + if (const char* toolset = this->GetPlatformToolset()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset); } if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) { mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch); } + if (const char* cuda = this->GetPlatformToolsetCuda()) { + mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda); + } return true; } bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( std::string const& ts, cmMakefile* mf) { - if (ts.find_first_of(",=") != ts.npos) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "does not recognize the toolset\n" - " " << ts << "\n" - "that was specified."; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; + std::vector const fields = cmSystemTools::tokenize(ts, ","); + std::vector::const_iterator fi = fields.begin(); + if (fi == fields.end()) { + return true; + } + + // The first field may be the VS platform toolset. + if (fi->find('=') == fi->npos) { + this->GeneratorToolset = *fi; + ++fi; + } + + std::set handled; + + // The rest of the fields must be key=value pairs. + for (; fi != fields.end(); ++fi) { + std::string::size_type pos = fi->find('='); + if (pos == fi->npos) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains a field after the first ',' with no '='." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + std::string const key = fi->substr(0, pos); + std::string const value = fi->substr(pos + 1); + if (!handled.insert(key).second) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains duplicate field key '" << key << "'." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + if (!this->ProcessGeneratorToolsetField(key, value)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains invalid field '" << *fi << "'." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } } - this->GeneratorToolset = ts; return true; } +bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( + std::string const& key, std::string const& value) +{ + if (key == "cuda") { + this->GeneratorToolsetCuda = value; + return true; + } + return false; +} + bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) { if (this->SystemName == "Windows") { @@ -354,6 +478,16 @@ void cmGlobalVisualStudio10Generator::Generate() void cmGlobalVisualStudio10Generator::EnableLanguage( std::vector const& lang, cmMakefile* mf, bool optional) { + for (std::vector::const_iterator it = lang.begin(); + it != lang.end(); ++it) { + if (*it == "ASM_NASM") { + this->NasmEnabled = true; + } + if (*it == "CUDA") { + this->CudaEnabled = true; + } + } + this->AddPlatformDefinitions(mf); cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); } @@ -388,6 +522,20 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const return CM_NULLPTR; } +const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const +{ + if (!this->GeneratorToolsetCuda.empty()) { + return this->GeneratorToolsetCuda.c_str(); + } + return CM_NULLPTR; +} + +std::string const& +cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const +{ + return this->GeneratorToolsetCuda; +} + bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf) { if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) { @@ -442,6 +590,208 @@ std::string cmGlobalVisualStudio10Generator::FindDevEnvCommand() return this->cmGlobalVisualStudio71Generator::FindDevEnvCommand(); } +bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) +{ + // Skip this in special cases within our own test suite. + if (this->GetPlatformName() == "Test Platform" || + this->GetPlatformToolsetString() == "Test Toolset") { + return true; + } + + std::string wd; + if (!this->ConfiguredFilesPath.empty()) { + // In a try-compile we are given the outer CMakeFiles directory. + wd = this->ConfiguredFilesPath; + } else { + wd = this->GetCMakeInstance()->GetHomeOutputDirectory(); + wd += cmake::GetCMakeFilesDirectory(); + } + wd += "/"; + wd += cmVersion::GetCMakeVersion(); + + // We record the result persistently in a file. + std::string const txt = wd + "/VCTargetsPath.txt"; + + // If we have a recorded result, use it. + { + cmsys::ifstream fin(txt.c_str()); + if (fin && cmSystemTools::GetLineFromStream(fin, this->VCTargetsPath) && + cmSystemTools::FileIsDirectory(this->VCTargetsPath)) { + cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath); + return true; + } + } + + // Prepare the work directory. + if (!cmSystemTools::MakeDirectory(wd)) { + std::string e = "Failed to make directory:\n " + wd; + mf->IssueMessage(cmake::FATAL_ERROR, e.c_str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + // Generate a project file for MSBuild to tell us the VCTargetsPath value. + std::string const vcxproj = "VCTargetsPath.vcxproj"; + { + std::string const vcxprojAbs = wd + "/" + vcxproj; + cmsys::ofstream fout(vcxprojAbs.c_str()); + cmXMLWriter xw(fout); + + /* clang-format off */ + xw.StartDocument(); + xw.StartElement("Project"); + xw.Attribute("DefaultTargets", "Build"); + xw.Attribute("ToolsVersion", "4.0"); + xw.Attribute("xmlns", + "http://schemas.microsoft.com/developer/msbuild/2003"); + if (this->IsNsightTegra()) { + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "NsightTegraProject"); + xw.StartElement("NsightTegraProjectRevisionNumber"); + xw.Content("6"); + xw.EndElement(); // NsightTegraProjectRevisionNumber + xw.EndElement(); // PropertyGroup + } + xw.StartElement("ItemGroup"); + xw.Attribute("Label", "ProjectConfigurations"); + xw.StartElement("ProjectConfiguration"); + xw.Attribute("Include", "Debug|" + this->GetPlatformName()); + xw.StartElement("Configuration"); + xw.Content("Debug"); + xw.EndElement(); // Configuration + xw.StartElement("Platform"); + xw.Content(this->GetPlatformName()); + xw.EndElement(); // Platform + xw.EndElement(); // ProjectConfiguration + xw.EndElement(); // ItemGroup + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "Globals"); + xw.StartElement("ProjectGuid"); + xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}"); + xw.EndElement(); // ProjectGuid + xw.StartElement("Keyword"); + xw.Content("Win32Proj"); + xw.EndElement(); // Keyword + xw.StartElement("Platform"); + xw.Content(this->GetPlatformName()); + xw.EndElement(); // Platform + if (this->GetSystemName() == "WindowsPhone") { + xw.StartElement("ApplicationType"); + xw.Content("Windows Phone"); + xw.EndElement(); // ApplicationType + xw.StartElement("ApplicationTypeRevision"); + xw.Content(this->GetSystemVersion()); + xw.EndElement(); // ApplicationTypeRevision + } else if (this->GetSystemName() == "WindowsStore") { + xw.StartElement("ApplicationType"); + xw.Content("Windows Store"); + xw.EndElement(); // ApplicationType + xw.StartElement("ApplicationTypeRevision"); + xw.Content(this->GetSystemVersion()); + xw.EndElement(); // ApplicationTypeRevision + } + if (!this->WindowsTargetPlatformVersion.empty()) { + xw.StartElement("WindowsTargetPlatformVersion"); + xw.Content(this->WindowsTargetPlatformVersion); + xw.EndElement(); // WindowsTargetPlatformVersion + } + if (this->GetPlatformName() == "ARM") { + xw.StartElement("WindowsSDKDesktopARMSupport"); + xw.Content("true"); + xw.EndElement(); // WindowsSDKDesktopARMSupport + } + xw.EndElement(); // PropertyGroup + xw.StartElement("Import"); + xw.Attribute("Project", + "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); + xw.EndElement(); // Import + if (!this->GeneratorToolsetHostArchitecture.empty()) { + xw.StartElement("PropertyGroup"); + xw.StartElement("PreferredToolArchitecture"); + xw.Content(this->GeneratorToolsetHostArchitecture); + xw.EndElement(); // PreferredToolArchitecture + xw.EndElement(); // PropertyGroup + } + xw.StartElement("PropertyGroup"); + xw.Attribute("Label", "Configuration"); + xw.StartElement("ConfigurationType"); + if (this->IsNsightTegra()) { + // Tegra-Android platform does not understand "Utility". + xw.Content("StaticLibrary"); + } else { + xw.Content("Utility"); + } + xw.EndElement(); // ConfigurationType + xw.StartElement("CharacterSet"); + xw.Content("MultiByte"); + xw.EndElement(); // CharacterSet + if (this->IsNsightTegra()) { + xw.StartElement("NdkToolchainVersion"); + xw.Content(this->GetPlatformToolsetString()); + xw.EndElement(); // NdkToolchainVersion + } else { + xw.StartElement("PlatformToolset"); + xw.Content(this->GetPlatformToolsetString()); + xw.EndElement(); // PlatformToolset + } + xw.EndElement(); // PropertyGroup + xw.StartElement("Import"); + xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"); + xw.EndElement(); // Import + xw.StartElement("ItemDefinitionGroup"); + xw.StartElement("PostBuildEvent"); + xw.StartElement("Command"); + xw.Content("echo VCTargetsPath=$(VCTargetsPath)"); + xw.EndElement(); // Command + xw.EndElement(); // PostBuildEvent + xw.EndElement(); // ItemDefinitionGroup + xw.StartElement("Import"); + xw.Attribute("Project", + "$(VCTargetsPath)\\Microsoft.Cpp.targets"); + xw.EndElement(); // Import + xw.EndElement(); // Project + xw.EndDocument(); + /* clang-format on */ + } + + std::vector cmd; + cmd.push_back(this->GetMSBuildCommand()); + cmd.push_back(vcxproj); + cmd.push_back(std::string("/p:VisualStudioVersion=") + + this->GetIDEVersion()); + std::string out; + int ret = 0; + cmsys::RegularExpression regex("\n *VCTargetsPath=([^%\r\n]+)[\r\n]"); + if (!cmSystemTools::RunSingleCommand(cmd, &out, &out, &ret, wd.c_str(), + cmSystemTools::OUTPUT_NONE) || + ret != 0 || !regex.find(out)) { + cmSystemTools::ReplaceString(out, "\n", "\n "); + std::ostringstream e; + /* clang-format off */ + e << + "Failed to run MSBuild command:\n" + " " << cmd[0] << "\n" + "to get the value of VCTargetsPath:\n" + " " << out << "\n" + ; + /* clang-format on */ + if (ret != 0) { + e << "Exit code: " << ret << "\n"; + } + mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + this->VCTargetsPath = regex.match(1); + cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath); + + { + cmsys::ofstream fout(txt.c_str()); + fout << this->VCTargetsPath << "\n"; + } + return true; +} + void cmGlobalVisualStudio10Generator::GenerateBuildCommand( std::vector& makeCommand, const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, @@ -656,6 +1006,17 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const return (table != CM_NULLPTR) ? table : this->DefaultLinkFlagTable; } +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const +{ + return this->DefaultCudaFlagTable; +} + +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable() + const +{ + return this->DefaultCudaHostFlagTable; +} + cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const { cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable( @@ -663,3 +1024,8 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const return (table != CM_NULLPTR) ? table : this->DefaultMasmFlagTable; } + +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const +{ + return this->DefaultNasmFlagTable; +} diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 5bfaf3848..4a5c2454b 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -23,7 +23,6 @@ public: virtual bool SetSystemName(std::string const& s, cmMakefile* mf); virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); - virtual bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); virtual void GenerateBuildCommand( std::vector& makeCommand, const std::string& makeProgram, @@ -43,6 +42,8 @@ public: cmMakefile*, bool optional); virtual void WriteSLNHeader(std::ostream& fout); + bool IsCudaEnabled() const { return this->CudaEnabled; } + /** Generating for Nsight Tegra VS plugin? */ bool IsNsightTegra() const; std::string GetNsightTegraVersion() const; @@ -54,6 +55,17 @@ public: /** The toolset host architecture name (e.g. x64 for 64-bit host tools). */ const char* GetPlatformToolsetHostArchitecture() const; + /** The cuda toolset version. */ + const char* GetPlatformToolsetCuda() const; + std::string const& GetPlatformToolsetCudaString() const; + + /** Return whether we need to use No/Debug instead of false/true + for GenerateDebugInformation. */ + bool GetPlatformToolsetNeedsDebugEnum() const + { + return this->PlatformToolsetNeedsDebugEnum; + } + /** Return the CMAKE_SYSTEM_NAME. */ std::string const& GetSystemName() const { return this->SystemName; } @@ -95,7 +107,10 @@ public: cmIDEFlagTable const* GetRcFlagTable() const; cmIDEFlagTable const* GetLibFlagTable() const; cmIDEFlagTable const* GetLinkFlagTable() const; + cmIDEFlagTable const* GetCudaFlagTable() const; + cmIDEFlagTable const* GetCudaHostFlagTable() const; cmIDEFlagTable const* GetMasmFlagTable() const; + cmIDEFlagTable const* GetNasmFlagTable() const; protected: virtual void Generate(); @@ -105,6 +120,9 @@ protected: virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual bool ProcessGeneratorToolsetField(std::string const& key, + std::string const& value); + virtual std::string SelectWindowsCEToolset() const; virtual bool SelectWindowsPhoneToolset(std::string& toolset) const; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; @@ -115,6 +133,7 @@ protected: std::string GeneratorToolset; std::string GeneratorToolsetHostArchitecture; + std::string GeneratorToolsetCuda; std::string DefaultPlatformToolset; std::string WindowsTargetPlatformVersion; std::string SystemName; @@ -124,7 +143,10 @@ protected: cmIDEFlagTable const* DefaultCSharpFlagTable; cmIDEFlagTable const* DefaultLibFlagTable; cmIDEFlagTable const* DefaultLinkFlagTable; + cmIDEFlagTable const* DefaultCudaFlagTable; + cmIDEFlagTable const* DefaultCudaHostFlagTable; cmIDEFlagTable const* DefaultMasmFlagTable; + cmIDEFlagTable const* DefaultNasmFlagTable; cmIDEFlagTable const* DefaultRcFlagTable; bool SystemIsWindowsCE; bool SystemIsWindowsPhone; @@ -154,6 +176,15 @@ private: virtual std::string FindDevEnvCommand(); virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); } + bool PlatformToolsetNeedsDebugEnum; + + bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + + std::string VCTargetsPath; + bool FindVCTargetsPath(cmMakefile* mf); + + bool CudaEnabled; + // We do not use the reload macros for VS >= 10. virtual std::string GetUserMacrosDirectory() { return ""; } }; diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index ae994087f..b4b327d8a 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalVisualStudio11Generator_h #define cmGlobalVisualStudio11Generator_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index 2656dccf8..de62ff0ac 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -109,19 +109,15 @@ bool cmGlobalVisualStudio12Generator::MatchesGeneratorName( return false; } -bool cmGlobalVisualStudio12Generator::ParseGeneratorToolset( - std::string const& ts, cmMakefile* mf) +bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField( + std::string const& key, std::string const& value) { - std::string::size_type ts_end = ts.size(); - if (cmHasLiteralSuffix(ts, ",host=x64")) { + if (key == "host" && value == "x64") { this->GeneratorToolsetHostArchitecture = "x64"; - ts_end -= 9; - } else if (ts == "host=x64") { - this->GeneratorToolsetHostArchitecture = "x64"; - ts_end = 0; + return true; } - return this->cmGlobalVisualStudio11Generator::ParseGeneratorToolset( - ts.substr(0, ts_end), mf); + return this->cmGlobalVisualStudio11Generator::ProcessGeneratorToolsetField( + key, value); } bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf) diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 79efe521d..ebc95bb63 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalVisualStudio12Generator_h #define cmGlobalVisualStudio12Generator_h -#include +#include "cmConfigure.h" #include #include @@ -31,8 +31,8 @@ public: // version number virtual const char* GetToolsVersion() { return "12.0"; } protected: - bool ParseGeneratorToolset(std::string const& ts, - cmMakefile* mf) CM_OVERRIDE; + bool ProcessGeneratorToolsetField(std::string const& key, + std::string const& value) CM_OVERRIDE; virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 81c305c8c..c8cf02cdd 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -8,8 +8,8 @@ #include "cmMakefile.h" #include "cmVS140CLFlagTable.h" #include "cmVS140CSharpFlagTable.h" +#include "cmVS140LinkFlagTable.h" #include "cmVS14LibFlagTable.h" -#include "cmVS14LinkFlagTable.h" #include "cmVS14MASMFlagTable.h" #include "cmVS14RCFlagTable.h" @@ -93,7 +93,7 @@ cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( this->DefaultClFlagTable = cmVS140CLFlagTable; this->DefaultCSharpFlagTable = cmVS140CSharpFlagTable; this->DefaultLibFlagTable = cmVS14LibFlagTable; - this->DefaultLinkFlagTable = cmVS14LinkFlagTable; + this->DefaultLinkFlagTable = cmVS140LinkFlagTable; this->DefaultMasmFlagTable = cmVS14MASMFlagTable; this->DefaultRcFlagTable = cmVS14RCFlagTable; this->Version = VS14; @@ -217,29 +217,48 @@ struct NoWindowsH std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() { #if defined(_WIN32) && !defined(__CYGWIN__) - // This logic is taken from the vcvarsqueryregistry.bat file from VS2015 - // Try HKLM and then HKCU. - std::string win10Root; - if (!cmSystemTools::ReadRegistryValue( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot10", - win10Root, cmSystemTools::KeyWOW64_32) && - !cmSystemTools::ReadRegistryValue( - "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" - "Windows Kits\\Installed Roots;KitsRoot10", - win10Root, cmSystemTools::KeyWOW64_32)) { + std::vector win10Roots; + + { + std::string win10Root; + if (cmSystemTools::GetEnv("CMAKE_WINDOWS_KITS_10_DIR", win10Root)) { + cmSystemTools::ConvertToUnixSlashes(win10Root); + win10Roots.push_back(win10Root); + } + } + + { + // This logic is taken from the vcvarsqueryregistry.bat file from VS2015 + // Try HKLM and then HKCU. + std::string win10Root; + if (cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot10", + win10Root, cmSystemTools::KeyWOW64_32) || + cmSystemTools::ReadRegistryValue( + "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot10", + win10Root, cmSystemTools::KeyWOW64_32)) { + cmSystemTools::ConvertToUnixSlashes(win10Root); + win10Roots.push_back(win10Root); + } + } + + if (win10Roots.empty()) { return std::string(); } std::vector sdks; - std::string path = win10Root + "Include/*"; // Grab the paths of the different SDKs that are installed - cmSystemTools::GlobDirs(path, sdks); + for (std::vector::iterator i = win10Roots.begin(); + i != win10Roots.end(); ++i) { + std::string path = *i + "/Include/*"; + cmSystemTools::GlobDirs(path, sdks); + } // Skip SDKs that do not contain because that indicates that // only the UCRT MSIs were installed for them. - sdks.erase(std::remove_if(sdks.begin(), sdks.end(), NoWindowsH()), - sdks.end()); + cmEraseIf(sdks, NoWindowsH()); if (!sdks.empty()) { // Only use the filename, which will be the SDK version. diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index ab22978fc..0ce9a5641 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalVisualStudio14Generator_h #define cmGlobalVisualStudio14Generator_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index 2312bc05b..ce1ba007f 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -8,6 +8,7 @@ #include "cmMakefile.h" #include "cmVS141CLFlagTable.h" #include "cmVS141CSharpFlagTable.h" +#include "cmVS141LinkFlagTable.h" #include "cmVSSetupHelper.h" static const char vs15generatorName[] = "Visual Studio 15 2017"; @@ -85,6 +86,7 @@ cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator( this->DefaultPlatformToolset = "v141"; this->DefaultClFlagTable = cmVS141CLFlagTable; this->DefaultCSharpFlagTable = cmVS141CSharpFlagTable; + this->DefaultLinkFlagTable = cmVS141LinkFlagTable; this->Version = VS15; } @@ -164,7 +166,7 @@ bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" "Windows Kits\\Installed Roots;KitsRoot81", win81Root, cmSystemTools::KeyWOW64_32)) { - return true; + return cmSystemTools::FileExists(win81Root + "/um/windows.h", true); } return false; } diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index f979b65c0..4be88f44f 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalVisualStudio15Generator_h #define cmGlobalVisualStudio15Generator_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 55a788f0d..aeceb8deb 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -13,58 +13,6 @@ cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator( : cmGlobalVisualStudio7Generator(cm, platformName) { this->ProjectConfigurationSectionName = "ProjectConfiguration"; - this->Version = VS71; -} - -std::string cmGlobalVisualStudio71Generator::GetUserMacrosDirectory() -{ - // Macros not supported on Visual Studio 7.1 and earlier because - // they do not appear to work *during* a build when called by an - // outside agent... - // - return ""; - -#if 0 - // - // The COM result from calling a Visual Studio macro with 7.1 indicates - // that the call succeeds, but the macro does not appear to execute... - // - // So, I am leaving this code here to show how to do it, but have not - // yet figured out what the issue is in terms of why the macro does not - // appear to execute... - // - std::string base; - std::string path; - - // base begins with the VisualStudioProjectsLocation reg value... - if (cmSystemTools::ReadRegistryValue( - "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\7.1;" - "VisualStudioProjectsLocation", - base)) - { - cmSystemTools::ConvertToUnixSlashes(base); - - // 7.1 macros folder: - path = base + "/VSMacros71"; - } - - // path is (correctly) still empty if we did not read the base value from - // the Registry value - return path; -#endif -} - -std::string cmGlobalVisualStudio71Generator::GetUserMacrosRegKeyBase() -{ - // Macros not supported on Visual Studio 7.1 and earlier because - // they do not appear to work *during* a build when called by an - // outside agent... - // - return ""; - -#if 0 - return "Software\\Microsoft\\VisualStudio\\7.1\\vsmacros"; -#endif } void cmGlobalVisualStudio71Generator::WriteSLNFile( @@ -91,11 +39,6 @@ void cmGlobalVisualStudio71Generator::WriteSLNFile( std::ostringstream targetsSlnString; this->WriteTargetsToSolution(targetsSlnString, root, orderedProjectTargets); - // VS 7 does not support folders specified first. - if (this->GetVersion() <= VS71) { - fout << targetsSlnString.str(); - } - // Generate folder specification. bool useFolderProperty = this->UseFolderProperty(); if (useFolderProperty) { @@ -103,9 +46,7 @@ void cmGlobalVisualStudio71Generator::WriteSLNFile( } // Now write the actual target specification content. - if (this->GetVersion() > VS71) { - fout << targetsSlnString.str(); - } + fout << targetsSlnString.str(); // Write out the configurations information for the solution fout << "Global\n"; @@ -249,7 +190,7 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject( // Write a dsp file into the SLN file, Note, that dependencies from // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteProjectConfigurations( - std::ostream& fout, const std::string& name, cmStateEnums::TargetType, + std::ostream& fout, const std::string& name, cmGeneratorTarget const& target, std::vector const& configs, const std::set& configsPartOfDefaultBuild, std::string const& platformMapping) @@ -259,13 +200,18 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations( std::string guid = this->GetGUID(name); for (std::vector::const_iterator i = configs.begin(); i != configs.end(); ++i) { - fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << *i << "|" - << platformName << std::endl; + const char* dstConfig = target.GetProperty("MAP_IMPORTED_CONFIG_" + + cmSystemTools::UpperCase(*i)); + if (dstConfig == CM_NULLPTR) { + dstConfig = i->c_str(); + } + fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << dstConfig + << "|" << platformName << std::endl; std::set::const_iterator ci = configsPartOfDefaultBuild.find(*i); if (!(ci == configsPartOfDefaultBuild.end())) { - fout << "\t\t{" << guid << "}." << *i << ".Build.0 = " << *i << "|" - << platformName << std::endl; + fout << "\t\t{" << guid << "}." << *i << ".Build.0 = " << dstConfig + << "|" << platformName << std::endl; } } } @@ -275,10 +221,3 @@ void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout) { fout << "Microsoft Visual Studio Solution File, Format Version 8.00\n"; } - -void cmGlobalVisualStudio71Generator::GetDocumentation( - cmDocumentationEntry& entry) -{ - entry.Name = cmGlobalVisualStudio71Generator::GetActualName(); - entry.Brief = "Deprecated. Generates Visual Studio .NET 2003 project files."; -} diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 99530479e..0ce02aa46 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -15,37 +15,8 @@ class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator public: cmGlobalVisualStudio71Generator(cmake* cm, const std::string& platformName = ""); - static cmGlobalGeneratorFactory* NewFactory() - { - return new cmGlobalGeneratorSimpleFactory< - cmGlobalVisualStudio71Generator>(); - } - - ///! Get the name for the generator. - virtual std::string GetName() const - { - return cmGlobalVisualStudio71Generator::GetActualName(); - } - static std::string GetActualName() { return "Visual Studio 7 .NET 2003"; } - - /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); - - /** - * Where does this version of Visual Studio look for macros for the - * current user? Returns the empty string if this version of Visual - * Studio does not implement support for VB macros. - */ - virtual std::string GetUserMacrosDirectory(); - - /** - * What is the reg key path to "vsmacros" for this version of Visual - * Studio? - */ - virtual std::string GetUserMacrosRegKeyBase(); protected: - virtual const char* GetIDEVersion() { return "7.1"; } virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, std::vector& generators); virtual void WriteSolutionConfigurations( @@ -56,8 +27,8 @@ protected: const char* path, cmGeneratorTarget const* t); virtual void WriteProjectConfigurations( - std::ostream& fout, const std::string& name, cmStateEnums::TargetType type, - std::vector const& configs, + std::ostream& fout, const std::string& name, + cmGeneratorTarget const& target, std::vector const& configs, const std::set& configsPartOfDefaultBuild, const std::string& platformMapping = ""); virtual void WriteExternalProject(std::ostream& fout, diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 602666ee2..b155f5b55 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -1,7 +1,5 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include "windows.h" // this must be first to define GetCurrentDirectory - #include "cmGlobalVisualStudio7Generator.h" #include "cmGeneratedFileStream.h" @@ -11,9 +9,11 @@ #include "cmState.h" #include "cmUuid.h" #include "cmake.h" -#include +#include "cmsys/Encoding.hxx" #include +#include +#include static cmVS7FlagTable cmVS7ExtraFlagTable[] = { // Precompiled header and related options. Note that the @@ -47,6 +47,7 @@ cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( this->IntelProjectVersion = 0; this->DevEnvCommandInitialized = false; this->MasmEnabled = false; + this->NasmEnabled = false; if (platformName.empty()) { this->DefaultPlatformName = "Win32"; @@ -54,7 +55,6 @@ cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( this->DefaultPlatformName = platformName; } this->ExtraFlagTable = cmVS7ExtraFlagTable; - this->Version = VS7; } cmGlobalVisualStudio7Generator::~cmGlobalVisualStudio7Generator() @@ -295,16 +295,16 @@ void cmGlobalVisualStudio7Generator::Generate() this->CallVisualStudioMacro(MacroReload); } - if (this->Version == VS71 && !this->CMakeInstance->GetIsInTryCompile()) { - const char* cmakeWarnVS71 = - this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS71"); - if (!cmakeWarnVS71 || !cmSystemTools::IsOff(cmakeWarnVS71)) { + if (this->Version == VS8 && !this->CMakeInstance->GetIsInTryCompile()) { + const char* cmakeWarnVS8 = + this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS8"); + if (!cmakeWarnVS8 || !cmSystemTools::IsOff(cmakeWarnVS8)) { this->CMakeInstance->IssueMessage( cmake::WARNING, - "The \"Visual Studio 7 .NET 2003\" generator is deprecated " + "The \"Visual Studio 8 2005\" generator is deprecated " "and will be removed in a future version of CMake." "\n" - "Add CMAKE_WARN_VS71=OFF to the cache to disable this warning."); + "Add CMAKE_WARN_VS8=OFF to the cache to disable this warning."); } } } @@ -356,16 +356,16 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( if (expath) { std::set allConfigurations(configs.begin(), configs.end()); const char* mapping = target->GetProperty("VS_PLATFORM_MAPPING"); - this->WriteProjectConfigurations( - fout, target->GetName().c_str(), target->GetType(), configs, - allConfigurations, mapping ? mapping : ""); + this->WriteProjectConfigurations(fout, target->GetName().c_str(), + *target, configs, allConfigurations, + mapping ? mapping : ""); } else { const std::set& configsPartOfDefaultBuild = this->IsPartOfDefaultBuild(configs, projectTargets, target); const char* vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) { - this->WriteProjectConfigurations(fout, vcprojName, target->GetType(), - configs, configsPartOfDefaultBuild); + this->WriteProjectConfigurations(fout, vcprojName, *target, configs, + configsPartOfDefaultBuild); } } } @@ -520,6 +520,7 @@ std::string cmGlobalVisualStudio7Generator::ConvertToSolutionPath( void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( std::ostream& fout, cmLocalGenerator* root) { + std::string const guid = this->GetGUID(root->GetProjectName() + ".sln"); bool extensibilityGlobalsOverridden = false; bool extensibilityAddInsOverridden = false; const std::vector propKeys = @@ -538,11 +539,14 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( } else continue; if (!name.empty()) { - if (name == "ExtensibilityGlobals" && sectionType == "postSolution") + bool addGuid = false; + if (name == "ExtensibilityGlobals" && sectionType == "postSolution") { + addGuid = true; extensibilityGlobalsOverridden = true; - else if (name == "ExtensibilityAddIns" && - sectionType == "postSolution") + } else if (name == "ExtensibilityAddIns" && + sectionType == "postSolution") { extensibilityAddInsOverridden = true; + } fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n"; std::vector keyValuePairs; cmSystemTools::ExpandListArgument( @@ -557,15 +561,23 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( const std::string value = cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1)); fout << "\t\t" << key << " = " << value << "\n"; + if (key == "SolutionGuid") { + addGuid = false; + } } } + if (addGuid) { + fout << "\t\tSolutionGuid = {" << guid << "}\n"; + } fout << "\tEndGlobalSection\n"; } } } - if (!extensibilityGlobalsOverridden) + if (!extensibilityGlobalsOverridden) { fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n" + << "\t\tSolutionGuid = {" << guid << "}\n" << "\tEndGlobalSection\n"; + } if (!extensibilityAddInsOverridden) fout << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n" << "\tEndGlobalSection\n"; @@ -681,10 +693,10 @@ std::set cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( // default build if another target depends on it int type = target->GetType(); if (type == cmStateEnums::GLOBAL_TARGET) { - std::list targetNames; + std::vector targetNames; targetNames.push_back("INSTALL"); targetNames.push_back("PACKAGE"); - for (std::list::const_iterator t = targetNames.begin(); + for (std::vector::const_iterator t = targetNames.begin(); t != targetNames.end(); ++t) { // check if target <*t> is part of default build if (target->GetName() == *t) { diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 62194c383..32a8d6056 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -95,6 +95,7 @@ public: /** Is the Microsoft Assembler enabled? */ bool IsMasmEnabled() const { return this->MasmEnabled; } + bool IsNasmEnabled() const { return this->NasmEnabled; } // Encoding for Visual Studio files virtual std::string Encoding(); @@ -120,8 +121,8 @@ protected: const char* path, cmGeneratorTarget const* t) = 0; virtual void WriteProjectConfigurations( - std::ostream& fout, const std::string& name, cmStateEnums::TargetType type, - std::vector const& configs, + std::ostream& fout, const std::string& name, + cmGeneratorTarget const& target, std::vector const& configs, const std::set& configsPartOfDefaultBuild, const std::string& platformMapping = "") = 0; virtual void WriteSLNGlobalSections(std::ostream& fout, @@ -163,6 +164,7 @@ protected: std::string GeneratorPlatform; std::string DefaultPlatformName; bool MasmEnabled; + bool NasmEnabled; private: char* IntelProjectVersion; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 8353a3f31..7a42b72e8 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -54,7 +54,7 @@ public: void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE { entry.Name = std::string(vs8generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2005 project files. " + entry.Brief = "Deprecated. Generates Visual Studio 2005 project files. " "Optional [arch] can be \"Win64\"."; } @@ -153,13 +153,6 @@ void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout) fout << "# Visual Studio 2005\n"; } -void cmGlobalVisualStudio8Generator::GetDocumentation( - cmDocumentationEntry& entry) -{ - entry.Name = cmGlobalVisualStudio8Generator::GetActualName(); - entry.Brief = "Generates Visual Studio 8 2005 project files."; -} - std::string cmGlobalVisualStudio8Generator::GetGenerateStampList() { return "generate.stamp.list"; @@ -353,7 +346,7 @@ void cmGlobalVisualStudio8Generator::WriteSolutionConfigurations( } void cmGlobalVisualStudio8Generator::WriteProjectConfigurations( - std::ostream& fout, const std::string& name, cmStateEnums::TargetType type, + std::ostream& fout, const std::string& name, cmGeneratorTarget const& target, std::vector const& configs, const std::set& configsPartOfDefaultBuild, std::string const& platformMapping) @@ -361,8 +354,13 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations( std::string guid = this->GetGUID(name); for (std::vector::const_iterator i = configs.begin(); i != configs.end(); ++i) { + const char* dstConfig = target.GetProperty("MAP_IMPORTED_CONFIG_" + + cmSystemTools::UpperCase(*i)); + if (dstConfig == CM_NULLPTR) { + dstConfig = i->c_str(); + } fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName() - << ".ActiveCfg = " << *i << "|" + << ".ActiveCfg = " << dstConfig << "|" << (!platformMapping.empty() ? platformMapping : this->GetPlatformName()) << "\n"; @@ -370,14 +368,14 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations( configsPartOfDefaultBuild.find(*i); if (!(ci == configsPartOfDefaultBuild.end())) { fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName() - << ".Build.0 = " << *i << "|" + << ".Build.0 = " << dstConfig << "|" << (!platformMapping.empty() ? platformMapping : this->GetPlatformName()) << "\n"; } - if (this->NeedsDeploy(type)) { + if (this->NeedsDeploy(target.GetType())) { fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName() - << ".Deploy.0 = " << *i << "|" + << ".Deploy.0 = " << dstConfig << "|" << (!platformMapping.empty() ? platformMapping : this->GetPlatformName()) << "\n"; diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 53feb4740..4723b83ba 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -20,9 +20,6 @@ public: ///! Get the name for the generator. virtual std::string GetName() const { return this->Name; } - /** Get the documentation entry for this generator. */ - static void GetDocumentation(cmDocumentationEntry& entry); - /** Get the name of the main stamp list file. */ static std::string GetGenerateStampList(); @@ -82,8 +79,8 @@ protected: virtual void WriteSolutionConfigurations( std::ostream& fout, std::vector const& configs); virtual void WriteProjectConfigurations( - std::ostream& fout, const std::string& name, cmStateEnums::TargetType type, - std::vector const& configs, + std::ostream& fout, const std::string& name, + cmGeneratorTarget const& target, std::vector const& configs, const std::set& configsPartOfDefaultBuild, const std::string& platformMapping = ""); virtual bool ComputeTargetDepends(); diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index ced0c266b..87a22d1dc 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -3,8 +3,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalVisualStudioGenerator.h" -#include +#include "cmsys/Encoding.hxx" #include +#include #include "cmAlgorithms.h" #include "cmCallVisualStudioMacro.h" @@ -19,6 +20,7 @@ cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm) : cmGlobalGenerator(cm) { + cm->GetState()->SetIsGeneratorMultiConfig(true); cm->GetState()->SetWindowsShell(true); cm->GetState()->SetWindowsVSIDE(true); } @@ -441,8 +443,6 @@ std::string cmGlobalVisualStudioGenerator::GetStartupProjectName( return this->GetAllTargetName(); } -#include - bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, const std::string& regKeyBase, std::string& nextAvailableSubKeyName) @@ -730,12 +730,26 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( return false; } } + // If there's only one source language, Fortran has to be used + // in order for the sources to compile. + // Note: Via linker propagation, LINKER_LANGUAGE could become CXX in + // this situation and mismatch from the actual language of the linker. gt->GetLanguages(languages, ""); if (languages.size() == 1) { if (*languages.begin() == "Fortran") { return true; } } + + // In the case of mixed object files or sources mixed with objects, + // decide the language based on the value of LINKER_LANGUAGE. + // This will not make it possible to mix source files of different + // languages, but object libraries will be linked together in the + // same fashion as other generators do. + if (gt->GetLinkerLanguage("") == "Fortran") { + return true; + } + return false; } @@ -814,10 +828,14 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( cmGeneratorTarget* gt, std::vector& commands, std::string const& configName) { + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + gt->GetModuleDefinitionInfo(configName); + if (!mdi || !mdi->DefFileGenerated) { + return; + } + std::vector outputs; - std::string deffile = gt->ObjectDirectory; - deffile += "/exportall.def"; - outputs.push_back(deffile); + outputs.push_back(mdi->DefFile); std::vector empty; std::vector objectSources; gt->GetObjectSources(objectSources, configName); @@ -835,50 +853,58 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( cmdl.push_back(cmakeCommand); cmdl.push_back("-E"); cmdl.push_back("__create_def"); - cmdl.push_back(deffile); + cmdl.push_back(mdi->DefFile); std::string obj_dir_expanded = obj_dir; cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(), configName.c_str()); - std::string objs_file = obj_dir_expanded; - cmSystemTools::MakeDirectory(objs_file.c_str()); - objs_file += "/objects.txt"; + cmSystemTools::MakeDirectory(obj_dir_expanded); + std::string const objs_file = obj_dir_expanded + "/objects.txt"; cmdl.push_back(objs_file); cmGeneratedFileStream fout(objs_file.c_str()); if (!fout) { cmSystemTools::Error("could not open ", objs_file.c_str()); return; } - std::vector objs; - for (std::vector::const_iterator it = - objectSources.begin(); - it != objectSources.end(); ++it) { - // Find the object file name corresponding to this source file. - std::map::const_iterator map_it = - mapping.find(*it); - // It must exist because we populated the mapping just above. - assert(!map_it->second.empty()); - std::string objFile = obj_dir + map_it->second; - objs.push_back(objFile); - } - std::vector externalObjectSources; - gt->GetExternalObjects(externalObjectSources, configName); - for (std::vector::const_iterator it = - externalObjectSources.begin(); - it != externalObjectSources.end(); ++it) { - objs.push_back((*it)->GetFullPath()); - } - gt->UseObjectLibraries(objs, configName); - for (std::vector::iterator it = objs.begin(); it != objs.end(); - ++it) { - std::string objFile = *it; - // replace $(ConfigurationName) in the object names - cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(), - configName.c_str()); - if (cmHasLiteralSuffix(objFile, ".obj")) { - fout << objFile << "\n"; + if (mdi->WindowsExportAllSymbols) { + std::vector objs; + for (std::vector::const_iterator it = + objectSources.begin(); + it != objectSources.end(); ++it) { + // Find the object file name corresponding to this source file. + std::map::const_iterator map_it = + mapping.find(*it); + // It must exist because we populated the mapping just above. + assert(!map_it->second.empty()); + std::string objFile = obj_dir + map_it->second; + objs.push_back(objFile); + } + std::vector externalObjectSources; + gt->GetExternalObjects(externalObjectSources, configName); + for (std::vector::const_iterator it = + externalObjectSources.begin(); + it != externalObjectSources.end(); ++it) { + objs.push_back((*it)->GetFullPath()); + } + + for (std::vector::iterator it = objs.begin(); + it != objs.end(); ++it) { + std::string objFile = *it; + // replace $(ConfigurationName) in the object names + cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(), + configName.c_str()); + if (cmHasLiteralSuffix(objFile, ".obj")) { + fout << objFile << "\n"; + } } } + + for (std::vector::const_iterator i = + mdi->Sources.begin(); + i != mdi->Sources.end(); ++i) { + fout << (*i)->GetFullPath() << "\n"; + } + cmCustomCommandLines commandLines; commandLines.push_back(cmdl); cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty, diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index f32f0bbe8..c12a93334 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalVisualStudioGenerator_h #define cmGlobalVisualStudioGenerator_h -#include +#include "cmConfigure.h" #include #include @@ -32,8 +32,6 @@ public: /** Known versions of Visual Studio. */ enum VSVersion { - VS7 = 70, - VS71 = 71, VS8 = 80, VS9 = 90, VS10 = 100, diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index 1c290f8ad..b2d6d5d71 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -3,7 +3,7 @@ #ifndef cmGlobalWatcomWMakeGenerator_h #define cmGlobalWatcomWMakeGenerator_h -#include +#include "cmConfigure.h" #include "cmGlobalGeneratorFactory.h" #include "cmGlobalUnixMakefileGenerator3.h" diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index dd771b1fb..3cd14e132 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalXCodeGenerator.h" +#include "cmsys/RegularExpression.hxx" #include -#include #include #include #include @@ -28,6 +28,7 @@ #include "cmTarget.h" #include "cmXCode21Object.h" #include "cmXCodeObject.h" +#include "cmXCodeScheme.h" #include "cm_auto_ptr.hxx" #include "cmake.h" @@ -132,24 +133,23 @@ public: bool SupportsPlatform() const CM_OVERRIDE { return false; } }; -cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(cmake* cm, - std::string const& version) +cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( + cmake* cm, std::string const& version_string, unsigned int version_number) : cmGlobalGenerator(cm) { - this->VersionString = version; - - // Compute an integer form of the version number. - unsigned int v[2] = { 0, 0 }; - sscanf(this->VersionString.c_str(), "%u.%u", &v[0], &v[1]); - this->XcodeVersion = 10 * v[0] + v[1]; + this->VersionString = version_string; + this->XcodeVersion = version_number; this->RootObject = 0; this->MainGroupChildren = 0; - this->SourcesGroupChildren = 0; - this->ResourcesGroupChildren = 0; this->CurrentMakefile = 0; this->CurrentLocalGenerator = 0; this->XcodeBuildCommandInitialized = false; + + this->ObjectDirArchDefault = "$(CURRENT_ARCH)"; + this->ObjectDirArch = this->ObjectDirArchDefault; + + cm->GetState()->SetIsGeneratorMultiConfig(true); } cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory() @@ -170,7 +170,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( std::string::size_type pos; if (cmSystemTools::RunSingleCommand("xcode-select --print-path", &out, 0, 0, 0, cmSystemTools::OUTPUT_NONE) && - (pos = out.find(".app/"), pos != out.npos)) { + (pos = out.find(".app/"), pos != std::string::npos)) { versionFile = out.substr(0, pos + 5) + "Contents/version.plist"; } } @@ -183,13 +183,21 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( parser.ParseFile( "/Developer/Applications/Xcode.app/Contents/version.plist"); } - CM_AUTO_PTR gg( - new cmGlobalXCodeGenerator(cm, parser.Version)); - if (gg->XcodeVersion == 20) { - cmSystemTools::Message("Xcode 2.0 not really supported by cmake, " - "using Xcode 15 generator\n"); - gg->XcodeVersion = 15; + std::string const& version_string = parser.Version; + + // Compute an integer form of the version number. + unsigned int v[2] = { 0, 0 }; + sscanf(version_string.c_str(), "%u.%u", &v[0], &v[1]); + unsigned int version_number = 10 * v[0] + v[1]; + + if (version_number < 30) { + cm->IssueMessage(cmake::FATAL_ERROR, + "Xcode " + version_string + " not supported."); + return CM_NULLPTR; } + + CM_AUTO_PTR gg( + new cmGlobalXCodeGenerator(cm, version_string, version_number)); return gg.release(); #else std::cerr << "CMake should be built with cmake to use Xcode, " @@ -236,29 +244,25 @@ std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand() bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, cmMakefile* mf) { - if (this->XcodeVersion >= 30) { - if (ts.find_first_of(",=") != ts.npos) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "does not recognize the toolset\n" - " " << ts << "\n" - "that was specified."; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - this->GeneratorToolset = ts; - if (!this->GeneratorToolset.empty()) { - mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", - this->GeneratorToolset.c_str()); - } - return true; - } else { - return cmGlobalGenerator::SetGeneratorToolset(ts, mf); + if (ts.find_first_of(",=") != std::string::npos) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "does not recognize the toolset\n" + " " << ts << "\n" + "that was specified."; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + this->GeneratorToolset = ts; + if (!this->GeneratorToolset.empty()) { + mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", + this->GeneratorToolset.c_str()); } + return true; } void cmGlobalXCodeGenerator::EnableLanguage( @@ -266,26 +270,17 @@ void cmGlobalXCodeGenerator::EnableLanguage( { mf->AddDefinition("XCODE", "1"); mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str()); - if (this->XcodeVersion == 15) { - } else { - if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", - "Semicolon separated list of supported configuration types, " - "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " - "anything else will be ignored.", - cmStateEnums::STRING); - } + if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { + mf->AddCacheDefinition( + "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", + "Semicolon separated list of supported configuration types, " + "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " + "anything else will be ignored.", + cmStateEnums::STRING); } mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); - const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES"); - const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); - if (osxArch && sysroot) { - this->Architectures.clear(); - cmSystemTools::ExpandListArgument(std::string(osxArch), - this->Architectures); - } + this->ComputeArchitectures(mf); } void cmGlobalXCodeGenerator::GenerateBuildCommand( @@ -301,9 +296,7 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand( makeCommand.push_back("-project"); std::string projectArg = projectName; projectArg += ".xcode"; - if (this->XcodeVersion > 20) { - projectArg += "proj"; - } + projectArg += "proj"; makeCommand.push_back(projectArg); bool clean = false; @@ -323,13 +316,8 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand( } else { makeCommand.push_back("ALL_BUILD"); } - if (this->XcodeVersion == 15) { - makeCommand.push_back("-buildstyle"); - makeCommand.push_back("Development"); - } else { - makeCommand.push_back("-configuration"); - makeCommand.push_back(!config.empty() ? config : "Debug"); - } + makeCommand.push_back("-configuration"); + makeCommand.push_back(!config.empty() ? config : "Debug"); makeCommand.insert(makeCommand.end(), makeOptions.begin(), makeOptions.end()); } @@ -391,9 +379,7 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( std::string target = tName; std::replace(target.begin(), target.end(), ' ', '_'); std::string out = "PostBuild." + target; - if (this->XcodeVersion > 20) { - out += "." + configName; - } + out += "." + configName; return out; } @@ -423,14 +409,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); cmCustomCommandLine makeHelper; - if (this->XcodeVersion < 50) { - makeHelper.push_back("make"); - makeHelper.push_back("-C"); - makeHelper.push_back(dir); - makeHelper.push_back("-f"); - makeHelper.push_back(this->CurrentXCodeHackMakefile); - makeHelper.push_back(""); // placeholder, see below - } + makeHelper.push_back("make"); + makeHelper.push_back("-C"); + makeHelper.push_back(dir); + makeHelper.push_back("-f"); + makeHelper.push_back(this->CurrentXCodeHackMakefile); + makeHelper.push_back(""); // placeholder, see below // Add ZERO_CHECK bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION"); @@ -475,13 +459,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // run the depend check makefile as a post build rule // this will make sure that when the next target is built // things are up-to-date - if (!makeHelper.empty() && - (target->GetType() == cmStateEnums::EXECUTABLE || - // Nope - no post-build for OBJECT_LIRBRARY - // target->GetType() == cmStateEnums::OBJECT_LIBRARY || - target->GetType() == cmStateEnums::STATIC_LIBRARY || - target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->GetType() == cmStateEnums::MODULE_LIBRARY)) { + if (target->GetType() == cmStateEnums::OBJECT_LIBRARY || + (this->XcodeVersion < 50 && + (target->GetType() == cmStateEnums::EXECUTABLE || + target->GetType() == cmStateEnums::STATIC_LIBRARY || + target->GetType() == cmStateEnums::SHARED_LIBRARY || + target->GetType() == cmStateEnums::MODULE_LIBRARY))) { makeHelper[makeHelper.size() - 1] = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); cmCustomCommandLines commandLines; @@ -489,7 +472,8 @@ void cmGlobalXCodeGenerator::AddExtraTargets( std::vector no_byproducts; lg->GetMakefile()->AddCustomCommandToTarget( target->GetName(), no_byproducts, no_depends, commandLines, - cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str()); + cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true, + false, "", false, cmMakefile::AcceptObjectLibraryCommands); } if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -605,12 +589,7 @@ void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj) cmXCodeObject* cmGlobalXCodeGenerator::CreateObject( cmXCodeObject::PBXType ptype) { - cmXCodeObject* obj; - if (this->XcodeVersion == 15) { - obj = new cmXCodeObject(ptype, cmXCodeObject::OBJECT); - } else { - obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT); - } + cmXCodeObject* obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT); this->addObject(obj); return obj; } @@ -653,11 +632,6 @@ std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target, return key; } -std::string GetGroupMapKey(cmGeneratorTarget* target, cmSourceFile* sf) -{ - return GetGroupMapKeyFromPath(target, sf->GetFullPath()); -} - cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath( const std::string& fullpath, cmGeneratorTarget* target, const std::string& lang, cmSourceFile* sf) @@ -725,18 +699,13 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( cmXCodeObject* buildFile = this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf); - cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject(); cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); settings->AddAttributeIfNotEmpty("COMPILER_FLAGS", this->CreateString(flags)); - // Is this a resource file in this target? Add it to the resources group... - // - cmGeneratorTarget::SourceFileFlags tsFlags = gtgt->GetTargetSourceFileFlags(sf); - bool isResource = tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource; cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); @@ -746,10 +715,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( if (gtgt->IsFrameworkOnApple()) { if (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) { attrs->AddObject(this->CreateString("Private")); - isResource = true; } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader) { attrs->AddObject(this->CreateString("Public")); - isResource = true; } } @@ -769,14 +736,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs); - // Add the fileRef to the top level Resources group/folder if it is not - // already there. - // - if (isResource && this->ResourcesGroupChildren && - !this->ResourcesGroupChildren->HasObject(fileRef)) { - this->ResourcesGroupChildren->AddObject(fileRef); - } - buildFile->AddAttributeIfNotEmpty("settings", settings); return buildFile; } @@ -901,9 +860,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( fileRef->AddAttribute("name", this->CreateString(name)); fileRef->AddAttribute("path", this->CreateString(path)); fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree)); - if (this->XcodeVersion == 15) { - fileRef->AddAttribute("refType", this->CreateString("4")); - } return fileRef; } @@ -1053,11 +1009,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( // Add object library contents as external objects. (Equivalent to // the externalObjFiles above, except each one is not a cmSourceFile // within the target.) - std::vector objs; - gtgt->UseObjectLibraries(objs, ""); - for (std::vector::const_iterator oi = objs.begin(); + std::vector objs; + gtgt->GetExternalObjects(objs, ""); + for (std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { - std::string obj = *oi; + if ((*oi)->GetObjectLibrary().empty()) { + continue; + } + std::string const& obj = (*oi)->GetFullPath(); cmXCodeObject* xsf = this->CreateXCodeSourceFileFromPath(obj, gtgt, "", 0); externalObjFiles.push_back(xsf); @@ -1155,8 +1114,12 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( // dstPath in frameworks is relative to Versions/ ostr << mit->first; } else if (mit->first != "MacOS") { - // dstPath in bundles is relative to Contents/MacOS - ostr << "../" << mit->first.c_str(); + if (gtgt->Target->GetMakefile()->PlatformIsAppleIos()) { + ostr << mit->first; + } else { + // dstPath in bundles is relative to Contents/MacOS + ostr << "../" << mit->first; + } } copyFilesBuildPhase->AddAttribute("dstPath", this->CreateString(ostr.str())); @@ -1174,6 +1137,45 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( } } + // create vector of "resource content file" build phases - only for + // framework or bundle targets + if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { + typedef std::map > + mapOfVectorOfSourceFiles; + mapOfVectorOfSourceFiles bundleFiles; + for (std::vector::const_iterator i = classes.begin(); + i != classes.end(); ++i) { + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(*i); + if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { + bundleFiles[tsFlags.MacFolder].push_back(*i); + } + } + mapOfVectorOfSourceFiles::iterator mit; + for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + copyFilesBuildPhase->SetComment("Copy files"); + copyFilesBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", + this->CreateString("7")); + copyFilesBuildPhase->AddAttribute("dstPath", + this->CreateString(mit->first)); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + std::vector::iterator sfIt; + for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, *sfIt, gtgt); + buildFiles->AddObject(xsf); + } + contentBuildPhases.push_back(copyFilesBuildPhase); + } + } + // create framework build phase cmXCodeObject* frameworkBuildPhase = 0; if (!externalObjFiles.empty()) { @@ -1398,7 +1400,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag, std::string retFlag; std::string::size_type lastOccurancePos = flags.rfind(flag); bool saved = false; - while (lastOccurancePos != flags.npos) { + while (lastOccurancePos != std::string::npos) { // increment pos, we use lastOccurancePos to reduce search space on next // inc std::string::size_type pos = lastOccurancePos; @@ -1515,6 +1517,17 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase( makecmd += " all"; buildphase->AddAttribute("shellScript", this->CreateString(makecmd)); buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0")); + + cmXCodeObject* outputFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (std::vector::const_iterator i = commands.begin(); + i != commands.end(); ++i) { + std::vector const& outputs = i->GetOutputs(); + for (std::vector::const_iterator j = outputs.begin(); + j != outputs.end(); ++j) { + outputFiles->AddObject(this->CreateString(*j)); + } + } + buildphase->AddAttribute("outputPaths", outputFiles); } void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( @@ -1522,9 +1535,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( std::vector const& commands, const std::string& configName) { std::string makefileName = makefileBasename; - if (this->XcodeVersion > 20) { - makefileName += configName; - } + makefileName += configName; cmGeneratedFileStream makefileStream(makefileName.c_str()); if (!makefileStream) { return; @@ -1645,7 +1656,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string& flags = cflags[lang]; // Add language-specific flags. - this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName); + this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang, + configName); // Add shared-library flags if needed. this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang, @@ -1665,16 +1677,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, return; } + if (gtgt->IsIPOEnabled(llang, configName)) { + const char* ltoValue = + this->CurrentMakefile->IsOn("_CMAKE_LTO_THIN") ? "YES_THIN" : "YES"; + buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue)); + } + // Add define flags this->CurrentLocalGenerator->AppendFlags( defFlags, this->CurrentMakefile->GetDefineFlags()); // Add preprocessor definitions for this target and configuration. - BuildObjectListOrString ppDefs(this, this->XcodeVersion >= 30); - if (this->XcodeVersion > 15) { - this->AppendDefines( - ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\""); - } + BuildObjectListOrString ppDefs(this, true); + this->AppendDefines( + ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\""); if (const char* exportMacro = gtgt->GetExportMacro()) { // Add the export symbol definition for shared library objects. this->AppendDefines(ppDefs, exportMacro); @@ -1774,15 +1790,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, gtgt->GetType() == cmStateEnums::SHARED_LIBRARY || gtgt->GetType() == cmStateEnums::MODULE_LIBRARY || gtgt->GetType() == cmStateEnums::EXECUTABLE) { - if (this->XcodeVersion >= 21) { - if (!gtgt->UsesDefaultOutputDir(configName, false)) { - std::string pncdir = gtgt->GetDirectory(configName); - buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", - this->CreateString(pncdir)); - } - } else { - buildSettings->AddAttribute("OBJROOT", this->CreateString(pndir)); - pndir = gtgt->GetDirectory(configName); + if (!gtgt->UsesDefaultOutputDir(configName, + cmStateEnums::RuntimeBinaryArtifact)) { + std::string pncdir = gtgt->GetDirectory(configName); + buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", + this->CreateString(pncdir)); } if (gtgt->IsFrameworkOnApple() || gtgt->IsCFBundleOnApple()) { @@ -1798,16 +1810,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, pnbase = gtgt->GetName(); pnsuffix = ".a"; - if (this->XcodeVersion >= 21) { - std::string pncdir = this->GetObjectsNormalDirectory( - this->CurrentProject, configName, gtgt); - buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", - this->CreateString(pncdir)); - } else { - buildSettings->AddAttribute("OBJROOT", this->CreateString(pndir)); - pndir = this->GetObjectsNormalDirectory(this->CurrentProject, configName, - gtgt); - } + std::string pncdir = + this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt); + buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", + this->CreateString(pncdir)); } // Store the product name for all target types. @@ -1876,7 +1882,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); buildSettings->AddAttribute("INFOPLIST_FILE", this->CreateString(plist)); - } else if (this->XcodeVersion >= 22) { + } else { buildSettings->AddAttribute("MACH_O_TYPE", this->CreateString("mh_bundle")); buildSettings->AddAttribute("GCC_DYNAMIC_NO_PIC", @@ -1888,14 +1894,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, extraLinkOptions += " "; extraLinkOptions += createFlags; } - } else { - // Add the flags to create a module. - std::string createFlags = this->LookupFlags( - "CMAKE_SHARED_MODULE_CREATE_", llang, "_FLAGS", "-bundle"); - if (!createFlags.empty()) { - extraLinkOptions += " "; - extraLinkOptions += createFlags; - } } break; } @@ -1961,12 +1959,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, default: break; } - if (this->XcodeVersion >= 22 && this->XcodeVersion < 40) { + if (this->XcodeVersion < 40) { buildSettings->AddAttribute("PREBINDING", this->CreateString("NO")); } - BuildObjectListOrString dirs(this, this->XcodeVersion >= 30); - BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30); + BuildObjectListOrString dirs(this, true); + BuildObjectListOrString fdirs(this, true); + BuildObjectListOrString sysdirs(this, true); + BuildObjectListOrString sysfdirs(this, true); + const bool emitSystemIncludes = this->XcodeVersion >= 83; + std::vector includes; this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, "C", configName); @@ -1980,11 +1982,22 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, frameworkDir += "/../"; frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir); if (emitted.insert(frameworkDir).second) { - fdirs.Add(this->XCodeEscapePath(frameworkDir)); + std::string incpath = this->XCodeEscapePath(frameworkDir); + if (emitSystemIncludes && + gtgt->IsSystemIncludeDirectory(frameworkDir, configName)) { + sysfdirs.Add(incpath); + } else { + fdirs.Add(incpath); + } } } else { std::string incpath = this->XCodeEscapePath(*i); - dirs.Add(incpath); + if (emitSystemIncludes && + gtgt->IsSystemIncludeDirectory(*i, configName)) { + sysdirs.Add(incpath); + } else { + dirs.Add(incpath); + } } } // Add framework search paths needed for linking. @@ -1993,7 +2006,13 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, for (std::vector::const_iterator fdi = fwDirs.begin(); fdi != fwDirs.end(); ++fdi) { if (emitted.insert(*fdi).second) { - fdirs.Add(this->XCodeEscapePath(*fdi)); + std::string incpath = this->XCodeEscapePath(*fdi); + if (emitSystemIncludes && + gtgt->IsSystemIncludeDirectory(*fdi, configName)) { + sysfdirs.Add(incpath); + } else { + fdirs.Add(incpath); + } } } } @@ -2003,8 +2022,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if (!dirs.IsEmpty()) { buildSettings->AddAttribute("HEADER_SEARCH_PATHS", dirs.CreateList()); } + if (!sysfdirs.IsEmpty()) { + buildSettings->AddAttribute("SYSTEM_FRAMEWORK_SEARCH_PATHS", + sysfdirs.CreateList()); + } + if (!sysdirs.IsEmpty()) { + buildSettings->AddAttribute("SYSTEM_HEADER_SEARCH_PATHS", + sysdirs.CreateList()); + } - if (this->XcodeVersion >= 60) { + if (this->XcodeVersion >= 60 && !emitSystemIncludes) { // Add those per-language flags in addition to HEADER_SEARCH_PATHS to gain // system include directory awareness. We need to also keep on setting // HEADER_SEARCH_PATHS to work around a missing compile options flag for @@ -2170,18 +2197,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("OTHER_REZFLAGS", this->CreateString("")); buildSettings->AddAttribute("SECTORDER_FLAGS", this->CreateString("")); buildSettings->AddAttribute("USE_HEADERMAP", this->CreateString("NO")); - if (this->XcodeVersion >= 30) { - cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST); - group->AddObject(this->CreateString("-Wmost")); - group->AddObject(this->CreateString("-Wno-four-char-constants")); - group->AddObject(this->CreateString("-Wno-unknown-pragmas")); - group->AddObject(this->CreateString("$(inherited)")); - buildSettings->AddAttribute("WARNING_CFLAGS", group); - } else { - buildSettings->AddAttribute( - "WARNING_CFLAGS", this->CreateString("-Wmost -Wno-four-char-constants" - " -Wno-unknown-pragmas")); - } + cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST); + group->AddObject(this->CreateString("-Wmost")); + group->AddObject(this->CreateString("-Wno-four-char-constants")); + group->AddObject(this->CreateString("-Wno-unknown-pragmas")); + group->AddObject(this->CreateString("$(inherited)")); + buildSettings->AddAttribute("WARNING_CFLAGS", group); // Runtime version information. if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) { @@ -2261,16 +2282,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0, gtgt); target->AddAttribute("buildPhases", buildPhases); - if (this->XcodeVersion > 20) { - this->AddConfigurations(target, gtgt); - } else { - std::string theConfig = - this->CurrentMakefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmXCodeObject* buildSettings = - this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - this->CreateBuildSettings(gtgt, buildSettings, theConfig); - target->AddAttribute("buildSettings", buildSettings); - } + this->AddConfigurations(target, gtgt); cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST); target->AddAttribute("dependencies", dependencies); target->AddAttribute("name", this->CreateString(gtgt->GetName())); @@ -2372,8 +2384,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType( else if (target->IsCFBundleOnApple()) return "wrapper.plug-in"; else - return ((this->XcodeVersion >= 22) ? "compiled.mach-o.executable" - : "compiled.mach-o.dylib"); + return "compiled.mach-o.executable"; case cmStateEnums::SHARED_LIBRARY: return (target->GetPropertyAsBool("FRAMEWORK") ? "wrapper.framework" @@ -2406,9 +2417,7 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType( else if (target->IsCFBundleOnApple()) return "com.apple.product-type.bundle"; else - return ((this->XcodeVersion >= 22) - ? "com.apple.product-type.tool" - : "com.apple.product-type.library.dynamic"); + return "com.apple.product-type.tool"; case cmStateEnums::SHARED_LIBRARY: return (target->GetPropertyAsBool("FRAMEWORK") ? "com.apple.product-type.framework" @@ -2434,15 +2443,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget( cmXCodeObject* buildRules = this->CreateObject(cmXCodeObject::OBJECT_LIST); target->AddAttribute("buildRules", buildRules); std::string defConfig; - if (this->XcodeVersion > 20) { - defConfig = this->AddConfigurations(target, gtgt); - } else { - cmXCodeObject* buildSettings = - this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - defConfig = this->CurrentMakefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - this->CreateBuildSettings(gtgt, buildSettings, defConfig); - target->AddAttribute("buildSettings", buildSettings); - } + defConfig = this->AddConfigurations(target, gtgt); cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST); target->AddAttribute("dependencies", dependencies); target->AddAttribute("name", this->CreateString(gtgt->GetName())); @@ -2461,9 +2462,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget( fullName = gtgt->GetFullName(defConfig); } fileRef->AddAttribute("path", this->CreateString(fullName)); - if (this->XcodeVersion == 15) { - fileRef->AddAttribute("refType", this->CreateString("0")); - } fileRef->AddAttribute("sourceTree", this->CreateString("BUILT_PRODUCTS_DIR")); fileRef->SetComment(gtgt->GetName()); @@ -2564,32 +2562,25 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute( cmXCodeObject* target, const char* attribute, const char* value, const std::string& configName) { - if (this->XcodeVersion < 21) { - // There is only one configuration. Add the setting to the buildSettings - // of the target. - this->AppendOrAddBuildSetting(target->GetObject("buildSettings"), - attribute, value); - } else { - // There are multiple configurations. Add the setting to the - // buildSettings of the configuration name given. - cmXCodeObject* configurationList = - target->GetObject("buildConfigurationList")->GetObject(); - cmXCodeObject* buildConfigs = - configurationList->GetObject("buildConfigurations"); - std::vector list = buildConfigs->GetObjectList(); - // each configuration and the target itself has a buildSettings in it - // list.push_back(target); - for (std::vector::iterator i = list.begin(); - i != list.end(); ++i) { - if (!configName.empty()) { - if ((*i)->GetObject("name")->GetString() == configName) { - cmXCodeObject* settings = (*i)->GetObject("buildSettings"); - this->AppendOrAddBuildSetting(settings, attribute, value); - } - } else { + // There are multiple configurations. Add the setting to the + // buildSettings of the configuration name given. + cmXCodeObject* configurationList = + target->GetObject("buildConfigurationList")->GetObject(); + cmXCodeObject* buildConfigs = + configurationList->GetObject("buildConfigurations"); + std::vector list = buildConfigs->GetObjectList(); + // each configuration and the target itself has a buildSettings in it + // list.push_back(target); + for (std::vector::iterator i = list.begin(); i != list.end(); + ++i) { + if (!configName.empty()) { + if ((*i)->GetObject("name")->GetString() == configName) { cmXCodeObject* settings = (*i)->GetObject("buildSettings"); this->AppendOrAddBuildSetting(settings, attribute, value); } + } else { + cmXCodeObject* settings = (*i)->GetObject("buildSettings"); + this->AppendOrAddBuildSetting(settings, attribute, value); } } } @@ -2625,13 +2616,16 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) // Add object library contents as link flags. std::string linkObjs; const char* sep = ""; - std::vector objs; - gt->UseObjectLibraries(objs, ""); - for (std::vector::const_iterator oi = objs.begin(); + std::vector objs; + gt->GetExternalObjects(objs, configName); + for (std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { + if ((*oi)->GetObjectLibrary().empty()) { + continue; + } linkObjs += sep; sep = " "; - linkObjs += this->XCodeEscapePath(*oi); + linkObjs += this->XCodeEscapePath((*oi)->GetFullPath()); } this->AppendBuildSettingAttribute( target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName); @@ -2666,13 +2660,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) for (std::vector::const_iterator libDir = libDirs.begin(); libDir != libDirs.end(); ++libDir) { if (libDir->size() && *libDir != "/usr/lib") { - if (this->XcodeVersion > 15) { - // Now add the same one but append - // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it: - linkDirs += " "; - linkDirs += this->XCodeEscapePath( - *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"); - } + // Now add the same one but append + // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it: + linkDirs += " "; + linkDirs += this->XCodeEscapePath( + *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"); linkDirs += " "; linkDirs += this->XCodeEscapePath(*libDir); } @@ -2738,32 +2730,23 @@ bool cmGlobalXCodeGenerator::CreateGroups( gtgt->AddSource(plist); } - std::vector classes; - if (!gtgt->GetConfigCommonSourceFiles(classes)) { - return false; - } + std::vector const& sources = + gtgt->GetAllConfigSources(); + // Put cmSourceFile instances in proper groups: - for (std::vector::const_iterator s = classes.begin(); - s != classes.end(); s++) { - cmSourceFile* sf = *s; + for (std::vector::const_iterator si = + sources.begin(); + si != sources.end(); ++si) { + cmSourceFile const* sf = si->Source; + if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) { + // Object library files go on the link line instead. + continue; + } // Add the file to the list of sources. std::string const& source = sf->GetFullPath(); cmSourceGroup* sourceGroup = mf->FindSourceGroup(source.c_str(), sourceGroups); cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); - std::string key = GetGroupMapKey(gtgt, sf); - this->GroupMap[key] = pbxgroup; - } - - // Put OBJECT_LIBRARY objects in proper groups: - std::vector objs; - gtgt->UseObjectLibraries(objs, ""); - for (std::vector::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - std::string const& source = *oi; - cmSourceGroup* sourceGroup = - mf->FindSourceGroup(source.c_str(), sourceGroups); - cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); std::string key = GetGroupMapKeyFromPath(gtgt, source); this->GroupMap[key] = pbxgroup; } @@ -2783,9 +2766,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreatePBXGroup(cmXCodeObject* parent, this->CreateObject(cmXCodeObject::OBJECT_LIST); group->AddAttribute("name", this->CreateString(name)); group->AddAttribute("children", groupChildren); - if (this->XcodeVersion == 15) { - group->AddAttribute("refType", this->CreateString("4")); - } group->AddAttribute("sourceTree", this->CreateString("")); if (parentChildren) parentChildren->AddObject(group); @@ -2833,7 +2813,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( tgroup = this->CreatePBXGroup(tgroup, tgt_folders[i]); this->TargetGroup[curr_tgt_folder] = tgroup; if (i == 0) { - this->SourcesGroupChildren->AddObject(tgroup); + this->MainGroupChildren->AddObject(tgroup); } } } @@ -2879,69 +2859,27 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( { this->ClearXCodeObjects(); this->RootObject = 0; - this->SourcesGroupChildren = 0; - this->ResourcesGroupChildren = 0; this->MainGroupChildren = 0; cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO")); - cmXCodeObject* developBuildStyle = - this->CreateObject(cmXCodeObject::PBXBuildStyle); cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST); - if (this->XcodeVersion == 15) { - developBuildStyle->AddAttribute("name", this->CreateString("Development")); - developBuildStyle->AddAttribute("buildSettings", group); - listObjs->AddObject(developBuildStyle); - group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES")); - cmXCodeObject* deployBuildStyle = + for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) { + cmXCodeObject* buildStyle = this->CreateObject(cmXCodeObject::PBXBuildStyle); - deployBuildStyle->AddAttribute("name", this->CreateString("Deployment")); - deployBuildStyle->AddAttribute("buildSettings", group); - listObjs->AddObject(deployBuildStyle); - } else { - for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) { - cmXCodeObject* buildStyle = - this->CreateObject(cmXCodeObject::PBXBuildStyle); - const char* name = this->CurrentConfigurationTypes[i].c_str(); - buildStyle->AddAttribute("name", this->CreateString(name)); - buildStyle->SetComment(name); - cmXCodeObject* sgroup = - this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - sgroup->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO")); - buildStyle->AddAttribute("buildSettings", sgroup); - listObjs->AddObject(buildStyle); - } + const char* name = this->CurrentConfigurationTypes[i].c_str(); + buildStyle->AddAttribute("name", this->CreateString(name)); + buildStyle->SetComment(name); + cmXCodeObject* sgroup = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); + sgroup->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO")); + buildStyle->AddAttribute("buildSettings", sgroup); + listObjs->AddObject(buildStyle); } cmXCodeObject* mainGroup = this->CreateObject(cmXCodeObject::PBXGroup); this->MainGroupChildren = this->CreateObject(cmXCodeObject::OBJECT_LIST); mainGroup->AddAttribute("children", this->MainGroupChildren); - if (this->XcodeVersion == 15) { - mainGroup->AddAttribute("refType", this->CreateString("4")); - } mainGroup->AddAttribute("sourceTree", this->CreateString("")); - cmXCodeObject* sourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup); - this->SourcesGroupChildren = this->CreateObject(cmXCodeObject::OBJECT_LIST); - sourcesGroup->AddAttribute("name", this->CreateString("Sources")); - sourcesGroup->AddAttribute("children", this->SourcesGroupChildren); - if (this->XcodeVersion == 15) { - sourcesGroup->AddAttribute("refType", this->CreateString("4")); - } - sourcesGroup->AddAttribute("sourceTree", this->CreateString("")); - this->MainGroupChildren->AddObject(sourcesGroup); - - cmXCodeObject* resourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup); - this->ResourcesGroupChildren = - this->CreateObject(cmXCodeObject::OBJECT_LIST); - resourcesGroup->AddAttribute("name", this->CreateString("Resources")); - resourcesGroup->AddAttribute("children", this->ResourcesGroupChildren); - if (this->XcodeVersion == 15) { - resourcesGroup->AddAttribute("refType", this->CreateString("4")); - } - resourcesGroup->AddAttribute("sourceTree", this->CreateString("")); - this->MainGroupChildren->AddObject(resourcesGroup); - // now create the cmake groups if (!this->CreateGroups(generators)) { return false; @@ -2949,9 +2887,6 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( cmXCodeObject* productGroup = this->CreateObject(cmXCodeObject::PBXGroup); productGroup->AddAttribute("name", this->CreateString("Products")); - if (this->XcodeVersion == 15) { - productGroup->AddAttribute("refType", this->CreateString("4")); - } productGroup->AddAttribute("sourceTree", this->CreateString("")); cmXCodeObject* productGroupChildren = this->CreateObject(cmXCodeObject::OBJECT_LIST); @@ -2973,24 +2908,22 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->RootObject->AddAttribute("buildStyles", listObjs); this->RootObject->AddAttribute("hasScannedForEncodings", this->CreateString("0")); - if (this->XcodeVersion >= 30) { - group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - group->AddAttribute("BuildIndependentTargetsInParallel", - this->CreateString("YES")); - std::ostringstream v; - v << std::setfill('0') << std::setw(4) << XcodeVersion * 10; - group->AddAttribute("LastUpgradeCheck", this->CreateString(v.str())); - this->RootObject->AddAttribute("attributes", group); - if (this->XcodeVersion >= 32) - this->RootObject->AddAttribute("compatibilityVersion", - this->CreateString("Xcode 3.2")); - else if (this->XcodeVersion >= 31) - this->RootObject->AddAttribute("compatibilityVersion", - this->CreateString("Xcode 3.1")); - else - this->RootObject->AddAttribute("compatibilityVersion", - this->CreateString("Xcode 3.0")); - } + group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); + group->AddAttribute("BuildIndependentTargetsInParallel", + this->CreateString("YES")); + std::ostringstream v; + v << std::setfill('0') << std::setw(4) << XcodeVersion * 10; + group->AddAttribute("LastUpgradeCheck", this->CreateString(v.str())); + this->RootObject->AddAttribute("attributes", group); + if (this->XcodeVersion >= 32) + this->RootObject->AddAttribute("compatibilityVersion", + this->CreateString("Xcode 3.2")); + else if (this->XcodeVersion >= 31) + this->RootObject->AddAttribute("compatibilityVersion", + this->CreateString("Xcode 3.1")); + else + this->RootObject->AddAttribute("compatibilityVersion", + this->CreateString("Xcode 3.0")); // Point Xcode at the top of the source tree. { std::string pdir = @@ -3005,26 +2938,15 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( typedef std::vector > Configs; Configs configs; const char* defaultConfigName = "Debug"; - if (this->XcodeVersion == 15) { - cmXCodeObject* configDebug = - this->CreateObject(cmXCodeObject::XCBuildConfiguration); - configDebug->AddAttribute("name", this->CreateString("Debug")); - configs.push_back(std::make_pair("Debug", configDebug)); - cmXCodeObject* configRelease = - this->CreateObject(cmXCodeObject::XCBuildConfiguration); - configRelease->AddAttribute("name", this->CreateString("Release")); - configs.push_back(std::make_pair("Release", configRelease)); - } else { - for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) { - const char* name = this->CurrentConfigurationTypes[i].c_str(); - if (0 == i) { - defaultConfigName = name; - } - cmXCodeObject* config = - this->CreateObject(cmXCodeObject::XCBuildConfiguration); - config->AddAttribute("name", this->CreateString(name)); - configs.push_back(std::make_pair(name, config)); + for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) { + const char* name = this->CurrentConfigurationTypes[i].c_str(); + if (0 == i) { + defaultConfigName = name; } + cmXCodeObject* config = + this->CreateObject(cmXCodeObject::XCBuildConfiguration); + config->AddAttribute("name", this->CreateString(name)); + configs.push_back(std::make_pair(name, config)); } for (Configs::iterator c = configs.begin(); c != configs.end(); ++c) { buildConfigurations->AddObject(c->second); @@ -3042,23 +2964,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->CreateString(defaultConfigName)); cmXCodeObject* buildSettings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - const char* osxArch = - this->CurrentMakefile->GetDefinition("CMAKE_OSX_ARCHITECTURES"); const char* sysroot = this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT"); const char* deploymentTarget = this->CurrentMakefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET"); - std::string archs; if (sysroot) { - if (osxArch) { - // recompute this as it may have been changed since enable language - this->Architectures.clear(); - cmSystemTools::ExpandListArgument(std::string(osxArch), - this->Architectures); - archs = cmJoin(this->Architectures, " "); - } buildSettings->AddAttribute("SDKROOT", this->CreateString(sysroot)); } + // recompute this as it may have been changed since enable language + this->ComputeArchitectures(this->CurrentMakefile); + std::string const archs = cmJoin(this->Architectures, " "); if (archs.empty()) { // Tell Xcode to use NATIVE_ARCH instead of ARCHS. buildSettings->AddAttribute("ONLY_ACTIVE_ARCH", this->CreateString("YES")); @@ -3133,10 +3048,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( cmXCodeObject* t = *i; this->AddDependAndLinkInformation(t); } - if (this->XcodeVersion < 50) { - // now create xcode depend hack makefile - this->CreateXCodeDependHackTarget(targets); - } + this->CreateXCodeDependHackTarget(targets); // now add all targets to the root object cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST); for (std::vector::iterator i = targets.begin(); @@ -3168,6 +3080,38 @@ std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory( return dir; } +void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) +{ + this->Architectures.clear(); + const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES"); + const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); + if (osxArch && sysroot) { + cmSystemTools::ExpandListArgument(std::string(osxArch), + this->Architectures); + } + + if (this->Architectures.empty()) { + // With no ARCHS we use ONLY_ACTIVE_ARCH. + // Look up the arch that Xcode chooses in this case. + if (const char* arch = mf->GetDefinition("CMAKE_XCODE_CURRENT_ARCH")) { + this->ObjectDirArchDefault = arch; + } + } + + this->ComputeObjectDirArch(mf); +} + +void cmGlobalXCodeGenerator::ComputeObjectDirArch(cmMakefile* mf) +{ + if (this->Architectures.size() > 1 || this->UseEffectivePlatformName(mf)) { + this->ObjectDirArch = "$(CURRENT_ARCH)"; + } else if (!this->Architectures.empty()) { + this->ObjectDirArch = this->Architectures[0]; + } else { + this->ObjectDirArch = this->ObjectDirArchDefault; + } +} + void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::vector& targets) { @@ -3187,29 +3131,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( "default:\n" "\techo \"Do not invoke directly\"\n" "\n"; - makefileStream - << "# For each target create a dummy rule " - "so the target does not have to exist\n"; /* clang-format on */ - std::set emitted; - for (std::vector::iterator i = targets.begin(); - i != targets.end(); ++i) { - cmXCodeObject* target = *i; - std::map const& deplibs = - target->GetDependLibraries(); - for (std::map::const_iterator ci = - deplibs.begin(); - ci != deplibs.end(); ++ci) { - for (cmXCodeObject::StringVec::const_iterator d = ci->second.begin(); - d != ci->second.end(); ++d) { - if (emitted.insert(*d).second) { - makefileStream << this->ConvertToRelativeForMake(d->c_str()) - << ":\n"; - } - } - } - } - makefileStream << "\n\n"; + + std::set dummyRules; // Write rules to help Xcode relink things at the right time. /* clang-format off */ @@ -3228,8 +3152,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( cmGeneratorTarget* gt = target->GetTarget(); if (gt->GetType() == cmStateEnums::EXECUTABLE || - // Nope - no post-build for OBJECT_LIRBRARY - // gt->GetType() == cmStateEnums::OBJECT_LIBRARY || + gt->GetType() == cmStateEnums::OBJECT_LIBRARY || gt->GetType() == cmStateEnums::STATIC_LIBRARY || gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { @@ -3239,6 +3162,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } if (gt->GetType() == cmStateEnums::EXECUTABLE || + gt->GetType() == cmStateEnums::STATIC_LIBRARY || gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { std::string tfull = gt->GetFullPath(configName); @@ -3256,6 +3180,15 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } } + std::vector objlibs; + gt->GetObjectLibrariesCMP0026(objlibs); + for (std::vector::const_iterator it = + objlibs.begin(); + it != objlibs.end(); ++it) { + makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct) + << ": " << trel << "\n"; + } + // Create a rule for this target. makefileStream << trel << ":"; @@ -3266,10 +3199,28 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::vector const& deplibs = x->second; for (std::vector::const_iterator d = deplibs.begin(); d != deplibs.end(); ++d) { - makefileStream << "\\\n\t" - << this->ConvertToRelativeForMake(d->c_str()); + std::string file = this->ConvertToRelativeForMake(d->c_str()); + makefileStream << "\\\n\t" << file; + dummyRules.insert(file); } } + + for (std::vector::const_iterator it = + objlibs.begin(); + it != objlibs.end(); ++it) { + + const std::string objLibName = (*it)->GetName(); + std::string d = this->GetObjectsNormalDirectory(this->CurrentProject, + configName, *it); + d += "lib"; + d += objLibName; + d += ".a"; + + std::string dependency = this->ConvertToRelativeForMake(d.c_str()); + makefileStream << "\\\n\t" << dependency; + dummyRules.insert(dependency); + } + // Write the action to remove the target if it is out of date. makefileStream << "\n"; makefileStream << "\t/bin/rm -f " @@ -3297,6 +3248,14 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } } } + + makefileStream << "\n\n" + << "# For each target create a dummy rule" + << "so the target does not have to exist\n"; + for (std::set::const_iterator it = dummyRules.begin(); + it != dummyRules.end(); ++it) { + makefileStream << *it << ":\n"; + } } void cmGlobalXCodeGenerator::OutputXCodeProject( @@ -3319,10 +3278,7 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( std::string xcodeDir = root->GetCurrentBinaryDirectory(); xcodeDir += "/"; xcodeDir += root->GetProjectName(); - xcodeDir += ".xcode"; - if (this->XcodeVersion > 20) { - xcodeDir += "proj"; - } + xcodeDir += ".xcodeproj"; cmSystemTools::MakeDirectory(xcodeDir.c_str()); std::string xcodeProjFile = xcodeDir + "/project.pbxproj"; cmGeneratedFileStream fout(xcodeProjFile.c_str()); @@ -3331,6 +3287,17 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( return; } this->WriteXCodePBXProj(fout, root, generators); + + // Since the lowest available Xcode version for testing was 7.0, + // I'm setting this as a limit then + if (this->XcodeVersion >= 70) { + if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || + root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) { + this->OutputXCodeSharedSchemes(xcodeDir); + this->OutputXCodeWorkspaceSettings(xcodeDir); + } + } + this->ClearXCodeObjects(); // Since this call may have created new cache entries, save the cache: @@ -3339,6 +3306,54 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( root->GetBinaryDirectory()); } +void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( + const std::string& xcProjDir) +{ + for (std::vector::const_iterator i = + this->XCodeObjects.begin(); + i != this->XCodeObjects.end(); ++i) { + cmXCodeObject* obj = *i; + if (obj->GetType() == cmXCodeObject::OBJECT && + (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || + obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) { + cmXCodeScheme schm(obj, this->CurrentConfigurationTypes, + this->XcodeVersion); + schm.WriteXCodeSharedScheme(xcProjDir, + this->RelativeToSource(xcProjDir.c_str())); + } + } +} + +void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( + const std::string& xcProjDir) +{ + std::string xcodeSharedDataDir = xcProjDir; + xcodeSharedDataDir += "/project.xcworkspace/xcshareddata"; + cmSystemTools::MakeDirectory(xcodeSharedDataDir); + + std::string workspaceSettingsFile = xcodeSharedDataDir; + workspaceSettingsFile += "/WorkspaceSettings.xcsettings"; + + cmGeneratedFileStream fout(workspaceSettingsFile.c_str()); + fout.SetCopyIfDifferent(true); + if (!fout) { + return; + } + + cmXMLWriter xout(fout); + xout.StartDocument(); + xout.Doctype("plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\"" + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\""); + xout.StartElement("plist"); + xout.Attribute("version", "1.0"); + xout.StartElement("dict"); + xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded"); + xout.Element("false"); + xout.EndElement(); // dict + xout.EndElement(); // plist + xout.EndDocument(); +} + void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator*, std::vector&) @@ -3354,20 +3369,13 @@ void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout, cmXCodeObject::Indent(1, fout); fout << "};\n"; cmXCodeObject::Indent(1, fout); - if (this->XcodeVersion >= 21) { - if (this->XcodeVersion >= 32) - fout << "objectVersion = 46;\n"; - else if (this->XcodeVersion >= 31) - fout << "objectVersion = 45;\n"; - else if (this->XcodeVersion >= 30) - fout << "objectVersion = 44;\n"; - else - fout << "objectVersion = 42;\n"; - cmXCode21Object::PrintList(this->XCodeObjects, fout); - } else { - fout << "objectVersion = 39;\n"; - cmXCodeObject::PrintList(this->XCodeObjects, fout); - } + if (this->XcodeVersion >= 32) + fout << "objectVersion = 46;\n"; + else if (this->XcodeVersion >= 31) + fout << "objectVersion = 45;\n"; + else + fout << "objectVersion = 44;\n"; + cmXCode21Object::PrintList(this->XCodeObjects, fout); cmXCodeObject::Indent(1, fout); fout << "rootObject = " << this->RootObject->GetId() << " /* Project object */;\n"; @@ -3376,9 +3384,7 @@ void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout, const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const { - return this->XcodeVersion >= 21 - ? "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" - : "."; + return "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; } std::string cmGlobalXCodeGenerator::ExpandCFGIntDir( @@ -3428,7 +3434,7 @@ std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p) std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p) { - if (p.find(' ') != p.npos) { + if (p.find(' ') != std::string::npos) { std::string t = "\""; t += p; t += "\""; @@ -3441,12 +3447,10 @@ void cmGlobalXCodeGenerator::AppendDirectoryForConfig( const std::string& prefix, const std::string& config, const std::string& suffix, std::string& dir) { - if (this->XcodeVersion > 20) { - if (!config.empty()) { - dir += prefix; - dir += config; - dir += suffix; - } + if (!config.empty()) { + dir += prefix; + dir += config; + dir += suffix; } } @@ -3518,7 +3522,7 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, // Check if the flag needs quoting. bool quoteFlag = - flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != flag.npos; + flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != std::string::npos; // We escape a flag as follows: // - Place each flag in single quotes '' @@ -3571,12 +3575,19 @@ std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation( // i.e. "Can I build Debug and Release in the same tree?" bool cmGlobalXCodeGenerator::IsMultiConfig() const { - // Old Xcode 1.5 is single config: - if (this->XcodeVersion == 15) { + // Newer Xcode versions are multi config: + return true; +} + +bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation( + std::string* reason) const +{ + if (this->ObjectDirArch.find('$') != std::string::npos) { + if (reason != CM_NULLPTR) { + *reason = " under Xcode with multiple architectures"; + } return false; } - - // Newer Xcode versions are multi config: return true; } @@ -3593,21 +3604,19 @@ bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const return cmSystemTools::IsOn(epnValue); } +bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const +{ + // Xcode determines Resource location itself + return true; +} + void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { std::string configName = this->GetCMakeCFGIntDir(); std::string dir = this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt); - if (this->XcodeVersion >= 21) { - dir += "$(CURRENT_ARCH)/"; - } else { -#ifdef __ppc__ - dir += "ppc/"; -#endif -#ifdef __i386 - dir += "i386/"; -#endif - } + dir += this->ObjectDirArch; + dir += "/"; gt->ObjectDirectory = dir; } diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1aaf9c709..e69793bcc 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -3,7 +3,8 @@ #ifndef cmGlobalXCodeGenerator_h #define cmGlobalXCodeGenerator_h -#include +#include "cmConfigure.h" + #include #include #include @@ -31,7 +32,8 @@ struct cmDocumentationEntry; class cmGlobalXCodeGenerator : public cmGlobalGenerator { public: - cmGlobalXCodeGenerator(cmake* cm, std::string const& version); + cmGlobalXCodeGenerator(cmake* cm, std::string const& version_string, + unsigned int version_number); static cmGlobalGeneratorFactory* NewFactory(); ///! Get the name for the generator. @@ -86,8 +88,14 @@ public: i.e. "Can I build Debug and Release in the same tree?" */ bool IsMultiConfig() const CM_OVERRIDE; + bool HasKnownObjectFileLocation(std::string* reason) const CM_OVERRIDE; + + bool IsIPOSupported() const CM_OVERRIDE { return true; } + bool UseEffectivePlatformName(cmMakefile* mf) const CM_OVERRIDE; + bool ShouldStripResourcePath(cmMakefile*) const CM_OVERRIDE; + bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) CM_OVERRIDE; void AppendFlag(std::string& flags, std::string const& flag); @@ -165,6 +173,9 @@ private: std::vector& generators); void OutputXCodeProject(cmLocalGenerator* root, std::vector& generators); + // Write shared scheme files for all the native targets + void OutputXCodeSharedSchemes(const std::string& xcProjDir); + void OutputXCodeWorkspaceSettings(const std::string& xcProjDir); void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root, std::vector& generators); cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath, @@ -235,12 +246,13 @@ private: const std::string& configName, const cmGeneratorTarget* t) const; + void ComputeArchitectures(cmMakefile* mf); + void ComputeObjectDirArch(cmMakefile* mf); + void addObject(cmXCodeObject* obj); std::string PostBuildMakeTarget(std::string const& tName, std::string const& configName); cmXCodeObject* MainGroupChildren; - cmXCodeObject* SourcesGroupChildren; - cmXCodeObject* ResourcesGroupChildren; cmMakefile* CurrentMakefile; cmLocalGenerator* CurrentLocalGenerator; std::vector CurrentConfigurationTypes; @@ -256,6 +268,8 @@ private: std::map FileRefs; std::map XCodeObjectMap; std::vector Architectures; + std::string ObjectDirArchDefault; + std::string ObjectDirArch; std::string GeneratorToolset; }; diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h index e6aec47c2..46cf87871 100644 --- a/Source/cmGraphAdjacencyList.h +++ b/Source/cmGraphAdjacencyList.h @@ -3,7 +3,7 @@ #ifndef cmGraphAdjacencyList_h #define cmGraphAdjacencyList_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include @@ -15,26 +15,11 @@ class cmGraphEdge { public: - cmGraphEdge() - : Dest(0) - , Strong(true) - { - } - cmGraphEdge(int n) - : Dest(n) - , Strong(true) - { - } - cmGraphEdge(int n, bool s) + cmGraphEdge(int n = 0, bool s = true) : Dest(n) , Strong(s) { } - cmGraphEdge(cmGraphEdge const& r) - : Dest(r.Dest) - , Strong(r.Strong) - { - } operator int() const { return this->Dest; } bool IsStrong() const { return this->Strong; } diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 0f69aaa46..7e953cef1 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGraphVizWriter.h" -#include +#include "cmConfigure.h" #include #include #include @@ -61,7 +61,7 @@ cmGraphVizWriter::cmGraphVizWriter( void cmGraphVizWriter::ReadSettings(const char* settingsFileName, const char* fallbackSettingsFileName) { - cmake cm; + cmake cm(cmake::RoleScript); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h index 1ff07abd7..824999b96 100644 --- a/Source/cmGraphVizWriter.h +++ b/Source/cmGraphVizWriter.h @@ -3,11 +3,11 @@ #ifndef CMGRAPHVIZWRITER_H #define CMGRAPHVIZWRITER_H -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmStateTypes.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/cmHexFileConverter.cxx b/Source/cmHexFileConverter.cxx index d9d659893..78dceb794 100644 --- a/Source/cmHexFileConverter.cxx +++ b/Source/cmHexFileConverter.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmHexFileConverter.h" -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h index 64ade76b9..152e293eb 100644 --- a/Source/cmIDEFlagTable.h +++ b/Source/cmIDEFlagTable.h @@ -24,6 +24,9 @@ struct cmIDEFlagTable // IgnoreDefaultLibraryNames) UserFollowing = (1 << 5), // expect value in following argument CaseInsensitive = (1 << 6), // flag may be any case + SpaceAppendable = (1 << 7), // a flag that if specified multiple times + // should have its value appended to the + // old value with spaces UserValueIgnored = UserValue | UserIgnored, UserValueRequired = UserValue | UserRequired diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 8d07776b7..5e872d2ff 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmIDEOptions.h" -#include +#include "cmsys/String.h" #include #include @@ -125,6 +125,8 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry, this->FlagMap[entry->IDEName] = entry->value; } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) { this->FlagMap[entry->IDEName].push_back(new_value); + } else if (entry->special & cmIDEFlagTable::SpaceAppendable) { + this->FlagMap[entry->IDEName].append_with_space(new_value); } else { // Use the user-specified value. this->FlagMap[entry->IDEName] = new_value; @@ -177,6 +179,12 @@ void cmIDEOptions::AppendFlag(std::string const& flag, std::copy(value.begin(), value.end(), std::back_inserter(fv)); } +void cmIDEOptions::AppendFlagString(std::string const& flag, + std::string const& value) +{ + this->FlagMap[flag].append_with_space(value); +} + void cmIDEOptions::RemoveFlag(const char* flag) { this->FlagMap.erase(flag); diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index be2fd6da8..19e96bd44 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -3,7 +3,7 @@ #ifndef cmIDEOptions_h #define cmIDEOptions_h -#include +#include "cmConfigure.h" #include #include @@ -31,6 +31,7 @@ public: void AppendFlag(std::string const& flag, std::string const& value); void AppendFlag(std::string const& flag, std::vector const& value); + void AppendFlagString(std::string const& flag, std::string const& value); void RemoveFlag(const char* flag); bool HasFlag(std::string const& flag) const; const char* GetFlag(const char* flag); @@ -59,15 +60,22 @@ protected: this->derived::operator=(r); return *this; } + FlagValue& append_with_space(std::string const& r) + { + this->resize(1); + std::string& l = this->operator[](0); + if (!l.empty()) { + l += " "; + } + l += r; + return *this; + } }; std::map FlagMap; // Preprocessor definitions. std::vector Defines; - // Unrecognized flags that get no special handling. - std::string FlagString; - bool DoingDefine; bool AllowDefine; bool AllowSlash; diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index a8fa4f92e..0972664a2 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -57,8 +57,19 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, // watch for our state change if (scopeDepth == 0 && !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(), "else")) { + + if (this->ElseSeen) { + cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]); + mf.GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, + "A duplicate ELSE command was found inside an IF block.", bt); + cmSystemTools::SetFatalErrorOccured(); + return true; + } + this->IsBlocking = this->HasRun; this->HasRun = true; + this->ElseSeen = true; // if trace is enabled, print a (trivially) evaluated "else" // statement @@ -68,6 +79,15 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, } else if (scopeDepth == 0 && !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(), "elseif")) { + if (this->ElseSeen) { + cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]); + mf.GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, + "An ELSEIF command was found after an ELSE command.", bt); + cmSystemTools::SetFatalErrorOccured(); + return true; + } + if (this->HasRun) { this->IsBlocking = true; } else { @@ -117,15 +137,15 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, status.Clear(); mf.ExecuteCommand(this->Functions[c], status); if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(true); + inStatus.SetReturnInvoked(); return true; } if (status.GetBreakInvoked()) { - inStatus.SetBreakInvoked(true); + inStatus.SetBreakInvoked(); return true; } if (status.GetContinueInvoked()) { - inStatus.SetContinueInvoked(true); + inStatus.SetContinueInvoked(); return true; } } diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index 56eef30e2..5877a7d12 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -3,7 +3,8 @@ #ifndef cmIfCommand_h #define cmIfCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -21,6 +22,7 @@ public: cmIfFunctionBlocker() { this->HasRun = false; + this->ElseSeen = false; this->ScopeDepth = 0; } ~cmIfFunctionBlocker() CM_OVERRIDE {} @@ -32,6 +34,7 @@ public: std::vector Functions; bool IsBlocking; bool HasRun; + bool ElseSeen; unsigned int ScopeDepth; }; @@ -61,16 +64,6 @@ public: return false; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "if"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - // Filter the given variable definition based on policy CMP0054. static const char* GetDefinitionIfUnquoted( const cmMakefile* mf, cmExpandedCommandArgument const& argument); diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h index 78edd43c2..16dda0ef5 100644 --- a/Source/cmIncludeCommand.h +++ b/Source/cmIncludeCommand.h @@ -3,7 +3,8 @@ #ifndef cmIncludeCommand_h #define cmIncludeCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,16 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "include"; } }; #endif diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index cdb027972..b81f7cb2d 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -113,7 +113,7 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc) { std::string::size_type b = inc.find_first_not_of(" \r"); std::string::size_type e = inc.find_last_not_of(" \r"); - if ((b != inc.npos) && (e != inc.npos)) { + if ((b != std::string::npos) && (e != std::string::npos)) { inc.assign(inc, b, 1 + e - b); // copy the remaining substring } else { inc = ""; diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h index 287b5d3cd..12de698cb 100644 --- a/Source/cmIncludeDirectoryCommand.h +++ b/Source/cmIncludeDirectoryCommand.h @@ -3,7 +3,8 @@ #ifndef cmIncludeDirectoryCommand_h #define cmIncludeDirectoryCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "include_directories"; } - protected: // used internally void GetIncludes(const std::string& arg, std::vector& incs); diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h index 9fcf467c5..375646fa6 100644 --- a/Source/cmIncludeExternalMSProjectCommand.h +++ b/Source/cmIncludeExternalMSProjectCommand.h @@ -3,7 +3,8 @@ #ifndef cmIncludeExternalMSProjectCommand_h #define cmIncludeExternalMSProjectCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -35,14 +36,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "include_external_msproject"; - } }; #endif diff --git a/Source/cmIncludeRegularExpressionCommand.h b/Source/cmIncludeRegularExpressionCommand.h index c68d9f297..bac4b8fc3 100644 --- a/Source/cmIncludeRegularExpressionCommand.h +++ b/Source/cmIncludeRegularExpressionCommand.h @@ -3,7 +3,8 @@ #ifndef cmIncludeRegularExpressionCommand_h #define cmIncludeRegularExpressionCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -34,14 +35,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "include_regular_expression"; - } }; #endif diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 4c331c72b..294fb178d 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallCommand.h" -#include +#include "cmsys/Glob.hxx" #include #include @@ -75,29 +75,31 @@ bool cmInstallCommand::InitialPass(std::vector const& args, this->DefaultComponentName = "Unspecified"; } + std::string const& mode = args[0]; + // Switch among the command modes. - if (args[0] == "SCRIPT") { + if (mode == "SCRIPT") { return this->HandleScriptMode(args); } - if (args[0] == "CODE") { + if (mode == "CODE") { return this->HandleScriptMode(args); } - if (args[0] == "TARGETS") { + if (mode == "TARGETS") { return this->HandleTargetsMode(args); } - if (args[0] == "FILES") { + if (mode == "FILES") { return this->HandleFilesMode(args); } - if (args[0] == "PROGRAMS") { + if (mode == "PROGRAMS") { return this->HandleFilesMode(args); } - if (args[0] == "DIRECTORY") { + if (mode == "DIRECTORY") { return this->HandleDirectoryMode(args); } - if (args[0] == "EXPORT") { + if (mode == "EXPORT") { return this->HandleExportMode(args); } - if (args[0] == "EXPORT_ANDROID_MK") { + if (mode == "EXPORT_ANDROID_MK") { return this->HandleExportAndroidMKMode(args); } @@ -165,7 +167,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector const& args) script.c_str(), false, component.c_str(), exclude_from_all)); } else if (doing_code) { doing_code = false; - std::string code = args[i]; + std::string const& code = args[i]; this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator( code.c_str(), true, component.c_str(), exclude_from_all)); } @@ -206,6 +208,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) cmCAStringVector archiveArgVector(&argHelper, "ARCHIVE", &group); cmCAStringVector libraryArgVector(&argHelper, "LIBRARY", &group); cmCAStringVector runtimeArgVector(&argHelper, "RUNTIME", &group); + cmCAStringVector objectArgVector(&argHelper, "OBJECTS", &group); cmCAStringVector frameworkArgVector(&argHelper, "FRAMEWORK", &group); cmCAStringVector bundleArgVector(&argHelper, "BUNDLE", &group); cmCAStringVector includesArgVector(&argHelper, "INCLUDES", &group); @@ -234,6 +237,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) cmInstallCommandArguments archiveArgs(this->DefaultComponentName); cmInstallCommandArguments libraryArgs(this->DefaultComponentName); cmInstallCommandArguments runtimeArgs(this->DefaultComponentName); + cmInstallCommandArguments objectArgs(this->DefaultComponentName); cmInstallCommandArguments frameworkArgs(this->DefaultComponentName); cmInstallCommandArguments bundleArgs(this->DefaultComponentName); cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName); @@ -246,6 +250,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) archiveArgs.Parse(&archiveArgVector.GetVector(), &unknownArgs); libraryArgs.Parse(&libraryArgVector.GetVector(), &unknownArgs); runtimeArgs.Parse(&runtimeArgVector.GetVector(), &unknownArgs); + objectArgs.Parse(&objectArgVector.GetVector(), &unknownArgs); frameworkArgs.Parse(&frameworkArgVector.GetVector(), &unknownArgs); bundleArgs.Parse(&bundleArgVector.GetVector(), &unknownArgs); privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs); @@ -265,6 +270,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) archiveArgs.SetGenericArguments(&genericArgs); libraryArgs.SetGenericArguments(&genericArgs); runtimeArgs.SetGenericArguments(&genericArgs); + objectArgs.SetGenericArguments(&genericArgs); frameworkArgs.SetGenericArguments(&genericArgs); bundleArgs.SetGenericArguments(&genericArgs); privateHeaderArgs.SetGenericArguments(&genericArgs); @@ -274,6 +280,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) success = success && archiveArgs.Finalize(); success = success && libraryArgs.Finalize(); success = success && runtimeArgs.Finalize(); + success = success && objectArgs.Finalize(); success = success && frameworkArgs.Finalize(); success = success && bundleArgs.Finalize(); success = success && privateHeaderArgs.Finalize(); @@ -287,8 +294,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) // Enforce argument rules too complex to specify for the // general-purpose parser. if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() || - frameworkArgs.GetNamelinkOnly() || bundleArgs.GetNamelinkOnly() || - privateHeaderArgs.GetNamelinkOnly() || + objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() || + bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() || publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) { this->SetError( "TARGETS given NAMELINK_ONLY option not in LIBRARY group. " @@ -296,8 +303,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) return false; } if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() || - frameworkArgs.GetNamelinkSkip() || bundleArgs.GetNamelinkSkip() || - privateHeaderArgs.GetNamelinkSkip() || + objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() || + bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() || publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) { this->SetError( "TARGETS given NAMELINK_SKIP option not in LIBRARY group. " @@ -356,11 +363,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) return false; } if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - std::ostringstream e; - e << "TARGETS given OBJECT library \"" << (*targetIt) - << "\" which may not be installed."; - this->SetError(e.str()); - return false; + std::string reason; + if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation( + &reason)) { + std::ostringstream e; + e << "TARGETS given OBJECT library \"" << (*targetIt) + << "\" which may not be installed" << reason << "."; + this->SetError(e.str()); + return false; + } } // Store the target in the list to be installed. targets.push_back(target); @@ -379,6 +390,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) bool installsArchive = false; bool installsLibrary = false; bool installsRuntime = false; + bool installsObject = false; bool installsFramework = false; bool installsBundle = false; bool installsPrivateHeader = false; @@ -393,6 +405,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) cmInstallTargetGenerator* archiveGenerator = CM_NULLPTR; cmInstallTargetGenerator* libraryGenerator = CM_NULLPTR; cmInstallTargetGenerator* runtimeGenerator = CM_NULLPTR; + cmInstallTargetGenerator* objectGenerator = CM_NULLPTR; cmInstallTargetGenerator* frameworkGenerator = CM_NULLPTR; cmInstallTargetGenerator* bundleGenerator = CM_NULLPTR; cmInstallFilesGenerator* privateHeaderGenerator = CM_NULLPTR; @@ -522,6 +535,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) return false; } } break; + case cmStateEnums::OBJECT_LIBRARY: { + // Objects use OBJECT properties. + if (!objectArgs.GetDestination().empty()) { + objectGenerator = + CreateInstallTargetGenerator(target, objectArgs, false); + } else { + std::ostringstream e; + e << "TARGETS given no OBJECTS DESTINATION for object library " + "target \"" + << target.GetName() << "\"."; + this->SetError(e.str()); + return false; + } + } break; case cmStateEnums::EXECUTABLE: { if (target.IsAppBundleOnApple()) { // Application bundles use the BUNDLE properties. @@ -664,6 +691,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) installsArchive = installsArchive || archiveGenerator != CM_NULLPTR; installsLibrary = installsLibrary || libraryGenerator != CM_NULLPTR; installsRuntime = installsRuntime || runtimeGenerator != CM_NULLPTR; + installsObject = installsObject || objectGenerator != CM_NULLPTR; installsFramework = installsFramework || frameworkGenerator != CM_NULLPTR; installsBundle = installsBundle || bundleGenerator != CM_NULLPTR; installsPrivateHeader = @@ -675,6 +703,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) this->Makefile->AddInstallGenerator(archiveGenerator); this->Makefile->AddInstallGenerator(libraryGenerator); this->Makefile->AddInstallGenerator(runtimeGenerator); + this->Makefile->AddInstallGenerator(objectGenerator); this->Makefile->AddInstallGenerator(frameworkGenerator); this->Makefile->AddInstallGenerator(bundleGenerator); this->Makefile->AddInstallGenerator(privateHeaderGenerator); @@ -692,6 +721,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) te->HeaderGenerator = publicHeaderGenerator; te->LibraryGenerator = libraryGenerator; te->RuntimeGenerator = runtimeGenerator; + te->ObjectsGenerator = objectGenerator; this->Makefile->GetGlobalGenerator() ->GetExportSets()[exports.GetString()] ->AddTargetExport(te); @@ -715,6 +745,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) this->Makefile->GetGlobalGenerator()->AddInstallComponent( runtimeArgs.GetComponent().c_str()); } + if (installsObject) { + this->Makefile->GetGlobalGenerator()->AddInstallComponent( + objectArgs.GetComponent().c_str()); + } if (installsFramework) { this->Makefile->GetGlobalGenerator()->AddInstallComponent( frameworkArgs.GetComponent().c_str()); @@ -1176,7 +1210,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode( // Check the file name. std::string fname = filename.GetString(); - if (fname.find_first_of(":/\\") != fname.npos) { + if (fname.find_first_of(":/\\") != std::string::npos) { std::ostringstream e; e << args[0] << " given invalid export file name \"" << fname << "\". " << "The FILE argument may not contain a path. " @@ -1194,7 +1228,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode( this->SetError(e.str()); return false; } - if (fname.find_first_of(":/\\") != fname.npos) { + if (fname.find_first_of(":/\\") != std::string::npos) { std::ostringstream e; e << args[0] << " given export name \"" << exp.GetString() << "\". " << "This name cannot be safely converted to a file name. " @@ -1268,7 +1302,7 @@ bool cmInstallCommand::HandleExportMode(std::vector const& args) // Check the file name. std::string fname = filename.GetString(); - if (fname.find_first_of(":/\\") != fname.npos) { + if (fname.find_first_of(":/\\") != std::string::npos) { std::ostringstream e; e << args[0] << " given invalid export file name \"" << fname << "\". " << "The FILE argument may not contain a path. " @@ -1292,7 +1326,7 @@ bool cmInstallCommand::HandleExportMode(std::vector const& args) fname = exp.GetString(); fname += ".cmake"; - if (fname.find_first_of(":/\\") != fname.npos) { + if (fname.find_first_of(":/\\") != std::string::npos) { std::ostringstream e; e << args[0] << " given export name \"" << exp.GetString() << "\". " << "This name cannot be safely converted to a file name. " @@ -1357,7 +1391,7 @@ bool cmInstallCommand::MakeFilesFullPath( } // Make sure the file is not a directory. - if (gpos == file.npos && cmSystemTools::FileIsDirectory(file)) { + if (gpos == std::string::npos && cmSystemTools::FileIsDirectory(file)) { std::ostringstream e; e << modeName << " given directory \"" << (*fileIt) << "\" to install."; this->SetError(e.str()); @@ -1372,11 +1406,11 @@ bool cmInstallCommand::MakeFilesFullPath( bool cmInstallCommand::CheckCMP0006(bool& failure) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) { - case cmPolicies::WARN: { + case cmPolicies::WARN: this->Makefile->IssueMessage( cmake::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0006)); - } + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to allow compatibility return true; diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 187a6ceae..f5d1f9265 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -3,7 +3,8 @@ #ifndef cmInstallCommand_h #define cmInstallCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "install"; } - private: bool HandleScriptMode(std::vector const& args); bool HandleTargetsMode(std::vector const& args); diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx index 6b1546868..b73414dd0 100644 --- a/Source/cmInstallCommandArguments.cxx +++ b/Source/cmInstallCommandArguments.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallCommandArguments.h" -#include +#include "cmConfigure.h" #include "cmSystemTools.h" diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index c1523b235..a576e7202 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -3,7 +3,7 @@ #ifndef cmInstallCommandArguments_h #define cmInstallCommandArguments_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index dfb3aebe3..54ad85c3b 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -48,7 +48,7 @@ void cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg) } void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os, - Indent const& indent) + Indent indent) { if (this->ActionsPerConfig) { this->cmInstallGenerator::GenerateScriptActions(os, indent); @@ -58,7 +58,7 @@ void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os, } void cmInstallDirectoryGenerator::GenerateScriptForConfig( - std::ostream& os, const std::string& config, Indent const& indent) + std::ostream& os, const std::string& config, Indent indent) { std::vector dirs; cmGeneratorExpression ge; @@ -82,7 +82,7 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig( } void cmInstallDirectoryGenerator::AddDirectoryInstallRule( - std::ostream& os, const std::string& config, Indent const& indent, + std::ostream& os, const std::string& config, Indent indent, std::vector const& dirs) { // Write code to install the directories. diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h index 0518092c8..aa2cbc690 100644 --- a/Source/cmInstallDirectoryGenerator.h +++ b/Source/cmInstallDirectoryGenerator.h @@ -6,7 +6,8 @@ #include "cmInstallGenerator.h" #include "cmScriptGenerator.h" -#include +#include "cmConfigure.h" + #include #include #include @@ -33,12 +34,11 @@ public: std::string GetDestination(std::string const& config) const; protected: - void GenerateScriptActions(std::ostream& os, - Indent const& indent) CM_OVERRIDE; + void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE; void GenerateScriptForConfig(std::ostream& os, const std::string& config, - Indent const& indent) CM_OVERRIDE; + Indent indent) CM_OVERRIDE; void AddDirectoryInstallRule(std::ostream& os, const std::string& config, - Indent const& indent, + Indent indent, std::vector const& dirs); cmLocalGenerator* LocalGenerator; std::vector Directories; diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 39fab4fc0..b176e85c5 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -166,7 +166,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os) } void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os, - Indent const& indent) + Indent indent) { // Create the main install rules first. this->cmInstallGenerator::GenerateScriptConfigs(os, indent); @@ -189,7 +189,7 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os, } void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, - Indent const& indent) + Indent indent) { // Remove old per-configuration export files if the main changes. std::string installedDir = "$ENV{DESTDIR}"; diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index b0fe88916..047e6b3cd 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -3,7 +3,7 @@ #ifndef cmInstallExportGenerator_h #define cmInstallExportGenerator_h -#include +#include "cmConfigure.h" #include "cmInstallGenerator.h" #include "cmScriptGenerator.h" @@ -44,10 +44,8 @@ public: protected: void GenerateScript(std::ostream& os) CM_OVERRIDE; - void GenerateScriptConfigs(std::ostream& os, - Indent const& indent) CM_OVERRIDE; - void GenerateScriptActions(std::ostream& os, - Indent const& indent) CM_OVERRIDE; + void GenerateScriptConfigs(std::ostream& os, Indent indent) CM_OVERRIDE; + void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE; void GenerateImportFile(cmExportSet const* exportSet); void GenerateImportFile(const char* config, cmExportSet const* exportSet); void ComputeTempDir(); diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index 86fd46dbb..4a3b620af 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -54,7 +54,7 @@ void cmInstallFilesCommand::FinalPass() } std::string testf; - std::string ext = this->FinalArgs[0]; + std::string const& ext = this->FinalArgs[0]; // two different options if (this->FinalArgs.size() > 1) { @@ -64,7 +64,7 @@ void cmInstallFilesCommand::FinalPass() // for each argument, get the files for (; s != this->FinalArgs.end(); ++s) { // replace any variables - std::string temps = *s; + std::string const& temps = *s; if (!cmSystemTools::GetFilenamePath(temps).empty()) { testf = cmSystemTools::GetFilenamePath(temps) + "/" + cmSystemTools::GetFilenameWithoutLastExtension(temps) + ext; @@ -78,7 +78,7 @@ void cmInstallFilesCommand::FinalPass() } else // reg exp list { std::vector files; - std::string regex = this->FinalArgs[0]; + std::string const& regex = this->FinalArgs[0]; cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(), regex, files); diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h index c3e291964..b3c27b827 100644 --- a/Source/cmInstallFilesCommand.h +++ b/Source/cmInstallFilesCommand.h @@ -3,7 +3,8 @@ #ifndef cmInstallFilesCommand_h #define cmInstallFilesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "install_files"; } - /** * This is called at the end after all the information * specified by the command is accumulated. Most commands do diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 7daea385b..6323a9189 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -54,7 +54,7 @@ std::string cmInstallFilesGenerator::GetDestination( } void cmInstallFilesGenerator::AddFilesInstallRule( - std::ostream& os, std::string const& config, Indent const& indent, + std::ostream& os, std::string const& config, Indent indent, std::vector const& files) { // Write code to install the files. @@ -67,7 +67,7 @@ void cmInstallFilesGenerator::AddFilesInstallRule( } void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os, - Indent const& indent) + Indent indent) { if (this->ActionsPerConfig) { this->cmInstallGenerator::GenerateScriptActions(os, indent); @@ -77,7 +77,7 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os, } void cmInstallFilesGenerator::GenerateScriptForConfig( - std::ostream& os, const std::string& config, Indent const& indent) + std::ostream& os, const std::string& config, Indent indent) { std::vector files; cmGeneratorExpression ge; diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index ca8c6e110..62b57f9c7 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -3,7 +3,7 @@ #ifndef cmInstallFilesGenerator_h #define cmInstallFilesGenerator_h -#include +#include "cmConfigure.h" #include "cmInstallGenerator.h" #include "cmScriptGenerator.h" @@ -34,12 +34,11 @@ public: std::string GetDestination(std::string const& config) const; protected: - void GenerateScriptActions(std::ostream& os, - Indent const& indent) CM_OVERRIDE; + void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE; void GenerateScriptForConfig(std::ostream& os, const std::string& config, - Indent const& indent) CM_OVERRIDE; + Indent indent) CM_OVERRIDE; void AddFilesInstallRule(std::ostream& os, std::string const& config, - Indent const& indent, + Indent indent, std::vector const& files); cmLocalGenerator* LocalGenerator; diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index 120d1b3aa..13b588efb 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -27,7 +27,7 @@ void cmInstallGenerator::AddInstallRule( std::vector const& files, bool optional /* = false */, const char* permissions_file /* = 0 */, const char* permissions_dir /* = 0 */, const char* rename /* = 0 */, - const char* literal_args /* = 0 */, Indent const& indent) + const char* literal_args /* = 0 */, Indent indent) { // Use the FILE command to install the file. std::string stype; diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index 48e1644ee..8f8701f1a 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -3,7 +3,7 @@ #ifndef cmInstallGenerator_h #define cmInstallGenerator_h -#include +#include "cmConfigure.h" #include "cmInstallType.h" #include "cmScriptGenerator.h" @@ -21,6 +21,8 @@ class cmMakefile; */ class cmInstallGenerator : public cmScriptGenerator { + CM_DISABLE_COPY(cmInstallGenerator) + public: enum MessageLevel { @@ -41,7 +43,7 @@ public: std::vector const& files, bool optional = false, const char* permissions_file = CM_NULLPTR, const char* permissions_dir = CM_NULLPTR, const char* rename = CM_NULLPTR, - const char* literal_args = CM_NULLPTR, Indent const& indent = Indent()); + const char* literal_args = CM_NULLPTR, Indent indent = Indent()); /** Get the install destination as it should appear in the installation script. */ diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h index ca07a2f39..242fb953d 100644 --- a/Source/cmInstallProgramsCommand.h +++ b/Source/cmInstallProgramsCommand.h @@ -3,7 +3,8 @@ #ifndef cmInstallProgramsCommand_h #define cmInstallProgramsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "install_programs"; } - /** * This is called at the end after all the information * specified by the command is accumulated. Most commands do diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h index 0b54994d3..e183999d0 100644 --- a/Source/cmInstallScriptGenerator.h +++ b/Source/cmInstallScriptGenerator.h @@ -3,7 +3,7 @@ #ifndef cmInstallScriptGenerator_h #define cmInstallScriptGenerator_h -#include +#include "cmConfigure.h" #include "cmInstallGenerator.h" diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 88fcc56ac..84d6f7ac9 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -58,27 +58,8 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os) } void cmInstallTargetGenerator::GenerateScriptForConfig( - std::ostream& os, const std::string& config, Indent const& indent) + std::ostream& os, const std::string& config, Indent indent) { - // Compute the build tree directory from which to copy the target. - std::string fromDirConfig; - if (this->Target->NeedRelinkBeforeInstall(config)) { - fromDirConfig = - this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(); - fromDirConfig += cmake::GetCMakeFilesDirectory(); - fromDirConfig += "/CMakeRelink.dir/"; - } else { - fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary); - fromDirConfig += "/"; - } - std::string toDir = - this->ConvertToAbsoluteDestination(this->GetDestination(config)); - toDir += "/"; - - // Compute the list of files to install for this target. - std::vector filesFrom; - std::vector filesTo; - std::string literal_args; cmStateEnums::TargetType targetType = this->Target->GetType(); cmInstallType type = cmInstallType(); switch (targetType) { @@ -100,7 +81,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( assert(false && "INTERFACE_LIBRARY targets have no installable outputs."); break; + case cmStateEnums::OBJECT_LIBRARY: + this->GenerateScriptForConfigObjectLibrary(os, config, indent); + return; + case cmStateEnums::UTILITY: case cmStateEnums::GLOBAL_TARGET: case cmStateEnums::UNKNOWN_LIBRARY: @@ -109,6 +94,31 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( "cmInstallTargetGenerator created with non-installable target."); return; } + + // Compute the build tree directory from which to copy the target. + std::string fromDirConfig; + if (this->Target->NeedRelinkBeforeInstall(config)) { + fromDirConfig = + this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(); + fromDirConfig += cmake::GetCMakeFilesDirectory(); + fromDirConfig += "/CMakeRelink.dir/"; + } else { + cmStateEnums::ArtifactType artifact = this->ImportLibrary + ? cmStateEnums::ImportLibraryArtifact + : cmStateEnums::RuntimeBinaryArtifact; + fromDirConfig = this->Target->GetDirectory(config, artifact); + fromDirConfig += "/"; + } + + std::string toDir = + this->ConvertToAbsoluteDestination(this->GetDestination(config)); + toDir += "/"; + + // Compute the list of files to install for this target. + std::vector filesFrom; + std::vector filesTo; + std::string literal_args; + if (targetType == cmStateEnums::EXECUTABLE) { // There is a bug in cmInstallCommand if this fails. assert(this->NamelinkMode == NamelinkModeNone); @@ -315,6 +325,49 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( &cmInstallTargetGenerator::PostReplacementTweaks); } +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 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 = CM_NULLPTR; + const char* no_rename = CM_NULLPTR; + this->AddInstallRule(os, dest, cmInstallType_FILES, objects, this->Optional, + this->FilePermissions.c_str(), no_dir_permissions, + no_rename, literal_args.c_str(), indent); +} + +void cmInstallTargetGenerator::GetInstallObjectNames( + std::string const& config, std::vector& objects) const +{ + this->Target->GetTargetObjectNames(config, objects); + for (std::vector::iterator i = objects.begin(); + i != objects.end(); ++i) { + *i = computeInstallObjectDir(this->Target, config) + "/" + *i; + } +} + std::string cmInstallTargetGenerator::GetDestination( std::string const& config) const { @@ -391,7 +444,7 @@ void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg) this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName); } -void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent, +void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent, const std::string& config, std::string const& file, TweakMethod tweak) @@ -407,7 +460,7 @@ void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent, } } -void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent, +void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent, const std::string& config, std::vector const& files, TweakMethod tweak) @@ -447,7 +500,7 @@ std::string cmInstallTargetGenerator::GetDestDirPath(std::string const& file) } void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os, - Indent const& indent, + Indent indent, const std::string& config, std::string const& file) { @@ -455,7 +508,7 @@ void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os, } void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os, - Indent const& indent, + Indent indent, const std::string& config, std::string const& file) { @@ -467,7 +520,7 @@ void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os, } void cmInstallTargetGenerator::AddInstallNamePatchRule( - std::ostream& os, Indent const& indent, const std::string& config, + std::ostream& os, Indent indent, const std::string& config, std::string const& toDestDirPath) { if (this->ImportLibrary || @@ -568,7 +621,7 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule( } void cmInstallTargetGenerator::AddRPathCheckRule( - std::ostream& os, Indent const& indent, const std::string& config, + std::ostream& os, Indent indent, const std::string& config, std::string const& toDestDirPath) { // Skip the chrpath if the target does not need it. @@ -602,7 +655,7 @@ void cmInstallTargetGenerator::AddRPathCheckRule( } void cmInstallTargetGenerator::AddChrpathPatchRule( - std::ostream& os, Indent const& indent, const std::string& config, + std::ostream& os, Indent indent, const std::string& config, std::string const& toDestDirPath) { // Skip the chrpath if the target does not need it. @@ -697,8 +750,7 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( } } -void cmInstallTargetGenerator::AddStripRule(std::ostream& os, - Indent const& indent, +void cmInstallTargetGenerator::AddStripRule(std::ostream& os, Indent indent, const std::string& toDestDirPath) { @@ -726,8 +778,7 @@ void cmInstallTargetGenerator::AddStripRule(std::ostream& os, os << indent << "endif()\n"; } -void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, - Indent const& indent, +void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, Indent indent, const std::string& toDestDirPath) { // Static libraries need ranlib on this platform. @@ -752,7 +803,7 @@ void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, } void cmInstallTargetGenerator::AddUniversalInstallRule( - std::ostream& os, Indent const& indent, const std::string& toDestDirPath) + std::ostream& os, Indent indent, const std::string& toDestDirPath) { cmMakefile const* mf = this->Target->Target->GetMakefile(); diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 084a0333d..cf2de58f9 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmInstallTargetGenerator_h #define cmInstallTargetGenerator_h -#include +#include "cmConfigure.h" #include "cmInstallGenerator.h" #include "cmScriptGenerator.h" @@ -41,6 +41,9 @@ public: std::string GetInstallFilename(const std::string& config) const; + void GetInstallObjectNames(std::string const& config, + std::vector& objects) const; + enum NameType { NameNormal, @@ -64,39 +67,39 @@ public: protected: void GenerateScript(std::ostream& os) CM_OVERRIDE; void GenerateScriptForConfig(std::ostream& os, const std::string& config, - Indent const& indent) CM_OVERRIDE; - typedef void (cmInstallTargetGenerator::*TweakMethod)(std::ostream&, - Indent const&, + Indent indent) CM_OVERRIDE; + void GenerateScriptForConfigObjectLibrary(std::ostream& os, + const std::string& config, + Indent indent); + typedef void (cmInstallTargetGenerator::*TweakMethod)(std::ostream&, Indent, const std::string&, std::string const&); - void AddTweak(std::ostream& os, Indent const& indent, - const std::string& config, std::string const& file, - TweakMethod tweak); - void AddTweak(std::ostream& os, Indent const& indent, - const std::string& config, + 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 const& files, TweakMethod tweak); std::string GetDestDirPath(std::string const& file); - void PreReplacementTweaks(std::ostream& os, Indent const& indent, + void PreReplacementTweaks(std::ostream& os, Indent indent, const std::string& config, std::string const& file); - void PostReplacementTweaks(std::ostream& os, Indent const& indent, + void PostReplacementTweaks(std::ostream& os, Indent indent, const std::string& config, std::string const& file); - void AddInstallNamePatchRule(std::ostream& os, Indent const& indent, + void AddInstallNamePatchRule(std::ostream& os, Indent indent, const std::string& config, const std::string& toDestDirPath); - void AddChrpathPatchRule(std::ostream& os, Indent const& indent, + void AddChrpathPatchRule(std::ostream& os, Indent indent, const std::string& config, std::string const& toDestDirPath); - void AddRPathCheckRule(std::ostream& os, Indent const& indent, + void AddRPathCheckRule(std::ostream& os, Indent indent, const std::string& config, std::string const& toDestDirPath); - void AddStripRule(std::ostream& os, Indent const& indent, + void AddStripRule(std::ostream& os, Indent indent, const std::string& toDestDirPath); - void AddRanlibRule(std::ostream& os, Indent const& indent, + void AddRanlibRule(std::ostream& os, Indent indent, const std::string& toDestDirPath); - void AddUniversalInstallRule(std::ostream& os, Indent const& indent, + void AddUniversalInstallRule(std::ostream& os, Indent indent, const std::string& toDestDirPath); std::string TargetName; diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h index 150397d34..cc8484365 100644 --- a/Source/cmInstallTargetsCommand.h +++ b/Source/cmInstallTargetsCommand.h @@ -3,7 +3,8 @@ #ifndef cmInstallTargetsCommand_h #define cmInstallTargetsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "install_targets"; } }; #endif diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 8dd42b6d4..d51fd8d74 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -7,7 +7,7 @@ #include "cmMakefile.h" #include "cmSystemTools.h" -#include +#include "cmConfigure.h" #include cmInstalledFile::cmInstalledFile() diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index 4fe813462..fbf754ffd 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -3,6 +3,8 @@ #ifndef cmInstalledFile_h #define cmInstalledFile_h +#include "cmConfigure.h" // IWYU pragma: keep + #include "cmGeneratorExpression.h" #include "cm_auto_ptr.hxx" diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index f86329249..9b0c28817 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -49,6 +49,7 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir) case cmPolicies::REQUIRED_ALWAYS: e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015); this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior converts convertToAbsolute = true; diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h index 387b3b94f..b64e48d70 100644 --- a/Source/cmLinkDirectoriesCommand.h +++ b/Source/cmLinkDirectoriesCommand.h @@ -3,7 +3,8 @@ #ifndef cmLinkDirectoriesCommand_h #define cmLinkDirectoriesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -34,11 +35,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "link_directories"; } - private: void AddLinkDir(std::string const& dir); }; diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 6fd6f500f..f0fded21f 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -3,7 +3,7 @@ #ifndef cmLinkItem_h #define cmLinkItem_h -#include +#include "cmConfigure.h" #include #include @@ -32,11 +32,6 @@ public: , Target(t) { } - cmLinkItem(cmLinkItem const& r) - : std_string(r) - , Target(r.Target) - { - } cmGeneratorTarget const* Target; }; @@ -56,12 +51,6 @@ public: , FromGenex(fromGenex) { } - cmLinkImplItem(cmLinkImplItem const& r) - : cmLinkItem(r) - , Backtrace(r.Backtrace) - , FromGenex(r.FromGenex) - { - } cmListFileBacktrace Backtrace; bool FromGenex; }; diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h index 66d7ec4f4..f1b3a6816 100644 --- a/Source/cmLinkLibrariesCommand.h +++ b/Source/cmLinkLibrariesCommand.h @@ -3,7 +3,8 @@ #ifndef cmLinkLibrariesCommand_h #define cmLinkLibrariesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "link_libraries"; } }; #endif diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index e728632bd..c0f702e25 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -13,7 +13,7 @@ #include "cmStateTypes.h" cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, - cmStateDirectory stateDir) + cmStateDirectory const& stateDir) : StateDir(stateDir) , OutputConverter(outputConverter) , ForResponse(false) diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index 57a70bc4d..d33e8d1ff 100644 --- a/Source/cmLinkLineComputer.h +++ b/Source/cmLinkLineComputer.h @@ -4,7 +4,7 @@ #ifndef cmLinkLineComputer_h #define cmLinkLineComputer_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include @@ -16,9 +16,11 @@ class cmOutputConverter; class cmLinkLineComputer { + CM_DISABLE_COPY(cmLinkLineComputer) + public: cmLinkLineComputer(cmOutputConverter* outputConverter, - cmStateDirectory stateDir); + cmStateDirectory const& stateDir); virtual ~cmLinkLineComputer(); void SetUseWatcomQuote(bool useWatcomQuote); diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 6a700ff15..942e9b92c 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -2,13 +2,20 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLinkLineDeviceComputer.h" + +#include +#include +#include + #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" -#include "cmOutputConverter.h" +#include "cmStateTypes.h" + +class cmOutputConverter; cmLinkLineDeviceComputer::cmLinkLineDeviceComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir) + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) : cmLinkLineComputer(outputConverter, stateDir) { } @@ -31,9 +38,24 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( continue; } - if (li->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY || - li->Target->GetType() == cmStateEnums::SHARED_LIBRARY || - li->Target->GetType() == cmStateEnums::MODULE_LIBRARY) { + bool skippable = false; + switch (li->Target->GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::INTERFACE_LIBRARY: + skippable = true; + break; + case cmStateEnums::STATIC_LIBRARY: + // If a static library is resolving its device linking, it should + // be removed for other device linking + skippable = + li->Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); + break; + default: + break; + } + + if (skippable) { continue; } @@ -66,7 +88,7 @@ std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*, } cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir, + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir, cmGlobalNinjaGenerator const* gg) : cmLinkLineDeviceComputer(outputConverter, stateDir) , GG(gg) diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h index f4bb3ebfb..c3fac6182 100644 --- a/Source/cmLinkLineDeviceComputer.h +++ b/Source/cmLinkLineDeviceComputer.h @@ -4,14 +4,25 @@ #ifndef cmLinkLineDeviceComputer_h #define cmLinkLineDeviceComputer_h +#include "cmConfigure.h" + +#include + #include "cmLinkLineComputer.h" + +class cmComputeLinkInformation; +class cmGeneratorTarget; class cmGlobalNinjaGenerator; +class cmOutputConverter; +class cmStateDirectory; class cmLinkLineDeviceComputer : public cmLinkLineComputer { + CM_DISABLE_COPY(cmLinkLineDeviceComputer) + public: cmLinkLineDeviceComputer(cmOutputConverter* outputConverter, - cmStateDirectory stateDir); + cmStateDirectory const& stateDir); ~cmLinkLineDeviceComputer() CM_OVERRIDE; std::string ComputeLinkLibraries(cmComputeLinkInformation& cli, @@ -24,9 +35,11 @@ public: class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer { + CM_DISABLE_COPY(cmNinjaLinkLineDeviceComputer) + public: cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter, - cmStateDirectory stateDir, + cmStateDirectory const& stateDir, cmGlobalNinjaGenerator const* gg); std::string ConvertToLinkReference(std::string const& input) const diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h index 4f9552260..55592cb35 100644 --- a/Source/cmLinkedTree.h +++ b/Source/cmLinkedTree.h @@ -3,7 +3,7 @@ #ifndef cmLinkedTree_h #define cmLinkedTree_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 295ea288f..0542c4fce 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmListCommand.h" +#include "cmsys/RegularExpression.hxx" #include #include -#include #include #include #include diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h index e7413caa9..7789f7df1 100644 --- a/Source/cmListCommand.h +++ b/Source/cmListCommand.h @@ -3,7 +3,8 @@ #ifndef cmListCommand_h #define cmListCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "list"; } - protected: bool HandleLengthCommand(std::vector const& args); bool HandleGetCommand(std::vector const& args); diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index b1cd8891a..0c73cd725 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -9,14 +9,14 @@ #include "cmSystemTools.h" #include "cmake.h" +#include "cmConfigure.h" #include #include -#include #include struct cmListFileParser { - cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, + cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt, cmMessenger* messenger, const char* filename); ~cmListFileParser(); void IssueFileOpenError(std::string const& text) const; @@ -39,7 +39,8 @@ struct cmListFileParser } Separation; }; -cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, +cmListFileParser::cmListFileParser(cmListFile* lf, + cmListFileBacktrace const& lfbt, cmMessenger* messenger, const char* filename) : ListFile(lf) @@ -80,6 +81,13 @@ bool cmListFileParser::ParseFile() return false; } + if (bom == cmListFileLexer_BOM_Broken) { + cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); + this->IssueFileOpenError("Error while reading Byte-Order-Mark. " + "File not seekable?"); + return false; + } + // Verify the Byte-Order-Mark, if any. if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) { cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); @@ -299,7 +307,8 @@ struct cmListFileBacktrace::Entry : public cmListFileContext unsigned int RefCount; }; -cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot bottom, Entry* up, +cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom, + Entry* up, cmListFileContext const& lfc) : Bottom(bottom) , Cur(new Entry(lfc, up)) @@ -308,7 +317,8 @@ cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot bottom, Entry* up, this->Cur->Ref(); } -cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot bottom, Entry* cur) +cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom, + Entry* cur) : Bottom(bottom) , Cur(cur) { @@ -324,7 +334,7 @@ cmListFileBacktrace::cmListFileBacktrace() { } -cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot snapshot) +cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot) : Bottom(snapshot.GetCallStackBottom()) , Cur(CM_NULLPTR) { diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 1a30f2908..349ddef91 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -3,7 +3,7 @@ #ifndef cmListFileCache_h #define cmListFileCache_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -45,12 +45,6 @@ struct cmListFileArgument , Line(0) { } - cmListFileArgument(const cmListFileArgument& r) - : Value(r.Value) - , Delim(r.Delim) - , Line(r.Line) - { - } cmListFileArgument(const std::string& v, Delimiter d, long line) : Value(v) , Delim(d) @@ -113,7 +107,7 @@ public: // Construct an empty backtrace whose bottom sits in the directory // indicated by the given valid snapshot. - cmListFileBacktrace(cmStateSnapshot snapshot); + cmListFileBacktrace(cmStateSnapshot const& snapshot); // Backtraces may be copied and assigned as values. cmListFileBacktrace(cmListFileBacktrace const& r); @@ -149,9 +143,9 @@ private: cmStateSnapshot Bottom; Entry* Cur; - cmListFileBacktrace(cmStateSnapshot bottom, Entry* up, + cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* up, cmListFileContext const& lfc); - cmListFileBacktrace(cmStateSnapshot bottom, Entry* cur); + cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* cur); }; struct cmListFile diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h index c9fb6da1d..f243010ad 100644 --- a/Source/cmListFileLexer.h +++ b/Source/cmListFileLexer.h @@ -32,6 +32,7 @@ struct cmListFileLexer_Token_s enum cmListFileLexer_BOM_e { cmListFileLexer_BOM_None, + cmListFileLexer_BOM_Broken, cmListFileLexer_BOM_UTF8, cmListFileLexer_BOM_UTF16BE, cmListFileLexer_BOM_UTF16LE, diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index ea84877a9..00a30bf0e 100644 --- a/Source/cmLoadCacheCommand.cxx +++ b/Source/cmLoadCacheCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLoadCacheCommand.h" -#include +#include "cmsys/FStream.hxx" #include "cmMakefile.h" #include "cmStateTypes.h" diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h index 539c74e62..1a8a0fc4c 100644 --- a/Source/cmLoadCacheCommand.h +++ b/Source/cmLoadCacheCommand.h @@ -3,7 +3,8 @@ #ifndef cmLoadCacheCommand_h #define cmLoadCacheCommand_h -#include +#include "cmConfigure.h" + #include #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "load_cache"; } - protected: std::set VariablesToRead; std::string Prefix; diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index b6743f144..92a32a147 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -2,22 +2,21 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLoadCommandCommand.h" +#include +#include +#include +#include +#include + #include "cmCPluginAPI.cxx" #include "cmCPluginAPI.h" #include "cmDynamicLoader.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmState.h" #include "cmSystemTools.h" class cmExecutionStatus; -#include -#include -#include -#include -#include - #ifdef __QNX__ #include /* for malloc/free on QNX */ #endif @@ -67,11 +66,6 @@ public: return this->info.FinalPass != CM_NULLPTR; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return info.Name; } - static const char* LastName; static void TrapsForSignals(int sig) { @@ -174,11 +168,6 @@ cmLoadedCommand::~cmLoadedCommand() bool cmLoadCommandCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0031, - "The load_command command should not be called; see CMP0031.")) { - return true; - } if (args.empty()) { return true; } @@ -252,7 +241,7 @@ bool cmLoadCommandCommand::InitialPass(std::vector const& args, // create a function blocker and set it up cmLoadedCommand* f = new cmLoadedCommand(); (*initFunction)(&f->info); - this->Makefile->GetState()->AddCommand(f); + this->Makefile->GetState()->AddScriptedCommand(args[0], f); return true; } this->SetError("Attempt to load command failed. " diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h index d16dfeaa2..030786e3d 100644 --- a/Source/cmLoadCommandCommand.h +++ b/Source/cmLoadCommandCommand.h @@ -3,7 +3,8 @@ #ifndef cmLoadCommandCommand_h #define cmLoadCommandCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -17,7 +18,6 @@ public: cmCommand* Clone() CM_OVERRIDE { return new cmLoadCommandCommand; } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "load_command"; } }; #endif diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index d5f9d27cd..6524db401 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -15,14 +15,6 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg, std::string const& wd) : cmLocalGenerator(gg, mf) , WorkingDirectory(wd) -{ -} - -cmLocalCommonGenerator::~cmLocalCommonGenerator() -{ -} - -void cmLocalCommonGenerator::SetConfigName() { // Store the configuration name that will be generated. if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) { @@ -34,6 +26,10 @@ void cmLocalCommonGenerator::SetConfigName() } } +cmLocalCommonGenerator::~cmLocalCommonGenerator() +{ +} + std::string cmLocalCommonGenerator::GetTargetFortranFlags( cmGeneratorTarget const* target, std::string const& config) { diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h index f83f3713e..a5afcd87d 100644 --- a/Source/cmLocalCommonGenerator.h +++ b/Source/cmLocalCommonGenerator.h @@ -3,7 +3,7 @@ #ifndef cmLocalCommonGenerator_h #define cmLocalCommonGenerator_h -#include +#include "cmConfigure.h" #include @@ -33,7 +33,6 @@ public: protected: std::string WorkingDirectory; - void SetConfigName(); std::string ConfigName; friend class cmCommonTargetGenerator; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 7077bbbc9..6ce31c5ea 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -13,7 +13,6 @@ #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" -#include "cmLinkLineDeviceComputer.h" #include "cmMakefile.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -31,9 +30,9 @@ #include "cmCryptoHash.h" #endif +#include "cmsys/RegularExpression.hxx" #include #include -#include #include #include #include @@ -89,7 +88,19 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) std::vector enabledLanguages = this->GetState()->GetEnabledLanguages(); - this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + if (const char* sysrootCompile = + this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { + this->CompilerSysroot = sysrootCompile; + } else { + this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + } + + if (const char* sysrootLink = + this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) { + this->LinkerSysroot = sysrootLink; + } else { + this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + } for (std::vector::iterator i = enabledLanguages.begin(); i != enabledLanguages.end(); ++i) { @@ -129,7 +140,7 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars); replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) { std::string actualReplace = *replaceIter; - if (actualReplace.find("${LANG}") != actualReplace.npos) { + if (actualReplace.find("${LANG}") != std::string::npos) { cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang); } @@ -143,7 +154,8 @@ cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander() const { return new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings, - this->CompilerSysroot); + this->CompilerSysroot, + this->LinkerSysroot); } cmLocalGenerator::~cmLocalGenerator() @@ -559,6 +571,31 @@ void cmLocalGenerator::ComputeTargetManifest() } } +bool cmLocalGenerator::ComputeTargetCompileFeatures() +{ + // Collect the set of configuration types. + std::vector configNames; + this->Makefile->GetConfigurations(configNames); + if (configNames.empty()) { + configNames.push_back(""); + } + + // Process compile features of all targets. + std::vector targets = this->GetGeneratorTargets(); + for (std::vector::iterator t = targets.begin(); + t != targets.end(); ++t) { + cmGeneratorTarget* target = *t; + for (std::vector::iterator ci = configNames.begin(); + ci != configNames.end(); ++ci) { + if (!target->ComputeCompileFeatures(*ci)) { + return false; + } + } + } + + return true; +} + bool cmLocalGenerator::IsRootMakefile() const { return !this->StateSnapshot.GetBuildsystemDirectoryParent().IsValid(); @@ -743,14 +780,6 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, this->AppendFlagEscape(flags, *i); } } - std::vector features; - target->GetCompileFeatures(features, config); - for (std::vector::const_iterator it = features.begin(); - it != features.end(); ++it) { - if (!this->Makefile->AddRequiredTargetFeature(target->Target, *it)) { - return; - } - } for (std::map::const_iterator it = target->GetMaxLanguageStandards().begin(); @@ -827,7 +856,13 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, return; } - std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + std::string rootPath; + if (const char* sysrootCompile = + this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) { + rootPath = sysrootCompile; + } else { + rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"); + } std::vector implicitDirs; // Load implicit include directories for this language. @@ -881,6 +916,20 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector& dirs, } } + // Add standard include directories for this language. + // We do not filter out implicit directories here. + std::string const standardIncludesVar = + "CMAKE_" + lang + "_STANDARD_INCLUDE_DIRECTORIES"; + std::string const standardIncludes = + this->Makefile->GetSafeDefinition(standardIncludesVar); + std::vector::size_type const before = includes.size(); + cmSystemTools::ExpandListArgument(standardIncludes, includes); + for (std::vector::iterator i = includes.begin() + before; + i != includes.end(); ++i) { + cmSystemTools::ConvertToUnixSlashes(*i); + dirs.push_back(*i); + } + for (std::vector::const_iterator i = implicitDirs.begin(); i != implicitDirs.end(); ++i) { if (std::find(includes.begin(), includes.end(), *i) != includes.end()) { @@ -916,12 +965,16 @@ void cmLocalGenerator::GetTargetFlags( const char* libraryLinkVariable = "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library + const std::string linkLanguage = + linkLineComputer->GetLinkerLanguage(target, buildType); + switch (target->GetType()) { case cmStateEnums::STATIC_LIBRARY: this->GetStaticLibraryFlags(linkFlags, buildType, target); break; case cmStateEnums::MODULE_LIBRARY: libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS"; + CM_FALLTHROUGH; case cmStateEnums::SHARED_LIBRARY: { linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable); linkFlags += " "; @@ -977,16 +1030,13 @@ void cmLocalGenerator::GetTargetFlags( linkFlags += this->Makefile->GetSafeDefinition(build); linkFlags += " "; } - - const std::string linkLanguage = - linkLineComputer->GetLinkerLanguage(target, buildType); if (linkLanguage.empty()) { cmSystemTools::Error( "CMake can not determine linker language for target: ", target->GetName().c_str()); return; } - this->AddLanguageFlags(flags, linkLanguage, buildType); + this->AddLanguageFlagsForLinking(flags, target, linkLanguage, buildType); if (pcli) { this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); @@ -1041,6 +1091,8 @@ void cmLocalGenerator::GetTargetFlags( default: break; } + + this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage); } void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, @@ -1051,11 +1103,7 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, cmMakefile* mf = this->GetMakefile(); // Add language-specific flags. - this->AddLanguageFlags(flags, lang, config); - - if (target->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION", config)) { - this->AppendFeatureOptions(flags, lang, "IPO"); - } + this->AddLanguageFlags(flags, target, lang, config); this->AddArchitectureFlags(flags, target, lang, config); @@ -1215,6 +1263,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( /* clang-format on */ this->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to always add the flags add_shlib_flags = true; @@ -1224,6 +1273,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( this->IssueMessage( cmake::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065)); + CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior is to only add the flags if ENABLE_EXPORTS is on add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS"); @@ -1288,6 +1338,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, } void cmLocalGenerator::AddLanguageFlags(std::string& flags, + cmGeneratorTarget const* target, const std::string& lang, const std::string& config) { @@ -1296,6 +1347,26 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, flagsVar += lang; flagsVar += "_FLAGS"; this->AddConfigVariableFlags(flags, flagsVar, config); + + if (target->IsIPOEnabled(lang, config)) { + this->AppendFeatureOptions(flags, lang, "IPO"); + } +} + +void cmLocalGenerator::AddLanguageFlagsForLinking( + std::string& flags, cmGeneratorTarget const* target, const std::string& lang, + const std::string& config) +{ + if (this->Makefile->IsOn("CMAKE_" + lang + + "_LINK_WITH_STANDARD_COMPILE_OPTION")) { + // This toolchain requires use of the language standard flag + // when linking in order to use the matching standard library. + // FIXME: If CMake gains an abstraction for standard library + // selection, this will have to be reconciled with it. + this->AddCompilerRequirementFlag(flags, target, lang); + } + + this->AddLanguageFlags(flags, target, lang, config); } cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse( @@ -1462,7 +1533,11 @@ void cmLocalGenerator::AddCompilerRequirementFlag( "does not know the compile flags to use to enable it."; this->IssueMessage(cmake::FATAL_ERROR, e.str()); } else { - this->AppendFlagEscape(flags, opt); + std::vector optVec; + cmSystemTools::ExpandListArgument(opt, optVec); + for (size_t i = 0; i < optVec.size(); ++i) { + this->AppendFlagEscape(flags, optVec[i]); + } } return; } @@ -1479,6 +1554,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( langStdMap["C"].push_back("99"); langStdMap["C"].push_back("90"); + langStdMap["CUDA"].push_back("14"); langStdMap["CUDA"].push_back("11"); langStdMap["CUDA"].push_back("98"); } @@ -1515,7 +1591,11 @@ void cmLocalGenerator::AddCompilerRequirementFlag( const char* opt = target->Target->GetMakefile()->GetRequiredDefinition(option_flag); - this->AppendFlagEscape(flags, opt); + std::vector optVec; + cmSystemTools::ExpandListArgument(opt, optVec); + for (size_t i = 0; i < optVec.size(); ++i) { + this->AppendFlagEscape(flags, optVec[i]); + } return; } @@ -1525,7 +1605,11 @@ void cmLocalGenerator::AddCompilerRequirementFlag( if (const char* opt = target->Target->GetMakefile()->GetDefinition(option_flag)) { - this->AppendFlagEscape(flags, opt); + std::vector optVec; + cmSystemTools::ExpandListArgument(opt, optVec); + for (size_t i = 0; i < optVec.size(); ++i) { + this->AppendFlagEscape(flags, optVec[i]); + } return; } } @@ -1688,7 +1772,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018); this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); - // fall through to OLD behaviour + CM_FALLTHROUGH; } case cmPolicies::OLD: return true; @@ -1769,6 +1853,38 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags, this->AppendFlags(flags, this->EscapeForShell(rawFlag)); } +void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, + cmGeneratorTarget* target, + const std::string& config, + const std::string& lang) +{ + if (!target->IsIPOEnabled(lang, config)) { + return; + } + + switch (target->GetType()) { + case cmStateEnums::EXECUTABLE: + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + break; + default: + return; + } + + const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO"; + const char* rawFlagsList = this->Makefile->GetDefinition(name); + if (rawFlagsList == CM_NULLPTR) { + return; + } + + std::vector flagsList; + cmSystemTools::ExpandListArgument(rawFlagsList, flagsList); + for (std::vector::const_iterator oi = flagsList.begin(); + oi != flagsList.end(); ++oi) { + this->AppendFlagEscape(flags, *oi); + } +} + void cmLocalGenerator::AppendDefines(std::set& defines, const char* defines_list) const { @@ -1841,7 +1957,7 @@ void cmLocalGenerator::JoinDefines(const std::set& defines, // -DNAME="value" instead of -D"NAME=value" for historical reasons. std::string::size_type eq = defineIt->find("="); def += defineIt->substr(0, eq); - if (eq != defineIt->npos) { + if (eq != std::string::npos) { def += "="; def += this->EscapeForShell(defineIt->c_str() + eq + 1, true); } @@ -2018,7 +2134,7 @@ static bool cmLocalGeneratorShortenObjectName(std::string& objName, // its own md5 sum. std::string::size_type pos = objName.find('/', objName.size() - max_len + 32); - if (pos != objName.npos) { + if (pos != std::string::npos) { cmCryptoHash md5(cmCryptoHash::AlgoMD5); std::string md5name = md5.HashString(objName.substr(0, pos)); md5name += objName.substr(pos); @@ -2163,11 +2279,11 @@ bool cmLocalGenerator::IsNMake() const std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( const cmSourceFile& source, std::string const& dir_max, - bool* hasSourceExtension) + bool* hasSourceExtension, char const* customOutputExtension) { // Construct the object file name using the full path to the source // file which is its only unique identification. - const char* fullPath = source.GetFullPath().c_str(); + std::string const& fullPath = source.GetFullPath(); // Try referencing the source relative to the source tree. std::string relFromSource = @@ -2224,7 +2340,7 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( } // Remove the source extension if it is to be replaced. - if (replaceExt) { + if (replaceExt || customOutputExtension) { keptSourceExtension = false; std::string::size_type dot_pos = objectName.rfind('.'); if (dot_pos != std::string::npos) { @@ -2233,7 +2349,11 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( } // Store the new extension. - objectName += this->GlobalGenerator->GetLanguageOutputExtension(source); + if (customOutputExtension) { + objectName += customOutputExtension; + } else { + objectName += this->GlobalGenerator->GetLanguageOutputExtension(source); + } } if (hasSourceExtension) { *hasSourceExtension = keptSourceExtension; @@ -2365,7 +2485,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const } // Many compilers do not support # in the value so we disable it. - if (define.find_first_of('#') != define.npos) { + if (define.find_first_of('#') != std::string::npos) { std::ostringstream e; /* clang-format off */ e << "WARNING: Preprocessor definitions containing '#' may not be " diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 901ca3541..9f78be465 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -3,9 +3,9 @@ #ifndef cmLocalGenerator_h #define cmLocalGenerator_h -#include +#include "cmConfigure.h" -#include +#include "cm_kwiml.h" #include #include #include @@ -70,6 +70,8 @@ public: */ void ComputeTargetManifest(); + bool ComputeTargetCompileFeatures(); + bool IsRootMakefile() const; ///! Get the makefile for this generator @@ -98,8 +100,12 @@ public: const std::string& lang, const std::string& config); - void AddLanguageFlags(std::string& flags, const std::string& lang, - const std::string& config); + void AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target, + const std::string& lang, const std::string& config); + void AddLanguageFlagsForLinking(std::string& flags, + cmGeneratorTarget const* target, + const std::string& lang, + const std::string& config); void AddCMP0018Flags(std::string& flags, cmGeneratorTarget const* target, std::string const& lang, const std::string& config); void AddVisibilityPresetFlags(std::string& flags, @@ -115,6 +121,9 @@ public: virtual void AppendFlags(std::string& flags, const char* newFlags); virtual void AppendFlagEscape(std::string& flags, const std::string& rawFlag); + void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target, + const std::string& config, + const std::string& lang); ///! Get the include flags for the current makefile and language std::string GetIncludeFlags(const std::vector& includes, cmGeneratorTarget* target, @@ -273,7 +282,8 @@ public: // Compute object file names. std::string GetObjectFileNameWithoutTarget( const cmSourceFile& source, std::string const& dir_max, - bool* hasSourceExtension = CM_NULLPTR); + bool* hasSourceExtension = CM_NULLPTR, + char const* customOutputExtension = CM_NULLPTR); /** Fill out the static linker flags for the given target. */ void GetStaticLibraryFlags(std::string& flags, std::string const& config, @@ -352,6 +362,7 @@ protected: std::map Compilers; std::map VariableMappings; std::string CompilerSysroot; + std::string LinkerSysroot; bool EmitUniversalBinaryFlags; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index c2d9d575e..266710cb1 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -37,8 +37,9 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmRulePlaceholderExpander* cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const { - cmRulePlaceholderExpander* ret = new cmRulePlaceholderExpander( - this->Compilers, this->VariableMappings, this->CompilerSysroot); + cmRulePlaceholderExpander* ret = + new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings, + this->CompilerSysroot, this->LinkerSysroot); ret->SetTargetImpLib("$TARGET_IMPLIB"); return ret; } @@ -57,8 +58,6 @@ void cmLocalNinjaGenerator::Generate() this->HomeRelativeOutputPath = ""; } - this->SetConfigName(); - this->WriteProcessedMakefile(this->GetBuildFileStream()); #ifdef NINJA_GEN_VERBOSE_FILES this->WriteProcessedMakefile(this->GetRulesFileStream()); @@ -214,7 +213,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) std::vector pools; cmSystemTools::ExpandListArgument(jobpools, pools); for (size_t i = 0; i < pools.size(); ++i) { - const std::string pool = pools[i]; + std::string const& pool = pools[i]; const std::string::size_type eq = pool.find('='); unsigned int jobs; if (eq != std::string::npos && @@ -249,12 +248,15 @@ void cmLocalNinjaGenerator::ComputeObjectFilenames( std::map& mapping, cmGeneratorTarget const* gt) { + // Determine if these object files should use a custom extension + char const* custom_ext = gt->GetCustomObjectExtension(); for (std::map::iterator si = mapping.begin(); si != mapping.end(); ++si) { cmSourceFile const* sf = si->first; - si->second = - this->GetObjectFileNameWithoutTarget(*sf, gt->ObjectDirectory); + bool keptSourceExtension; + si->second = this->GetObjectFileNameWithoutTarget( + *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext); } } @@ -278,9 +280,11 @@ void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target, } void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target, - cmNinjaDeps& outputs) + cmNinjaDeps& outputs, + cmNinjaTargetDepends depends) { - this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs); + this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs, + depends); } void cmLocalNinjaGenerator::AppendCustomCommandDeps( @@ -317,7 +321,13 @@ std::string cmLocalNinjaGenerator::BuildCommandLine( } else if (cmdLines.size() > 1) { cmd << "cmd.exe /C \""; } - cmd << *li; + // Put current cmdLine in brackets if it contains "||" because it has + // higher precedence than "&&" in cmd.exe + if (li->find("||") != std::string::npos) { + cmd << "( " << *li << " )"; + } else { + cmd << *li; + } } if (cmdLines.size() > 1) { cmd << "\""; diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 10803196f..a45e01851 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -3,7 +3,7 @@ #ifndef cmLocalNinjaGenerator_h #define cmLocalNinjaGenerator_h -#include +#include "cmConfigure.h" #include #include @@ -63,7 +63,9 @@ public: std::string BuildCommandLine(const std::vector& cmdLines); void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs); - void AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs); + void AppendTargetDepends( + cmGeneratorTarget* target, cmNinjaDeps& outputs, + cmNinjaTargetDepends depends = DependOnTargetArtifact); void AddCustomCommandTarget(cmCustomCommand const* cc, cmGeneratorTarget* target); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 41a4caf92..9b9d22cf5 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalUnixMakefileGenerator3.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Terminal.h" #include -#include -#include #include #include #include @@ -79,7 +79,7 @@ static std::string cmSplitExtension(std::string const& in, std::string& base) std::string::size_type dot_pos = in.rfind('.'); if (dot_pos != std::string::npos) { // Remove the extension first in case &base == &in. - ext = in.substr(dot_pos, std::string::npos); + ext = in.substr(dot_pos); base = in.substr(0, dot_pos); } else { base = in; @@ -105,8 +105,6 @@ cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() void cmLocalUnixMakefileGenerator3::Generate() { - this->SetConfigName(); - // Record whether some options are enabled to avoid checking many // times later. if (!this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile()) { @@ -159,12 +157,15 @@ void cmLocalUnixMakefileGenerator3::ComputeObjectFilenames( std::map& mapping, cmGeneratorTarget const* gt) { + // Determine if these object files should use a custom extension + char const* custom_ext = gt->GetCustomObjectExtension(); for (std::map::iterator si = mapping.begin(); si != mapping.end(); ++si) { cmSourceFile const* sf = si->first; - si->second = - this->GetObjectFileNameWithoutTarget(*sf, gt->ObjectDirectory); + bool keptSourceExtension; + si->second = this->GetObjectFileNameWithoutTarget( + *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext); } } @@ -605,7 +606,7 @@ std::string cmLocalUnixMakefileGenerator3::MaybeConvertWatcomShellCommand( std::string const& cmd) { if (this->IsWatcomWMake() && cmSystemTools::FileIsFullPath(cmd.c_str()) && - cmd.find_first_of("( )") != cmd.npos) { + cmd.find_first_of("( )") != std::string::npos) { // On Watcom WMake use the windows short path for the command // name. This is needed to avoid funny quoting problems on // lines with shell redirection operators. @@ -851,7 +852,7 @@ void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags, { if (this->IsWatcomWMake() && !newFlags.empty()) { std::string newf = newFlags; - if (newf.find("\\\"") != newf.npos) { + if (newf.find("\\\"") != std::string::npos) { cmSystemTools::ReplaceString(newf, "\\\"", "\""); this->cmLocalGenerator::AppendFlags(flags, newf); return; @@ -977,11 +978,11 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( cmSystemTools::ReplaceString(cmd, "/./", "/"); // Convert the command to a relative path only if the current // working directory will be the start-output directory. - bool had_slash = cmd.find('/') != cmd.npos; + bool had_slash = cmd.find('/') != std::string::npos; if (workingDir.empty()) { cmd = this->MaybeConvertToRelativePath(currentBinDir, cmd); } - bool has_slash = cmd.find('/') != cmd.npos; + bool has_slash = cmd.find('/') != std::string::npos; if (had_slash && !has_slash) { // This command was specified as a path to a file in the // current directory. Add a leading "./" so it can run @@ -1038,9 +1039,9 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // curly braces are removed. The hack can be skipped if the // first curly brace is the last character. std::string::size_type lcurly = cmd.find('{'); - if (lcurly != cmd.npos && lcurly < (cmd.size() - 1)) { + if (lcurly != std::string::npos && lcurly < (cmd.size() - 1)) { std::string::size_type rcurly = cmd.find('}'); - if (rcurly == cmd.npos || rcurly > lcurly) { + if (rcurly == std::string::npos || rcurly > lcurly) { // The first curly is a left curly. Use the hack. std::string hack_cmd = cmd.substr(0, lcurly); hack_cmd += "{{}"; @@ -1199,17 +1200,19 @@ void cmLocalUnixMakefileGenerator3::AppendEcho( } std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable( - const std::string& sin, const std::string& s2) + std::string const& s, std::string const& s2) { - std::string s = sin; std::string unmodified = s; unmodified += s2; // if there is no restriction on the length of make variables // and there are no "." characters in the string, then return the // unmodified combination. - if ((!this->MakefileVariableSize && unmodified.find('.') == s.npos) && - (!this->MakefileVariableSize && unmodified.find('+') == s.npos) && - (!this->MakefileVariableSize && unmodified.find('-') == s.npos)) { + if ((!this->MakefileVariableSize && + unmodified.find('.') == std::string::npos) && + (!this->MakefileVariableSize && + unmodified.find('+') == std::string::npos) && + (!this->MakefileVariableSize && + unmodified.find('-') == std::string::npos)) { return unmodified; } @@ -1864,10 +1867,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( std::string binaryDir = this->GetState()->GetBinaryDirectory(); if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) { const char* sourceDir = this->GetState()->GetSourceDirectory(); - std::vector::iterator itr = - std::remove_if(includes.begin(), includes.end(), - ::NotInProjectDir(sourceDir, binaryDir)); - includes.erase(itr, includes.end()); + cmEraseIf(includes, ::NotInProjectDir(sourceDir, binaryDir)); } for (std::vector::iterator i = includes.begin(); i != includes.end(); ++i) { diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index c3ecda44c..f64409cba 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -3,7 +3,7 @@ #ifndef cmLocalUnixMakefileGenerator3_h #define cmLocalUnixMakefileGenerator3_h -#include +#include "cmConfigure.h" #include "cmDepends.h" #include "cmLocalCommonGenerator.h" diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 0516bdf5f..85d4a73b7 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -8,7 +8,7 @@ #include "cmVisualStudio10TargetGenerator.h" #include "cmXMLParser.h" -#include +#include "cm_expat.h" class cmVS10XMLParser : public cmXMLParser { diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index 1ed57ec65..e57dd8f20 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -3,7 +3,7 @@ #ifndef cmLocalVisualStudio10Generator_h #define cmLocalVisualStudio10Generator_h -#include +#include "cmConfigure.h" #include diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 38dda040b..dd08e5bdb 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -9,13 +9,14 @@ #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmXMLParser.h" +#include "cm_expat.h" #include "cmake.h" -#include #include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" #include // for isspace +#include static bool cmLVS7G_IsFAT(const char* dir); @@ -29,7 +30,7 @@ public: typedef cmComputeLinkInformation::ItemVector ItemVector; void OutputLibraries(std::ostream& fout, ItemVector const& libs); void OutputObjects(std::ostream& fout, cmGeneratorTarget* t, - const char* isep = 0); + std::string const& config, const char* isep = 0); private: cmLocalVisualStudio7Generator* LocalGenerator; @@ -669,6 +670,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( // Add the target-specific flags. this->AddCompileOptions(flags, target, linkLanguage, configName); + + // Check IPO related warning/error. + target->IsIPOEnabled(linkLanguage, configName); } if (this->FortranProject) { @@ -745,11 +749,13 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( if (this->FortranProject) { // Intel Fortran >= 15.0 uses TargetName property. - std::string targetNameFull = target->GetFullName(configName); - std::string targetName = + std::string const targetNameFull = target->GetFullName(configName); + std::string const targetName = cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); - std::string targetExt = - cmSystemTools::GetFilenameLastExtension(targetNameFull); + std::string const targetExt = + target->GetType() == cmStateEnums::OBJECT_LIBRARY + ? ".lib" + : cmSystemTools::GetFilenameLastExtension(targetNameFull); /* clang-format off */ fout << "\t\t\tTargetName=\"" << this->EscapeForXML(targetName) << "\"\n" @@ -787,7 +793,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( << this->ConvertToXMLOutputPath(modDir.c_str()) << "\\$(ConfigurationName)\"\n"; } - targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); fout << "\t\t\t\tAdditionalIncludeDirectories=\""; std::vector includes; this->GetIncludeDirectories(includes, target, "C", configName); @@ -893,8 +898,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( // end of GetVersion() >= cmGlobalVisualStudioGenerator::VS8) { + if (targetBuilds) { const char* manifestTool = "VCManifestTool"; if (this->FortranProject) { manifestTool = "VFManifestTool"; @@ -997,19 +1001,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable); linkOptions.Parse(extraLinkOptions.c_str()); - if (!this->ModuleDefinitionFile.empty()) { - std::string defFile = this->ConvertToOutputFormat( - this->ModuleDefinitionFile, cmOutputConverter::SHELL); + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + target->GetModuleDefinitionInfo(configName); + if (mdi && !mdi->DefFile.empty()) { + std::string defFile = + this->ConvertToOutputFormat(mdi->DefFile, cmOutputConverter::SHELL); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); } - if ((target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def"); - } - } switch (target->GetType()) { case cmStateEnums::UNKNOWN_LIBRARY: break; @@ -1040,10 +1039,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << "\t\t\tGetVersion() < cmGlobalVisualStudioGenerator::VS8 || - this->FortranProject) { + if (this->FortranProject) { std::ostringstream libdeps; - this->Internal->OutputObjects(libdeps, target); + this->Internal->OutputObjects(libdeps, target, configName); if (!libdeps.str().empty()) { fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n"; @@ -1090,14 +1088,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( if (!gg->NeedLinkLibraryDependencies(target)) { fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n"; } - linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 || - this->FortranProject) { - this->Internal->OutputObjects(fout, target, " "); + if (this->FortranProject) { + this->Internal->OutputObjects(fout, target, configName, " "); } fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); @@ -1134,7 +1130,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n"; } - temp = target->GetDirectory(configName, true); + temp = + target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact); temp += "/"; temp += targetNameImport; fout << "\t\t\t\tImportLibrary=\"" @@ -1176,14 +1173,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( if (!gg->NeedLinkLibraryDependencies(target)) { fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n"; } - linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 || - this->FortranProject) { - this->Internal->OutputObjects(fout, target, " "); + if (this->FortranProject) { + this->Internal->OutputObjects(fout, target, configName, " "); } fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); @@ -1233,7 +1228,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\""; } - temp = target->GetDirectory(configName, true); + temp = + target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact); temp += "/"; temp += targetNameImport; fout << "\t\t\t\tImportLibrary=\"" @@ -1302,20 +1298,26 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries( } void cmLocalVisualStudio7GeneratorInternals::OutputObjects( - std::ostream& fout, cmGeneratorTarget* gt, const char* isep) + std::ostream& fout, cmGeneratorTarget* gt, std::string const& configName, + const char* isep) { // VS < 8 does not support per-config source locations so we // list object library content on the link line instead. cmLocalVisualStudio7Generator* lg = this->LocalGenerator; std::string currentBinDir = lg->GetCurrentBinaryDirectory(); - std::vector objs; - gt->UseObjectLibraries(objs, ""); + + std::vector objs; + gt->GetExternalObjects(objs, configName); + const char* sep = isep ? isep : ""; - for (std::vector::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - std::string rel = lg->ConvertToRelativePath(currentBinDir, oi->c_str()); - fout << sep << lg->ConvertToXMLOutputPath(rel.c_str()); - sep = " "; + for (std::vector::const_iterator i = objs.begin(); + i != objs.end(); ++i) { + if (!(*i)->GetObjectLibrary().empty()) { + std::string const& objFile = (*i)->GetFullPath(); + std::string rel = lg->ConvertToRelativePath(currentBinDir, objFile); + fout << sep << lg->ConvertToXMLOutputPath(rel.c_str()); + sep = " "; + } } } @@ -1364,25 +1366,26 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // We may be modifying the source groups temporarily, so make a copy. std::vector sourceGroups = this->Makefile->GetSourceGroups(); - // get the classes from the source lists then add them to the groups - this->ModuleDefinitionFile = ""; - std::vector classes; - if (!target->GetConfigCommonSourceFiles(classes)) { - return; - } - for (std::vector::const_iterator i = classes.begin(); - i != classes.end(); i++) { - if (!(*i)->GetObjectLibrary().empty()) { - continue; + std::vector const& sources = + target->GetAllConfigSources(); + std::map sourcesIndex; + + for (size_t si = 0; si < sources.size(); ++si) { + cmSourceFile const* sf = sources[si].Source; + sourcesIndex[sf] = si; + if (!sf->GetObjectLibrary().empty()) { + if (this->FortranProject) { + // Intel Fortran does not support per-config source locations + // so we list object library content on the link line instead. + // See OutputObjects. + continue; + } } // Add the file to the list of sources. - std::string source = (*i)->GetFullPath(); - if (cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") { - this->ModuleDefinitionFile = (*i)->GetFullPath(); - } + std::string const source = sf->GetFullPath(); cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); - sourceGroup->AssignSource(*i); + sourceGroup->AssignSource(sf); } // open the project @@ -1395,25 +1398,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // Loop through every source group. for (unsigned int i = 0; i < sourceGroups.size(); ++i) { cmSourceGroup sg = sourceGroups[i]; - this->WriteGroup(&sg, target, fout, libName, configs); - } - - if (this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8 && - !this->FortranProject) { - // VS >= 8 support per-config source locations so we - // list object library content as external objects. - std::vector objs; - target->UseObjectLibraries(objs, ""); - if (!objs.empty()) { - // TODO: Separate sub-filter for each object library used? - fout << "\t\t\n"; - for (std::vector::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str()); - fout << "\t\t\t\n"; - } - fout << "\t\t\n"; - } + this->WriteGroup(&sg, target, fout, libName, configs, sourcesIndex); } fout << "\t\n"; @@ -1435,25 +1420,28 @@ struct cmLVS7GFileConfig class cmLocalVisualStudio7GeneratorFCInfo { public: - cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, - cmGeneratorTarget* target, - cmSourceFile const& sf, - std::vector const& configs); + cmLocalVisualStudio7GeneratorFCInfo( + cmLocalVisualStudio7Generator* lg, cmGeneratorTarget* target, + cmGeneratorTarget::AllConfigSource const& acs, + std::vector const& configs); std::map FileConfigMap; }; cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( cmLocalVisualStudio7Generator* lg, cmGeneratorTarget* gt, - cmSourceFile const& sf, std::vector const& configs) + cmGeneratorTarget::AllConfigSource const& acs, + std::vector const& configs) { + cmSourceFile const& sf = *acs.Source; std::string objectName; if (gt->HasExplicitObjectName(&sf)) { objectName = gt->GetObjectName(&sf); } // Compute per-source, per-config information. + size_t ci = 0; for (std::vector::const_iterator i = configs.begin(); - i != configs.end(); ++i) { + i != configs.end(); ++i, ++ci) { std::string configUpper = cmSystemTools::UpperCase(*i); cmLVS7GFileConfig fc; bool needfc = false; @@ -1519,7 +1507,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( } // If HEADER_FILE_ONLY is set, we must suppress this generation in // the project file - fc.ExcludedFromBuild = (sf.GetPropertyAsBool("HEADER_FILE_ONLY")); + fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") || + std::find(acs.Configs.begin(), acs.Configs.end(), ci) == + acs.Configs.end(); if (fc.ExcludedFromBuild) { needfc = true; } @@ -1574,7 +1564,8 @@ std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory( bool cmLocalVisualStudio7Generator::WriteGroup( const cmSourceGroup* sg, cmGeneratorTarget* target, std::ostream& fout, - const std::string& libName, std::vector const& configs) + const std::string& libName, std::vector const& configs, + std::map const& sourcesIndex) { cmGlobalVisualStudio7Generator* gg = static_cast(this->GlobalGenerator); @@ -1585,7 +1576,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup( bool hasChildrenWithSources = false; std::ostringstream tmpOut; for (unsigned int i = 0; i < children.size(); ++i) { - if (this->WriteGroup(&children[i], target, tmpOut, libName, configs)) { + if (this->WriteGroup(&children[i], target, tmpOut, libName, configs, + sourcesIndex)) { hasChildrenWithSources = true; } } @@ -1601,15 +1593,26 @@ bool cmLocalVisualStudio7Generator::WriteGroup( this->WriteVCProjBeginGroup(fout, name.c_str(), ""); } + std::vector const& sources = + target->GetAllConfigSources(); + // Loop through each source in the source group. for (std::vector::const_iterator sf = sourceFiles.begin(); sf != sourceFiles.end(); ++sf) { std::string source = (*sf)->GetFullPath(); - FCInfo fcinfo(this, target, *(*sf), configs); if (source != libName || target->GetType() == cmStateEnums::UTILITY || target->GetType() == cmStateEnums::GLOBAL_TARGET) { + // Look up the source kind and configs. + std::map::const_iterator map_it = + sourcesIndex.find(*sf); + // The map entry must exist because we populated it earlier. + assert(map_it != sourcesIndex.end()); + cmGeneratorTarget::AllConfigSource const& acs = sources[map_it->second]; + + FCInfo fcinfo(this, target, acs, configs); + fout << "\t\t\tConvertToXMLOutputPathSingle(source.c_str()); // Tell MS-Dev what the source is. If the compiler knows how to @@ -1649,6 +1652,9 @@ bool cmLocalVisualStudio7Generator::WriteGroup( lang == "ASM_MASM") { aCompilerTool = "MASM"; } + if (acs.Kind == cmGeneratorTarget::SourceKindExternalObject) { + aCompilerTool = "VCCustomBuildTool"; + } for (std::map::const_iterator fci = fcinfo.FileConfigMap.begin(); fci != fcinfo.FileConfigMap.end(); ++fci) { @@ -1675,7 +1681,6 @@ bool cmLocalVisualStudio7Generator::WriteGroup( fileOptions.Parse(fc.CompileFlags.c_str()); fileOptions.AddDefines(fc.CompileDefs.c_str()); fileOptions.AddDefines(fc.CompileDefsConfig.c_str()); - fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n"); fileOptions.OutputFlagMap(fout, "\t\t\t\t\t"); fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n", ppLang); @@ -1829,17 +1834,15 @@ void cmLocalVisualStudio7Generator::OutputTargetRules( tool = this->FortranProject ? "VFPreLinkEventTool" : "VCPreLinkEventTool"; event.Start(tool); bool addedPrelink = false; - if ((target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - addedPrelink = true; - std::vector commands = target->GetPreLinkCommands(); - cmGlobalVisualStudioGenerator* gg = - static_cast(this->GlobalGenerator); - gg->AddSymbolExportCommand(target, commands, configName); - event.Write(commands); - } + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + target->GetModuleDefinitionInfo(configName); + if (mdi && mdi->DefFileGenerated) { + addedPrelink = true; + std::vector commands = target->GetPreLinkCommands(); + cmGlobalVisualStudioGenerator* gg = + static_cast(this->GlobalGenerator); + gg->AddSymbolExportCommand(target, commands, configName); + event.Write(commands); } if (!addedPrelink) { event.Write(target->GetPreLinkCommands()); @@ -1956,11 +1959,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStart( << "GetVersion() == cmGlobalVisualStudioGenerator::VS71) { - fout << "\tVersion=\"7.10\"\n"; - } else { - fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n"; - } + fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n"; const char* projLabel = target->GetProperty("PROJECT_LABEL"); if (!projLabel) { projLabel = libName.c_str(); @@ -1970,9 +1969,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStart( keyword = "Win32Proj"; } fout << "\tName=\"" << projLabel << "\"\n"; - if (gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) { - fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n"; - } + fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n"; this->WriteProjectSCC(fout, target); if (const char* targetFrameworkVersion = target->GetProperty("VS_DOTNET_TARGET_FRAMEWORK_VERSION")) { @@ -2130,7 +2127,6 @@ std::string cmLocalVisualStudio7Generator::GetTargetDirectory( return dir; } -#include static bool cmLVS7G_IsFAT(const char* dir) { if (dir[0] && dir[1] == ':') { diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index d69cce128..89a3ee353 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -3,7 +3,7 @@ #ifndef cmLocalVisualStudio7Generator_h #define cmLocalVisualStudio7Generator_h -#include +#include "cmConfigure.h" #include #include @@ -119,7 +119,8 @@ private: bool WriteGroup(const cmSourceGroup* sg, cmGeneratorTarget* target, std::ostream& fout, const std::string& libName, - std::vector const& configs); + std::vector const& configs, + std::map const& sourcesIndex); friend class cmLocalVisualStudio7GeneratorFCInfo; friend class cmLocalVisualStudio7GeneratorInternals; @@ -128,7 +129,6 @@ private: friend class EventWriter; - std::string ModuleDefinitionFile; bool FortranProject; bool WindowsCEProject; cmLocalVisualStudio7GeneratorInternals* Internal; diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index e20fe5067..41025af6c 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -32,6 +32,7 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames( std::map& mapping, cmGeneratorTarget const* gt) { + char const* custom_ext = gt->GetCustomObjectExtension(); std::string dir_max = this->ComputeLongestObjectDirectory(gt); // Count the number of object files with each name. Note that @@ -44,7 +45,12 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames( cmSourceFile const* sf = si->first; std::string objectNameLower = cmSystemTools::LowerCase( cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())); - objectNameLower += this->GlobalGenerator->GetLanguageOutputExtension(*sf); + if (custom_ext) { + objectNameLower += custom_ext; + } else { + objectNameLower += + this->GlobalGenerator->GetLanguageOutputExtension(*sf); + } counts[objectNameLower] += 1; } @@ -57,10 +63,16 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames( cmSourceFile const* sf = si->first; std::string objectName = cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); - objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf); + if (custom_ext) { + objectName += custom_ext; + } else { + objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf); + } if (counts[cmSystemTools::LowerCase(objectName)] > 1) { const_cast(gt)->AddExplicitObjectName(sf); - objectName = this->GetObjectFileNameWithoutTarget(*sf, dir_max); + bool keptSourceExtension; + objectName = this->GetObjectFileNameWithoutTarget( + *sf, dir_max, &keptSourceExtension, custom_ext); } si->second = objectName; } @@ -80,8 +92,10 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target, !(isFortran && target->GetType() == cmStateEnums::SHARED_LIBRARY)) { return pcc; } - std::string outDir = target->GetDirectory(config, false); - std::string impDir = target->GetDirectory(config, true); + std::string outDir = + target->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact); + std::string impDir = + target->GetDirectory(config, cmStateEnums::ImportLibraryArtifact); if (impDir == outDir) { return pcc; } diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 39188f902..85fb8a511 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -3,7 +3,7 @@ #ifndef cmLocalVisualStudioGenerator_h #define cmLocalVisualStudioGenerator_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index b4a8c6c05..4ca02a9d0 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -3,7 +3,8 @@ #ifndef cmLocalXCodeGenerator_h #define cmLocalXCodeGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep + #include #include diff --git a/Source/cmLocale.h b/Source/cmLocale.h index cca7cf549..9f90a3a99 100644 --- a/Source/cmLocale.h +++ b/Source/cmLocale.h @@ -3,14 +3,14 @@ #ifndef cmLocale_h #define cmLocale_h -#include +#include "cmConfigure.h" #include #include class cmLocaleRAII { - std::string OldLocale; + CM_DISABLE_COPY(cmLocaleRAII) public: cmLocaleRAII() @@ -19,6 +19,9 @@ public: setlocale(LC_CTYPE, ""); } ~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale.c_str()); } + +private: + std::string OldLocale; }; #endif diff --git a/Source/cmMSVC60LinkLineComputer.cxx b/Source/cmMSVC60LinkLineComputer.cxx index d761e7ba0..5298d1a79 100644 --- a/Source/cmMSVC60LinkLineComputer.cxx +++ b/Source/cmMSVC60LinkLineComputer.cxx @@ -3,8 +3,6 @@ #include "cmMSVC60LinkLineComputer.h" -#include "cmStateDirectory.h" - #if defined(_WIN32) && !defined(__CYGWIN__) #include "cmSystemTools.h" #endif @@ -12,7 +10,7 @@ class cmOutputConverter; cmMSVC60LinkLineComputer::cmMSVC60LinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir) + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) : cmLinkLineComputer(outputConverter, stateDir) { } @@ -24,7 +22,7 @@ std::string cmMSVC60LinkLineComputer::ConvertToLinkReference( // Work-ardound command line parsing limitations in MSVC 6.0 // Search for the last space. std::string::size_type pos = lib.rfind(' '); - if (pos != lib.npos) { + if (pos != std::string::npos) { // Find the slash after the last space, if any. pos = lib.find('/', pos); diff --git a/Source/cmMSVC60LinkLineComputer.h b/Source/cmMSVC60LinkLineComputer.h index 9a28dca0d..f2892d53f 100644 --- a/Source/cmMSVC60LinkLineComputer.h +++ b/Source/cmMSVC60LinkLineComputer.h @@ -4,7 +4,7 @@ #ifndef cmMSVC60LinkLineComputer_h #define cmMSVC60LinkLineComputer_h -#include +#include "cmConfigure.h" #include @@ -15,9 +15,11 @@ class cmStateDirectory; class cmMSVC60LinkLineComputer : public cmLinkLineComputer { + CM_DISABLE_COPY(cmMSVC60LinkLineComputer) + public: cmMSVC60LinkLineComputer(cmOutputConverter* outputConverter, - cmStateDirectory stateDir); + cmStateDirectory const& stateDir); std::string ConvertToLinkReference(std::string const& input) const CM_OVERRIDE; diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx index 586e6c697..a4350f7ce 100644 --- a/Source/cmMachO.cxx +++ b/Source/cmMachO.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMachO.h" +#include "cmsys/FStream.hxx" #include -#include #include #include #include diff --git a/Source/cmMachO.h b/Source/cmMachO.h index 901f17abc..42745cf60 100644 --- a/Source/cmMachO.h +++ b/Source/cmMachO.h @@ -3,7 +3,7 @@ #ifndef cmMachO_h #define cmMachO_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 583f80180..a6a9ea316 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -21,11 +21,6 @@ public: ///! clean up any memory allocated by the macro ~cmMacroHelperCommand() CM_OVERRIDE {} - /** - * This determines if the command is defined in a cmake script. - */ - bool IsUserDefined() const CM_OVERRIDE { return true; } - /** * This is a virtual constructor for the command. */ @@ -40,11 +35,6 @@ public: return newC; } - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - /** * This is called when the command is first encountered in * the CMakeLists.txt file. @@ -58,11 +48,6 @@ public: return false; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return this->Args[0]; } - std::vector Args; std::vector Functions; cmPolicies::PolicyMap Policies; @@ -156,15 +141,15 @@ bool cmMacroHelperCommand::InvokeInitialPass( // The error message should have already included the call stack // so we do not need to report an error here. macroScope.Quiet(); - inStatus.SetNestedError(true); + inStatus.SetNestedError(); return false; } if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(true); + inStatus.SetReturnInvoked(); return true; } if (status.GetBreakInvoked()) { - inStatus.SetBreakInvoked(true); + inStatus.SetBreakInvoked(); return true; } } @@ -189,10 +174,7 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, f->Functions = this->Functions; f->FilePath = this->GetStartingContext().FilePath; mf.RecordPolicies(f->Policies); - std::string newName = "_" + this->Args[0]; - mf.GetState()->RenameCommand(this->Args[0], newName); - mf.GetState()->AddCommand(f); - + mf.GetState()->AddScriptedCommand(this->Args[0], f); // remove the function blocker now that the macro is defined mf.RemoveFunctionBlocker(this, lff); return true; diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h index acb42339c..0d35fe06e 100644 --- a/Source/cmMacroCommand.h +++ b/Source/cmMacroCommand.h @@ -3,7 +3,8 @@ #ifndef cmMacroCommand_h #define cmMacroCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -43,16 +44,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "macro"; } }; #endif diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h index d9cce6f73..af72eab96 100644 --- a/Source/cmMakeDirectoryCommand.h +++ b/Source/cmMakeDirectoryCommand.h @@ -3,7 +3,8 @@ #ifndef cmMakeDirectoryCommand_h #define cmMakeDirectoryCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -34,16 +35,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "make_directory"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } }; #endif diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 1e995fb93..608b18a46 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2,10 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefile.h" +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #include #include -#include -#include #include #include #include @@ -36,7 +36,9 @@ #include "cmTest.h" #include "cmTestGenerator.h" // IWYU pragma: keep #include "cmVersion.h" +#include "cmWorkingDirectory.h" #include "cm_auto_ptr.hxx" +#include "cm_sys_stat.h" #include "cmake.h" #ifdef CMAKE_BUILD_WITH_CMAKE @@ -92,6 +94,10 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, this->AddSourceGroup("CMake Rules", "\\.rule$"); this->AddSourceGroup("Resources", "\\.plist$"); this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$"); + + this->ObjectLibrariesSourceGroupIndex = this->SourceGroups.size(); + this->SourceGroups.push_back( + cmSourceGroup("Object Libraries", "^MATCH_NO_SOURCES$")); #endif } @@ -112,7 +118,7 @@ void cmMakefile::IssueMessage(cmake::MessageType t, { if (!this->ExecutionStatusStack.empty()) { if ((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) { - this->ExecutionStatusStack.back()->SetNestedError(true); + this->ExecutionStatusStack.back()->SetNestedError(); } } this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace()); @@ -266,11 +272,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, pcmd->SetMakefile(this); // Decide whether to invoke the command. - if (!cmSystemTools::GetFatalErrorOccured() && - (this->GetCMakeInstance()->GetWorkingMode() != cmake::SCRIPT_MODE || - pcmd->IsScriptable())) - - { + if (!cmSystemTools::GetFatalErrorOccured()) { // if trace is enabled, print out invoke information if (this->GetCMakeInstance()->GetTrace()) { this->PrintCommandTrace(lff); @@ -281,7 +283,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, if (!invokeSucceeded || hadNestedError) { if (!hadNestedError) { // The command invocation requested that we report an error. - this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError()); + std::string const error = name + " " + pcmd->GetError(); + this->IssueMessage(cmake::FATAL_ERROR, error); } result = false; if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { @@ -291,15 +294,6 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, // use the command this->FinalPassCommands.push_back(pcmd.release()); } - } else if (this->GetCMakeInstance()->GetWorkingMode() == - cmake::SCRIPT_MODE && - !pcmd->IsScriptable()) { - std::string error = "Command "; - error += pcmd->GetName(); - error += "() is not scriptable"; - this->IssueMessage(cmake::FATAL_ERROR, error); - result = false; - cmSystemTools::SetFatalErrorOccured(); } } else { if (!cmSystemTools::GetFatalErrorOccured()) { @@ -322,6 +316,7 @@ public: bool noPolicyScope); ~IncludeScope(); void Quiet() { this->ReportError = false; } + private: cmMakefile* Makefile; bool NoPolicyScope; @@ -365,6 +360,7 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf, // We should never make this policy required, but we handle it // here just in case. this->CheckCMP0011 = true; + CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior is to push a (strong) scope. this->Makefile->PushPolicy(); @@ -486,6 +482,7 @@ public: } void Quiet() { this->ReportError = false; } + private: cmMakefile* Makefile; bool ReportError; @@ -631,7 +628,7 @@ struct file_not_persistent { bool operator()(const std::string& path) const { - return !(path.find("CMakeTmp") == path.npos && + return !(path.find("CMakeTmp") == std::string::npos && cmSystemTools::FileExists(path.c_str())); } }; @@ -653,21 +650,12 @@ void cmMakefile::FinalPass() // we don't want cmake to re-run if a configured file is created and deleted // during processing as that would make it a transient file that can't // influence the build process - - // remove_if will move all items that don't have a valid file name to the - // back of the vector - std::vector::iterator new_output_files_end = std::remove_if( - this->OutputFiles.begin(), this->OutputFiles.end(), file_not_persistent()); - // we just have to erase all items at the back - this->OutputFiles.erase(new_output_files_end, this->OutputFiles.end()); + cmEraseIf(this->OutputFiles, file_not_persistent()); // if a configured file is used as input for another configured file, // and then deleted it will show up in the input list files so we // need to scan those too - std::vector::iterator new_list_files_end = std::remove_if( - this->ListFiles.begin(), this->ListFiles.end(), file_not_persistent()); - - this->ListFiles.erase(new_list_files_end, this->ListFiles.end()); + cmEraseIf(this->ListFiles, file_not_persistent()); } // Generate the output file @@ -692,7 +680,8 @@ void cmMakefile::AddCustomCommandToTarget( const std::vector& depends, const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile, bool command_expand_lists) + bool uses_terminal, const std::string& depfile, bool command_expand_lists, + ObjectLibraryCommands objLibraryCommands) { // Find the target to which to add the custom command. cmTargets::iterator ti = this->Targets.find(target); @@ -732,7 +721,8 @@ void cmMakefile::AddCustomCommandToTarget( return; } - if (ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (objLibraryCommands == RejectObjectLibraryCommands && + ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) { std::ostringstream e; e << "Target \"" << target << "\" is an OBJECT library " @@ -1172,6 +1162,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) case cmPolicies::WARN: this->IssueMessage(cmake::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0005)); + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to not escape the value. We should not // convert the definition to use the property. @@ -1360,6 +1351,7 @@ public: } void Quiet() { this->ReportError = false; } + private: cmMakefile* Makefile; cmGlobalGenerator* GG; @@ -1521,6 +1513,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: e << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0014); + CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior prints the error. this->IssueMessage(cmake::FATAL_ERROR, e.str()); @@ -1906,7 +1899,7 @@ cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput( out = *o; std::string::size_type pos = out.rfind(name); // If the output matches exactly - if (pos != out.npos && pos == out.size() - name.size() && + if (pos != std::string::npos && pos == out.size() - name.size() && (pos == 0 || out[pos - 1] == '/')) { return *i; } @@ -2155,6 +2148,12 @@ bool cmMakefile::IsSet(const std::string& name) const bool cmMakefile::PlatformIs32Bit() const { + if (const char* plat_abi = + this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { + if (strcmp(plat_abi, "ELF X32") == 0) { + return false; + } + } if (const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) { return atoi(sizeof_dptr) == 4; } @@ -2169,6 +2168,17 @@ bool cmMakefile::PlatformIs64Bit() const return false; } +bool cmMakefile::PlatformIsx32() const +{ + if (const char* plat_abi = + this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) { + if (strcmp(plat_abi, "ELF X32") == 0) { + return true; + } + } + return false; +} + bool cmMakefile::PlatformIsAppleIos() const { std::string sdkRoot; @@ -2333,6 +2343,7 @@ const char* cmMakefile::ExpandVariablesInString( newErrorstr, newResult, escapeQuotes, noEscapes, atOnly, filename, line, removeEmpty, replaceAt); this->SuppressWatches = false; + CM_FALLTHROUGH; } case cmPolicies::OLD: mtype = @@ -2402,7 +2413,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( bool removeEmpty, bool replaceAt) const { // Fast path strings without any special characters. - if (source.find_first_of("$@\\") == source.npos) { + if (source.find_first_of("$@\\") == std::string::npos) { return cmake::LOG; } @@ -2489,6 +2500,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( switch (this->GetPolicyStatus(cmPolicies::CMP0010)) { case cmPolicies::WARN: error << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0010); + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior is to just warn and continue. mtype = cmake::AUTHOR_WARNING; @@ -2642,6 +2654,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( } break; } + CM_FALLTHROUGH; case '\\': if (!noEscapes) { const char* next = in + 1; @@ -3111,6 +3124,18 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName, return this->CreateSource(sourceName, generated); } +void cmMakefile::AddTargetObject(std::string const& tgtName, + std::string const& objFile) +{ + cmSourceFile* sf = this->GetOrCreateSource(objFile, true); + sf->SetObjectLibrary(tgtName); + sf->SetProperty("EXTERNAL_OBJECT", "1"); +#if defined(CMAKE_BUILD_WITH_CMAKE) + this->SourceGroups[this->ObjectLibrariesSourceGroupIndex].AddGroupFile( + sf->GetFullPath()); +#endif +} + void cmMakefile::EnableLanguage(std::vector const& lang, bool optional) { @@ -3124,7 +3149,7 @@ void cmMakefile::EnableLanguage(std::vector const& lang, langs.reserve(lang.size()); for (std::vector::const_iterator i = lang.begin(); i != lang.end(); ++i) { - if (i->compare("RC") == 0) { + if (*i == "RC") { langsRC.push_back(*i); } else { langs.push_back(*i); @@ -3153,13 +3178,12 @@ int cmMakefile::TryCompile(const std::string& srcdir, // change to the tests directory and run cmake // use the cmake object instead of calling cmake - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - cmSystemTools::ChangeDirectory(bindir); + cmWorkingDirectory workdir(bindir); // make sure the same generator is used // use this program as the cmake to be run, it should not // be run that way but the cmake object requires a vailid path - cmake cm; + cmake cm(cmake::RoleProject); cm.SetIsInTryCompile(true); cmGlobalGenerator* gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName()); @@ -3168,8 +3192,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, this->GetGlobalGenerator()->GetName() + "' could not be created."); cmSystemTools::SetFatalErrorOccured(); - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return 1; } @@ -3233,8 +3255,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, this->IssueMessage(cmake::FATAL_ERROR, "Failed to configure test project build system."); cmSystemTools::SetFatalErrorOccured(); - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return 1; } @@ -3243,8 +3263,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, this->IssueMessage(cmake::FATAL_ERROR, "Failed to generate test project build system."); cmSystemTools::SetFatalErrorOccured(); - // return to the original directory - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return 1; } @@ -3253,7 +3271,6 @@ int cmMakefile::TryCompile(const std::string& srcdir, int ret = this->GetGlobalGenerator()->TryCompile( srcdir, bindir, projectName, targetName, fast, output, this); - cmSystemTools::ChangeDirectory(cwd); this->IsSourceFileTryCompile = false; return ret; } @@ -3375,7 +3392,7 @@ std::string cmMakefile::GetModulesFile(const char* filename) const /* clang-format on */ this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); - // break; // fall through to OLD behaviour + CM_FALLTHROUGH; } case cmPolicies::OLD: result = moduleInCMakeModulePath; @@ -3452,7 +3469,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, int cmMakefile::ConfigureFile(const char* infile, const char* outfile, bool copyonly, bool atOnly, bool escapeQuotes, - const cmNewLineStyle& newLine) + cmNewLineStyle newLine) { int res = 1; if (!this->CanIWriteThisFile(outfile)) { @@ -3768,6 +3785,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, case cmPolicies::WARN: this->IssueMessage(cmake::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0002)); + CM_FALLTHROUGH; case cmPolicies::OLD: return true; case cmPolicies::REQUIRED_IF_USED: @@ -3853,12 +3871,14 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, << "compatibility."; /* clang-format on */ this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + CM_FALLTHROUGH; case cmPolicies::OLD: // OLD behavior does not warn. return true; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0013) << "\n"; + CM_FALLTHROUGH; case cmPolicies::NEW: // NEW behavior prints the error. /* clang-format off */ @@ -3981,6 +4001,13 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, return false; } + // Deprecate old policies, especially those that require a lot + // of code to maintain the old behavior. + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0036) { + this->IssueMessage(cmake::DEPRECATION_WARNING, + cmPolicies::GetPolicyDeprecatedWarning(id)); + } + this->StateSnapshot.SetPolicy(id, status); return true; } @@ -4163,6 +4190,23 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target, const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang, std::string* error) const { + if (!this->GlobalGenerator->GetLanguageEnabled(lang)) { + std::ostringstream e; + if (error) { + e << "cannot"; + } else { + e << "Cannot"; + } + e << " use features from non-enabled language " << lang; + if (error) { + *error = e.str(); + } else { + this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Backtrace); + } + return CM_NULLPTR; + } + const char* featuresKnown = this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES"); @@ -4174,9 +4218,9 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang, e << "No"; } e << " known features for " << lang << " compiler\n\"" - << this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID") + << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID") << "\"\nversion " - << this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << "."; + << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << "."; if (error) { *error = e.str(); } else { diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 9d9e90a76..e65ba468f 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -3,12 +3,14 @@ #ifndef cmMakefile_h #define cmMakefile_h -#include +#include "cmConfigure.h" -#include +#include "cmsys/RegularExpression.hxx" +#include #include #include #include +#include #include #include @@ -53,6 +55,8 @@ class cmVariableWatch; */ class cmMakefile { + CM_DISABLE_COPY(cmMakefile) + public: /* Mark a variable as used */ void MarkVariableAsUsed(const std::string& var); @@ -119,6 +123,13 @@ public: */ void FinalPass(); + /** How to handle custom commands for object libraries */ + enum ObjectLibraryCommands + { + RejectObjectLibraryCommands, + AcceptObjectLibraryCommands + }; + /** Add a custom command to the build. */ void AddCustomCommandToTarget( const std::string& target, const std::vector& byproducts, @@ -126,7 +137,8 @@ public: const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle = true, bool uses_terminal = false, const std::string& depfile = "", - bool command_expand_lists = false); + bool command_expand_lists = false, + ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands); cmSourceFile* AddCustomCommandToOutput( const std::vector& outputs, const std::vector& byproducts, @@ -398,6 +410,8 @@ public: cmSourceFile* GetOrCreateSource(const std::string& sourceName, bool generated = false); + void AddTargetObject(std::string const& tgtName, std::string const& objFile); + /** * Given a variable name, return its value (as a string). * If the variable is not found in this makefile instance, the @@ -428,6 +442,8 @@ public: /** Return whether the target platform is 64-bit. */ bool PlatformIs64Bit() const; + /** Return whether the target platform is x32. */ + bool PlatformIsx32() const; /** Return whether the target platform is Apple iOS. */ bool PlatformIsAppleIos() const; @@ -532,7 +548,7 @@ public: */ int ConfigureFile(const char* infile, const char* outfile, bool copyonly, bool atOnly, bool escapeQuotes, - const cmNewLineStyle& = cmNewLineStyle()); + cmNewLineStyle = cmNewLineStyle()); #if defined(CMAKE_BUILD_WITH_CMAKE) /** @@ -696,6 +712,7 @@ public: /** Helper class to push and pop scopes automatically. */ class ScopePushPop { + CM_DISABLE_COPY(ScopePushPop) public: ScopePushPop(cmMakefile* m) : Makefile(m) @@ -770,6 +787,10 @@ public: void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen); void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen); + // Maintain a stack of pacakge names to determine the depth of find modules + // we are currently being called with + std::deque FindPackageModuleStack; + protected: // add link libraries and directories to the target void AddGlobalLinkInformation(cmTarget& target); @@ -807,6 +828,7 @@ protected: #if defined(CMAKE_BUILD_WITH_CMAKE) std::vector SourceGroups; + size_t ObjectLibrariesSourceGroupIndex; #endif std::vector FinalPassCommands; @@ -815,9 +837,6 @@ protected: cmExecutionStatus& status); private: - cmMakefile(const cmMakefile& mf); - cmMakefile& operator=(const cmMakefile& mf); - cmStateSnapshot StateSnapshot; cmListFileBacktrace Backtrace; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index b76ddeb5a..359b9fdbb 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileExecutableTargetGenerator.h" +#include #include #include #include @@ -20,6 +21,7 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" +#include "cmStateTypes.h" #include "cmSystemTools.h" #include "cm_auto_ptr.hxx" #include "cmake.h" @@ -120,7 +122,11 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( std::string buildEcho = "Linking "; buildEcho += linkLanguage; buildEcho += " device code "; - buildEcho += targetOutputReal; + buildEcho += this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), + this->DeviceLinkObject), + cmOutputConverter::SHELL); this->LocalGenerator->AppendEcho( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } @@ -144,7 +150,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( linkLanguage, *this->GeneratorTarget)); // Add language feature flags. - this->AddFeatureFlags(flags, linkLanguage); + this->LocalGenerator->AddLanguageFlagsForLinking( + flags, this->GeneratorTarget, linkLanguage, this->ConfigName); this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, linkLanguage, this->ConfigName); @@ -331,7 +338,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } else { cmSystemTools::MakeDirectory(outpath.c_str()); if (!targetNameImport.empty()) { - outpathImp = this->GeneratorTarget->GetDirectory(this->ConfigName, true); + outpathImp = this->GeneratorTarget->GetDirectory( + this->ConfigName, cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp.c_str()); outpathImp += "/"; } @@ -426,7 +434,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } // Add language feature flags. - this->AddFeatureFlags(flags, linkLanguage); + this->LocalGenerator->AddLanguageFlagsForLinking( + flags, this->GeneratorTarget, linkLanguage, this->ConfigName); this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget, linkLanguage, this->ConfigName); @@ -448,6 +457,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags); } + this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, + this->ConfigName, linkLanguage); + // Construct a list of files associated with this executable that // may need to be cleaned. std::vector exeCleanFiles; @@ -555,10 +567,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } // maybe create .def file from list of objects - if (this->GeneratorTarget->IsExecutableWithExports() && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - this->GenDefFile(real_link_commands, linkFlags); - } + this->GenDefFile(real_link_commands); std::string manifests = this->GetManifests(); diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h index 642182b67..01aa6270c 100644 --- a/Source/cmMakefileExecutableTargetGenerator.h +++ b/Source/cmMakefileExecutableTargetGenerator.h @@ -3,7 +3,9 @@ #ifndef cmMakefileExecutableTargetGenerator_h #define cmMakefileExecutableTargetGenerator_h -#include +#include "cmConfigure.h" + +#include #include "cmMakefileTargetGenerator.h" diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index ff8b604a4..3d1594bdb 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -2,8 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileLibraryTargetGenerator.h" -#include // IWYU pragma: keep - +#include #include #include @@ -128,16 +127,29 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { + const std::string cuda_lang("CUDA"); + cmGeneratorTarget::LinkClosure const* closure = + this->GeneratorTarget->GetLinkClosure(this->ConfigName); + + const bool hasCUDA = + (std::find(closure->Languages.begin(), closure->Languages.end(), + cuda_lang) != closure->Languages.end()); + + const bool resolveDeviceSymbols = + this->GeneratorTarget->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); + if (hasCUDA && resolveDeviceSymbols) { + std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; + std::string extraFlags; + this->LocalGenerator->AppendFlags( + extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); + this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, false); + } + std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - std::string linkRuleVar = "CMAKE_"; - linkRuleVar += linkLanguage; - linkRuleVar += "_CREATE_STATIC_LIBRARY"; - if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION") && - this->Makefile->GetDefinition(linkRuleVar + "_IPO")) { - linkRuleVar += "_IPO"; - } + std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( + linkLanguage, this->ConfigName); std::string extraFlags; this->LocalGenerator->GetStaticLibraryFlags( @@ -298,8 +310,12 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); // Add the link message. - std::string buildEcho = "Linking " + linkLanguage + " device code"; - buildEcho += targetOutputReal; + std::string buildEcho = "Linking " + linkLanguage + " device code "; + buildEcho += this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), + this->DeviceLinkObject), + cmOutputConverter::SHELL); this->LocalGenerator->AppendEcho( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } @@ -379,9 +395,10 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( vars.LinkFlags = linkFlags.c_str(); vars.TargetCompilePDB = targetOutPathCompilePDB.c_str(); - // Add language feature flags. + // Add language-specific flags. std::string langFlags; - this->AddFeatureFlags(langFlags, linkLanguage); + this->LocalGenerator->AddLanguageFlagsForLinking( + langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); vars.LanguageCompileFlags = langFlags.c_str(); @@ -477,6 +494,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Create set of linking flags. std::string linkFlags; this->LocalGenerator->AppendFlags(linkFlags, extraFlags); + this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget, + this->ConfigName, linkLanguage); // Add OSX version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || @@ -520,7 +539,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmSystemTools::MakeDirectory(outpath.c_str()); outpath += "/"; if (!targetNameImport.empty()) { - outpathImp = this->GeneratorTarget->GetDirectory(this->ConfigName, true); + outpathImp = this->GeneratorTarget->GetDirectory( + this->ConfigName, cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp.c_str()); outpathImp += "/"; } @@ -677,18 +697,30 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string arCreateVar = "CMAKE_"; arCreateVar += linkLanguage; arCreateVar += "_ARCHIVE_CREATE"; + + arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + arCreateVar, linkLanguage, this->ConfigName); + if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) { cmSystemTools::ExpandListArgument(rule, archiveCreateCommands); } std::string arAppendVar = "CMAKE_"; arAppendVar += linkLanguage; arAppendVar += "_ARCHIVE_APPEND"; + + arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + arAppendVar, linkLanguage, this->ConfigName); + if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) { cmSystemTools::ExpandListArgument(rule, archiveAppendCommands); } std::string arFinishVar = "CMAKE_"; arFinishVar += linkLanguage; arFinishVar += "_ARCHIVE_FINISH"; + + arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + arFinishVar, linkLanguage, this->ConfigName); + if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) { cmSystemTools::ExpandListArgument(rule, archiveFinishCommands); } @@ -751,10 +783,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } // maybe create .def file from list of objects - if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - this->GenDefFile(real_link_commands, linkFlags); - } + this->GenDefFile(real_link_commands); std::string manifests = this->GetManifests(); @@ -827,9 +856,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } } - // Add language feature flags. + // Add language-specific flags. std::string langFlags; - this->AddFeatureFlags(langFlags, linkLanguage); + this->LocalGenerator->AddLanguageFlagsForLinking( + langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); this->LocalGenerator->AddArchitectureFlags( langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); @@ -853,6 +883,16 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::vector object_strings; this->WriteObjectsStrings(object_strings, archiveCommandLimit); + // Add the cuda device object to the list of archive files. This will + // only occur on archives which have CUDA_RESOLVE_DEVICE_SYMBOLS enabled + if (!this->DeviceLinkObject.empty()) { + object_strings.push_back(this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), + this->DeviceLinkObject), + cmOutputConverter::SHELL)); + } + // Create the archive with the first set of objects. std::vector::iterator osi = object_strings.begin(); { diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h index 93ce90210..da1d8b65c 100644 --- a/Source/cmMakefileLibraryTargetGenerator.h +++ b/Source/cmMakefileLibraryTargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmMakefileLibraryTargetGenerator_h #define cmMakefileLibraryTargetGenerator_h -#include +#include "cmConfigure.h" #include "cmMakefileTargetGenerator.h" diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 54b3f3657..a4511b63b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -30,10 +30,6 @@ #include "cm_auto_ptr.hxx" #include "cmake.h" -#ifndef _WIN32 -#include -#endif - cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) : cmCommonTargetGenerator(target) , OSXBundleGenerator(CM_NULLPTR) @@ -509,8 +505,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - targetFullPathReal = - this->GeneratorTarget->GetFullPath(this->ConfigName, false, true); + targetFullPathReal = this->GeneratorTarget->GetFullPath( + this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true); targetFullPathPDB = this->GeneratorTarget->GetPDBDirectory(this->ConfigName); targetFullPathPDB += "/"; @@ -593,6 +589,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( if (this->GeneratorTarget->GetPropertyAsBool( "CUDA_SEPARABLE_COMPILATION")) { cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION"); + } else if (this->GeneratorTarget->GetPropertyAsBool( + "CUDA_PTX_COMPILATION")) { + cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION"); } else { cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"); } @@ -1256,7 +1255,7 @@ class cmMakefileTargetGeneratorObjectStrings public: cmMakefileTargetGeneratorObjectStrings(std::vector& strings, cmOutputConverter* outputConverter, - cmStateDirectory stateDir, + cmStateDirectory const& stateDir, std::string::size_type limit) : Strings(strings) , OutputConverter(outputConverter) @@ -1288,6 +1287,7 @@ public: this->CurrentString += this->NextObject; } void Done() { this->Strings.push_back(this->CurrentString); } + private: std::string MaybeConvertToRelativePath(std::string const& obj) { @@ -1414,8 +1414,14 @@ void cmMakefileTargetGenerator::AppendLinkDepends( this->AppendTargetDepends(depends); // Add a dependency on the link definitions file, if any. - if (this->ModuleDefinitionFile) { - depends.push_back(this->ModuleDefinitionFile->GetFullPath()); + if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo( + this->GetConfigName())) { + for (std::vector::const_iterator i = + mdi->Sources.begin(); + i != mdi->Sources.end(); ++i) { + depends.push_back((*i)->GetFullPath()); + } } // Add a dependency on user-specified manifest files, if any. @@ -1486,15 +1492,6 @@ void cmMakefileTargetGenerator::CreateLinkScript( makefile_depends.push_back(linkScriptName); } -static size_t calculateCommandLineLengthLimit() -{ -#if defined(_SC_ARG_MAX) - return ((size_t)sysconf(_SC_ARG_MAX)) - 1000; -#else - return 0; -#endif -} - bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects( std::string const& l) const { @@ -1508,7 +1505,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects( } // Check for a system limit. - if (size_t const limit = calculateCommandLineLengthLimit()) { + 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 @@ -1577,7 +1574,7 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( } cmLinkLineComputer* cmMakefileTargetGenerator::CreateLinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir) + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) { if (this->Makefile->IsOn("MSVC60")) { return this->GlobalGenerator->CreateMSVC60LinkLineComputer(outputConverter, @@ -1600,7 +1597,8 @@ void cmMakefileTargetGenerator::CreateLinkLibs( frameworkPath, linkPath); linkLibs = frameworkPath + linkPath + linkLibs; - if (useResponseFile && linkLibs.find_first_not_of(' ') != linkLibs.npos) { + if (useResponseFile && + linkLibs.find_first_not_of(' ') != std::string::npos) { // Lookup the response file reference flag. std::string responseFlagVar = "CMAKE_"; responseFlagVar += @@ -1718,31 +1716,32 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, } void cmMakefileTargetGenerator::GenDefFile( - std::vector& real_link_commands, std::string& linkFlags) + std::vector& real_link_commands) { - if (this->GeneratorTarget->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - std::string name_of_def_file = - this->GeneratorTarget->GetSupportDirectory(); - name_of_def_file += std::string("/") + this->GeneratorTarget->GetName(); - name_of_def_file += ".def"; - std::string cmd = cmSystemTools::GetCMakeCommand(); - cmd = this->LocalGenerator->ConvertToOutputFormat( - cmd, cmOutputConverter::SHELL); - cmd += " -E __create_def "; - cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file), - cmOutputConverter::SHELL); - cmd += " "; - std::string objlist_file = name_of_def_file; - objlist_file += ".objs"; - cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), - cmOutputConverter::SHELL); - real_link_commands.insert(real_link_commands.begin(), cmd); - // create a list of obj files for the -E __create_def to read - cmGeneratedFileStream fout(objlist_file.c_str()); + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName()); + if (!mdi || !mdi->DefFileGenerated) { + return; + } + std::string cmd = cmSystemTools::GetCMakeCommand(); + cmd = + this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL); + cmd += " -E __create_def "; + cmd += this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile), + cmOutputConverter::SHELL); + cmd += " "; + std::string objlist_file = mdi->DefFile + ".objs"; + cmd += this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), + cmOutputConverter::SHELL); + real_link_commands.insert(real_link_commands.begin(), cmd); + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(objlist_file.c_str()); + + if (mdi->WindowsExportAllSymbols) { for (std::vector::const_iterator i = this->Objects.begin(); i != this->Objects.end(); ++i) { if (cmHasLiteralSuffix(*i, ".obj")) { @@ -1754,13 +1753,11 @@ void cmMakefileTargetGenerator::GenDefFile( i != this->ExternalObjects.end(); ++i) { fout << *i << "\n"; } - // now add the def file link flag - linkFlags += " "; - linkFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); - linkFlags += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file), - cmOutputConverter::SHELL); - linkFlags += " "; + } + + for (std::vector::const_iterator i = + mdi->Sources.begin(); + i != mdi->Sources.end(); ++i) { + fout << (*i)->GetFullPath() << "\n"; } } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 347f9f2ba..92c9f60b0 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmMakefileTargetGenerator_h #define cmMakefileTargetGenerator_h -#include +#include "cmConfigure.h" #include #include @@ -143,7 +143,7 @@ protected: std::vector& makefile_depends); cmLinkLineComputer* CreateLinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir); + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir); /** Create a response file with the given set of options. Returns the relative path from the target build working directory to the @@ -166,8 +166,7 @@ protected: bool useWatcomQuote); /** Add commands for generate def files */ - void GenDefFile(std::vector& real_link_commands, - std::string& linkFlags); + void GenDefFile(std::vector& real_link_commands); void AddIncludeFlags(std::string& flags, const std::string& lang) CM_OVERRIDE; diff --git a/Source/cmMakefileUtilityTargetGenerator.h b/Source/cmMakefileUtilityTargetGenerator.h index 332c04e64..8df5dd46f 100644 --- a/Source/cmMakefileUtilityTargetGenerator.h +++ b/Source/cmMakefileUtilityTargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmMakefileUtilityTargetGenerator_h #define cmMakefileUtilityTargetGenerator_h -#include +#include "cmConfigure.h" #include "cmMakefileTargetGenerator.h" diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx index b2f0d22e1..14fd96f08 100644 --- a/Source/cmMarkAsAdvancedCommand.cxx +++ b/Source/cmMarkAsAdvancedCommand.cxx @@ -30,7 +30,7 @@ bool cmMarkAsAdvancedCommand::InitialPass(std::vector const& args, i = 1; } for (; i < args.size(); ++i) { - std::string variable = args[i]; + std::string const& variable = args[i]; cmState* state = this->Makefile->GetState(); if (!state->GetCacheEntryValue(variable)) { this->Makefile->GetCMakeInstance()->AddCacheEntry( diff --git a/Source/cmMarkAsAdvancedCommand.h b/Source/cmMarkAsAdvancedCommand.h index 26caa6624..a7791a932 100644 --- a/Source/cmMarkAsAdvancedCommand.h +++ b/Source/cmMarkAsAdvancedCommand.h @@ -3,7 +3,8 @@ #ifndef cmMarkAsAdvancedCommand_h #define cmMarkAsAdvancedCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,19 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "mark_as_advanced"; } - - /** - * This determines if the command is invoked when in script mode. - * mark_as_advanced() will have no effect in script mode, but this will - * make many of the modules usable in cmake/ctest scripts, (among them - * FindUnixMake.cmake used by the CTEST_BUILD command. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } }; #endif diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h index 9b49b211b..67dbdda37 100644 --- a/Source/cmMathCommand.h +++ b/Source/cmMathCommand.h @@ -3,7 +3,8 @@ #ifndef cmMathCommand_h #define cmMathCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -27,16 +28,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "math"; } - protected: bool HandleExprCommand(std::vector const& args); }; diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h index a5656355b..96939e514 100644 --- a/Source/cmMessageCommand.h +++ b/Source/cmMessageCommand.h @@ -3,7 +3,8 @@ #ifndef cmMessageCommand_h #define cmMessageCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -29,16 +30,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "message"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } }; #endif diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index fe1c261cc..3ae5bc5c2 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -8,7 +8,7 @@ #include "cmSystemTools.h" #if defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cmsys/SystemInformation.hxx" #endif #include diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h index 89f8efe08..4aafbd40b 100644 --- a/Source/cmMessenger.h +++ b/Source/cmMessenger.h @@ -3,7 +3,7 @@ #ifndef cmMessenger_h #define cmMessenger_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmListFileCache.h" #include "cmake.h" diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx index 55451ff97..5500eba65 100644 --- a/Source/cmNewLineStyle.cxx +++ b/Source/cmNewLineStyle.cxx @@ -23,7 +23,7 @@ bool cmNewLineStyle::ReadFromArguments(const std::vector& args, if (args[i] == "NEWLINE_STYLE") { size_t const styleIndex = i + 1; if (args.size() > styleIndex) { - const std::string eol = args[styleIndex]; + std::string const& eol = args[styleIndex]; if (eol == "LF" || eol == "UNIX") { NewLineStyle = LF; return true; diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h index b46414cd9..397cd2c50 100644 --- a/Source/cmNewLineStyle.h +++ b/Source/cmNewLineStyle.h @@ -3,7 +3,7 @@ #ifndef cmNewLineStyle_h #define cmNewLineStyle_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmNinjaLinkLineComputer.cxx b/Source/cmNinjaLinkLineComputer.cxx index 2546b555f..7fbeeeaa3 100644 --- a/Source/cmNinjaLinkLineComputer.cxx +++ b/Source/cmNinjaLinkLineComputer.cxx @@ -4,12 +4,11 @@ #include "cmNinjaLinkLineComputer.h" #include "cmGlobalNinjaGenerator.h" -#include "cmStateDirectory.h" class cmOutputConverter; cmNinjaLinkLineComputer::cmNinjaLinkLineComputer( - cmOutputConverter* outputConverter, cmStateDirectory stateDir, + cmOutputConverter* outputConverter, cmStateDirectory const& stateDir, cmGlobalNinjaGenerator const* gg) : cmLinkLineComputer(outputConverter, stateDir) , GG(gg) diff --git a/Source/cmNinjaLinkLineComputer.h b/Source/cmNinjaLinkLineComputer.h index ff0771b82..13f05a838 100644 --- a/Source/cmNinjaLinkLineComputer.h +++ b/Source/cmNinjaLinkLineComputer.h @@ -4,7 +4,7 @@ #ifndef cmNinjaLinkLineComputer_h #define cmNinjaLinkLineComputer_h -#include +#include "cmConfigure.h" #include @@ -16,9 +16,11 @@ class cmStateDirectory; class cmNinjaLinkLineComputer : public cmLinkLineComputer { + CM_DISABLE_COPY(cmNinjaLinkLineComputer) + public: cmNinjaLinkLineComputer(cmOutputConverter* outputConverter, - cmStateDirectory stateDir, + cmStateDirectory const& stateDir, cmGlobalNinjaGenerator const* gg); std::string ConvertToLinkReference(std::string const& input) const diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index b1374c27b..14a4ef824 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -5,11 +5,9 @@ #include #include #include -#include #include #include #include -#include #include "cmAlgorithms.h" #include "cmCustomCommand.h" @@ -35,10 +33,6 @@ #include "cm_auto_ptr.hxx" #include "cmake.h" -#ifndef _WIN32 -#include -#endif - cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( cmGeneratorTarget* target) : cmNinjaTargetGenerator(target) @@ -260,12 +254,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i, vars); } - { - // If there is no ranlib the command will be ":". Skip it. - std::vector::iterator newEnd = std::remove_if( - linkCmds.begin(), linkCmds.end(), cmNinjaRemoveNoOpCommands()); - linkCmds.erase(newEnd, linkCmds.end()); - } + + // If there is no ranlib the command will be ":". Skip it. + cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); std::string linkCmd = this->GetLocalGenerator()->BuildCommandLine(linkCmds); @@ -388,12 +379,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i, vars); } - { - // If there is no ranlib the command will be ":". Skip it. - std::vector::iterator newEnd = std::remove_if( - linkCmds.begin(), linkCmds.end(), cmNinjaRemoveNoOpCommands()); - linkCmds.erase(newEnd, linkCmds.end()); - } + + // If there is no ranlib the command will be ":". Skip it. + cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); linkCmds.push_back("$POST_BUILD"); @@ -459,6 +447,7 @@ std::vector cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() // an executable or a dynamic library. std::string linkCmd; switch (this->GetGeneratorTarget()->GetType()) { + case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { const std::string cudaLinkCmd( @@ -497,10 +486,9 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() cmGeneratorTarget& gt = *this->GetGeneratorTarget(); const std::string cfgName = this->GetConfigName(); std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName)); - std::string targetOutputReal = - this->ConvertToNinjaPath(gt.GetFullPath(cfgName, - /*implib=*/false, - /*realname=*/true)); + std::string targetOutputReal = this->ConvertToNinjaPath( + gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true)); cmakeCommand += targetOutputReal; cmakeCommand += " || true"; linkCmds.push_back(cmakeCommand); @@ -522,6 +510,10 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() std::string linkCmdVar = "CMAKE_"; linkCmdVar += this->TargetLinkLanguage; linkCmdVar += "_ARCHIVE_CREATE"; + + linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmSystemTools::ExpandListArgument(linkCmd, linkCmds); } @@ -529,6 +521,10 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() std::string linkCmdVar = "CMAKE_"; linkCmdVar += this->TargetLinkLanguage; linkCmdVar += "_ARCHIVE_FINISH"; + + linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( + linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); + const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar); cmSystemTools::ExpandListArgument(linkCmd, linkCmds); } @@ -544,36 +540,6 @@ std::vector cmNinjaNormalTargetGenerator::ComputeLinkCmd() return std::vector(); } -static int calculateCommandLineLengthLimit(int linkRuleLength) -{ - static int const limits[] = { -#ifdef _WIN32 - 8000, -#endif -#if defined(__linux) - // #define MAX_ARG_STRLEN (PAGE_SIZE * 32) in Linux's binfmts.h - ((int)sysconf(_SC_PAGESIZE) * 32) - 1000, -#endif - std::numeric_limits::max() - }; - - size_t const arrSz = cmArraySize(limits); - int sz = *std::min_element(limits, limits + arrSz); -#if defined(_SC_ARG_MAX) - // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac - int const szArgMax = static_cast(sysconf(_SC_ARG_MAX)); - // a return value of -1 signifies an unrestricted value - if (szArgMax != -1) { - sz = std::min(sz, szArgMax - 1000); - } -#endif - if (sz == std::numeric_limits::max()) { - return 0; - } - - return sz - linkRuleLength; -} - void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() { cmGeneratorTarget& genTarget = *this->GetGeneratorTarget(); @@ -594,11 +560,15 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() case cmStateEnums::EXECUTABLE: shouldHaveDeviceLinking = true; break; + case cmStateEnums::STATIC_LIBRARY: + shouldHaveDeviceLinking = + genTarget.GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); + break; default: break; } - if (!shouldHaveDeviceLinking || !hasCUDA) { + if (!(shouldHaveDeviceLinking && hasCUDA)) { return; } @@ -614,9 +584,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() std::string const targetOutputReal = ConvertToNinjaPath( genTarget.ObjectDirectory + "cmake_device_link" + objExt); - std::string const targetOutputImplib = - ConvertToNinjaPath(genTarget.GetFullPath(cfgName, - /*implib=*/true)); + std::string const targetOutputImplib = ConvertToNinjaPath( + genTarget.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); this->DeviceLinkObject = targetOutputReal; @@ -686,7 +655,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName); vars["ARCH_FLAGS"] = t; t = ""; - localGen.AddLanguageFlags(t, cudaLinkLanguage, cfgName); + localGen.AddLanguageFlagsForLinking(t, &genTarget, cudaLinkLanguage, + cfgName); vars["LANGUAGE_COMPILE_FLAGS"] = t; } if (this->GetGeneratorTarget()->HasSOName(cfgName)) { @@ -759,8 +729,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // Device linking currently doesn't support response files so // do not check if the user has explicitly forced a response file. - int const commandLineLengthLimit = calculateCommandLineLengthLimit( - globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule())); + int const commandLineLengthLimit = + static_cast(cmSystemTools::CalculateCommandLineLengthLimit()) - + globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule()); const std::string rspfile = std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + @@ -786,13 +757,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmGeneratorTarget& gt = *this->GetGeneratorTarget(); const std::string cfgName = this->GetConfigName(); std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName)); - std::string targetOutputReal = - ConvertToNinjaPath(gt.GetFullPath(cfgName, - /*implib=*/false, - /*realname=*/true)); - std::string targetOutputImplib = - ConvertToNinjaPath(gt.GetFullPath(cfgName, - /*implib=*/true)); + std::string targetOutputReal = ConvertToNinjaPath( + gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true)); + std::string targetOutputImplib = ConvertToNinjaPath( + gt.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact)); if (gt.IsAppBundleOnApple()) { // Create the app bundle @@ -869,19 +838,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"], vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget); - if (this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && - (gt.GetType() == cmStateEnums::SHARED_LIBRARY || - gt.IsExecutableWithExports())) { - if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - std::string name_of_def_file = gt.GetSupportDirectory(); - name_of_def_file += "/" + gt.GetName(); - name_of_def_file += ".def "; - vars["LINK_FLAGS"] += " /DEF:"; - vars["LINK_FLAGS"] += this->GetLocalGenerator()->ConvertToOutputFormat( - name_of_def_file, cmOutputConverter::SHELL); - } - } - // Add OS X version flags, if any. if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { @@ -919,7 +875,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["ARCH_FLAGS"] = t; t = ""; t += lwyuFlags; - localGen.AddLanguageFlags(t, TargetLinkLanguage, cfgName); + localGen.AddLanguageFlagsForLinking(t, &genTarget, TargetLinkLanguage, + cfgName); vars["LANGUAGE_COMPILE_FLAGS"] = t; } if (this->GetGeneratorTarget()->HasSOName(cfgName)) { @@ -998,35 +955,39 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } // maybe create .def file from list of objects - if ((gt.GetType() == cmStateEnums::SHARED_LIBRARY || - gt.IsExecutableWithExports()) && - this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) { - std::string cmakeCommand = - this->GetLocalGenerator()->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); - std::string name_of_def_file = gt.GetSupportDirectory(); - name_of_def_file += "/" + gt.GetName(); - name_of_def_file += ".def"; - std::string cmd = cmakeCommand; - cmd += " -E __create_def "; - cmd += this->GetLocalGenerator()->ConvertToOutputFormat( - name_of_def_file, cmOutputConverter::SHELL); - cmd += " "; + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + gt.GetModuleDefinitionInfo(this->GetConfigName()); + if (mdi && mdi->DefFileGenerated) { + std::string cmakeCommand = + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); + std::string cmd = cmakeCommand; + cmd += " -E __create_def "; + cmd += this->GetLocalGenerator()->ConvertToOutputFormat( + mdi->DefFile, cmOutputConverter::SHELL); + cmd += " "; + std::string obj_list_file = mdi->DefFile + ".objs"; + cmd += this->GetLocalGenerator()->ConvertToOutputFormat( + obj_list_file, cmOutputConverter::SHELL); + preLinkCmdLines.push_back(cmd); + + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(obj_list_file.c_str()); + + if (mdi->WindowsExportAllSymbols) { cmNinjaDeps objs = this->GetObjects(); - std::string obj_list_file = name_of_def_file; - obj_list_file += ".objs"; - cmd += this->GetLocalGenerator()->ConvertToOutputFormat( - obj_list_file, cmOutputConverter::SHELL); - preLinkCmdLines.push_back(cmd); - // create a list of obj files for the -E __create_def to read - cmGeneratedFileStream fout(obj_list_file.c_str()); for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) { if (cmHasLiteralSuffix(*i, ".obj")) { fout << *i << "\n"; } } } + + for (std::vector::const_iterator i = + mdi->Sources.begin(); + i != mdi->Sources.end(); ++i) { + fout << (*i)->GetFullPath() << "\n"; + } } // If we have any PRE_LINK commands, we need to go back to CMAKE_BINARY_DIR // for @@ -1055,8 +1016,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() !(this->TargetLinkLanguage == "RC" || this->TargetLinkLanguage == "CUDA"); int commandLineLengthLimit = -1; if (!lang_supports_response || !this->ForceResponseFile()) { - commandLineLengthLimit = calculateCommandLineLengthLimit( - globalGen.GetRuleCmdLength(this->LanguageLinkerRule())); + commandLineLengthLimit = + static_cast(cmSystemTools::CalculateCommandLineLengthLimit()) - + globalGen.GetRuleCmdLength(this->LanguageLinkerRule()); } const std::string rspfile = diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index e5595ea08..677b1c666 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmNinjaNormalTargetGenerator_h #define cmNinjaNormalTargetGenerator_h -#include +#include "cmConfigure.h" #include "cmNinjaTargetGenerator.h" diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index d57b8f759..d38dbcb09 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -2,10 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmNinjaTargetGenerator.h" +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" #include #include -#include -#include #include #include #include @@ -117,7 +117,7 @@ bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget() { - return "cmake_order_depends_target_" + this->GetTargetName(); + return "cmake_object_order_depends_target_" + this->GetTargetName(); } // TODO: Most of the code is picked up from @@ -212,9 +212,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath()); // Add a dependency on the link definitions file, if any. - if (this->ModuleDefinitionFile) { - result.push_back( - this->ConvertToNinjaPath(this->ModuleDefinitionFile->GetFullPath())); + if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo( + this->GetConfigName())) { + for (std::vector::const_iterator i = + mdi->Sources.begin(); + i != mdi->Sources.end(); ++i) { + result.push_back(this->ConvertToNinjaPath((*i)->GetFullPath())); + } } // Add a dependency on user-specified manifest files, if any. @@ -552,13 +557,26 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // Write the rule for ninja dyndep file generation. std::vector ddCmds; +#ifdef _WIN32 + // Windows command line length is limited -> use response file for dyndep + // rules + std::string ddRspFile = "$out.rsp"; + std::string ddRspContent = "$in"; + std::string ddInput = "@" + ddRspFile; +#else + std::string ddRspFile; + std::string ddRspContent; + std::string ddInput = "$in"; +#endif + // Run CMake dependency scanner on preprocessed output. std::string const cmake = this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); ddCmds.push_back(cmake + " -E cmake_ninja_dyndep" " --tdi=" + tdi + " --dd=$out" - " $in"); + " " + + ddInput); std::string const ddCmdLine = this->GetLocalGenerator()->BuildCommandLine(ddCmds); @@ -570,9 +588,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) this->GetGlobalGenerator()->AddRule( this->LanguageDyndepRule(lang), ddCmdLine, ddDesc.str(), ddComment.str(), /*depfile*/ "", - /*deps*/ "", - /*rspfile*/ "", - /*rspcontent*/ "", + /*deps*/ "", ddRspFile, ddRspContent, /*restat*/ "", /*generator*/ false); } @@ -584,6 +600,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) if (this->GeneratorTarget->GetPropertyAsBool( "CUDA_SEPARABLE_COMPILATION")) { cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION"); + } else if (this->GeneratorTarget->GetPropertyAsBool( + "CUDA_PTX_COMPILATION")) { + cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION"); } else { cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"); } @@ -710,8 +729,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() } cmNinjaDeps orderOnlyDeps; - this->GetLocalGenerator()->AppendTargetDepends(this->GeneratorTarget, - orderOnlyDeps); + this->GetLocalGenerator()->AppendTargetDepends( + this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering); // Add order-only dependencies on other files associated with the target. orderOnlyDeps.insert(orderOnlyDeps.end(), this->ExtraFiles.begin(), @@ -732,7 +751,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() std::back_inserter(orderOnlyDeps), MapToNinjaPath()); } - if (!orderOnlyDeps.empty()) { + std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end()); + orderOnlyDeps.erase(std::unique(orderOnlyDeps.begin(), orderOnlyDeps.end()), + orderOnlyDeps.end()); + + { cmNinjaDeps orderOnlyTarget; orderOnlyTarget.push_back(this->OrderDependsTargetForTarget()); this->GetGlobalGenerator()->WritePhonyBuild( @@ -745,7 +768,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() for (std::vector::const_iterator si = objectSources.begin(); si != objectSources.end(); ++si) { - this->WriteObjectBuildStatement(*si, !orderOnlyDeps.empty()); + this->WriteObjectBuildStatement(*si); } if (!this->DDIFiles.empty()) { @@ -762,6 +785,17 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() ddOutputs.push_back(this->GetDyndepFilePath("Fortran")); + // Make sure dyndep files for all our dependencies have already + // been generated so that the 'FortranModules.json' files they + // produced as side-effects are available for us to read. + // Ideally we should depend on the 'FortranModules.json' files + // from our dependencies directly, but we don't know which of + // our dependencies produces them. Fixing this will require + // refactoring the Ninja generator to generate targets in + // dependency order so that we can collect the needed information. + this->GetLocalGenerator()->AppendTargetDepends( + this->GeneratorTarget, ddOrderOnlyDeps, DependOnTargetArtifact); + this->GetGlobalGenerator()->WriteBuild( this->GetBuildFileStream(), ddComment, ddRule, ddOutputs, ddImplicitOuts, ddExplicitDeps, ddImplicitDeps, ddOrderOnlyDeps, ddVars); @@ -771,7 +805,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() } void cmNinjaTargetGenerator::WriteObjectBuildStatement( - cmSourceFile const* source, bool writeOrderDependsTargetForTarget) + cmSourceFile const* source) { std::string const language = source->GetLanguage(); std::string const sourceFileName = @@ -788,8 +822,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["DEFINES"] = this->ComputeDefines(source, language); vars["INCLUDES"] = this->GetIncludes(language); if (!this->NeedDepTypeMSVC(language)) { - vars["DEP_FILE"] = - cmGlobalNinjaGenerator::EncodeDepfileSpace(objectFileName + ".d"); + vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( + objectFileName + ".d", cmOutputConverter::SHELL); } this->ExportObjectCompileCommand( @@ -822,9 +856,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } cmNinjaDeps orderOnlyDeps; - if (writeOrderDependsTargetForTarget) { - orderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); - } + orderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of @@ -888,8 +920,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"]; // Explicit preprocessing always uses a depfile. - ppVars["DEP_FILE"] = - cmGlobalNinjaGenerator::EncodeDepfileSpace(ppFileName + ".d"); + ppVars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( + ppFileName + ".d", cmOutputConverter::SHELL); // The actual compilation does not need a depfile because it // depends on the already-preprocessed source. vars.erase("DEP_FILE"); @@ -1032,13 +1064,28 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( compileObjectVars.Includes = includes.c_str(); // Rule for compiling object file. - std::string compileCmdVar = "CMAKE_"; - compileCmdVar += language; - compileCmdVar += "_COMPILE_OBJECT"; - std::string compileCmd = - this->GetMakefile()->GetRequiredDefinition(compileCmdVar); std::vector compileCmds; - cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + if (language == "CUDA") { + std::string cmdVar; + if (this->GeneratorTarget->GetPropertyAsBool( + "CUDA_SEPARABLE_COMPILATION")) { + cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION"); + } else if (this->GeneratorTarget->GetPropertyAsBool( + "CUDA_PTX_COMPILATION")) { + cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION"); + } else { + cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"); + } + std::string compileCmd = + this->GetMakefile()->GetRequiredDefinition(cmdVar); + cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + } else { + const std::string cmdVar = + std::string("CMAKE_") + language + "_COMPILE_OBJECT"; + std::string compileCmd = + this->GetMakefile()->GetRequiredDefinition(cmdVar); + cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + } CM_AUTO_PTR rulePlaceholderExpander( this->GetLocalGenerator()->CreateRulePlaceholderExpander()); diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 7aba66b46..5eb7a9a49 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmNinjaTargetGenerator_h #define cmNinjaTargetGenerator_h -#include +#include "cmConfigure.h" #include "cmCommonTargetGenerator.h" #include "cmGlobalNinjaGenerator.h" @@ -119,8 +119,7 @@ protected: void WriteLanguageRules(const std::string& language); void WriteCompileRule(const std::string& language); void WriteObjectBuildStatements(); - void WriteObjectBuildStatement(cmSourceFile const* source, - bool writeOrderDependsTargetForTarget); + void WriteObjectBuildStatement(cmSourceFile const* source); void WriteTargetDependInfo(std::string const& lang); void ExportObjectCompileCommand( diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h index 3fd536ab4..ec435d9dd 100644 --- a/Source/cmNinjaTypes.h +++ b/Source/cmNinjaTypes.h @@ -3,12 +3,18 @@ #ifndef cmNinjaTypes_h #define cmNinjaTypes_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include #include +enum cmNinjaTargetDepends +{ + DependOnTargetArtifact, + DependOnTargetOrdering +}; + typedef std::vector cmNinjaDeps; typedef std::map cmNinjaVars; diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h index 897f4324e..9256e369c 100644 --- a/Source/cmNinjaUtilityTargetGenerator.h +++ b/Source/cmNinjaUtilityTargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmNinjaUtilityTargetGenerator_h #define cmNinjaUtilityTargetGenerator_h -#include +#include "cmConfigure.h" #include "cmNinjaTargetGenerator.h" diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 8139be44a..beddc6e6d 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -2,11 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmOSXBundleGenerator.h" -#include +#include "cmConfigure.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -42,22 +43,22 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // Compute bundle directory names. std::string out = outpath; out += "/"; - out += this->GT->GetAppBundleDirectory(this->ConfigName, false); + out += this->GT->GetAppBundleDirectory(this->ConfigName, + cmGeneratorTarget::FullLevel); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); - std::string newoutpath = out; - // Configure the Info.plist file. Note that it needs the executable name // to be set. std::string plist = outpath; plist += "/"; - plist += this->GT->GetAppBundleDirectory(this->ConfigName, true); + plist += this->GT->GetAppBundleDirectory(this->ConfigName, + cmGeneratorTarget::ContentLevel); plist += "/Info.plist"; this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist.c_str()); this->Makefile->AddCMakeOutputFile(plist); - outpath = newoutpath; + outpath = out; } void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, @@ -70,12 +71,14 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, assert(this->MacContentFolders); // Compute the location of the top-level foo.framework directory. - std::string contentdir = - outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, true); + std::string contentdir = outpath + "/" + + this->GT->GetFrameworkDirectory(this->ConfigName, + cmGeneratorTarget::ContentLevel); contentdir += "/"; - std::string newoutpath = - outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, false); + std::string newoutpath = outpath + "/" + + this->GT->GetFrameworkDirectory(this->ConfigName, + cmGeneratorTarget::FullLevel); std::string frameworkVersion = this->GT->GetFrameworkVersion(); @@ -170,14 +173,16 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, // Compute bundle directory names. std::string out = root; out += "/"; - out += this->GT->GetCFBundleDirectory(this->ConfigName, false); + out += this->GT->GetCFBundleDirectory(this->ConfigName, + cmGeneratorTarget::FullLevel); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = - root + "/" + this->GT->GetCFBundleDirectory(this->ConfigName, true); + std::string plist = root + "/" + + this->GT->GetCFBundleDirectory(this->ConfigName, + cmGeneratorTarget::ContentLevel); plist += "/Info.plist"; std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist.c_str()); @@ -207,8 +212,8 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory( { // Construct the full path to the content subdirectory. - std::string macdir = this->GT->GetMacContentDirectory(this->ConfigName, - /*implib*/ false); + std::string macdir = this->GT->GetMacContentDirectory( + this->ConfigName, cmStateEnums::RuntimeBinaryArtifact); macdir += "/"; macdir += pkgloc; cmSystemTools::MakeDirectory(macdir.c_str()); diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h index 0a5a6c5ee..be7e932f9 100644 --- a/Source/cmOSXBundleGenerator.h +++ b/Source/cmOSXBundleGenerator.h @@ -3,7 +3,7 @@ #ifndef cmOSXBundleGenerator_h #define cmOSXBundleGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmOptionCommand.h b/Source/cmOptionCommand.h index 09567ffc2..634e3a824 100644 --- a/Source/cmOptionCommand.h +++ b/Source/cmOptionCommand.h @@ -3,7 +3,8 @@ #ifndef cmOptionCommand_h #define cmOptionCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "option"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } }; #endif diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index d48eb53a3..333e3134c 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -424,7 +424,7 @@ struct cmOrderDirectoriesCompare // The conflict pair is unique based on just the directory // (first). The second element is only used for displaying // information about why the entry is present. - bool operator()(ConflictPair const& l, ConflictPair const& r) + bool operator()(ConflictPair l, ConflictPair r) { return l.first == r.first; } diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h index d9e01269f..3a0637afb 100644 --- a/Source/cmOrderDirectories.h +++ b/Source/cmOrderDirectories.h @@ -3,9 +3,9 @@ #ifndef cmOrderDirectories_h #define cmOrderDirectories_h -#include +#include "cmConfigure.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index d6864a618..14c986dd8 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -14,7 +14,7 @@ #include "cmStateDirectory.h" #include "cmSystemTools.h" -cmOutputConverter::cmOutputConverter(cmStateSnapshot snapshot) +cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot) : StateSnapshot(snapshot) , LinkScriptShell(false) { @@ -81,7 +81,7 @@ static bool cmOutputConverterNotAbove(const char* a, const char* b) bool cmOutputConverter::ContainedInDirectory(std::string const& local_path, std::string const& remote_path, - cmStateDirectory directory) + cmStateDirectory const& directory) { const std::string relativePathTopBinary = directory.GetRelativePathTopBinary(); diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index a3da4cd16..ae15055ed 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -3,7 +3,7 @@ #ifndef cmOutputConverter_h #define cmOutputConverter_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include @@ -15,7 +15,7 @@ class cmStateDirectory; class cmOutputConverter { public: - cmOutputConverter(cmStateSnapshot snapshot); + cmOutputConverter(cmStateSnapshot const& snapshot); enum OutputFormat { @@ -94,7 +94,7 @@ public: static bool ContainedInDirectory(std::string const& local_path, std::string const& remote_path, - cmStateDirectory directory); + cmStateDirectory const& directory); /** * Convert the given remote path to a relative path with respect to diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index 7a17f2cbd..2339d6876 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -2,15 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmOutputRequiredFilesCommand.h" -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #include #include #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -189,9 +188,8 @@ protected: if (qstart == std::string::npos) { cmSystemTools::Error("unknown include directive ", line.c_str()); continue; - } else { - qend = line.find('>', qstart + 1); } + qend = line.find('>', qstart + 1); } else { qend = line.find('\"', qstart + 1); } @@ -495,11 +493,6 @@ protected: bool cmOutputRequiredFilesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed(cmPolicies::CMP0032, "The output_required_files " - "command should not be called; " - "see CMP0032.")) { - return true; - } if (args.size() != 2) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h index c4ce68025..d20bfbdc1 100644 --- a/Source/cmOutputRequiredFilesCommand.h +++ b/Source/cmOutputRequiredFilesCommand.h @@ -3,7 +3,8 @@ #ifndef cmOutputRequiredFilesCommand_h #define cmOutputRequiredFilesCommand_h -#include +#include "cmConfigure.h" + #include #include #include @@ -20,7 +21,6 @@ public: cmCommand* Clone() CM_OVERRIDE { return new cmOutputRequiredFilesCommand; } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "output_required_files"; } void ListDependencies(cmDependInformation const* info, FILE* fout, std::set* visited); diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h index 079eadb82..359fb85b9 100644 --- a/Source/cmParseArgumentsCommand.h +++ b/Source/cmParseArgumentsCommand.h @@ -3,7 +3,8 @@ #ifndef cmParseArgumentsCommand_h #define cmParseArgumentsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -28,16 +29,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "cmake_parse_arguments"; } }; #endif diff --git a/Source/cmPathLabel.h b/Source/cmPathLabel.h index cd9743c70..97551fb46 100644 --- a/Source/cmPathLabel.h +++ b/Source/cmPathLabel.h @@ -3,7 +3,7 @@ #ifndef cmPathLabel_h #define cmPathLabel_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 6339e1158..da3edd427 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -8,8 +8,8 @@ #include "cmVersion.h" #include "cmake.h" +#include "cmConfigure.h" #include -#include #include #include #include @@ -275,6 +275,22 @@ std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id) return msg.str(); } +std::string cmPolicies::GetPolicyDeprecatedWarning(cmPolicies::PolicyID id) +{ + std::ostringstream msg; + /* clang-format off */ + msg << + "The OLD behavior for policy " << idToString(id) << " " + "will be removed from a future version of CMake.\n" + "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." + ; + /* clang-format on */ + return msg.str(); +} + ///! return an error string for when a required policy is unspecified std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id) { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 62e67c74f..69cbc1844 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -3,7 +3,7 @@ #ifndef cmPolicies_h #define cmPolicies_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -200,7 +200,13 @@ class cmMakefile; 7, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0067, \ "Honor language standard in try_compile() source-file signature.", \ - 3, 8, 0, cmPolicies::WARN) + 3, 8, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0068, \ + "RPATH settings on macOS do not affect install_name.", 3, 9, 0, \ + cmPolicies::WARN) \ + SELECT(POLICY, CMP0069, \ + "INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.", 3, 9, 0, \ + cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -221,7 +227,9 @@ class cmMakefile; F(CMP0052) \ F(CMP0060) \ F(CMP0063) \ - F(CMP0065) + F(CMP0065) \ + F(CMP0068) \ + F(CMP0069) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies @@ -271,6 +279,7 @@ public: ///! return a warning string for a given policy static std::string GetPolicyWarning(cmPolicies::PolicyID id); + static std::string GetPolicyDeprecatedWarning(cmPolicies::PolicyID id); ///! return an error string for when a required policy is unspecified static std::string GetRequiredPolicyError(cmPolicies::PolicyID id); diff --git a/Source/cmProcessOutput.h b/Source/cmProcessOutput.h index d2e631f88..b5ec4a8be 100644 --- a/Source/cmProcessOutput.h +++ b/Source/cmProcessOutput.h @@ -3,7 +3,7 @@ #ifndef cmProcessOutput_h #define cmProcessOutput_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx index b75665075..de7b06126 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -3,7 +3,7 @@ #include "cmProcessTools.h" #include "cmProcessOutput.h" -#include +#include "cmsys/Process.h" #include void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out, diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h index df131b95b..e7d9a10eb 100644 --- a/Source/cmProcessTools.h +++ b/Source/cmProcessTools.h @@ -3,8 +3,8 @@ #ifndef cmProcessTools_h #define cmProcessTools_h +#include "cmConfigure.h" #include "cmProcessOutput.h" -#include #include #include diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 4e0fa575a..d72c7909c 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmProjectCommand.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include @@ -22,11 +22,14 @@ bool cmProjectCommand::InitialPass(std::vector const& args, this->SetError("PROJECT called with incorrect number of arguments"); return false; } - this->Makefile->SetProjectName(args[0]); - std::string bindir = args[0]; + std::string const& projectName = args[0]; + + this->Makefile->SetProjectName(projectName); + + std::string bindir = projectName; bindir += "_BINARY_DIR"; - std::string srcdir = args[0]; + std::string srcdir = projectName; srcdir += "_SOURCE_DIR"; this->Makefile->AddCacheDefinition( @@ -44,7 +47,7 @@ bool cmProjectCommand::InitialPass(std::vector const& args, this->Makefile->AddDefinition(srcdir, this->Makefile->GetCurrentSourceDirectory()); - this->Makefile->AddDefinition("PROJECT_NAME", args[0].c_str()); + this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str()); // Set the CMAKE_PROJECT_NAME variable to be the highest-level // project name in the tree. If there are two project commands @@ -54,18 +57,21 @@ bool cmProjectCommand::InitialPass(std::vector const& args, // will work. if (!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") || (this->Makefile->IsRootMakefile())) { - this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", args[0].c_str()); - this->Makefile->AddCacheDefinition("CMAKE_PROJECT_NAME", args[0].c_str(), - "Value Computed by CMake", - cmStateEnums::STATIC); + this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName.c_str()); + this->Makefile->AddCacheDefinition( + "CMAKE_PROJECT_NAME", projectName.c_str(), "Value Computed by CMake", + cmStateEnums::STATIC); } bool haveVersion = false; bool haveLanguages = false; + bool haveDescription = false; std::string version; + std::string description; std::vector languages; enum Doing { + DoingDescription, DoingLanguages, DoingVersion }; @@ -89,9 +95,21 @@ bool cmProjectCommand::InitialPass(std::vector const& args, } haveVersion = true; doing = DoingVersion; + } else if (args[i] == "DESCRIPTION") { + if (haveDescription) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, "DESCRITPION may be specified at most once."); + cmSystemTools::SetFatalErrorOccured(); + return true; + } + haveDescription = true; + doing = DoingDescription; } else if (doing == DoingVersion) { doing = DoingLanguages; version = args[i]; + } else if (doing == DoingDescription) { + doing = DoingLanguages; + description = args[i]; } else // doing == DoingLanguages { languages.push_back(args[i]); @@ -148,19 +166,19 @@ bool cmProjectCommand::InitialPass(std::vector const& args, } std::string vv; - vv = args[0] + "_VERSION"; + vv = projectName + "_VERSION"; this->Makefile->AddDefinition("PROJECT_VERSION", vs.c_str()); this->Makefile->AddDefinition(vv, vs.c_str()); - vv = args[0] + "_VERSION_MAJOR"; + vv = projectName + "_VERSION_MAJOR"; this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", vb[0]); this->Makefile->AddDefinition(vv, vb[0]); - vv = args[0] + "_VERSION_MINOR"; + vv = projectName + "_VERSION_MINOR"; this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", vb[1]); this->Makefile->AddDefinition(vv, vb[1]); - vv = args[0] + "_VERSION_PATCH"; + vv = projectName + "_VERSION_PATCH"; this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", vb[2]); this->Makefile->AddDefinition(vv, vb[2]); - vv = args[0] + "_VERSION_TWEAK"; + vv = projectName + "_VERSION_TWEAK"; this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]); this->Makefile->AddDefinition(vv, vb[3]); } else if (cmp0048 != cmPolicies::OLD) { @@ -171,11 +189,11 @@ bool cmProjectCommand::InitialPass(std::vector const& args, vv.push_back("PROJECT_VERSION_MINOR"); vv.push_back("PROJECT_VERSION_PATCH"); vv.push_back("PROJECT_VERSION_TWEAK"); - vv.push_back(args[0] + "_VERSION"); - vv.push_back(args[0] + "_VERSION_MAJOR"); - vv.push_back(args[0] + "_VERSION_MINOR"); - vv.push_back(args[0] + "_VERSION_PATCH"); - vv.push_back(args[0] + "_VERSION_TWEAK"); + vv.push_back(projectName + "_VERSION"); + vv.push_back(projectName + "_VERSION_MAJOR"); + vv.push_back(projectName + "_VERSION_MINOR"); + vv.push_back(projectName + "_VERSION_PATCH"); + vv.push_back(projectName + "_VERSION_TWEAK"); std::string vw; for (std::vector::iterator i = vv.begin(); i != vv.end(); ++i) { @@ -197,13 +215,29 @@ bool cmProjectCommand::InitialPass(std::vector const& args, } } + if (haveDescription) { + this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str()); + // Set the CMAKE_PROJECT_DESCRIPTION variable to be the highest-level + // project name in the tree. If there are two project commands + // in the same CMakeLists.txt file, and it is the top level + // CMakeLists.txt file, then go with the last one. + if (!this->Makefile->GetDefinition("CMAKE_PROJECT_DESCRIPTION") || + (this->Makefile->IsRootMakefile())) { + this->Makefile->AddDefinition("CMAKE_PROJECT_DESCRIPTION", + description.c_str()); + this->Makefile->AddCacheDefinition( + "CMAKE_PROJECT_DESCRIPTION", description.c_str(), + "Value Computed by CMake", cmStateEnums::STATIC); + } + } + if (languages.empty()) { // if no language is specified do c and c++ languages.push_back("C"); languages.push_back("CXX"); } this->Makefile->EnableLanguage(languages, false); - std::string extraInclude = "CMAKE_PROJECT_" + args[0] + "_INCLUDE"; + std::string extraInclude = "CMAKE_PROJECT_" + projectName + "_INCLUDE"; const char* include = this->Makefile->GetDefinition(extraInclude); if (include) { bool readit = this->Makefile->ReadDependentFile(include); diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h index cd92176c3..3c579ac9d 100644 --- a/Source/cmProjectCommand.h +++ b/Source/cmProjectCommand.h @@ -3,7 +3,8 @@ #ifndef cmProjectCommand_h #define cmProjectCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -33,11 +34,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "project"; } }; #endif diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx index 90122a49f..222afb497 100644 --- a/Source/cmProperty.cxx +++ b/Source/cmProperty.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmProperty.h" -#include +#include "cmConfigure.h" void cmProperty::Set(const char* value) { diff --git a/Source/cmProperty.h b/Source/cmProperty.h index 3f2dcfe13..d11c5efbb 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -3,7 +3,7 @@ #ifndef cmProperty_h #define cmProperty_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h index eb8d06440..9adff4902 100644 --- a/Source/cmPropertyDefinition.h +++ b/Source/cmPropertyDefinition.h @@ -3,7 +3,7 @@ #ifndef cmPropertyDefinition_h #define cmPropertyDefinition_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmProperty.h" diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h index e74750385..97ba55391 100644 --- a/Source/cmPropertyDefinitionMap.h +++ b/Source/cmPropertyDefinitionMap.h @@ -3,7 +3,7 @@ #ifndef cmPropertyDefinitionMap_h #define cmPropertyDefinitionMap_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmProperty.h" #include "cmPropertyDefinition.h" diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index fa92ae231..1e089d1c8 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPropertyMap.h" +#include "cmConfigure.h" #include #include -#include #include cmProperty* cmPropertyMap::GetOrCreateProperty(const std::string& name) diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index e1db7df66..5a0515076 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -3,7 +3,7 @@ #ifndef cmPropertyMap_h #define cmPropertyMap_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmProperty.h" diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h index 8eb5ff93e..ad1ccf38d 100644 --- a/Source/cmQTWrapCPPCommand.h +++ b/Source/cmQTWrapCPPCommand.h @@ -3,7 +3,8 @@ #ifndef cmQTWrapCPPCommand_h #define cmQTWrapCPPCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,11 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "qt_wrap_cpp"; } }; #endif diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h index 876ddd529..ac7ab01c7 100644 --- a/Source/cmQTWrapUICommand.h +++ b/Source/cmQTWrapUICommand.h @@ -3,7 +3,8 @@ #ifndef cmQTWrapUICommand_h #define cmQTWrapUICommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,11 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "qt_wrap_ui"; } }; #endif diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGeneratorCommon.cxx new file mode 100644 index 000000000..3e1b58caa --- /dev/null +++ b/Source/cmQtAutoGeneratorCommon.cxx @@ -0,0 +1,216 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGeneratorCommon.h" +#include "cmAlgorithms.h" +#include "cmSystemTools.h" + +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" + +#include +#include + +// - Static functions + +static std::string utilStripCR(std::string const& line) +{ + // Strip CR characters rcc may have printed (possibly more than one!). + std::string::size_type cr = line.find('\r'); + if (cr != std::string::npos) { + return line.substr(0, cr); + } + return line; +} + +/// @brief Reads the resource files list from from a .qrc file - Qt4 version +/// @return True if the .qrc file was successfully parsed +static bool RccListInputsQt4(const std::string& fileName, + std::vector& files, + std::string* errorMessage) +{ + bool allGood = true; + // Read qrc file content into string + std::string qrcContents; + { + cmsys::ifstream ifs(fileName.c_str()); + if (ifs) { + std::ostringstream osst; + osst << ifs.rdbuf(); + qrcContents = osst.str(); + } else { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc file not readable:\n" + << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; + *errorMessage = ost.str(); + } + allGood = false; + } + } + if (allGood) { + // qrc file directory + std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName)); + if (!qrcDir.empty()) { + qrcDir += '/'; + } + + cmsys::RegularExpression fileMatchRegex("(]*>)"); + + size_t offset = 0; + while (fileMatchRegex.find(qrcContents.c_str() + offset)) { + std::string qrcEntry = fileMatchRegex.match(1); + offset += qrcEntry.size(); + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } + if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { + qrcEntry = qrcDir + qrcEntry; + } + files.push_back(qrcEntry); + } + } + return allGood; +} + +/// @brief Reads the resource files list from from a .qrc file - Qt5 version +/// @return True if the .qrc file was successfully parsed +static bool RccListInputsQt5(const std::string& rccCommand, + const std::string& fileName, + std::vector& files, + std::string* errorMessage) +{ + if (rccCommand.empty()) { + cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n"); + return false; + } + + // Read rcc features + bool hasDashDashList = false; + { + std::vector command; + command.push_back(rccCommand); + command.push_back("--help"); + std::string rccStdOut; + std::string rccStdErr; + int retVal = 0; + bool result = + cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, + CM_NULLPTR, cmSystemTools::OUTPUT_NONE); + if (result && retVal == 0 && + rccStdOut.find("--list") != std::string::npos) { + hasDashDashList = true; + } + } + + // Run rcc list command + bool result = false; + int retVal = 0; + std::string rccStdOut; + std::string rccStdErr; + { + std::vector command; + command.push_back(rccCommand); + command.push_back(hasDashDashList ? "--list" : "-list"); + command.push_back(fileName); + result = + cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, + CM_NULLPTR, cmSystemTools::OUTPUT_NONE); + } + if (!result || retVal) { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc list process for " << fileName + << " failed:\n" + << rccStdOut << "\n" + << rccStdErr << "\n"; + *errorMessage = ost.str(); + } + return false; + } + + // Parse rcc std output + { + std::istringstream ostr(rccStdOut); + std::string oline; + while (std::getline(ostr, oline)) { + oline = utilStripCR(oline); + if (!oline.empty()) { + files.push_back(oline); + } + } + } + // Parse rcc error output + { + std::istringstream estr(rccStdErr); + std::string eline; + while (std::getline(estr, eline)) { + eline = utilStripCR(eline); + if (cmHasLiteralPrefix(eline, "RCC: Error in")) { + static std::string searchString = "Cannot find file '"; + + std::string::size_type pos = eline.find(searchString); + if (pos == std::string::npos) { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc lists unparsable output:\n" + << cmQtAutoGeneratorCommon::Quoted(eline) << "\n"; + *errorMessage = ost.str(); + } + return false; + } + pos += searchString.length(); + std::string::size_type sz = eline.size() - pos - 1; + files.push_back(eline.substr(pos, sz)); + } + } + } + + return true; +} + +// - Class definitions + +const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@"; + +std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text) +{ + static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", + "\b", "\\b", "\f", "\\f", "\n", "\\n", + "\r", "\\r", "\t", "\\t", "\v", "\\v" }; + + std::string res = text; + for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep); + it += 2) { + cmSystemTools::ReplaceString(res, *it, *(it + 1)); + } + res = '"' + res; + res += '"'; + return res; +} + +bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion, + const std::string& rccCommand, + const std::string& fileName, + std::vector& files, + std::string* errorMessage) +{ + bool allGood = false; + if (cmsys::SystemTools::FileExists(fileName.c_str())) { + if (qtMajorVersion == "4") { + allGood = RccListInputsQt4(fileName, files, errorMessage); + } else { + allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage); + } + } else { + if (errorMessage != CM_NULLPTR) { + std::ostringstream ost; + ost << "AutoRcc: Error: Rcc file does not exist:\n" + << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n"; + *errorMessage = ost.str(); + } + } + return allGood; +} diff --git a/Source/cmQtAutoGeneratorCommon.h b/Source/cmQtAutoGeneratorCommon.h new file mode 100644 index 000000000..a131baf20 --- /dev/null +++ b/Source/cmQtAutoGeneratorCommon.h @@ -0,0 +1,39 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGeneratorCommon_h +#define cmQtAutoGeneratorCommon_h + +#include "cmConfigure.h" + +#include +#include + +class cmQtAutoGeneratorCommon +{ + // - Types and statics +public: + static const char* listSep; + + enum GeneratorType + { + MOC, + UIC, + RCC + }; + +public: + /// @brief Returns a the string escaped and enclosed in quotes + /// + static std::string Quoted(const std::string& text); + + /// @brief Reads the resource files list from from a .qrc file + /// @arg fileName Must be the absolute path of the .qrc file + /// @return True if the rcc file was successfully parsed + static bool RccListInputs(const std::string& qtMajorVersion, + const std::string& rccCommand, + const std::string& fileName, + std::vector& files, + std::string* errorMessage = CM_NULLPTR); +}; + +#endif diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 825eba0e1..cecf16541 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGeneratorInitializer.h" +#include "cmQtAutoGeneratorCommon.h" #include "cmAlgorithms.h" #include "cmCustomCommandLines.h" @@ -11,27 +12,23 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmSourceFile.h" -#include "cmSourceFileLocation.h" +#include "cmSourceGroup.h" #include "cmState.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cm_sys_stat.h" #include "cmake.h" #if defined(_WIN32) && !defined(__CYGWIN__) #include "cmGlobalVisualStudioGenerator.h" #endif +#include "cmConfigure.h" +#include "cmsys/FStream.hxx" #include -#include -#include -#include -#include #include #include -#include -#include #include -#include #include #include @@ -45,14 +42,16 @@ static void utilCopyTargetProperty(cmTarget* destinationTarget, } } -static std::string utilStripCR(std::string const& line) +inline static bool PropertyEnabled(cmSourceFile* sourceFile, const char* key) { - // Strip CR characters rcc may have printed (possibly more than one!). - std::string::size_type cr = line.find('\r'); - if (cr != line.npos) { - return line.substr(0, cr); - } - return line; + return cmSystemTools::IsOn(sourceFile->GetPropertyForUser(key)); +} + +static std::string GetSafeProperty(cmGeneratorTarget const* target, + const char* key) +{ + const char* tmp = target->GetProperty(key); + return std::string((tmp != CM_NULLPTR) ? tmp : ""); } static std::string GetAutogenTargetName(cmGeneratorTarget const* target) @@ -69,17 +68,19 @@ static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target) targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); targetDir += "/"; targetDir += GetAutogenTargetName(target); - targetDir += ".dir/"; + targetDir += ".dir"; return targetDir; } static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target) { - cmMakefile* makefile = target->Target->GetMakefile(); - std::string targetDir = makefile->GetCurrentBinaryDirectory(); - targetDir += "/"; - targetDir += GetAutogenTargetName(target); - targetDir += "/"; + std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR"); + if (targetDir.empty()) { + cmMakefile* makefile = target->Target->GetMakefile(); + targetDir = makefile->GetCurrentBinaryDirectory(); + targetDir += "/"; + targetDir += GetAutogenTargetName(target); + } return targetDir; } @@ -98,21 +99,200 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target) return qtMajorVersion; } -static void SetupSourceFiles(cmGeneratorTarget const* target, +static std::string GetQtMinorVersion(cmGeneratorTarget const* target, + const std::string& qtMajorVersion) +{ + cmMakefile* makefile = target->Target->GetMakefile(); + std::string qtMinorVersion; + if (qtMajorVersion == "5") { + qtMinorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); + } + if (qtMinorVersion.empty()) { + qtMinorVersion = makefile->GetSafeDefinition("QT_VERSION_MINOR"); + } + + const char* targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", ""); + if (targetQtVersion != CM_NULLPTR) { + qtMinorVersion = targetQtVersion; + } + return qtMinorVersion; +} + +static bool QtVersionGreaterOrEqual(const std::string& major, + const std::string& minor, + unsigned long requestMajor, + unsigned long requestMinor) +{ + unsigned long majorUL(0); + unsigned long minorUL(0); + if (cmSystemTools::StringToULong(major.c_str(), &majorUL) && + cmSystemTools::StringToULong(minor.c_str(), &minorUL)) { + return (majorUL > requestMajor) || + (majorUL == requestMajor && minorUL >= requestMinor); + } + return false; +} + +static void GetCompileDefinitionsAndDirectories( + cmGeneratorTarget const* target, const std::string& config, + std::string& incs, std::string& defs) +{ + cmLocalGenerator* localGen = target->GetLocalGenerator(); + { + std::vector includeDirs; + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); + incs = cmJoin(includeDirs, ";"); + } + { + std::set defines; + localGen->AddCompileDefinitions(defines, target, config, "CXX"); + defs += cmJoin(defines, ";"); + } +} + +static bool IsMultiConfig(cmGlobalGenerator* globalGen) +{ + // FIXME: Xcode does not support per-config sources, yet. + // (EXCLUDED_SOURCE_FILE_NAMES) + // Treat it as a single configuration generator meanwhile. + if (globalGen->GetName().find("Xcode") != std::string::npos) { + return false; + } + // FIXME: Visual Studio does not fully support per-config sources yet. + if (globalGen->GetName().find("Visual Studio") != std::string::npos) { + return false; + } + return globalGen->IsMultiConfig(); +} + +static std::vector GetConfigurations( + cmMakefile* makefile, std::string* config = CM_NULLPTR) +{ + std::vector configs; + { + std::string cfg = makefile->GetConfigurations(configs); + if (config != CM_NULLPTR) { + *config = cfg; + } + } + // Add empty configuration on demand + if (configs.empty()) { + configs.push_back(""); + } + return configs; +} + +static std::vector GetConfigurationSuffixes(cmMakefile* makefile) +{ + std::vector suffixes; + if (IsMultiConfig(makefile->GetGlobalGenerator())) { + makefile->GetConfigurations(suffixes); + for (std::vector::iterator it = suffixes.begin(); + it != suffixes.end(); ++it) { + it->insert(0, "_"); + } + } + if (suffixes.empty()) { + suffixes.push_back(""); + } + return suffixes; +} + +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::string& value) +{ + makefile->AddDefinition(key, + cmOutputConverter::EscapeForCMake(value).c_str()); +} + +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::vector& values) +{ + makefile->AddDefinition( + key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); +} + +static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName, + cmQtAutoGeneratorCommon::GeneratorType genType) +{ + cmSourceGroup* sourceGroup = CM_NULLPTR; + // Acquire source group + { + const char* groupName = CM_NULLPTR; + // Use generator specific group name + switch (genType) { + case cmQtAutoGeneratorCommon::MOC: + groupName = + makefile->GetState()->GetGlobalProperty("AUTOMOC_SOURCE_GROUP"); + break; + case cmQtAutoGeneratorCommon::RCC: + groupName = + makefile->GetState()->GetGlobalProperty("AUTORCC_SOURCE_GROUP"); + break; + default: + break; + } + // Use default group name on demand + if ((groupName == CM_NULLPTR) || (*groupName == 0)) { + groupName = + makefile->GetState()->GetGlobalProperty("AUTOGEN_SOURCE_GROUP"); + } + // Generate a source group on demand + if ((groupName != CM_NULLPTR) && (*groupName != 0)) { + { + const char* delimiter = + makefile->GetDefinition("SOURCE_GROUP_DELIMITER"); + if (delimiter == CM_NULLPTR) { + delimiter = "\\"; + } + std::vector folders = + cmSystemTools::tokenize(groupName, delimiter); + sourceGroup = makefile->GetSourceGroup(folders); + if (sourceGroup == CM_NULLPTR) { + makefile->AddSourceGroup(folders); + sourceGroup = makefile->GetSourceGroup(folders); + } + } + if (sourceGroup == CM_NULLPTR) { + cmSystemTools::Error( + "Autogen: Could not create or find source group: ", + cmQtAutoGeneratorCommon::Quoted(groupName).c_str()); + return false; + } + } + } + if (sourceGroup != CM_NULLPTR) { + sourceGroup->AddGroupFile(fileName); + } + return true; +} + +static void AddGeneratedSource(cmMakefile* makefile, + const std::string& filename, + cmQtAutoGeneratorCommon::GeneratorType genType) +{ + cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true); + gFile->SetProperty("GENERATED", "1"); + gFile->SetProperty("SKIP_AUTOGEN", "On"); + + AddToSourceGroup(makefile, filename, genType); +} + +static void AcquireScanFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, - std::vector& skipMocList, - std::vector& skipUicList) + std::vector& mocSkipList, + std::vector& uicSkipList) { - cmMakefile* makefile = target->Target->GetMakefile(); + const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); + const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - - const bool targetMoc = target->GetPropertyAsBool("AUTOMOC"); - const bool targetUic = target->GetPropertyAsBool("AUTOUIC"); - - cmFilePathChecksum fpathCheckSum(makefile); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; @@ -123,30 +303,31 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { continue; } - if (cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { + if (PropertyEnabled(sf, "GENERATED") && + !target->GetPropertyAsBool("__UNDOCUMENTED_AUTOGEN_GENERATED_FILES")) { + // FIXME: Add a policy whose NEW behavior allows generated files. + // The implementation already works. We disable it here to avoid + // changing behavior for existing projects that do not expect it. continue; } const std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); // Skip flags - const bool skipAll = - cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); - const bool skipMoc = - skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - const bool skipUic = - skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")); + const bool skipAll = PropertyEnabled(sf, "SKIP_AUTOGEN"); + const bool mocSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOMOC"); + const bool uicSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOUIC"); // Add file name to skip lists. // Do this even when the file is not added to the sources/headers lists // because the file name may be extracted from an other file when // processing - if (skipMoc) { - skipMocList.push_back(absFile); + if (mocSkip) { + mocSkipList.push_back(absFile); } - if (skipUic) { - skipUicList.push_back(absFile); + if (uicSkip) { + uicSkipList.push_back(absFile); } - if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) { + if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) { // Add file name to sources or headers list switch (fileType) { case cmSystemTools::CXX_FILE_FORMAT: @@ -162,100 +343,87 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, } } -static void GetCompileDefinitionsAndDirectories( - cmGeneratorTarget const* target, const std::string& config, - std::string& incs, std::string& defs) -{ - std::vector includeDirs; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see https://gitlab.kitware.com/cmake/cmake/issues/13667 - localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); - - incs = cmJoin(includeDirs, ";"); - - std::set defines; - localGen->AddCompileDefinitions(defines, target, config, "CXX"); - - defs += cmJoin(defines, ";"); -} - static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, - std::vector const& skipMoc, - std::map& configIncludes, - std::map& configDefines) + std::string const& qtMajorVersion, std::string const& config, + std::vector const& configs, + std::vector const& mocSkipList, + std::map& configMocIncludes, + std::map& configMocDefines) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); - std::string _moc_options = (tmp != CM_NULLPTR ? tmp : ""); - makefile->AddDefinition( - "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); - makefile->AddDefinition( - "_skip_moc", - cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); - bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); - makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); - - std::string _moc_incs; - std::string _moc_compile_defs; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - GetCompileDefinitionsAndDirectories(target, config, _moc_incs, - _moc_compile_defs); - - makefile->AddDefinition( - "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); - makefile->AddDefinition( - "_moc_compile_defs", - cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); - - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_moc_incs; - std::string config_moc_compile_defs; - GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, - config_moc_compile_defs); - if (config_moc_incs != _moc_incs) { - configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs); - if (_moc_incs.empty()) { - _moc_incs = config_moc_incs; + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); + AddDefinitionEscaped(makefile, "_moc_depend_filters", + GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS")); + + if (QtVersionGreaterOrEqual( + qtMajorVersion, GetQtMinorVersion(target, qtMajorVersion), 5, 8)) { + AddDefinitionEscaped( + makefile, "_moc_predefs_cmd", + makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND")); + } + // Moc includes and compile definitions + { + // Default settings + std::string incs; + std::string compileDefs; + GetCompileDefinitionsAndDirectories(target, config, incs, compileDefs); + AddDefinitionEscaped(makefile, "_moc_incs", incs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs); + + // Configuration specific settings + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string configIncs; + std::string configCompileDefs; + GetCompileDefinitionsAndDirectories(target, *li, configIncs, + configCompileDefs); + if (configIncs != incs) { + configMocIncludes[*li] = cmOutputConverter::EscapeForCMake(configIncs); } - } - if (config_moc_compile_defs != _moc_compile_defs) { - configDefines[*li] = - cmOutputConverter::EscapeForCMake(config_moc_compile_defs); - if (_moc_compile_defs.empty()) { - _moc_compile_defs = config_moc_compile_defs; + if (configCompileDefs != compileDefs) { + configMocDefines[*li] = + cmOutputConverter::EscapeForCMake(configCompileDefs); } } } - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); - if (!qt5Moc) { - cmSystemTools::Error("Qt5::moc target not found ", - autogenTargetName.c_str()); - return; + // Moc executable + { + std::string err; + const char* mocExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); + if (qt5Moc != CM_NULLPTR) { + mocExec = qt5Moc->ImportedGetLocation(""); + } else { + err = "Qt5::moc target not found " + autogenTargetName; + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); + if (qt4Moc != CM_NULLPTR) { + mocExec = qt4Moc->ImportedGetLocation(""); + } else { + err = "Qt4::moc target not found " + autogenTargetName; + } + } else { + err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 "; + err += autogenTargetName; } - makefile->AddDefinition("_qt_moc_executable", - qt5Moc->ImportedGetLocation("")); - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); - if (!qt4Moc) { - cmSystemTools::Error("Qt4::moc target not found ", - autogenTargetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", + mocExec ? mocExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_moc_executable", - qt4Moc->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " - "Qt 5 ", - autogenTargetName.c_str()); } } @@ -268,126 +436,137 @@ static void UicGetOpts(cmGeneratorTarget const* target, } static void UicSetupAutoTarget( - cmGeneratorTarget const* target, std::vector const& skipUic, + cmGeneratorTarget const* target, std::string const& qtMajorVersion, + std::string const& config, std::vector const& configs, + std::vector const& uicSkipList, std::map& configUicOptions) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - std::set skipped; - skipped.insert(skipUic.begin(), skipUic.end()); + AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList); - makefile->AddDefinition( - "_skip_uic", - cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); - - std::vector uiFilesWithOptions = - makefile->GetQtUiFilesWithOptions(); - - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::string _uic_opts; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - UicGetOpts(target, config, _uic_opts); - - if (!_uic_opts.empty()) { - _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); - makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); - } - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_uic_opts; - UicGetOpts(target, *li, config_uic_opts); - if (config_uic_opts != _uic_opts) { - configUicOptions[*li] = - cmOutputConverter::EscapeForCMake(config_uic_opts); - if (_uic_opts.empty()) { - _uic_opts = config_uic_opts; + // Uic search paths + { + std::vector uicSearchPaths; + cmSystemTools::ExpandListArgument( + GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS"), uicSearchPaths); + const std::string srcDir = makefile->GetCurrentSourceDirectory(); + for (std::vector::iterator it = uicSearchPaths.begin(); + it != uicSearchPaths.end(); ++it) { + *it = cmSystemTools::CollapseFullPath(*it, srcDir); + } + AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths); + } + // Uic target options + { + // Default settings + std::string uicOpts; + UicGetOpts(target, config, uicOpts); + AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts); + + // Configuration specific settings + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string configUicOpts; + UicGetOpts(target, *li, configUicOpts); + if (configUicOpts != uicOpts) { + configUicOptions[*li] = + cmOutputConverter::EscapeForCMake(configUicOpts); } } } - - std::string uiFileFiles; - std::string uiFileOptions; - const char* sep = ""; - - for (std::vector::const_iterator fileIt = - uiFilesWithOptions.begin(); - fileIt != uiFilesWithOptions.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - - if (!skipped.insert(absFile).second) { - continue; + // Uic files options + { + std::vector uiFileFiles; + std::vector uiFileOptions; + { + std::set skipped; + skipped.insert(uicSkipList.begin(), uicSkipList.end()); + + const std::vector uiFilesWithOptions = + makefile->GetQtUiFilesWithOptions(); + for (std::vector::const_iterator fileIt = + uiFilesWithOptions.begin(); + fileIt != uiFilesWithOptions.end(); ++fileIt) { + cmSourceFile* sf = *fileIt; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (skipped.insert(absFile).second) { + // The file wasn't skipped + uiFileFiles.push_back(absFile); + { + std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); + cmSystemTools::ReplaceString(opts, ";", + cmQtAutoGeneratorCommon::listSep); + uiFileOptions.push_back(opts); + } + } + } } - uiFileFiles += sep; - uiFileFiles += absFile; - uiFileOptions += sep; - std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); - uiFileOptions += opts; - sep = ";"; + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); } - makefile->AddDefinition( - "_qt_uic_options_files", - cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); - makefile->AddDefinition( - "_qt_uic_options_options", - cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); - if (!qt5Uic) { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + // Uic executable + { + std::string err; + const char* uicExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); + if (qt5Uic != CM_NULLPTR) { + uicExec = qt5Uic->ImportedGetLocation(""); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); + if (qt4Uic != CM_NULLPTR) { + uicExec = qt4Uic->ImportedGetLocation(""); + } else { + err = "Qt4::uic target not found " + target->GetName(); + } } else { - makefile->AddDefinition("_qt_uic_executable", - qt5Uic->ImportedGetLocation("")); + err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 "; + err += target->GetName(); } - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); - if (!qt4Uic) { - cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", + uicExec ? uicExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_uic_executable", - qt4Uic->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); } } static std::string RccGetExecutable(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { + std::string rccExec; cmLocalGenerator* lg = target->GetLocalGenerator(); - - std::string const& targetName = target->GetName(); if (qtMajorVersion == "5") { cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc"); - if (!qt5Rcc) { - cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt5Rcc != CM_NULLPTR) { + rccExec = qt5Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt5::rcc target not found ", + target->GetName().c_str()); } - return qt5Rcc->ImportedGetLocation(""); - } - if (qtMajorVersion == "4") { + } else if (qtMajorVersion == "4") { cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc"); - if (!qt4Rcc) { - cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt4Rcc != CM_NULLPTR) { + rccExec = qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt4::rcc target not found ", + target->GetName().c_str()); } - return qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error( + "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ", + target->GetName().c_str()); } - - cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); - return std::string(); + return rccExec; } static void RccMergeOptions(std::vector& opts, @@ -397,255 +576,104 @@ static void RccMergeOptions(std::vector& opts, static const char* valueOptions[] = { "name", "root", "compress", "threshold" }; std::vector extraOpts; - for (std::vector::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) { + for (std::vector::const_iterator fit = fileOpts.begin(); + fit != fileOpts.end(); ++fit) { std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *it); + std::find(opts.begin(), opts.end(), *fit); if (existingIt != opts.end()) { - const char* o = it->c_str(); - if (*o == '-') { - ++o; - } - if (isQt5 && *o == '-') { - ++o; + const char* optName = fit->c_str(); + if (*optName == '-') { + ++optName; + if (isQt5 && *optName == '-') { + ++optName; + } } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; + // Test if this is a value option and change the existing value + if ((optName != fit->c_str()) && + std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { + const std::vector::iterator existValueIt(existingIt + 1); + const std::vector::const_iterator fileValueIt(fit + 1); + if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) { + *existValueIt = *fileValueIt; + ++fit; + } } } else { - extraOpts.push_back(*it); + extraOpts.push_back(*fit); } } opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); } -/// @brief Reads the resource files list from from a .qrc file - Qt5 version -/// @return True if the .qrc file was successfully parsed -static bool RccListInputsQt5(cmSourceFile* sf, cmGeneratorTarget const* target, - std::vector& depends) -{ - const std::string rccCommand = RccGetExecutable(target, "5"); - if (rccCommand.empty()) { - cmSystemTools::Error("AUTOGEN: error: rcc executable not available\n"); - return false; - } - - bool hasDashDashList = false; - // Read rcc features - { - std::vector command; - command.push_back(rccCommand); - command.push_back("--help"); - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, - CM_NULLPTR, cmSystemTools::OUTPUT_NONE); - if (result && retVal == 0 && - rccStdOut.find("--list") != std::string::npos) { - hasDashDashList = true; - } - } - // Run rcc list command - std::vector command; - command.push_back(rccCommand); - command.push_back(hasDashDashList ? "--list" : "-list"); - - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - command.push_back(absFile); - - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal, - CM_NULLPTR, cmSystemTools::OUTPUT_NONE); - if (!result || retVal) { - std::ostringstream err; - err << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath() - << " failed:\n" - << rccStdOut << "\n" - << rccStdErr << std::endl; - cmSystemTools::Error(err.str().c_str()); - return false; - } - - // Parse rcc list output - { - std::istringstream ostr(rccStdOut); - std::string oline; - while (std::getline(ostr, oline)) { - oline = utilStripCR(oline); - if (!oline.empty()) { - depends.push_back(oline); - } - } - } - - { - std::istringstream estr(rccStdErr); - std::string eline; - while (std::getline(estr, eline)) { - eline = utilStripCR(eline); - if (cmHasLiteralPrefix(eline, "RCC: Error in")) { - static std::string searchString = "Cannot find file '"; - - std::string::size_type pos = eline.find(searchString); - if (pos == std::string::npos) { - std::ostringstream err; - err << "AUTOGEN: error: Rcc lists unparsable output " << eline - << std::endl; - cmSystemTools::Error(err.str().c_str()); - return false; - } - pos += searchString.length(); - std::string::size_type sz = eline.size() - pos - 1; - depends.push_back(eline.substr(pos, sz)); - } - } - } - - return true; -} - -/// @brief Reads the resource files list from from a .qrc file - Qt4 version -/// @return True if the .qrc file was successfully parsed -static bool RccListInputsQt4(cmSourceFile* sf, - std::vector& depends) -{ - // Read file into string - std::string qrcContents; - { - std::ostringstream stream; - stream << cmsys::ifstream(sf->GetFullPath().c_str()).rdbuf(); - qrcContents = stream.str(); - } - - cmsys::RegularExpression fileMatchRegex("(]*>)"); - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - - qrcEntry = qrcEntry.substr(tag.size()); - - if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { - qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; - } - - depends.push_back(qrcEntry); - } - return true; -} - -/// @brief Reads the resource files list from from a .qrc file -/// @return True if the rcc file was successfully parsed -static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf, - cmGeneratorTarget const* target, - std::vector& depends) -{ - if (qtMajorVersion == "5") { - return RccListInputsQt5(sf, target, depends); - } - return RccListInputsQt4(sf, depends); -} - static void RccSetupAutoTarget(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { - std::string _rcc_files; - const char* sepRccFiles = ""; cmMakefile* makefile = target->Target->GetMakefile(); - - std::vector srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - - std::string qrcInputs; - const char* qrcInputsSep = ""; - - std::string rccFileFiles; - std::string rccFileOptions; - const char* optionSep = ""; - const bool qtMajorVersion5 = (qtMajorVersion == "5"); - - std::vector rccOptions; + const std::string rccCommand = RccGetExecutable(target, qtMajorVersion); + std::vector _rcc_files; + std::vector _rcc_inputs; + std::vector rccFileFiles; + std::vector rccFileOptions; + std::vector rccOptionsTarget; if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) { - cmSystemTools::ExpandListArgument(opts, rccOptions); + cmSystemTools::ExpandListArgument(opts, rccOptionsTarget); } + std::vector srcFiles; + target->GetConfigCommonSourceFiles(srcFiles); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - std::string ext = sf->GetExtension(); - if (ext == "qrc") { - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - const bool skip = - cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || - cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - - if (!skip) { - _rcc_files += sepRccFiles; - _rcc_files += absFile; - sepRccFiles = ";"; - + if ((sf->GetExtension() == "qrc") && + !PropertyEnabled(sf, "SKIP_AUTOGEN") && + !PropertyEnabled(sf, "SKIP_AUTORCC")) { + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + // qrc file + _rcc_files.push_back(absFile); + // qrc file entries + { + std::string entriesList = "{"; + // Read input file list only for non generated .qrc files. + if (!PropertyEnabled(sf, "GENERATED")) { + std::string error; + std::vector files; + if (cmQtAutoGeneratorCommon::RccListInputs( + qtMajorVersion, rccCommand, absFile, files, &error)) { + entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep); + } else { + cmSystemTools::Error(error.c_str()); + } + } + entriesList += "}"; + _rcc_inputs.push_back(entriesList); + } + // rcc options for this qrc file + { + // Merged target and file options + std::vector rccOptions(rccOptionsTarget); if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { std::vector optsVec; cmSystemTools::ExpandListArgument(prop, optsVec); RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); } - + // Only store non empty options lists if (!rccOptions.empty()) { - rccFileFiles += optionSep; - rccFileFiles += absFile; - rccFileOptions += optionSep; - } - const char* listSep = ""; - for (std::vector::const_iterator it = rccOptions.begin(); - it != rccOptions.end(); ++it) { - rccFileOptions += listSep; - rccFileOptions += *it; - listSep = "@list_sep@"; + rccFileFiles.push_back(absFile); + rccFileOptions.push_back( + cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep)); } - optionSep = ";"; - - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - std::vector depends; - if (RccListInputs(qtMajorVersion, sf, target, depends)) { - entriesList = cmJoin(depends, "@list_sep@"); - } else { - return; - } - } - qrcInputs += qrcInputsSep; - qrcInputs += entriesList; - qrcInputsSep = ";"; } } } - makefile->AddDefinition( - "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); - makefile->AddDefinition( - "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); - makefile->AddDefinition( - "_rcc_options_files", - cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); - makefile->AddDefinition( - "_rcc_options_options", - cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); - makefile->AddDefinition("_qt_rcc_executable", - RccGetExecutable(target, qtMajorVersion).c_str()); + + AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand); + AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files); + AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs); + AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); + AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); } void cmQtAutoGeneratorInitializer::InitializeAutogenSources( @@ -653,11 +681,24 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenSources( { if (target->GetPropertyAsBool("AUTOMOC")) { cmMakefile* makefile = target->Target->GetMakefile(); - const std::string mocCppFile = - GetAutogenTargetBuildDir(target) + "moc_compilation.cpp"; - cmSourceFile* gf = makefile->GetOrCreateSource(mocCppFile, true); - gf->SetProperty("SKIP_AUTOGEN", "On"); - target->AddSource(mocCppFile); + const std::vector suffixes = + GetConfigurationSuffixes(makefile); + // Get build directory + const std::string autogenBuildDir = GetAutogenTargetBuildDir(target); + // Register all compilation files as generated + for (std::vector::const_iterator it = suffixes.begin(); + it != suffixes.end(); ++it) { + std::string mcFile = autogenBuildDir + "/mocs_compilation"; + mcFile += *it; + mcFile += ".cpp"; + AddGeneratedSource(makefile, mcFile, cmQtAutoGeneratorCommon::MOC); + } + // Mocs compilation file + if (IsMultiConfig(target->GetGlobalGenerator())) { + target->AddSource(autogenBuildDir + "/mocs_compilation_$.cpp"); + } else { + target->AddSource(autogenBuildDir + "/mocs_compilation.cpp"); + } } } @@ -667,45 +708,33 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( cmMakefile* makefile = target->Target->GetMakefile(); // Create a custom target for running generators at buildtime + const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); + const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); + const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); + const bool multiConfig = IsMultiConfig(target->GetGlobalGenerator()); const std::string autogenTargetName = GetAutogenTargetName(target); const std::string autogenBuildDir = GetAutogenTargetBuildDir(target); const std::string workingDirectory = cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory()); const std::string qtMajorVersion = GetQtMajorVersion(target); - std::vector autogenOutputFiles; - - // Remove old settings on cleanup - { - std::string fname = GetAutogenTargetFilesDir(target); - fname += "/AutogenOldSettings.cmake"; - makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fname.c_str(), - false); - } + const std::string rccCommand = RccGetExecutable(target, qtMajorVersion); + const std::vector suffixes = GetConfigurationSuffixes(makefile); + std::vector autogenDepends; + std::vector autogenProvides; - // Create autogen target build directory and add it to the clean files - cmSystemTools::MakeDirectory(autogenBuildDir); + // Remove build directories on cleanup makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", autogenBuildDir.c_str(), false); - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC")) { - // Create autogen target includes directory and - // add it to the origin target INCLUDE_DIRECTORIES - const std::string incsDir = autogenBuildDir + "include"; - cmSystemTools::MakeDirectory(incsDir); - target->AddIncludeDirectory(incsDir, true); - } - - if (target->GetPropertyAsBool("AUTOMOC")) { - // Register moc compilation file as generated - autogenOutputFiles.push_back(autogenBuildDir + "moc_compilation.cpp"); - } - - // Initialize autogen target dependencies - std::vector depends; - if (const char* autogenDepends = - target->GetProperty("AUTOGEN_TARGET_DEPENDS")) { - cmSystemTools::ExpandListArgument(autogenDepends, depends); + // Remove old settings on cleanup + { + std::string base = GetAutogenTargetFilesDir(target); + for (std::vector::const_iterator it = suffixes.begin(); + it != suffixes.end(); ++it) { + std::string fname = base + "/AutogenOldSettings" + *it + ".cmake"; + makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fname.c_str(), + false); + } } // Compose command lines @@ -724,13 +753,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( std::string autogenComment; { std::vector toolNames; - if (target->GetPropertyAsBool("AUTOMOC")) { + if (mocEnabled) { toolNames.push_back("MOC"); } - if (target->GetPropertyAsBool("AUTOUIC")) { + if (uicEnabled) { toolNames.push_back("UIC"); } - if (target->GetPropertyAsBool("AUTORCC")) { + if (rccEnabled) { toolNames.push_back("RCC"); } @@ -746,89 +775,162 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( autogenComment = "Automatic " + tools + " for target " + target->GetName(); } + // Add moc compilation to generated files list + if (mocEnabled) { + for (std::vector::const_iterator it = suffixes.begin(); + it != suffixes.end(); ++it) { + std::string mcFile = autogenBuildDir + "/mocs_compilation"; + mcFile += *it; + mcFile += ".cpp"; + autogenProvides.push_back(mcFile); + } + } + + // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES + if (mocEnabled || uicEnabled) { + if (multiConfig) { + target->AddIncludeDirectory(autogenBuildDir + "/include_$", + true); + + } else { + target->AddIncludeDirectory(autogenBuildDir + "/include", true); + } + } + #if defined(_WIN32) && !defined(__CYGWIN__) bool usePRE_BUILD = false; cmGlobalGenerator* gg = lg->GetGlobalGenerator(); if (gg->GetName().find("Visual Studio") != std::string::npos) { - cmGlobalVisualStudioGenerator* vsgg = - static_cast(gg); - // Under VS >= 7 use a PRE_BUILD event instead of a separate target to + // Under VS use a PRE_BUILD event instead of a separate target to // reduce the number of targets loaded into the IDE. // This also works around a VS 11 bug that may skip updating the target: // https://connect.microsoft.com/VisualStudio/feedback/details/769495 - usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7; - if (usePRE_BUILD) { - // If the autogen target depends on an other target - // don't use PRE_BUILD - for (std::vector::iterator it = depends.begin(); - it != depends.end(); ++it) { - if (!makefile->FindTargetToUse(it->c_str())) { - usePRE_BUILD = false; - break; - } - } - } + usePRE_BUILD = true; } #endif - if (target->GetPropertyAsBool("AUTORCC")) { + // Initialize autogen target dependencies + if (const char* deps = target->GetProperty("AUTOGEN_TARGET_DEPENDS")) { + cmSystemTools::ExpandListArgument(deps, autogenDepends); + } + // Add link library targets to the autogen dependencies + { + const cmTarget::LinkLibraryVectorType& libVec = + target->Target->GetOriginalLinkLibraries(); + for (cmTarget::LinkLibraryVectorType::const_iterator it = libVec.begin(); + it != libVec.end(); ++it) { + const std::string& libName = it->first; + if (makefile->FindTargetToUse(libName) != CM_NULLPTR) { + autogenDepends.push_back(libName); + } + } + } + { cmFilePathChecksum fpathCheckSum(makefile); + // Iterate over all source files std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - if (sf->GetExtension() == "qrc" && - !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) && - !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) { - { + if (!PropertyEnabled(sf, "SKIP_AUTOGEN")) { + std::string const& ext = sf->GetExtension(); + // Add generated file that will be scanned by moc or uic to + // the dependencies + if (mocEnabled || uicEnabled) { + const cmSystemTools::FileFormat fileType = + cmSystemTools::GetFileFormat(ext.c_str()); + if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || + (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { + if (PropertyEnabled(sf, "GENERATED")) { + if ((mocEnabled && !PropertyEnabled(sf, "SKIP_AUTOMOC")) || + (uicEnabled && !PropertyEnabled(sf, "SKIP_AUTOUIC"))) { + autogenDepends.push_back( + cmsys::SystemTools::GetRealPath(sf->GetFullPath())); +#if defined(_WIN32) && !defined(__CYGWIN__) + // Cannot use PRE_BUILD with generated files + usePRE_BUILD = false; +#endif + } + } + } + } + // Process rcc enabled files + if (rccEnabled && (ext == "qrc") && + !PropertyEnabled(sf, "SKIP_AUTORCC")) { const std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - // Run cmake again when .qrc file changes - makefile->AddCMakeDependFile(absFile); - - std::string rccOutputFile = autogenBuildDir; - rccOutputFile += fpathCheckSum.getPart(absFile); - rccOutputFile += "/qrc_"; - rccOutputFile += - cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile); - rccOutputFile += ".cpp"; - - // Add rcc output file to origin target sources - cmSourceFile* gf = makefile->GetOrCreateSource(rccOutputFile, true); - gf->SetProperty("SKIP_AUTOGEN", "On"); - target->AddSource(rccOutputFile); - // Register rcc output file as generated - autogenOutputFiles.push_back(rccOutputFile); - } - if (lg->GetGlobalGenerator()->GetName() == "Ninja" -#if defined(_WIN32) && !defined(__CYGWIN__) - || usePRE_BUILD -#endif - ) { - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - RccListInputs(qtMajorVersion, sf, target, depends); + // Compose rcc output file name + { + std::string rccOutBase = autogenBuildDir + "/"; + rccOutBase += fpathCheckSum.getPart(absFile); + rccOutBase += "/qrc_"; + rccOutBase += + cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile); + + // Register rcc ouput file as generated + for (std::vector::const_iterator it = + suffixes.begin(); + it != suffixes.end(); ++it) { + std::string rccOutCfg = rccOutBase; + rccOutCfg += *it; + rccOutCfg += ".cpp"; + AddGeneratedSource(makefile, rccOutCfg, + cmQtAutoGeneratorCommon::RCC); + autogenProvides.push_back(rccOutCfg); + } + // Add rcc output file to origin target sources + if (multiConfig) { + target->AddSource(rccOutBase + "_$.cpp"); + } else { + target->AddSource(rccOutBase + ".cpp"); + } + } + + if (PropertyEnabled(sf, "GENERATED")) { + // Add generated qrc file to the dependencies + autogenDepends.push_back(absFile); + } else { + // Run cmake again when .qrc file changes + makefile->AddCMakeDependFile(absFile); + + // Add the qrc input files to the dependencies + std::string error; + if (!cmQtAutoGeneratorCommon::RccListInputs( + qtMajorVersion, rccCommand, absFile, autogenDepends, + &error)) { + cmSystemTools::Error(error.c_str()); + } + } #if defined(_WIN32) && !defined(__CYGWIN__) - // Cannot use PRE_BUILD because the resource files themselves - // may not be sources within the target so VS may not know the - // target needs to re-build at all. - usePRE_BUILD = false; + // Cannot use PRE_BUILD because the resource files themselves + // may not be sources within the target so VS may not know the + // target needs to re-build at all. + usePRE_BUILD = false; #endif - } } } } } #if defined(_WIN32) && !defined(__CYGWIN__) + if (usePRE_BUILD) { + // If the autogen target depends on an other target don't use PRE_BUILD + for (std::vector::iterator it = autogenDepends.begin(); + it != autogenDepends.end(); ++it) { + if (makefile->FindTargetToUse(*it) != CM_NULLPTR) { + usePRE_BUILD = false; + break; + } + } + } if (usePRE_BUILD) { // Add the pre-build command directly to bypass the OBJECT_LIBRARY // rejection in cmMakefile::AddCustomCommandToTarget because we know // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. std::vector no_output; - std::vector no_byproducts; - cmCustomCommand cc(makefile, no_output, no_byproducts, depends, + cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends, commandLines, autogenComment.c_str(), workingDirectory.c_str()); cc.SetEscapeOldStyle(false); @@ -839,7 +941,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( { cmTarget* autogenTarget = makefile->AddUtilityCommand( autogenTargetName, true, workingDirectory.c_str(), - /*byproducts=*/autogenOutputFiles, depends, commandLines, false, + /*byproducts=*/autogenProvides, autogenDepends, commandLines, false, autogenComment.c_str()); cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg); @@ -872,61 +974,72 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmMakefile::ScopePushPop varScope(makefile); static_cast(varScope); - // create a custom target for running generators at buildtime: - const std::string autogenTargetName = GetAutogenTargetName(target); - const std::string qtMajorVersion = GetQtMajorVersion(target); + // Get configurations + std::string config; + const std::vector configs(GetConfigurations(makefile, &config)); - makefile->AddDefinition( - "_moc_target_name", - cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); - makefile->AddDefinition( - "_origin_target_name", - cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); - makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str()); - - std::vector mocUicSources; - std::vector mocUicHeaders; - std::vector skipMoc; - std::vector skipUic; + // Configurations settings buffers + std::map configSuffix; std::map configMocIncludes; std::map configMocDefines; std::map configUicOptions; - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC") || - target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); + // Configuration suffix + if (IsMultiConfig(target->GetGlobalGenerator())) { + for (std::vector::const_iterator it = configs.begin(); + it != configs.end(); ++it) { + configSuffix[*it] = "_" + *it; + } } - makefile->AddDefinition( - "_moc_uic_sources", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); - makefile->AddDefinition( - "_moc_uic_headers", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); - if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes, - configMocDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) { - UicSetupAutoTarget(target, skipUic, configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) { - RccSetupAutoTarget(target, qtMajorVersion); - } + // Basic setup + { + const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC"); + const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC"); + const bool rccEnabled = target->GetPropertyAsBool("AUTORCC"); + const std::string autogenTargetName = GetAutogenTargetName(target); + const std::string qtMajorVersion = GetQtMajorVersion(target); + + std::vector sources; + std::vector headers; + + if (mocEnabled || uicEnabled || rccEnabled) { + std::vector mocSkipList; + std::vector uicSkipList; + AcquireScanFiles(target, sources, headers, mocSkipList, uicSkipList); + if (mocEnabled) { + MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, config, + configs, mocSkipList, configMocIncludes, + configMocDefines); + } + if (uicEnabled) { + UicSetupAutoTarget(target, qtMajorVersion, config, configs, + uicSkipList, configUicOptions); + } + if (rccEnabled) { + RccSetupAutoTarget(target, qtMajorVersion); + } + } - // Generate config file - std::string inputFile = cmSystemTools::GetCMakeRoot(); - inputFile += "/Modules/AutogenInfo.cmake.in"; - std::string outputFile = GetAutogenTargetFilesDir(target); - outputFile += "/AutogenInfo.cmake"; + AddDefinitionEscaped(makefile, "_autogen_build_dir", + GetAutogenTargetBuildDir(target)); + AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); + AddDefinitionEscaped(makefile, "_sources", sources); + AddDefinitionEscaped(makefile, "_headers", headers); + } - makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, - false); + // Generate info file + std::string infoFile = GetAutogenTargetFilesDir(target); + infoFile += "/AutogenInfo.cmake"; + { + std::string inf = cmSystemTools::GetCMakeRoot(); + inf += "/Modules/AutogenInfo.cmake.in"; + makefile->ConfigureFile(inf.c_str(), infoFile.c_str(), false, true, false); + } - // Append custom definitions to config file - if (!configMocDefines.empty() || !configMocIncludes.empty() || - !configUicOptions.empty()) { + // Append custom definitions to info file on demand + if (!configSuffix.empty() || !configMocDefines.empty() || + !configMocIncludes.empty() || !configUicOptions.empty()) { // Ensure we have write permission in case .in was read-only. mode_t perm = 0; @@ -935,45 +1048,49 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( #else mode_t mode_write = S_IWUSR; #endif - cmSystemTools::GetPermissions(outputFile, perm); + cmSystemTools::GetPermissions(infoFile, perm); if (!(perm & mode_write)) { - cmSystemTools::SetPermissions(outputFile, perm | mode_write); + cmSystemTools::SetPermissions(infoFile, perm | mode_write); } - cmsys::ofstream infoFile(outputFile.c_str(), std::ios::app); - if (!infoFile) { - std::string error = "Internal CMake error when trying to open file: "; - error += outputFile; - error += " for writing."; - cmSystemTools::Error(error.c_str()); - return; - } - if (!configMocDefines.empty()) { + // Open and write file + cmsys::ofstream ofs(infoFile.c_str(), std::ios::app); + if (ofs) { + ofs << "# Configuration specific options\n"; + for (std::map::iterator + it = configSuffix.begin(), + end = configSuffix.end(); + it != end; ++it) { + ofs << "set(AM_CONFIG_SUFFIX_" << it->first << " " << it->second + << ")\n"; + } for (std::map::iterator it = configMocDefines.begin(), end = configMocDefines.end(); it != end; ++it) { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " - << it->second << ")\n"; + ofs << "set(AM_MOC_DEFINITIONS_" << it->first << " " << it->second + << ")\n"; } - } - if (!configMocIncludes.empty()) { for (std::map::iterator it = configMocIncludes.begin(), end = configMocIncludes.end(); it != end; ++it) { - infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second - << ")\n"; + ofs << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second + << ")\n"; } - } - if (!configUicOptions.empty()) { for (std::map::iterator it = configUicOptions.begin(), end = configUicOptions.end(); it != end; ++it) { - infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " - << it->second << ")\n"; + ofs << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " << it->second + << ")\n"; } + } else { + // File open error + std::string error = "Internal CMake error when trying to open file: "; + error += cmQtAutoGeneratorCommon::Quoted(infoFile); + error += " for writing."; + cmSystemTools::Error(error.c_str()); } } } diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h index 26f2c8ee7..ca806f5a9 100644 --- a/Source/cmQtAutoGeneratorInitializer.h +++ b/Source/cmQtAutoGeneratorInitializer.h @@ -3,7 +3,7 @@ #ifndef cmQtAutoGeneratorInitializer_h #define cmQtAutoGeneratorInitializer_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep class cmGeneratorTarget; class cmLocalGenerator; diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 1d6972b8e..042d1117a 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1,19 +1,22 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenerators.h" +#include "cmQtAutoGeneratorCommon.h" +#include "cmConfigure.h" +#include "cmsys/FStream.hxx" +#include "cmsys/Terminal.h" #include #include -#include -#include -#include -#include +#include #include #include #include #include #include "cmAlgorithms.h" +#include "cmCryptoHash.h" +#include "cmFilePathChecksum.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" @@ -29,70 +32,104 @@ // -- Static variables -static const char* MocOldSettingsKey = "AM_MOC_OLD_SETTINGS"; -static const char* UicOldSettingsKey = "AM_UIC_OLD_SETTINGS"; -static const char* RccOldSettingsKey = "AM_RCC_OLD_SETTINGS"; +static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH"; +static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH"; +static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH"; // -- Static functions -static std::string GetConfigDefinition(cmMakefile* makefile, - const std::string& key, - const std::string& config) +inline static std::string Quoted(const std::string& text) { - std::string keyConf = key; - if (!config.empty()) { - keyConf += "_"; - keyConf += config; - } - const char* valueConf = makefile->GetDefinition(keyConf); - if (valueConf != CM_NULLPTR) { - return valueConf; + return cmQtAutoGeneratorCommon::Quoted(text); +} + +static std::string QuotedCommand(const std::vector& command) +{ + std::string res; + for (std::vector::const_iterator cit = command.begin(); + cit != command.end(); ++cit) { + if (!res.empty()) { + res.push_back(' '); + } + const std::string cesc = Quoted(*cit); + if (cit->empty() || (cesc.size() > (cit->size() + 2)) || + (cesc.find(' ') != std::string::npos)) { + res += cesc; + } else { + res += *cit; + } } - return makefile->GetSafeDefinition(key); + return res; } -static std::string OldSettingsFile(const std::string& targetDirectory) +static void InfoGet(cmMakefile* makefile, const char* key, std::string& value) { - std::string filename(cmSystemTools::CollapseFullPath(targetDirectory)); - cmSystemTools::ConvertToUnixSlashes(filename); - filename += "/AutogenOldSettings.cmake"; - return filename; + value = makefile->GetSafeDefinition(key); } -static std::string FindMatchingHeader( - const std::string& absPath, const std::string& mocSubDir, - const std::string& basename, - const std::vector& headerExtensions) +static void InfoGet(cmMakefile* makefile, const char* key, bool& value) { - std::string header; - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - std::string sourceFilePath = absPath + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } - // Try subdirectory instead - if (!mocSubDir.empty()) { - sourceFilePath = mocSubDir + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } + value = makefile->IsOn(key); +} + +static void InfoGet(cmMakefile* makefile, const char* key, + std::vector& list) +{ + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); +} + +static void InfoGetConfig(cmMakefile* makefile, const char* key, + const std::string& config, std::string& value) +{ + const char* valueConf = CM_NULLPTR; + { + std::string keyConf = key; + if (!config.empty()) { + keyConf += "_"; + keyConf += config; } + valueConf = makefile->GetDefinition(keyConf); + } + if (valueConf == CM_NULLPTR) { + valueConf = makefile->GetSafeDefinition(key); } + value = valueConf; +} - return header; +static void InfoGetConfig(cmMakefile* makefile, const char* key, + const std::string& config, + std::vector& list) +{ + std::string value; + InfoGetConfig(makefile, key, config, value); + cmSystemTools::ExpandListArgument(value, list); } -static std::string ExtractSubDir(const std::string& absPath, - const std::string& currentMoc) +inline static bool SettingsMatch(cmMakefile* makefile, const char* key, + const std::string& value) { - std::string subDir; - if (currentMoc.find_first_of('/') != std::string::npos) { - subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/'; + return (value == makefile->GetSafeDefinition(key)); +} + +static void SettingAppend(std::string& str, const char* key, + const std::string& value) +{ + if (!value.empty()) { + str += "set("; + str += key; + str += " "; + str += cmOutputConverter::EscapeForCMake(value); + str += ")\n"; } - return subDir; +} + +static std::string SubDirPrefix(const std::string& fileName) +{ + std::string res(cmsys::SystemTools::GetFilenamePath(fileName)); + if (!res.empty()) { + res += '/'; + } + return res; } static bool FileNameIsUnique(const std::string& filePath, @@ -112,13 +149,19 @@ static bool FileNameIsUnique(const std::string& filePath, return true; } -static std::string ReadAll(const std::string& filename) +static bool ReadAll(std::string& content, const std::string& filename) { - cmsys::ifstream file(filename.c_str()); - std::ostringstream stream; - stream << file.rdbuf(); - file.close(); - return stream.str(); + bool success = false; + { + cmsys::ifstream ifs(filename.c_str()); + if (ifs) { + std::ostringstream osst; + osst << ifs.rdbuf(); + content = osst.str(); + success = true; + } + } + return success; } /** @@ -140,13 +183,19 @@ static bool ListContains(const std::vector& list, return (std::find(list.begin(), list.end(), entry) != list.end()); } -static std::string JoinOptions(const std::map& opts) +static std::string JoinOptionsList(const std::vector& opts) +{ + return cmOutputConverter::EscapeForCMake(cmJoin(opts, ";")); +} + +static std::string JoinOptionsMap( + const std::map& opts) { std::string result; for (std::map::const_iterator it = opts.begin(); it != opts.end(); ++it) { if (it != opts.begin()) { - result += "%%%"; + result += cmQtAutoGeneratorCommon::listSep; } result += it->first; result += "==="; @@ -211,12 +260,13 @@ static void UicMergeOptions(std::vector& opts, cmQtAutoGenerators::cmQtAutoGenerators() : Verbose(cmsys::SystemTools::HasEnv("VERBOSE")) , ColorOutput(true) - , RunMocFailed(false) - , RunUicFailed(false) - , RunRccFailed(false) - , GenerateMocAll(false) - , GenerateUicAll(false) - , GenerateRccAll(false) + , MocSettingsChanged(false) + , MocPredefsChanged(false) + , MocRunFailed(false) + , UicSettingsChanged(false) + , UicRunFailed(false) + , RccSettingsChanged(false) + , RccRunFailed(false) { std::string colorEnv; @@ -229,20 +279,24 @@ cmQtAutoGenerators::cmQtAutoGenerators() } } + // Moc macro filters + this->MocMacroFilters[0].first = "Q_OBJECT"; + this->MocMacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); + this->MocMacroFilters[1].first = "Q_GADGET"; + this->MocMacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); + // Precompile regular expressions - this->RegExpQObject.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); - this->RegExpQGadget.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); - this->RegExpMocInclude.compile( + this->MocRegExpInclude.compile( "[\n][ \t]*#[ \t]*include[ \t]+" "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); - this->RegExpUicInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+" + this->UicRegExpInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+" "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); } bool cmQtAutoGenerators::Run(const std::string& targetDirectory, const std::string& config) { - cmake cm; + cmake cm(cmake::RoleScript); cm.SetHomeOutputDirectory(targetDirectory); cm.SetHomeDirectory(targetDirectory); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -255,23 +309,46 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, CM_AUTO_PTR mf(new cmMakefile(&gg, snapshot)); gg.SetCurrentMakefile(mf.get()); - if (!this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) { - return false; - } - // Read old settings - this->OldSettingsReadFile(mf.get(), targetDirectory); - // Init and run - this->Init(); - if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { - if (!this->RunAutogen(mf.get())) { - return false; + bool success = false; + if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) { + // Read old settings + this->SettingsFileRead(mf.get()); + // Init and run + this->Init(mf.get()); + if (this->RunAutogen()) { + // Write current settings + if (this->SettingsFileWrite()) { + success = true; + } } } - // Write latest settings - if (!this->OldSettingsWriteFile(targetDirectory)) { - return false; + return success; +} + +bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key, + const std::string& regExp) +{ + bool success = false; + if (!key.empty()) { + if (!regExp.empty()) { + MocDependFilter filter; + filter.key = key; + if (filter.regExp.compile(regExp)) { + this->MocDependFilters.push_back(filter); + success = true; + } else { + this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling " + "regular expression failed.\nKey: " + + Quoted(key) + "\nExp.: " + Quoted(regExp)); + } + } else { + this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular " + "expression is empty"); + } + } else { + this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty"); } - return true; + return success; } bool cmQtAutoGenerators::ReadAutogenInfoFile( @@ -283,395 +360,420 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( filename += "/AutogenInfo.cmake"; if (!makefile->ReadListFile(filename.c_str())) { - std::ostringstream err; - err << "AutoGen: error processing file: " << filename << std::endl; - this->LogError(err.str()); + this->LogError("AutoGen: Error processing file: " + filename); return false; } - // - Target names - this->OriginTargetName = - makefile->GetSafeDefinition("AM_ORIGIN_TARGET_NAME"); - this->AutogenTargetName = makefile->GetSafeDefinition("AM_TARGET_NAME"); - - // - Directories - this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR"); - this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR"); - this->CurrentSourceDir = - makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR"); - this->CurrentBinaryDir = - makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR"); + // - Old settings file + { + this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory); + cmSystemTools::ConvertToUnixSlashes(this->SettingsFile); + this->SettingsFile += "/AutogenOldSettings"; + this->SettingsFile += this->ConfigSuffix; + this->SettingsFile += ".cmake"; + } + + // -- Meta + InfoGetConfig(makefile, "AM_CONFIG_SUFFIX", config, this->ConfigSuffix); + + // - Files and directories + InfoGet(makefile, "AM_CMAKE_SOURCE_DIR", this->ProjectSourceDir); + InfoGet(makefile, "AM_CMAKE_BINARY_DIR", this->ProjectBinaryDir); + InfoGet(makefile, "AM_CMAKE_CURRENT_SOURCE_DIR", this->CurrentSourceDir); + InfoGet(makefile, "AM_CMAKE_CURRENT_BINARY_DIR", this->CurrentBinaryDir); + InfoGet(makefile, "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", + this->IncludeProjectDirsBefore); + InfoGet(makefile, "AM_BUILD_DIR", this->AutogenBuildDir); + if (this->AutogenBuildDir.empty()) { + this->LogError("AutoGen: Error: Missing autogen build directory "); + return false; + } + InfoGet(makefile, "AM_SOURCES", this->Sources); + InfoGet(makefile, "AM_HEADERS", this->Headers); // - Qt environment - this->QtMajorVersion = makefile->GetSafeDefinition("AM_QT_VERSION_MAJOR"); - if (this->QtMajorVersion == "") { - this->QtMajorVersion = - makefile->GetSafeDefinition("AM_Qt5Core_VERSION_MAJOR"); + InfoGet(makefile, "AM_QT_VERSION_MAJOR", this->QtMajorVersion); + if (this->QtMajorVersion.empty()) { + InfoGet(makefile, "AM_Qt5Core_VERSION_MAJOR", this->QtMajorVersion); + } + InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable); + InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable); + InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable); + + InfoGet(makefile, "AM_MOC_PREDEFS_CMD", this->MocPredefsCmd); + // Check Qt version + if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) { + this->LogError("AutoGen: Error: Unsupported Qt version: " + + Quoted(this->QtMajorVersion)); + return false; } - this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE"); - this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE"); - this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE"); - - // - File Lists - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SOURCES"), - this->Sources); - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_HEADERS"), - this->Headers); // - Moc - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), - this->SkipMoc); - this->MocCompileDefinitionsStr = - GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config); - this->MocIncludesStr = - GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); - this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); - - // - Uic - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), - this->SkipUic); - cmSystemTools::ExpandListArgument( - GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), - this->UicTargetOptions); - { - std::vector uicFilesVec; - std::vector uicOptionsVec; - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES"), uicFilesVec); - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"), uicOptionsVec); - if (uicFilesVec.size() != uicOptionsVec.size()) { - std::ostringstream err; - err << "AutoGen: Error: Uic files/options lists size missmatch in: " - << filename << std::endl; - this->LogError(err.str()); - return false; + if (this->MocEnabled()) { + InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList); + InfoGetConfig(makefile, "AM_MOC_DEFINITIONS", config, + this->MocDefinitions); +#ifdef _WIN32 + { + const std::string win32("WIN32"); + if (!ListContains(this->MocDefinitions, win32)) { + this->MocDefinitions.push_back(win32); + } } - for (std::vector::iterator fileIt = uicFilesVec.begin(), - optionIt = uicOptionsVec.begin(); - fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); - this->UicOptions[*fileIt] = *optionIt; +#endif + InfoGetConfig(makefile, "AM_MOC_INCLUDES", config, this->MocIncludePaths); + InfoGet(makefile, "AM_MOC_OPTIONS", this->MocOptions); + InfoGet(makefile, "AM_MOC_RELAXED_MODE", this->MocRelaxedMode); + { + std::vector mocDependFilters; + InfoGet(makefile, "AM_MOC_DEPEND_FILTERS", mocDependFilters); + // Insert Q_PLUGIN_METADATA dependency filter + if (this->QtMajorVersion != "4") { + this->MocDependFilterPush("Q_PLUGIN_METADATA", + "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\(" + "[^\\)]*FILE[ \t]*\"([^\"]+)\""); + } + // Insert user defined dependency filters + if ((mocDependFilters.size() % 2) == 0) { + for (std::vector::const_iterator dit = + mocDependFilters.begin(); + dit != mocDependFilters.end(); dit += 2) { + if (!this->MocDependFilterPush(*dit, *(dit + 1))) { + return false; + } + } + } else { + this->LogError( + "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not " + "a multiple of 2 in:\n" + + Quoted(filename)); + return false; + } } } - // - Rcc - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_SOURCES"), this->RccSources); - { - std::vector rccFilesVec; - std::vector rccOptionsVec; - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES"), rccFilesVec); - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"), rccOptionsVec); - if (rccFilesVec.size() != rccOptionsVec.size()) { - std::ostringstream err; - err << "AutoGen: Error: RCC files/options lists size missmatch in: " - << filename << std::endl; - this->LogError(err.str()); - return false; - } - for (std::vector::iterator fileIt = rccFilesVec.begin(), - optionIt = rccOptionsVec.begin(); - fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); - this->RccOptions[*fileIt] = *optionIt; + // - Uic + if (this->UicEnabled()) { + InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList); + InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths); + InfoGetConfig(makefile, "AM_UIC_TARGET_OPTIONS", config, + this->UicTargetOptions); + { + std::vector uicFilesVec; + std::vector uicOptionsVec; + InfoGet(makefile, "AM_UIC_OPTIONS_FILES", uicFilesVec); + InfoGet(makefile, "AM_UIC_OPTIONS_OPTIONS", uicOptionsVec); + // Compare list sizes + if (uicFilesVec.size() == uicOptionsVec.size()) { + for (std::vector::iterator + fileIt = uicFilesVec.begin(), + optionIt = uicOptionsVec.begin(); + fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { + cmSystemTools::ReplaceString(*optionIt, + cmQtAutoGeneratorCommon::listSep, ";"); + this->UicOptions[*fileIt] = *optionIt; + } + } else { + this->LogError( + "AutoGen: Error: Uic files/options lists size missmatch in:\n" + + Quoted(filename)); + return false; + } } } - { - std::vector rccInputLists; - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_INPUTS"), rccInputLists); - - // qrc files in the end of the list may have been empty - if (rccInputLists.size() < this->RccSources.size()) { - rccInputLists.resize(this->RccSources.size()); - } - if (this->RccSources.size() != rccInputLists.size()) { - std::ostringstream err; - err << "AutoGen: Error: RCC sources/inputs lists size missmatch in: " - << filename << std::endl; - this->LogError(err.str()); - return false; + + // - Rcc + if (this->RccEnabled()) { + InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources); + // File options + { + std::vector rccFilesVec; + std::vector rccOptionsVec; + InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec); + InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec); + if (rccFilesVec.size() == rccOptionsVec.size()) { + for (std::vector::iterator + fileIt = rccFilesVec.begin(), + optionIt = rccOptionsVec.begin(); + fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { + // Replace item separator + cmSystemTools::ReplaceString(*optionIt, + cmQtAutoGeneratorCommon::listSep, ";"); + this->RccOptions[*fileIt] = *optionIt; + } + } else { + this->LogError( + "AutoGen: Error: RCC files/options lists size missmatch in:\n" + + Quoted(filename)); + return false; + } } - for (std::vector::iterator fileIt = this->RccSources.begin(), - inputIt = rccInputLists.begin(); - fileIt != this->RccSources.end(); ++fileIt, ++inputIt) { - cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";"); - std::vector rccInputFiles; - cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); - this->RccInputs[*fileIt] = rccInputFiles; + // File lists + { + std::vector rccInputLists; + InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists); + if (this->RccSources.size() == rccInputLists.size()) { + for (std::vector::iterator + fileIt = this->RccSources.begin(), + inputIt = rccInputLists.begin(); + fileIt != this->RccSources.end(); ++fileIt, ++inputIt) { + // Remove braces + *inputIt = inputIt->substr(1, inputIt->size() - 2); + // Replace item separator + cmSystemTools::ReplaceString(*inputIt, + cmQtAutoGeneratorCommon::listSep, ";"); + std::vector rccInputFiles; + cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); + this->RccInputs[*fileIt] = rccInputFiles; + } + } else { + this->LogError( + "AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" + + Quoted(filename)); + return false; + } } } - // - Flags - this->IncludeProjectDirsBefore = - makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"); - this->MocRelaxedMode = makefile->IsOn("AM_MOC_RELAXED_MODE"); - return true; } -std::string cmQtAutoGenerators::MocSettingsStringCompose() -{ - std::string res; - res += this->MocCompileDefinitionsStr; - res += " ~~~ "; - res += this->MocIncludesStr; - res += " ~~~ "; - res += this->MocOptionsStr; - res += " ~~~ "; - res += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; - res += " ~~~ "; - return res; -} - -std::string cmQtAutoGenerators::UicSettingsStringCompose() -{ - std::string res; - res += cmJoin(this->UicTargetOptions, "@osep@"); - res += " ~~~ "; - res += JoinOptions(this->UicOptions); - res += " ~~~ "; - return res; -} - -std::string cmQtAutoGenerators::RccSettingsStringCompose() +void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) { - std::string res; - res += JoinOptions(this->RccOptions); - res += " ~~~ "; - return res; -} - -void cmQtAutoGenerators::OldSettingsReadFile( - cmMakefile* makefile, const std::string& targetDirectory) -{ - if (!this->MocExecutable.empty() || !this->UicExecutable.empty() || - !this->RccExecutable.empty()) { - // Compose current settings strings - this->MocSettingsString = this->MocSettingsStringCompose(); - this->UicSettingsString = this->UicSettingsStringCompose(); - this->RccSettingsString = this->RccSettingsStringCompose(); + // Compose current settings strings + { + cmCryptoHash crypt(cmCryptoHash::AlgoSHA256); + const std::string sep(" ~~~ "); + if (this->MocEnabled()) { + std::string str; + str += this->MocExecutable; + str += sep; + str += JoinOptionsList(this->MocDefinitions); + str += sep; + str += JoinOptionsList(this->MocIncludePaths); + str += sep; + str += JoinOptionsList(this->MocOptions); + str += sep; + str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; + str += sep; + str += JoinOptionsList(this->MocPredefsCmd); + str += sep; + this->SettingsStringMoc = crypt.HashString(str); + } + if (this->UicEnabled()) { + std::string str; + str += this->UicExecutable; + str += sep; + str += JoinOptionsList(this->UicTargetOptions); + str += sep; + str += JoinOptionsMap(this->UicOptions); + str += sep; + this->SettingsStringUic = crypt.HashString(str); + } + if (this->RccEnabled()) { + std::string str; + str += this->RccExecutable; + str += sep; + str += JoinOptionsMap(this->RccOptions); + str += sep; + this->SettingsStringRcc = crypt.HashString(str); + } + } - // Read old settings - const std::string filename = OldSettingsFile(targetDirectory); - if (makefile->ReadListFile(filename.c_str())) { - if (!this->MocExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(MocOldSettingsKey); - if (sol != this->MocSettingsString) { - this->GenerateMocAll = true; - } - } - if (!this->UicExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(UicOldSettingsKey); - if (sol != this->UicSettingsString) { - this->GenerateUicAll = true; - } - } - if (!this->RccExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(RccOldSettingsKey); - if (sol != this->RccSettingsString) { - this->GenerateRccAll = 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 (this->GenerateMocAll || this->GenerateUicAll || - this->GenerateRccAll) { - cmSystemTools::RemoveFile(filename); - } - } else { - // If the file could not be read re-generate everythiung. - this->GenerateMocAll = true; - this->GenerateUicAll = true; - this->GenerateRccAll = true; + // Read old settings + if (makefile->ReadListFile(this->SettingsFile.c_str())) { + if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) { + this->MocSettingsChanged = true; + } + if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) { + this->UicSettingsChanged = true; + } + if (!SettingsMatch(makefile, SettingsKeyRcc, this->SettingsStringRcc)) { + this->RccSettingsChanged = 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 (this->AnySettingsChanged()) { + cmSystemTools::RemoveFile(this->SettingsFile); } + } else { + // If the file could not be read re-generate everythiung. + this->MocSettingsChanged = true; + this->UicSettingsChanged = true; + this->RccSettingsChanged = true; } } -bool cmQtAutoGenerators::OldSettingsWriteFile( - const std::string& targetDirectory) +bool cmQtAutoGenerators::SettingsFileWrite() { bool success = true; // Only write if any setting changed - if (this->GenerateMocAll || this->GenerateUicAll || this->GenerateRccAll) { - const std::string filename = OldSettingsFile(targetDirectory); - cmsys::ofstream outfile; - outfile.open(filename.c_str(), std::ios::trunc); - if (outfile) { - if (!this->MocExecutable.empty()) { - outfile << "set(" << MocOldSettingsKey << " " - << cmOutputConverter::EscapeForCMake(this->MocSettingsString) - << ")\n"; - } - if (!this->UicExecutable.empty()) { - outfile << "set(" << UicOldSettingsKey << " " - << cmOutputConverter::EscapeForCMake(this->UicSettingsString) - << ")\n"; - } - if (!this->RccExecutable.empty()) { - outfile << "set(" << RccOldSettingsKey << " " - << cmOutputConverter::EscapeForCMake(this->RccSettingsString) - << ")\n"; - } - success = outfile.good(); - outfile.close(); - } else { + if (this->AnySettingsChanged()) { + if (this->Verbose) { + this->LogInfo("AutoGen: Writing settings file " + + Quoted(this->SettingsFile)); + } + // Compose settings file content + std::string settings; + SettingAppend(settings, SettingsKeyMoc, this->SettingsStringMoc); + SettingAppend(settings, SettingsKeyUic, this->SettingsStringUic); + SettingAppend(settings, SettingsKeyRcc, this->SettingsStringRcc); + // Write settings file + if (!this->FileWrite("AutoGen", this->SettingsFile, settings)) { + this->LogError("AutoGen: Error: Could not write old settings file " + + Quoted(this->SettingsFile)); + // Remove old settings file to trigger a full rebuild on the next run + cmSystemTools::RemoveFile(this->SettingsFile); success = false; - // Remove old settings file to trigger full rebuild on next run - cmSystemTools::RemoveFile(filename); - { - std::ostringstream err; - err << "AutoGen: Error: Writing old settings file failed: " << filename - << std::endl; - this->LogError(err.str()); - } } } return success; } -void cmQtAutoGenerators::Init() +void cmQtAutoGenerators::Init(cmMakefile* makefile) { - this->AutogenBuildSubDir = this->AutogenTargetName; - this->AutogenBuildSubDir += "/"; + // Mocs compilation file + this->MocCompFileRel = "mocs_compilation"; + this->MocCompFileRel += this->ConfigSuffix; + this->MocCompFileRel += ".cpp"; + this->MocCompFileAbs = cmSystemTools::CollapseCombinedPath( + this->AutogenBuildDir, this->MocCompFileRel); - this->OutMocCppFilenameRel = this->AutogenBuildSubDir; - this->OutMocCppFilenameRel += "moc_compilation.cpp"; + // Mocs include directory + this->AutogenIncludeDir = "include"; + this->AutogenIncludeDir += this->ConfigSuffix; + this->AutogenIncludeDir += "/"; - this->OutMocCppFilenameAbs = - this->CurrentBinaryDir + this->OutMocCppFilenameRel; + // Moc predefs file + if (!this->MocPredefsCmd.empty()) { + this->MocPredefsFileRel = "moc_predefs.h"; + this->MocPredefsFileAbs = cmSystemTools::CollapseCombinedPath( + this->AutogenBuildDir, this->MocPredefsFileRel); + } // Init file path checksum generator - fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir, + FPathChecksum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir, this->ProjectBinaryDir); - std::vector cdefList; - cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList); - for (std::vector::const_iterator it = cdefList.begin(); - it != cdefList.end(); ++it) { - this->MocDefinitions.push_back("-D" + (*it)); - } - - cmSystemTools::ExpandListArgument(this->MocOptionsStr, this->MocOptions); - - std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocIncludesStr, incPaths); - - std::set frameworkPaths; - for (std::vector::const_iterator it = incPaths.begin(); - it != incPaths.end(); ++it) { - const std::string& path = *it; - this->MocIncludes.push_back("-I" + path); - if (cmHasLiteralSuffix(path, ".framework/Headers")) { - // Go up twice to get to the framework root - std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( - pathComponents.begin(), pathComponents.end() - 2); - frameworkPaths.insert(frameworkPath); - } - } - - for (std::set::const_iterator it = frameworkPaths.begin(); - it != frameworkPaths.end(); ++it) { - this->MocIncludes.push_back("-F"); - this->MocIncludes.push_back(*it); - } + // Acquire header extensions + this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); + // Sort include directories on demand if (this->IncludeProjectDirsBefore) { - const std::string binDir = "-I" + this->ProjectBinaryDir; - const std::string srcDir = "-I" + this->ProjectSourceDir; - - std::list sortedMocIncludes; - std::list::iterator it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, binDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; + // Move strings to temporary list + std::list includes; + includes.insert(includes.end(), this->MocIncludePaths.begin(), + this->MocIncludePaths.end()); + this->MocIncludePaths.clear(); + this->MocIncludePaths.reserve(includes.size()); + // Append project directories only + { + const char* movePaths[2] = { this->ProjectBinaryDir.c_str(), + this->ProjectSourceDir.c_str() }; + for (const char* const* mpit = cmArrayBegin(movePaths); + mpit != cmArrayEnd(movePaths); ++mpit) { + std::list::iterator it = includes.begin(); + while (it != includes.end()) { + const std::string& path = *it; + if (cmsys::SystemTools::StringStartsWith(path, *mpit)) { + this->MocIncludePaths.push_back(path); + it = includes.erase(it); + } else { + ++it; + } + } } } - it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, srcDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; + // Append remaining directories + this->MocIncludePaths.insert(this->MocIncludePaths.end(), includes.begin(), + includes.end()); + } + // Compose moc includes list + { + std::set frameworkPaths; + for (std::vector::const_iterator it = + this->MocIncludePaths.begin(); + it != this->MocIncludePaths.end(); ++it) { + const std::string& path = *it; + this->MocIncludes.push_back("-I" + path); + // Extract framework path + if (cmHasLiteralSuffix(path, ".framework/Headers")) { + // Go up twice to get to the framework root + std::vector pathComponents; + cmsys::SystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmsys::SystemTools::JoinPath( + pathComponents.begin(), pathComponents.end() - 2); + frameworkPaths.insert(frameworkPath); } } - sortedMocIncludes.insert(sortedMocIncludes.end(), - this->MocIncludes.begin(), - this->MocIncludes.end()); - this->MocIncludes = sortedMocIncludes; + // Append framework includes + for (std::set::const_iterator it = frameworkPaths.begin(); + it != frameworkPaths.end(); ++it) { + this->MocIncludes.push_back("-F"); + this->MocIncludes.push_back(*it); + } } } -bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) +bool cmQtAutoGenerators::RunAutogen() { // the program goes through all .cpp files to see which moc files are // included. It is not really interesting how the moc file is named, but // what file the moc is created from. Once a moc is included the same moc - // may not be included in the moc_compilation.cpp file anymore. OTOH if - // there's a header containing Q_OBJECT where no corresponding moc file - // is included anywhere a moc_.cpp file is created and included in - // the moc_compilation.cpp file. + // may not be included in the mocs_compilation_$.cpp file anymore. + // OTOH if there's a header containing Q_OBJECT where no corresponding + // moc file is included anywhere a moc_.cpp file is created and + // included in the mocs_compilation_$.cpp file. // key = moc source filepath, value = moc output filepath - std::map includedMocs; - std::map notIncludedMocs; - std::map > includedUis; + std::map mocsIncluded; + std::map mocsNotIncluded; + std::map > mocDepends; + std::map > uisIncluded; // collects all headers which may need to be mocced - std::set headerFilesMoc; - std::set headerFilesUic; + std::set mocHeaderFiles; + std::set uicHeaderFiles; // Parse sources - { - const std::vector& headerExtensions = - makefile->GetCMakeInstance()->GetHeaderExtensions(); - - for (std::vector::const_iterator it = this->Sources.begin(); - it != this->Sources.end(); ++it) { - const std::string& absFilename = *it; - // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, headerExtensions, includedMocs, - includedUis, this->MocRelaxedMode)) { - return false; - } - // Find additional headers - this->SearchHeadersForSourceFile(absFilename, headerExtensions, - headerFilesMoc, headerFilesUic); + for (std::vector::const_iterator it = this->Sources.begin(); + it != this->Sources.end(); ++it) { + const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); + // Parse source file for MOC/UIC + if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends, + uisIncluded, this->MocRelaxedMode)) { + return false; } + // Find additional headers + this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles, + uicHeaderFiles); } // Parse headers for (std::vector::const_iterator it = this->Headers.begin(); it != this->Headers.end(); ++it) { - const std::string& headerName = *it; - if (!this->MocSkipTest(headerName)) { - headerFilesMoc.insert(headerName); + const std::string& headerName = cmsys::SystemTools::GetRealPath(*it); + if (!this->MocSkip(headerName)) { + mocHeaderFiles.insert(headerName); } - if (!this->UicSkipTest(headerName)) { - headerFilesUic.insert(headerName); + if (!this->UicSkip(headerName)) { + uicHeaderFiles.insert(headerName); } } - this->ParseHeaders(headerFilesMoc, headerFilesUic, includedMocs, - notIncludedMocs, includedUis); + if (!this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, + mocsNotIncluded, mocDepends, uisIncluded)) { + return false; + }; // Generate files - if (!this->MocGenerateAll(includedMocs, notIncludedMocs)) { + if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) { return false; } - if (!this->UicGenerateAll(includedUis)) { + if (!this->UicGenerateAll(uisIncluded)) { return false; } - if (!this->QrcGenerateAll()) { + if (!this->RccGenerateAll()) { return false; } @@ -682,35 +784,73 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) * @brief Tests if the C++ content requires moc processing * @return True if moc is required */ -bool cmQtAutoGenerators::MocRequired(const std::string& text, - std::string& macroName) +bool cmQtAutoGenerators::MocRequired(const std::string& contentText, + std::string* macroName) { - // Run a simple check before an expensive regular expression check - if (strstr(text.c_str(), "Q_OBJECT") != CM_NULLPTR) { - if (this->RegExpQObject.find(text)) { - macroName = "Q_OBJECT"; - return true; + for (unsigned int ii = 0; ii != cmArraySize(this->MocMacroFilters); ++ii) { + MocMacroFilter& filter = this->MocMacroFilters[ii]; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.first) != std::string::npos) { + if (filter.second.find(contentText)) { + // Return macro name on demand + if (macroName != CM_NULLPTR) { + *macroName = filter.first; + } + return true; + } } } - if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) { - if (this->RegExpQGadget.find(text)) { - macroName = "Q_GADGET"; - return true; + return false; +} + +void cmQtAutoGenerators::MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends) +{ + for (std::vector::iterator fit = + this->MocDependFilters.begin(); + fit != this->MocDependFilters.end(); ++fit) { + MocDependFilter& filter = *fit; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.key) != std::string::npos) { + // Run regular expression check loop + const std::string sourcePath = SubDirPrefix(absFilename); + const char* contentChars = contentText.c_str(); + while (filter.regExp.find(contentChars)) { + // Evaluate match + const std::string match = filter.regExp.match(1); + if (!match.empty()) { + // Find the dependency file + std::string incFile; + if (this->MocFindIncludedFile(incFile, sourcePath, match)) { + mocDepends[absFilename].insert(incFile); + if (this->Verbose) { + this->LogInfo("AutoMoc: Found dependency:\n " + + Quoted(absFilename) + "\n " + Quoted(incFile)); + } + } else { + this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) + + "\n" + "Could not find dependency file " + + Quoted(match)); + } + } + contentChars += filter.regExp.end(); + } } } - return false; } /** * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored */ -bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename) +bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) const { - // Test if moc scanning is enabled - if (!this->MocExecutable.empty()) { + if (this->MocEnabled()) { // Test if the file name is on the skip list - if (!ListContains(this->SkipMoc, absFilename)) { + if (!ListContains(this->MocSkipList, absFilename)) { return false; } } @@ -720,12 +860,11 @@ bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename) /** * @brief Tests if the file name is in the skip list */ -bool cmQtAutoGenerators::UicSkipTest(const std::string& absFilename) +bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const { - // Test if uic scanning is enabled - if (!this->UicExecutable.empty()) { + if (this->UicEnabled()) { // Test if the file name is on the skip list - if (!ListContains(this->SkipUic, absFilename)) { + if (!ListContains(this->UicSkipList, absFilename)) { return false; } } @@ -737,53 +876,50 @@ bool cmQtAutoGenerators::UicSkipTest(const std::string& absFilename) */ bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, - std::map& includedMocs, - std::map >& includedUis, bool relaxed) + std::map& mocsIncluded, + std::map >& mocDepends, + std::map >& uisIncluded, bool relaxed) { - bool success = true; - const std::string contentsString = ReadAll(absFilename); - if (contentsString.empty()) { - std::ostringstream err; - err << "AutoGen: Warning: " << absFilename << "\n" - << "The file is empty\n"; - this->LogWarning(err.str()); - } else { - // Parse source contents for MOC - if (success && !this->MocSkipTest(absFilename)) { - success = this->ParseContentForMoc( - absFilename, contentsString, headerExtensions, includedMocs, relaxed); - } - // Parse source contents for UIC - if (success && !this->UicSkipTest(absFilename)) { - this->ParseContentForUic(absFilename, contentsString, includedUis); + std::string contentText; + bool success = ReadAll(contentText, absFilename); + if (success) { + if (!contentText.empty()) { + // Parse source contents for MOC + if (success && !this->MocSkip(absFilename)) { + success = this->MocParseSourceContent( + absFilename, contentText, mocsIncluded, mocDepends, relaxed); + } + // Parse source contents for UIC + if (success && !this->UicSkip(absFilename)) { + this->UicParseContent(absFilename, contentText, uisIncluded); + } + } else { + std::ostringstream ost; + ost << "AutoGen: Warning: The file is empty:\n" + << Quoted(absFilename) << "\n"; + this->LogWarning(ost.str()); } + } else { + std::ostringstream ost; + ost << "AutoGen: Error: Could not read file:\n" << Quoted(absFilename); + this->LogError(ost.str()); } return success; } -void cmQtAutoGenerators::ParseContentForUic( - const std::string& absFilename, const std::string& contentsString, - std::map >& includedUis) +void cmQtAutoGenerators::UicParseContent( + const std::string& absFilename, const std::string& contentText, + std::map >& uisIncluded) { - // Process if (this->Verbose) { - std::ostringstream err; - err << "AutoUic: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoUic: Checking " + absFilename); } - const std::string realName = cmsys::SystemTools::GetRealPath(absFilename); - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { - while (this->RegExpUicInclude.find(contentChars)) { - const std::string currentUi = this->RegExpUicInclude.match(1); - const std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); - // basename should be the part of the ui filename used for - // finding the correct header, so we need to remove the ui_ part - includedUis[realName].push_back(basename.substr(3)); - contentChars += this->RegExpUicInclude.end(); + while (this->UicRegExpInclude.find(contentChars)) { + uisIncluded[absFilename].push_back(this->UicRegExpInclude.match(1)); + contentChars += this->UicRegExpInclude.end(); } } } @@ -791,79 +927,69 @@ void cmQtAutoGenerators::ParseContentForUic( /** * @return True on success */ -bool cmQtAutoGenerators::ParseContentForMoc( - const std::string& absFilename, const std::string& contentsString, - const std::vector& headerExtensions, - std::map& includedMocs, bool relaxed) +bool cmQtAutoGenerators::MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed) { - // Process if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoMoc: Checking " + absFilename); } - const std::string scannedFileAbsPath = - cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)) + - '/'; + const std::string scannedFileAbsPath = SubDirPrefix(absFilename); const std::string scannedFileBasename = cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->MocRequired(contentsString, macroName); + const bool requiresMoc = this->MocRequired(contentText, ¯oName); bool ownDotMocIncluded = false; - bool ownMocUnderscoreIncluded = false; - std::string ownMocUnderscoreFile; - std::string ownMocHeaderFile; + std::string ownMocUnderscoreInclude; + std::string ownMocUnderscoreHeader; // first a simple string check for "moc" is *much* faster than the regexp, // and if the string search already fails, we don't have to try the // expensive regexp - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "moc") != CM_NULLPTR) { // Iterate over all included moc files - while (this->RegExpMocInclude.find(contentChars)) { - const std::string currentMoc = this->RegExpMocInclude.match(1); - // Basename of the current moc include - std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc); + while (this->MocRegExpInclude.find(contentChars)) { + const std::string incString = this->MocRegExpInclude.match(1); + // Basename of the moc include + const std::string incSubDir(SubDirPrefix(incString)); + const std::string incBasename = + cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); // If the moc include is of the moc_foo.cpp style we expect // the Q_OBJECT class declaration in a header file. // If the moc include is of the foo.moc style we need to look for // a Q_OBJECT macro in the current source file, if it contains the // macro we generate the moc file from the source file. - if (cmHasLiteralPrefix(basename, "moc_")) { + if (cmHasLiteralPrefix(incBasename, "moc_")) { // Include: moc_FOO.cxx - // basename should be the part of the moc filename used for - // finding the correct header, so we need to remove the moc_ part - basename = basename.substr(4); - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); - + // Remove the moc_ part + const std::string incRealBasename = incBasename.substr(4); + const std::string headerToMoc = + this->MocFindHeader(scannedFileAbsPath, incSubDir + incRealBasename); if (!headerToMoc.empty()) { - includedMocs[headerToMoc] = currentMoc; - if (relaxed && (basename == scannedFileBasename)) { - ownMocUnderscoreIncluded = true; - ownMocUnderscoreFile = currentMoc; - ownMocHeaderFile = headerToMoc; + if (!this->MocSkip(headerToMoc)) { + // Register moc job + mocsIncluded[headerToMoc] = incString; + this->MocFindDepends(headerToMoc, contentText, mocDepends); + // Store meta information for relaxed mode + if (relaxed && (incRealBasename == scannedFileBasename)) { + ownMocUnderscoreInclude = incString; + ownMocUnderscoreHeader = headerToMoc; + } } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\", but could not find header \"" << basename << '{' - << JoinExts(headerExtensions) << "}\" "; - if (mocSubDir.empty()) { - err << "in " << scannedFileAbsPath << "\n"; - } else { - err << "neither in " << scannedFileAbsPath << " nor in " - << mocSubDir << "\n"; - } - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << ", but could not find header " + << Quoted(incRealBasename + "{" + + JoinExts(this->HeaderExtensions) + "}"); + ; + this->LogError(ost.str()); return false; } } else { @@ -871,108 +997,125 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (!requiresMoc || basename != scannedFileBasename) { - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); + if (requiresMoc && (incBasename == scannedFileBasename)) { + // Include self + fileToMoc = absFilename; + ownDotMocIncluded = true; + } else { + // In relaxed mode try to find a header instead but issue a warning + const std::string headerToMoc = + this->MocFindHeader(scannedFileAbsPath, incSubDir + incBasename); if (!headerToMoc.empty()) { - // This is for KDE4 compatibility: - fileToMoc = headerToMoc; - if (!requiresMoc && basename == scannedFileBasename) { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\", but does not contain a " << macroName - << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename - << ".cpp\" for a compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); - } else { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\" instead of \"moc_" << basename - << ".cpp\". Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename - << ".cpp\" for compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + if (!this->MocSkip(headerToMoc)) { + // This is for KDE4 compatibility: + fileToMoc = headerToMoc; + if (!requiresMoc && (incBasename == scannedFileBasename)) { + std::ostringstream ost; + ost + << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" + << "Running moc on " << Quoted(headerToMoc) << "!\n" + << "Include " << Quoted("moc_" + incBasename + ".cpp") + << " for a compatibility with strict mode (see " + "CMAKE_AUTOMOC_RELAXED_MODE).\n"; + this->LogWarning(ost.str()); + } else { + std::ostringstream ost; + ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << " instead of " + << Quoted("moc_" + incBasename + ".cpp") << ".\n" + << "Running moc on " << Quoted(headerToMoc) << "!\n" + << "Include " << Quoted("moc_" + incBasename + ".cpp") + << " for compatibility with strict mode (see " + "CMAKE_AUTOMOC_RELAXED_MODE).\n"; + this->LogWarning(ost.str()); + } } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\", which seems to be the moc file from a different " + std::ostringstream ost; + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << ", which seems to be the moc file from a different " "source file. CMake also could not find a matching " - "header.\n"; - this->LogError(err.str()); + "header."; + this->LogError(ost.str()); return false; } - } else { - // Include self - fileToMoc = absFilename; - ownDotMocIncluded = true; } } else { // Mode: Strict - if (basename == scannedFileBasename) { + if (incBasename == scannedFileBasename) { // Include self fileToMoc = absFilename; ownDotMocIncluded = true; + // Accept but issue a warning if moc isn't required + if (!requiresMoc) { + std::ostringstream ost; + ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << ", but does not contain a Q_OBJECT or Q_GADGET " + "macro."; + this->LogWarning(ost.str()); + } } else { // Don't allow FOO.moc include other than self in strict mode - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\", which seems to be the moc file from a different " - "source file. This is not supported. Include \"" - << scannedFileBasename - << ".moc\" to run moc on this source file.\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << ", which seems to be the moc file from a different " + "source file. This is not supported. Include " + << Quoted(scannedFileBasename + ".moc") + << " to run moc on this source file."; + this->LogError(ost.str()); return false; } } if (!fileToMoc.empty()) { - includedMocs[fileToMoc] = currentMoc; + mocsIncluded[fileToMoc] = incString; + this->MocFindDepends(fileToMoc, contentText, mocDepends); } } // Forward content pointer - contentChars += this->RegExpMocInclude.end(); + contentChars += this->MocRegExpInclude.end(); } } - // In this case, check whether the scanned file itself contains a Q_OBJECT. - // If this is the case, the moc_foo.cpp should probably be generated from - // foo.cpp instead of foo.h, because otherwise it won't build. - // But warn, since this is not how it is supposed to be used. if (requiresMoc && !ownDotMocIncluded) { - if (relaxed && ownMocUnderscoreIncluded) { + // In this case, check whether the scanned file itself contains a Q_OBJECT. + // If this is the case, the moc_foo.cpp should probably be generated from + // foo.cpp instead of foo.h, because otherwise it won't build. + // But warn, since this is not how it is supposed to be used. + if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" << "The file contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreFile << "\". Running moc on " - << "\"" << absFilename << "\" ! Better include \"" - << scannedFileBasename - << ".moc\" for compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + << Quoted(scannedFileBasename + ".moc") << ", but instead includes " + << Quoted(ownMocUnderscoreInclude) << ".\n" + << "Running moc on " << Quoted(absFilename) << "!\n" + << "Better include " << Quoted(scannedFileBasename + ".moc") + << " for compatibility with strict mode (see " + "CMAKE_AUTOMOC_RELAXED_MODE)."; + this->LogWarning(ost.str()); // Use scanned source file instead of scanned header file as moc source - includedMocs[absFilename] = ownMocUnderscoreFile; - includedMocs.erase(ownMocHeaderFile); + mocsIncluded[absFilename] = ownMocUnderscoreInclude; + this->MocFindDepends(absFilename, contentText, mocDepends); + // Remove + mocsIncluded.erase(ownMocUnderscoreHeader); } else { // Otherwise always error out since it will not compile: - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" << "The file contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\" !\n"; - this->LogError(err.str()); + << Quoted(scannedFileBasename + ".moc") << "!\n" + << "Consider adding the include or enabling SKIP_AUTOMOC for this " + "file."; + this->LogError(ost.str()); return false; } } @@ -980,337 +1123,410 @@ bool cmQtAutoGenerators::ParseContentForMoc( return true; } +void cmQtAutoGenerators::MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends) +{ + // Log + if (this->Verbose) { + this->LogInfo("AutoMoc: Checking " + absFilename); + } + if (this->MocRequired(contentText)) { + // Register moc job + mocsNotIncluded[absFilename] = + this->ChecksumedPath(absFilename, "moc_", this->ConfigSuffix + ".cpp"); + this->MocFindDepends(absFilename, contentText, mocDepends); + } +} + void cmQtAutoGenerators::SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& absHeadersMoc, std::set& absHeadersUic) + const std::string& absFilename, std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const { - // search for header files and private header files we may need to moc: - std::string basepath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)); - basepath += '/'; - basepath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); - - // Search for regular header - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - const std::string headerName = basepath + "." + (*ext); - if (cmsys::SystemTools::FileExists(headerName.c_str())) { - // Moc headers - if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) { - absHeadersMoc.insert(headerName); - } - // Uic headers - if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) { - absHeadersUic.insert(headerName); - } - break; - } + std::string basepaths[2]; + { + std::string bpath = SubDirPrefix(absFilename); + bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); + // search for default header files and private header files + basepaths[0] = bpath; + basepaths[1] = bpath + "_p"; } - // Search for private header - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - const std::string headerName = basepath + "_p." + (*ext); - if (cmsys::SystemTools::FileExists(headerName.c_str())) { + + for (const std::string* bpit = cmArrayBegin(basepaths); + bpit != cmArrayEnd(basepaths); ++bpit) { + std::string headerName; + if (this->FindHeader(headerName, *bpit)) { // Moc headers - if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) { - absHeadersMoc.insert(headerName); + if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) { + mocHeaderFiles.insert(headerName); } // Uic headers - if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) { - absHeadersUic.insert(headerName); + if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) { + uicHeaderFiles.insert(headerName); } - break; } } } -void cmQtAutoGenerators::ParseHeaders( - const std::set& absHeadersMoc, - const std::set& absHeadersUic, - const std::map& includedMocs, - std::map& notIncludedMocs, - std::map >& includedUis) +bool cmQtAutoGenerators::ParseHeaders( + const std::set& mocHeaderFiles, + const std::set& uicHeaderFiles, + const std::map& mocsIncluded, + std::map& mocsNotIncluded, + std::map >& mocDepends, + std::map >& uisIncluded) { + bool success = true; // Merged header files list to read files only once std::set headerFiles; - headerFiles.insert(absHeadersMoc.begin(), absHeadersMoc.end()); - headerFiles.insert(absHeadersUic.begin(), absHeadersUic.end()); + headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end()); + headerFiles.insert(uicHeaderFiles.begin(), uicHeaderFiles.end()); for (std::set::const_iterator hIt = headerFiles.begin(); hIt != headerFiles.end(); ++hIt) { const std::string& headerName = *hIt; - const std::string contents = ReadAll(headerName); - - // Parse header content for MOC - if ((absHeadersMoc.find(headerName) != absHeadersMoc.end()) && - (includedMocs.find(headerName) == includedMocs.end())) { - // Process - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << headerName << "\n"; - this->LogInfo(err.str()); + std::string contentText; + if (ReadAll(contentText, headerName)) { + // Parse header content for MOC + if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) && + (mocsIncluded.find(headerName) == mocsIncluded.end())) { + this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded, + mocDepends); } - std::string macroName; - if (this->MocRequired(contents, macroName)) { - notIncludedMocs[headerName] = fpathCheckSum.getPart(headerName) + - "/moc_" + - cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName) + - ".cpp"; + // Parse header content for UIC + if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) { + this->UicParseContent(headerName, contentText, uisIncluded); } - } - - // Parse header content for UIC - if (absHeadersUic.find(headerName) != absHeadersUic.end()) { - this->ParseContentForUic(headerName, contents, includedUis); + } else { + std::ostringstream ost; + ost << "AutoGen: Error: Could not read header file:\n" + << Quoted(headerName); + this->LogError(ost.str()); + success = false; + break; } } + return success; } bool cmQtAutoGenerators::MocGenerateAll( - const std::map& includedMocs, - const std::map& notIncludedMocs) + const std::map& mocsIncluded, + const std::map& mocsNotIncluded, + const std::map >& mocDepends) { - if (this->MocExecutable.empty()) { + if (!this->MocEnabled()) { return true; } - // look for name collisions + // Look for name collisions { std::multimap collisions; // Test merged map of included and notIncluded - std::map mergedMocs(includedMocs); - mergedMocs.insert(notIncludedMocs.begin(), notIncludedMocs.end()); + std::map mergedMocs(mocsIncluded); + mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end()); if (this->NameCollisionTest(mergedMocs, collisions)) { - std::ostringstream err; - err << "AutoMoc: Error: " + std::ostringstream ost; + ost << "AutoMoc: Error: " "The same moc file will be generated " - "from different sources." - << std::endl - << "To avoid this error either" << std::endl - << "- rename the source files or" << std::endl - << "- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + "from different sources.\n" + "To avoid this error either\n" + "- rename the source files or\n" + "- do not include the (moc_NAME.cpp|NAME.moc) file"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } - // generate moc files that are included by source files. - { - const std::string subDirPrefix = "include/"; - for (std::map::const_iterator it = - includedMocs.begin(); - it != includedMocs.end(); ++it) { - if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) { - if (this->RunMocFailed) { + // Generate moc_predefs + if (!this->MocPredefsCmd.empty()) { + if (this->MocSettingsChanged || + FileAbsentOrOlder(this->MocPredefsFileAbs, this->SettingsFile)) { + this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel); + + std::string output; + { + // Compose command + std::vector cmd = this->MocPredefsCmd; + // Add includes + cmd.insert(cmd.end(), this->MocIncludes.begin(), + this->MocIncludes.end()); + // Add definitions + for (std::vector::const_iterator it = + this->MocDefinitions.begin(); + it != this->MocDefinitions.end(); ++it) { + cmd.push_back("-D" + (*it)); + } + // Add options + cmd.insert(cmd.end(), this->MocOptions.begin(), + this->MocOptions.end()); + // Execute command + if (!this->RunCommand(cmd, output, false)) { + { + std::ostringstream ost; + ost << "AutoMoc: Error: moc predefs generation command failed\n"; + ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n"; + ost << "AutoMoc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); + } + return false; + } + } + // (Re)write predefs file only on demand + if (this->FileDiffers(this->MocPredefsFileAbs, output)) { + if (this->FileWrite("AutoMoc", this->MocPredefsFileAbs, output)) { + this->MocPredefsChanged = true; + } else { return false; } } } } - // generate moc files that are _not_ included by source files. - bool automocCppChanged = false; - { - const std::string subDirPrefix; - for (std::map::const_iterator it = - notIncludedMocs.begin(); - it != notIncludedMocs.end(); ++it) { - if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) { - automocCppChanged = true; - } else { - if (this->RunMocFailed) { - return false; - } + // Generate moc files that are included by source files. + for (std::map::const_iterator it = + mocsIncluded.begin(); + it != mocsIncluded.end(); ++it) { + if (!this->MocGenerateFile(it->first, it->second, mocDepends, true)) { + if (this->MocRunFailed) { + return false; + } + } + } + + // Generate moc files that are _not_ included by source files. + bool mocCompFileGenerated = false; + for (std::map::const_iterator it = + mocsNotIncluded.begin(); + it != mocsNotIncluded.end(); ++it) { + if (this->MocGenerateFile(it->first, it->second, mocDepends, false)) { + mocCompFileGenerated = true; + } else { + if (this->MocRunFailed) { + return false; } } } - // Compose moc_compilation.cpp content + // Compose mocs compilation file content std::string automocSource; { - std::ostringstream outStream; - outStream << "/* This file is autogenerated, do not edit*/\n"; - if (notIncludedMocs.empty()) { + std::ostringstream ost; + ost << "/* This file is autogenerated, do not edit*/\n"; + if (mocsNotIncluded.empty()) { // Dummy content - outStream << "enum some_compilers { need_more_than_nothing };\n"; + ost << "enum some_compilers { need_more_than_nothing };\n"; } else { // Valid content for (std::map::const_iterator it = - notIncludedMocs.begin(); - it != notIncludedMocs.end(); ++it) { - outStream << "#include \"" << it->second << "\"\n"; + mocsNotIncluded.begin(); + it != mocsNotIncluded.end(); ++it) { + ost << "#include \"" << it->second << "\"\n"; } } - outStream.flush(); - automocSource = outStream.str(); - } - - // Check if we even need to update moc_compilation.cpp - if (!automocCppChanged) { - // compare contents of the moc_compilation.cpp file - const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs); - if (oldContents == automocSource) { - // nothing changed: don't touch the moc_compilation.cpp file - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: " << this->OutMocCppFilenameRel << " still up to date" - << std::endl; - this->LogInfo(err.str()); - } - return true; - } + automocSource = ost.str(); } - // Actually write moc_compilation.cpp - { - std::string msg = "Generating MOC compilation "; - msg += this->OutMocCppFilenameRel; - this->LogBold(msg); - } - // Make sure the parent directory exists - bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs); - if (success) { - cmsys::ofstream outfile; - outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc); - if (!outfile) { - success = false; - std::ostringstream err; - err << "AutoMoc: error opening " << this->OutMocCppFilenameAbs << "\n"; - this->LogError(err.str()); - } else { - outfile << automocSource; - // Check for write errors - if (!outfile.good()) { - success = false; - std::ostringstream err; - err << "AutoMoc: error writing " << this->OutMocCppFilenameAbs << "\n"; - this->LogError(err.str()); - } + if (this->FileDiffers(this->MocCompFileAbs, automocSource)) { + // Actually write mocs compilation file + this->LogBold("Generating MOC compilation " + this->MocCompFileRel); + if (!this->FileWrite("AutoMoc", this->MocCompFileAbs, automocSource)) { + return false; } + } else if (mocCompFileGenerated) { + // Only touch mocs compilation file + if (this->Verbose) { + this->LogInfo("Touching MOC compilation " + this->MocCompFileRel); + } + cmSystemTools::Touch(this->MocCompFileAbs, false); } - return success; + + return true; } /** * @return True if a moc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix) +bool cmQtAutoGenerators::MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::map >& mocDepends, + bool included) { + bool mocGenerated = false; + bool generateMoc = this->MocSettingsChanged || this->MocPredefsChanged; + const std::string mocFileRel = - this->AutogenBuildSubDir + subDirPrefix + mocFileName; - const std::string mocFileAbs = this->CurrentBinaryDir + mocFileRel; + included ? (this->AutogenIncludeDir + mocFileName) : mocFileName; + const std::string mocFileAbs = + cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, mocFileRel); - bool generateMoc = this->GenerateMocAll; - // Test if the source file is newer that the build file if (!generateMoc) { + // Test if the source file is newer that the build file generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile); + if (!generateMoc) { + // Test if a dependency file changed + std::map >::const_iterator dit = + mocDepends.find(sourceFile); + if (dit != mocDepends.end()) { + for (std::set::const_iterator fit = dit->second.begin(); + fit != dit->second.end(); ++fit) { + if (FileAbsentOrOlder(mocFileAbs, *fit)) { + generateMoc = true; + break; + } + } + } + } } if (generateMoc) { // Log this->LogBold("Generating MOC source " + mocFileRel); // Make sure the parent directory exists - if (!this->MakeParentDirectory(mocFileAbs)) { - this->RunMocFailed = true; - return false; - } - - std::vector command; - command.push_back(this->MocExecutable); - command.insert(command.end(), this->MocIncludes.begin(), - this->MocIncludes.end()); - command.insert(command.end(), this->MocDefinitions.begin(), - this->MocDefinitions.end()); - command.insert(command.end(), this->MocOptions.begin(), - this->MocOptions.end()); -#ifdef _WIN32 - command.push_back("-DWIN32"); -#endif - command.push_back("-o"); - command.push_back(mocFileAbs); - command.push_back(sourceFile); - - if (this->Verbose) { - this->LogCommand(command); + if (this->MakeParentDirectory("AutoMoc", mocFileAbs)) { + // Compose moc command + std::vector cmd; + cmd.push_back(this->MocExecutable); + // Add includes + cmd.insert(cmd.end(), this->MocIncludes.begin(), + this->MocIncludes.end()); + // Add definitions + for (std::vector::const_iterator it = + this->MocDefinitions.begin(); + it != this->MocDefinitions.end(); ++it) { + cmd.push_back("-D" + (*it)); + } + // Add options + cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end()); + // Add predefs include + if (!this->MocPredefsFileAbs.empty()) { + cmd.push_back("--include"); + cmd.push_back(this->MocPredefsFileAbs); + } + cmd.push_back("-o"); + cmd.push_back(mocFileAbs); + cmd.push_back(sourceFile); + + // Execute moc command + std::string output; + if (this->RunCommand(cmd, output)) { + // Success + mocGenerated = true; + } else { + // Command failed + { + std::ostringstream ost; + ost << "AutoMoc: Error: moc process failed for\n"; + ost << Quoted(mocFileRel) << "\n"; + ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n"; + ost << "AutoMoc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); + } + cmSystemTools::RemoveFile(mocFileAbs); + this->MocRunFailed = true; + } + } else { + // Parent directory creation failed + this->MocRunFailed = true; } + } + return mocGenerated; +} - std::string output; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &output, &output, &retVal); - if (!result || retVal) { - { - std::ostringstream err; - err << "AutoMoc: Error: moc process for " << mocFileRel << " failed:\n" - << output << std::endl; - this->LogError(err.str()); +bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, + const std::string& sourceFile, + const std::string& includeString) +{ + bool success = false; + // Search in vicinity of the source + { + std::string testPath = SubDirPrefix(sourceFile); + testPath += includeString; + if (cmsys::SystemTools::FileExists(testPath.c_str())) { + absFile = cmsys::SystemTools::GetRealPath(testPath); + success = true; + } + } + // Search in include directories + if (!success) { + for (std::vector::const_iterator iit = + this->UicSearchPaths.begin(); + iit != this->UicSearchPaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + includeString); + if (cmsys::SystemTools::FileExists(fullPath.c_str())) { + absFile = cmsys::SystemTools::GetRealPath(fullPath); + success = true; + break; } - cmSystemTools::RemoveFile(mocFileAbs); - this->RunMocFailed = true; - return false; } - return true; } - return false; + return success; } bool cmQtAutoGenerators::UicGenerateAll( - const std::map >& includedUis) + const std::map >& uisIncluded) { - if (this->UicExecutable.empty()) { + if (!this->UicEnabled()) { return true; } // single map with input / output names - std::map > uiGenMap; - std::map testMap; - for (std::map >::const_iterator it = - includedUis.begin(); - it != includedUis.end(); ++it) { - // source file path - std::string sourcePath = cmsys::SystemTools::GetFilenamePath(it->first); - sourcePath += '/'; - // insert new map for source file an use new reference - uiGenMap[it->first] = std::map(); - std::map& sourceMap = uiGenMap[it->first]; - for (std::vector::const_iterator sit = it->second.begin(); - sit != it->second.end(); ++sit) { - const std::string& uiFileName = *sit; - const std::string uiInputFile = sourcePath + uiFileName + ".ui"; - const std::string uiOutputFile = "ui_" + uiFileName + ".h"; - sourceMap[uiInputFile] = uiOutputFile; - testMap[uiInputFile] = uiOutputFile; - } - } - - // look for name collisions + std::map > sourceGenMap; { - std::multimap collisions; - if (this->NameCollisionTest(testMap, collisions)) { - std::ostringstream err; - err << "AutoUic: Error: The same ui_NAME.h file will be generated " - "from different sources." - << std::endl - << "To avoid this error rename the source files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); - return false; + // Collision lookup map + std::map testMap; + // Compile maps + for (std::map >::const_iterator sit = + uisIncluded.begin(); + sit != uisIncluded.end(); ++sit) { + const std::string& source(sit->first); + const std::vector& sourceIncs(sit->second); + // insert new source/destination map + std::map& uiGenMap = sourceGenMap[source]; + for (std::vector::const_iterator uit = sourceIncs.begin(); + uit != sourceIncs.end(); ++uit) { + // Remove ui_ from the begin filename by substr() + const std::string uiBasePath = SubDirPrefix(*uit); + const std::string uiBaseName = + cmsys::SystemTools::GetFilenameWithoutLastExtension(*uit).substr(3); + const std::string searchFileName = uiBasePath + uiBaseName + ".ui"; + std::string uiInputFile; + if (UicFindIncludedFile(uiInputFile, source, searchFileName)) { + std::string uiOutputFile = uiBasePath + "ui_" + uiBaseName + ".h"; + cmSystemTools::ReplaceString(uiOutputFile, "..", "__"); + uiGenMap[uiInputFile] = uiOutputFile; + testMap[uiInputFile] = uiOutputFile; + } else { + this->LogError("AutoUic: Error: " + Quoted(sit->first) + + "\nCould not find " + Quoted(searchFileName)); + return false; + } + } + } + // look for name collisions + { + std::multimap collisions; + if (this->NameCollisionTest(testMap, collisions)) { + std::ostringstream ost; + ost << "AutoUic: Error: The same ui_NAME.h file will be generated " + "from different sources.\n" + "To avoid this error rename the source files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); + return false; + } } } - testMap.clear(); // generate ui files for (std::map >::const_iterator it = - uiGenMap.begin(); - it != uiGenMap.end(); ++it) { + sourceGenMap.begin(); + it != sourceGenMap.end(); ++it) { for (std::map::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit) { if (!this->UicGenerateFile(it->first, sit->first, sit->second)) { - if (this->RunUicFailed) { + if (this->UicRunFailed) { return false; } } @@ -1327,13 +1543,15 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, const std::string& uiInputFile, const std::string& uiOutputFile) { - const std::string uicFileRel = - this->AutogenBuildSubDir + "include/" + uiOutputFile; - const std::string uicFileAbs = this->CurrentBinaryDir + uicFileRel; + bool uicGenerated = false; + bool generateUic = this->UicSettingsChanged; + + const std::string uicFileRel = this->AutogenIncludeDir + uiOutputFile; + const std::string uicFileAbs = + cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, uicFileRel); - bool generateUic = this->GenerateUicAll; - // Test if the source file is newer that the build file if (!generateUic) { + // Test if the source file is newer that the build file generateUic = FileAbsentOrOlder(uicFileAbs, uiInputFile); } if (generateUic) { @@ -1341,67 +1559,70 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, this->LogBold("Generating UIC header " + uicFileRel); // Make sure the parent directory exists - if (!this->MakeParentDirectory(uicFileAbs)) { - this->RunUicFailed = true; - return false; - } - - std::vector command; - command.push_back(this->UicExecutable); - - std::vector opts = this->UicTargetOptions; - std::map::const_iterator optionIt = - this->UicOptions.find(uiInputFile); - if (optionIt != this->UicOptions.end()) { - std::vector fileOpts; - cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); - UicMergeOptions(opts, fileOpts, this->QtMajorVersion == "5"); - } - command.insert(command.end(), opts.begin(), opts.end()); - - command.push_back("-o"); - command.push_back(uicFileAbs); - command.push_back(uiInputFile); - - if (this->Verbose) { - this->LogCommand(command); - } - std::string output; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &output, &output, &retVal); - if (!result || retVal) { + if (this->MakeParentDirectory("AutoUic", uicFileAbs)) { + // Compose uic command + std::vector cmd; + cmd.push_back(this->UicExecutable); { - std::ostringstream err; - err << "AutoUic: Error: uic process for " << uicFileRel - << " needed by\n \"" << realName << "\"\nfailed:\n" - << output << std::endl; - this->LogError(err.str()); + std::vector allOpts = this->UicTargetOptions; + std::map::const_iterator optionIt = + this->UicOptions.find(uiInputFile); + if (optionIt != this->UicOptions.end()) { + std::vector fileOpts; + cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); + UicMergeOptions(allOpts, fileOpts, (this->QtMajorVersion == "5")); + } + cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } - cmSystemTools::RemoveFile(uicFileAbs); - this->RunUicFailed = true; - return false; + cmd.push_back("-o"); + cmd.push_back(uicFileAbs); + cmd.push_back(uiInputFile); + + std::string output; + if (this->RunCommand(cmd, output)) { + // Success + uicGenerated = true; + } else { + // Command failed + { + std::ostringstream ost; + ost << "AutoUic: Error: uic process failed for\n"; + ost << Quoted(uicFileRel) << " needed by\n"; + ost << Quoted(realName) << "\n"; + ost << "AutoUic: Command:\n" << QuotedCommand(cmd) << "\n"; + ost << "AutoUic: Command output:\n" << output << "\n"; + this->LogError(ost.str()); + } + cmSystemTools::RemoveFile(uicFileAbs); + this->UicRunFailed = true; + } + } else { + // Parent directory creation failed + this->UicRunFailed = true; } - return true; } - return false; + return uicGenerated; } -bool cmQtAutoGenerators::QrcGenerateAll() +bool cmQtAutoGenerators::RccGenerateAll() { - if (this->RccExecutable.empty()) { + if (!this->RccEnabled()) { return true; } // generate single map with input / output names std::map qrcGenMap; - for (std::vector::const_iterator si = this->RccSources.begin(); - si != this->RccSources.end(); ++si) { - const std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si); - if (ext == ".qrc") { - qrcGenMap[*si] = this->AutogenBuildSubDir + fpathCheckSum.getPart(*si) + - "/qrc_" + cmsys::SystemTools::GetFilenameWithoutLastExtension(*si) + - ".cpp"; + { + const std::string qrcPrefix = "qrc_"; + const std::string qrcSuffix = this->ConfigSuffix + ".cpp"; + for (std::vector::const_iterator si = + this->RccSources.begin(); + si != this->RccSources.end(); ++si) { + const std::string ext = + cmsys::SystemTools::GetFilenameLastExtension(*si); + if (ext == ".qrc") { + qrcGenMap[*si] = this->ChecksumedPath(*si, qrcPrefix, qrcSuffix); + } } } @@ -1409,12 +1630,11 @@ bool cmQtAutoGenerators::QrcGenerateAll() { std::multimap collisions; if (this->NameCollisionTest(qrcGenMap, collisions)) { - std::ostringstream err; - err << "AutoRcc: Error: The same qrc_NAME.cpp file" - " will be generated from different sources." - << std::endl - << "To avoid this error rename the source .qrc files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + std::ostringstream ost; + ost << "AutoRcc: Error: The same qrc_NAME.cpp file" + " will be generated from different sources.\n" + "To avoid this error rename the source .qrc files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1424,8 +1644,8 @@ bool cmQtAutoGenerators::QrcGenerateAll() qrcGenMap.begin(); si != qrcGenMap.end(); ++si) { bool unique = FileNameIsUnique(si->first, qrcGenMap); - if (!this->QrcGenerateFile(si->first, si->second, unique)) { - if (this->RunRccFailed) { + if (!this->RccGenerateFile(si->first, si->second, unique)) { + if (this->RccRunFailed) { return false; } } @@ -1436,145 +1656,168 @@ bool cmQtAutoGenerators::QrcGenerateAll() /** * @return True if a rcc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::QrcGenerateFile(const std::string& qrcInputFile, - const std::string& qrcOutputFile, +bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, + const std::string& rccOutputFile, bool unique_n) { - std::string symbolName = - cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile); - if (!unique_n) { - symbolName += "_"; - symbolName += fpathCheckSum.getPart(qrcInputFile); - } - // Replace '-' with '_'. The former is valid for - // file names but not for symbol names. - std::replace(symbolName.begin(), symbolName.end(), '-', '_'); - - const std::string qrcBuildFile = this->CurrentBinaryDir + qrcOutputFile; - - bool generateQrc = this->GenerateRccAll; - // Test if the resources list file is newer than build file - if (!generateQrc) { - generateQrc = FileAbsentOrOlder(qrcBuildFile, qrcInputFile); - } - // Test if any resource file is newer than the build file - if (!generateQrc) { - const std::vector& files = this->RccInputs[qrcInputFile]; - for (std::vector::const_iterator it = files.begin(); - it != files.end(); ++it) { - if (FileAbsentOrOlder(qrcBuildFile, *it)) { - generateQrc = true; - break; + bool rccGenerated = false; + bool generateRcc = this->RccSettingsChanged; + + const std::string rccBuildFile = + cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, rccOutputFile); + + if (!generateRcc) { + // Test if the resources list file is newer than build file + generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile); + if (!generateRcc) { + // Acquire input file list + std::vector readFiles; + const std::vector* files = &this->RccInputs[rccInputFile]; + if (files->empty()) { + // Read input file list from qrc file + std::string error; + if (cmQtAutoGeneratorCommon::RccListInputs( + this->QtMajorVersion, this->RccExecutable, rccInputFile, + readFiles, &error)) { + files = &readFiles; + } else { + files = CM_NULLPTR; + this->LogError(error); + this->RccRunFailed = true; + } + } + // Test if any input file is newer than the build file + if (files != CM_NULLPTR) { + for (std::vector::const_iterator it = files->begin(); + it != files->end(); ++it) { + if (FileAbsentOrOlder(rccBuildFile, *it)) { + generateRcc = true; + break; + } + } } } } - if (generateQrc) { - { - std::string msg = "Generating RCC source "; - msg += qrcOutputFile; - this->LogBold(msg); - } + if (generateRcc) { + // Log + this->LogBold("Generating RCC source " + rccOutputFile); // Make sure the parent directory exists - if (!this->MakeParentDirectory(qrcOutputFile)) { - this->RunRccFailed = true; - return false; - } - - std::vector command; - command.push_back(this->RccExecutable); - { - std::map::const_iterator optionIt = - this->RccOptions.find(qrcInputFile); - if (optionIt != this->RccOptions.end()) { - cmSystemTools::ExpandListArgument(optionIt->second, command); + if (this->MakeParentDirectory("AutoRcc", rccBuildFile)) { + // Compose symbol name + std::string symbolName = + cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile); + if (!unique_n) { + symbolName += "_"; + symbolName += FPathChecksum.getPart(rccInputFile); } - } - command.push_back("-name"); - command.push_back(symbolName); - command.push_back("-o"); - command.push_back(qrcBuildFile); - command.push_back(qrcInputFile); + // Replace '-' with '_'. The former is valid for + // file names but not for symbol names. + std::replace(symbolName.begin(), symbolName.end(), '-', '_'); - if (this->Verbose) { - this->LogCommand(command); - } - std::string output; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &output, &output, &retVal); - if (!result || retVal) { + // Compose rcc command + std::vector cmd; + cmd.push_back(this->RccExecutable); { - std::ostringstream err; - err << "AutoRcc: Error: rcc process for " << qrcOutputFile - << " failed:\n" - << output << std::endl; - this->LogError(err.str()); + std::map::const_iterator optionIt = + this->RccOptions.find(rccInputFile); + if (optionIt != this->RccOptions.end()) { + cmSystemTools::ExpandListArgument(optionIt->second, cmd); + } } - cmSystemTools::RemoveFile(qrcBuildFile); - this->RunRccFailed = true; - return false; + cmd.push_back("-name"); + cmd.push_back(symbolName); + cmd.push_back("-o"); + cmd.push_back(rccBuildFile); + cmd.push_back(rccInputFile); + + std::string output; + if (this->RunCommand(cmd, output)) { + // Success + rccGenerated = true; + } else { + // Command failed + { + std::ostringstream ost; + ost << "AutoRcc: Error: rcc process failed for\n"; + ost << Quoted(rccOutputFile) << "\n"; + ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n"; + ost << "AutoRcc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); + } + cmSystemTools::RemoveFile(rccBuildFile); + this->RccRunFailed = true; + } + } else { + // Parent directory creation failed + this->RccRunFailed = true; } - return true; } - return false; + return rccGenerated; } void cmQtAutoGenerators::LogErrorNameCollision( const std::string& message, - const std::multimap& collisions) + const std::multimap& collisions) const { typedef std::multimap::const_iterator Iter; - std::ostringstream err; + std::ostringstream ost; // Add message - err << message; + if (!message.empty()) { + ost << message; + if (message[message.size() - 1] != '\n') { + ost << '\n'; + } + } // Append collision list for (Iter it = collisions.begin(); it != collisions.end(); ++it) { - err << it->first << " : " << it->second << std::endl; + ost << it->first << " : " << it->second << '\n'; } - this->LogError(err.str()); + this->LogError(ost.str()); } -void cmQtAutoGenerators::LogBold(const std::string& message) +void cmQtAutoGenerators::LogBold(const std::string& message) const { cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | cmsysTerminal_Color_ForegroundBold, message.c_str(), true, this->ColorOutput); } -void cmQtAutoGenerators::LogInfo(const std::string& message) +void cmQtAutoGenerators::LogInfo(const std::string& message) const { - std::cout << message.c_str(); -} - -void cmQtAutoGenerators::LogWarning(const std::string& message) -{ - std::ostringstream ostr; - ostr << message << "\n"; - std::cout << message.c_str(); + std::string msg(message); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } -void cmQtAutoGenerators::LogError(const std::string& message) +void cmQtAutoGenerators::LogWarning(const std::string& message) const { - std::ostringstream ostr; - ostr << message << "\n\n"; - std::cerr << ostr.str(); + std::string msg(message); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } -void cmQtAutoGenerators::LogCommand(const std::vector& command) +void cmQtAutoGenerators::LogError(const std::string& message) const { - std::ostringstream sbuf; - for (std::vector::const_iterator cmdIt = command.begin(); - cmdIt != command.end(); ++cmdIt) { - if (cmdIt != command.begin()) { - sbuf << " "; + std::string msg(message); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); } - sbuf << *cmdIt; - } - if (!sbuf.str().empty()) { - sbuf << std::endl; - this->LogInfo(sbuf.str()); + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); } } @@ -1584,7 +1827,7 @@ void cmQtAutoGenerators::LogCommand(const std::vector& command) */ bool cmQtAutoGenerators::NameCollisionTest( const std::map& genFiles, - std::multimap& collisions) + std::multimap& collisions) const { typedef std::map::const_iterator Iter; typedef std::map::value_type VType; @@ -1608,20 +1851,175 @@ bool cmQtAutoGenerators::NameCollisionTest( return !collisions.empty(); } +/** + * @brief Generates a file path based on the checksum of the source file path + * @return The path + */ +std::string cmQtAutoGenerators::ChecksumedPath( + const std::string& sourceFile, const std::string& basePrefix, + const std::string& baseSuffix) const +{ + std::string res = FPathChecksum.getPart(sourceFile); + res += "/"; + res += basePrefix; + res += cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFile); + res += baseSuffix; + return res; +} + /** * @brief Generates the parent directory of the given file on demand * @return True on success */ -bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) +bool cmQtAutoGenerators::MakeParentDirectory(const char* logPrefix, + const std::string& filename) const { bool success = true; const std::string dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { success = cmsys::SystemTools::MakeDirectory(dirName); if (!success) { - std::ostringstream err; - err << "AutoGen: Directory creation failed: " << dirName << std::endl; - this->LogError(err.str()); + std::string error = logPrefix; + error += ": Error: Parent directory creation failed for "; + error += Quoted(filename); + this->LogError(error); + } + } + return success; +} + +bool cmQtAutoGenerators::FileDiffers(const std::string& filename, + const std::string& content) +{ + bool differs = true; + { + std::string oldContents; + if (ReadAll(oldContents, filename)) { + differs = (oldContents != content); + } + } + return differs; +} + +bool cmQtAutoGenerators::FileWrite(const char* logPrefix, + const std::string& filename, + const std::string& content) +{ + std::string error; + // Make sure the parent directory exists + if (this->MakeParentDirectory(logPrefix, filename)) { + cmsys::ofstream outfile; + outfile.open(filename.c_str(), std::ios::trunc); + if (outfile) { + outfile << content; + // Check for write errors + if (!outfile.good()) { + error = logPrefix; + error += ": Error writing "; + error += Quoted(filename); + } + } else { + error = logPrefix; + error = ": Error opening "; + error += Quoted(filename); + } + } + if (!error.empty()) { + this->LogError(error); + return false; + } + return true; +} + +/** + * @brief Runs a command and returns true on success + * @return True on success + */ +bool cmQtAutoGenerators::RunCommand(const std::vector& command, + std::string& output, bool verbose) const +{ + // Log command + if (this->Verbose) { + this->LogInfo(QuotedCommand(command)); + } + // Execute command + int retVal = 0; + bool res = cmSystemTools::RunSingleCommand( + command, &output, &output, &retVal, CM_NULLPTR, + verbose ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE); + return (res && (retVal == 0)); +} + +/** + * @brief Tries to find the header file to the given file base path by + * appending different header extensions + * @return True on success + */ +bool cmQtAutoGenerators::FindHeader(std::string& header, + const std::string& testBasePath) const +{ + for (std::vector::const_iterator ext = + this->HeaderExtensions.begin(); + ext != this->HeaderExtensions.end(); ++ext) { + std::string testFilePath(testBasePath); + testFilePath += '.'; + testFilePath += (*ext); + if (cmsys::SystemTools::FileExists(testFilePath.c_str())) { + header = testFilePath; + return true; + } + } + return false; +} + +std::string cmQtAutoGenerators::MocFindHeader( + const std::string& sourcePath, const std::string& includeBase) const +{ + std::string header; + // Search in vicinity of the source + if (!this->FindHeader(header, sourcePath + includeBase)) { + // Search in include directories + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + includeBase); + if (FindHeader(header, fullPath)) { + break; + } + } + } + // Sanitize + if (!header.empty()) { + header = cmsys::SystemTools::GetRealPath(header); + } + return header; +} + +bool cmQtAutoGenerators::MocFindIncludedFile( + std::string& absFile, const std::string& sourcePath, + const std::string& includeString) const +{ + bool success = false; + // Search in vicinity of the source + { + std::string testPath = sourcePath; + testPath += includeString; + if (cmsys::SystemTools::FileExists(testPath.c_str())) { + absFile = cmsys::SystemTools::GetRealPath(testPath); + success = true; + } + } + // Search in include directories + if (!success) { + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + includeString); + if (cmsys::SystemTools::FileExists(fullPath.c_str())) { + absFile = cmsys::SystemTools::GetRealPath(fullPath); + success = true; + break; + } } } return success; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 7891eb986..b525364c0 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -3,14 +3,15 @@ #ifndef cmQtAutoGenerators_h #define cmQtAutoGenerators_h -#include // IWYU pragma: keep -#include -#include +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmFilePathChecksum.h" +#include "cmsys/RegularExpression.hxx" -#include #include #include #include +#include #include class cmMakefile; @@ -22,147 +23,199 @@ public: bool Run(const std::string& targetDirectory, const std::string& config); private: - // - Configuration + // -- Types + + /// @brief Used to extract additional dependencies from content text + struct MocDependFilter + { + std::string key; + cmsys::RegularExpression regExp; + }; + typedef std::pair MocMacroFilter; + + // -- Configuration + bool MocDependFilterPush(const std::string& key, const std::string& regExp); bool ReadAutogenInfoFile(cmMakefile* makefile, const std::string& targetDirectory, const std::string& config); - std::string MocSettingsStringCompose(); - std::string UicSettingsStringCompose(); - std::string RccSettingsStringCompose(); - void OldSettingsReadFile(cmMakefile* makefile, - const std::string& targetDirectory); - bool OldSettingsWriteFile(const std::string& targetDirectory); + bool MocEnabled() const { return !this->MocExecutable.empty(); } + bool UicEnabled() const { return !this->UicExecutable.empty(); } + bool RccEnabled() const { return !this->RccExecutable.empty(); } + + // -- Settings file + void SettingsFileRead(cmMakefile* makefile); + bool SettingsFileWrite(); + + bool AnySettingsChanged() const + { + return (this->MocSettingsChanged || this->RccSettingsChanged || + this->UicSettingsChanged); + } + + // -- Init and run + void Init(cmMakefile* makefile); + bool RunAutogen(); - // - Init and run - void Init(); - bool RunAutogen(cmMakefile* makefile); + // -- Content analysis + bool MocRequired(const std::string& contentText, + std::string* macroName = CM_NULLPTR); + void MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends); - // - Content analysis - bool MocRequired(const std::string& text, std::string& macroName); - bool MocSkipTest(const std::string& absFilename); - bool UicSkipTest(const std::string& absFilename); + bool MocSkip(const std::string& absFilename) const; + bool UicSkip(const std::string& absFilename) const; bool ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, - std::map& includedMocs, + std::map& mocsIncluded, + std::map >& mocDepends, std::map >& includedUis, bool relaxed); - void SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& absHeadersMoc, - std::set& absHeadersUic); - - void ParseHeaders( - const std::set& absHeadersMoc, - const std::set& absHeadersUic, - const std::map& includedMocs, - std::map& notIncludedMocs, + void SearchHeadersForSourceFile(const std::string& absFilename, + std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const; + + bool ParseHeaders( + const std::set& mocHeaderFiles, + const std::set& uicHeaderFiles, + const std::map& mocsIncluded, + std::map& mocsNotIncluded, + std::map >& mocDepends, std::map >& includedUis); - void ParseContentForUic( - const std::string& fileName, const std::string& contentsString, + void UicParseContent( + const std::string& fileName, const std::string& contentText, std::map >& includedUis); - bool ParseContentForMoc(const std::string& absFilename, - const std::string& contentsString, - const std::vector& headerExtensions, - std::map& includedMocs, - bool relaxed); + bool MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed); - // - Moc file generation - bool MocGenerateAll( - const std::map& includedMocs, - const std::map& notIncludedMocs); - bool MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix); + void MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends); - // - Uic file generation + // -- Moc file generation + bool MocGenerateAll( + const std::map& mocsIncluded, + const std::map& mocsNotIncluded, + const std::map >& mocDepends); + bool MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::map >& mocDepends, + bool included); + + // -- Uic file generation + bool UicFindIncludedFile(std::string& absFile, const std::string& sourceFile, + const std::string& includeString); bool UicGenerateAll( const std::map >& includedUis); bool UicGenerateFile(const std::string& realName, const std::string& uiInputFile, const std::string& uiOutputFile); - // - Qrc file generation - bool QrcGenerateAll(); - bool QrcGenerateFile(const std::string& qrcInputFile, + // -- Rcc file generation + bool RccGenerateAll(); + bool RccGenerateFile(const std::string& qrcInputFile, const std::string& qrcOutputFile, bool unique_n); - // - Logging + // -- Logging void LogErrorNameCollision( const std::string& message, - const std::multimap& collisions); - void LogBold(const std::string& message); - void LogInfo(const std::string& message); - void LogWarning(const std::string& message); - void LogError(const std::string& message); - void LogCommand(const std::vector& command); - - // - Utility - bool NameCollisionTest(const std::map& genFiles, - std::multimap& collisions); - bool MakeParentDirectory(const std::string& filename); - - // - Target names - std::string OriginTargetName; - std::string AutogenTargetName; - // - Directories + const std::multimap& collisions) const; + void LogBold(const std::string& message) const; + void LogInfo(const std::string& message) const; + void LogWarning(const std::string& message) const; + void LogError(const std::string& message) const; + void LogCommand(const std::vector& command) const; + + // -- Utility + bool NameCollisionTest( + const std::map& genFiles, + std::multimap& collisions) const; + std::string ChecksumedPath(const std::string& sourceFile, + const std::string& basePrefix, + const std::string& baseSuffix) const; + bool MakeParentDirectory(const char* logPrefix, + const std::string& filename) const; + bool FileDiffers(const std::string& filename, const std::string& content); + bool FileWrite(const char* logPrefix, const std::string& filename, + const std::string& content); + + bool RunCommand(const std::vector& command, std::string& output, + bool verbose = true) const; + + bool FindHeader(std::string& header, const std::string& testBasePath) const; + + std::string MocFindHeader(const std::string& sourcePath, + const std::string& includeBase) const; + bool MocFindIncludedFile(std::string& absFile, const std::string& sourceFile, + const std::string& includeString) const; + + // -- Meta + std::string ConfigSuffix; + // -- Directories std::string ProjectSourceDir; std::string ProjectBinaryDir; std::string CurrentSourceDir; std::string CurrentBinaryDir; - std::string AutogenBuildSubDir; - // - Qt environment + std::string AutogenBuildDir; + std::string AutogenIncludeDir; + // -- Qt environment std::string QtMajorVersion; std::string MocExecutable; std::string UicExecutable; std::string RccExecutable; - // - File lists + // -- File lists std::vector Sources; std::vector Headers; - // - Moc - std::vector SkipMoc; - std::string MocCompileDefinitionsStr; - std::string MocIncludesStr; - std::string MocOptionsStr; - std::string OutMocCppFilenameRel; - std::string OutMocCppFilenameAbs; - std::list MocIncludes; - std::list MocDefinitions; + std::vector HeaderExtensions; + cmFilePathChecksum FPathChecksum; + // -- Settings + bool IncludeProjectDirsBefore; + bool Verbose; + bool ColorOutput; + std::string SettingsFile; + std::string SettingsStringMoc; + std::string SettingsStringUic; + std::string SettingsStringRcc; + // -- Moc + bool MocSettingsChanged; + bool MocPredefsChanged; + bool MocRelaxedMode; + bool MocRunFailed; + std::string MocCompFileRel; + std::string MocCompFileAbs; + std::string MocPredefsFileRel; + std::string MocPredefsFileAbs; + std::vector MocSkipList; + std::vector MocIncludePaths; + std::vector MocIncludes; + std::vector MocDefinitions; std::vector MocOptions; - std::string MocSettingsString; - // - Uic - std::vector SkipUic; + std::vector MocPredefsCmd; + std::vector MocDependFilters; + MocMacroFilter MocMacroFilters[2]; + cmsys::RegularExpression MocRegExpInclude; + // -- Uic + bool UicSettingsChanged; + bool UicRunFailed; + std::vector UicSkipList; std::vector UicTargetOptions; std::map UicOptions; - std::string UicSettingsString; - // - Rcc + std::vector UicSearchPaths; + cmsys::RegularExpression UicRegExpInclude; + // -- Rcc + bool RccSettingsChanged; + bool RccRunFailed; std::vector RccSources; std::map RccOptions; std::map > RccInputs; - std::string RccSettingsString; - // - Utility - cmFilePathChecksum fpathCheckSum; - cmsys::RegularExpression RegExpQObject; - cmsys::RegularExpression RegExpQGadget; - cmsys::RegularExpression RegExpMocInclude; - cmsys::RegularExpression RegExpUicInclude; - // - Flags - bool IncludeProjectDirsBefore; - bool Verbose; - bool ColorOutput; - bool RunMocFailed; - bool RunUicFailed; - bool RunRccFailed; - bool GenerateMocAll; - bool GenerateUicAll; - bool GenerateRccAll; - bool MocRelaxedMode; }; #endif diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 355b8c41d..5364f76f4 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -6,8 +6,8 @@ #include "cmSystemTools.h" #include "cmVersion.h" +#include "cmsys/FStream.hxx" #include -#include #include #include #include @@ -80,7 +80,7 @@ void cmRST::ProcessModule(std::istream& is) if (!rst.empty() && rst != "#") { // Bracket mode: check for end bracket std::string::size_type pos = line.find(rst); - if (pos == line.npos) { + if (pos == std::string::npos) { this->ProcessLine(line); } else { if (line[0] != '#') { @@ -96,14 +96,14 @@ void cmRST::ProcessModule(std::istream& is) if (line == "#") { this->ProcessLine(""); continue; - } else if (line.substr(0, 2) == "# ") { - this->ProcessLine(line.substr(2, line.npos)); + } + if (line.substr(0, 2) == "# ") { + this->ProcessLine(line.substr(2)); continue; - } else { - rst = ""; - this->Reset(); - this->OutputLinePending = true; } + rst = ""; + this->Reset(); + this->OutputLinePending = true; } if (line == "#.rst:") { rst = "#"; @@ -156,8 +156,8 @@ void cmRST::ProcessLine(std::string const& line) isspace(line[2]))) { this->Reset(); this->Markup = - (line.find_first_not_of(" \t", 2) == line.npos ? MarkupEmpty - : MarkupNormal); + (line.find_first_not_of(" \t", 2) == std::string::npos ? MarkupEmpty + : MarkupNormal); if (this->CMakeDirective.find(line)) { // Output cmake domain directives and their content normally. this->NormalLine(line); @@ -252,7 +252,7 @@ void cmRST::OutputLine(std::string const& line_in, bool inlineMarkup) // no explicit "(...)" then add "()" to the text. if (this->CMakeRole.match(2) == "command" && this->CMakeRole.match(5).empty() && - text.find_first_of("()") == text.npos) { + text.find_first_of("()") == std::string::npos) { text += "()"; } this->OS << "``" << text << "``"; diff --git a/Source/cmRST.h b/Source/cmRST.h index 2fedf4bfa..d1a8e2711 100644 --- a/Source/cmRST.h +++ b/Source/cmRST.h @@ -3,9 +3,9 @@ #ifndef _cmRST_h #define _cmRST_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep -#include +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx index 5a5292765..1db84414a 100644 --- a/Source/cmRemoveCommand.cxx +++ b/Source/cmRemoveCommand.cxx @@ -15,7 +15,7 @@ bool cmRemoveCommand::InitialPass(std::vector const& args, return true; } - const char* variable = args[0].c_str(); // VAR is always first + std::string const& variable = args[0]; // VAR is always first // get the old value const char* cacheValue = this->Makefile->GetDefinition(variable); diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h index c935f2870..f2e89f6e1 100644 --- a/Source/cmRemoveCommand.h +++ b/Source/cmRemoveCommand.h @@ -3,7 +3,8 @@ #ifndef cmRemoveCommand_h #define cmRemoveCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "remove"; } }; #endif diff --git a/Source/cmRemoveDefinitionsCommand.h b/Source/cmRemoveDefinitionsCommand.h index 2bcc12dd7..9a9a5d535 100644 --- a/Source/cmRemoveDefinitionsCommand.h +++ b/Source/cmRemoveDefinitionsCommand.h @@ -3,7 +3,8 @@ #ifndef cmRemoveDefinitionsCommand_h #define cmRemoveDefinitionsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "remove_definitions"; } }; #endif diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx index f8b31294d..ceea8b4d9 100644 --- a/Source/cmReturnCommand.cxx +++ b/Source/cmReturnCommand.cxx @@ -8,6 +8,6 @@ bool cmReturnCommand::InitialPass(std::vector const&, cmExecutionStatus& status) { - status.SetReturnInvoked(true); + status.SetReturnInvoked(); return true; } diff --git a/Source/cmReturnCommand.h b/Source/cmReturnCommand.h index 9496d67a3..87900e7e9 100644 --- a/Source/cmReturnCommand.h +++ b/Source/cmReturnCommand.h @@ -3,7 +3,8 @@ #ifndef cmReturnCommand_h #define cmReturnCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "return"; } }; #endif diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index f190a5c35..a71861af7 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -12,10 +12,11 @@ cmRulePlaceholderExpander::cmRulePlaceholderExpander( std::map const& compilers, std::map const& variableMappings, - std::string const& compilerSysroot) + std::string const& compilerSysroot, std::string const& linkerSysroot) : Compilers(compilers) , VariableMappings(variableMappings) , CompilerSysroot(compilerSysroot) + , LinkerSysroot(linkerSysroot) { } @@ -154,7 +155,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( // Strip the last extension off the target name. std::string targetBase = replaceValues.Target; std::string::size_type pos = targetBase.rfind('.'); - if (pos != targetBase.npos) { + if (pos != std::string::npos) { return targetBase.substr(0, pos); } return targetBase; @@ -249,10 +250,19 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( ret += compilerOptionExternalToolchain; ret += outputConverter->EscapeForShell(compilerExternalToolchain, true); } - if (!this->CompilerSysroot.empty() && !compilerOptionSysroot.empty()) { + std::string sysroot; + // Some platforms may use separate sysroots for compiling and linking. + // If we detect link flags, then we pass the link sysroot instead. + // FIXME: Use a more robust way to detect link line expansion. + if (replaceValues.LinkFlags) { + sysroot = this->LinkerSysroot; + } else { + sysroot = this->CompilerSysroot; + } + if (!sysroot.empty() && !compilerOptionSysroot.empty()) { ret += " "; ret += compilerOptionSysroot; - ret += outputConverter->EscapeForShell(this->CompilerSysroot, true); + ret += outputConverter->EscapeForShell(sysroot, true); } return ret; } @@ -260,7 +270,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable( std::map::iterator mapIt = this->VariableMappings.find(variable); if (mapIt != this->VariableMappings.end()) { - if (variable.find("_FLAG") == variable.npos) { + if (variable.find("_FLAG") == std::string::npos) { return outputConverter->ConvertToOutputForExisting(mapIt->second); } return mapIt->second; @@ -274,15 +284,15 @@ void cmRulePlaceholderExpander::ExpandRuleVariables( { std::string::size_type start = s.find('<'); // no variables to expand - if (start == s.npos) { + if (start == std::string::npos) { return; } std::string::size_type pos = 0; std::string expandedInput; - while (start != s.npos && start < s.size() - 2) { + while (start != std::string::npos && start < s.size() - 2) { std::string::size_type end = s.find('>', start); // if we find a < with no > we are done - if (end == s.npos) { + if (end == std::string::npos) { return; } char c = s[start + 1]; diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index 83291664a..7b19210d3 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -4,7 +4,7 @@ #ifndef cmRulePlaceholderExpander_h #define cmRulePlaceholderExpander_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -17,7 +17,7 @@ public: cmRulePlaceholderExpander( std::map const& compilers, std::map const& variableMappings, - std::string const& compilerSysroot); + std::string const& compilerSysroot, std::string const& linkerSysroot); void SetTargetImpLib(std::string const& targetImpLib) { @@ -76,6 +76,7 @@ private: std::map Compilers; std::map VariableMappings; std::string CompilerSysroot; + std::string LinkerSysroot; }; #endif diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx index 4c5ab64f7..753a1ba6f 100644 --- a/Source/cmScriptGenerator.cxx +++ b/Source/cmScriptGenerator.cxx @@ -4,8 +4,6 @@ #include "cmSystemTools.h" -#include - cmScriptGenerator::cmScriptGenerator( const std::string& config_var, std::vector const& configurations) @@ -90,8 +88,7 @@ void cmScriptGenerator::GenerateScript(std::ostream& os) this->GenerateScriptConfigs(os, indent); } -void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os, - Indent const& indent) +void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent) { if (this->ActionsPerConfig) { this->GenerateScriptActionsPerConfig(os, indent); @@ -100,8 +97,7 @@ void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os, } } -void cmScriptGenerator::GenerateScriptActions(std::ostream& os, - Indent const& indent) +void cmScriptGenerator::GenerateScriptActions(std::ostream& os, Indent indent) { if (this->ActionsPerConfig) { // This is reached for single-configuration build generators in a @@ -112,7 +108,7 @@ void cmScriptGenerator::GenerateScriptActions(std::ostream& os, void cmScriptGenerator::GenerateScriptForConfig(std::ostream& /*unused*/, const std::string& /*unused*/, - Indent const& /*unused*/) + Indent /*unused*/) { // No actions for this generator. } @@ -138,7 +134,7 @@ bool cmScriptGenerator::GeneratesForConfig(const std::string& config) } void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os, - Indent const& indent) + Indent indent) { if (this->Configurations.empty()) { // This rule is for all configurations. @@ -153,7 +149,7 @@ void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os, } void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os, - Indent const& indent) + Indent indent) { if (this->ConfigurationTypes->empty()) { // In a single-configuration generator there is only one action diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h index a8f6fae9f..d0879c687 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -3,7 +3,7 @@ #ifndef cmScriptGenerator_h #define cmScriptGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include #include @@ -35,7 +35,7 @@ private: int Level; }; inline std::ostream& operator<<(std::ostream& os, - cmScriptGeneratorIndent const& indent) + cmScriptGeneratorIndent indent) { indent.Write(os); return os; @@ -47,6 +47,8 @@ inline std::ostream& operator<<(std::ostream& os, */ class cmScriptGenerator { + CM_DISABLE_COPY(cmScriptGenerator) + public: cmScriptGenerator(const std::string& config_var, std::vector const& configurations); @@ -58,12 +60,12 @@ public: protected: typedef cmScriptGeneratorIndent Indent; virtual void GenerateScript(std::ostream& os); - virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent); - virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); + virtual void GenerateScriptConfigs(std::ostream& os, Indent indent); + virtual void GenerateScriptActions(std::ostream& os, Indent indent); virtual void GenerateScriptForConfig(std::ostream& os, const std::string& config, - Indent const& indent); - virtual void GenerateScriptNoConfig(std::ostream&, Indent const&) {} + Indent indent); + virtual void GenerateScriptNoConfig(std::ostream&, Indent) {} virtual bool NeedsScriptNoConfig() const { return false; } // Test if this generator does something for a given configuration. @@ -87,8 +89,8 @@ protected: bool ActionsPerConfig; private: - void GenerateScriptActionsOnce(std::ostream& os, Indent const& indent); - void GenerateScriptActionsPerConfig(std::ostream& os, Indent const& indent); + void GenerateScriptActionsOnce(std::ostream& os, Indent indent); + void GenerateScriptActionsPerConfig(std::ostream& os, Indent indent); }; #endif diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h index 9ffa87125..932022aa1 100644 --- a/Source/cmSearchPath.h +++ b/Source/cmSearchPath.h @@ -3,7 +3,7 @@ #ifndef cmSearchPath_h #define cmSearchPath_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx index b27d227f3..7b222a041 100644 --- a/Source/cmSeparateArgumentsCommand.cxx +++ b/Source/cmSeparateArgumentsCommand.cxx @@ -40,6 +40,13 @@ bool cmSeparateArgumentsCommand::InitialPass( if (doing == DoingVariable) { var = args[i]; doing = DoingMode; + } else if (doing == DoingMode && args[i] == "NATIVE_COMMAND") { +#ifdef _WIN32 + mode = ModeWindows; +#else + mode = ModeUnix; +#endif + doing = DoingCommand; } else if (doing == DoingMode && args[i] == "UNIX_COMMAND") { mode = ModeUnix; doing = DoingCommand; diff --git a/Source/cmSeparateArgumentsCommand.h b/Source/cmSeparateArgumentsCommand.h index 1cbf56e79..6bf8549cf 100644 --- a/Source/cmSeparateArgumentsCommand.h +++ b/Source/cmSeparateArgumentsCommand.h @@ -3,7 +3,8 @@ #ifndef cmSeparateArgumentsCommand_h #define cmSeparateArgumentsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "separate_arguments"; } }; #endif diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 5a71dc01f..7fc6ed755 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -6,18 +6,15 @@ #include "cmServerDictionary.h" #include "cmServerProtocol.h" #include "cmSystemTools.h" -#include "cmVersionMacros.h" -#include "cmake.h" - -#if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_jsoncpp_reader.h" -#include "cm_jsoncpp_value.h" -#endif +#include "cm_jsoncpp_writer.h" +#include "cmake.h" +#include "cmsys/FStream.hxx" #include -#include -#include -#include +#include +#include +#include class cmServer::DebugInfo { @@ -150,7 +147,7 @@ void cmServer::reportProgress(const char* msg, float progress, void* data) { const cmServerRequest* request = static_cast(data); assert(request); - if (progress < 0.0 || progress > 1.0) { + if (progress < 0.0f || progress > 1.0f) { request->ReportMessage(msg, ""); } else { request->ReportProgress(0, static_cast(progress * 1000), 1000, msg); @@ -270,10 +267,8 @@ void cmServer::WriteJsonObject(const Json::Value& jsonValue, } if (!debug->OutputFile.empty()) { - std::ofstream myfile; - myfile.open(debug->OutputFile); + cmsys::ofstream myfile(debug->OutputFile.c_str()); myfile << result; - myfile.close(); } } diff --git a/Source/cmServer.h b/Source/cmServer.h index 7f29e3221..b8140504c 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -2,13 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once -#include "cmListFileCache.h" -#include "cmState.h" +#include "cmConfigure.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_jsoncpp_value.h" #include "cm_uv.h" -#endif #include #include @@ -21,6 +18,8 @@ class cmServerResponse; class cmServer { + CM_DISABLE_COPY(cmServer) + public: class DebugInfo; diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx index 008052b24..36312edf4 100644 --- a/Source/cmServerConnection.cxx +++ b/Source/cmServerConnection.cxx @@ -2,10 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmServerConnection.h" -#include "cmServerDictionary.h" - #include "cmFileMonitor.h" #include "cmServer.h" +#include "cmServerDictionary.h" #include #include diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h index 3efe28d02..b96bf3c54 100644 --- a/Source/cmServerConnection.h +++ b/Source/cmServerConnection.h @@ -2,19 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once -#include -#include +#include "cmConfigure.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_uv.h" -#endif -class cmServer; +#include + class cmFileMonitor; -class LoopGuard; +class cmServer; class cmServerConnection { + CM_DISABLE_COPY(cmServerConnection) + public: cmServerConnection(); virtual ~cmServerConnection(); diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index a5c1a23e1..defba7726 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -4,27 +4,32 @@ #include "cmExternalMakefileProjectGenerator.h" #include "cmFileMonitor.h" +#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkLineComputer.h" -#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmServer.h" #include "cmServerDictionary.h" #include "cmSourceFile.h" +#include "cmState.h" +#include "cmStateDirectory.h" +#include "cmStateSnapshot.h" +#include "cmStateTypes.h" #include "cmSystemTools.h" +#include "cm_uv.h" #include "cmake.h" -#include "cmServerDictionary.h" - -#if defined(CMAKE_BUILD_WITH_CMAKE) -#include "cm_jsoncpp_reader.h" -#include "cm_jsoncpp_value.h" -#endif - #include +#include +#include +#include +#include +#include +#include #include +#include #include // Get rid of some windows macros: @@ -50,9 +55,8 @@ std::vector getConfigurations(const cmake* cm) bool hasString(const Json::Value& v, const std::string& s) { return !v.isNull() && - std::find_if(v.begin(), v.end(), [s](const Json::Value& i) { - return i.asString() == s; - }) != v.end(); + std::any_of(v.begin(), v.end(), + [s](const Json::Value& i) { return i.asString() == s; }); } template @@ -211,7 +215,7 @@ bool cmServerProtocol::Activate(cmServer* server, { assert(server); this->m_Server = server; - this->m_CMakeInstance = std::make_unique(); + this->m_CMakeInstance = std::make_unique(cmake::RoleProject); const bool result = this->DoActivate(request, errorMessage); if (!result) { this->m_CMakeInstance = CM_NULLPTR; @@ -493,16 +497,14 @@ cmServerResponse cmServerProtocol1_0::ProcessCache( if (keys.empty()) { keys = allKeys; } else { - for (auto i : keys) { - if (std::find_if(allKeys.begin(), allKeys.end(), - [i](const std::string& j) { return i == j; }) == - allKeys.end()) { + for (const auto& i : keys) { + if (std::find(allKeys.begin(), allKeys.end(), i) == allKeys.end()) { return request.ReportError("Key \"" + i + "\" not found in cache."); } } } std::sort(keys.begin(), keys.end()); - for (auto key : keys) { + for (const auto& key : keys) { Json::Value entry = Json::objectValue; entry[kKEY_KEY] = key; entry[kTYPE_KEY] = @@ -511,7 +513,7 @@ cmServerResponse cmServerProtocol1_0::ProcessCache( Json::Value props = Json::objectValue; bool haveProperties = false; - for (auto prop : state->GetCacheEntryPropertyList(key)) { + for (const auto& prop : state->GetCacheEntryPropertyList(key)) { haveProperties = true; props[prop] = state->GetCacheEntryProperty(key, prop); } @@ -598,7 +600,7 @@ bool LanguageData::operator==(const LanguageData& other) const void LanguageData::SetDefines(const std::set& defines) { std::vector result; - for (auto i : defines) { + for (const auto& i : defines) { result.push_back(i); } std::sort(result.begin(), result.end()); @@ -615,11 +617,11 @@ struct hash using std::hash; size_t result = hash()(in.Language) ^ hash()(in.Flags); - for (auto i : in.IncludePathList) { + for (const auto& i : in.IncludePathList) { result = result ^ (hash()(i.first) ^ (i.second ? std::numeric_limits::max() : 0)); } - for (auto i : in.Defines) { + for (const auto& i : in.Defines) { result = result ^ hash()(i); } result = @@ -643,7 +645,7 @@ static Json::Value DumpSourceFileGroup(const LanguageData& data, } if (!data.IncludePathList.empty()) { Json::Value includes = Json::arrayValue; - for (auto i : data.IncludePathList) { + for (const auto& i : data.IncludePathList) { Json::Value tmp = Json::objectValue; tmp[kPATH_KEY] = i.first; if (i.second) { @@ -661,7 +663,7 @@ static Json::Value DumpSourceFileGroup(const LanguageData& data, result[kIS_GENERATED_KEY] = data.IsGenerated; Json::Value sourcesValue = Json::arrayValue; - for (auto i : files) { + for (const auto& i : files) { const std::string relPath = cmSystemTools::RelativePath(baseDir.c_str(), i.c_str()); sourcesValue.append(relPath.size() < i.size() ? relPath : i); @@ -763,9 +765,11 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, if (target->HaveWellDefinedOutputFiles()) { Json::Value artifacts = Json::arrayValue; - artifacts.append(target->GetFullPath(config, false)); + artifacts.append( + target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact)); if (target->IsDLLPlatform()) { - artifacts.append(target->GetFullPath(config, true)); + artifacts.append( + target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); const cmGeneratorTarget::OutputInfo* output = target->GetOutputInfo(config); if (output && !output->PdbDir.empty()) { @@ -817,7 +821,7 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, std::set languages; target->GetLanguages(languages, config); std::map languageDataMap; - for (auto lang : languages) { + for (const auto& lang : languages) { LanguageData& ld = languageDataMap[lang]; ld.Language = lang; lg->GetTargetCompileFlags(target, config, lang, ld.Flags); @@ -1093,7 +1097,7 @@ cmServerResponse cmServerProtocol1_0::ProcessSetGlobalSettings( kWARN_UNINITIALIZED_KEY, kWARN_UNUSED_KEY, kWARN_UNUSED_CLI_KEY, kCHECK_SYSTEM_VARS_KEY }; - for (auto i : boolValues) { + for (const auto& i : boolValues) { if (!request.Data[i].isNull() && !request.Data[i].isBool()) { return request.ReportError("\"" + i + "\" must be unset or a bool value."); diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 027f14571..83b3d58de 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -2,20 +2,17 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once -#include "cmListFileCache.h" -#include "cmake.h" +#include "cmConfigure.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) -#include "cm_jsoncpp_writer.h" -#endif +#include "cm_jsoncpp_value.h" +#include "cmake.h" #include #include +#include -class cmake; class cmFileMonitor; class cmServer; - class cmServerRequest; class cmServerResponse @@ -72,8 +69,11 @@ private: class cmServerProtocol { + CM_DISABLE_COPY(cmServerProtocol) + public: - virtual ~cmServerProtocol() {} + cmServerProtocol() = default; + virtual ~cmServerProtocol() = default; virtual std::pair ProtocolVersion() const = 0; virtual bool IsExperimental() const = 0; diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h index 190092acc..c0858b15b 100644 --- a/Source/cmSetCommand.h +++ b/Source/cmSetCommand.h @@ -3,7 +3,8 @@ #ifndef cmSetCommand_h #define cmSetCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "set"; } }; #endif diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h index 854ad4374..8832b3389 100644 --- a/Source/cmSetDirectoryPropertiesCommand.h +++ b/Source/cmSetDirectoryPropertiesCommand.h @@ -3,7 +3,8 @@ #ifndef cmSetDirectoryPropertiesCommand_h #define cmSetDirectoryPropertiesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -27,19 +28,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "set_directory_properties"; - } - /** * Static entry point for use by other commands */ diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 60c198a91..b57f62a50 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -138,7 +138,7 @@ bool cmSetPropertyCommand::HandleGlobalMode() // Set or append the property. cmake* cm = this->Makefile->GetCMakeInstance(); - const char* name = this->PropertyName.c_str(); + std::string const& name = this->PropertyName; const char* value = this->PropertyValue.c_str(); if (this->Remove) { value = CM_NULLPTR; @@ -188,7 +188,7 @@ bool cmSetPropertyCommand::HandleDirectoryMode() } // Set or append the property. - const char* name = this->PropertyName.c_str(); + std::string const& name = this->PropertyName; const char* value = this->PropertyValue.c_str(); if (this->Remove) { value = CM_NULLPTR; @@ -229,7 +229,7 @@ bool cmSetPropertyCommand::HandleTargetMode() bool cmSetPropertyCommand::HandleTarget(cmTarget* target) { // Set or append the property. - const char* name = this->PropertyName.c_str(); + std::string const& name = this->PropertyName; const char* value = this->PropertyValue.c_str(); if (this->Remove) { value = CM_NULLPTR; @@ -268,7 +268,7 @@ bool cmSetPropertyCommand::HandleSourceMode() bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf) { // Set or append the property. - const char* name = this->PropertyName.c_str(); + std::string const& name = this->PropertyName; const char* value = this->PropertyValue.c_str(); if (this->Remove) { value = CM_NULLPTR; @@ -316,7 +316,7 @@ bool cmSetPropertyCommand::HandleTestMode() bool cmSetPropertyCommand::HandleTest(cmTest* test) { // Set or append the property. - const char* name = this->PropertyName.c_str(); + std::string const& name = this->PropertyName; const char* value = this->PropertyValue.c_str(); if (this->Remove) { value = CM_NULLPTR; @@ -383,7 +383,7 @@ bool cmSetPropertyCommand::HandleCacheMode() bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey) { // Set or append the property. - const char* name = this->PropertyName.c_str(); + std::string const& name = this->PropertyName; const char* value = this->PropertyValue.c_str(); cmState* state = this->Makefile->GetState(); if (this->Remove) { diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h index fd7c922ab..08158244a 100644 --- a/Source/cmSetPropertyCommand.h +++ b/Source/cmSetPropertyCommand.h @@ -3,7 +3,8 @@ #ifndef cmSetsPropertiesCommand_h #define cmSetsPropertiesCommand_h -#include +#include "cmConfigure.h" + #include #include #include @@ -30,16 +31,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "set_property"; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - private: std::set Names; std::string PropertyName; diff --git a/Source/cmSetSourceFilesPropertiesCommand.h b/Source/cmSetSourceFilesPropertiesCommand.h index 8fa12c780..2e22dc9ef 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.h +++ b/Source/cmSetSourceFilesPropertiesCommand.h @@ -3,7 +3,8 @@ #ifndef cmSetSourceFilesPropertiesCommand_h #define cmSetSourceFilesPropertiesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -27,14 +28,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "set_source_files_properties"; - } - static bool RunCommand(cmMakefile* mf, std::vector::const_iterator filebeg, std::vector::const_iterator fileend, diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index da2697231..642591337 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -32,9 +32,8 @@ bool cmSetTargetPropertiesCommand::InitialPass( } propertyPairs.insert(propertyPairs.end(), j, args.end()); break; - } else { - numFiles++; } + numFiles++; } if (propertyPairs.empty()) { this->SetError("called with illegal arguments, maybe missing " diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h index c3c0d06cf..425618157 100644 --- a/Source/cmSetTargetPropertiesCommand.h +++ b/Source/cmSetTargetPropertiesCommand.h @@ -3,7 +3,8 @@ #ifndef cmSetTargetsPropertiesCommand_h #define cmSetTargetsPropertiesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -24,11 +25,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "set_target_properties"; } - /** * Used by this command and cmSetPropertiesCommand */ diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx index 4fd379fba..e27c675c6 100644 --- a/Source/cmSetTestsPropertiesCommand.cxx +++ b/Source/cmSetTestsPropertiesCommand.cxx @@ -32,9 +32,8 @@ bool cmSetTestsPropertiesCommand::InitialPass( } propertyPairs.insert(propertyPairs.end(), j, args.end()); break; - } else { - numFiles++; } + numFiles++; } if (propertyPairs.empty()) { this->SetError("called with illegal arguments, maybe " diff --git a/Source/cmSetTestsPropertiesCommand.h b/Source/cmSetTestsPropertiesCommand.h index 45aed792c..90f004c34 100644 --- a/Source/cmSetTestsPropertiesCommand.h +++ b/Source/cmSetTestsPropertiesCommand.h @@ -3,7 +3,8 @@ #ifndef cmSetTestsPropertiesCommand_h #define cmSetTestsPropertiesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -24,11 +25,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "set_tests_properties"; } - static bool SetOneTest(const std::string& tname, std::vector& propertyPairs, cmMakefile* mf, std::string& errors); diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index 4322a6d28..7eace268f 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSiteNameCommand.h" -#include +#include "cmsys/RegularExpression.hxx" #include "cmMakefile.h" #include "cmStateTypes.h" diff --git a/Source/cmSiteNameCommand.h b/Source/cmSiteNameCommand.h index 01023b96e..6c65480ed 100644 --- a/Source/cmSiteNameCommand.h +++ b/Source/cmSiteNameCommand.h @@ -3,7 +3,8 @@ #ifndef cmSiteNameCommand_h #define cmSiteNameCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "site_name"; } }; #endif diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index bbcc3006b..0be659c5f 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -3,7 +3,7 @@ #ifndef cmSourceFile_h #define cmSourceFile_h -#include +#include "cmConfigure.h" #include "cmPropertyMap.h" #include "cmSourceFileLocation.h" diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index 4e0880e93..86711d784 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceFileLocation.h" -#include +#include "cmConfigure.h" #include "cmAlgorithms.h" #include "cmGlobalGenerator.h" diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h index aa2e6c768..6dbc2daed 100644 --- a/Source/cmSourceFileLocation.h +++ b/Source/cmSourceFileLocation.h @@ -3,7 +3,7 @@ #ifndef cmSourceFileLocation_h #define cmSourceFileLocation_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index 545da8192..97affed6e 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -3,9 +3,9 @@ #ifndef cmSourceGroup_h #define cmSourceGroup_h -#include +#include "cmConfigure.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index 555519908..a966300c0 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -2,7 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceGroupCommand.h" +#include #include +#include #include "cmMakefile.h" #include "cmSourceGroup.h" @@ -12,7 +14,7 @@ namespace { const size_t RootIndex = 1; const size_t FilesWithoutPrefixKeywordIndex = 2; const size_t FilesWithPrefixKeywordIndex = 4; -const size_t PrefixKeywordIdex = 2; +const size_t PrefixKeywordIndex = 2; std::vector tokenizePath(const std::string& path) { @@ -34,21 +36,31 @@ std::string getFullFilePath(const std::string& currentPath, } std::set getSourceGroupFilesPaths( - const std::string& currentPath, const std::string& root, - const std::vector& files) + const std::string& root, const std::vector& files) { std::set ret; const std::string::size_type rootLength = root.length(); for (size_t i = 0; i < files.size(); ++i) { - const std::string fullPath = getFullFilePath(currentPath, files[i]); - - ret.insert(fullPath.substr(rootLength + 1)); // +1 to also omnit last '/' + ret.insert(files[i].substr(rootLength + 1)); // +1 to also omnit last '/' } return ret; } +bool rootIsPrefix(const std::string& root, + const std::vector& files, std::string& error) +{ + for (size_t i = 0; i < files.size(); ++i) { + if (!cmSystemTools::StringStartsWith(files[i], root.c_str())) { + error = "ROOT: " + root + " is not a prefix of file: " + files[i]; + return false; + } + } + + return true; +} + cmSourceGroup* addSourceGroup(const std::vector& tokenizedPath, cmMakefile& makefile) { @@ -66,7 +78,31 @@ cmSourceGroup* addSourceGroup(const std::vector& tokenizedPath, return sg; } -bool addFilesToItsSourceGroups(const std::set& sgFilesPaths, +std::string prepareFilePathForTree(const std::string& path, + const std::string& currentSourceDir) +{ + if (!cmSystemTools::FileIsFullPath(path)) { + return cmSystemTools::CollapseFullPath(currentSourceDir + "/" + path); + } + return cmSystemTools::CollapseFullPath(path); +} + +std::vector prepareFilesPathsForTree( + std::vector::const_iterator begin, + std::vector::const_iterator end, + const std::string& currentSourceDir) +{ + std::vector prepared; + + for (; begin != end; ++begin) { + prepared.push_back(prepareFilePathForTree(*begin, currentSourceDir)); + } + + return prepared; +} + +bool addFilesToItsSourceGroups(const std::string& root, + const std::set& sgFilesPaths, const std::string& prefix, cmMakefile& makefile, std::string& errorMsg) { @@ -91,8 +127,7 @@ bool addFilesToItsSourceGroups(const std::set& sgFilesPaths, errorMsg = "Could not create source group for file: " + *it; return false; } - const std::string fullPath = - getFullFilePath(makefile.GetCurrentSourceDirectory(), *it); + const std::string fullPath = getFullFilePath(root, *it); sg->AddGroupFile(fullPath); } } @@ -201,13 +236,13 @@ bool cmSourceGroupCommand::checkTreeArgumentsPreconditions( } if (args[FilesWithoutPrefixKeywordIndex] != "FILES" && - args[PrefixKeywordIdex] != "PREFIX") { + args[PrefixKeywordIndex] != "PREFIX") { errorMsg = "Unknown argument \"" + args[2] + "\". Perhaps the FILES keyword is missing.\n"; return false; } - if (args[PrefixKeywordIdex] == "PREFIX" && + if (args[PrefixKeywordIndex] == "PREFIX" && (args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) { errorMsg = "Missing FILES arguments."; return false; @@ -226,22 +261,24 @@ bool cmSourceGroupCommand::processTree(const std::vector& args, const std::string root = cmSystemTools::CollapseFullPath(args[RootIndex]); std::string prefix; size_t filesBegin = FilesWithoutPrefixKeywordIndex + 1; - if (args[PrefixKeywordIdex] == "PREFIX") { - prefix = args[PrefixKeywordIdex + 1]; + if (args[PrefixKeywordIndex] == "PREFIX") { + prefix = args[PrefixKeywordIndex + 1]; filesBegin = FilesWithPrefixKeywordIndex + 1; } - const std::vector filesVector(args.begin() + filesBegin, - args.end()); + const std::vector filesVector = + prepareFilesPathsForTree(args.begin() + filesBegin, args.end(), + this->Makefile->GetCurrentSourceDirectory()); - std::set sourceGroupPaths = getSourceGroupFilesPaths( - this->Makefile->GetCurrentSourceDirectory(), root, filesVector); + if (!rootIsPrefix(root, filesVector, errorMsg)) { + return false; + } - addFilesToItsSourceGroups(sourceGroupPaths, prefix, *(this->Makefile), - errorMsg); + std::set sourceGroupPaths = + getSourceGroupFilesPaths(root, filesVector); - if (!errorMsg.empty()) { - this->SetError(errorMsg); + if (!addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, + *(this->Makefile), errorMsg)) { return false; } diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h index 55490963e..7d56b0d65 100644 --- a/Source/cmSourceGroupCommand.h +++ b/Source/cmSourceGroupCommand.h @@ -3,7 +3,8 @@ #ifndef cmSourceGroupCommand_h #define cmSourceGroupCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "source_group"; } - private: bool processTree(const std::vector& args, std::string& errorMsg); diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h deleted file mode 100644 index a2047af9c..000000000 --- a/Source/cmStandardIncludes.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/** - * Include header files as a function of the build process, compiler, - * and operating system. - */ -#ifndef cmStandardIncludes_h -#define cmStandardIncludes_h - -#include - -// Provide fixed-size integer types. -#include - -#include -#include -#include -#include - -// we must have stl with the standard include style -#include -#include -#include -#include -#include -#include -#include - -// include the "c" string header -#include -#include -#include - -#if defined(_MSC_VER) -typedef unsigned short mode_t; -#else -#include -#endif - -// use this class to shrink the size of symbols in .o files -// std::string is really basic_string<....lots of stuff....> -// when combined with a map or set, the symbols can be > 2000 chars! -#include -// typedef cmsys::String std::string; - -/* Poison this operator to avoid common mistakes. */ -extern void operator<<(std::ostream&, const std::ostringstream&); - -#include "cmCustomCommandLines.h" -#include "cmDocumentationEntry.h" -#include "cmTargetLinkLibraryType.h" - -#endif diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h index b9adee5bc..c9f42e4ce 100644 --- a/Source/cmStandardLexer.h +++ b/Source/cmStandardLexer.h @@ -3,7 +3,7 @@ #ifndef cmStandardLexer_h #define cmStandardLexer_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep /* Disable some warnings. */ #if defined(_MSC_VER) @@ -50,7 +50,7 @@ #define YY_NO_UNPUT 1 #define ECHO -#include +#include "cm_kwiml.h" typedef KWIML_INT_int8_t flex_int8_t; typedef KWIML_INT_uint8_t flex_uint8_t; typedef KWIML_INT_int16_t flex_int16_t; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 18d5ea192..92e47f748 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmState.h" +#include "cmsys/RegularExpression.hxx" #include #include -#include #include #include @@ -12,14 +12,17 @@ #include "cmCacheManager.h" #include "cmCommand.h" #include "cmDefinitions.h" +#include "cmDisallowedCommand.h" #include "cmListFileCache.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" +#include "cmUnexpectedCommand.h" #include "cmake.h" cmState::cmState() : IsInTryCompile(false) + , IsGeneratorMultiConfig(false) , WindowsShell(false) , WindowsVSIDE(false) , WatcomWMake(false) @@ -33,7 +36,8 @@ cmState::cmState() cmState::~cmState() { delete this->CacheManager; - cmDeleteAll(this->Commands); + cmDeleteAll(this->BuiltinCommands); + cmDeleteAll(this->ScriptedCommands); } const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType) @@ -364,99 +368,102 @@ void cmState::SetIsInTryCompile(bool b) this->IsInTryCompile = b; } -void cmState::RenameCommand(std::string const& oldName, - std::string const& newName) +bool cmState::GetIsGeneratorMultiConfig() const { - // if the command already exists, free the old one - std::string sOldName = cmSystemTools::LowerCase(oldName); - std::string sNewName = cmSystemTools::LowerCase(newName); - std::map::iterator pos = - this->Commands.find(sOldName); - if (pos == this->Commands.end()) { - return; - } - cmCommand* cmd = pos->second; + return this->IsGeneratorMultiConfig; +} - pos = this->Commands.find(sNewName); - if (pos != this->Commands.end()) { - delete pos->second; - this->Commands.erase(pos); - } - this->Commands.insert(std::make_pair(sNewName, cmd)); - pos = this->Commands.find(sOldName); - this->Commands.erase(pos); +void cmState::SetIsGeneratorMultiConfig(bool b) +{ + this->IsGeneratorMultiConfig = b; } -void cmState::AddCommand(cmCommand* command) +void cmState::AddBuiltinCommand(std::string const& name, cmCommand* command) { - std::string name = cmSystemTools::LowerCase(command->GetName()); - // if the command already exists, free the old one - std::map::iterator pos = this->Commands.find(name); - if (pos != this->Commands.end()) { - delete pos->second; - this->Commands.erase(pos); - } - this->Commands.insert(std::make_pair(name, command)); + assert(name == cmSystemTools::LowerCase(name)); + assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end()); + this->BuiltinCommands.insert(std::make_pair(name, command)); +} + +void cmState::AddDisallowedCommand(std::string const& name, cmCommand* command, + cmPolicies::PolicyID policy, + const char* message) +{ + this->AddBuiltinCommand(name, + new cmDisallowedCommand(command, policy, message)); +} + +void cmState::AddUnexpectedCommand(std::string const& name, const char* error) +{ + this->AddBuiltinCommand(name, new cmUnexpectedCommand(name, error)); } -void cmState::RemoveUnscriptableCommands() +void cmState::AddScriptedCommand(std::string const& name, cmCommand* command) { - std::vector unscriptableCommands; - for (std::map::iterator pos = - this->Commands.begin(); - pos != this->Commands.end();) { - if (!pos->second->IsScriptable()) { + std::string sName = cmSystemTools::LowerCase(name); + + // if the command already exists, give a new name to the old command. + if (cmCommand* oldCmd = this->GetCommand(sName)) { + std::string const newName = "_" + sName; + std::map::iterator pos = + this->ScriptedCommands.find(newName); + if (pos != this->ScriptedCommands.end()) { delete pos->second; - this->Commands.erase(pos++); - } else { - ++pos; + this->ScriptedCommands.erase(pos); } + this->ScriptedCommands.insert(std::make_pair(newName, oldCmd->Clone())); + } + + // if the command already exists, free the old one + std::map::iterator pos = + this->ScriptedCommands.find(sName); + if (pos != this->ScriptedCommands.end()) { + delete pos->second; + this->ScriptedCommands.erase(pos); } + this->ScriptedCommands.insert(std::make_pair(sName, command)); } cmCommand* cmState::GetCommand(std::string const& name) const { - cmCommand* command = CM_NULLPTR; std::string sName = cmSystemTools::LowerCase(name); - std::map::const_iterator pos = - this->Commands.find(sName); - if (pos != this->Commands.end()) { - command = (*pos).second; + std::map::const_iterator pos; + pos = this->ScriptedCommands.find(sName); + if (pos != this->ScriptedCommands.end()) { + return pos->second; } - return command; + pos = this->BuiltinCommands.find(sName); + if (pos != this->BuiltinCommands.end()) { + return pos->second; + } + return CM_NULLPTR; } std::vector cmState::GetCommandNames() const { std::vector commandNames; - commandNames.reserve(this->Commands.size()); - std::map::const_iterator cmds = - this->Commands.begin(); - for (; cmds != this->Commands.end(); ++cmds) { + commandNames.reserve(this->BuiltinCommands.size() + + this->ScriptedCommands.size()); + for (std::map::const_iterator cmds = + this->BuiltinCommands.begin(); + cmds != this->BuiltinCommands.end(); ++cmds) { + commandNames.push_back(cmds->first); + } + for (std::map::const_iterator cmds = + this->ScriptedCommands.begin(); + cmds != this->ScriptedCommands.end(); ++cmds) { commandNames.push_back(cmds->first); } + std::sort(commandNames.begin(), commandNames.end()); + commandNames.erase(std::unique(commandNames.begin(), commandNames.end()), + commandNames.end()); return commandNames; } void cmState::RemoveUserDefinedCommands() { - std::vector renamedCommands; - for (std::map::iterator j = this->Commands.begin(); - j != this->Commands.end();) { - if (j->second->IsUserDefined()) { - delete j->second; - this->Commands.erase(j++); - } else if (j->first != j->second->GetName()) { - renamedCommands.push_back(j->second); - this->Commands.erase(j++); - } else { - ++j; - } - } - for (std::vector::const_iterator it = renamedCommands.begin(); - it != renamedCommands.end(); ++it) { - this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it; - } + cmDeleteAll(this->ScriptedCommands); + this->ScriptedCommands.clear(); } void cmState::SetGlobalProperty(const std::string& prop, const char* value) @@ -481,6 +488,9 @@ const char* cmState::GetGlobalProperty(const std::string& prop) } else if (prop == "IN_TRY_COMPILE") { this->SetGlobalProperty("IN_TRY_COMPILE", this->IsInTryCompile ? "1" : "0"); + } else if (prop == "GENERATOR_IS_MULTI_CONFIG") { + this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG", + this->IsGeneratorMultiConfig ? "1" : "0"); } else if (prop == "ENABLED_LANGUAGES") { std::string langs; langs = cmJoin(this->EnabledLanguages, ";"); @@ -623,7 +633,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot() } cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot( - cmStateSnapshot originSnapshot) + cmStateSnapshot const& originSnapshot) { assert(originSnapshot.IsValid()); cmStateDetail::PositionType pos = @@ -657,7 +667,7 @@ cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot( } cmStateSnapshot cmState::CreateFunctionCallSnapshot( - cmStateSnapshot originSnapshot, std::string const& fileName) + cmStateSnapshot const& originSnapshot, std::string const& fileName) { cmStateDetail::PositionType pos = this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position); @@ -676,7 +686,7 @@ cmStateSnapshot cmState::CreateFunctionCallSnapshot( } cmStateSnapshot cmState::CreateMacroCallSnapshot( - cmStateSnapshot originSnapshot, std::string const& fileName) + cmStateSnapshot const& originSnapshot, std::string const& fileName) { cmStateDetail::PositionType pos = this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position); @@ -691,7 +701,7 @@ cmStateSnapshot cmState::CreateMacroCallSnapshot( } cmStateSnapshot cmState::CreateIncludeFileSnapshot( - cmStateSnapshot originSnapshot, const std::string& fileName) + cmStateSnapshot const& originSnapshot, std::string const& fileName) { cmStateDetail::PositionType pos = this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position); @@ -706,7 +716,7 @@ cmStateSnapshot cmState::CreateIncludeFileSnapshot( } cmStateSnapshot cmState::CreateVariableScopeSnapshot( - cmStateSnapshot originSnapshot) + cmStateSnapshot const& originSnapshot) { cmStateDetail::PositionType pos = this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position); @@ -724,7 +734,7 @@ cmStateSnapshot cmState::CreateVariableScopeSnapshot( } cmStateSnapshot cmState::CreateInlineListFileSnapshot( - cmStateSnapshot originSnapshot, const std::string& fileName) + cmStateSnapshot const& originSnapshot, std::string const& fileName) { cmStateDetail::PositionType pos = this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position); @@ -738,7 +748,7 @@ cmStateSnapshot cmState::CreateInlineListFileSnapshot( } cmStateSnapshot cmState::CreatePolicyScopeSnapshot( - cmStateSnapshot originSnapshot) + cmStateSnapshot const& originSnapshot) { cmStateDetail::PositionType pos = this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position); @@ -749,7 +759,7 @@ cmStateSnapshot cmState::CreatePolicyScopeSnapshot( return cmStateSnapshot(this, pos); } -cmStateSnapshot cmState::Pop(cmStateSnapshot originSnapshot) +cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot) { cmStateDetail::PositionType pos = originSnapshot.Position; cmStateDetail::PositionType prevPos = pos; diff --git a/Source/cmState.h b/Source/cmState.h index 41ffcdcd2..e03ad8981 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -3,7 +3,7 @@ #ifndef cmState_h #define cmState_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -12,6 +12,7 @@ #include "cmDefinitions.h" #include "cmLinkedTree.h" +#include "cmPolicies.h" #include "cmProperty.h" #include "cmPropertyDefinitionMap.h" #include "cmPropertyMap.h" @@ -35,18 +36,20 @@ public: cmStateSnapshot CreateBaseSnapshot(); cmStateSnapshot CreateBuildsystemDirectorySnapshot( - cmStateSnapshot originSnapshot); - cmStateSnapshot CreateFunctionCallSnapshot(cmStateSnapshot originSnapshot, - std::string const& fileName); - cmStateSnapshot CreateMacroCallSnapshot(cmStateSnapshot originSnapshot, - std::string const& fileName); - cmStateSnapshot CreateIncludeFileSnapshot(cmStateSnapshot originSnapshot, - std::string const& fileName); - cmStateSnapshot CreateVariableScopeSnapshot(cmStateSnapshot originSnapshot); - cmStateSnapshot CreateInlineListFileSnapshot(cmStateSnapshot originSnapshot, - std::string const& fileName); - cmStateSnapshot CreatePolicyScopeSnapshot(cmStateSnapshot originSnapshot); - cmStateSnapshot Pop(cmStateSnapshot originSnapshot); + cmStateSnapshot const& originSnapshot); + cmStateSnapshot CreateFunctionCallSnapshot( + cmStateSnapshot const& originSnapshot, std::string const& fileName); + cmStateSnapshot CreateMacroCallSnapshot( + cmStateSnapshot const& originSnapshot, std::string const& fileName); + cmStateSnapshot CreateIncludeFileSnapshot( + cmStateSnapshot const& originSnapshot, std::string const& fileName); + cmStateSnapshot CreateVariableScopeSnapshot( + cmStateSnapshot const& originSnapshot); + cmStateSnapshot CreateInlineListFileSnapshot( + cmStateSnapshot const& originSnapshot, std::string const& fileName); + cmStateSnapshot CreatePolicyScopeSnapshot( + cmStateSnapshot const& originSnapshot); + cmStateSnapshot Pop(cmStateSnapshot const& originSnapshot); static cmStateEnums::CacheEntryType StringToCacheEntryType(const char*); static const char* CacheEntryTypeToString(cmStateEnums::CacheEntryType); @@ -116,10 +119,15 @@ public: bool GetIsInTryCompile() const; void SetIsInTryCompile(bool b); + bool GetIsGeneratorMultiConfig() const; + void SetIsGeneratorMultiConfig(bool b); + cmCommand* GetCommand(std::string const& name) const; - void AddCommand(cmCommand* command); - void RemoveUnscriptableCommands(); - void RenameCommand(std::string const& oldName, std::string const& newName); + void AddBuiltinCommand(std::string const& name, cmCommand* command); + void AddDisallowedCommand(std::string const& name, cmCommand* command, + cmPolicies::PolicyID policy, const char* message); + void AddUnexpectedCommand(std::string const& name, const char* error); + void AddScriptedCommand(std::string const& name, cmCommand* command); void RemoveUserDefinedCommands(); std::vector GetCommandNames() const; @@ -158,7 +166,8 @@ private: std::map PropertyDefinitions; std::vector EnabledLanguages; - std::map Commands; + std::map BuiltinCommands; + std::map ScriptedCommands; cmPropertyMap GlobalProperties; cmCacheManager* CacheManager; @@ -174,6 +183,7 @@ private: std::string SourceDirectory; std::string BinaryDirectory; bool IsInTryCompile; + bool IsGeneratorMultiConfig; bool WindowsShell; bool WindowsVSIDE; bool WatcomWMake; diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 8accc8e11..79bb36943 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -4,7 +4,7 @@ #ifndef cmStateDirectory_h #define cmStateDirectory_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index 20700f2b3..f36ee37ea 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -4,7 +4,7 @@ #ifndef cmStatePrivate_h #define cmStatePrivate_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -57,11 +57,6 @@ struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap , Weak(w) { } - PolicyStackEntry(PolicyStackEntry const& r) - : derived(r) - , Weak(r.Weak) - { - } bool Weak; }; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index c6288a56e..77413c7b5 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -18,6 +18,10 @@ #include "cmVersion.h" #include "cmake.h" +#if !defined(_WIN32) +#include +#endif + #if defined(__CYGWIN__) #include "cmSystemTools.h" #endif @@ -121,7 +125,7 @@ cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const return cmStateSnapshot(this->State, pos); } -void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap entry, bool weak) +void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak) { cmStateDetail::PositionType pos = this->Position; pos->Policies = this->State->PolicyStack.Push( @@ -298,9 +302,15 @@ void cmStateSnapshot::SetDefaultDefinitions() #if defined(_WIN32) this->SetDefinition("WIN32", "1"); this->SetDefinition("CMAKE_HOST_WIN32", "1"); + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows"); #else this->SetDefinition("UNIX", "1"); this->SetDefinition("CMAKE_HOST_UNIX", "1"); + + struct utsname uts_name; + if (uname(&uts_name) >= 0) { + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname); + } #endif #if defined(__CYGWIN__) std::string legacy; diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h index 72d0349b0..6293803b9 100644 --- a/Source/cmStateSnapshot.h +++ b/Source/cmStateSnapshot.h @@ -4,7 +4,7 @@ #ifndef cmStateSnapshot_h #define cmStateSnapshot_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -45,7 +45,7 @@ public: void SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status); cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id) const; bool HasDefinedPolicyCMP0011(); - void PushPolicy(cmPolicies::PolicyMap entry, bool weak); + void PushPolicy(cmPolicies::PolicyMap const& entry, bool weak); bool PopPolicy(); bool CanPopPolicyScope(); diff --git a/Source/cmStateTypes.h b/Source/cmStateTypes.h index 2c974c1dc..7d6158e33 100644 --- a/Source/cmStateTypes.h +++ b/Source/cmStateTypes.h @@ -4,7 +4,7 @@ #ifndef cmStateTypes_h #define cmStateTypes_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmLinkedTree.h" @@ -27,6 +27,9 @@ enum SnapshotType VariableScopeType }; +// There are multiple overlapping ranges represented here. Be aware that adding +// a value to this enumeration may cause failures in numerous places which +// assume details about the ordering. enum TargetType { EXECUTABLE, @@ -50,6 +53,12 @@ enum CacheEntryType STATIC, UNINITIALIZED }; + +enum ArtifactType +{ + RuntimeBinaryArtifact, + ImportLibraryArtifact +}; } #endif diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index eb94080f3..7a097ba21 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmStringCommand.h" -#include +#include "cmsys/RegularExpression.hxx" #include #include #include @@ -128,7 +128,7 @@ bool cmStringCommand::HandleToUpperLowerCommand( return false; } - std::string outvar = args[2]; + std::string const& outvar = args[2]; std::string output; if (toUpper) { @@ -149,7 +149,7 @@ bool cmStringCommand::HandleAsciiCommand(std::vector const& args) return false; } std::string::size_type cc; - std::string outvar = args[args.size() - 1]; + std::string const& outvar = args[args.size() - 1]; std::string output; for (cc = 1; cc < args.size() - 1; cc++) { int ch = atoi(args[cc].c_str()); @@ -212,7 +212,7 @@ bool cmStringCommand::HandleRegexCommand(std::vector const& args) this->SetError("sub-command REGEX requires a mode to be specified."); return false; } - std::string mode = args[1]; + std::string const& mode = args[1]; if (mode == "MATCH") { if (args.size() < 5) { this->SetError("sub-command REGEX, mode MATCH needs " @@ -247,8 +247,8 @@ bool cmStringCommand::RegexMatch(std::vector const& args) { //"STRING(REGEX MATCH // [...])\n"; - std::string regex = args[2]; - std::string outvar = args[3]; + std::string const& regex = args[2]; + std::string const& outvar = args[3]; this->Makefile->ClearMatches(); // Compile the regular expression. @@ -288,8 +288,8 @@ bool cmStringCommand::RegexMatchAll(std::vector const& args) { //"STRING(REGEX MATCHALL // [...])\n"; - std::string regex = args[2]; - std::string outvar = args[3]; + std::string const& regex = args[2]; + std::string const& outvar = args[3]; this->Makefile->ClearMatches(); // Compile the regular expression. @@ -334,9 +334,9 @@ bool cmStringCommand::RegexReplace(std::vector const& args) { //"STRING(REGEX REPLACE // [...])\n" - std::string regex = args[2]; - std::string replace = args[3]; - std::string outvar = args[4]; + std::string const& regex = args[2]; + std::string const& replace = args[3]; + std::string const& outvar = args[4]; // Pull apart the replace expression to find the escaped [0-9] values. std::vector replacement; @@ -502,7 +502,7 @@ bool cmStringCommand::HandleCompareCommand( this->SetError("sub-command COMPARE requires a mode to be specified."); return false; } - std::string mode = args[1]; + std::string const& mode = args[1]; if ((mode == "EQUAL") || (mode == "NOTEQUAL") || (mode == "LESS") || (mode == "LESS_EQUAL") || (mode == "GREATER") || (mode == "GREATER_EQUAL")) { diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index c63bc3f90..88015ad5e 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -3,7 +3,8 @@ #ifndef cmStringCommand_h #define cmStringCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "string"; } - protected: bool HandleConfigureCommand(std::vector const& args); bool HandleAsciiCommand(std::vector const& args); diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h index ce1f876e8..a2af0fd58 100644 --- a/Source/cmSubdirCommand.h +++ b/Source/cmSubdirCommand.h @@ -3,7 +3,8 @@ #ifndef cmSubdirCommand_h #define cmSubdirCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "subdirs"; } }; #endif diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx index 925983677..0bb2c0ac4 100644 --- a/Source/cmSubdirDependsCommand.cxx +++ b/Source/cmSubdirDependsCommand.cxx @@ -2,15 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSubdirDependsCommand.h" -#include "cmPolicies.h" - class cmExecutionStatus; bool cmSubdirDependsCommand::InitialPass(std::vector const&, cmExecutionStatus&) { - this->Disallowed( - cmPolicies::CMP0029, - "The subdir_depends command should not be called; see CMP0029."); return true; } diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h index 80ff24f38..d8ea9284f 100644 --- a/Source/cmSubdirDependsCommand.h +++ b/Source/cmSubdirDependsCommand.h @@ -3,7 +3,8 @@ #ifndef cmSubdirDependsCommand_h #define cmSubdirDependsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -17,7 +18,6 @@ public: cmCommand* Clone() CM_OVERRIDE { return new cmSubdirDependsCommand; } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "subdir_depends"; } }; #endif diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9efc13b14..f7192e0b6 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -4,11 +4,12 @@ #include "cmAlgorithms.h" #include "cmProcessOutput.h" +#include "cm_sys_stat.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmArchiveWrite.h" #include "cmLocale.h" -#include +#include "cm_libarchive.h" #ifndef __LA_INT64_T #define __LA_INT64_T la_int64_t #endif @@ -26,15 +27,14 @@ #include "cmMachO.h" #endif +#include "cmsys/Directory.hxx" +#include "cmsys/Encoding.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" +#include "cmsys/System.h" +#include "cmsys/Terminal.h" #include #include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -43,8 +43,8 @@ #include #include #include -#include #include +#include #if defined(_WIN32) #include @@ -134,6 +134,7 @@ public: operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; } bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; } operator HANDLE() const { return this->handle_; } + private: HANDLE handle_; }; @@ -196,7 +197,6 @@ void cmSystemTools::ExpandRegistryValues(std::string& source, while (regEntry.find(source)) { // the arguments are the second match std::string key = regEntry.match(1); - std::string val; std::string reg = "["; reg += key + "]"; cmSystemTools::ReplaceString(source, reg.c_str(), "/registry"); @@ -348,12 +348,12 @@ bool cmSystemTools::IsInternallyOn(const char* val) if (!val) { return false; } - std::basic_string v = val; + std::string v = val; if (v.size() > 4) { return false; } - for (std::basic_string::iterator c = v.begin(); c != v.end(); c++) { + for (std::string::iterator c = v.begin(); c != v.end(); c++) { *c = static_cast(toupper(*c)); } return v == "I_ON"; @@ -368,7 +368,7 @@ bool cmSystemTools::IsOn(const char* val) if (len > 4) { return false; } - std::basic_string v(val, len); + std::string v(val, len); static std::set onValues; if (onValues.empty()) { @@ -378,7 +378,7 @@ bool cmSystemTools::IsOn(const char* val) onValues.insert("TRUE"); onValues.insert("Y"); } - for (std::basic_string::iterator c = v.begin(); c != v.end(); c++) { + for (std::string::iterator c = v.begin(); c != v.end(); c++) { *c = static_cast(toupper(*c)); } return (onValues.count(v) > 0); @@ -413,8 +413,8 @@ bool cmSystemTools::IsOff(const char* val) offValues.insert("IGNORE"); } // Try and avoid toupper(). - std::basic_string v(val, len); - for (std::basic_string::iterator c = v.begin(); c != v.end(); c++) { + std::string v(val, len); + for (std::string::iterator c = v.begin(); c != v.end(); c++) { *c = static_cast(toupper(*c)); } return (offValues.count(v) > 0); @@ -505,6 +505,39 @@ void cmSystemTools::ParseUnixCommandLine(const char* command, argv.Store(args); } +std::vector cmSystemTools::HandleResponseFile( + std::vector::const_iterator argBeg, + std::vector::const_iterator argEnd) +{ + std::vector arg_full; + for (std::vector::const_iterator a = argBeg; a != argEnd; ++a) { + std::string const& arg = *a; + if (cmHasLiteralPrefix(arg, "@")) { + cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in); + if (!responseFile) { + std::string error = "failed to open for reading ("; + error += cmSystemTools::GetLastSystemError(); + error += "):\n "; + error += arg.substr(1); + cmSystemTools::Error(error.c_str()); + } else { + std::string line; + cmSystemTools::GetLineFromStream(responseFile, line); + std::vector args2; +#ifdef _WIN32 + cmSystemTools::ParseWindowsCommandLine(line.c_str(), args2); +#else + cmSystemTools::ParseUnixCommandLine(line.c_str(), args2); +#endif + arg_full.insert(arg_full.end(), args2.begin(), args2.end()); + } + } else { + arg_full.push_back(arg); + } + } + return arg_full; +} + std::vector cmSystemTools::ParseArguments(const char* command) { std::vector args; @@ -570,6 +603,46 @@ std::vector cmSystemTools::ParseArguments(const char* command) return args; } +size_t cmSystemTools::CalculateCommandLineLengthLimit() +{ + size_t sz = +#ifdef _WIN32 + // There's a maximum of 65536 bytes and thus 32768 WCHARs on Windows + // However, cmd.exe itself can only handle 8191 WCHARs and Ninja for + // example uses it to spawn processes. + size_t(8191); +#elif defined(__linux) + // MAX_ARG_STRLEN is the maximum length of a string permissible for + // the execve() syscall on Linux. It's defined as (PAGE_SIZE * 32) + // in Linux's binfmts.h + static_cast(sysconf(_SC_PAGESIZE) * 32); +#else + size_t(0); +#endif + +#if defined(_SC_ARG_MAX) + // ARG_MAX is the maximum size of the command and environment + // that can be passed to the exec functions on UNIX. + // The value in limits.h does not need to be present and may + // depend upon runtime memory constraints, hence sysconf() + // should be used to query it. + long szArgMax = sysconf(_SC_ARG_MAX); + // A return value of -1 signifies an undetermined limit, but + // it does not imply an infinite limit, and thus is ignored. + if (szArgMax != -1) { + // We estimate the size of the environment block to be 1000. + // This isn't accurate at all, but leaves some headroom. + szArgMax = szArgMax < 1000 ? 0 : szArgMax - 1000; +#if defined(_WIN32) || defined(__linux) + sz = std::min(sz, static_cast(szArgMax)); +#else + sz = static_cast(szArgMax); +#endif + } +#endif + return sz; +} + bool cmSystemTools::RunSingleCommand(std::vector const& command, std::string* captureStdOut, std::string* captureStdErr, int* retVal, @@ -617,8 +690,6 @@ bool cmSystemTools::RunSingleCommand(std::vector const& command, while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) > 0) { // Translate NULL characters in the output into valid text. - // Visual Studio 7 puts these characters in the output of its - // build process. for (int i = 0; i < length; ++i) { if (data[i] == '\0') { data[i] = ' '; @@ -1669,7 +1740,8 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, for (; outiter != out.end(); ++outiter) { if ((*outiter == '\r') && ((outiter + 1) == out.end())) { break; - } else if (*outiter == '\n' || *outiter == '\0') { + } + if (*outiter == '\n' || *outiter == '\0') { std::vector::size_type length = outiter - out.begin(); if (length > 1 && *(outiter - 1) == '\r') { --length; @@ -1686,7 +1758,8 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, for (; erriter != err.end(); ++erriter) { if ((*erriter == '\r') && ((erriter + 1) == err.end())) { break; - } else if (*erriter == '\n' || *erriter == '\0') { + } + if (*erriter == '\n' || *erriter == '\0') { std::vector::size_type length = erriter - err.begin(); if (length > 1 && *(erriter - 1) == '\r') { --length; @@ -1978,6 +2051,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0) // ??? } #endif + exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir); cmSystemToolsCMakeCommand = exe_dir; cmSystemToolsCMakeCommand += "/cmake"; cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension(); @@ -2015,8 +2089,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0) // Install tree has // - "/cmake" // - "" - const std::string actual_case = cmSystemTools::GetActualCaseForPath(exe_dir); - if (cmHasSuffix(actual_case, CMAKE_BIN_DIR)) { + if (cmHasSuffix(exe_dir, CMAKE_BIN_DIR)) { std::string const prefix = exe_dir.substr(0, exe_dir.size() - strlen(CMAKE_BIN_DIR)); cmSystemToolsCMakeRoot = prefix + CMAKE_DATA_DIR; @@ -2299,8 +2372,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file, // not being changed. rp[rp_count].Value = se[i]->Value.substr(0, prefix_len); rp[rp_count].Value += newRPath; - rp[rp_count].Value += - se[i]->Value.substr(pos + oldRPath.length(), oldRPath.npos); + rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length()); if (!rp[rp_count].Value.empty()) { remove_rpath = false; @@ -2585,29 +2657,28 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, it = dentries.erase(it); entriesErased++; continue; - } else { - if (cmELF::TagMipsRldMapRel != 0 && - it->first == cmELF::TagMipsRldMapRel) { - // Background: debuggers need to know the "linker map" which contains - // the addresses each dynamic object is loaded at. Most arches use - // the DT_DEBUG tag which the dynamic linker writes to (directly) and - // contain the location of the linker map, however on MIPS the - // .dynamic section is always read-only so this is not possible. MIPS - // objects instead contain a DT_MIPS_RLD_MAP tag which contains the - // address where the dyanmic linker will write to (an indirect - // version of DT_DEBUG). Since this doesn't work when using PIE, a - // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this - // version contains a relative offset, moving it changes the - // calculated address. This may cause the dyanmic linker to write - // into memory it should not be changing. - // - // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If - // we move it up by n bytes, we add n bytes to the value of this tag. - it->second += entriesErased * sizeof_dentry; - } - - it++; } + if (cmELF::TagMipsRldMapRel != 0 && + it->first == cmELF::TagMipsRldMapRel) { + // Background: debuggers need to know the "linker map" which contains + // the addresses each dynamic object is loaded at. Most arches use + // the DT_DEBUG tag which the dynamic linker writes to (directly) and + // contain the location of the linker map, however on MIPS the + // .dynamic section is always read-only so this is not possible. MIPS + // objects instead contain a DT_MIPS_RLD_MAP tag which contains the + // address where the dyanmic linker will write to (an indirect + // version of DT_DEBUG). Since this doesn't work when using PIE, a + // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this + // version contains a relative offset, moving it changes the + // calculated address. This may cause the dyanmic linker to write + // into memory it should not be changing. + // + // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If + // we move it up by n bytes, we add n bytes to the value of this tag. + it->second += entriesErased * sizeof_dentry; + } + + it++; } // Encode new entries list diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 10e828032..9de796728 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -3,21 +3,15 @@ #ifndef cmSystemTools_h #define cmSystemTools_h -#include // IWYU pragma: keep +#include "cmConfigure.h" -#include -#include -#include +#include "cmProcessOutput.h" +#include "cmsys/Process.h" +#include "cmsys/SystemTools.hxx" // IWYU pragma: export #include #include #include -#if defined(_MSC_VER) -typedef unsigned short mode_t; -#else -#include -#endif - class cmSystemToolsFileTime; /** \class cmSystemTools @@ -259,6 +253,15 @@ public: static void ParseUnixCommandLine(const char* command, std::vector& args); + /** + * Handle response file in an argument list and return a new argument list + * **/ + static std::vector HandleResponseFile( + std::vector::const_iterator argBeg, + std::vector::const_iterator argEnd); + + static size_t CalculateCommandLineLengthLimit(); + static void EnableMessages() { s_DisableMessages = false; } static void DisableMessages() { s_DisableMessages = true; } static void DisableRunCommandOutput() { s_DisableRunCommandOutput = true; } @@ -383,9 +386,10 @@ public: original environment. */ class SaveRestoreEnvironment { + CM_DISABLE_COPY(SaveRestoreEnvironment) public: SaveRestoreEnvironment(); - virtual ~SaveRestoreEnvironment(); + ~SaveRestoreEnvironment(); private: std::vector Env; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index fe3472d5d..c95a3ca2c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTarget.h" +#include "cmsys/RegularExpression.hxx" #include #include -#include #include #include #include @@ -35,7 +35,7 @@ const char* cmTargetPropertyComputer::ComputeLocationForBuild( { static std::string loc; if (tgt->IsImported()) { - loc = tgt->ImportedGetFullPath("", false); + loc = tgt->ImportedGetFullPath("", cmStateEnums::RuntimeBinaryArtifact); return loc.c_str(); } @@ -54,7 +54,8 @@ const char* cmTargetPropertyComputer::ComputeLocation( { static std::string loc; if (tgt->IsImported()) { - loc = tgt->ImportedGetFullPath(config, false); + loc = + tgt->ImportedGetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); return loc.c_str(); } @@ -63,7 +64,7 @@ const char* cmTargetPropertyComputer::ComputeLocation( gg->CreateGenerationObjects(); } cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName()); - loc = gt->GetFullPath(config, false); + loc = gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact); return loc.c_str(); } @@ -230,6 +231,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("INSTALL_NAME_DIR", CM_NULLPTR); this->SetPropertyDefault("INSTALL_RPATH", ""); this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF"); + this->SetPropertyDefault("INTERPROCEDURAL_OPTIMIZATION", CM_NULLPTR); this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF"); this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF"); this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", CM_NULLPTR); @@ -245,14 +247,17 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("AUTOMOC", CM_NULLPTR); this->SetPropertyDefault("AUTOUIC", CM_NULLPTR); this->SetPropertyDefault("AUTORCC", CM_NULLPTR); + this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", CM_NULLPTR); this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", CM_NULLPTR); this->SetPropertyDefault("AUTOUIC_OPTIONS", CM_NULLPTR); + this->SetPropertyDefault("AUTOUIC_SEARCH_PATHS", CM_NULLPTR); this->SetPropertyDefault("AUTORCC_OPTIONS", CM_NULLPTR); this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", CM_NULLPTR); this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", CM_NULLPTR); this->SetPropertyDefault("WIN32_EXECUTABLE", CM_NULLPTR); this->SetPropertyDefault("MACOSX_BUNDLE", CM_NULLPTR); this->SetPropertyDefault("MACOSX_RPATH", CM_NULLPTR); + this->SetPropertyDefault("BUILD_WITH_INSTALL_NAME_DIR", CM_NULLPTR); this->SetPropertyDefault("C_CLANG_TIDY", CM_NULLPTR); this->SetPropertyDefault("C_COMPILER_LAUNCHER", CM_NULLPTR); this->SetPropertyDefault("C_CPPLINT", CM_NULLPTR); @@ -287,13 +292,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (this->GetType() != cmStateEnums::UTILITY) { const char* configProps[] = { /* clang-format needs this comment to break after the opening brace */ - "ARCHIVE_OUTPUT_DIRECTORY_", - "LIBRARY_OUTPUT_DIRECTORY_", - "RUNTIME_OUTPUT_DIRECTORY_", - "PDB_OUTPUT_DIRECTORY_", - "COMPILE_PDB_OUTPUT_DIRECTORY_", - "MAP_IMPORTED_CONFIG_", - CM_NULLPTR + "ARCHIVE_OUTPUT_DIRECTORY_", "LIBRARY_OUTPUT_DIRECTORY_", + "RUNTIME_OUTPUT_DIRECTORY_", "PDB_OUTPUT_DIRECTORY_", + "COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_", + "INTERPROCEDURAL_OPTIMIZATION_", CM_NULLPTR }; for (std::vector::iterator ci = configNames.begin(); ci != configNames.end(); ++ci) { @@ -939,6 +941,14 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") && !this->CheckImportedLibName(prop, value ? value : "")) { /* error was reported by check method */ + } else if (prop == "CUDA_PTX_COMPILATION" && + this->GetType() != cmStateEnums::OBJECT_LIBRARY) { + std::ostringstream e; + e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT " + "targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; } else { this->Properties.SetProperty(prop, value); } @@ -1293,68 +1303,96 @@ bool cmTarget::GetPropertyAsBool(const std::string& prop) const return cmSystemTools::IsOn(this->GetProperty(prop)); } -const char* cmTarget::GetSuffixVariableInternal(bool implib) const +const char* cmTarget::GetSuffixVariableInternal( + cmStateEnums::ArtifactType artifact) const { switch (this->GetType()) { case cmStateEnums::STATIC_LIBRARY: return "CMAKE_STATIC_LIBRARY_SUFFIX"; case cmStateEnums::SHARED_LIBRARY: - return (implib ? "CMAKE_IMPORT_LIBRARY_SUFFIX" - : "CMAKE_SHARED_LIBRARY_SUFFIX"); + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + return "CMAKE_SHARED_LIBRARY_SUFFIX"; + case cmStateEnums::ImportLibraryArtifact: + return "CMAKE_IMPORT_LIBRARY_SUFFIX"; + } + break; case cmStateEnums::MODULE_LIBRARY: - return (implib ? "CMAKE_IMPORT_LIBRARY_SUFFIX" - : "CMAKE_SHARED_MODULE_SUFFIX"); + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + return "CMAKE_SHARED_MODULE_SUFFIX"; + case cmStateEnums::ImportLibraryArtifact: + return "CMAKE_IMPORT_LIBRARY_SUFFIX"; + } + break; case cmStateEnums::EXECUTABLE: - return (implib - ? "CMAKE_IMPORT_LIBRARY_SUFFIX" - // Android GUI application packages store the native - // binary as a shared library. - : (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI") - ? "CMAKE_SHARED_LIBRARY_SUFFIX" - : "CMAKE_EXECUTABLE_SUFFIX")); + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + // Android GUI application packages store the native + // binary as a shared library. + return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI") + ? "CMAKE_SHARED_LIBRARY_SUFFIX" + : "CMAKE_EXECUTABLE_SUFFIX"); + case cmStateEnums::ImportLibraryArtifact: + return "CMAKE_IMPORT_LIBRARY_SUFFIX"; + } + break; default: break; } return ""; } -const char* cmTarget::GetPrefixVariableInternal(bool implib) const +const char* cmTarget::GetPrefixVariableInternal( + cmStateEnums::ArtifactType artifact) const { switch (this->GetType()) { case cmStateEnums::STATIC_LIBRARY: return "CMAKE_STATIC_LIBRARY_PREFIX"; case cmStateEnums::SHARED_LIBRARY: - return (implib ? "CMAKE_IMPORT_LIBRARY_PREFIX" - : "CMAKE_SHARED_LIBRARY_PREFIX"); + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + return "CMAKE_SHARED_LIBRARY_PREFIX"; + case cmStateEnums::ImportLibraryArtifact: + return "CMAKE_IMPORT_LIBRARY_PREFIX"; + } + break; case cmStateEnums::MODULE_LIBRARY: - return (implib ? "CMAKE_IMPORT_LIBRARY_PREFIX" - : "CMAKE_SHARED_MODULE_PREFIX"); + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + return "CMAKE_SHARED_MODULE_PREFIX"; + case cmStateEnums::ImportLibraryArtifact: + return "CMAKE_IMPORT_LIBRARY_PREFIX"; + } + break; case cmStateEnums::EXECUTABLE: - return (implib - ? "CMAKE_IMPORT_LIBRARY_PREFIX" - // Android GUI application packages store the native - // binary as a shared library. - : (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI") - ? "CMAKE_SHARED_LIBRARY_PREFIX" - : "")); + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + // Android GUI application packages store the native + // binary as a shared library. + return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI") + ? "CMAKE_SHARED_LIBRARY_PREFIX" + : ""); + case cmStateEnums::ImportLibraryArtifact: + return "CMAKE_IMPORT_LIBRARY_PREFIX"; + } + break; default: break; } return ""; } -std::string cmTarget::ImportedGetFullPath(const std::string& config, - bool pimplib) const +std::string cmTarget::ImportedGetFullPath( + const std::string& config, cmStateEnums::ArtifactType artifact) const { assert(this->IsImported()); // Lookup/compute/cache the import information for this // configuration. - std::string config_upper; - if (!config.empty()) { - config_upper = cmSystemTools::UpperCase(config); - } else { - config_upper = "NOCONFIG"; + std::string desired_config = config; + if (config.empty()) { + desired_config = "NOCONFIG"; } std::string result; @@ -1364,33 +1402,38 @@ std::string cmTarget::ImportedGetFullPath(const std::string& config, std::string suffix; if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && - this->GetMappedConfig(config_upper, &loc, &imp, suffix)) { - if (!pimplib) { - if (loc) { - result = loc; - } else { - std::string impProp = "IMPORTED_LOCATION"; - impProp += suffix; - if (const char* config_location = this->GetProperty(impProp)) { - result = config_location; - } else if (const char* location = - this->GetProperty("IMPORTED_LOCATION")) { - result = location; + this->GetMappedConfig(desired_config, &loc, &imp, suffix)) { + switch (artifact) { + case cmStateEnums::RuntimeBinaryArtifact: + if (loc) { + result = loc; + } else { + std::string impProp = "IMPORTED_LOCATION"; + impProp += suffix; + if (const char* config_location = this->GetProperty(impProp)) { + result = config_location; + } else if (const char* location = + this->GetProperty("IMPORTED_LOCATION")) { + result = location; + } } - } - } else { - if (imp) { - result = imp; - } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || - this->IsExecutableWithExports()) { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; - if (const char* config_implib = this->GetProperty(impProp)) { - result = config_implib; - } else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) { - result = implib; + break; + + case cmStateEnums::ImportLibraryArtifact: + if (imp) { + result = imp; + } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || + this->IsExecutableWithExports()) { + std::string impProp = "IMPORTED_IMPLIB"; + impProp += suffix; + if (const char* config_implib = this->GetProperty(impProp)) { + result = config_implib; + } else if (const char* implib = + this->GetProperty("IMPORTED_IMPLIB")) { + result = implib; + } } - } + break; } } @@ -1433,7 +1476,7 @@ bool cmTarget::CheckImportedLibName(std::string const& prop, return false; } std::string::size_type bad = value.find_first_of(":/\\;"); - if (bad != value.npos) { + if (bad != std::string::npos) { this->Makefile->IssueMessage( cmake::FATAL_ERROR, prop + " property value\n " + value + "\nmay not contain '" + value.substr(bad, 1) + "'."); @@ -1447,18 +1490,28 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, const char** loc, const char** imp, std::string& suffix) const { - std::string const locPropBase = - this->GetType() == cmStateEnums::INTERFACE_LIBRARY ? "IMPORTED_LIBNAME" - : "IMPORTED_LOCATION"; + std::string config_upper; + if (!desired_config.empty()) { + config_upper = cmSystemTools::UpperCase(desired_config); + } + + std::string locPropBase; + if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + locPropBase = "IMPORTED_LIBNAME"; + } else if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) { + locPropBase = "IMPORTED_OBJECTS"; + } else { + locPropBase = "IMPORTED_LOCATION"; + } // Track the configuration-specific property suffix. suffix = "_"; - suffix += desired_config; + suffix += config_upper; std::vector mappedConfigs; { std::string mapProp = "MAP_IMPORTED_CONFIG_"; - mapProp += desired_config; + mapProp += config_upper; if (const char* mapValue = this->GetProperty(mapProp)) { cmSystemTools::ExpandListArgument(mapValue, mappedConfigs, true); } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 1d40d2012..1f00c0155 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -3,7 +3,7 @@ #ifndef cmTarget_h #define cmTarget_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include @@ -267,11 +267,13 @@ public: }; std::string ImportedGetFullPath(const std::string& config, - bool implib) const; + cmStateEnums::ArtifactType artifact) const; private: - const char* GetSuffixVariableInternal(bool implib) const; - const char* GetPrefixVariableInternal(bool implib) const; + const char* GetSuffixVariableInternal( + cmStateEnums::ArtifactType artifact) const; + const char* GetPrefixVariableInternal( + cmStateEnums::ArtifactType artifact) const; // Use a makefile variable to set a default for the given property. // If the variable is not defined use the given default instead. diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index caaf23b2a..11abf571c 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -3,7 +3,8 @@ #ifndef cmTargetCompileDefinitionsCommand_h #define cmTargetCompileDefinitionsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,14 +32,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "target_compile_definitions"; - } - private: void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE; void HandleMissingTarget(const std::string& name) CM_OVERRIDE; diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h index 01f2938fc..990868004 100644 --- a/Source/cmTargetCompileFeaturesCommand.h +++ b/Source/cmTargetCompileFeaturesCommand.h @@ -3,7 +3,8 @@ #ifndef cmTargetCompileFeaturesCommand_h #define cmTargetCompileFeaturesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -20,8 +21,6 @@ class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "target_compile_features"; } - private: void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE; void HandleMissingTarget(const std::string& name) CM_OVERRIDE; diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h index 179013b92..b5408f7cb 100644 --- a/Source/cmTargetCompileOptionsCommand.h +++ b/Source/cmTargetCompileOptionsCommand.h @@ -3,7 +3,8 @@ #ifndef cmTargetCompileOptionsCommand_h #define cmTargetCompileOptionsCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -28,11 +29,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "target_compile_options"; } - private: void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE; void HandleMissingTarget(const std::string& name) CM_OVERRIDE; diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index a953efb2a..daa902ecf 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -3,7 +3,7 @@ #ifndef cmTargetDepend_h #define cmTargetDepend_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include @@ -30,7 +30,7 @@ public: operator cmGeneratorTarget const*() const { return this->Target; } cmGeneratorTarget const* operator->() const { return this->Target; } cmGeneratorTarget const& operator*() const { return *this->Target; } - friend bool operator<(cmTargetDepend const& l, cmTargetDepend const& r) + friend bool operator<(cmTargetDepend l, cmTargetDepend r) { return l.Target < r.Target; } diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h index b08ede289..9304eabbb 100644 --- a/Source/cmTargetExport.h +++ b/Source/cmTargetExport.h @@ -3,7 +3,7 @@ #ifndef cmTargetExport_h #define cmTargetExport_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include @@ -26,6 +26,7 @@ public: cmInstallTargetGenerator* ArchiveGenerator; cmInstallTargetGenerator* RuntimeGenerator; cmInstallTargetGenerator* LibraryGenerator; + cmInstallTargetGenerator* ObjectsGenerator; cmInstallTargetGenerator* FrameworkGenerator; cmInstallTargetGenerator* BundleGenerator; cmInstallFilesGenerator* HeaderGenerator; diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index bc6cf0dea..374a867dc 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -3,7 +3,8 @@ #ifndef cmTargetIncludeDirectoriesCommand_h #define cmTargetIncludeDirectoriesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,14 +32,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE - { - return "target_include_directories"; - } - private: void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE; void HandleMissingTarget(const std::string& name) CM_OVERRIDE; diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index 762b48fc0..3fd20accd 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -3,7 +3,8 @@ #ifndef cmTargetLinkLibrariesCommand_h #define cmTargetLinkLibrariesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -35,11 +36,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "target_link_libraries"; } - private: void LinkLibraryTypeSpecifierWarning(int left, int right); static const char* LinkLibraryTypeNames[3]; diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 9a5c1da24..45fe430c1 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -78,7 +78,7 @@ bool cmTargetPropCommandBase::ProcessContentArgs( std::vector const& args, unsigned int& argIndex, bool prepend, bool system) { - const std::string scope = args[argIndex]; + std::string const& scope = args[argIndex]; if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") { this->SetError("called with invalid arguments"); diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 8b49653cd..46a2f6b07 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -3,7 +3,7 @@ #ifndef cmTargetPropCommandBase_h #define cmTargetPropCommandBase_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index 45d31be3b..94688e313 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -3,7 +3,7 @@ #ifndef cmTargetPropertyComputer_h #define cmTargetPropertyComputer_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h index b1afac21c..09ba72915 100644 --- a/Source/cmTargetSourcesCommand.h +++ b/Source/cmTargetSourcesCommand.h @@ -3,7 +3,8 @@ #ifndef cmTargetSourcesCommand_h #define cmTargetSourcesCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -28,11 +29,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "target_sources"; } - private: void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE; void HandleMissingTarget(const std::string& name) CM_OVERRIDE; diff --git a/Source/cmTest.h b/Source/cmTest.h index 274a9242d..d4839d171 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -3,7 +3,7 @@ #ifndef cmTest_h #define cmTest_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include "cmListFileCache.h" #include "cmPropertyMap.h" diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 4164f3a81..be4b37847 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -35,15 +35,13 @@ void cmTestGenerator::Compute(cmLocalGenerator* lg) this->LG = lg; } -void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, - Indent const& indent) +void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent) { // Create the tests. this->cmScriptGenerator::GenerateScriptConfigs(os, indent); } -void cmTestGenerator::GenerateScriptActions(std::ostream& os, - Indent const& indent) +void cmTestGenerator::GenerateScriptActions(std::ostream& os, Indent indent) { if (this->ActionsPerConfig) { // This is the per-config generation in a single-configuration @@ -59,7 +57,7 @@ void cmTestGenerator::GenerateScriptActions(std::ostream& os, void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, const std::string& config, - Indent const& indent) + Indent indent) { this->TestGenerated = true; @@ -125,8 +123,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } } -void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, - Indent const& indent) +void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent) { os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n"; } @@ -139,8 +136,7 @@ bool cmTestGenerator::NeedsScriptNoConfig() const !this->ConfigurationTypes->empty()); // config-dependent command } -void cmTestGenerator::GenerateOldStyle(std::ostream& fout, - Indent const& indent) +void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) { this->TestGenerated = true; diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index b350806c8..b2273050f 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h @@ -3,7 +3,7 @@ #ifndef cmTestGenerator_h #define cmTestGenerator_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include "cmScriptGenerator.h" @@ -20,6 +20,8 @@ class cmTest; */ class cmTestGenerator : public cmScriptGenerator { + CM_DISABLE_COPY(cmTestGenerator) + public: cmTestGenerator(cmTest* test, std::vector const& configurations = @@ -29,16 +31,13 @@ public: void Compute(cmLocalGenerator* lg); protected: - void GenerateScriptConfigs(std::ostream& os, - Indent const& indent) CM_OVERRIDE; - void GenerateScriptActions(std::ostream& os, - Indent const& indent) CM_OVERRIDE; + void GenerateScriptConfigs(std::ostream& os, Indent indent) CM_OVERRIDE; + void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE; void GenerateScriptForConfig(std::ostream& os, const std::string& config, - Indent const& indent) CM_OVERRIDE; - void GenerateScriptNoConfig(std::ostream& os, - Indent const& indent) CM_OVERRIDE; + Indent indent) CM_OVERRIDE; + void GenerateScriptNoConfig(std::ostream& os, Indent indent) CM_OVERRIDE; bool NeedsScriptNoConfig() const CM_OVERRIDE; - void GenerateOldStyle(std::ostream& os, Indent const& indent); + void GenerateOldStyle(std::ostream& os, Indent indent); cmLocalGenerator* LG; cmTest* Test; diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 3d42e262e..4b9718847 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTimestamp.h" -#include +#include "cmConfigure.h" #include #include #include diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h index fdee56401..8dd499a3e 100644 --- a/Source/cmTimestamp.h +++ b/Source/cmTimestamp.h @@ -3,7 +3,7 @@ #ifndef cmTimestamp_h #define cmTimestamp_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index 52a034591..483654822 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -3,7 +3,8 @@ #ifndef cmTryCompileCommand_h #define cmTryCompileCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -31,11 +32,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "try_compile"; } }; #endif diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index c4fc94e2f..07e20e62f 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTryRunCommand.h" -#include +#include "cmsys/FStream.hxx" #include #include diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h index 8b44ac5a9..c27b026ad 100644 --- a/Source/cmTryRunCommand.h +++ b/Source/cmTryRunCommand.h @@ -3,7 +3,8 @@ #ifndef cmTryRunCommand_h #define cmTryRunCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -32,11 +33,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "try_run"; } - private: void RunExecutable(const std::string& runArgs, std::string* runOutputContents); diff --git a/Source/cmUnexpectedCommand.h b/Source/cmUnexpectedCommand.h index 897dfb689..995d8a5d6 100644 --- a/Source/cmUnexpectedCommand.h +++ b/Source/cmUnexpectedCommand.h @@ -3,7 +3,8 @@ #ifndef cmUnexpectedCommand_h #define cmUnexpectedCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -28,10 +29,6 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - bool IsScriptable() const CM_OVERRIDE { return true; } - - std::string GetName() const CM_OVERRIDE { return this->Name; } - private: std::string Name; const char* Error; diff --git a/Source/cmUnsetCommand.h b/Source/cmUnsetCommand.h index 5b07202fc..2a1f3f0a6 100644 --- a/Source/cmUnsetCommand.h +++ b/Source/cmUnsetCommand.h @@ -3,7 +3,8 @@ #ifndef cmUnsetCommand_h #define cmUnsetCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -30,16 +31,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "unset"; } }; #endif diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 3e72d7572..07095b137 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -2,10 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmUseMangledMesaCommand.h" -#include -#include +#include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" -#include "cmPolicies.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -13,11 +12,6 @@ class cmExecutionStatus; bool cmUseMangledMesaCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0030, - "The use_mangled_mesa command should not be called; see CMP0030.")) { - return true; - } // expected two arguments: // arguement one: the full path to gl_mangle.h // arguement two : directory for output of edited headers diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h index 9a49f94a4..511882989 100644 --- a/Source/cmUseMangledMesaCommand.h +++ b/Source/cmUseMangledMesaCommand.h @@ -3,7 +3,8 @@ #ifndef cmUseMangledMesaCommand_h #define cmUseMangledMesaCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -17,8 +18,7 @@ public: cmCommand* Clone() CM_OVERRIDE { return new cmUseMangledMesaCommand; } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "use_mangled_mesa"; } - bool IsScriptable() const CM_OVERRIDE { return true; } + protected: void CopyAndFullPathMesaHeader(const char* source, const char* outdir); }; diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 3b78abec0..eabd7ef31 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -5,7 +5,6 @@ #include #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -16,11 +15,6 @@ class cmExecutionStatus; bool cmUtilitySourceCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0034, - "The utility_source command should not be called; see CMP0034.")) { - return true; - } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; @@ -29,7 +23,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector const& args, std::vector::const_iterator arg = args.begin(); // The first argument is the cache entry name. - std::string cacheEntry = *arg++; + std::string const& cacheEntry = *arg++; const char* cacheValue = this->Makefile->GetDefinition(cacheEntry); // If it exists already and appears up to date then we are done. If // the string contains "(IntDir)" but that is not the @@ -63,11 +57,11 @@ bool cmUtilitySourceCommand::InitialPass(std::vector const& args, // The second argument is the utility's executable name, which will be // needed later. - std::string utilityName = *arg++; + std::string const& utilityName = *arg++; // The third argument specifies the relative directory of the source // of the utility. - std::string relativeSource = *arg++; + std::string const& relativeSource = *arg++; std::string utilitySource = this->Makefile->GetCurrentSourceDirectory(); utilitySource = utilitySource + "/" + relativeSource; diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h index 849b96695..a95b48d6a 100644 --- a/Source/cmUtilitySourceCommand.h +++ b/Source/cmUtilitySourceCommand.h @@ -3,7 +3,8 @@ #ifndef cmUtilitySourceCommand_h #define cmUtilitySourceCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -17,7 +18,6 @@ public: cmCommand* Clone() CM_OVERRIDE { return new cmUtilitySourceCommand; } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "utility_source"; } }; #endif diff --git a/Source/cmUtils.hxx b/Source/cmUtils.hxx index 3f65872a9..c5c767c02 100644 --- a/Source/cmUtils.hxx +++ b/Source/cmUtils.hxx @@ -3,7 +3,7 @@ #ifndef cmUtils_hxx #define cmUtils_hxx -#include +#include "cmsys/SystemTools.hxx" // Use the make system's VERBOSE environment variable to enable // verbose output. This can be skipped by also setting CMAKE_NO_VERBOSE diff --git a/Source/cmUuid.h b/Source/cmUuid.h index 1bc222952..158ce6ee4 100644 --- a/Source/cmUuid.h +++ b/Source/cmUuid.h @@ -3,7 +3,7 @@ #ifndef cmUuid_h #define cmUuid_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmVS10CudaFlagTable.h b/Source/cmVS10CudaFlagTable.h new file mode 100644 index 000000000..da19d649b --- /dev/null +++ b/Source/cmVS10CudaFlagTable.h @@ -0,0 +1,51 @@ +static cmVS7FlagTable cmVS10CudaFlagTable[] = { + // Collect options meant for the host compiler. + { "AdditionalCompilerOptions", "Xcompiler=", "Host compiler options", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SpaceAppendable }, + { "AdditionalCompilerOptions", "Xcompiler", "Host compiler options", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SpaceAppendable }, + + // Select the CUDA runtime library. + { "CudaRuntime", "cudart=none", "No CUDA runtime library", "None", 0 }, + { "CudaRuntime", "cudart=shared", "Shared/dynamic CUDA runtime library", + "Shared", 0 }, + { "CudaRuntime", "cudart=static", "Static CUDA runtime library", "Static", + 0 }, + { "CudaRuntime", "cudart", "CUDA runtime library", "", + cmVS7FlagTable::UserFollowing }, + + // Capture arch/code arguments into temporaries for post-processing. + { "cmake-temp-gencode", "gencode=", "", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "gencode", "", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "-generate-code=", "", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "cmake-temp-gencode", "-generate-code", "", "", + cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable }, + + { "cmake-temp-code", "code=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-code", "code", "", "", cmVS7FlagTable::UserFollowing }, + { "cmake-temp-code", "-gpu-code=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-code", "-gpu-code", "", "", cmVS7FlagTable::UserFollowing }, + + { "cmake-temp-arch", "arch=", "", "", cmVS7FlagTable::UserValue }, + { "cmake-temp-arch", "arch", "", "", cmVS7FlagTable::UserFollowing }, + { "cmake-temp-arch", "-gpu-architecture=", "", "", + cmVS7FlagTable::UserValue }, + { "cmake-temp-arch", "-gpu-architecture", "", "", + cmVS7FlagTable::UserFollowing }, + + // Other flags. + + { "FastMath", "use_fast_math", "", "true", 0 }, + { "FastMath", "-use_fast_math", "", "true", 0 }, + + { "GPUDebugInfo", "G", "", "true", 0 }, + { "GPUDebugInfo", "-device-debug", "", "true", 0 }, + + { "HostDebugInfo", "g", "", "true", 0 }, + { "HostDebugInfo", "-debug", "", "true", 0 }, + + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVS10CudaHostFlagTable.h b/Source/cmVS10CudaHostFlagTable.h new file mode 100644 index 000000000..5b61066ca --- /dev/null +++ b/Source/cmVS10CudaHostFlagTable.h @@ -0,0 +1,35 @@ +static cmVS7FlagTable cmVS10CudaHostFlagTable[] = { + //{"Optimization", "", "", "InheritFromHost", 0}, + { "Optimization", "Od", "Disabled", "Od", 0 }, + { "Optimization", "O1", "Minimize Size", "O1", 0 }, + { "Optimization", "O2", "Maximize Speed", "O2", 0 }, + { "Optimization", "Ox", "Full Optimization", "O3", 0 }, + + //{"Runtime", "", "", "InheritFromHost", 0}, + { "Runtime", "MT", "Multi-Threaded", "MT", 0 }, + { "Runtime", "MTd", "Multi-Threaded Debug", "MTd", 0 }, + { "Runtime", "MD", "Multi-Threaded DLL", "MD", 0 }, + { "Runtime", "MDd", "Multi-threaded Debug DLL", "MDd", 0 }, + { "Runtime", "ML", "Single-Threaded", "ML", 0 }, + { "Runtime", "MLd", "Single-Threaded Debug", "MLd", 0 }, + + //{"RuntimeChecks", "", "", "InheritFromHost", 0}, + //{"RuntimeChecks", "", "Default", "Default", 0}, + { "RuntimeChecks", "RTCs", "Stack Frames", "RTCs", 0 }, + { "RuntimeChecks", "RTCu", "Uninitialized Variables", "RTCu", 0 }, + { "RuntimeChecks", "RTC1", "Both", "RTC1", 0 }, + + //{"TypeInfo", "", "", "InheritFromHost", 0}, + { "TypeInfo", "GR", "Yes", "true", 0 }, + { "TypeInfo", "GR-", "No", "false", 0 }, + + //{"Warning", "", "", "InheritFromHost", 0}, + { "Warning", "W0", "Off: Turn Off All Warnings", "W0", 0 }, + { "Warning", "W1", "Level 1", "W1", 0 }, + { "Warning", "W2", "Level 2", "W2", 0 }, + { "Warning", "W3", "Level 3", "W3", 0 }, + { "Warning", "W4", "Level 4", "W4", 0 }, + { "Warning", "Wall", "Enable All Warnings", "Wall", 0 }, + + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVS10MASMFlagTable.h b/Source/cmVS10MASMFlagTable.h index 82e527005..0a452453f 100644 --- a/Source/cmVS10MASMFlagTable.h +++ b/Source/cmVS10MASMFlagTable.h @@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS10MASMFlagTable[] = { // Enum Properties { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1", + { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", 0 }, - { "PreserveIdentifierCase", "/Cu", + { "PreserveIdentifierCase", "Cu", "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "/Cx", + { "PreserveIdentifierCase", "Cx", "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 }, + { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, + { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, + { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, + { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5", - 0 }, + { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, + { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, + { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, + { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, + { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2", + { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", 0 }, - { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3", + { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", 0 }, + { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - { "ErrorReporting", "/errorReport:prompt", + { "ErrorReporting", "errorReport:prompt", "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "/errorReport:queue", + { "ErrorReporting", "errorReport:queue", "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "/errorReport:send", + { "ErrorReporting", "errorReport:send", "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "/errorReport:none", + { "ErrorReporting", "errorReport:none", "Do not send report (/errorReport:none)", "3", 0 }, // Bool Properties - { "NoLogo", "/nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 }, - { "ListAllAvailableInformation", "/Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 }, - { "AddFirstPassListing", "/Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 }, - { "DisableSymbolTable", "/Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "/WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 }, - { "GenerateDebugInformation", "/Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "/Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 }, + { "NoLogo", "nologo", "", "true", 0 }, + { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, + { "ListAllAvailableInformation", "Sa", "", "true", 0 }, + { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, + { "AddFirstPassListing", "Sf", "", "true", 0 }, + { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, + { "DisableSymbolTable", "Sn", "", "true", 0 }, + { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, + { "TreatWarningsAsErrors", "WX", "", "true", 0 }, + { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, + { "GenerateDebugInformation", "Zi", "", "true", 0 }, + { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, + { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, // Bool Properties With Argument // String List Properties - { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "", + { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "/I", "Include Paths", "", + { "IncludePaths", "I", "Include Paths", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "/FR", "Generate Browse Information File", "", + { "BrowseFile", "FR", "Generate Browse Information File", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, // Skip [AdditionalDependencies] - no command line Switch. // String Properties // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "/Fo", "Object File Name", "", + { "ObjectFileName", "Fo", "Object File Name", "", cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "", + { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", cmVS7FlagTable::UserValue }, // Skip [CommandLineTemplate] - no command line Switch. // Skip [ExecutionDescription] - no command line Switch. diff --git a/Source/cmVS10NASMFlagTable.h b/Source/cmVS10NASMFlagTable.h new file mode 100644 index 000000000..b91af9270 --- /dev/null +++ b/Source/cmVS10NASMFlagTable.h @@ -0,0 +1,50 @@ +static cmVS7FlagTable cmVS10NASMFlagTable[] = { + + // Enum Properties + { "Outputswitch", "fwin32", "", "0", 0 }, + { "Outputswitch", "fwin", "", "0", 0 }, + { "Outputswitch", "fwin64", "", "1", 0 }, + { "Outputswitch", "felf", "", "2", 0 }, + { "Outputswitch", "felf32", "", "2", 0 }, + { "Outputswitch", "felf64", "", "3", 0 }, + + { "ErrorReportingFormat", "Xgnu", "", "-Xgnu GNU format: Default format", + 0 }, + { "ErrorReportingFormat", "Xvc", "", + "-Xvc Style used by Microsoft Visual C++", 0 }, + + // Bool Properties + { "TreatWarningsAsErrors", "Werror", "", "true", 0 }, + { "GenerateDebugInformation", "g", "", "true", 0 }, + { "floatunderflow", "w+float-underflow", "", "true", 0 }, + { "macrodefaults", "w-macro-defaults", "", "true", 0 }, + { "user", "w-user", "%warning directives (default on)", "true", 0 }, + { "floatoverflow", "w-float-overflow", "", "true", 0 }, + { "floatdenorm", "w+float-denorm", "", "true", 0 }, + { "numberoverflow", "w-number-overflow", "", "true", 0 }, + { "macroselfref", "w+macro-selfref", "", "true", 0 }, + { "floattoolong", "w-float-toolong", "", "true", 0 }, + { "orphanlabels", "w-orphan-labels", "", "true", 0 }, + { "tasmmode", "t", "", "true", 0 }, + + // Bool Properties With Argument + + // String List Properties + { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "UndefinePreprocessorDefinitions", "U", + "Undefine Preprocessor Definitions", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "IncludePaths", "I", "Include Paths", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "AssembledCodeListingFile", "l", + "Generates an assembled code listing file.", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + + // String Properties + // Skip [Inputs] - no command line Switch. + // Skip [CommandLineTemplate] - no command line Switch. + // Skip [ExecutionDescription] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVS10RCFlagTable.h b/Source/cmVS10RCFlagTable.h index 32f35e52c..6e2b8344c 100644 --- a/Source/cmVS10RCFlagTable.h +++ b/Source/cmVS10RCFlagTable.h @@ -1,6 +1,7 @@ static cmVS7FlagTable cmVS10RCFlagTable[] = { // Bool Properties { "NullTerminateStrings", "n", "", "true", 0 }, + { "SuppressStartupBanner", "nologo", "", "true", 0 }, { 0, 0, 0, 0, 0 } }; diff --git a/Source/cmVS11MASMFlagTable.h b/Source/cmVS11MASMFlagTable.h index 1aca169bd..fdf8239da 100644 --- a/Source/cmVS11MASMFlagTable.h +++ b/Source/cmVS11MASMFlagTable.h @@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS11MASMFlagTable[] = { // Enum Properties { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1", + { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", 0 }, - { "PreserveIdentifierCase", "/Cu", + { "PreserveIdentifierCase", "Cu", "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "/Cx", + { "PreserveIdentifierCase", "Cx", "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 }, + { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, + { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, + { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, + { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5", - 0 }, + { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, + { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, + { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, + { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, + { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2", + { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", 0 }, - { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3", + { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", 0 }, + { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - { "ErrorReporting", "/errorReport:prompt", + { "ErrorReporting", "errorReport:prompt", "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "/errorReport:queue", + { "ErrorReporting", "errorReport:queue", "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "/errorReport:send", + { "ErrorReporting", "errorReport:send", "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "/errorReport:none", + { "ErrorReporting", "errorReport:none", "Do not send report (/errorReport:none)", "3", 0 }, // Bool Properties - { "NoLogo", "/nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 }, - { "ListAllAvailableInformation", "/Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 }, - { "AddFirstPassListing", "/Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 }, - { "DisableSymbolTable", "/Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "/WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 }, - { "GenerateDebugInformation", "/Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "/Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 }, + { "NoLogo", "nologo", "", "true", 0 }, + { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, + { "ListAllAvailableInformation", "Sa", "", "true", 0 }, + { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, + { "AddFirstPassListing", "Sf", "", "true", 0 }, + { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, + { "DisableSymbolTable", "Sn", "", "true", 0 }, + { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, + { "TreatWarningsAsErrors", "WX", "", "true", 0 }, + { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, + { "GenerateDebugInformation", "Zi", "", "true", 0 }, + { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, + { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, // Bool Properties With Argument // String List Properties - { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "", + { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "/I", "Include Paths", "", + { "IncludePaths", "I", "Include Paths", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "/FR", "Generate Browse Information File", "", + { "BrowseFile", "FR", "Generate Browse Information File", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, // Skip [AdditionalDependencies] - no command line Switch. // String Properties // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "/Fo", "Object File Name", "", + { "ObjectFileName", "Fo", "Object File Name", "", cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "", + { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", cmVS7FlagTable::UserValue }, // Skip [CommandLineTemplate] - no command line Switch. // Skip [ExecutionDescription] - no command line Switch. diff --git a/Source/cmVS11RCFlagTable.h b/Source/cmVS11RCFlagTable.h index 666e4344a..4997fe115 100644 --- a/Source/cmVS11RCFlagTable.h +++ b/Source/cmVS11RCFlagTable.h @@ -1,6 +1,7 @@ static cmVS7FlagTable cmVS11RCFlagTable[] = { // Bool Properties { "NullTerminateStrings", "n", "", "true", 0 }, + { "SuppressStartupBanner", "nologo", "", "true", 0 }, { 0, 0, 0, 0, 0 } }; diff --git a/Source/cmVS12MASMFlagTable.h b/Source/cmVS12MASMFlagTable.h index a7e4a80a9..acc0d48e1 100644 --- a/Source/cmVS12MASMFlagTable.h +++ b/Source/cmVS12MASMFlagTable.h @@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS12MASMFlagTable[] = { // Enum Properties { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1", + { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", 0 }, - { "PreserveIdentifierCase", "/Cu", + { "PreserveIdentifierCase", "Cu", "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "/Cx", + { "PreserveIdentifierCase", "Cx", "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 }, + { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, + { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, + { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, + { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5", - 0 }, + { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, + { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, + { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, + { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, + { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2", + { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", 0 }, - { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3", + { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", 0 }, + { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - { "ErrorReporting", "/errorReport:prompt", + { "ErrorReporting", "errorReport:prompt", "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "/errorReport:queue", + { "ErrorReporting", "errorReport:queue", "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "/errorReport:send", + { "ErrorReporting", "errorReport:send", "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "/errorReport:none", + { "ErrorReporting", "errorReport:none", "Do not send report (/errorReport:none)", "3", 0 }, // Bool Properties - { "NoLogo", "/nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 }, - { "ListAllAvailableInformation", "/Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 }, - { "AddFirstPassListing", "/Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 }, - { "DisableSymbolTable", "/Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "/WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 }, - { "GenerateDebugInformation", "/Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "/Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 }, + { "NoLogo", "nologo", "", "true", 0 }, + { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, + { "ListAllAvailableInformation", "Sa", "", "true", 0 }, + { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, + { "AddFirstPassListing", "Sf", "", "true", 0 }, + { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, + { "DisableSymbolTable", "Sn", "", "true", 0 }, + { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, + { "TreatWarningsAsErrors", "WX", "", "true", 0 }, + { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, + { "GenerateDebugInformation", "Zi", "", "true", 0 }, + { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, + { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, // Bool Properties With Argument // String List Properties - { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "", + { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "/I", "Include Paths", "", + { "IncludePaths", "I", "Include Paths", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "/FR", "Generate Browse Information File", "", + { "BrowseFile", "FR", "Generate Browse Information File", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, // Skip [AdditionalDependencies] - no command line Switch. // String Properties // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "/Fo", "Object File Name", "", + { "ObjectFileName", "Fo", "Object File Name", "", cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "", + { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", cmVS7FlagTable::UserValue }, // Skip [CommandLineTemplate] - no command line Switch. // Skip [ExecutionDescription] - no command line Switch. diff --git a/Source/cmVS12RCFlagTable.h b/Source/cmVS12RCFlagTable.h index d047f824b..a650f8522 100644 --- a/Source/cmVS12RCFlagTable.h +++ b/Source/cmVS12RCFlagTable.h @@ -1,6 +1,7 @@ static cmVS7FlagTable cmVS12RCFlagTable[] = { // Bool Properties { "NullTerminateStrings", "n", "", "true", 0 }, + { "SuppressStartupBanner", "nologo", "", "true", 0 }, { 0, 0, 0, 0, 0 } }; diff --git a/Source/cmVS14LinkFlagTable.h b/Source/cmVS140LinkFlagTable.h similarity index 97% rename from Source/cmVS14LinkFlagTable.h rename to Source/cmVS140LinkFlagTable.h index 596f88095..b9a4dc30a 100644 --- a/Source/cmVS14LinkFlagTable.h +++ b/Source/cmVS140LinkFlagTable.h @@ -1,4 +1,4 @@ -static cmVS7FlagTable cmVS14LinkFlagTable[] = { +static cmVS7FlagTable cmVS140LinkFlagTable[] = { // Enum Properties { "ShowProgress", "", "Not Set", "NotSet", 0 }, @@ -38,7 +38,12 @@ static cmVS7FlagTable cmVS14LinkFlagTable[] = { { "GenerateDebugInformation", "DEBUG:FASTLINK", "Optimize for faster linking", "DebugFastLink", cmVS7FlagTable::CaseInsensitive }, - { "GenerateDebugInformation", "DEBUG", "Optimize for debugging", "Debug", + { "GenerateDebugInformation", "DEBUG:FULL", "Optimize for debugging", "true", + cmVS7FlagTable::CaseInsensitive }, + { "GenerateDebugInformation", "DEBUG:NONE", + "Produces no debugging information", "false", + cmVS7FlagTable::CaseInsensitive }, + { "GenerateDebugInformation", "DEBUG", "Optimize for debugging", "true", cmVS7FlagTable::CaseInsensitive }, { "SubSystem", "", "Not Set", "NotSet", 0 }, @@ -129,9 +134,6 @@ static cmVS7FlagTable cmVS14LinkFlagTable[] = { { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only", "SystemDlls", 0 }, - { "LinkControlFlowGuard", "guard:cf", "Enable Security Check with Guard", - "Guard", 0 }, - // Bool Properties { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 }, { "LinkIncremental", "INCREMENTAL", "", "true", 0 }, diff --git a/Source/cmVS141LinkFlagTable.h b/Source/cmVS141LinkFlagTable.h new file mode 100644 index 000000000..8f0f1f42d --- /dev/null +++ b/Source/cmVS141LinkFlagTable.h @@ -0,0 +1,283 @@ +static cmVS7FlagTable cmVS141LinkFlagTable[] = { + + // Enum Properties + { "ShowProgress", "", "Not Set", "NotSet", 0 }, + { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose", + 0 }, + { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib", + 0 }, + { "ShowProgress", "VERBOSE:ICF", + "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 }, + { "ShowProgress", "VERBOSE:REF", + "About data removed during optimized linking", "LinkVerboseREF", 0 }, + { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH", + "LinkVerboseSAFESEH", 0 }, + { "ShowProgress", "VERBOSE:CLR", + "About linker activity related to managed code", "LinkVerboseCLR", 0 }, + + { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 }, + { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only", + "MultiplyDefinedSymbolOnly", 0 }, + { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only", + "UndefinedSymbolOnly", 0 }, + + { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 }, + { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only", + "X86Image", 0 }, + { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only", + "X64Image", 0 }, + { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", + "ItaniumImage", 0 }, + + { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, + { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", + "HighestAvailable", 0 }, + { "UACExecutionLevel", "level='requireAdministrator'", + "requireAdministrator", "RequireAdministrator", 0 }, + + { "GenerateDebugInformation", "DEBUG:FASTLINK", + "Generate Debug Information optimized for faster links", "DebugFastLink", + cmVS7FlagTable::CaseInsensitive }, + { "GenerateDebugInformation", "DEBUG:FULL", + "Generate Debug Information optimized for sharing and publishing", + "DebugFull", cmVS7FlagTable::CaseInsensitive }, + { "GenerateDebugInformation", "DEBUG:NONE", + "Produces no debugging information", "false", + cmVS7FlagTable::CaseInsensitive }, + { "GenerateDebugInformation", "DEBUG", "Generate Debug Information", "true", + cmVS7FlagTable::CaseInsensitive }, + + { "SubSystem", "", "Not Set", "NotSet", 0 }, + { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 }, + { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 }, + { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 }, + { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application", + "EFI Application", 0 }, + { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", + "EFI Boot Service Driver", "EFI Boot Service Driver", 0 }, + { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 }, + { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime", + 0 }, + { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 }, + + { "Driver", "", "Not Set", "NotSet", 0 }, + { "Driver", "Driver", "Driver", "Driver", 0 }, + { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 }, + { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 }, + + { "LinkTimeCodeGeneration", "", "Default", "Default", 0 }, + { "LinkTimeCodeGeneration", "LTCG:incremental", + "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 }, + { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation", + "UseLinkTimeCodeGeneration", 0 }, + { "LinkTimeCodeGeneration", "LTCG:PGInstrument", + "Profile Guided Optimization - Instrument", "PGInstrument", 0 }, + { "LinkTimeCodeGeneration", "LTCG:PGOptimize", + "Profile Guided Optimization - Optimization", "PGOptimization", 0 }, + { "LinkTimeCodeGeneration", "LTCG:PGUpdate", + "Profile Guided Optimization - Update", "PGUpdate", 0 }, + + { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 }, + { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 }, + + { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, + { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, + { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, + { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, + + { "TargetMachine", "", "Not Set", "NotSet", 0 }, + { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 }, + { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 }, + { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 }, + { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 }, + { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 }, + { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU", + 0 }, + { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16", + "MachineMIPSFPU16", 0 }, + { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 }, + { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 }, + { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 }, + { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 }, + + { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute", + "MTAThreadingAttribute", 0 }, + { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute", + "STAThreadingAttribute", 0 }, + { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE", + "Default threading attribute", "DefaultThreadingAttribute", 0 }, + + { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage", + 0 }, + { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image", + "ForcePureILImage", 0 }, + { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image", + "ForceSafeILImage", 0 }, + { "CLRImageType", "", "Default image type", "Default", 0 }, + + { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 }, + { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 }, + { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 }, + { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 }, + + { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately", + "PromptImmediately", 0 }, + { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login", + "QueueForNextLogin", 0 }, + { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report", + "SendErrorReport", 0 }, + { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report", + "NoErrorReport", 0 }, + + { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 }, + { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled", + 0 }, + { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only", + "SystemDlls", 0 }, + + // Bool Properties + { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 }, + { "LinkIncremental", "INCREMENTAL", "", "true", 0 }, + { "SuppressStartupBanner", "NOLOGO", "", "true", 0 }, + { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 }, + { "LinkStatus", "LTCG:STATUS", "", "true", 0 }, + { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 }, + { "PreventDllBinding", "ALLOWBIND", "", "true", 0 }, + { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 }, + { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 }, + { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 }, + { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, + { "GenerateManifest", "MANIFEST", "", "true", 0 }, + { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, + { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, + { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, + { "ManifestEmbed", "manifest:embed", "", "true", 0 }, + { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, + { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, + { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 }, + { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 }, + { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 }, + { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 }, + { "TerminalServerAware", "TSAWARE", "", "true", 0 }, + { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 }, + { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 }, + { "OptimizeReferences", "OPT:NOREF", "", "false", 0 }, + { "OptimizeReferences", "OPT:REF", "", "true", 0 }, + { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 }, + { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 }, + { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 }, + { "AppContainer", "APPCONTAINER", "", "true", 0 }, + { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 }, + { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 }, + { "NoEntryPoint", "NOENTRY", "", "true", 0 }, + { "SetChecksum", "RELEASE", "", "true", 0 }, + { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 }, + { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 }, + { "FixedBaseAddress", "FIXED:NO", "", "false", 0 }, + { "FixedBaseAddress", "FIXED", "", "true", 0 }, + { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 }, + { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 }, + { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 }, + { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 }, + { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 }, + { "Profile", "PROFILE", "", "true", 0 }, + { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 }, + { "LinkDelaySign", "DELAYSIGN", "", "true", 0 }, + { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 }, + { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 }, + { "DetectOneDefinitionRule", "ODR", "", "true", 0 }, + { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 }, + { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 }, + { "LinkDLL", "DLL", "", "true", 0 }, + + // Bool Properties With Argument + { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 }, + { "EnableUAC", "MANIFESTUAC:", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "", + cmVS7FlagTable::UserValueRequired }, + { "GenerateMapFile", "MAP", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "MapFileName", "MAP:", "Generate Map File", "", + cmVS7FlagTable::UserValueRequired }, + + // String List Properties + { "AdditionalLibraryDirectories", "LIBPATH:", + "Additional Library Directories", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "Natvis", "NATVIS:", "Natvis files", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + // Skip [AdditionalDependencies] - no command line Switch. + { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:", + "Ignore Specific Default Libraries", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:", + "Embed Managed Resource File", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:", + "Additional Manifest Dependencies", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "ManifestInput", "manifestinput:", "Manifest Input", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + + // String Properties + { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue }, + { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue }, + { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "", + cmVS7FlagTable::UserValue }, + { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "", + cmVS7FlagTable::UserValue }, + // Skip [TrackerLogDirectory] - no command line Switch. + { "ModuleDefinitionFile", "DEF:", "Module Definition File", "", + cmVS7FlagTable::UserValue }, + { "ManifestFile", "ManifestFile:", "Manifest File", "", + cmVS7FlagTable::UserValue }, + { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "", + cmVS7FlagTable::UserValue }, + { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "", + cmVS7FlagTable::UserValue }, + // Skip [MapFileName] - no command line Switch. + // Skip [MinimumRequiredVersion] - no command line Switch. + { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "", + cmVS7FlagTable::UserValue }, + // Skip [HeapCommitSize] - no command line Switch. + { "StackReserveSize", "STACK:", "Stack Reserve Size", "", + cmVS7FlagTable::UserValue }, + // Skip [StackCommitSize] - no command line Switch. + { "FunctionOrder", "ORDER:@", "Function Order", "", + cmVS7FlagTable::UserValue }, + { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "", + cmVS7FlagTable::UserValue }, + { "MidlCommandFile", "MIDL:@", "MIDL Commands", "", + cmVS7FlagTable::UserValue }, + { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "", + cmVS7FlagTable::UserValue }, + { "TypeLibraryFile", "TLBOUT:", "Type Library", "", + cmVS7FlagTable::UserValue }, + { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "", + cmVS7FlagTable::UserValue }, + { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File", + "", cmVS7FlagTable::UserValue }, + { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:", + "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue }, + { "EntryPointSymbol", "ENTRY:", "Entry Point", "", + cmVS7FlagTable::UserValue }, + { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue }, + { "ImportLibrary", "IMPLIB:", "Import Library", "", + cmVS7FlagTable::UserValue }, + { "MergeSections", "MERGE:", "Merge Sections", "", + cmVS7FlagTable::UserValue }, + { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue }, + { "KeyContainer", "KEYCONTAINER:", "Key Container", "", + cmVS7FlagTable::UserValue }, + // Skip [AdditionalOptions] - no command line Switch. + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVS14MASMFlagTable.h b/Source/cmVS14MASMFlagTable.h index c4e5e1e5d..82ec9f1d0 100644 --- a/Source/cmVS14MASMFlagTable.h +++ b/Source/cmVS14MASMFlagTable.h @@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS14MASMFlagTable[] = { // Enum Properties { "PreserveIdentifierCase", "", "Default", "0", 0 }, - { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1", + { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1", 0 }, - { "PreserveIdentifierCase", "/Cu", + { "PreserveIdentifierCase", "Cu", "Maps all identifiers to upper case. (/Cu)", "2", 0 }, - { "PreserveIdentifierCase", "/Cx", + { "PreserveIdentifierCase", "Cx", "Preserves case in public and extern symbols. (/Cx)", "3", 0 }, - { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 }, - { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 }, - { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 }, - { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 }, + { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 }, + { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 }, + { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 }, + { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 }, { "PackAlignmentBoundary", "", "Default", "0", 0 }, - { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, - { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, - { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, - { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, - { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5", - 0 }, + { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 }, + { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 }, + { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 }, + { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 }, + { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 }, { "CallingConvention", "", "Default", "0", 0 }, - { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1", - 0 }, - { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2", + { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1", 0 }, - { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3", + { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2", 0 }, + { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 }, - { "ErrorReporting", "/errorReport:prompt", + { "ErrorReporting", "errorReport:prompt", "Prompt to send report immediately (/errorReport:prompt)", "0", 0 }, - { "ErrorReporting", "/errorReport:queue", + { "ErrorReporting", "errorReport:queue", "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 }, - { "ErrorReporting", "/errorReport:send", + { "ErrorReporting", "errorReport:send", "Automatically send report (/errorReport:send)", "2", 0 }, - { "ErrorReporting", "/errorReport:none", + { "ErrorReporting", "errorReport:none", "Do not send report (/errorReport:none)", "3", 0 }, // Bool Properties - { "NoLogo", "/nologo", "", "true", 0 }, - { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 }, - { "ListAllAvailableInformation", "/Sa", "", "true", 0 }, - { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 }, - { "AddFirstPassListing", "/Sf", "", "true", 0 }, - { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 }, - { "DisableSymbolTable", "/Sn", "", "true", 0 }, - { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 }, - { "TreatWarningsAsErrors", "/WX", "", "true", 0 }, - { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 }, - { "GenerateDebugInformation", "/Zi", "", "true", 0 }, - { "EnableMASM51Compatibility", "/Zm", "", "true", 0 }, - { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 }, + { "NoLogo", "nologo", "", "true", 0 }, + { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 }, + { "ListAllAvailableInformation", "Sa", "", "true", 0 }, + { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 }, + { "AddFirstPassListing", "Sf", "", "true", 0 }, + { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 }, + { "DisableSymbolTable", "Sn", "", "true", 0 }, + { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 }, + { "TreatWarningsAsErrors", "WX", "", "true", 0 }, + { "MakeAllSymbolsPublic", "Zf", "", "true", 0 }, + { "GenerateDebugInformation", "Zi", "", "true", 0 }, + { "EnableMASM51Compatibility", "Zm", "", "true", 0 }, + { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 }, // Bool Properties With Argument // String List Properties - { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "", + { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "IncludePaths", "/I", "Include Paths", "", + { "IncludePaths", "I", "Include Paths", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, - { "BrowseFile", "/FR", "Generate Browse Information File", "", + { "BrowseFile", "FR", "Generate Browse Information File", "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, // Skip [AdditionalDependencies] - no command line Switch. // String Properties // Skip [Inputs] - no command line Switch. - { "ObjectFileName", "/Fo", "Object File Name", "", + { "ObjectFileName", "Fo", "Object File Name", "", cmVS7FlagTable::UserValue }, - { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "", + { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "", cmVS7FlagTable::UserValue }, // Skip [CommandLineTemplate] - no command line Switch. // Skip [ExecutionDescription] - no command line Switch. diff --git a/Source/cmVS14RCFlagTable.h b/Source/cmVS14RCFlagTable.h index 11e00d513..5dc8d5ada 100644 --- a/Source/cmVS14RCFlagTable.h +++ b/Source/cmVS14RCFlagTable.h @@ -1,6 +1,7 @@ static cmVS7FlagTable cmVS14RCFlagTable[] = { // Bool Properties { "NullTerminateStrings", "n", "", "true", 0 }, + { "SuppressStartupBanner", "nologo", "", "true", 0 }, { 0, 0, 0, 0, 0 } }; diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index c2ff66453..7168f266c 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVSSetupHelper.h" +#include "cmSystemTools.h" #ifndef VSSetupConstants #define VSSetupConstants @@ -240,6 +241,22 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() setupHelper == NULL) return false; + std::string envVSCommonToolsDir; + + // FIXME: When we support VS versions beyond 2017, the version + // to choose will be passed in by the caller. We need to map that + // to a per-version name of this environment variable. + if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) { + cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir); + } + // FIXME: If the environment variable value changes between runs + // of CMake within a given build tree the results are not defined. + // Instead we should save a CMAKE_GENERATOR_INSTANCE value in the cache + // (similar to CMAKE_GENERATOR_TOOLSET) to hold it persistently. + // Unfortunately doing so will require refactoring elsewhere in + // order to make sure the value is available in time to create + // the generator. + std::vector vecVSInstances; SmartCOMPtr enumInstances = NULL; if (FAILED( @@ -263,6 +280,17 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() instance = instance2 = NULL; if (isInstalled) { + if (!envVSCommonToolsDir.empty()) { + std::string currentVSLocation(instanceInfo.VSInstallLocation.begin(), + instanceInfo.VSInstallLocation.end()); + cmSystemTools::ConvertToUnixSlashes(currentVSLocation); + currentVSLocation += "/Common7/Tools"; + if (cmSystemTools::ComparePath(currentVSLocation, + envVSCommonToolsDir)) { + chosenInstanceInfo = instanceInfo; + return true; + } + } vecVSInstances.push_back(instanceInfo); } } diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index 1eb1f20ca..06ca53c0a 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -3,7 +3,6 @@ #include "cmVariableRequiresCommand.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmState.h" #include "cmSystemTools.h" @@ -13,21 +12,16 @@ class cmExecutionStatus; bool cmVariableRequiresCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0035, - "The variable_requires command should not be called; see CMP0035.")) { - return true; - } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; } - std::string testVariable = args[0]; + std::string const& testVariable = args[0]; if (!this->Makefile->IsOn(testVariable)) { return true; } - std::string resultVariable = args[1]; + std::string const& resultVariable = args[1]; bool requirementsMet = true; std::string notSet; bool hasAdvanced = false; diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h index baf717c66..9808d5f0c 100644 --- a/Source/cmVariableRequiresCommand.h +++ b/Source/cmVariableRequiresCommand.h @@ -3,7 +3,8 @@ #ifndef cmVariableRequiresCommand_h #define cmVariableRequiresCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -17,7 +18,6 @@ public: cmCommand* Clone() CM_OVERRIDE { return new cmVariableRequiresCommand; } bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - std::string GetName() const CM_OVERRIDE { return "variable_requires"; } }; #endif diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx index c94ce17c2..419e1a411 100644 --- a/Source/cmVariableWatch.cxx +++ b/Source/cmVariableWatch.cxx @@ -4,8 +4,8 @@ #include "cmAlgorithms.h" +#include "cm_auto_ptr.hxx" #include -#include #include static const char* const cmVariableWatchAccessStrings[] = { diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h index 0b8b433ec..a575afe9d 100644 --- a/Source/cmVariableWatch.h +++ b/Source/cmVariableWatch.h @@ -3,7 +3,7 @@ #ifndef cmVariableWatch_h #define cmVariableWatch_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index 90b0b2864..281850ecc 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -106,7 +106,7 @@ bool cmVariableWatchCommand::InitialPass(std::vector const& args, this->SetError("must be called with at least one argument."); return false; } - std::string variable = args[0]; + std::string const& variable = args[0]; std::string command; if (args.size() > 1) { command = args[1]; diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h index 919bac4ec..9f0439175 100644 --- a/Source/cmVariableWatchCommand.h +++ b/Source/cmVariableWatchCommand.h @@ -3,7 +3,8 @@ #ifndef cmVariableWatchCommand_h #define cmVariableWatchCommand_h -#include +#include "cmConfigure.h" + #include #include #include @@ -37,20 +38,10 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - /** This command does not really have a final pass but it needs to stay alive since it owns variable watch callback information. */ bool HasFinalPass() const CM_OVERRIDE { return true; } - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "variable_watch"; } - protected: std::set WatchedVariables; }; diff --git a/Source/cmVersion.h b/Source/cmVersion.h index e77ec99b4..bfd994d09 100644 --- a/Source/cmVersion.h +++ b/Source/cmVersion.h @@ -3,7 +3,7 @@ #ifndef cmVersion_h #define cmVersion_h -#include +#include "cm_kwiml.h" /** \class cmVersion * \brief Helper class for providing CMake and CTest version information. diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 902fe0328..88fa19c60 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVisualStudio10TargetGenerator.h" +#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" #include "cmGeneratedFileStream.h" @@ -10,12 +11,11 @@ #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmSystemTools.h" #include "cmVisualStudioGeneratorOptions.h" #include "windows.h" -#include - -static std::string const kWINDOWS_7_1_SDK = "Windows7.1SDK"; +#include "cm_auto_ptr.hxx" static std::string cmVS10EscapeXML(std::string arg) { @@ -111,6 +111,14 @@ cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() i != this->LinkOptions.end(); ++i) { delete i->second; } + for (OptionsMap::iterator i = this->CudaOptions.begin(); + i != this->CudaOptions.end(); ++i) { + delete i->second; + } + for (OptionsMap::iterator i = this->CudaLinkOptions.begin(); + i != this->CudaLinkOptions.end(); ++i) { + delete i->second; + } if (!this->BuildFileStream) { return; } @@ -205,9 +213,18 @@ void cmVisualStudio10TargetGenerator::Generate() if (!this->ComputeRcOptions()) { return; } + if (!this->ComputeCudaOptions()) { + return; + } + if (!this->ComputeCudaLinkOptions()) { + return; + } if (!this->ComputeMasmOptions()) { return; } + if (!this->ComputeNasmOptions()) { + return; + } if (!this->ComputeLinkOptions()) { return; } @@ -279,8 +296,8 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteProjectConfigurations(); } this->WriteString("\n", 1); - this->WriteString("", 2); - (*this->BuildFileStream) << "{" << this->GUID << "}\n"; + this->WriteString("", 2); + (*this->BuildFileStream) << "{" << this->GUID << "}\n"; if (this->MSTools && this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) { @@ -450,11 +467,34 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString("\n", 1); } this->WriteString("\n", 1); + if (this->GlobalGenerator->IsCudaEnabled()) { + this->WriteString("BuildFileStream) + << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString()) + << ".props\" />\n"; + } if (this->GlobalGenerator->IsMasmEnabled()) { this->WriteString("\n", 2); } + if (this->GlobalGenerator->IsNasmEnabled()) { + // Always search in the standard modules location. + std::string propsTemplate = + GetCMakeFilePath("Templates/MSBuild/nasm.props.in"); + + std::string propsLocal; + propsLocal += this->DefaultArtifactDir; + propsLocal += "\\nasm.props"; + this->ConvertToWindowsSlash(propsLocal); + this->Makefile->ConfigureFile(propsTemplate.c_str(), propsLocal.c_str(), + false, true, true); + std::string import = std::string("\n"; + this->WriteString(import.c_str(), 2); + } this->WriteString("\n", 1); this->WriteString("\n", 1); { @@ -505,11 +545,26 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteTargetSpecificReferences(); this->WriteString("\n", 1); this->WriteTargetsFileReferences(); + if (this->GlobalGenerator->IsCudaEnabled()) { + this->WriteString("BuildFileStream) + << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString()) + << ".targets\" />\n"; + } if (this->GlobalGenerator->IsMasmEnabled()) { this->WriteString("\n", 2); } + if (this->GlobalGenerator->IsNasmEnabled()) { + std::string nasmTargets = + GetCMakeFilePath("Templates/MSBuild/nasm.targets"); + std::string import = "\n"; + this->WriteString(import.c_str(), 2); + } this->WriteString("\n", 1); if (csproj == this->ProjectType) { for (std::vector::const_iterator i = @@ -926,19 +981,21 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( const char* mfcFlag = this->GeneratorTarget->Target->GetMakefile()->GetDefinition( "CMAKE_MFC_FLAG"); - std::string mfcFlagValue = mfcFlag ? mfcFlag : "0"; + if (mfcFlag) { + std::string const mfcFlagValue = mfcFlag; - std::string useOfMfcValue = "false"; - if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) { - if (mfcFlagValue == "1") { - useOfMfcValue = "Static"; - } else if (mfcFlagValue == "2") { - useOfMfcValue = "Dynamic"; + std::string useOfMfcValue = "false"; + if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) { + if (mfcFlagValue == "1") { + useOfMfcValue = "Static"; + } else if (mfcFlagValue == "2") { + useOfMfcValue = "Dynamic"; + } } + std::string mfcLine = ""; + mfcLine += useOfMfcValue + "\n"; + this->WriteString(mfcLine.c_str(), 2); } - std::string mfcLine = ""; - mfcLine += useOfMfcValue + "\n"; - this->WriteString(mfcLine.c_str(), 2); if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY && this->ClOptions[config]->UsingUnicode()) || @@ -1002,8 +1059,8 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( std::string postfixName = cmSystemTools::UpperCase(config); postfixName += "_POSTFIX"; - std::string assemblyName = - this->GeneratorTarget->GetOutputName(config, false); + std::string assemblyName = this->GeneratorTarget->GetOutputName( + config, cmStateEnums::RuntimeBinaryArtifact); if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) { assemblyName += postfix; } @@ -1192,16 +1249,15 @@ void cmVisualStudio10TargetGenerator::WriteGroups() // collect up group information std::vector sourceGroups = this->Makefile->GetSourceGroups(); - std::vector classes; - if (!this->GeneratorTarget->GetConfigCommonSourceFiles(classes)) { - return; - } + + std::vector const& sources = + this->GeneratorTarget->GetAllConfigSources(); std::set groupsUsed; - for (std::vector::const_iterator s = classes.begin(); - s != classes.end(); s++) { - cmSourceFile* sf = *s; - std::string const& source = sf->GetFullPath(); + for (std::vector::const_iterator si = + sources.begin(); + si != sources.end(); ++si) { + std::string const& source = si->Source->GetFullPath(); cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); groupsUsed.insert(sourceGroup); @@ -1288,23 +1344,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteString("\n", 1); } - // Add object library contents as external objects. - std::vector objs; - this->GeneratorTarget->UseObjectLibraries(objs, ""); - if (!objs.empty()) { - this->WriteString("\n", 1); - for (std::vector::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - std::string obj = *oi; - this->WriteString("ConvertToWindowsSlash(obj); - (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n"; - this->WriteString("Object Libraries\n", 3); - this->WriteString("\n", 2); - } - this->WriteString("\n", 1); - } - this->WriteString("\n", 1); for (std::set::iterator g = groupsUsed.begin(); g != groupsUsed.end(); ++g) { @@ -1322,15 +1361,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteString("\n", 2); } } - if (!objs.empty()) { - this->WriteString("\n", 2); - std::string guidName = "SG_Filter_Object Libraries"; - this->WriteString("", 3); - std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str()); - (*this->BuildFileStream) << "{" << guid << "}" - << "\n"; - this->WriteString("\n", 2); - } if (!resxObjs.empty() || !this->AddedFiles.empty()) { this->WriteString("\n", 2); @@ -1668,8 +1698,10 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool, // // and fail if this exceeds the maximum allowed path length. Our path // conversion uses full paths when possible to allow deeper trees. - bool forceRelative = false; - std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false); + // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA + // we must use relative paths. + bool forceRelative = sf->GetLanguage() == "CUDA"; + std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative); if (this->LocalGenerator->GetVersion() == cmGlobalVisualStudioGenerator::VS10 && cmSystemTools::FileIsFullPath(sourceFile.c_str())) { @@ -1702,15 +1734,6 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool, this->Tools[tool].push_back(toolSource); } -void cmVisualStudio10TargetGenerator::WriteSources( - std::string const& tool, std::vector const& sources) -{ - for (std::vector::const_iterator si = sources.begin(); - si != sources.end(); ++si) { - this->WriteSource(tool, *si); - } -} - void cmVisualStudio10TargetGenerator::WriteAllSources() { if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) { @@ -1718,105 +1741,121 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } this->WriteString("\n", 1); - std::vector headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources, ""); - for (std::vector::const_iterator si = - headerSources.begin(); - si != headerSources.end(); ++si) { - this->WriteHeaderSource(*si); + std::vector all_configs; + for (size_t ci = 0; ci < this->Configurations.size(); ++ci) { + all_configs.push_back(ci); } - std::vector idlSources; - this->GeneratorTarget->GetIDLSources(idlSources, ""); - this->WriteSources("Midl", idlSources); - std::vector objectSources; - this->GeneratorTarget->GetObjectSources(objectSources, ""); - for (std::vector::const_iterator si = - objectSources.begin(); - si != objectSources.end(); ++si) { - const std::string& lang = (*si)->GetLanguage(); + std::vector const& sources = + this->GeneratorTarget->GetAllConfigSources(); + + for (std::vector::const_iterator si = + sources.begin(); + si != sources.end(); ++si) { std::string tool; - if (lang == "C" || lang == "CXX") { - tool = "ClCompile"; - } else if (lang == "ASM_MASM" && this->GlobalGenerator->IsMasmEnabled()) { - tool = "MASM"; - } else if (lang == "RC") { - tool = "ResourceCompile"; - } else if (lang == "CSharp") { - tool = "Compile"; + switch (si->Kind) { + case cmGeneratorTarget::SourceKindAppManifest: + tool = "AppxManifest"; + break; + case cmGeneratorTarget::SourceKindCertificate: + tool = "None"; + break; + case cmGeneratorTarget::SourceKindCustomCommand: + // Handled elsewhere. + break; + case cmGeneratorTarget::SourceKindExternalObject: + tool = "Object"; + if (this->LocalGenerator->GetVersion() < + cmGlobalVisualStudioGenerator::VS11) { + // For VS == 10 we cannot use LinkObjects to avoid linking custom + // command outputs. If an object file is generated in this target, + // then vs10 will use it in the build, and we have to list it as + // None instead of Object. + std::vector const* d = + this->GeneratorTarget->GetSourceDepends(si->Source); + if (d && !d->empty()) { + tool = "None"; + } + } + break; + case cmGeneratorTarget::SourceKindExtra: + this->WriteExtraSource(si->Source); + break; + case cmGeneratorTarget::SourceKindHeader: + this->WriteHeaderSource(si->Source); + break; + case cmGeneratorTarget::SourceKindIDL: + tool = "Midl"; + break; + case cmGeneratorTarget::SourceKindManifest: + // Handled elsewhere. + break; + case cmGeneratorTarget::SourceKindModuleDefinition: + tool = "None"; + break; + case cmGeneratorTarget::SourceKindObjectSource: { + const std::string& lang = si->Source->GetLanguage(); + if (lang == "C" || lang == "CXX") { + tool = "ClCompile"; + } else if (lang == "ASM_MASM" && + this->GlobalGenerator->IsMasmEnabled()) { + tool = "MASM"; + } else if (lang == "ASM_NASM" && + this->GlobalGenerator->IsNasmEnabled()) { + tool = "NASM"; + } else if (lang == "RC") { + tool = "ResourceCompile"; + } else if (lang == "CSharp") { + tool = "Compile"; + } else if (lang == "CUDA" && this->GlobalGenerator->IsCudaEnabled()) { + tool = "CudaCompile"; + } else { + tool = "None"; + } + } break; + case cmGeneratorTarget::SourceKindResx: + // Handled elsewhere. + break; + case cmGeneratorTarget::SourceKindXaml: + // Handled elsewhere. + break; } if (!tool.empty()) { - this->WriteSource(tool, *si, " "); - if (this->OutputSourceSpecificFlags(*si)) { + // Compute set of configurations to exclude, if any. + std::vector const& include_configs = si->Configs; + std::vector exclude_configs; + std::set_difference(all_configs.begin(), all_configs.end(), + include_configs.begin(), include_configs.end(), + std::back_inserter(exclude_configs)); + + if (si->Kind == cmGeneratorTarget::SourceKindObjectSource) { + // FIXME: refactor generation to avoid tracking XML syntax state. + this->WriteSource(tool, si->Source, " "); + bool have_nested = this->OutputSourceSpecificFlags(si->Source); + if (!exclude_configs.empty()) { + if (!have_nested) { + (*this->BuildFileStream) << ">\n"; + } + this->WriteExcludeFromBuild(exclude_configs); + have_nested = true; + } + if (have_nested) { + this->WriteString("BuildFileStream) << tool << ">\n"; + } else { + (*this->BuildFileStream) << " />\n"; + } + } else if (!exclude_configs.empty()) { + this->WriteSource(tool, si->Source, ">\n"); + this->WriteExcludeFromBuild(exclude_configs); this->WriteString("BuildFileStream) << tool << ">\n"; } else { - (*this->BuildFileStream) << " />\n"; + this->WriteSource(tool, si->Source); } - } else { - this->WriteSource("None", *si); - } - } - - std::vector manifestSources; - this->GeneratorTarget->GetAppManifest(manifestSources, ""); - this->WriteSources("AppxManifest", manifestSources); - - std::vector certificateSources; - this->GeneratorTarget->GetCertificates(certificateSources, ""); - this->WriteSources("None", certificateSources); - - std::vector externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects, ""); - for (std::vector::iterator si = externalObjects.begin(); - si != externalObjects.end();) { - if (!(*si)->GetObjectLibrary().empty()) { - si = externalObjects.erase(si); - } else { - ++si; } } - if (this->LocalGenerator->GetVersion() > - cmGlobalVisualStudioGenerator::VS10) { - // For VS >= 11 we use LinkObjects to avoid linking custom command - // outputs. Use Object for all external objects, generated or not. - this->WriteSources("Object", externalObjects); - } else { - // If an object file is generated in this target, then vs10 will use - // it in the build, and we have to list it as None instead of Object. - for (std::vector::const_iterator si = - externalObjects.begin(); - si != externalObjects.end(); ++si) { - std::vector const* d = - this->GeneratorTarget->GetSourceDepends(*si); - this->WriteSource((d && !d->empty()) ? "None" : "Object", *si); - } - } - - std::vector extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, ""); - for (std::vector::const_iterator si = - extraSources.begin(); - si != extraSources.end(); ++si) { - this->WriteExtraSource(*si); - } - - // Add object library contents as external objects. - std::vector objs; - this->GeneratorTarget->UseObjectLibraries(objs, ""); - for (std::vector::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - std::string obj = *oi; - this->WriteString("ConvertToWindowsSlash(obj); - (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\" />\n"; - } - - if (cmSourceFile const* defsrc = - this->GeneratorTarget->GetModuleDefinitionFile("")) { - this->WriteSource("None", defsrc); - } if (this->IsMissingFiles) { this->WriteMissingFiles(); @@ -1850,7 +1889,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( std::string lang = this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str()); std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf); - const std::string& linkLanguage = this->GeneratorTarget->GetLinkerLanguage(); + const std::string& linkLanguage = + this->GeneratorTarget->GetLinkerLanguage(""); bool needForceLang = false; // source file does not match its extension language if (lang != sourceLang) { @@ -1904,9 +1944,24 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( hasFlags = true; cmGlobalVisualStudio10Generator* gg = static_cast(this->GlobalGenerator); + cmIDEFlagTable const* flagtable = CM_NULLPTR; + const std::string& srclang = source->GetLanguage(); + if (srclang == "C" || srclang == "CXX") { + flagtable = gg->GetClFlagTable(); + } else if (srclang == "ASM_MASM" && + this->GlobalGenerator->IsMasmEnabled()) { + flagtable = gg->GetMasmFlagTable(); + } else if (lang == "ASM_NASM" && + this->GlobalGenerator->IsNasmEnabled()) { + flagtable = gg->GetNasmFlagTable(); + } else if (srclang == "RC") { + flagtable = gg->GetRcFlagTable(); + } else if (srclang == "CSharp") { + flagtable = gg->GetCSharpFlagTable(); + } cmVisualStudioGeneratorOptions clOptions( this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler, - gg->GetClFlagTable(), 0, this); + flagtable, 0, this); if (compileAs) { clOptions.AddFlag("CompileAs", compileAs); } @@ -1932,7 +1987,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } clOptions.AddDefines(configDefines.c_str()); clOptions.SetConfiguration((*config).c_str()); - clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + clOptions.PrependInheritedString("AdditionalOptions"); clOptions.OutputFlagMap(*this->BuildFileStream, " "); clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", lang); @@ -1995,6 +2050,19 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( return hasFlags; } +void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild( + std::vector const& exclude_configs) +{ + for (std::vector::const_iterator ci = exclude_configs.begin(); + ci != exclude_configs.end(); ++ci) { + this->WriteString("", 3); + (*this->BuildFileStream) + << "Configurations[*ci]) << "|" + << cmVS10EscapeXML(this->Platform) << "'\">true\n"; + } +} + void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() { cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType(); @@ -2005,15 +2073,15 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() return; } - this->WriteString("\n", 2); + this->WriteString("\n", 1); this->WriteString("<_ProjectFileVersion>10.0.20506.1" "\n", - 3); + 2); for (std::vector::const_iterator config = this->Configurations.begin(); config != this->Configurations.end(); ++config) { if (ttype >= cmStateEnums::UTILITY) { - this->WritePlatformConfigTag("IntDir", config->c_str(), 3); + this->WritePlatformConfigTag("IntDir", config->c_str(), 2); *this->BuildFileStream << "$(Platform)\\$(Configuration)\\$(ProjectName)\\" << "\n"; @@ -2036,24 +2104,24 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() this->ConvertToWindowsSlash(intermediateDir); this->ConvertToWindowsSlash(outDir); - this->WritePlatformConfigTag("OutDir", config->c_str(), 3); + this->WritePlatformConfigTag("OutDir", config->c_str(), 2); *this->BuildFileStream << cmVS10EscapeXML(outDir) << "\n"; - this->WritePlatformConfigTag("IntDir", config->c_str(), 3); + this->WritePlatformConfigTag("IntDir", config->c_str(), 2); *this->BuildFileStream << cmVS10EscapeXML(intermediateDir) << "\n"; if (const char* workingDir = this->GeneratorTarget->GetProperty( "VS_DEBUGGER_WORKING_DIRECTORY")) { this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory", - config->c_str(), 3); + config->c_str(), 2); *this->BuildFileStream << cmVS10EscapeXML(workingDir) << "\n"; } std::string name = cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); - this->WritePlatformConfigTag("TargetName", config->c_str(), 3); + this->WritePlatformConfigTag("TargetName", config->c_str(), 2); *this->BuildFileStream << cmVS10EscapeXML(name) << "\n"; std::string ext = @@ -2063,13 +2131,13 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() // A single "." appears to be treated as an empty extension. ext = "."; } - this->WritePlatformConfigTag("TargetExt", config->c_str(), 3); + this->WritePlatformConfigTag("TargetExt", config->c_str(), 2); *this->BuildFileStream << cmVS10EscapeXML(ext) << "\n"; this->OutputLinkIncremental(*config); } } - this->WriteString("\n", 2); + this->WriteString("\n", 1); } void cmVisualStudio10TargetGenerator::OutputLinkIncremental( @@ -2090,13 +2158,13 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( Options& linkOptions = *(this->LinkOptions[configName]); const char* incremental = linkOptions.GetFlag("LinkIncremental"); - this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 3); + this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 2); *this->BuildFileStream << (incremental ? incremental : "true") << "\n"; linkOptions.RemoveFlag("LinkIncremental"); const char* manifest = linkOptions.GetFlag("GenerateManifest"); - this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 3); + this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 2); *this->BuildFileStream << (manifest ? manifest : "true") << "\n"; linkOptions.RemoveFlag("GenerateManifest"); @@ -2107,7 +2175,7 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( for (const char** f = flags; *f; ++f) { const char* flag = *f; if (const char* value = linkOptions.GetFlag(flag)) { - this->WritePlatformConfigTag(flag, configName.c_str(), 3); + this->WritePlatformConfigTag(flag, configName.c_str(), 2); *this->BuildFileStream << value << "\n"; linkOptions.RemoveFlag(flag); } @@ -2158,10 +2226,27 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->Name.c_str()); return false; } - if (linkLanguage == "C" || linkLanguage == "CXX" || - linkLanguage == "Fortran" || linkLanguage == "CSharp") { + + // Choose a language whose flags to use for ClCompile. + static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" }; + std::string langForClCompile; + if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) != + cmArrayEnd(clLangs)) { + langForClCompile = linkLanguage; + } else { + std::set languages; + this->GeneratorTarget->GetLanguages(languages, configName); + for (const char* const* l = cmArrayBegin(clLangs); + l != cmArrayEnd(clLangs); ++l) { + if (languages.find(*l) != languages.end()) { + langForClCompile = *l; + break; + } + } + } + if (!langForClCompile.empty()) { std::string baseFlagVar = "CMAKE_"; - baseFlagVar += linkLanguage; + baseFlagVar += langForClCompile; baseFlagVar += "_FLAGS"; flags = this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition( @@ -2172,6 +2257,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition( flagVar.c_str()); + this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, + langForClCompile, configName); } // set the correct language if (linkLanguage == "C") { @@ -2180,8 +2267,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( if (linkLanguage == "CXX") { clOptions.AddFlag("CompileAs", "CompileAsCpp"); } - this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, - linkLanguage, configName.c_str()); + + // Check IPO related warning/error. + this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName); // Get preprocessor definitions for this directory. std::string defineFlags = @@ -2265,7 +2353,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( return; } this->WriteString("\n", 2); - clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + clOptions.PrependInheritedString("AdditionalOptions"); clOptions.AppendFlag("AdditionalIncludeDirectories", includes); clOptions.AppendFlag("AdditionalIncludeDirectories", "%(AdditionalIncludeDirectories)"); @@ -2369,12 +2457,191 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions( rcOptions.AppendFlag("AdditionalIncludeDirectories", includes); rcOptions.AppendFlag("AdditionalIncludeDirectories", "%(AdditionalIncludeDirectories)"); + rcOptions.PrependInheritedString("AdditionalOptions"); rcOptions.OutputFlagMap(*this->BuildFileStream, " "); - rcOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); this->WriteString("\n", 2); } +bool cmVisualStudio10TargetGenerator::ComputeCudaOptions() +{ + if (!this->GlobalGenerator->IsCudaEnabled()) { + return true; + } + for (std::vector::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) { + if (!this->ComputeCudaOptions(*i)) { + return false; + } + } + return true; +} + +bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( + std::string const& configName) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast(this->GlobalGenerator); + CM_AUTO_PTR pOptions(new Options( + this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable())); + Options& cudaOptions = *pOptions; + + // Get compile flags for CUDA in this directory. + std::string CONFIG = cmSystemTools::UpperCase(configName); + std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG; + std::string flags = + std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) + + std::string(" ") + + std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA", + configName); + + // Get preprocessor definitions for this directory. + std::string defineFlags = + this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags(); + + cudaOptions.Parse(flags.c_str()); + cudaOptions.Parse(defineFlags.c_str()); + cudaOptions.ParseFinish(); + + if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) { + cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true"); + } else if (this->GeneratorTarget->GetPropertyAsBool( + "CUDA_PTX_COMPILATION")) { + cudaOptions.AddFlag("NvccCompilation", "ptx"); + // We drop the %(Extension) component as CMake expects all PTX files + // to not have the source file extension at all + cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).ptx"); + } + + // Convert the host compiler options to the toolset's abstractions + // using a secondary flag table. + cudaOptions.ClearTables(); + cudaOptions.AddTable(gg->GetCudaHostFlagTable()); + cudaOptions.Reparse("AdditionalCompilerOptions"); + + // `CUDA 8.0.targets` places AdditionalCompilerOptions before nvcc! + // Pass them through -Xcompiler in AdditionalOptions instead. + if (const char* acoPtr = cudaOptions.GetFlag("AdditionalCompilerOptions")) { + std::string aco = acoPtr; + cudaOptions.RemoveFlag("AdditionalCompilerOptions"); + if (!aco.empty()) { + aco = this->LocalGenerator->EscapeForShell(aco, false); + cudaOptions.AppendFlagString("AdditionalOptions", "-Xcompiler=" + aco); + } + } + + cudaOptions.FixCudaCodeGeneration(); + + std::vector targetDefines; + this->GeneratorTarget->GetCompileDefinitions(targetDefines, + configName.c_str(), "CUDA"); + cudaOptions.AddDefines(targetDefines); + + // Add a definition for the configuration name. + std::string configDefine = "CMAKE_INTDIR=\""; + configDefine += configName; + configDefine += "\""; + cudaOptions.AddDefine(configDefine); + if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) { + cudaOptions.AddDefine(exportMacro); + } + + this->CudaOptions[configName] = pOptions.release(); + return true; +} + +void cmVisualStudio10TargetGenerator::WriteCudaOptions( + std::string const& configName, std::vector const& includes) +{ + if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) { + return; + } + this->WriteString("\n", 2); + + Options& cudaOptions = *(this->CudaOptions[configName]); + cudaOptions.AppendFlag("Include", includes); + cudaOptions.AppendFlag("Include", "%(Include)"); + cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "CUDA"); + cudaOptions.PrependInheritedString("AdditionalOptions"); + cudaOptions.OutputFlagMap(*this->BuildFileStream, " "); + + this->WriteString("\n", 2); +} + +bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions() +{ + if (!this->GlobalGenerator->IsCudaEnabled()) { + return true; + } + for (std::vector::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) { + if (!this->ComputeCudaLinkOptions(*i)) { + return false; + } + } + return true; +} + +bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( + std::string const& configName) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast(this->GlobalGenerator); + CM_AUTO_PTR pOptions(new Options( + this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable())); + Options& cudaLinkOptions = *pOptions; + + // Determine if we need to do a device link + bool doDeviceLinking = false; + switch (this->GeneratorTarget->GetType()) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::EXECUTABLE: + doDeviceLinking = true; + break; + case cmStateEnums::STATIC_LIBRARY: + doDeviceLinking = this->GeneratorTarget->GetPropertyAsBool( + "CUDA_RESOLVE_DEVICE_SYMBOLS"); + break; + default: + break; + } + + cudaLinkOptions.AddFlag("PerformDeviceLink", + doDeviceLinking ? "true" : "false"); + + // Suppress deprecation warnings for default GPU targets during device link. + if (cmSystemTools::VersionCompareGreaterEq( + this->GlobalGenerator->GetPlatformToolsetCudaString(), "8.0")) { + cudaLinkOptions.AppendFlagString("AdditionalOptions", + "-Wno-deprecated-gpu-targets"); + } + + this->CudaLinkOptions[configName] = pOptions.release(); + return true; +} + +void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions( + std::string const& configName) +{ + if (this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) { + return; + } + + if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) { + return; + } + + this->WriteString("\n", 2); + Options& cudaLinkOptions = *(this->CudaLinkOptions[configName]); + cudaLinkOptions.OutputFlagMap(*this->BuildFileStream, " "); + this->WriteString("\n", 2); +} + bool cmVisualStudio10TargetGenerator::ComputeMasmOptions() { if (!this->GlobalGenerator->IsMasmEnabled()) { @@ -2427,12 +2694,77 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions( Options& masmOptions = *(this->MasmOptions[configName]); masmOptions.AppendFlag("IncludePaths", includes); masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)"); + masmOptions.PrependInheritedString("AdditionalOptions"); masmOptions.OutputFlagMap(*this->BuildFileStream, " "); - masmOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); this->WriteString("\n", 2); } +bool cmVisualStudio10TargetGenerator::ComputeNasmOptions() +{ + if (!this->GlobalGenerator->IsNasmEnabled()) { + return true; + } + for (std::vector::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) { + if (!this->ComputeNasmOptions(*i)) { + return false; + } + } + return true; +} + +bool cmVisualStudio10TargetGenerator::ComputeNasmOptions( + std::string const& configName) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast(this->GlobalGenerator); + CM_AUTO_PTR pOptions(new Options( + this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable())); + Options& nasmOptions = *pOptions; + + std::string CONFIG = cmSystemTools::UpperCase(configName); + std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG; + std::string flags = + std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS")) + + std::string(" -f") + std::string(this->Makefile->GetSafeDefinition( + "CMAKE_ASM_NASM_OBJECT_FORMAT")) + + std::string(" ") + + std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + nasmOptions.Parse(flags.c_str()); + this->NasmOptions[configName] = pOptions.release(); + return true; +} + +void cmVisualStudio10TargetGenerator::WriteNasmOptions( + std::string const& configName, std::vector includes) +{ + if (!this->GlobalGenerator->IsNasmEnabled()) { + return; + } + this->WriteString("\n", 2); + + Options& nasmOptions = *(this->NasmOptions[configName]); + for (size_t i = 0; i < includes.size(); i++) { + includes[i] += "\\"; + } + + nasmOptions.AppendFlag("IncludePaths", includes); + nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)"); + nasmOptions.OutputFlagMap(*this->BuildFileStream, " "); + nasmOptions.PrependInheritedString("AdditionalOptions"); + nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "ASM_NASM"); + + // Preprocessor definitions and includes are shared with clOptions. + Options& clOptions = *(this->ClOptions[configName]); + clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "ASM_NASM"); + + this->WriteString("\n", 2); +} + void cmVisualStudio10TargetGenerator::WriteLibOptions( std::string const& config) { @@ -2451,7 +2783,7 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker, gg->GetLibFlagTable(), 0, this); libOptions.Parse(libflags.c_str()); - libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + libOptions.PrependInheritedString("AdditionalOptions"); libOptions.OutputFlagMap(*this->BuildFileStream, " "); this->WriteString("\n", 2); } @@ -2648,8 +2980,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), 0, this)); Options& linkOptions = *pOptions; - const std::string& linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(config.c_str()); + cmGeneratorTarget::LinkClosure const* linkClosure = + this->GeneratorTarget->GetLinkClosure(config); + + const std::string& linkLanguage = linkClosure->LinkerLanguage; if (linkLanguage.empty()) { cmSystemTools::Error( "CMake can not determine linker language for target: ", @@ -2690,25 +3024,6 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( flags += " "; flags += flagsConfig; } - std::string standardLibsVar = "CMAKE_"; - standardLibsVar += linkLanguage; - standardLibsVar += "_STANDARD_LIBRARIES"; - std::string libs = - this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - // Remove trailing spaces from libs - std::string::size_type pos = libs.size() - 1; - if (!libs.empty()) { - while (libs[pos] == ' ') { - pos--; - } - } - if (pos != libs.size() - 1) { - libs = libs.substr(0, pos + 1); - } - // Replace spaces in libs with ; - std::replace(libs.begin(), libs.end(), ' ', ';'); - std::vector libVec; - cmSystemTools::ExpandListArgument(libs, libVec); cmComputeLinkInformation* pcli = this->GeneratorTarget->GetLinkInformation(config.c_str()); @@ -2718,10 +3033,30 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( this->Name.c_str()); return false; } - // add the libraries for the target to libs string cmComputeLinkInformation& cli = *pcli; + + std::vector libVec; std::vector vsTargetVec; this->AddLibraries(cli, libVec, vsTargetVec); + if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(), + "CUDA") != linkClosure->Languages.end()) { + switch (this->CudaOptions[config]->GetCudaRuntime()) { + case cmVisualStudioGeneratorOptions::CudaRuntimeStatic: + libVec.push_back("cudart_static.lib"); + break; + case cmVisualStudioGeneratorOptions::CudaRuntimeShared: + libVec.push_back("cudart.lib"); + break; + case cmVisualStudioGeneratorOptions::CudaRuntimeNone: + break; + } + } + std::string standardLibsVar = "CMAKE_"; + standardLibsVar += linkLanguage; + standardLibsVar += "_STANDARD_LIBRARIES"; + std::string const libs = + this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec); linkOptions.AddFlag("AdditionalDependencies", libVec); // Populate TargetsFileAndConfigsVec @@ -2793,18 +3128,13 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( linkOptions.AddFlag("StackReserveSize", stackVal); } - if (this->LocalGenerator->GetVersion() >= - cmGlobalVisualStudioGenerator::VS14) { - linkOptions.AddFlag("GenerateDebugInformation", "No"); - } else { - linkOptions.AddFlag("GenerateDebugInformation", "false"); - } + linkOptions.AddFlag("GenerateDebugInformation", "false"); std::string pdb = this->GeneratorTarget->GetPDBDirectory(config.c_str()); pdb += "/"; pdb += targetNamePDB; - std::string imLib = - this->GeneratorTarget->GetDirectory(config.c_str(), true); + std::string imLib = this->GeneratorTarget->GetDirectory( + config.c_str(), cmStateEnums::ImportLibraryArtifact); imLib += "/"; imLib += targetNameImport; @@ -2836,46 +3166,23 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( linkOptions.Parse(flags.c_str()); if (this->MSTools) { - if (cmSourceFile const* defsrc = - this->GeneratorTarget->GetModuleDefinitionFile("")) { - linkOptions.AddFlag("ModuleDefinitionFile", - defsrc->GetFullPath().c_str()); + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(config); + if (mdi && !mdi->DefFile.empty()) { + linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str()); } linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "%(IgnoreSpecificDefaultLibraries)"); } - if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || - this->GeneratorTarget->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (this->GeneratorTarget->GetPropertyAsBool( - "WINDOWS_EXPORT_ALL_SYMBOLS")) { - linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def"); - } - } - - // Hack to fix flag version selection in a common use case. - // FIXME: Select flag table based on toolset instead of VS version. - if (this->LocalGenerator->GetVersion() >= - cmGlobalVisualStudioGenerator::VS14) { - cmGlobalVisualStudio10Generator* gg = - static_cast(this->GlobalGenerator); - const char* toolset = gg->GetPlatformToolset(); - if (toolset && - (toolset == kWINDOWS_7_1_SDK || /* clang-format please break here */ - cmHasLiteralPrefix(toolset, "v80") || - cmHasLiteralPrefix(toolset, "v90") || - cmHasLiteralPrefix(toolset, "v100") || - cmHasLiteralPrefix(toolset, "v110") || - cmHasLiteralPrefix(toolset, "v120"))) { - if (const char* debug = - linkOptions.GetFlag("GenerateDebugInformation")) { - // Convert value from enumeration back to boolean for older toolsets. - if (strcmp(debug, "No") == 0) { - linkOptions.AddFlag("GenerateDebugInformation", "false"); - } else if (strcmp(debug, "Debug") == 0) { - linkOptions.AddFlag("GenerateDebugInformation", "true"); - } + // VS 2015 without all updates has a v140 toolset whose + // GenerateDebugInformation expects No/Debug instead of false/true. + if (gg->GetPlatformToolsetNeedsDebugEnum()) { + if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) { + if (strcmp(debug, "false") == 0) { + linkOptions.AddFlag("GenerateDebugInformation", "No"); + } else if (strcmp(debug, "true") == 0) { + linkOptions.AddFlag("GenerateDebugInformation", "Debug"); } } } @@ -2940,7 +3247,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions( Options& linkOptions = *(this->LinkOptions[config]); this->WriteString("\n", 2); - linkOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + linkOptions.PrependInheritedString("AdditionalOptions"); linkOptions.OutputFlagMap(*this->BuildFileStream, " "); this->WriteString("\n", 2); @@ -3063,7 +3370,9 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteClOptions(*i, includes); // output rc compile flags this->WriteRCOptions(*i, includes); + this->WriteCudaOptions(*i, includes); this->WriteMasmOptions(*i, includes); + this->WriteNasmOptions(*i, includes); } // output midl flags this->WriteMidlOptions(*i, includes); @@ -3073,6 +3382,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() } // output link flags this->WriteLinkOptions(*i); + this->WriteCudaLinkOptions(*i); // output lib flags this->WriteLibOptions(*i); // output manifest flags @@ -3090,18 +3400,15 @@ void cmVisualStudio10TargetGenerator::WriteEvents( std::string const& configName) { bool addedPrelink = false; - if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || - this->GeneratorTarget->IsExecutableWithExports()) && - this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { - if (this->GeneratorTarget->GetPropertyAsBool( - "WINDOWS_EXPORT_ALL_SYMBOLS")) { - addedPrelink = true; - std::vector commands = - this->GeneratorTarget->GetPreLinkCommands(); - this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget, - commands, configName); - this->WriteEvent("PreLinkEvent", commands, configName); - } + cmGeneratorTarget::ModuleDefinitionInfo const* mdi = + this->GeneratorTarget->GetModuleDefinitionInfo(configName); + if (mdi && mdi->DefFileGenerated) { + addedPrelink = true; + std::vector commands = + this->GeneratorTarget->GetPreLinkCommands(); + this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget, + commands, configName); + this->WriteEvent("PreLinkEvent", commands, configName); } if (!addedPrelink) { this->WriteEvent("PreLinkEvent", @@ -3174,10 +3481,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() ->TargetIsFortranOnly(dt)) { continue; } - if (csproj == this->ProjectType && - !this->GlobalGenerator->TargetIsCSharpOnly(dt)) { - continue; - } this->WriteString("GetLocalGenerator(); std::string name = dt->GetName(); @@ -3194,13 +3497,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n"; this->WriteString("", 3); - if (csproj == this->ProjectType) { - (*this->BuildFileStream) << "{"; - } - (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str()); - if (csproj == this->ProjectType) { - (*this->BuildFileStream) << "}"; - } + (*this->BuildFileStream) + << "{" << this->GlobalGenerator->GetGUID(name.c_str()) << "}"; (*this->BuildFileStream) << "\n"; this->WriteString("", 3); (*this->BuildFileStream) << name << "\n"; @@ -3990,3 +4288,14 @@ bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const CloseHandle(h); return true; } + +std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath( + const char* relativeFilePath) const +{ + // Always search in the standard modules location. + std::string path = cmSystemTools::GetCMakeRoot() + "/"; + path += relativeFilePath; + this->ConvertToWindowsSlash(path); + + return path; +} diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 45464c051..61066158c 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -3,7 +3,7 @@ #ifndef cmVisualStudioTargetGenerator_h #define cmVisualStudioTargetGenerator_h -#include +#include "cmConfigure.h" #include #include @@ -51,7 +51,7 @@ private: }; std::string ConvertPath(std::string const& path, bool forceRelative); - void ConvertToWindowsSlash(std::string& s); + static void ConvertToWindowsSlash(std::string& s); void WriteString(const char* line, int indentLevel); void WriteProjectConfigurations(); void WriteProjectConfigurationValues(); @@ -62,8 +62,7 @@ private: void WriteNsightTegraConfigurationValues(std::string const& config); void WriteSource(std::string const& tool, cmSourceFile const* sf, const char* end = 0); - void WriteSources(std::string const& tool, - std::vector const&); + void WriteExcludeFromBuild(std::vector const& exclude_configs); void WriteAllSources(); void WriteDotNetReferences(); void WriteDotNetReference(std::string const& ref, std::string const& hint); @@ -98,10 +97,24 @@ private: bool ComputeRcOptions(std::string const& config); void WriteRCOptions(std::string const& config, std::vector const& includes); + bool ComputeCudaOptions(); + bool ComputeCudaOptions(std::string const& config); + void WriteCudaOptions(std::string const& config, + std::vector const& includes); + + bool ComputeCudaLinkOptions(); + bool ComputeCudaLinkOptions(std::string const& config); + void WriteCudaLinkOptions(std::string const& config); + bool ComputeMasmOptions(); bool ComputeMasmOptions(std::string const& config); void WriteMasmOptions(std::string const& config, std::vector const& includes); + bool ComputeNasmOptions(); + bool ComputeNasmOptions(std::string const& config); + void WriteNasmOptions(std::string const& config, + std::vector includes); + bool ComputeLinkOptions(); bool ComputeLinkOptions(std::string const& config); bool ComputeLibOptions(); @@ -145,7 +158,10 @@ private: typedef std::map OptionsMap; OptionsMap ClOptions; OptionsMap RcOptions; + OptionsMap CudaOptions; + OptionsMap CudaLinkOptions; OptionsMap MasmOptions; + OptionsMap NasmOptions; OptionsMap LinkOptions; std::string PathToProjectFile; std::string ProjectFileExtension; @@ -177,6 +193,7 @@ private: typedef std::map ToolSourceMap; ToolSourceMap Tools; + std::string GetCMakeFilePath(const char* name) const; }; #endif diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx index afca216fe..9a1d95078 100644 --- a/Source/cmVisualStudio10ToolsetOptions.cxx +++ b/Source/cmVisualStudio10ToolsetOptions.cxx @@ -26,10 +26,11 @@ #include "cmVS12RCFlagTable.h" #include "cmVS140CLFlagTable.h" #include "cmVS140CSharpFlagTable.h" +#include "cmVS140LinkFlagTable.h" #include "cmVS141CLFlagTable.h" #include "cmVS141CSharpFlagTable.h" +#include "cmVS141LinkFlagTable.h" #include "cmVS14LibFlagTable.h" -#include "cmVS14LinkFlagTable.h" #include "cmVS14MASMFlagTable.h" #include "cmVS14RCFlagTable.h" @@ -114,8 +115,10 @@ cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLinkFlagTable( { std::string const useToolset = this->GetToolsetName(name, toolset); - if ((useToolset == "v140") || (useToolset == "v141")) { - return cmVS14LinkFlagTable; + if (useToolset == "v141") { + return cmVS141LinkFlagTable; + } else if (useToolset == "v140") { + return cmVS140LinkFlagTable; } else if (useToolset == "v120") { return cmVS12LinkFlagTable; } else if (useToolset == "v110") { diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h index 2459f5e01..4233337ba 100644 --- a/Source/cmVisualStudio10ToolsetOptions.h +++ b/Source/cmVisualStudio10ToolsetOptions.h @@ -3,7 +3,7 @@ #ifndef cmVisualStudio10ToolsetOptions_h #define cmVisualStudio10ToolsetOptions_h -#include +#include "cmConfigure.h" #include diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index da6f9a70b..1f808c8b2 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -44,6 +44,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( this->FortranRuntimeDebug = false; this->FortranRuntimeDLL = false; this->FortranRuntimeMT = false; + + this->UnknownFlagField = "AdditionalOptions"; } cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( @@ -68,6 +70,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions( this->FortranRuntimeDebug = false; this->FortranRuntimeDLL = false; this->FortranRuntimeMT = false; + + this->UnknownFlagField = "AdditionalOptions"; } void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table) @@ -82,6 +86,13 @@ void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table) } } +void cmVisualStudioGeneratorOptions::ClearTables() +{ + for (int i = 0; i < FlagTableCount; ++i) { + this->FlagTable[i] = CM_NULLPTR; + } +} + void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() { // Exception handling is on by default because the platform file has @@ -90,10 +101,6 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() // the flag to disable exception handling. When the user does // remove the flag we need to override the IDE default of on. switch (this->Version) { - case cmGlobalVisualStudioGenerator::VS7: - case cmGlobalVisualStudioGenerator::VS71: - this->FlagMap["ExceptionHandling"] = "FALSE"; - break; case cmGlobalVisualStudioGenerator::VS10: case cmGlobalVisualStudioGenerator::VS11: case cmGlobalVisualStudioGenerator::VS12: @@ -177,6 +184,78 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const return false; } +cmVisualStudioGeneratorOptions::CudaRuntime +cmVisualStudioGeneratorOptions::GetCudaRuntime() const +{ + std::map::const_iterator i = + this->FlagMap.find("CudaRuntime"); + if (i != this->FlagMap.end() && i->second.size() == 1) { + std::string const& cudaRuntime = i->second[0]; + if (cudaRuntime == "Static") { + return CudaRuntimeStatic; + } + if (cudaRuntime == "Shared") { + return CudaRuntimeShared; + } + if (cudaRuntime == "None") { + return CudaRuntimeNone; + } + } + // nvcc default is static + return CudaRuntimeStatic; +} + +void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() +{ + // Extract temporary values stored by our flag table. + FlagValue arch = this->TakeFlag("cmake-temp-arch"); + FlagValue code = this->TakeFlag("cmake-temp-code"); + FlagValue gencode = this->TakeFlag("cmake-temp-gencode"); + + // No -code allowed without -arch. + if (arch.empty()) { + code.clear(); + } + + if (arch.empty() && gencode.empty()) { + return; + } + + // Create a CodeGeneration field with [arch],[code] syntax in each entry. + // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`. + FlagValue& result = this->FlagMap["CodeGeneration"]; + + // First entries for the -arch= [-code=,...] pair. + if (!arch.empty()) { + std::string arch_name = arch[0]; + std::vector codes; + if (!code.empty()) { + codes = cmSystemTools::tokenize(code[0], ","); + } + if (codes.empty()) { + codes.push_back(arch_name); + // nvcc -arch= has a special case that allows a real + // architecture to be specified instead of a virtual arch. + // It translates to -arch= -code=. + cmSystemTools::ReplaceString(arch_name, "sm_", "compute_"); + } + for (std::vector::iterator ci = codes.begin(); + ci != codes.end(); ++ci) { + std::string entry = arch_name + "," + *ci; + result.push_back(entry); + } + } + + // Now add entries for the -gencode=, pairs. + for (std::vector::iterator ei = gencode.begin(); + ei != gencode.end(); ++ei) { + std::string entry = *ei; + cmSystemTools::ReplaceString(entry, "arch=", ""); + cmSystemTools::ReplaceString(entry, "code=", ""); + result.push_back(entry); + } +} + void cmVisualStudioGeneratorOptions::Parse(const char* flags) { // Parse the input string as a windows command line since the string @@ -210,6 +289,44 @@ void cmVisualStudioGeneratorOptions::ParseFinish() rl += this->FortranRuntimeDLL ? "DLL" : ""; this->FlagMap["RuntimeLibrary"] = rl; } + + if (this->CurrentTool == CudaCompiler) { + std::map::iterator i = + this->FlagMap.find("CudaRuntime"); + if (i != this->FlagMap.end() && i->second.size() == 1) { + std::string& cudaRuntime = i->second[0]; + if (cudaRuntime == "static") { + cudaRuntime = "Static"; + } else if (cudaRuntime == "shared") { + cudaRuntime = "Shared"; + } else if (cudaRuntime == "none") { + cudaRuntime = "None"; + } + } + } +} + +void cmVisualStudioGeneratorOptions::PrependInheritedString( + std::string const& key) +{ + std::map::iterator i = this->FlagMap.find(key); + if (i == this->FlagMap.end() || i->second.size() != 1) { + return; + } + std::string& value = i->second[0]; + value = "%(" + key + ") " + value; +} + +void cmVisualStudioGeneratorOptions::Reparse(std::string const& key) +{ + std::map::iterator i = this->FlagMap.find(key); + if (i == this->FlagMap.end() || i->second.size() != 1) { + return; + } + std::string const original = i->second[0]; + i->second[0] = ""; + this->UnknownFlagField = key; + this->Parse(original.c_str()); } void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) @@ -235,10 +352,22 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) } // This option is not known. Store it in the output flags. - this->FlagString += " "; - this->FlagString += cmOutputConverter::EscapeWindowsShellArgument( + std::string const opts = cmOutputConverter::EscapeWindowsShellArgument( flag, cmOutputConverter::Shell_Flag_AllowMakeVariables | cmOutputConverter::Shell_Flag_VSIDE); + this->AppendFlagString(this->UnknownFlagField, opts); +} + +cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag( + std::string const& key) +{ + FlagValue value; + std::map::iterator i = this->FlagMap.find(key); + if (i != this->FlagMap.end()) { + value = i->second; + this->FlagMap.erase(i); + } + return value; } void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config) @@ -253,19 +382,22 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( if (this->Defines.empty()) { return; } + const char* tag = "PreprocessorDefinitions"; + if (lang == "CUDA") { + tag = "Defines"; + } if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { // if there are configuration specific flags, then // use the configuration specific tag for PreprocessorDefinitions if (!this->Configuration.empty()) { fout << prefix; this->TargetGenerator->WritePlatformConfigTag( - "PreprocessorDefinitions", this->Configuration.c_str(), 0, 0, 0, - &fout); + tag, this->Configuration.c_str(), 0, 0, 0, &fout); } else { - fout << prefix << ""; + fout << prefix << "<" << tag << ">"; } } else { - fout << prefix << "PreprocessorDefinitions=\""; + fout << prefix << tag << "=\""; } const char* sep = ""; std::vector::const_iterator de = @@ -294,7 +426,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( sep = ";"; } if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { - fout << ";%(PreprocessorDefinitions)" << suffix; + fout << ";%(" << tag << ")" << suffix; } else { fout << "\"" << suffix; } @@ -335,26 +467,3 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout, } } } - -void cmVisualStudioGeneratorOptions::OutputAdditionalOptions( - std::ostream& fout, const char* prefix, const char* suffix) -{ - if (!this->FlagString.empty()) { - if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { - fout << prefix; - if (!this->Configuration.empty()) { - this->TargetGenerator->WritePlatformConfigTag( - "AdditionalOptions", this->Configuration.c_str(), 0, 0, 0, &fout); - } else { - fout << ""; - } - fout << "%(AdditionalOptions) " - << cmVisualStudio10GeneratorOptionsEscapeForXML(this->FlagString) - << "\n"; - } else { - fout << prefix << "AdditionalOptions=\""; - fout << cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString); - fout << "\"" << suffix; - } - } -} diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index ab6b8cca2..44d271908 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -3,7 +3,7 @@ #ifndef cmVisualStudioGeneratorOptions_h #define cmVisualStudioGeneratorOptions_h -#include +#include "cmConfigure.h" #include #include @@ -26,7 +26,9 @@ public: { Compiler, ResourceCompiler, + CudaCompiler, MasmCompiler, + NasmCompiler, Linker, FortranCompiler, CSharpCompiler @@ -42,10 +44,19 @@ public: // Add a table of flags. void AddTable(cmVS7FlagTable const* table); + // Clear the flag tables. + void ClearTables(); + // Store options from command line flags. void Parse(const char* flags); void ParseFinish(); + void PrependInheritedString(std::string const& key); + + // Parse the content of the given flag table entry again to extract + // known flags and leave the rest in the original entry. + void Reparse(std::string const& key); + // Fix the ExceptionHandling option to default to off. void FixExceptionHandlingDefault(); @@ -56,6 +67,16 @@ public: bool UsingUnicode() const; bool UsingSBCS() const; + enum CudaRuntime + { + CudaRuntimeStatic, + CudaRuntimeShared, + CudaRuntimeNone + }; + CudaRuntime GetCudaRuntime() const; + + void FixCudaCodeGeneration(); + bool IsDebug() const; bool IsWinRt() const; bool IsManaged() const; @@ -64,8 +85,6 @@ public: const char* suffix, const std::string& lang); void OutputFlagMap(std::ostream& fout, const char* indent); - void OutputAdditionalOptions(std::ostream& fout, const char* prefix, - const char* suffix); void SetConfiguration(const char* config); private: @@ -80,7 +99,11 @@ private: bool FortranRuntimeDLL; bool FortranRuntimeMT; + std::string UnknownFlagField; + virtual void StoreUnknownFlag(const char* flag); + + FlagValue TakeFlag(std::string const& key); }; #endif diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h index b2f8db927..e12047fb5 100644 --- a/Source/cmVisualStudioSlnData.h +++ b/Source/cmVisualStudioSlnData.h @@ -3,7 +3,7 @@ #ifndef cmVisualStudioSlnData_h #define cmVisualStudioSlnData_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx index 939120a75..1a32abacf 100644 --- a/Source/cmVisualStudioSlnParser.cxx +++ b/Source/cmVisualStudioSlnParser.cxx @@ -4,7 +4,7 @@ #include "cmSystemTools.h" #include "cmVisualStudioSlnData.h" -#include +#include "cmsys/FStream.hxx" #include #include diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h index a3391a642..d51732407 100644 --- a/Source/cmVisualStudioSlnParser.h +++ b/Source/cmVisualStudioSlnParser.h @@ -3,7 +3,7 @@ #ifndef cmVisualStudioSlnParser_h #define cmVisualStudioSlnParser_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h index 8ed608329..75c3d1a39 100644 --- a/Source/cmVisualStudioWCEPlatformParser.h +++ b/Source/cmVisualStudioWCEPlatformParser.h @@ -3,7 +3,7 @@ #ifndef cmVisualStudioWCEPlatformParser_h #define cmVisualStudioWCEPlatformParser_h -#include +#include "cmConfigure.h" #include #include diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 38ea637e2..24d7bf1bf 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -82,7 +82,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus status; mf.ExecuteCommand(this->Functions[c], status); if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(true); + inStatus.SetReturnInvoked(); return true; } if (status.GetBreakInvoked()) { diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h index abd36b329..a95e4c30c 100644 --- a/Source/cmWhileCommand.h +++ b/Source/cmWhileCommand.h @@ -3,7 +3,8 @@ #ifndef cmWhileCommand_h #define cmWhileCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -56,16 +57,6 @@ public: { return false; } - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "while"; } }; #endif diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx new file mode 100644 index 000000000..99c9ba86a --- /dev/null +++ b/Source/cmWorkingDirectory.cxx @@ -0,0 +1,24 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmWorkingDirectory.h" + +#include "cmSystemTools.h" + +cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir) +{ + this->OldDir = cmSystemTools::GetCurrentWorkingDirectory(); + cmSystemTools::ChangeDirectory(newdir); +} + +cmWorkingDirectory::~cmWorkingDirectory() +{ + this->Pop(); +} + +void cmWorkingDirectory::Pop() +{ + if (!this->OldDir.empty()) { + cmSystemTools::ChangeDirectory(this->OldDir); + this->OldDir.clear(); + } +} diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h new file mode 100644 index 000000000..aff926755 --- /dev/null +++ b/Source/cmWorkingDirectory.h @@ -0,0 +1,25 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmWorkingDirectory_h +#define cmWorkingDirectory_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include + +/** \class cmWorkingDirectory + * \brief An RAII class to manipulate the working directory. + */ +class cmWorkingDirectory +{ +public: + cmWorkingDirectory(std::string const& newdir); + ~cmWorkingDirectory(); + + void Pop(); + +private: + std::string OldDir; +}; + +#endif diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx index 96c8e27d6..fc5fd2111 100644 --- a/Source/cmWriteFileCommand.cxx +++ b/Source/cmWriteFileCommand.cxx @@ -2,14 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWriteFileCommand.h" -#include - -#include -// include sys/stat.h after sys/types.h -#include +#include "cmsys/FStream.hxx" #include "cmMakefile.h" #include "cmSystemTools.h" +#include "cm_sys_stat.h" class cmExecutionStatus; @@ -24,7 +21,7 @@ bool cmWriteFileCommand::InitialPass(std::vector const& args, std::string message; std::vector::const_iterator i = args.begin(); - std::string fileName = *i; + std::string const& fileName = *i; bool overwrite = true; i++; diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h index 73e6e2256..19922cdf3 100644 --- a/Source/cmWriteFileCommand.h +++ b/Source/cmWriteFileCommand.h @@ -3,7 +3,8 @@ #ifndef cmWriteFileCommand_h #define cmWriteFileCommand_h -#include +#include "cmConfigure.h" + #include #include @@ -29,16 +30,6 @@ public: */ bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; - - /** - * This determines if the command is invoked when in script mode. - */ - bool IsScriptable() const CM_OVERRIDE { return true; } - - /** - * The name of the command as specified in CMakeList.txt. - */ - std::string GetName() const CM_OVERRIDE { return "write_file"; } }; #endif diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h index 083d22908..bcd8d93e1 100644 --- a/Source/cmXCode21Object.h +++ b/Source/cmXCode21Object.h @@ -3,7 +3,7 @@ #ifndef cmXCode21Object_h #define cmXCode21Object_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx index 3689ac4c2..0def8c321 100644 --- a/Source/cmXCodeObject.cxx +++ b/Source/cmXCodeObject.cxx @@ -224,11 +224,11 @@ void cmXCodeObject::PrintString(std::ostream& os, std::string String) { // The string needs to be quoted if it contains any characters // considered special by the Xcode project file parser. - bool needQuote = (String.empty() || String.find("//") != String.npos || + bool needQuote = (String.empty() || String.find("//") != std::string::npos || String.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" - "$_./") != String.npos); + "$_./") != std::string::npos); const char* quote = needQuote ? "\"" : ""; // Print the string, quoted and escaped as necessary. diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h index 3bfecdfcf..b92e6e33e 100644 --- a/Source/cmXCodeObject.h +++ b/Source/cmXCodeObject.h @@ -3,7 +3,7 @@ #ifndef cmXCodeObject_h #define cmXCodeObject_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx new file mode 100644 index 000000000..5c22531d4 --- /dev/null +++ b/Source/cmXCodeScheme.cxx @@ -0,0 +1,227 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmXCodeScheme.h" + +#include +#include +#include + +#include "cmGeneratedFileStream.h" +#include "cmGeneratorTarget.h" +#include "cmXMLSafe.h" + +cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, + const std::vector& configList, + unsigned int xcVersion) + : Target(xcObj) + , TargetName(xcObj->GetTarget()->GetName()) + , BuildableName(xcObj->GetTarget()->GetFullName()) + , TargetId(xcObj->GetId()) + , ConfigList(configList) + , XcodeVersion(xcVersion) +{ +} + +void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir, + const std::string& container) +{ + // Create shared scheme sub-directory tree + // + std::string xcodeSchemeDir = xcProjDir; + xcodeSchemeDir += "/xcshareddata/xcschemes"; + cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str()); + + std::string xcodeSchemeFile = xcodeSchemeDir; + xcodeSchemeFile += "/"; + xcodeSchemeFile += this->TargetName; + xcodeSchemeFile += ".xcscheme"; + + cmGeneratedFileStream fout(xcodeSchemeFile.c_str()); + fout.SetCopyIfDifferent(true); + if (!fout) { + return; + } + + WriteXCodeXCScheme(fout, container); +} + +void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout, + const std::string& container) +{ + cmXMLWriter xout(fout); + xout.SetIndentationElement(std::string(3, ' ')); + xout.StartDocument(); + + xout.StartElement("Scheme"); + xout.BreakAttributes(); + xout.Attribute("LastUpgradeVersion", WriteVersionString()); + xout.Attribute("version", "1.3"); + + WriteBuildAction(xout, container); + WriteTestAction(xout, FindConfiguration("Debug")); + WriteLaunchAction(xout, FindConfiguration("Debug"), container); + WriteProfileAction(xout, FindConfiguration("Release")); + WriteAnalyzeAction(xout, FindConfiguration("Debug")); + WriteArchiveAction(xout, FindConfiguration("Release")); + + xout.EndElement(); +} + +void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout, + const std::string& container) +{ + xout.StartElement("BuildAction"); + xout.BreakAttributes(); + xout.Attribute("parallelizeBuildables", "YES"); + xout.Attribute("buildImplicitDependencies", "YES"); + + xout.StartElement("BuildActionEntries"); + xout.StartElement("BuildActionEntry"); + xout.BreakAttributes(); + xout.Attribute("buildForTesting", "YES"); + xout.Attribute("buildForRunning", "YES"); + xout.Attribute("buildForProfiling", "YES"); + xout.Attribute("buildForArchiving", "YES"); + xout.Attribute("buildForAnalyzing", "YES"); + + xout.StartElement("BuildableReference"); + xout.BreakAttributes(); + xout.Attribute("BuildableIdentifier", "primary"); + xout.Attribute("BlueprintIdentifier", this->TargetId); + xout.Attribute("BuildableName", this->BuildableName); + xout.Attribute("BlueprintName", this->TargetName); + xout.Attribute("ReferencedContainer", "container:" + container); + xout.EndElement(); + + xout.EndElement(); // BuildActionEntry + xout.EndElement(); // BuildActionEntries + xout.EndElement(); // BuildAction +} + +void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("TestAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("selectedDebuggerIdentifier", + "Xcode.DebuggerFoundation.Debugger.LLDB"); + xout.Attribute("selectedLauncherIdentifier", + "Xcode.DebuggerFoundation.Launcher.LLDB"); + xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); + + xout.StartElement("Testables"); + xout.EndElement(); + + xout.StartElement("AdditionalOptions"); + xout.EndElement(); + + xout.EndElement(); // TestAction +} + +void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, + std::string configuration, + const std::string& container) +{ + xout.StartElement("LaunchAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("selectedDebuggerIdentifier", + "Xcode.DebuggerFoundation.Debugger.LLDB"); + xout.Attribute("selectedLauncherIdentifier", + "Xcode.DebuggerFoundation.Launcher.LLDB"); + xout.Attribute("launchStyle", "0"); + xout.Attribute("useCustomWorkingDirectory", "NO"); + xout.Attribute("ignoresPersistentStateOnLaunch", "NO"); + xout.Attribute("debugDocumentVersioning", "YES"); + xout.Attribute("debugServiceExtension", "internal"); + xout.Attribute("allowLocationSimulation", "YES"); + + if (IsExecutable(this->Target)) { + xout.StartElement("BuildableProductRunnable"); + xout.BreakAttributes(); + xout.Attribute("runnableDebuggingMode", "0"); + + } else { + xout.StartElement("MacroExpansion"); + } + + xout.StartElement("BuildableReference"); + xout.BreakAttributes(); + xout.Attribute("BuildableIdentifier", "primary"); + xout.Attribute("BlueprintIdentifier", this->TargetId); + xout.Attribute("BuildableName", this->BuildableName); + xout.Attribute("BlueprintName", this->TargetName); + xout.Attribute("ReferencedContainer", "container:" + container); + xout.EndElement(); + + xout.EndElement(); // MacroExpansion + + xout.StartElement("AdditionalOptions"); + xout.EndElement(); + + xout.EndElement(); // LaunchAction +} + +void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("ProfileAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); + xout.Attribute("savedToolIdentifier", ""); + xout.Attribute("useCustomWorkingDirectory", "NO"); + xout.Attribute("debugDocumentVersioning", "YES"); + xout.EndElement(); +} + +void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("AnalyzeAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.EndElement(); +} + +void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("ArchiveAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("revealArchiveInOrganizer", "YES"); + xout.EndElement(); +} + +std::string cmXCodeScheme::WriteVersionString() +{ + std::ostringstream v; + v << std::setfill('0') << std::setw(4) << this->XcodeVersion * 10; + return v.str(); +} + +std::string cmXCodeScheme::FindConfiguration(const std::string& name) +{ + // Try to find the desired configuration by name, + // and if it's not found return first from the list + // + if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) == + this->ConfigList.end() && + this->ConfigList.size() > 0) + return this->ConfigList[0]; + + return name; +} + +bool cmXCodeScheme::IsExecutable(const cmXCodeObject* target) +{ + cmGeneratorTarget* gt = target->GetTarget(); + if (!gt) { + cmSystemTools::Error("Error no target on xobject\n"); + return false; + } + + return gt->GetType() == cmStateEnums::EXECUTABLE; +} diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h new file mode 100644 index 000000000..379afed42 --- /dev/null +++ b/Source/cmXCodeScheme.h @@ -0,0 +1,50 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmXCodeScheme_h +#define cmXCodeScheme_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmGlobalXCodeGenerator.h" +#include "cmSystemTools.h" +#include "cmXCodeObject.h" +#include "cmXMLWriter.h" + +/** \class cmXCodeScheme + * \brief Write shared schemes for native targets in Xcode project. + */ +class cmXCodeScheme +{ +public: + cmXCodeScheme(cmXCodeObject* xcObj, + const std::vector& configList, + unsigned int xcVersion); + + void WriteXCodeSharedScheme(const std::string& xcProjDir, + const std::string& container); + +private: + const cmXCodeObject* const Target; + const std::string& TargetName; + const std::string BuildableName; + const std::string& TargetId; + const std::vector& ConfigList; + const unsigned int XcodeVersion; + + void WriteXCodeXCScheme(std::ostream& fout, const std::string& container); + + void WriteBuildAction(cmXMLWriter& xout, const std::string& container); + void WriteTestAction(cmXMLWriter& xout, std::string configuration); + void WriteLaunchAction(cmXMLWriter& xout, std::string configuration, + const std::string& container); + void WriteProfileAction(cmXMLWriter& xout, std::string configuration); + void WriteAnalyzeAction(cmXMLWriter& xout, std::string configuration); + void WriteArchiveAction(cmXMLWriter& xout, std::string configuration); + + std::string WriteVersionString(); + std::string FindConfiguration(const std::string& name); + + static bool IsExecutable(const cmXCodeObject* target); +}; + +#endif diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx index 231e95e86..18afbf370 100644 --- a/Source/cmXMLParser.cxx +++ b/Source/cmXMLParser.cxx @@ -2,8 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmXMLParser.h" -#include -#include +#include "cm_expat.h" +#include "cmsys/FStream.hxx" #include #include #include diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h index 60da51e7c..98ba04956 100644 --- a/Source/cmXMLParser.h +++ b/Source/cmXMLParser.h @@ -3,7 +3,7 @@ #ifndef cmXMLParser_h #define cmXMLParser_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include diff --git a/Source/cmXMLSafe.h b/Source/cmXMLSafe.h index c41554dea..9aaf2d157 100644 --- a/Source/cmXMLSafe.h +++ b/Source/cmXMLSafe.h @@ -3,7 +3,7 @@ #ifndef cmXMLSafe_h #define cmXMLSafe_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx index 2f50fe929..3cbc70dbd 100644 --- a/Source/cmXMLWriter.cxx +++ b/Source/cmXMLWriter.cxx @@ -2,11 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmXMLWriter.h" +#include "cmsys/FStream.hxx" #include -#include cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level) : Output(output) + , IndentationElement(1, '\t') , Level(level) , ElementOpen(false) , BreakAttrib(false) @@ -100,10 +101,18 @@ void cmXMLWriter::FragmentFile(const char* fname) this->Output << fin.rdbuf(); } +void cmXMLWriter::SetIndentationElement(std::string const& element) +{ + this->IndentationElement = element; +} + void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent) { if (condition) { - this->Output << '\n' << std::string(indent + this->Level, '\t'); + this->Output << '\n'; + for (std::size_t i = 0; i < indent + this->Level; ++i) { + this->Output << this->IndentationElement; + } } } diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index 904f73b45..ed76a88c7 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -3,7 +3,7 @@ #ifndef cmXMLWiter_h #define cmXMLWiter_h -#include // IWYU pragma: keep +#include "cmConfigure.h" #include "cmXMLSafe.h" @@ -14,6 +14,8 @@ class cmXMLWriter { + CM_DISABLE_COPY(cmXMLWriter) + public: cmXMLWriter(std::ostream& output, std::size_t level = 0); ~cmXMLWriter(); @@ -60,10 +62,9 @@ public: void FragmentFile(const char* fname); -private: - cmXMLWriter(const cmXMLWriter&); - cmXMLWriter& operator=(const cmXMLWriter&); + void SetIndentationElement(std::string const& element); +private: void ConditionalLineBreak(bool condition, std::size_t indent); void PreAttribute(); @@ -107,6 +108,7 @@ private: private: std::ostream& Output; std::stack > Elements; + std::string IndentationElement; std::size_t Level; bool ElementOpen; bool BreakAttrib; diff --git a/Source/cm_auto_ptr.hxx b/Source/cm_auto_ptr.hxx index 538201836..773602af9 100644 --- a/Source/cm_auto_ptr.hxx +++ b/Source/cm_auto_ptr.hxx @@ -3,7 +3,7 @@ #ifndef CM_AUTO_PTR_HXX #define CM_AUTO_PTR_HXX -#include +#include "cmConfigure.h" #ifdef CMake_HAVE_CXX_AUTO_PTR @@ -100,10 +100,10 @@ public: /** Assign from an auto_ptr holding a compatible object. This transfers ownership to the left-hand-side of the assignment. */ template - auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw() + auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw() // NOLINT { this->reset(cm_AUTO_PTR_CAST(a).release()); - return *this; + return *this; // NOLINT } /** @@ -127,10 +127,10 @@ public: /** Assign from another auto_ptr holding an object of the same type. This transfers ownership to the newly constructed auto_ptr. */ - auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw() + auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw() // NOLINT { this->reset(cm_AUTO_PTR_CAST(a).release()); - return *this; + return *this; // NOLINT } /** Destruct and delete the object held. */ @@ -192,7 +192,7 @@ public: auto_ptr& operator=(detail::auto_ptr_ref r) throw() { this->reset(r.p_); - return *this; + return *this; // NOLINT } /** Convert to an auto_ptr_ref. This is used when a function diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx index 869dd32f9..cf55741a7 100644 --- a/Source/cm_codecvt.cxx +++ b/Source/cm_codecvt.cxx @@ -1,18 +1,23 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cm_codecvt.hxx" -#include #if defined(_WIN32) +#include +#include #include #undef max -#include +#include "cmsys/Encoding.hxx" +#endif + +#if defined(_WIN32) +/* Number of leading ones before a zero in the byte (see cm_utf8.c). */ +extern "C" unsigned char const cm_utf8_ones[256]; #endif codecvt::codecvt(Encoding e) - : m_lastState(0) #if defined(_WIN32) - , m_codepage(0) + : m_codepage(0) #endif { switch (e) { @@ -45,76 +50,68 @@ std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from, const char*& from_next, char* to, char* to_end, char*& to_next) const { + from_next = from; + to_next = to; if (m_noconv) { - return noconv; + return std::codecvt_base::noconv; } - std::codecvt_base::result res = error; #if defined(_WIN32) - from_next = from; - to_next = to; - bool convert = true; - size_t count = from_end - from; - const char* data = from; - unsigned int& stateId = reinterpret_cast(state); - if (count == 0) { - return codecvt::ok; - } else if (count == 1) { - if (stateId == 0) { - // decode first byte for UTF-8 - if ((*from & 0xF8) == 0xF0 || // 1111 0xxx; 4 bytes for codepoint - (*from & 0xF0) == 0xE0 || // 1110 xxxx; 3 bytes for codepoint - (*from & 0xE0) == 0xC0) // 110x xxxx; 2 bytes for codepoint - { - stateId = findStateId(); - codecvt::State& s = m_states.at(stateId - 1); - s.bytes[0] = *from; - convert = false; - if ((*from & 0xF8) == 0xF0) { - s.totalBytes = 4; - } else if ((*from & 0xF0) == 0xE0) { - s.totalBytes = 3; - } else if ((*from & 0xE0) == 0xC0) { - s.totalBytes = 2; - } - s.bytesLeft = s.totalBytes - 1; - }; - // else 1 byte for codepoint - } else { - codecvt::State& s = m_states.at(stateId - 1); - s.bytes[s.totalBytes - s.bytesLeft] = *from; - s.bytesLeft--; - data = s.bytes; - count = s.totalBytes - s.bytesLeft; - if ((*from & 0xC0) == 0x80) { // 10xx xxxx - convert = s.bytesLeft == 0; - } else { - // invalid multi-byte - convert = true; - } - if (convert) { - s.used = false; - if (stateId == m_lastState) { - m_lastState--; - } - stateId = 0; - } + // Use a const view of the state because we should not modify it until we + // have fully processed and consume a byte (with sufficient space in the + // output buffer). We call helpers to re-cast and modify the state + State const& lstate = reinterpret_cast(state); + + while (from_next != from_end) { + // Count leading ones in the bits of the next byte. + unsigned char const ones = + cm_utf8_ones[static_cast(*from_next)]; + + if (ones != 1 && lstate.buffered != 0) { + // We have a buffered partial codepoint that we never completed. + return std::codecvt_base::error; + } else if (ones == 1 && lstate.buffered == 0) { + // This is a continuation of a codepoint that never started. + return std::codecvt_base::error; + } + + // Compute the number of bytes in the current codepoint. + int need = 0; + switch (ones) { + case 0: // 0xxx xxxx: new codepoint of size 1 + need = 1; + break; + case 1: // 10xx xxxx: continues a codepoint + assert(lstate.size != 0); + need = lstate.size; + break; + case 2: // 110x xxxx: new codepoint of size 2 + need = 2; + break; + case 3: // 1110 xxxx: new codepoint of size 3 + need = 3; + break; + case 4: // 1111 0xxx: new codepoint of size 4 + need = 4; + break; + default: // invalid byte + return std::codecvt_base::error; } - if (convert) { - std::wstring wide = cmsys::Encoding::ToWide(std::string(data, count)); - int r = WideCharToMultiByte(m_codepage, 0, wide.c_str(), - static_cast(wide.size()), to, - to_end - to, NULL, NULL); - if (r > 0) { - from_next = from_end; - to_next = to + r; - res = ok; + assert(need > 0); + + if (lstate.buffered + 1 == need) { + // This byte completes a codepoint. + std::codecvt_base::result decode_result = + this->Decode(state, need, from_next, to_next, to_end); + if (decode_result != std::codecvt_base::ok) { + return decode_result; } } else { - res = partial; - from_next = from_end; - to_next = to; + // This byte does not complete a codepoint. + this->BufferPartial(state, need, from_next); } } + + return std::codecvt_base::ok; #else static_cast(state); static_cast(from); @@ -123,46 +120,118 @@ std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from, static_cast(to); static_cast(to_end); static_cast(to_next); - res = codecvt::noconv; + return std::codecvt_base::noconv; #endif - return res; }; std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to, char* to_end, char*& to_next) const { - std::codecvt_base::result res = error; to_next = to; + if (m_noconv) { + return std::codecvt_base::noconv; + } #if defined(_WIN32) - unsigned int& stateId = reinterpret_cast(state); - if (stateId > 0) { - codecvt::State& s = m_states.at(stateId - 1); - s.used = false; - if (stateId == m_lastState) { - m_lastState--; - } - stateId = 0; - std::wstring wide = cmsys::Encoding::ToWide( - std::string(s.bytes, s.totalBytes - s.bytesLeft)); - int r = WideCharToMultiByte(m_codepage, 0, wide.c_str(), - static_cast(wide.size()), to, to_end - to, - NULL, NULL); - if (r > 0) { - to_next = to + r; - res = ok; - } - } else { - res = ok; + State& lstate = reinterpret_cast(state); + if (lstate.buffered != 0) { + return this->DecodePartial(state, to_next, to_end); } + return std::codecvt_base::ok; #else static_cast(state); static_cast(to_end); - res = ok; + return std::codecvt_base::ok; #endif - return res; }; +#if defined(_WIN32) +std::codecvt_base::result codecvt::Decode(mbstate_t& state, int size, + const char*& from_next, + char*& to_next, char* to_end) const +{ + State& lstate = reinterpret_cast(state); + + // Collect all the bytes for this codepoint. + char buf[4]; + memcpy(buf, lstate.partial, lstate.buffered); + buf[lstate.buffered] = *from_next; + + // Convert the encoding. + wchar_t wbuf[2]; + int wlen = + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buf, size, wbuf, 2); + if (wlen <= 0) { + return std::codecvt_base::error; + } + + int tlen = WideCharToMultiByte(m_codepage, 0, wbuf, wlen, to_next, + to_end - to_next, NULL, NULL); + if (tlen <= 0) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + return std::codecvt_base::partial; + } + return std::codecvt_base::error; + } + + // Move past the now-consumed byte in the input buffer. + ++from_next; + + // Move past the converted codepoint in the output buffer. + to_next += tlen; + + // Re-initialize the state for the next codepoint to start. + lstate = State(); + + return std::codecvt_base::ok; +} + +std::codecvt_base::result codecvt::DecodePartial(mbstate_t& state, + char*& to_next, + char* to_end) const +{ + State& lstate = reinterpret_cast(state); + + // Try converting the partial codepoint. + wchar_t wbuf[2]; + int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, lstate.partial, + lstate.buffered, wbuf, 2); + if (wlen <= 0) { + return std::codecvt_base::error; + } + + int tlen = WideCharToMultiByte(m_codepage, 0, wbuf, wlen, to_next, + to_end - to_next, NULL, NULL); + if (tlen <= 0) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + return std::codecvt_base::partial; + } + return std::codecvt_base::error; + } + + // Move past the converted codepoint in the output buffer. + to_next += tlen; + + // Re-initialize the state for the next codepoint to start. + lstate = State(); + + return std::codecvt_base::ok; +} + +void codecvt::BufferPartial(mbstate_t& state, int size, + const char*& from_next) const +{ + State& lstate = reinterpret_cast(state); + + // Save the byte in our buffer for later. + lstate.partial[lstate.buffered++] = *from_next; + lstate.size = size; + + // Move past the now-consumed byte in the input buffer. + ++from_next; +} +#endif + int codecvt::do_max_length() const throw() { return 4; @@ -172,44 +241,3 @@ int codecvt::do_encoding() const throw() { return 0; }; - -unsigned int codecvt::findStateId() const -{ - unsigned int stateId = 0; - bool add = false; - const unsigned int maxSize = std::numeric_limits::max(); - if (m_lastState >= maxSize) { - m_lastState = 0; - } - if (m_states.size() <= m_lastState) { - add = true; - } else { - unsigned int i = m_lastState; - while (i < maxSize) { - codecvt::State& s = m_states.at(i); - i++; - if (!s.used) { - m_lastState = i; - stateId = m_lastState; - s.used = true; - s.totalBytes = 0; - s.bytesLeft = 0; - break; - } - if (i >= m_states.size()) { - i = 0; - } - if (i == m_lastState) { - add = true; - break; - } - } - }; - if (add) { - codecvt::State s = { true, 0, 0, { 0, 0, 0, 0 } }; - m_states.push_back(s); - m_lastState = (unsigned int)m_states.size(); - stateId = m_lastState; - } - return stateId; -}; diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index fcd995432..30c6d5407 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -3,10 +3,9 @@ #ifndef cm_codecvt_hxx #define cm_codecvt_hxx -#include +#include "cmConfigure.h" #include -#include #include class codecvt : public std::codecvt @@ -35,21 +34,30 @@ protected: int do_encoding() const throw() CM_OVERRIDE; private: - typedef struct + // The mbstate_t argument to do_out and do_unshift is responsible + // for storing state between calls. We cannot control the type + // since we want to imbue on standard streams. However, we do + // know that it is a trivial type. Define our own type to overlay + // on it safely with no alignment requirements. + struct State { - bool used; - unsigned char totalBytes; - unsigned char bytesLeft; - char bytes[4]; - } State; + // Buffer bytes we have consumed from a partial codepoint. + char partial[3]; - unsigned int findStateId() const; + // Number of bytes we have buffered from a partial codepoint. + unsigned char buffered : 4; + + // Size of the current codepoint in bytes. + unsigned char size : 4; + }; bool m_noconv; - mutable std::vector m_states; - mutable unsigned int m_lastState; #if defined(_WIN32) unsigned int m_codepage; + result Decode(mbstate_t& state, int need, const char*& from_next, + char*& to_next, char* to_end) const; + result DecodePartial(mbstate_t& state, char*& to_next, char* to_end) const; + void BufferPartial(mbstate_t& state, int need, const char*& from_next) const; #endif #endif diff --git a/Source/cm_sys_stat.h b/Source/cm_sys_stat.h new file mode 100644 index 000000000..26e4baa03 --- /dev/null +++ b/Source/cm_sys_stat.h @@ -0,0 +1,14 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_sys_stat_h +#define cm_sys_stat_h + +#if defined(_MSC_VER) +typedef unsigned short mode_t; +#endif + +#include +// include sys/stat.h after sys/types.h +#include + +#endif diff --git a/Source/cm_unordered_map.hxx b/Source/cm_unordered_map.hxx index dc8ca3524..bf3890314 100644 --- a/Source/cm_unordered_map.hxx +++ b/Source/cm_unordered_map.hxx @@ -3,7 +3,7 @@ #ifndef CM_UNORDERED_MAP_HXX #define CM_UNORDERED_MAP_HXX -#include +#include "cmConfigure.h" #if defined(CMake_HAVE_CXX_UNORDERED_MAP) @@ -12,7 +12,7 @@ #elif defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cmsys/hash_map.hxx" #define CM_UNORDERED_MAP cmsys::hash_map #else diff --git a/Source/cm_unordered_set.hxx b/Source/cm_unordered_set.hxx index ce58dbf53..dd1a9a115 100644 --- a/Source/cm_unordered_set.hxx +++ b/Source/cm_unordered_set.hxx @@ -3,7 +3,7 @@ #ifndef CM_UNORDERED_SET_HXX #define CM_UNORDERED_SET_HXX -#include +#include "cmConfigure.h" #if defined(CMake_HAVE_CXX_UNORDERED_SET) @@ -12,7 +12,7 @@ #elif defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cmsys/hash_set.hxx" #define CM_UNORDERED_SET cmsys::hash_set #else diff --git a/Source/cm_utf8.c b/Source/cm_utf8.c index 6c49b5270..52af4a6f4 100644 --- a/Source/cm_utf8.c +++ b/Source/cm_utf8.c @@ -15,7 +15,7 @@ */ /* Number of leading ones before a zero in the byte. */ -static unsigned char const cm_utf8_ones[256] = { +unsigned char const cm_utf8_ones[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 6141f502e..689439378 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -23,10 +23,12 @@ #include "cmTargetLinkLibraryType.h" #include "cmUtils.hxx" #include "cmVersionConfig.h" +#include "cmWorkingDirectory.h" #include "cm_auto_ptr.hxx" +#include "cm_sys_stat.h" #if defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cm_jsoncpp_writer.h" #include "cmGraphVizWriter.h" #include "cmVariableWatch.h" @@ -61,7 +63,6 @@ #include "cmGlobalVisualStudio12Generator.h" #include "cmGlobalVisualStudio14Generator.h" #include "cmGlobalVisualStudio15Generator.h" -#include "cmGlobalVisualStudio71Generator.h" #include "cmGlobalVisualStudio8Generator.h" #include "cmGlobalVisualStudio9Generator.h" #include "cmVSSetupHelper.h" @@ -105,14 +106,10 @@ #include #endif -#include -// include sys/stat.h after sys/types.h -#include // struct stat - +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" +#include "cmsys/RegularExpression.hxx" #include -#include -#include -#include #include #include #include @@ -120,8 +117,6 @@ #include #include -class cmCommand; - namespace { #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -141,7 +136,7 @@ void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, cm->MarkCliAsUsed(variable); } -cmake::cmake() +cmake::cmake(Role role) { this->Trace = false; this->TraceExpand = false; @@ -179,7 +174,12 @@ cmake::cmake() this->AddDefaultGenerators(); this->AddDefaultExtraGenerators(); - this->AddDefaultCommands(); + if (role == RoleScript || role == RoleProject) { + this->AddScriptingCommands(); + } + if (role == RoleProject) { + this->AddProjectCommands(); + } // Make sure we can capture the build tool output. cmSystemTools::EnableVSConsoleOutput(); @@ -301,7 +301,7 @@ bool cmake::SetCacheArgs(const std::vector& args) { bool findPackageMode = false; for (unsigned int i = 1; i < args.size(); ++i) { - std::string arg = args[i]; + std::string const& arg = args[i]; if (arg.find("-D", 0) == 0) { std::string entry = arg.substr(2); if (entry.empty()) { @@ -447,6 +447,8 @@ bool cmake::SetCacheArgs(const std::vector& args) cmSystemTools::Error("No cmake script provided."); return false; } + // Register fake project commands that hint misuse in script mode. + GetProjectCommandsInScriptMode(this->State); this->ReadListFile(args, path.c_str()); } else if (arg.find("--find-package", 0) == 0) { findPackageMode = true; @@ -615,7 +617,7 @@ void cmake::SetArgs(const std::vector& args, bool haveToolset = false; bool havePlatform = false; for (unsigned int i = 1; i < args.size(); ++i) { - std::string arg = args[i]; + std::string const& arg = args[i]; if (arg.find("-H", 0) == 0) { directoriesSet = true; std::string path = arg.substr(2); @@ -1464,8 +1466,7 @@ void cmake::CreateDefaultGlobalGenerator() { "11.0", "Visual Studio 11 2012" }, // { "10.0", "Visual Studio 10 2010" }, // { "9.0", "Visual Studio 9 2008" }, // - { "8.0", "Visual Studio 8 2005" }, // - { "7.1", "Visual Studio 7 .NET 2003" } + { "8.0", "Visual Studio 8 2005" } }; static const char* const vsEntries[] = { "\\Setup\\VC;ProductDir", // @@ -1654,13 +1655,14 @@ const char* cmake::GetCacheDefinition(const std::string& name) const return this->State->GetInitializedCacheValue(name); } -void cmake::AddDefaultCommands() +void cmake::AddScriptingCommands() { - std::vector const commands = GetPredefinedCommands(); - for (std::vector::const_iterator i = commands.begin(); - i != commands.end(); ++i) { - this->State->AddCommand(*i); - } + GetScriptingCommands(this->State); +} + +void cmake::AddProjectCommands() +{ + GetProjectCommands(this->State); } void cmake::AddDefaultGenerators() @@ -1674,7 +1676,6 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalVisualStudio10Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio9Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio8Generator::NewFactory()); - this->Generators.push_back(cmGlobalVisualStudio71Generator::NewFactory()); this->Generators.push_back(cmGlobalBorlandMakefileGenerator::NewFactory()); this->Generators.push_back(cmGlobalNMakeMakefileGenerator::NewFactory()); this->Generators.push_back(cmGlobalJOMMakefileGenerator::NewFactory()); @@ -1893,7 +1894,7 @@ int cmake::CheckBuildSystem() // Read the rerun check file and use it to decide whether to do the // global generate. - cmake cm; + cmake cm(RoleScript); // Actually, all we need is the `set` command. cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); @@ -2145,7 +2146,7 @@ int cmake::GetSystemInformation(std::vector& args) // process the arguments bool writeToStdout = true; for (unsigned int i = 1; i < args.size(); ++i) { - std::string arg = args[i]; + std::string const& arg = args[i]; if (arg.find("-G", 0) == 0) { std::string value = arg.substr(2); if (value.empty()) { @@ -2199,24 +2200,23 @@ int cmake::GetSystemInformation(std::vector& args) resultFile += "/__cmake_systeminformation/results.txt"; } - // now run cmake on the CMakeLists file - cmSystemTools::ChangeDirectory(destPath); - std::vector args2; - args2.push_back(args[0]); - args2.push_back(destPath); - std::string resultArg = "-DRESULT_FILE="; - resultArg += resultFile; - args2.push_back(resultArg); - int res = this->Run(args2, false); + { + // now run cmake on the CMakeLists file + cmWorkingDirectory workdir(destPath); + std::vector args2; + args2.push_back(args[0]); + args2.push_back(destPath); + std::string resultArg = "-DRESULT_FILE="; + resultArg += resultFile; + args2.push_back(resultArg); + int res = this->Run(args2, false); - if (res != 0) { - std::cerr << "Error: --system-information failed on internal CMake!\n"; - return res; + if (res != 0) { + std::cerr << "Error: --system-information failed on internal CMake!\n"; + return res; + } } - // change back to the original directory - cmSystemTools::ChangeDirectory(cwd); - // echo results to stdout if needed if (writeToStdout) { FILE* fin = cmsys::SystemTools::Fopen(resultFile, "r"); @@ -2425,6 +2425,9 @@ int cmake::Build(const std::string& dir, const std::string& target, std::string homeOutputOrig = this->GetHomeOutputDirectory(); this->SetDirectoriesFromFile(cachePath.c_str()); + this->AddScriptingCommands(); + this->AddProjectCommands(); + int ret = this->Configure(); if (ret) { cmSystemTools::Message("CMake Configure step failed. " diff --git a/Source/cmake.h b/Source/cmake.h index 5347745b0..4ddacf701 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -3,7 +3,7 @@ #ifndef cmake_h #define cmake_h -#include +#include "cmConfigure.h" #include #include @@ -16,7 +16,7 @@ #include "cmStateTypes.h" #if defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cm_jsoncpp_value.h" #endif class cmExternalMakefileProjectGeneratorFactory; @@ -55,7 +55,16 @@ struct cmDocumentationEntry; class cmake { + CM_DISABLE_COPY(cmake) + public: + enum Role + { + RoleInternal, // no commands + RoleScript, // script commands + RoleProject // all commands + }; + enum MessageType { AUTHOR_WARNING, @@ -110,7 +119,7 @@ public: typedef std::map InstalledFilesMap; /// Default constructor - cmake(); + cmake(Role role); /// Destructor ~cmake(); @@ -409,7 +418,7 @@ public: void WatchUnusedCli(const std::string& var); cmState* GetState() const { return this->State; } - void SetCurrentSnapshot(cmStateSnapshot snapshot) + void SetCurrentSnapshot(cmStateSnapshot const& snapshot) { this->CurrentSnapshot = snapshot; } @@ -425,7 +434,8 @@ protected: typedef std::vector RegisteredExtraGeneratorsVector; RegisteredExtraGeneratorsVector ExtraGenerators; - void AddDefaultCommands(); + void AddScriptingCommands(); + void AddProjectCommands(); void AddDefaultGenerators(); void AddDefaultExtraGenerators(); @@ -459,8 +469,6 @@ protected: cmVariableWatch* VariableWatch; private: - cmake(const cmake&); // Not implemented. - void operator=(const cmake&); // Not implemented. ProgressCallbackType ProgressCallback; void* ProgressCallbackClientData; bool InTryCompile; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index b8e227f56..c5a6836bf 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -1,11 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -// include these first, otherwise there will be problems on Windows -// with GetCurrentDirectory() being redefined -#ifdef CMAKE_BUILD_WITH_CMAKE -#include "cmDocumentation.h" -#include "cmDynamicLoader.h" -#endif +#include "cmConfigure.h" #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" @@ -17,10 +12,14 @@ #include "cmake.h" #include "cmcmd.h" -#include -#include +#ifdef CMAKE_BUILD_WITH_CMAKE +#include "cmDocumentation.h" +#include "cmDynamicLoader.h" +#endif + +#include "cmsys/Encoding.hxx" #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cmsys/ConsoleBuf.hxx" #endif #include #include @@ -28,7 +27,11 @@ #include #ifdef CMAKE_USE_LIBUV -#include +#ifdef _WIN32 +#include /* _O_TEXT */ +#include /* _set_fmode, _fmode */ +#endif +#include "cm_uv.h" #endif #ifdef CMAKE_BUILD_WITH_CMAKE @@ -169,6 +172,18 @@ int main(int ac, char const* const* av) ac = args.argc(); av = args.argv(); +#if defined(CMAKE_USE_LIBUV) && defined(_WIN32) + // Perform libuv one-time initialization now, and then un-do its + // global _fmode setting so that using libuv does not change the + // default file text/binary mode. See libuv issue 840. + uv_loop_close(uv_default_loop()); +#ifdef _MSC_VER + _set_fmode(_O_TEXT); +#else + _fmode = _O_TEXT; +#endif +#endif + cmSystemTools::EnableMSVCDebugHook(); cmSystemTools::FindCMakeResources(av[0]); if (ac > 1) { @@ -202,7 +217,7 @@ int do_cmake(int ac, char const* const* av) doc.addCMakeStandardDocSections(); if (doc.CheckOptions(ac, av)) { // Construct and print requested documentation. - cmake hcm; + cmake hcm(cmake::RoleInternal); hcm.SetHomeDirectory(""); hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); @@ -284,13 +299,15 @@ int do_cmake(int ac, char const* const* av) } } if (sysinfo) { - cmake cm; + cmake cm(cmake::RoleProject); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); int ret = cm.GetSystemInformation(args); return ret; } - cmake cm; + cmake::Role const role = + workingMode == cmake::NORMAL_MODE ? cmake::RoleProject : cmake::RoleScript; + cmake cm(role); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm); @@ -408,7 +425,7 @@ static int do_build(int ac, char const* const* av) return 1; } - cmake cm; + cmake cm(cmake::RoleInternal); cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm); cm.SetProgressCallback(cmakemainProgressCallback, (void*)&cm); return cm.Build(dir, target, config, nativeOptions, clean); diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx index e166bee3f..72da456d4 100644 --- a/Source/cmakexbuild.cxx +++ b/Source/cmakexbuild.cxx @@ -1,9 +1,9 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep -#include +#include "cmsys/Process.h" #include #include #include @@ -29,7 +29,8 @@ int RunXCode(std::vector& argv, bool& hitbug) std::string line; int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err); while (pipe != cmsysProcess_Pipe_None) { - if (line.find("/bin/sh: bad interpreter: Text file busy") != line.npos) { + if (line.find("/bin/sh: bad interpreter: Text file busy") != + std::string::npos) { hitbug = true; std::cerr << "Hit xcodebuild bug : " << line << "\n"; } @@ -37,7 +38,7 @@ int RunXCode(std::vector& argv, bool& hitbug) // because it may contain bogus errors // also remove all output with setenv in it to tone down // the verbosity of xcodebuild - if (!hitbug && (line.find("setenv") == line.npos)) { + if (!hitbug && (line.find("setenv") == std::string::npos)) { if (pipe == cmsysProcess_Pipe_STDERR) { std::cerr << line << "\n"; } else if (pipe == cmsysProcess_Pipe_STDOUT) { diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index b86ad6e4f..0c5bbe2df 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -18,8 +18,8 @@ // /showIncludes is equivalent to -MD, not -MMD, that is, system headers are // included. -#include -#include +#include "cmSystemTools.h" +#include "cmsys/Encoding.hxx" #include #include diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 823b38f6c..d5b086174 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -32,12 +32,12 @@ #include "cmVisualStudioWCEPlatformParser.h" #endif +#include "cmConfigure.h" +#include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmsys/Process.h" +#include "cmsys/Terminal.h" #include -#include -#include -#include -#include -#include #include #include #include @@ -258,11 +258,18 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) << "\n"; return 1; } - std::string objfile; + std::string file; bindexplib deffile; - while (cmSystemTools::GetLineFromStream(fin, objfile)) { - if (!deffile.AddObjectFile(objfile.c_str())) { - return 1; + while (cmSystemTools::GetLineFromStream(fin, file)) { + std::string const& ext = cmSystemTools::GetFilenameLastExtension(file); + if (cmSystemTools::LowerCase(ext) == ".def") { + if (!deffile.AddDefinitionFile(file.c_str())) { + return 1; + } + } else { + if (!deffile.AddObjectFile(file.c_str())) { + return 1; + } } } deffile.WriteFile(fout); @@ -344,8 +351,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) } // Warn if iwyu reported anything. - if (stdErr.find("should remove these lines:") != stdErr.npos || - stdErr.find("should add these lines:") != stdErr.npos) { + if (stdErr.find("should remove these lines:") != std::string::npos || + stdErr.find("should add these lines:") != std::string::npos) { std::cerr << "Warning: include-what-you-use reported diagnostics:\n" << stdErr << "\n"; } @@ -405,7 +412,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) // Output the stdout from ldd -r -u to stderr // Warn if lwyu reported anything. - if (stdOut.find("Unused direct dependencies:") != stdOut.npos) { + if (stdOut.find("Unused direct dependencies:") != std::string::npos) { std::cerr << "Warning: " << stdOut; } } @@ -473,7 +480,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) std::cerr << "cmake -E env: unknown option '" << a << "'" << std::endl; return 1; - } else if (a.find('=') != a.npos) { + } else if (a.find('=') != std::string::npos) { // Set environment variable. cmSystemTools::PutEnv(a); } else { @@ -576,7 +583,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) std::cerr << "-E capabilities accepts no additional arguments\n"; return 1; } - cmake cm; + cmake cm(cmake::RoleInternal); #if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE std::cout << cm.ReportCapabilities(true); #else @@ -656,7 +663,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) // Command to change directory and run a program. if (args[1] == "chdir" && args.size() >= 4) { - std::string directory = args[2]; + std::string const& directory = args[2]; if (!cmSystemTools::FileExists(directory.c_str())) { cmSystemTools::Error("Directory does not exist for chdir command: ", args[2].c_str()); @@ -753,7 +760,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) const bool verbose = isCMakeVerbose(); // Create a cmake object instance to process dependencies. - cmake cm; + cmake cm(cmake::RoleScript); // All we need is the `set` command. std::string gen; std::string homeDir; std::string startDir; @@ -876,8 +883,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) if (args[1] == "tar" && args.size() > 3) { const char* knownFormats[] = { "7zip", "gnutar", "pax", "paxr", "zip" }; - std::string flags = args[2]; - std::string outFile = args[3]; + std::string const& flags = args[2]; + std::string const& outFile = args[3]; std::vector files; std::string mtime; std::string format; @@ -917,15 +924,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) cmSystemTools::TarCompressNone; bool verbose = false; int nCompress = 0; - if (flags.find_first_of('j') != flags.npos) { + if (flags.find_first_of('j') != std::string::npos) { compress = cmSystemTools::TarCompressBZip2; ++nCompress; } - if (flags.find_first_of('J') != flags.npos) { + if (flags.find_first_of('J') != std::string::npos) { compress = cmSystemTools::TarCompressXZ; ++nCompress; } - if (flags.find_first_of('z') != flags.npos) { + if (flags.find_first_of('z') != std::string::npos) { compress = cmSystemTools::TarCompressGZip; ++nCompress; } @@ -939,22 +946,22 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) "at most one flag of z, j, or J may be used"); return 1; } - if (flags.find_first_of('v') != flags.npos) { + if (flags.find_first_of('v') != std::string::npos) { verbose = true; } - if (flags.find_first_of('t') != flags.npos) { + if (flags.find_first_of('t') != std::string::npos) { if (!cmSystemTools::ListTar(outFile.c_str(), verbose)) { cmSystemTools::Error("Problem listing tar: ", outFile.c_str()); return 1; } - } else if (flags.find_first_of('c') != flags.npos) { + } else if (flags.find_first_of('c') != std::string::npos) { if (!cmSystemTools::CreateTar(outFile.c_str(), files, compress, verbose, mtime, format)) { cmSystemTools::Error("Problem creating tar: ", outFile.c_str()); return 1; } - } else if (flags.find_first_of('x') != flags.npos) { + } else if (flags.find_first_of('x') != std::string::npos) { if (!cmSystemTools::ExtractTar(outFile.c_str(), verbose)) { cmSystemTools::Error("Problem extracting tar: ", outFile.c_str()); return 1; @@ -1070,9 +1077,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) int cmcmd::SymlinkLibrary(std::vector& args) { int result = 0; - std::string realName = args[2]; - std::string soName = args[3]; - std::string name = args[4]; + std::string const& realName = args[2]; + std::string const& soName = args[3]; + std::string const& name = args[4]; if (soName != realName) { if (!cmcmd::SymlinkInternal(realName, soName)) { cmSystemTools::ReportLastSystemError("cmake_symlink_library"); @@ -1091,8 +1098,8 @@ int cmcmd::SymlinkLibrary(std::vector& args) int cmcmd::SymlinkExecutable(std::vector& args) { int result = 0; - std::string realName = args[2]; - std::string name = args[3]; + std::string const& realName = args[2]; + std::string const& name = args[3]; if (name != realName) { if (!cmcmd::SymlinkInternal(realName, name)) { cmSystemTools::ReportLastSystemError("cmake_symlink_executable"); @@ -1265,7 +1272,7 @@ int cmcmd::ExecuteLinkScript(std::vector& args) int result = 0; while (result == 0 && cmSystemTools::GetLineFromStream(fin, command)) { // Skip empty command lines. - if (command.find_first_not_of(" \t") == command.npos) { + if (command.find_first_not_of(" \t") == std::string::npos) { continue; } @@ -1413,7 +1420,7 @@ static bool RunCommand(const char* comment, std::vector& command, // it is the dumb rc command banner, but if the command // returned an error code then print the output anyway as // the banner may be mixed with some other important information. - if (output.find("Resource Compiler Version") == output.npos || !res || + if (output.find("Resource Compiler Version") == std::string::npos || !res || retCode) { std::cout << output; } @@ -1443,7 +1450,8 @@ bool cmVSLink::Parse(std::vector::const_iterator argBeg, if (*arg == "--") { ++arg; break; - } else if (*arg == "--manifests") { + } + if (*arg == "--manifests") { for (++arg; arg != argEnd && !cmHasLiteralPrefix(*arg, "-"); ++arg) { this->UserManifests.push_back(*arg); } diff --git a/Source/cmcmd.h b/Source/cmcmd.h index 139d2a824..929f1ae47 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -3,7 +3,7 @@ #ifndef cmcmd_h #define cmcmd_h -#include // IWYU pragma: keep +#include "cmConfigure.h" // IWYU pragma: keep #include #include diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 1cf75c879..84e815d1d 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -1,17 +1,16 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include +#include "cmConfigure.h" #include "CTest/cmCTestLaunch.h" #include "CTest/cmCTestScriptHandler.h" #include "cmCTest.h" #include "cmDocumentation.h" #include "cmSystemTools.h" -#include "cmake.h" -#include +#include "cmsys/Encoding.hxx" #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) -#include +#include "cmsys/ConsoleBuf.hxx" #endif #include #include @@ -52,6 +51,18 @@ static const char* cmDocumentationOptions[][2] = { "expression." }, { "-LE , --label-exclude ", "Exclude tests with labels " "matching regular expression." }, + { "-FA , --fixture-exclude-any ", "Do not automatically " + "add any tests for " + "fixtures matching " + "regular expression." }, + { "-FS , --fixture-exclude-setup ", "Do not automatically " + "add setup tests for " + "fixtures matching " + "regular expression." }, + { "-FC , --fixture-exclude-cleanup ", "Do not automatically " + "add cleanup tests for " + "fixtures matching " + "regular expression." }, { "-D , --dashboard ", "Execute dashboard test" }, { "-D :=", "Define a variable for script mode" }, { "-M , --test-model ", "Sets the model for a dashboard" }, @@ -158,11 +169,6 @@ int main(int argc, char const* const* argv) cmDocumentation doc; doc.addCTestStandardDocSections(); if (doc.CheckOptions(argc, argv)) { - cmake hcm; - hcm.SetHomeDirectory(""); - hcm.SetHomeOutputDirectory(""); - hcm.AddCMakePaths(); - // Construct and print requested documentation. cmCTestScriptHandler* ch = static_cast(inst.GetHandler("script")); diff --git a/Source/kwsys/.gitattributes b/Source/kwsys/.gitattributes index a121ad109..7065eb5cb 100644 --- a/Source/kwsys/.gitattributes +++ b/Source/kwsys/.gitattributes @@ -1,12 +1,13 @@ .git* export-ignore -*.c whitespace=tab-in-indent,no-lf-at-eof -*.h whitespace=tab-in-indent,no-lf-at-eof -*.h.in whitespace=tab-in-indent,no-lf-at-eof -*.cxx whitespace=tab-in-indent,no-lf-at-eof -*.hxx whitespace=tab-in-indent,no-lf-at-eof -*.hxx.in whitespace=tab-in-indent,no-lf-at-eof -*.txt whitespace=tab-in-indent,no-lf-at-eof -*.cmake whitespace=tab-in-indent,no-lf-at-eof +*.c kwsys-c-style +*.c.in kwsys-c-style +*.cxx kwsys-c-style +*.h kwsys-c-style +*.h.in kwsys-c-style +*.hxx kwsys-c-style +*.hxx.in kwsys-c-style +*.cmake whitespace=tab-in-indent *.rst whitespace=tab-in-indent conflict-marker-size=79 +*.txt whitespace=tab-in-indent diff --git a/Source/kwsys/Base64.c b/Source/kwsys/Base64.c index 37c3b8c40..99f008e59 100644 --- a/Source/kwsys/Base64.c +++ b/Source/kwsys/Base64.c @@ -9,13 +9,11 @@ #include "Base64.h.in" #endif -/*--------------------------------------------------------------------------*/ static const unsigned char kwsysBase64EncodeTable[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; -/*--------------------------------------------------------------------------*/ static const unsigned char kwsysBase64DecodeTable[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -40,19 +38,16 @@ static const unsigned char kwsysBase64DecodeTable[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -/*--------------------------------------------------------------------------*/ static unsigned char kwsysBase64EncodeChar(int c) { return kwsysBase64EncodeTable[(unsigned char)c]; } -/*--------------------------------------------------------------------------*/ static unsigned char kwsysBase64DecodeChar(unsigned char c) { return kwsysBase64DecodeTable[c]; } -/*--------------------------------------------------------------------------*/ /* Encode 3 bytes into a 4 byte string. */ void kwsysBase64_Encode3(const unsigned char* src, unsigned char* dest) { @@ -64,7 +59,6 @@ void kwsysBase64_Encode3(const unsigned char* src, unsigned char* dest) dest[3] = kwsysBase64EncodeChar(src[2] & 0x3F); } -/*--------------------------------------------------------------------------*/ /* Encode 2 bytes into a 4 byte string. */ void kwsysBase64_Encode2(const unsigned char* src, unsigned char* dest) { @@ -75,7 +69,6 @@ void kwsysBase64_Encode2(const unsigned char* src, unsigned char* dest) dest[3] = '='; } -/*--------------------------------------------------------------------------*/ /* Encode 1 bytes into a 4 byte string. */ void kwsysBase64_Encode1(const unsigned char* src, unsigned char* dest) { @@ -85,7 +78,6 @@ void kwsysBase64_Encode1(const unsigned char* src, unsigned char* dest) dest[3] = '='; } -/*--------------------------------------------------------------------------*/ /* Encode 'length' bytes from the input buffer and store the encoded stream into the output buffer. Return the length of the encoded buffer (output). Note that the output buffer must be allocated by the caller @@ -135,7 +127,6 @@ size_t kwsysBase64_Encode(const unsigned char* input, size_t length, return (size_t)(optr - output); } -/*--------------------------------------------------------------------------*/ /* Decode 4 bytes into a 3 byte string. */ int kwsysBase64_Decode3(const unsigned char* src, unsigned char* dest) { @@ -169,7 +160,6 @@ int kwsysBase64_Decode3(const unsigned char* src, unsigned char* dest) return 3; } -/*--------------------------------------------------------------------------*/ /* Decode bytes from the input buffer and store the decoded stream into the output buffer until 'length' bytes have been decoded. Return the real length of the decoded stream (which should be equal to 'length'). Note diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index d4fe8a71f..e915b1a80 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -69,6 +69,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR) FOREACH(p CMP0025 # CMake 3.0, Compiler id for Apple Clang is now AppleClang. + CMP0048 # CMake 3.0, Let the project command manage version variables. CMP0056 # CMake 3.2, Honor link flags in try_compile() source-file signature. CMP0063 # CMake 3.3, Honor visibility properties for all target types. ) @@ -796,6 +797,10 @@ ENDFOREACH() IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) ADD_LIBRARY(${KWSYS_NAMESPACE} ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY C_CLANG_TIDY "") + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY CXX_CLANG_TIDY "") + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY C_INCLUDE_WHAT_YOU_USE "") + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY LABELS ${KWSYS_LABELS_LIB}) IF(KWSYS_USE_DynamicLoader) IF(UNIX) @@ -940,13 +945,17 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) ENDIF() IF(KWSYS_USE_ConsoleBuf) ADD_EXECUTABLE(testConsoleBufChild testConsoleBufChild.cxx) + SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_CLANG_TIDY "") + SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_CLANG_TIDY "") + SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_INCLUDE_WHAT_YOU_USE "") + SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") SET_PROPERTY(TARGET testConsoleBufChild PROPERTY LABELS ${KWSYS_LABELS_EXE}) TARGET_LINK_LIBRARIES(testConsoleBufChild ${KWSYS_NAMESPACE}) SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testConsoleBuf ) IF("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND - NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0") + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506") set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8) ENDIF() SET_PROPERTY(SOURCE testConsoleBuf.cxx APPEND PROPERTY COMPILE_DEFINITIONS @@ -967,6 +976,10 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) ${KWSYS_CXX_TESTS} ) ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_CXX_TEST_SRCS}) + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_CLANG_TIDY "") + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_CLANG_TIDY "") + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_INCLUDE_WHAT_YOU_USE "") + SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY LABELS ${KWSYS_LABELS_EXE}) TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_NAMESPACE}) @@ -1032,8 +1045,12 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) # Some Apple compilers produce bad optimizations in this source. IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$") SET_SOURCE_FILES_PROPERTIES(testProcess.c PROPERTIES COMPILE_FLAGS -O0) - ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL") + ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL" AND + NOT (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND + NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1")) # Tell IBM XL not to warn about our test infinite loop + # v13.1.1 and newer on Linux ppc64le is clang based and does not accept + # the -qsuppress option SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS -qsuppress=1500-010) ENDIF() diff --git a/Source/kwsys/CONTRIBUTING.rst b/Source/kwsys/CONTRIBUTING.rst index d71832a1b..70a313e05 100644 --- a/Source/kwsys/CONTRIBUTING.rst +++ b/Source/kwsys/CONTRIBUTING.rst @@ -27,10 +27,12 @@ copies of KWSys within dependent projects can be updated to get the changes. Code Style ========== -We use `clang-format`_ to define our style for C++ code in the KWSys source -tree. See the `.clang-format`_ configuration file for our style settings. -Use ``clang-format`` version 3.8 or higher to format source files. -See also the `clang-format.bash`_ script. +We use `clang-format`_ version **3.8** to define our style for C++ code in +the KWSys source tree. See the `.clang-format`_ configuration file for +our style settings. Use the `clang-format.bash`_ script to format source +code. It automatically runs ``clang-format`` on the set of source files +for which we enforce style. The script also has options to format only +a subset of files, such as those that are locally modified. .. _`clang-format`: http://clang.llvm.org/docs/ClangFormat.html .. _`.clang-format`: .clang-format diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx index 226263cc9..5613bd7ab 100644 --- a/Source/kwsys/CommandLineArguments.cxx +++ b/Source/kwsys/CommandLineArguments.cxx @@ -41,8 +41,6 @@ namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- -//============================================================================ struct CommandLineArgumentsCallbackStructure { const char* Argument; @@ -91,10 +89,7 @@ public: VectorOfStrings UnusedArguments; }; -//============================================================================ -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- CommandLineArguments::CommandLineArguments() { this->Internals = new CommandLineArguments::Internal; @@ -103,13 +98,11 @@ CommandLineArguments::CommandLineArguments() this->StoreUnusedArgumentsFlag = false; } -//---------------------------------------------------------------------------- CommandLineArguments::~CommandLineArguments() { delete this->Internals; } -//---------------------------------------------------------------------------- void CommandLineArguments::Initialize(int argc, const char* const argv[]) { int cc; @@ -121,26 +114,22 @@ void CommandLineArguments::Initialize(int argc, const char* const argv[]) } } -//---------------------------------------------------------------------------- void CommandLineArguments::Initialize(int argc, char* argv[]) { this->Initialize(argc, static_cast(argv)); } -//---------------------------------------------------------------------------- void CommandLineArguments::Initialize() { this->Internals->Argv.clear(); this->Internals->LastArgument = 0; } -//---------------------------------------------------------------------------- void CommandLineArguments::ProcessArgument(const char* arg) { this->Internals->Argv.push_back(arg); } -//---------------------------------------------------------------------------- bool CommandLineArguments::GetMatchedArguments( std::vector* matches, const std::string& arg) { @@ -164,7 +153,6 @@ bool CommandLineArguments::GetMatchedArguments( return !matches->empty(); } -//---------------------------------------------------------------------------- int CommandLineArguments::Parse() { std::vector::size_type cc; @@ -286,7 +274,6 @@ int CommandLineArguments::Parse() return 1; } -//---------------------------------------------------------------------------- void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv) { CommandLineArguments::Internal::VectorOfStrings::size_type size = @@ -310,7 +297,6 @@ void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv) *argv = args; } -//---------------------------------------------------------------------------- void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv) { CommandLineArguments::Internal::VectorOfStrings::size_type size = @@ -334,7 +320,6 @@ void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv) *argv = args; } -//---------------------------------------------------------------------------- void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv) { int cc; @@ -344,7 +329,6 @@ void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv) delete[] * argv; } -//---------------------------------------------------------------------------- void CommandLineArguments::AddCallback(const char* argument, ArgumentTypeEnum type, CallbackType callback, void* call_data, @@ -363,7 +347,6 @@ void CommandLineArguments::AddCallback(const char* argument, this->GenerateHelp(); } -//---------------------------------------------------------------------------- void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, VariableTypeEnum vtype, void* variable, @@ -382,7 +365,6 @@ void CommandLineArguments::AddArgument(const char* argument, this->GenerateHelp(); } -//---------------------------------------------------------------------------- #define CommandLineArgumentsAddArgumentMacro(type, ctype) \ void CommandLineArguments::AddArgument(const char* argument, \ ArgumentTypeEnum type, \ @@ -392,22 +374,24 @@ void CommandLineArguments::AddArgument(const char* argument, variable, help); \ } +/* clang-format off */ CommandLineArgumentsAddArgumentMacro(BOOL, bool) - CommandLineArgumentsAddArgumentMacro(INT, int) - CommandLineArgumentsAddArgumentMacro(DOUBLE, double) - CommandLineArgumentsAddArgumentMacro(STRING, char*) - CommandLineArgumentsAddArgumentMacro(STL_STRING, std::string) - - CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, std::vector) - CommandLineArgumentsAddArgumentMacro(VECTOR_INT, std::vector) - CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, - std::vector) - CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, - std::vector) - CommandLineArgumentsAddArgumentMacro( - VECTOR_STL_STRING, std::vector) - -//---------------------------------------------------------------------------- +CommandLineArgumentsAddArgumentMacro(INT, int) +CommandLineArgumentsAddArgumentMacro(DOUBLE, double) +CommandLineArgumentsAddArgumentMacro(STRING, char*) +CommandLineArgumentsAddArgumentMacro(STL_STRING, std::string) + +CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, std::vector) +CommandLineArgumentsAddArgumentMacro(VECTOR_INT, std::vector) +CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, std::vector) +CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, std::vector) +CommandLineArgumentsAddArgumentMacro(VECTOR_STL_STRING, + std::vector) +#ifdef HELP_CLANG_FORMAT +; +#endif +/* clang-format on */ + #define CommandLineArgumentsAddBooleanArgumentMacro(type, ctype) \ void CommandLineArguments::AddBooleanArgument( \ const char* argument, ctype* variable, const char* help) \ @@ -416,29 +400,28 @@ CommandLineArgumentsAddArgumentMacro(BOOL, bool) CommandLineArguments::type##_TYPE, variable, help); \ } - CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool) - CommandLineArgumentsAddBooleanArgumentMacro(INT, int) - CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, - double) - CommandLineArgumentsAddBooleanArgumentMacro(STRING, - char*) - CommandLineArgumentsAddBooleanArgumentMacro( - STL_STRING, std::string) +/* clang-format off */ +CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool) +CommandLineArgumentsAddBooleanArgumentMacro(INT, int) +CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, double) +CommandLineArgumentsAddBooleanArgumentMacro(STRING, char*) +CommandLineArgumentsAddBooleanArgumentMacro(STL_STRING, std::string) +#ifdef HELP_CLANG_FORMAT +; +#endif +/* clang-format on */ - //---------------------------------------------------------------------------- - void CommandLineArguments::SetClientData(void* client_data) +void CommandLineArguments::SetClientData(void* client_data) { this->Internals->ClientData = client_data; } -//---------------------------------------------------------------------------- void CommandLineArguments::SetUnknownArgumentCallback( CommandLineArguments::ErrorCallbackType callback) { this->Internals->UnknownArgumentCallback = callback; } -//---------------------------------------------------------------------------- const char* CommandLineArguments::GetHelp(const char* arg) { CommandLineArguments::Internal::CallbacksMap::iterator it = @@ -461,7 +444,6 @@ const char* CommandLineArguments::GetHelp(const char* arg) return cs->Help; } -//---------------------------------------------------------------------------- void CommandLineArguments::SetLineLength(unsigned int ll) { if (ll < 9 || ll > 1000) { @@ -471,19 +453,16 @@ void CommandLineArguments::SetLineLength(unsigned int ll) this->GenerateHelp(); } -//---------------------------------------------------------------------------- const char* CommandLineArguments::GetArgv0() { return this->Internals->Argv0.c_str(); } -//---------------------------------------------------------------------------- unsigned int CommandLineArguments::GetLastArgument() { return static_cast(this->Internals->LastArgument + 1); } -//---------------------------------------------------------------------------- void CommandLineArguments::GenerateHelp() { std::ostringstream str; @@ -633,7 +612,6 @@ void CommandLineArguments::GenerateHelp() this->Help = str.str(); } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(bool* variable, const std::string& value) { @@ -646,7 +624,6 @@ void CommandLineArguments::PopulateVariable(bool* variable, } } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(int* variable, const std::string& value) { @@ -658,7 +635,6 @@ void CommandLineArguments::PopulateVariable(int* variable, // } } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(double* variable, const std::string& value) { @@ -670,7 +646,6 @@ void CommandLineArguments::PopulateVariable(double* variable, // } } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(char** variable, const std::string& value) { @@ -682,14 +657,12 @@ void CommandLineArguments::PopulateVariable(char** variable, strcpy(*variable, value.c_str()); } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(std::string* variable, const std::string& value) { *variable = value; } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(std::vector* variable, const std::string& value) { @@ -702,7 +675,6 @@ void CommandLineArguments::PopulateVariable(std::vector* variable, variable->push_back(val); } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(std::vector* variable, const std::string& value) { @@ -714,7 +686,6 @@ void CommandLineArguments::PopulateVariable(std::vector* variable, // } } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(std::vector* variable, const std::string& value) { @@ -726,7 +697,6 @@ void CommandLineArguments::PopulateVariable(std::vector* variable, // } } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(std::vector* variable, const std::string& value) { @@ -735,14 +705,12 @@ void CommandLineArguments::PopulateVariable(std::vector* variable, variable->push_back(var); } -//---------------------------------------------------------------------------- void CommandLineArguments::PopulateVariable(std::vector* variable, const std::string& value) { variable->push_back(value); } -//---------------------------------------------------------------------------- bool CommandLineArguments::PopulateVariable( CommandLineArgumentsCallbackStructure* cs, const char* value) { diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in index cb588658f..46d65a865 100644 --- a/Source/kwsys/ConsoleBuf.hxx.in +++ b/Source/kwsys/ConsoleBuf.hxx.in @@ -25,8 +25,7 @@ namespace @KWSYS_NAMESPACE@ { #if defined(_WIN32) template > -class @KWSYS_NAMESPACE@_EXPORT BasicConsoleBuf - : public std::basic_streambuf +class BasicConsoleBuf : public std::basic_streambuf { public: typedef typename Traits::int_type int_type; @@ -339,7 +338,7 @@ private: } bool decodeInputBuffer(const std::string buffer, std::wstring& wbuffer) { - int length = int(buffer.length()); + size_t length = buffer.length(); if (length == 0) { wbuffer = std::wstring(); return true; @@ -354,11 +353,12 @@ private: data += BOMsize; length -= BOMsize; } - const int wlength = - MultiByteToWideChar(actualCodepage, 0, data, length, NULL, 0); + const size_t wlength = static_cast(MultiByteToWideChar( + actualCodepage, 0, data, static_cast(length), NULL, 0)); wchar_t* wbuf = new wchar_t[wlength]; const bool success = - MultiByteToWideChar(actualCodepage, 0, data, length, wbuf, wlength) > 0 + MultiByteToWideChar(actualCodepage, 0, data, static_cast(length), + wbuf, static_cast(wlength)) > 0 ? true : false; wbuffer = std::wstring(wbuf, wlength); diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index 3c31b49eb..5141d4519 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -20,7 +20,6 @@ namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- class DirectoryInternals { public: @@ -31,25 +30,21 @@ public: std::string Path; }; -//---------------------------------------------------------------------------- Directory::Directory() { this->Internal = new DirectoryInternals; } -//---------------------------------------------------------------------------- Directory::~Directory() { delete this->Internal; } -//---------------------------------------------------------------------------- unsigned long Directory::GetNumberOfFiles() const { return static_cast(this->Internal->Files.size()); } -//---------------------------------------------------------------------------- const char* Directory::GetFile(unsigned long dindex) const { if (dindex >= this->Internal->Files.size()) { @@ -58,13 +53,11 @@ const char* Directory::GetFile(unsigned long dindex) const return this->Internal->Files[dindex].c_str(); } -//---------------------------------------------------------------------------- const char* Directory::GetPath() const { return this->Internal->Path.c_str(); } -//---------------------------------------------------------------------------- void Directory::Clear() { this->Internal->Path.resize(0); @@ -116,7 +109,7 @@ bool Directory::Load(const std::string& name) // Make sure the slashes in the wildcard suffix are consistent with the // rest of the path buf = new char[n + 2 + 1]; - if (name.find('\\') != name.npos) { + if (name.find('\\') != std::string::npos) { sprintf(buf, "%s\\*", name.c_str()); } else { sprintf(buf, "%s/*", name.c_str()); diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index e494db69c..1b4596a4e 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -26,20 +26,17 @@ // the static methods of DynamicLoader. #if !KWSYS_SUPPORTS_SHARED_LIBS -//---------------------------------------------------------------------------- // Implementation for environments without dynamic libs #include // for strerror() namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname) { return 0; } -//---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { if (!lib) { @@ -49,14 +46,12 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) return 1; } -//---------------------------------------------------------------------------- DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( DynamicLoader::LibraryHandle lib, const std::string& sym) { return 0; } -//---------------------------------------------------------------------------- const char* DynamicLoader::LastError() { return "General error"; @@ -65,21 +60,18 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE #elif defined(__hpux) -//---------------------------------------------------------------------------- // Implementation for HPUX machines #include #include namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname) { return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L); } -//---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { if (!lib) { @@ -88,7 +80,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) return !shl_unload(lib); } -//---------------------------------------------------------------------------- DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( DynamicLoader::LibraryHandle lib, const std::string& sym) { @@ -132,14 +123,12 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE #elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030) -//---------------------------------------------------------------------------- // Implementation for Mac OS X 10.2.x and earlier #include #include // for strlen namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname) { @@ -158,7 +147,6 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( return handle; } -//---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { // NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED @@ -170,7 +158,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) return success; } -//---------------------------------------------------------------------------- DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( DynamicLoader::LibraryHandle lib, const std::string& sym) { @@ -191,7 +178,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( return *reinterpret_cast(&result); } -//---------------------------------------------------------------------------- const char* DynamicLoader::LastError() { return 0; @@ -200,13 +186,11 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE #elif defined(_WIN32) && !defined(__CYGWIN__) -//---------------------------------------------------------------------------- // Implementation for Windows win32 code but not cygwin #include namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname) { @@ -220,13 +204,11 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( return lh; } -//---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { return (int)FreeLibrary(lib); } -//---------------------------------------------------------------------------- DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( DynamicLoader::LibraryHandle lib, const std::string& sym) { @@ -274,7 +256,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( #endif } -//---------------------------------------------------------------------------- const char* DynamicLoader::LastError() { LPVOID lpMsgBuf = NULL; @@ -299,7 +280,6 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE #elif defined(__BEOS__) -//---------------------------------------------------------------------------- // Implementation for BeOS / Haiku #include // for strerror() @@ -310,7 +290,6 @@ namespace KWSYS_NAMESPACE { static image_id last_dynamic_err = B_OK; -//---------------------------------------------------------------------------- DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname) { @@ -325,7 +304,6 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( return rc + 1; } -//---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { if (!lib) { @@ -343,7 +321,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) return 1; } -//---------------------------------------------------------------------------- DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( DynamicLoader::LibraryHandle lib, const std::string& sym) { @@ -372,7 +349,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( return result.psym; } -//---------------------------------------------------------------------------- const char* DynamicLoader::LastError() { const char* retval = strerror(last_dynamic_err); @@ -383,7 +359,6 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE #elif defined(__MINT__) -//---------------------------------------------------------------------------- // Implementation for FreeMiNT on Atari #define _GNU_SOURCE /* for program_invocation_name */ #include @@ -393,7 +368,6 @@ const char* DynamicLoader::LastError() namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname) { @@ -404,7 +378,6 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( return (void*)name; } -//---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { dld_unlink_by_file((char*)lib, 0); @@ -412,7 +385,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) return 0; } -//---------------------------------------------------------------------------- DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( DynamicLoader::LibraryHandle lib, const std::string& sym) { @@ -426,7 +398,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( return result.psym; } -//---------------------------------------------------------------------------- const char* DynamicLoader::LastError() { return dld_strerror(dld_errno); @@ -435,21 +406,18 @@ const char* DynamicLoader::LastError() } // namespace KWSYS_NAMESPACE #else -//---------------------------------------------------------------------------- // Default implementation for *NIX systems (including Mac OS X 10.3 and // later) which use dlopen #include namespace KWSYS_NAMESPACE { -//---------------------------------------------------------------------------- DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary( const std::string& libname) { return dlopen(libname.c_str(), RTLD_LAZY); } -//---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { if (lib) { @@ -460,7 +428,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) return 0; } -//---------------------------------------------------------------------------- DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( DynamicLoader::LibraryHandle lib, const std::string& sym) { @@ -474,7 +441,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress( return result.psym; } -//---------------------------------------------------------------------------- const char* DynamicLoader::LastError() { return dlerror(); diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in index 6639efdc4..09691fd3f 100644 --- a/Source/kwsys/Encoding.hxx.in +++ b/Source/kwsys/Encoding.hxx.in @@ -13,7 +13,7 @@ class @KWSYS_NAMESPACE@_EXPORT Encoding { public: // Container class for argc/argv. - class CommandLineArguments + class @KWSYS_NAMESPACE@_EXPORT CommandLineArguments { public: // On Windows, get the program command line arguments @@ -59,6 +59,17 @@ public: static std::string ToNarrow(const std::wstring& str); static std::string ToNarrow(const wchar_t* str); +#if defined(_WIN32) + /** + * Convert the path to an extended length path to avoid MAX_PATH length + * limitations on Windows. If the input is a local path the result will be + * prefixed with \\?\; if the input is instead a network path, the result + * will be prefixed with \\?\UNC\. All output will also be converted to + * absolute paths with Windows-style backslashes. + **/ + static std::wstring ToWindowsExtendedPath(std::string const&); +#endif + #endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING }; // class Encoding diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx index e904c1af1..b1e54c958 100644 --- a/Source/kwsys/EncodingCXX.cxx +++ b/Source/kwsys/EncodingCXX.cxx @@ -29,6 +29,7 @@ #if defined(_WIN32) #include +#include #include #endif @@ -146,11 +147,11 @@ std::wstring Encoding::ToWide(const std::string& str) wstr += ToWide(str.c_str() + pos); } nullPos = str.find('\0', pos); - if (nullPos != str.npos) { + if (nullPos != std::string::npos) { pos = nullPos + 1; wstr += wchar_t('\0'); } - } while (nullPos != str.npos); + } while (nullPos != std::string::npos); #endif return wstr; } @@ -180,11 +181,11 @@ std::string Encoding::ToNarrow(const std::wstring& str) nstr += ToNarrow(str.c_str() + pos); } nullPos = str.find(wchar_t('\0'), pos); - if (nullPos != str.npos) { + if (nullPos != std::string::npos) { pos = nullPos + 1; nstr += '\0'; } - } while (nullPos != str.npos); + } while (nullPos != std::string::npos); #endif return nstr; } @@ -214,6 +215,63 @@ std::string Encoding::ToNarrow(const wchar_t* wcstr) } return str; } + +#if defined(_WIN32) +// Convert local paths to UNC style paths +std::wstring Encoding::ToWindowsExtendedPath(std::string const& source) +{ + std::wstring wsource = Encoding::ToWide(source); + + // Resolve any relative paths + DWORD wfull_len; + + /* The +3 is a workaround for a bug in some versions of GetFullPathNameW that + * won't return a large enough buffer size if the input is too small */ + wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3; + std::vector wfull(wfull_len); + GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL); + + /* This should get the correct size without any extra padding from the + * previous size workaround. */ + wfull_len = static_cast(wcslen(&wfull[0])); + + if (wfull_len >= 2 && isalpha(wfull[0]) && + wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */ + return L"\\\\?\\" + std::wstring(&wfull[0]); + } else if (wfull_len >= 2 && wfull[0] == L'\\' && + wfull[1] == L'\\') { /* Starts with \\ */ + if (wfull_len >= 4 && wfull[2] == L'?' && + wfull[3] == L'\\') { /* Starts with \\?\ */ + if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' && + wfull[6] == L'C' && + wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */ + return std::wstring(&wfull[0]); + } else if (wfull_len >= 6 && isalpha(wfull[4]) && + wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */ + return std::wstring(&wfull[0]); + } else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */ + return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]); + } + } else if (wfull_len >= 4 && wfull[2] == L'.' && + wfull[3] == L'\\') { /* Starts with \\.\ a device name */ + if (wfull_len >= 6 && isalpha(wfull[4]) && + wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */ + return L"\\\\?\\" + std::wstring(&wfull[4]); + } else if (wfull_len >= + 5) { /* \\.\Foo\bar\ Device name is left unchanged */ + return std::wstring(&wfull[0]); + } + } else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */ + return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]); + } + } + + // If this case has been reached, then the path is invalid. Leave it + // unchanged + return Encoding::ToWide(source); +} +#endif + #endif // KWSYS_STL_HAS_WSTRING } // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in index 736214f6c..a4c65fe30 100644 --- a/Source/kwsys/FStream.hxx.in +++ b/Source/kwsys/FStream.hxx.in @@ -33,7 +33,7 @@ public: typedef std::basic_filebuf my_base_type; basic_filebuf* open(char const* s, std::ios_base::openmode mode) { - const std::wstring wstr = Encoding::ToWide(s); + const std::wstring wstr = Encoding::ToWindowsExtendedPath(s); return static_cast(my_base_type::open(wstr.c_str(), mode)); } #endif @@ -93,7 +93,7 @@ public: #if defined(_MSC_VER) const bool success = buf_->open(file_name, mode) != 0; #else - const std::wstring wstr = Encoding::ToWide(file_name); + const std::wstring wstr = Encoding::ToWindowsExtendedPath(file_name); bool success = false; std::wstring cmode = getcmode(mode); file_ = _wfopen(wstr.c_str(), cmode.c_str()); @@ -170,8 +170,6 @@ template > class basic_ifstream : public std::basic_istream, public basic_efilebuf { - using basic_efilebuf::is_open; - public: typedef typename basic_efilebuf::internal_buffer_type internal_buffer_type; @@ -201,6 +199,8 @@ public: void close() { this->_set_state(this->_close(), this, this); } + using basic_efilebuf::is_open; + internal_buffer_type* rdbuf() const { return this->buf_; } ~basic_ifstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { close(); } @@ -269,7 +269,7 @@ enum BOM // If a BOM exists, the stream is advanced to after the BOM. // This function requires a seekable stream (but not a relative // seekable stream). -BOM ReadBOM(std::istream& in); +@KWSYS_NAMESPACE@_EXPORT BOM ReadBOM(std::istream& in); } } diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx index fa8760d66..d2f0b8516 100644 --- a/Source/kwsys/Glob.cxx +++ b/Source/kwsys/Glob.cxx @@ -37,7 +37,6 @@ namespace KWSYS_NAMESPACE { #define KWSYS_GLOB_SUPPORT_NETWORK_PATHS #endif -//---------------------------------------------------------------------------- class GlobInternals { public: @@ -45,7 +44,6 @@ public: std::vector Expressions; }; -//---------------------------------------------------------------------------- Glob::Glob() { this->Internals = new GlobInternals; @@ -62,19 +60,16 @@ Glob::Glob() this->RecurseListDirs = false; } -//---------------------------------------------------------------------------- Glob::~Glob() { delete this->Internals; } -//---------------------------------------------------------------------------- std::vector& Glob::GetFiles() { return this->Internals->Files; } -//---------------------------------------------------------------------------- std::string Glob::PatternToRegex(const std::string& pattern, bool require_whole_string, bool preserve_case) { @@ -183,7 +178,6 @@ std::string Glob::PatternToRegex(const std::string& pattern, return regex; } -//---------------------------------------------------------------------------- bool Glob::RecurseDirectory(std::string::size_type start, const std::string& dir, GlobMessages* messages) { @@ -277,7 +271,6 @@ bool Glob::RecurseDirectory(std::string::size_type start, return true; } -//---------------------------------------------------------------------------- void Glob::ProcessDirectory(std::string::size_type start, const std::string& dir, GlobMessages* messages) { @@ -337,7 +330,6 @@ void Glob::ProcessDirectory(std::string::size_type start, } } -//---------------------------------------------------------------------------- bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages) { std::string cexpr; @@ -420,14 +412,12 @@ bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages) return true; } -//---------------------------------------------------------------------------- void Glob::AddExpression(const std::string& expr) { this->Internals->Expressions.push_back( kwsys::RegularExpression(this->PatternToRegex(expr))); } -//---------------------------------------------------------------------------- void Glob::SetRelative(const char* dir) { if (!dir) { @@ -437,7 +427,6 @@ void Glob::SetRelative(const char* dir) this->Relative = dir; } -//---------------------------------------------------------------------------- const char* Glob::GetRelative() { if (this->Relative.empty()) { @@ -446,7 +435,6 @@ const char* Glob::GetRelative() return this->Relative.c_str(); } -//---------------------------------------------------------------------------- void Glob::AddFile(std::vector& files, const std::string& file) { if (!this->Relative.empty()) { diff --git a/Source/kwsys/MD5.c b/Source/kwsys/MD5.c index 1310c6474..3188fb67a 100644 --- a/Source/kwsys/MD5.c +++ b/Source/kwsys/MD5.c @@ -13,8 +13,6 @@ #include /* malloc, free */ #include /* memcpy, strlen */ -/*--------------------------------------------------------------------------*/ - /* This MD5 implementation has been taken from a third party. Slight modifications to the arrangement of the code have been made to put it in a single source file instead of a separate header and @@ -425,14 +423,12 @@ static void md5_finish(md5_state_t* pms, md5_byte_t digest[16]) #pragma clang diagnostic pop #endif -/*--------------------------------------------------------------------------*/ /* Wrap up the MD5 state in our opaque structure. */ struct kwsysMD5_s { md5_state_t md5_state; }; -/*--------------------------------------------------------------------------*/ kwsysMD5* kwsysMD5_New(void) { /* Allocate a process control structure. */ @@ -443,7 +439,6 @@ kwsysMD5* kwsysMD5_New(void) return md5; } -/*--------------------------------------------------------------------------*/ void kwsysMD5_Delete(kwsysMD5* md5) { /* Make sure we have an instance. */ @@ -455,13 +450,11 @@ void kwsysMD5_Delete(kwsysMD5* md5) free(md5); } -/*--------------------------------------------------------------------------*/ void kwsysMD5_Initialize(kwsysMD5* md5) { md5_init(&md5->md5_state); } -/*--------------------------------------------------------------------------*/ void kwsysMD5_Append(kwsysMD5* md5, unsigned char const* data, int length) { size_t dlen; @@ -473,13 +466,11 @@ void kwsysMD5_Append(kwsysMD5* md5, unsigned char const* data, int length) md5_append(&md5->md5_state, (md5_byte_t const*)data, dlen); } -/*--------------------------------------------------------------------------*/ void kwsysMD5_Finalize(kwsysMD5* md5, unsigned char digest[16]) { md5_finish(&md5->md5_state, (md5_byte_t*)digest); } -/*--------------------------------------------------------------------------*/ void kwsysMD5_FinalizeHex(kwsysMD5* md5, char buffer[32]) { unsigned char digest[16]; @@ -487,7 +478,6 @@ void kwsysMD5_FinalizeHex(kwsysMD5* md5, char buffer[32]) kwsysMD5_DigestToHex(digest, buffer); } -/*--------------------------------------------------------------------------*/ void kwsysMD5_DigestToHex(unsigned char const digest[16], char buffer[32]) { /* Map from 4-bit index to hexadecimal representation. */ diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index b8349a66a..237001c60 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -42,7 +42,6 @@ #define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired) #define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed) #define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned) -#define kwsysProcess_GetState kwsys_ns(Process_GetState) #define kwsysProcess_State_e kwsys_ns(Process_State_e) #define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None) #define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault) @@ -50,12 +49,21 @@ #define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt) #define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical) #define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other) -#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException) #define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e) +#define kwsysProcess_GetState kwsys_ns(Process_GetState) +#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException) #define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode) #define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue) #define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString) #define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString) +#define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex) +#define kwsysProcess_GetExitExceptionByIndex \ + kwsys_ns(Process_GetExitExceptionByIndex) +#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex) +#define kwsysProcess_GetExitValueByIndex kwsys_ns(Process_GetExitValueByIndex) +#define kwsysProcess_GetExceptionStringByIndex \ + kwsys_ns(Process_GetExceptionStringByIndex) +#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex) #define kwsysProcess_Execute kwsys_ns(Process_Execute) #define kwsysProcess_Disown kwsys_ns(Process_Disown) #define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData) @@ -297,6 +305,67 @@ kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp); */ kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp); +/** +* Get the current state of the Process instance. Possible states are: +* +* kwsysProcess_StateByIndex_Starting = Execute has not yet been called. +* kwsysProcess_StateByIndex_Exception = Child process exited abnormally. +* kwsysProcess_StateByIndex_Exited = Child process exited normally. +* kwsysProcess_StateByIndex_Error = Error getting the child return code. +*/ +kwsysEXPORT int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx); +enum kwsysProcess_StateByIndex_e +{ + kwsysProcess_StateByIndex_Starting = kwsysProcess_State_Starting, + kwsysProcess_StateByIndex_Exception = kwsysProcess_State_Exception, + kwsysProcess_StateByIndex_Exited = kwsysProcess_State_Exited, + kwsysProcess_StateByIndex_Error = kwsysProcess_State_Error +}; + +/** +* When GetState returns "Exception", this method returns a +* platform-independent description of the exceptional behavior that +* caused the child to terminate abnormally. Possible exceptions are: +* +* kwsysProcess_Exception_None = No exceptional behavior occurred. +* kwsysProcess_Exception_Fault = Child crashed with a memory fault. +* kwsysProcess_Exception_Illegal = Child crashed with an illegal +* instruction. +* kwsysProcess_Exception_Interrupt = Child was interrupted by user +* (Cntl-C/Break). +* kwsysProcess_Exception_Numerical = Child crashed with a numerical +* exception. +* kwsysProcess_Exception_Other = Child terminated for another reason. +*/ +kwsysEXPORT int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, + int idx); + +/** +* When GetState returns "Exited" or "Exception", this method returns +* the platform-specific raw exit code of the process. UNIX platforms +* should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access +* this value. Windows users should compare the value to the various +* EXCEPTION_* values. +* +* If GetState returns "Exited", use GetExitValue to get the +* platform-independent child return value. +*/ +kwsysEXPORT int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx); + +/** +* When GetState returns "Exited", this method returns the child's +* platform-independent exit code (such as the value returned by the +* child's main). +*/ +kwsysEXPORT int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx); + +/** +* When GetState returns "Exception", this method returns a string +* describing the problem. Otherwise, it returns NULL. +*/ +kwsysEXPORT const char* kwsysProcess_GetExceptionStringByIndex( + kwsysProcess* cp, int idx); + /** * Start executing the child process. */ diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index ed0909543..9ebcfce59 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -140,7 +140,6 @@ typedef struct kwsysProcessCreateInformation_s int ErrorPipe[2]; } kwsysProcessCreateInformation; -/*--------------------------------------------------------------------------*/ static void kwsysProcessVolatileFree(volatile void* p); static int kwsysProcessInitialize(kwsysProcess* cp); static void kwsysProcessCleanup(kwsysProcess* cp, int error); @@ -166,7 +165,8 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2); -static void kwsysProcessSetExitException(kwsysProcess* cp, int sig); +static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig, + int idx); static void kwsysProcessChildErrorExit(int errorPipe); static void kwsysProcessRestoreDefaultSignalHandlers(void); static pid_t kwsysProcessFork(kwsysProcess* cp, @@ -184,7 +184,26 @@ static void kwsysProcessesSignalHandler(int signum, siginfo_t* info, static void kwsysProcessesSignalHandler(int signum); #endif -/*--------------------------------------------------------------------------*/ +/* A structure containing results data for each process. */ +typedef struct kwsysProcessResults_s kwsysProcessResults; +struct kwsysProcessResults_s +{ + /* The status of the child process. */ + int State; + + /* The exceptional behavior that terminated the process, if any. */ + int ExitException; + + /* The process exit code. */ + int ExitCode; + + /* The process return code, if any. */ + int ExitValue; + + /* Description for the ExitException. */ + char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1]; +}; + /* Structure containing data used to implement the child's execution. */ struct kwsysProcess_s { @@ -255,28 +274,18 @@ struct kwsysProcess_s /* The number of children still executing. */ int CommandsLeft; - /* The current status of the child process. Must be atomic because + /* The status of the process structure. Must be atomic because the signal handler checks this to avoid a race. */ volatile sig_atomic_t State; - /* The exceptional behavior that terminated the child process, if - * any. */ - int ExitException; - - /* The exit code of the child process. */ - int ExitCode; - - /* The exit value of the child process, if any. */ - int ExitValue; - /* Whether the process was killed. */ volatile sig_atomic_t Killed; /* Buffer for error message in case of failure. */ char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1]; - /* Description for the ExitException. */ - char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1]; + /* process results. */ + kwsysProcessResults* ProcessResults; /* The exit codes of each child process in the pipeline. */ int* CommandExitCodes; @@ -301,7 +310,6 @@ struct kwsysProcess_s char* RealWorkingDirectory; }; -/*--------------------------------------------------------------------------*/ kwsysProcess* kwsysProcess_New(void) { /* Allocate a process control structure. */ @@ -328,7 +336,6 @@ kwsysProcess* kwsysProcess_New(void) return cp; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_Delete(kwsysProcess* cp) { /* Make sure we have an instance. */ @@ -354,10 +361,10 @@ void kwsysProcess_Delete(kwsysProcess* cp) if (cp->CommandExitCodes) { free(cp->CommandExitCodes); } + free(cp->ProcessResults); free(cp); } -/*--------------------------------------------------------------------------*/ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) { int i; @@ -382,7 +389,6 @@ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) return 1; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) { int newNumberOfCommands; @@ -462,7 +468,6 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) return 1; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) { if (!cp) { @@ -476,7 +481,6 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) cp->TimeoutTime.tv_sec = -1; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) { if (!cp) { @@ -502,7 +506,6 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) return 1; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file) { char** pfile; @@ -543,7 +546,6 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file) return 1; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared) { if (!cp) { @@ -572,7 +574,6 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared) } } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2]) { int* pPipeNative = 0; @@ -612,7 +613,6 @@ void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2]) } } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) { if (!cp) { @@ -633,7 +633,6 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) } } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) { if (!cp) { @@ -658,31 +657,32 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) } } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetState(kwsysProcess* cp) { return cp ? cp->State : kwsysProcess_State_Error; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetExitException(kwsysProcess* cp) { - return cp ? cp->ExitException : kwsysProcess_Exception_Other; + return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) + ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException + : kwsysProcess_Exception_Other; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetExitCode(kwsysProcess* cp) { - return cp ? cp->ExitCode : 0; + return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) + ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode + : 0; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetExitValue(kwsysProcess* cp) { - return cp ? cp->ExitValue : -1; + return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) + ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue + : -1; } -/*--------------------------------------------------------------------------*/ const char* kwsysProcess_GetErrorString(kwsysProcess* cp) { if (!cp) { @@ -693,18 +693,58 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp) return "Success"; } -/*--------------------------------------------------------------------------*/ const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) { - if (!cp) { + if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) { return "GetExceptionString called with NULL process management structure"; } else if (cp->State == kwsysProcess_State_Exception) { - return cp->ExitExceptionString; + return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString; + } + return "No exception"; +} + +/* the index should be in array bound. */ +#define KWSYSPE_IDX_CHK(RET) \ + if (!cp || idx >= cp->NumberOfCommands || idx < 0) { \ + return RET; \ + } + +int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_State_Error) + return cp->ProcessResults[idx].State; +} + +int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other) + return cp->ProcessResults[idx].ExitException; +} + +int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->ProcessResults[idx].ExitValue; +} + +int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->CommandExitCodes[idx]; +} + +const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management " + "structure or index out of bound") + if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) { + return cp->ProcessResults[idx].ExitExceptionString; } return "No exception"; } -/*--------------------------------------------------------------------------*/ +#undef KWSYSPE_IDX_CHK + void kwsysProcess_Execute(kwsysProcess* cp) { int i; @@ -990,7 +1030,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) cp->Detached = cp->OptionDetach; } -/*--------------------------------------------------------------------------*/ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp) { /* Make sure a detached child process is running. */ @@ -1009,7 +1048,6 @@ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp) cp->State = kwsysProcess_State_Disowned; } -/*--------------------------------------------------------------------------*/ typedef struct kwsysProcessWaitData_s { int Expired; @@ -1021,7 +1059,6 @@ typedef struct kwsysProcessWaitData_s static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, kwsysProcessWaitData* wd); -/*--------------------------------------------------------------------------*/ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, double* userTimeout) { @@ -1083,7 +1120,6 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, } } -/*--------------------------------------------------------------------------*/ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, kwsysProcessWaitData* wd) { @@ -1285,10 +1321,8 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, #endif } -/*--------------------------------------------------------------------------*/ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) { - int status = 0; int prPipe = 0; /* Make sure we are executing a process. */ @@ -1319,10 +1353,6 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) cp->State = kwsysProcess_State_Error; return 1; } - - /* Use the status of the last process in the pipeline. */ - status = cp->CommandExitCodes[cp->NumberOfCommands - 1]; - /* Determine the outcome. */ if (cp->Killed) { /* We killed the child. */ @@ -1330,29 +1360,36 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) } else if (cp->TimeoutExpired) { /* The timeout expired. */ cp->State = kwsysProcess_State_Expired; - } else if (WIFEXITED(status)) { - /* The child exited normally. */ - cp->State = kwsysProcess_State_Exited; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitCode = status; - cp->ExitValue = (int)WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - /* The child received an unhandled signal. */ - cp->State = kwsysProcess_State_Exception; - cp->ExitCode = status; - kwsysProcessSetExitException(cp, (int)WTERMSIG(status)); } else { - /* Error getting the child return code. */ - strcpy(cp->ErrorMessage, "Error getting child return code."); - cp->State = kwsysProcess_State_Error; + /* The children exited. Report the outcome of the child processes. */ + for (prPipe = 0; prPipe < cp->NumberOfCommands; ++prPipe) { + cp->ProcessResults[prPipe].ExitCode = cp->CommandExitCodes[prPipe]; + if (WIFEXITED(cp->ProcessResults[prPipe].ExitCode)) { + /* The child exited normally. */ + cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Exited; + cp->ProcessResults[prPipe].ExitException = kwsysProcess_Exception_None; + cp->ProcessResults[prPipe].ExitValue = + (int)WEXITSTATUS(cp->ProcessResults[prPipe].ExitCode); + } else if (WIFSIGNALED(cp->ProcessResults[prPipe].ExitCode)) { + /* The child received an unhandled signal. */ + cp->ProcessResults[prPipe].State = kwsysProcess_State_Exception; + kwsysProcessSetExitExceptionByIndex( + cp, (int)WTERMSIG(cp->ProcessResults[prPipe].ExitCode), prPipe); + } else { + /* Error getting the child return code. */ + strcpy(cp->ProcessResults[prPipe].ExitExceptionString, + "Error getting child return code."); + cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Error; + } + } + /* support legacy state status value */ + cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State; } - /* Normal cleanup. */ kwsysProcessCleanup(cp, 0); return 1; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_Interrupt(kwsysProcess* cp) { int i; @@ -1384,7 +1421,6 @@ void kwsysProcess_Interrupt(kwsysProcess* cp) } } -/*--------------------------------------------------------------------------*/ void kwsysProcess_Kill(kwsysProcess* cp) { int i; @@ -1431,7 +1467,6 @@ void kwsysProcess_Kill(kwsysProcess* cp) cp->CommandsLeft = 0; } -/*--------------------------------------------------------------------------*/ /* Call the free() function with a pointer to volatile without causing compiler warnings. */ static void kwsysProcessVolatileFree(volatile void* p) @@ -1448,7 +1483,6 @@ static void kwsysProcessVolatileFree(volatile void* p) #endif } -/*--------------------------------------------------------------------------*/ /* Initialize a process control structure for kwsysProcess_Execute. */ static int kwsysProcessInitialize(kwsysProcess* cp) { @@ -1474,11 +1508,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp) #endif cp->State = kwsysProcess_State_Starting; cp->Killed = 0; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitCode = 1; - cp->ExitValue = 1; cp->ErrorMessage[0] = 0; - strcpy(cp->ExitExceptionString, "No exception"); oldForkPIDs = cp->ForkPIDs; cp->ForkPIDs = (volatile pid_t*)malloc(sizeof(volatile pid_t) * @@ -1504,6 +1534,23 @@ static int kwsysProcessInitialize(kwsysProcess* cp) memset(cp->CommandExitCodes, 0, sizeof(int) * (size_t)(cp->NumberOfCommands)); + /* Allocate process result information for each process. */ + free(cp->ProcessResults); + cp->ProcessResults = (kwsysProcessResults*)malloc( + sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands)); + if (!cp->ProcessResults) { + return 0; + } + memset(cp->ProcessResults, 0, + sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands)); + for (i = 0; i < cp->NumberOfCommands; i++) { + cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None; + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting; + cp->ProcessResults[i].ExitCode = 1; + cp->ProcessResults[i].ExitValue = 1; + strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception"); + } + /* Allocate memory to save the real working directory. */ if (cp->WorkingDirectory) { #if defined(MAXPATHLEN) @@ -1523,7 +1570,6 @@ static int kwsysProcessInitialize(kwsysProcess* cp) return 1; } -/*--------------------------------------------------------------------------*/ /* Free all resources used by the given kwsysProcess instance that were allocated by kwsysProcess_Execute. */ static void kwsysProcessCleanup(kwsysProcess* cp, int error) @@ -1590,7 +1636,6 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error) } } -/*--------------------------------------------------------------------------*/ /* Close the given file descriptor if it is open. Reset its value to -1. */ static void kwsysProcessCleanupDescriptor(int* pfd) { @@ -1603,7 +1648,6 @@ static void kwsysProcessCleanupDescriptor(int* pfd) } } -/*--------------------------------------------------------------------------*/ static void kwsysProcessClosePipes(kwsysProcess* cp) { int i; @@ -1636,7 +1680,6 @@ static void kwsysProcessClosePipes(kwsysProcess* cp) } } -/*--------------------------------------------------------------------------*/ static int kwsysProcessSetNonBlocking(int fd) { int flags = fcntl(fd, F_GETFL); @@ -1646,12 +1689,10 @@ static int kwsysProcessSetNonBlocking(int fd) return flags >= 0; } -/*--------------------------------------------------------------------------*/ #if defined(__VMS) int decc$set_child_standard_streams(int fd1, int fd2, int fd3); #endif -/*--------------------------------------------------------------------------*/ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, kwsysProcessCreateInformation* si) { @@ -1831,7 +1872,6 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, return 1; } -/*--------------------------------------------------------------------------*/ static void kwsysProcessDestroy(kwsysProcess* cp) { /* A child process has terminated. Reap it if it is one handled by @@ -1880,7 +1920,6 @@ static void kwsysProcessDestroy(kwsysProcess* cp) sigprocmask(SIG_SETMASK, &old_mask, 0); } -/*--------------------------------------------------------------------------*/ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name) { int fout; @@ -1906,7 +1945,6 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name) return 1; } -/*--------------------------------------------------------------------------*/ static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]) { /* Close the existing descriptor. */ @@ -1925,7 +1963,6 @@ static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]) return 1; } -/*--------------------------------------------------------------------------*/ /* Get the time at which either the process or user timeout will expire. Returns 1 if the user timeout is first, and 0 otherwise. */ static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, @@ -1957,7 +1994,6 @@ static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, return 0; } -/*--------------------------------------------------------------------------*/ /* Get the length of time before the given timeout time arrives. Returns 1 if the time has already arrived, and 0 otherwise. */ static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, @@ -1992,7 +2028,6 @@ static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, } } -/*--------------------------------------------------------------------------*/ static kwsysProcessTime kwsysProcessTimeGetCurrent(void) { kwsysProcessTime current; @@ -2003,13 +2038,11 @@ static kwsysProcessTime kwsysProcessTimeGetCurrent(void) return current; } -/*--------------------------------------------------------------------------*/ static double kwsysProcessTimeToDouble(kwsysProcessTime t) { return (double)t.tv_sec + (double)(t.tv_usec) * 0.000001; } -/*--------------------------------------------------------------------------*/ static kwsysProcessTime kwsysProcessTimeFromDouble(double d) { kwsysProcessTime t; @@ -2018,14 +2051,12 @@ static kwsysProcessTime kwsysProcessTimeFromDouble(double d) return t; } -/*--------------------------------------------------------------------------*/ static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2) { return ((in1.tv_sec < in2.tv_sec) || ((in1.tv_sec == in2.tv_sec) && (in1.tv_usec < in2.tv_usec))); } -/*--------------------------------------------------------------------------*/ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2) { @@ -2039,7 +2070,6 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, return out; } -/*--------------------------------------------------------------------------*/ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2) { @@ -2053,11 +2083,11 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, return out; } -/*--------------------------------------------------------------------------*/ #define KWSYSPE_CASE(type, str) \ - cp->ExitException = kwsysProcess_Exception_##type; \ - strcpy(cp->ExitExceptionString, str) -static void kwsysProcessSetExitException(kwsysProcess* cp, int sig) + cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type; \ + strcpy(cp->ProcessResults[idx].ExitExceptionString, str) +static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig, + int idx) { switch (sig) { #ifdef SIGSEGV @@ -2243,14 +2273,13 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int sig) #endif #endif default: - cp->ExitException = kwsysProcess_Exception_Other; - sprintf(cp->ExitExceptionString, "Signal %d", sig); + cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other; + sprintf(cp->ProcessResults[idx].ExitExceptionString, "Signal %d", sig); break; } } #undef KWSYSPE_CASE -/*--------------------------------------------------------------------------*/ /* When the child process encounters an error before its program is invoked, this is called to report the error to the parent and exit. */ @@ -2269,7 +2298,6 @@ static void kwsysProcessChildErrorExit(int errorPipe) _exit(1); } -/*--------------------------------------------------------------------------*/ /* Restores all signal handlers to their default values. */ static void kwsysProcessRestoreDefaultSignalHandlers(void) { @@ -2377,13 +2405,11 @@ static void kwsysProcessRestoreDefaultSignalHandlers(void) #endif } -/*--------------------------------------------------------------------------*/ static void kwsysProcessExit(void) { _exit(0); } -/*--------------------------------------------------------------------------*/ #if !defined(__VMS) static pid_t kwsysProcessFork(kwsysProcess* cp, kwsysProcessCreateInformation* si) @@ -2433,7 +2459,6 @@ static pid_t kwsysProcessFork(kwsysProcess* cp, } #endif -/*--------------------------------------------------------------------------*/ /* We try to obtain process information by invoking the ps command. Here we define the command to call on each platform and the corresponding parsing format string. The parsing format should @@ -2457,7 +2482,6 @@ static pid_t kwsysProcessFork(kwsysProcess* cp, #define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n" #endif -/*--------------------------------------------------------------------------*/ static void kwsysProcessKill(pid_t process_id) { #if defined(__linux__) || defined(__CYGWIN__) @@ -2561,7 +2585,6 @@ static void kwsysProcessKill(pid_t process_id) #endif } -/*--------------------------------------------------------------------------*/ #if defined(__VMS) int decc$feature_get_index(const char* name); int decc$feature_set_value(int index, int mode, int value); @@ -2574,7 +2597,6 @@ static int kwsysProcessSetVMSFeature(const char* name, int value) } #endif -/*--------------------------------------------------------------------------*/ /* Global set of executing processes for use by the signal handler. This global instance will be zero-initialized by the compiler. */ typedef struct kwsysProcessInstances_s @@ -2590,7 +2612,6 @@ static struct sigaction kwsysProcessesOldSigChldAction; static struct sigaction kwsysProcessesOldSigIntAction; static struct sigaction kwsysProcessesOldSigTermAction; -/*--------------------------------------------------------------------------*/ static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses) { /* Block signals while we update the set of pipes to check. @@ -2611,7 +2632,6 @@ static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses) sigprocmask(SIG_SETMASK, &oldset, 0); } -/*--------------------------------------------------------------------------*/ static int kwsysProcessesAdd(kwsysProcess* cp) { /* Create a pipe through which the signal handler can notify the @@ -2721,7 +2741,6 @@ static int kwsysProcessesAdd(kwsysProcess* cp) return 1; } -/*--------------------------------------------------------------------------*/ static void kwsysProcessesRemove(kwsysProcess* cp) { /* Attempt to remove the given signal pipe from the signal handler set. */ @@ -2772,7 +2791,6 @@ static void kwsysProcessesRemove(kwsysProcess* cp) kwsysProcessCleanupDescriptor(&cp->SignalPipe); } -/*--------------------------------------------------------------------------*/ static void kwsysProcessesSignalHandler(int signum #if KWSYSPE_USE_SIGINFO , @@ -2884,7 +2902,6 @@ static void kwsysProcessesSignalHandler(int signum errno = old_errno; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_ResetStartTime(kwsysProcess* cp) { if (!cp) { diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index d10c7339a..5183e3d2c 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -86,7 +86,6 @@ typedef struct kwsysProcessCreateInformation_s HANDLE hStdError; } kwsysProcessCreateInformation; -/*--------------------------------------------------------------------------*/ typedef struct kwsysProcessPipeData_s kwsysProcessPipeData; static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd); static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, @@ -119,6 +118,8 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2); static void kwsysProcessSetExitException(kwsysProcess* cp, int code); +static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code, + int idx); static void kwsysProcessKillTree(int pid); static void kwsysProcessDisablePipeThreads(kwsysProcess* cp); static int kwsysProcessesInitialize(void); @@ -129,7 +130,6 @@ static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId, static void kwsysProcessesRemove(HANDLE hProcess); static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType); -/*--------------------------------------------------------------------------*/ /* A structure containing synchronization data for each thread. */ typedef struct kwsysProcessPipeSync_s kwsysProcessPipeSync; struct kwsysProcessPipeSync_s @@ -147,7 +147,6 @@ struct kwsysProcessPipeSync_s HANDLE Reset; }; -/*--------------------------------------------------------------------------*/ /* A structure containing data for each pipe's threads. */ struct kwsysProcessPipeData_s { @@ -183,7 +182,26 @@ struct kwsysProcessPipeData_s HANDLE Write; }; -/*--------------------------------------------------------------------------*/ +/* A structure containing results data for each process. */ +typedef struct kwsysProcessResults_s kwsysProcessResults; +struct kwsysProcessResults_s +{ + /* The status of the process. */ + int State; + + /* The exceptional behavior that terminated the process, if any. */ + int ExitException; + + /* The process exit code. */ + DWORD ExitCode; + + /* The process return code, if any. */ + int ExitValue; + + /* Description for the ExitException. */ + char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1]; +}; + /* Structure containing data used to implement the child's execution. */ struct kwsysProcess_s { @@ -249,15 +267,6 @@ struct kwsysProcess_s /* ------------- Data managed per call to Execute ------------- */ - /* The exceptional behavior that terminated the process, if any. */ - int ExitException; - - /* The process exit code. */ - DWORD ExitCode; - - /* The process return code, if any. */ - int ExitValue; - /* Index of last pipe to report data, if any. */ int CurrentIndex; @@ -289,8 +298,8 @@ struct kwsysProcess_s /* Buffer for error messages. */ char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1]; - /* Description for the ExitException. */ - char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1]; + /* process results. */ + kwsysProcessResults* ProcessResults; /* Windows process information data. */ PROCESS_INFORMATION* ProcessInformation; @@ -308,7 +317,6 @@ struct kwsysProcess_s HANDLE PipeChildStd[3]; }; -/*--------------------------------------------------------------------------*/ kwsysProcess* kwsysProcess_New(void) { int i; @@ -447,7 +455,6 @@ kwsysProcess* kwsysProcess_New(void) return cp; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_Delete(kwsysProcess* cp) { int i; @@ -519,10 +526,10 @@ void kwsysProcess_Delete(kwsysProcess* cp) if (cp->CommandExitCodes) { free(cp->CommandExitCodes); } + free(cp->ProcessResults); free(cp); } -/*--------------------------------------------------------------------------*/ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) { int i; @@ -543,7 +550,6 @@ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) return 1; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) { int newNumberOfCommands; @@ -639,7 +645,6 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) return 1; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) { if (!cp) { @@ -653,7 +658,6 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) cp->TimeoutTime.QuadPart = -1; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) { if (!cp) { @@ -685,7 +689,6 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) return 1; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file) { char** pfile; @@ -727,7 +730,6 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file) return 1; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared) { if (!cp) { @@ -756,7 +758,6 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared) } } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2]) { HANDLE* pPipeNative = 0; @@ -796,7 +797,6 @@ void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2]) } } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) { if (!cp) { @@ -819,7 +819,6 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) } } -/*--------------------------------------------------------------------------*/ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) { if (!cp) { @@ -847,31 +846,32 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) } } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetState(kwsysProcess* cp) { return cp ? cp->State : kwsysProcess_State_Error; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetExitException(kwsysProcess* cp) { - return cp ? cp->ExitException : kwsysProcess_Exception_Other; + return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) + ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException + : kwsysProcess_Exception_Other; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetExitValue(kwsysProcess* cp) { - return cp ? cp->ExitValue : -1; + return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) + ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue + : -1; } -/*--------------------------------------------------------------------------*/ int kwsysProcess_GetExitCode(kwsysProcess* cp) { - return cp ? cp->ExitCode : 0; + return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) + ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode + : 0; } -/*--------------------------------------------------------------------------*/ const char* kwsysProcess_GetErrorString(kwsysProcess* cp) { if (!cp) { @@ -882,18 +882,59 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp) return "Success"; } -/*--------------------------------------------------------------------------*/ const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) { - if (!cp) { + if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) { return "GetExceptionString called with NULL process management structure"; } else if (cp->State == kwsysProcess_State_Exception) { - return cp->ExitExceptionString; + return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString; } return "No exception"; } -/*--------------------------------------------------------------------------*/ +/* the index should be in array bound. */ +#define KWSYSPE_IDX_CHK(RET) \ + if (!cp || idx >= cp->NumberOfCommands || idx < 0) { \ + KWSYSPE_DEBUG((stderr, "array index out of bound\n")); \ + return RET; \ + } + +int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_State_Error) + return cp->ProcessResults[idx].State; +} + +int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other) + return cp->ProcessResults[idx].ExitException; +} + +int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->ProcessResults[idx].ExitValue; +} + +int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->CommandExitCodes[idx]; +} + +const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management " + "structure or index out of bound") + if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) { + return cp->ProcessResults[idx].ExitExceptionString; + } + return "No exception"; +} + +#undef KWSYSPE_IDX_CHK + void kwsysProcess_Execute(kwsysProcess* cp) { int i; @@ -1135,7 +1176,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) cp->Detached = cp->OptionDetach; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_Disown(kwsysProcess* cp) { int i; @@ -1162,8 +1202,6 @@ void kwsysProcess_Disown(kwsysProcess* cp) cp->State = kwsysProcess_State_Disowned; } -/*--------------------------------------------------------------------------*/ - int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, double* userTimeout) { @@ -1289,7 +1327,6 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, } } -/*--------------------------------------------------------------------------*/ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) { int i; @@ -1338,25 +1375,29 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) /* The timeout expired. */ cp->State = kwsysProcess_State_Expired; } else { - /* The children exited. Report the outcome of the last process. */ - cp->ExitCode = cp->CommandExitCodes[cp->NumberOfCommands - 1]; - if ((cp->ExitCode & 0xF0000000) == 0xC0000000) { - /* Child terminated due to exceptional behavior. */ - cp->State = kwsysProcess_State_Exception; - cp->ExitValue = 1; - kwsysProcessSetExitException(cp, cp->ExitCode); - } else { - /* Child exited without exception. */ - cp->State = kwsysProcess_State_Exited; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitValue = cp->ExitCode; + /* The children exited. Report the outcome of the child processes. */ + for (i = 0; i < cp->NumberOfCommands; ++i) { + cp->ProcessResults[i].ExitCode = cp->CommandExitCodes[i]; + if ((cp->ProcessResults[i].ExitCode & 0xF0000000) == 0xC0000000) { + /* Child terminated due to exceptional behavior. */ + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exception; + cp->ProcessResults[i].ExitValue = 1; + kwsysProcessSetExitExceptionByIndex(cp, cp->ProcessResults[i].ExitCode, + i); + } else { + /* Child exited without exception. */ + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exited; + cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None; + cp->ProcessResults[i].ExitValue = cp->ProcessResults[i].ExitCode; + } } + /* support legacy state status value */ + cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State; } return 1; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_Interrupt(kwsysProcess* cp) { int i; @@ -1394,7 +1435,6 @@ void kwsysProcess_Interrupt(kwsysProcess* cp) } } -/*--------------------------------------------------------------------------*/ void kwsysProcess_Kill(kwsysProcess* cp) { int i; @@ -1429,8 +1469,6 @@ void kwsysProcess_Kill(kwsysProcess* cp) for them to exit. */ } -/*--------------------------------------------------------------------------*/ - /* Function executed for each pipe's thread. Argument is a pointer to the kwsysProcessPipeData instance for this thread. @@ -1451,8 +1489,6 @@ DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd) return 0; } -/*--------------------------------------------------------------------------*/ - /* Function called in each pipe's thread to handle data for one execution of a subprocess. @@ -1494,8 +1530,6 @@ void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td) ReleaseSemaphore(td->Reader.Go, 1, 0); } -/*--------------------------------------------------------------------------*/ - /* Function executed for each pipe's thread. Argument is a pointer to the kwsysProcessPipeData instance for this thread. @@ -1516,8 +1550,6 @@ DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd) return 0; } -/*--------------------------------------------------------------------------*/ - /* Function called in each pipe's thread to handle reading thread wakeup for one execution of a subprocess. @@ -1540,23 +1572,34 @@ void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td) } } -/*--------------------------------------------------------------------------*/ /* Initialize a process control structure for kwsysProcess_Execute. */ int kwsysProcessInitialize(kwsysProcess* cp) { + int i; /* Reset internal status flags. */ cp->TimeoutExpired = 0; cp->Terminated = 0; cp->Killed = 0; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitCode = 1; - cp->ExitValue = 1; - /* Reset error data. */ - cp->ErrorMessage[0] = 0; - strcpy(cp->ExitExceptionString, "No exception"); + free(cp->ProcessResults); + /* Allocate process result information for each process. */ + cp->ProcessResults = (kwsysProcessResults*)malloc( + sizeof(kwsysProcessResults) * (cp->NumberOfCommands)); + if (!cp->ProcessResults) { + return 0; + } + ZeroMemory(cp->ProcessResults, + sizeof(kwsysProcessResults) * cp->NumberOfCommands); + for (i = 0; i < cp->NumberOfCommands; i++) { + cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None; + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting; + cp->ProcessResults[i].ExitCode = 1; + cp->ProcessResults[i].ExitValue = 1; + strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception"); + } /* Allocate process information for each process. */ + free(cp->ProcessInformation); cp->ProcessInformation = (PROCESS_INFORMATION*)malloc( sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands); if (!cp->ProcessInformation) { @@ -1596,7 +1639,6 @@ int kwsysProcessInitialize(kwsysProcess* cp) } } { - int i; for (i = 0; i < 3; ++i) { cp->PipeChildStd[i] = INVALID_HANDLE_VALUE; } @@ -1605,7 +1647,6 @@ int kwsysProcessInitialize(kwsysProcess* cp) return 1; } -/*--------------------------------------------------------------------------*/ static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) { DWORD flags; @@ -1641,7 +1682,6 @@ static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) } } -/*--------------------------------------------------------------------------*/ DWORD kwsysProcessCreate(kwsysProcess* cp, int index, kwsysProcessCreateInformation* si) { @@ -1706,7 +1746,6 @@ DWORD kwsysProcessCreate(kwsysProcess* cp, int index, return error; } -/*--------------------------------------------------------------------------*/ void kwsysProcessDestroy(kwsysProcess* cp, int event) { int i; @@ -1756,7 +1795,6 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event) } } -/*--------------------------------------------------------------------------*/ DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) { HANDLE fout; @@ -1784,7 +1822,6 @@ DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) return ERROR_SUCCESS; } -/*--------------------------------------------------------------------------*/ void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) { /* Close the existing handle. */ @@ -1793,7 +1830,6 @@ void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) *handle = GetStdHandle(nStdHandle); } -/*--------------------------------------------------------------------------*/ void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle) { /* Close the existing handle. */ @@ -1802,8 +1838,6 @@ void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle) *handle = native; } -/*--------------------------------------------------------------------------*/ - /* Close the given handle if it is open. Reset its value to 0. */ void kwsysProcessCleanupHandle(PHANDLE h) { @@ -1816,8 +1850,6 @@ void kwsysProcessCleanupHandle(PHANDLE h) } } -/*--------------------------------------------------------------------------*/ - /* Close all handles created by kwsysProcess_Execute. */ void kwsysProcessCleanup(kwsysProcess* cp, DWORD error) { @@ -1902,7 +1934,6 @@ void kwsysProcessCleanup(kwsysProcess* cp, DWORD error) } } -/*--------------------------------------------------------------------------*/ void kwsysProcessCleanErrorMessage(kwsysProcess* cp) { /* Remove trailing period and newline, if any. */ @@ -1920,7 +1951,6 @@ void kwsysProcessCleanErrorMessage(kwsysProcess* cp) } } -/*--------------------------------------------------------------------------*/ /* Get the time at which either the process or user timeout will expire. Returns 1 if the user timeout is first, and 0 otherwise. */ int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, @@ -1952,7 +1982,6 @@ int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, return 0; } -/*--------------------------------------------------------------------------*/ /* Get the length of time before the given timeout time arrives. Returns 1 if the time has already arrived, and 0 otherwise. */ int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, @@ -1982,7 +2011,6 @@ int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, } } -/*--------------------------------------------------------------------------*/ kwsysProcessTime kwsysProcessTimeGetCurrent() { kwsysProcessTime current; @@ -1993,19 +2021,16 @@ kwsysProcessTime kwsysProcessTimeGetCurrent() return current; } -/*--------------------------------------------------------------------------*/ DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t) { return (DWORD)(t.QuadPart * 0.0001); } -/*--------------------------------------------------------------------------*/ double kwsysProcessTimeToDouble(kwsysProcessTime t) { return t.QuadPart * 0.0000001; } -/*--------------------------------------------------------------------------*/ kwsysProcessTime kwsysProcessTimeFromDouble(double d) { kwsysProcessTime t; @@ -2013,13 +2038,11 @@ kwsysProcessTime kwsysProcessTimeFromDouble(double d) return t; } -/*--------------------------------------------------------------------------*/ int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2) { return in1.QuadPart < in2.QuadPart; } -/*--------------------------------------------------------------------------*/ kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2) { @@ -2028,7 +2051,6 @@ kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, return out; } -/*--------------------------------------------------------------------------*/ kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2) { @@ -2037,11 +2059,11 @@ kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, return out; } -/*--------------------------------------------------------------------------*/ #define KWSYSPE_CASE(type, str) \ - cp->ExitException = kwsysProcess_Exception_##type; \ - strcpy(cp->ExitExceptionString, str) -static void kwsysProcessSetExitException(kwsysProcess* cp, int code) + cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type; \ + strcpy(cp->ProcessResults[idx].ExitExceptionString, str) +static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code, + int idx) { switch (code) { case STATUS_CONTROL_C_EXIT: @@ -2120,9 +2142,9 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int code) case STATUS_NO_MEMORY: default: - cp->ExitException = kwsysProcess_Exception_Other; - _snprintf(cp->ExitExceptionString, KWSYSPE_PIPE_BUFFER_SIZE, - "Exit code 0x%x\n", code); + cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other; + _snprintf(cp->ProcessResults[idx].ExitExceptionString, + KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code); break; } } @@ -2136,7 +2158,6 @@ static int kwsysProcess_List_NextProcess(kwsysProcess_List* self); static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self); static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self); -/*--------------------------------------------------------------------------*/ /* Windows NT 4 API definitions. */ #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) typedef LONG NTSTATUS; @@ -2168,7 +2189,6 @@ struct _SYSTEM_PROCESS_INFORMATION ULONG InheritedFromProcessId; }; -/*--------------------------------------------------------------------------*/ /* Toolhelp32 API definitions. */ #define TH32CS_SNAPPROCESS 0x00000002 #if defined(_WIN64) @@ -2192,7 +2212,6 @@ struct tagPROCESSENTRY32 char szExeFile[MAX_PATH]; }; -/*--------------------------------------------------------------------------*/ /* Windows API function types. */ typedef HANDLE(WINAPI* CreateToolhelp32SnapshotType)(DWORD, DWORD); typedef BOOL(WINAPI* Process32FirstType)(HANDLE, LPPROCESSENTRY32); @@ -2200,7 +2219,6 @@ typedef BOOL(WINAPI* Process32NextType)(HANDLE, LPPROCESSENTRY32); typedef NTSTATUS(WINAPI* ZwQuerySystemInformationType)(ULONG, PVOID, ULONG, PULONG); -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self); static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self); static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self); @@ -2233,7 +2251,6 @@ struct kwsysProcess_List_s PROCESSENTRY32 CurrentEntry; }; -/*--------------------------------------------------------------------------*/ static kwsysProcess_List* kwsysProcess_List_New(void) { OSVERSIONINFO osv; @@ -2279,7 +2296,6 @@ static kwsysProcess_List* kwsysProcess_List_New(void) return self; } -/*--------------------------------------------------------------------------*/ static void kwsysProcess_List_Delete(kwsysProcess_List* self) { if (self) { @@ -2292,7 +2308,6 @@ static void kwsysProcess_List_Delete(kwsysProcess_List* self) } } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List_Update(kwsysProcess_List* self) { return self ? (self->NT4 ? kwsysProcess_List__Update_NT4(self) @@ -2300,7 +2315,6 @@ static int kwsysProcess_List_Update(kwsysProcess_List* self) : 0; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self) { return self ? (self->NT4 ? kwsysProcess_List__GetProcessId_NT4(self) @@ -2308,7 +2322,6 @@ static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self) : -1; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self) { return self ? (self->NT4 ? kwsysProcess_List__GetParentId_NT4(self) @@ -2316,7 +2329,6 @@ static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self) : -1; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List_NextProcess(kwsysProcess_List* self) { return (self ? (self->NT4 ? kwsysProcess_List__Next_NT4(self) @@ -2324,7 +2336,6 @@ static int kwsysProcess_List_NextProcess(kwsysProcess_List* self) : 0); } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self) { /* Get a handle to the NT runtime module that should already be @@ -2348,7 +2359,6 @@ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self) return self->Buffer ? 1 : 0; } -/*--------------------------------------------------------------------------*/ static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self) { /* Free the process information buffer. */ @@ -2357,7 +2367,6 @@ static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self) } } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self) { self->CurrentInfo = 0; @@ -2387,7 +2396,6 @@ static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self) } } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self) { if (self->CurrentInfo) { @@ -2401,19 +2409,16 @@ static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self) return 0; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self) { return self->CurrentInfo ? self->CurrentInfo->ProcessId : -1; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self) { return self->CurrentInfo ? self->CurrentInfo->InheritedFromProcessId : -1; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self) { /* Get a handle to the Windows runtime module that should already be @@ -2436,7 +2441,6 @@ static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self) : 0; } -/*--------------------------------------------------------------------------*/ static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self) { if (self->Snapshot) { @@ -2444,7 +2448,6 @@ static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self) } } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self) { if (self->Snapshot) { @@ -2464,7 +2467,6 @@ static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self) return 1; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self) { if (self->Snapshot) { @@ -2477,19 +2479,16 @@ static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self) return 0; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self) { return self->Snapshot ? self->CurrentEntry.th32ProcessID : -1; } -/*--------------------------------------------------------------------------*/ static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self) { return self->Snapshot ? self->CurrentEntry.th32ParentProcessID : -1; } -/*--------------------------------------------------------------------------*/ static void kwsysProcessKill(DWORD pid) { HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid); @@ -2500,7 +2499,6 @@ static void kwsysProcessKill(DWORD pid) } } -/*--------------------------------------------------------------------------*/ static void kwsysProcessKillTree(int pid) { kwsysProcess_List* plist = kwsysProcess_List_New(); @@ -2516,7 +2514,6 @@ static void kwsysProcessKillTree(int pid) } } -/*--------------------------------------------------------------------------*/ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp) { int i; @@ -2568,7 +2565,6 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp) } } -/*--------------------------------------------------------------------------*/ /* Global set of executing processes for use by the Ctrl handler. This global instance will be zero-initialized by the compiler. @@ -2598,7 +2594,6 @@ typedef struct kwsysProcessInstances_s } kwsysProcessInstances; static kwsysProcessInstances kwsysProcesses; -/*--------------------------------------------------------------------------*/ /* Initialize critial section and set up console Ctrl handler. You MUST call this before using any other kwsysProcesses* functions below. */ static int kwsysProcessesInitialize(void) @@ -2617,7 +2612,6 @@ static int kwsysProcessesInitialize(void) return 1; } -/*--------------------------------------------------------------------------*/ /* The Ctrl handler waits on the global list of processes. To prevent an orphaned process, do not create a new process if the Ctrl handler is already running. Do so by using this function to check if it is ok to @@ -2636,7 +2630,6 @@ static int kwsysTryEnterCreateProcessSection(void) } } -/*--------------------------------------------------------------------------*/ /* Matching function on successful kwsysTryEnterCreateProcessSection return. Make sure you called kwsysProcessesAdd if applicable before calling this.*/ static void kwsysLeaveCreateProcessSection(void) @@ -2644,7 +2637,6 @@ static void kwsysLeaveCreateProcessSection(void) LeaveCriticalSection(&kwsysProcesses.Lock); } -/*--------------------------------------------------------------------------*/ /* Add new process to global process list. The Ctrl handler will wait for the process to exit before it returns. Do not close the process handle until after calling kwsysProcessesRemove. The newProcessGroup parameter @@ -2702,7 +2694,6 @@ static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid, return 1; } -/*--------------------------------------------------------------------------*/ /* Removes process to global process list. */ static void kwsysProcessesRemove(HANDLE hProcess) { @@ -2738,7 +2729,6 @@ static void kwsysProcessesRemove(HANDLE hProcess) LeaveCriticalSection(&kwsysProcesses.Lock); } -/*--------------------------------------------------------------------------*/ static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType) { size_t i; @@ -2774,7 +2764,6 @@ static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType) return FALSE; } -/*--------------------------------------------------------------------------*/ void kwsysProcess_ResetStartTime(kwsysProcess* cp) { if (!cp) { diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in index c9ae13552..f638267ec 100644 --- a/Source/kwsys/SharedForward.h.in +++ b/Source/kwsys/SharedForward.h.in @@ -72,8 +72,6 @@ #pragma warn - 8019 #endif -/*--------------------------------------------------------------------------*/ - /* Full path to the directory in which this executable is built. Do not include a trailing slash. */ #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD) @@ -159,7 +157,6 @@ #undef KWSYS_SHARED_FORWARD_OPTION_LDD #endif -/*--------------------------------------------------------------------------*/ /* Include needed system headers. */ #include @@ -180,7 +177,6 @@ #include #endif -/*--------------------------------------------------------------------------*/ /* Configuration for this platform. */ /* The path separator for this platform. */ @@ -292,7 +288,6 @@ static const char kwsys_shared_forward_path_slash[2] = { #endif #ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV -/*--------------------------------------------------------------------------*/ typedef struct kwsys_sf_arg_info_s { const char* arg; @@ -300,7 +295,6 @@ typedef struct kwsys_sf_arg_info_s int quote; } kwsys_sf_arg_info; -/*--------------------------------------------------------------------------*/ static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in) { /* Initialize information. */ @@ -354,7 +348,6 @@ static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in) return info; } -/*--------------------------------------------------------------------------*/ static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out) { /* String iterator. */ @@ -413,7 +406,6 @@ static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out) } #endif -/*--------------------------------------------------------------------------*/ /* Function to convert a logical or relative path to a physical full path. */ static int kwsys_shared_forward_realpath(const char* in_path, char* out_path) { @@ -428,7 +420,6 @@ static int kwsys_shared_forward_realpath(const char* in_path, char* out_path) #endif } -/*--------------------------------------------------------------------------*/ static int kwsys_shared_forward_samepath(const char* file1, const char* file2) { #if defined(_WIN32) @@ -458,7 +449,6 @@ static int kwsys_shared_forward_samepath(const char* file1, const char* file2) #endif } -/*--------------------------------------------------------------------------*/ /* Function to report a system error message. */ static void kwsys_shared_forward_strerror(char* message) { @@ -481,7 +471,6 @@ static void kwsys_shared_forward_strerror(char* message) #endif } -/*--------------------------------------------------------------------------*/ /* Functions to execute a child process. */ static void kwsys_shared_forward_execvp(const char* cmd, char const* const* argv) @@ -521,7 +510,6 @@ static void kwsys_shared_forward_execvp(const char* cmd, #endif } -/*--------------------------------------------------------------------------*/ /* Function to get the directory containing the given file or directory. */ static void kwsys_shared_forward_dirname(const char* begin, char* result) { @@ -557,7 +545,6 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result) } } -/*--------------------------------------------------------------------------*/ /* Function to check if a file exists and is executable. */ static int kwsys_shared_forward_is_executable(const char* f) { @@ -578,7 +565,6 @@ static int kwsys_shared_forward_is_executable(const char* f) } } -/*--------------------------------------------------------------------------*/ /* Function to locate the executable currently running. */ static int kwsys_shared_forward_self_path(const char* argv0, char* result) { @@ -644,7 +630,6 @@ static int kwsys_shared_forward_self_path(const char* argv0, char* result) return 0; } -/*--------------------------------------------------------------------------*/ /* Function to convert a specified path to a full path. If it is not already full, it is taken relative to the self path. */ static int kwsys_shared_forward_fullpath(const char* self_path, @@ -681,7 +666,6 @@ static int kwsys_shared_forward_fullpath(const char* self_path, return 1; } -/*--------------------------------------------------------------------------*/ /* Function to compute the library search path and executable name based on the self path. */ static int kwsys_shared_forward_get_settings(const char* self_path, @@ -773,7 +757,6 @@ static int kwsys_shared_forward_get_settings(const char* self_path, return 1; } -/*--------------------------------------------------------------------------*/ /* Function to print why execution of a command line failed. */ static void kwsys_shared_forward_print_failure(char const* const* argv) { @@ -791,7 +774,6 @@ static void kwsys_shared_forward_print_failure(char const* const* argv) static char kwsys_shared_forward_ldpath[65535] = KWSYS_SHARED_FORWARD_LDPATH "="; -/*--------------------------------------------------------------------------*/ /* Main driver function to be called from main. */ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in) { diff --git a/Source/kwsys/System.c b/Source/kwsys/System.c index 43c60c572..b9af8e9d9 100644 --- a/Source/kwsys/System.c +++ b/Source/kwsys/System.c @@ -22,7 +22,6 @@ typedef ptrdiff_t kwsysSystem_ptrdiff_t; typedef int kwsysSystem_ptrdiff_t; #endif -/*--------------------------------------------------------------------------*/ static int kwsysSystem__AppendByte(char* local, char** begin, char** end, int* size, char c) { @@ -47,7 +46,6 @@ static int kwsysSystem__AppendByte(char* local, char** begin, char** end, return 1; } -/*--------------------------------------------------------------------------*/ static int kwsysSystem__AppendArgument(char** local, char*** begin, char*** end, int* size, char* arg_local, char** arg_begin, char** arg_end, @@ -91,7 +89,6 @@ static int kwsysSystem__AppendArgument(char** local, char*** begin, return 1; } -/*--------------------------------------------------------------------------*/ #define KWSYSPE_LOCAL_BYTE_COUNT 1024 #define KWSYSPE_LOCAL_ARGS_COUNT 32 static char** kwsysSystem__ParseUnixCommand(const char* command, int flags) @@ -227,7 +224,6 @@ static char** kwsysSystem__ParseUnixCommand(const char* command, int flags) return newCommand; } -/*--------------------------------------------------------------------------*/ char** kwsysSystem_Parse_CommandForUnix(const char* command, int flags) { /* Validate the flags. */ diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index e01dcd7a7..86fdccdc7 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -35,8 +35,13 @@ #include "SystemInformation.hxx.in" #endif +#include +#include +#include #include #include +#include +#include #include #include #include @@ -394,7 +399,6 @@ public: bool SupportsMP; bool HasMMXPlus; bool HasSSEMMX; - bool SupportsHyperthreading; unsigned int LogicalProcessorsPerPhysical; int APIC_ID; CPUPowerManagement PowerManagement; @@ -463,10 +467,9 @@ protected: unsigned int NumberOfLogicalCPU; unsigned int NumberOfPhysicalCPU; - int CPUCount(); // For windows - unsigned char LogicalCPUPerPhysicalCPU(); + void CPUCountWindows(); // For windows unsigned char GetAPICId(); // For windows - bool IsHyperThreadingSupported(); + bool IsSMTSupported(); static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows // For Linux and Cygwin, /proc/cpuinfo formats are slightly different @@ -536,6 +539,7 @@ protected: std::string OSRelease; std::string OSVersion; std::string OSPlatform; + bool OSIs64Bit; }; SystemInformation::SystemInformation() @@ -834,7 +838,6 @@ void SystemInformation::RunMemoryCheck() this->Implementation->RunMemoryCheck(); } -// -------------------------------------------------------------- // SystemInformationImplementation starts here #define STORE_TLBCACHE_INFO(x, y) x = (x < (y)) ? (y) : x @@ -842,30 +845,6 @@ void SystemInformation::RunMemoryCheck() #define CLASSICAL_CPU_FREQ_LOOP 10000000 #define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31 -#define MMX_FEATURE 0x00000001 -#define MMX_PLUS_FEATURE 0x00000002 -#define SSE_FEATURE 0x00000004 -#define SSE2_FEATURE 0x00000008 -#define AMD_3DNOW_FEATURE 0x00000010 -#define AMD_3DNOW_PLUS_FEATURE 0x00000020 -#define IA64_FEATURE 0x00000040 -#define MP_CAPABLE 0x00000080 -#define HYPERTHREAD_FEATURE 0x00000100 -#define SERIALNUMBER_FEATURE 0x00000200 -#define APIC_FEATURE 0x00000400 -#define SSE_FP_FEATURE 0x00000800 -#define SSE_MMX_FEATURE 0x00001000 -#define CMOV_FEATURE 0x00002000 -#define MTRR_FEATURE 0x00004000 -#define L1CACHE_FEATURE 0x00008000 -#define L2CACHE_FEATURE 0x00010000 -#define L3CACHE_FEATURE 0x00020000 -#define ACPI_FEATURE 0x00040000 -#define THERMALMONITOR_FEATURE 0x00080000 -#define TEMPSENSEDIODE_FEATURE 0x00100000 -#define FREQUENCYID_FEATURE 0x00200000 -#define VOLTAGEID_FREQUENCY 0x00400000 - // Status Flag #define HT_NOT_CAPABLE 0 #define HT_ENABLED 1 @@ -939,7 +918,8 @@ int LoadLines(const char* fileName, std::vector& lines) // **************************************************************************** template -int NameValue(std::vector& lines, std::string name, T& value) +int NameValue(std::vector const& lines, std::string const& name, + T& value) { size_t nLines = lines.size(); for (size_t i = 0; i < nLines; ++i) { @@ -1310,7 +1290,6 @@ private: int ReportPath; }; -// -------------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const SymbolProperties& sp) { #if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) @@ -1329,7 +1308,6 @@ std::ostream& operator<<(std::ostream& os, const SymbolProperties& sp) return os; } -// -------------------------------------------------------------------------- SymbolProperties::SymbolProperties() { // not using an initializer list @@ -1348,20 +1326,18 @@ SymbolProperties::SymbolProperties() this->GetLineNumber(); } -// -------------------------------------------------------------------------- std::string SymbolProperties::GetFileName(const std::string& path) const { std::string file(path); if (!this->ReportPath) { size_t at = file.rfind("/"); if (at != std::string::npos) { - file = file.substr(at + 1, std::string::npos); + file = file.substr(at + 1); } } return file; } -// -------------------------------------------------------------------------- std::string SymbolProperties::GetBinary() const { // only linux has proc fs @@ -1382,7 +1358,6 @@ std::string SymbolProperties::GetBinary() const return this->GetFileName(this->Binary); } -// -------------------------------------------------------------------------- std::string SymbolProperties::Demangle(const char* symbol) const { std::string result = safes(symbol); @@ -1402,7 +1377,6 @@ std::string SymbolProperties::Demangle(const char* symbol) const return result; } -// -------------------------------------------------------------------------- void SymbolProperties::Initialize(void* address) { this->Address = address; @@ -1421,7 +1395,6 @@ void SymbolProperties::Initialize(void* address) } #endif // don't define this class if we're not using it -// -------------------------------------------------------------------------- #if defined(_WIN32) || defined(__CYGWIN__) #define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes #endif @@ -1496,6 +1469,7 @@ SystemInformationImplementation::SystemInformationImplementation() this->OSRelease = ""; this->OSVersion = ""; this->OSPlatform = ""; + this->OSIs64Bit = (sizeof(void*) == 8); } SystemInformationImplementation::~SystemInformationImplementation() @@ -1542,7 +1516,7 @@ void SystemInformationImplementation::RunCPUCheck() RetrieveProcessorSerialNumber(); } - this->CPUCount(); + this->CPUCountWindows(); #elif defined(__APPLE__) this->ParseSysCtl(); @@ -1870,11 +1844,11 @@ int SystemInformationImplementation::GetProcessorCacheSize() int SystemInformationImplementation::GetProcessorCacheXSize(long int dwCacheID) { switch (dwCacheID) { - case L1CACHE_FEATURE: + case SystemInformation::CPU_FEATURE_L1CACHE: return this->Features.L1CacheSize; - case L2CACHE_FEATURE: + case SystemInformation::CPU_FEATURE_L2CACHE: return this->Features.L2CacheSize; - case L3CACHE_FEATURE: + case SystemInformation::CPU_FEATURE_L3CACHE: return this->Features.L3CacheSize; } return -1; @@ -1885,104 +1859,121 @@ bool SystemInformationImplementation::DoesCPUSupportFeature(long int dwFeature) bool bHasFeature = false; // Check for MMX instructions. - if (((dwFeature & MMX_FEATURE) != 0) && this->Features.HasMMX) + if (((dwFeature & SystemInformation::CPU_FEATURE_MMX) != 0) && + this->Features.HasMMX) bHasFeature = true; // Check for MMX+ instructions. - if (((dwFeature & MMX_PLUS_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_MMX_PLUS) != 0) && this->Features.ExtendedFeatures.HasMMXPlus) bHasFeature = true; // Check for SSE FP instructions. - if (((dwFeature & SSE_FEATURE) != 0) && this->Features.HasSSE) + if (((dwFeature & SystemInformation::CPU_FEATURE_SSE) != 0) && + this->Features.HasSSE) bHasFeature = true; // Check for SSE FP instructions. - if (((dwFeature & SSE_FP_FEATURE) != 0) && this->Features.HasSSEFP) + if (((dwFeature & SystemInformation::CPU_FEATURE_SSE_FP) != 0) && + this->Features.HasSSEFP) bHasFeature = true; // Check for SSE MMX instructions. - if (((dwFeature & SSE_MMX_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_SSE_MMX) != 0) && this->Features.ExtendedFeatures.HasSSEMMX) bHasFeature = true; // Check for SSE2 instructions. - if (((dwFeature & SSE2_FEATURE) != 0) && this->Features.HasSSE2) + if (((dwFeature & SystemInformation::CPU_FEATURE_SSE2) != 0) && + this->Features.HasSSE2) bHasFeature = true; // Check for 3DNow! instructions. - if (((dwFeature & AMD_3DNOW_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_AMD_3DNOW) != 0) && this->Features.ExtendedFeatures.Has3DNow) bHasFeature = true; // Check for 3DNow+ instructions. - if (((dwFeature & AMD_3DNOW_PLUS_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS) != 0) && this->Features.ExtendedFeatures.Has3DNowPlus) bHasFeature = true; // Check for IA64 instructions. - if (((dwFeature & IA64_FEATURE) != 0) && this->Features.HasIA64) + if (((dwFeature & SystemInformation::CPU_FEATURE_IA64) != 0) && + this->Features.HasIA64) bHasFeature = true; // Check for MP capable. - if (((dwFeature & MP_CAPABLE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_MP_CAPABLE) != 0) && this->Features.ExtendedFeatures.SupportsMP) bHasFeature = true; // Check for a serial number for the processor. - if (((dwFeature & SERIALNUMBER_FEATURE) != 0) && this->Features.HasSerial) + if (((dwFeature & SystemInformation::CPU_FEATURE_SERIALNUMBER) != 0) && + this->Features.HasSerial) bHasFeature = true; // Check for a local APIC in the processor. - if (((dwFeature & APIC_FEATURE) != 0) && this->Features.HasAPIC) + if (((dwFeature & SystemInformation::CPU_FEATURE_APIC) != 0) && + this->Features.HasAPIC) bHasFeature = true; // Check for CMOV instructions. - if (((dwFeature & CMOV_FEATURE) != 0) && this->Features.HasCMOV) + if (((dwFeature & SystemInformation::CPU_FEATURE_CMOV) != 0) && + this->Features.HasCMOV) bHasFeature = true; // Check for MTRR instructions. - if (((dwFeature & MTRR_FEATURE) != 0) && this->Features.HasMTRR) + if (((dwFeature & SystemInformation::CPU_FEATURE_MTRR) != 0) && + this->Features.HasMTRR) bHasFeature = true; // Check for L1 cache size. - if (((dwFeature & L1CACHE_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_L1CACHE) != 0) && (this->Features.L1CacheSize != -1)) bHasFeature = true; // Check for L2 cache size. - if (((dwFeature & L2CACHE_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_L2CACHE) != 0) && (this->Features.L2CacheSize != -1)) bHasFeature = true; // Check for L3 cache size. - if (((dwFeature & L3CACHE_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_L3CACHE) != 0) && (this->Features.L3CacheSize != -1)) bHasFeature = true; // Check for ACPI capability. - if (((dwFeature & ACPI_FEATURE) != 0) && this->Features.HasACPI) + if (((dwFeature & SystemInformation::CPU_FEATURE_ACPI) != 0) && + this->Features.HasACPI) bHasFeature = true; // Check for thermal monitor support. - if (((dwFeature & THERMALMONITOR_FEATURE) != 0) && this->Features.HasThermal) + if (((dwFeature & SystemInformation::CPU_FEATURE_THERMALMONITOR) != 0) && + this->Features.HasThermal) bHasFeature = true; // Check for temperature sensing diode support. - if (((dwFeature & TEMPSENSEDIODE_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_TEMPSENSEDIODE) != 0) && this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode) bHasFeature = true; // Check for frequency ID support. - if (((dwFeature & FREQUENCYID_FEATURE) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_FREQUENCYID) != 0) && this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID) bHasFeature = true; // Check for voltage ID support. - if (((dwFeature & VOLTAGEID_FREQUENCY) != 0) && + if (((dwFeature & SystemInformation::CPU_FEATURE_VOLTAGEID_FREQUENCY) != + 0) && this->Features.ExtendedFeatures.PowerManagement.HasVoltageID) bHasFeature = true; + // Check for FPU support. + if (((dwFeature & SystemInformation::CPU_FEATURE_FPU) != 0) && + this->Features.HasFPU) + bHasFeature = true; + return bHasFeature; } @@ -2090,16 +2081,10 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() // Retrieve Intel specific extended features. if (this->ChipManufacturer == Intel) { - this->Features.ExtendedFeatures.SupportsHyperthreading = - ((cpuinfo[3] & 0x10000000) != - 0); // Intel specific: Hyperthreading --> Bit 28 - this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = - (this->Features.ExtendedFeatures.SupportsHyperthreading) - ? ((cpuinfo[1] & 0x00FF0000) >> 16) - : 1; - - if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && - (this->Features.HasAPIC)) { + bool SupportsSMT = + ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28 + + if ((SupportsSMT) && (this->Features.HasAPIC)) { // Retrieve APIC information if there is one present. this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24); @@ -3357,11 +3342,11 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile( std::string buffer, const char* word, size_t init) { size_t pos = buffer.find(word, init); - if (pos != buffer.npos) { + if (pos != std::string::npos) { this->CurrentPositionInFile = pos; pos = buffer.find(":", pos); size_t pos2 = buffer.find("\n", pos); - if (pos != buffer.npos && pos2 != buffer.npos) { + if (pos != std::string::npos && pos2 != std::string::npos) { // It may happen that the beginning matches, but this is still not the // requested key. // An example is looking for "cpu" when "cpu family" comes first. So we @@ -3376,7 +3361,7 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile( return buffer.substr(pos + 2, pos2 - pos - 2); } } - this->CurrentPositionInFile = buffer.npos; + this->CurrentPositionInFile = std::string::npos; return ""; } @@ -3401,38 +3386,33 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() fclose(fd); buffer.resize(fileSize - 2); // Number of logical CPUs (combination of multiple processors, multi-core - // and hyperthreading) + // and SMT) size_t pos = buffer.find("processor\t"); - while (pos != buffer.npos) { + while (pos != std::string::npos) { this->NumberOfLogicalCPU++; pos = buffer.find("processor\t", pos + 1); } #ifdef __linux - // Find the largest physical id. - int maxId = -1; + // Count sockets. + std::set PhysicalIDs; std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id"); - while (this->CurrentPositionInFile != buffer.npos) { + while (this->CurrentPositionInFile != std::string::npos) { int id = atoi(idc.c_str()); - if (id > maxId) { - maxId = id; - } + PhysicalIDs.insert(id); idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id", this->CurrentPositionInFile + 1); } + uint64_t NumberOfSockets = PhysicalIDs.size(); + NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1); // Physical ids returned by Linux don't distinguish cores. // We want to record the total number of cores in this->NumberOfPhysicalCPU // (checking only the first proc) - std::string cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); - int numberOfCoresPerCPU = atoi(cores.c_str()); - if (maxId > 0) { - this->NumberOfPhysicalCPU = - static_cast(numberOfCoresPerCPU * (maxId + 1)); - } else { - // Linux Sparc: get cpu count - this->NumberOfPhysicalCPU = - atoi(this->ExtractValueFromCpuInfoFile(buffer, "ncpus active").c_str()); - } + std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); + unsigned int NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str()); + NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u); + this->NumberOfPhysicalCPU = + NumberOfCoresPerSocket * (unsigned int)NumberOfSockets; #else // __CYGWIN__ // does not have "physical id" entries, neither "cpu cores" @@ -3447,7 +3427,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if (this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; } - // LogicalProcessorsPerPhysical>1 => hyperthreading. + // LogicalProcessorsPerPhysical>1 => SMT. this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU; @@ -3527,7 +3507,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() this->ExtractValueFromCpuInfoFile(buffer, cachename[index]); if (!cacheSize.empty()) { pos = cacheSize.find(" KB"); - if (pos != cacheSize.npos) { + if (pos != std::string::npos) { cacheSize = cacheSize.substr(0, pos); } this->Features.L1CacheSize += atoi(cacheSize.c_str()); @@ -4322,68 +4302,10 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS) (void)uiMS; } -/** Return the number of logical CPU per physical CPUs Works only for windows - */ -unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) -{ -#ifdef __APPLE__ - size_t len = 4; - int cores_per_package = 0; - int err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, - &len, NULL, 0); - if (err != 0) { - return 1; // That name was not found, default to 1 - } - return static_cast(cores_per_package); -#else - int Regs[4] = { 0, 0, 0, 0 }; -#if USE_CPUID - if (!this->IsHyperThreadingSupported()) { - return static_cast(1); // HT not supported - } - call_cpuid(1, Regs); -#endif - return static_cast((Regs[1] & NUM_LOGICAL_BITS) >> 16); -#endif -} - /** Works only for windows */ -bool SystemInformationImplementation::IsHyperThreadingSupported() +bool SystemInformationImplementation::IsSMTSupported() { - if (this->Features.ExtendedFeatures.SupportsHyperthreading) { - return true; - } - -#if USE_CPUID - int Regs[4] = { 0, 0, 0, 0 }, VendorId[4] = { 0, 0, 0, 0 }; - // Get vendor id string - if (!call_cpuid(0, VendorId)) { - return false; - } - // eax contains family processor type - // edx has info about the availability of hyper-Threading - if (!call_cpuid(1, Regs)) { - return false; - } - - if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) { - if (VendorId[1] == 0x756e6547) // 'uneG' - { - if (VendorId[3] == 0x49656e69) // 'Ieni' - { - if (VendorId[2] == 0x6c65746e) // 'letn' - { - // Genuine Intel with hyper-Threading technology - this->Features.ExtendedFeatures.SupportsHyperthreading = - ((Regs[3] & HT_BIT) != 0); - return this->Features.ExtendedFeatures.SupportsHyperthreading; - } - } - } - } -#endif - - return 0; // Not genuine Intel processor + return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1; } /** Return the APIC Id. Works only for windows. */ @@ -4392,7 +4314,7 @@ unsigned char SystemInformationImplementation::GetAPICId() int Regs[4] = { 0, 0, 0, 0 }; #if USE_CPUID - if (!this->IsHyperThreadingSupported()) { + if (!this->IsSMTSupported()) { return static_cast(-1); // HT not supported } // Logical processor = 1 call_cpuid(1, Regs); @@ -4402,102 +4324,63 @@ unsigned char SystemInformationImplementation::GetAPICId() } /** Count the number of CPUs. Works only on windows. */ -int SystemInformationImplementation::CPUCount() +void SystemInformationImplementation::CPUCountWindows() { #if defined(_WIN32) - unsigned char StatusFlag = 0; - SYSTEM_INFO info; - this->NumberOfPhysicalCPU = 0; this->NumberOfLogicalCPU = 0; - info.dwNumberOfProcessors = 0; - GetSystemInfo(&info); - - // Number of physical processors in a non-Intel system - // or in a 32-bit Intel system with Hyper-Threading technology disabled - this->NumberOfPhysicalCPU = (unsigned char)info.dwNumberOfProcessors; - - if (this->IsHyperThreadingSupported()) { - unsigned char HT_Enabled = 0; - this->NumberOfLogicalCPU = this->LogicalCPUPerPhysicalCPU(); - if (this->NumberOfLogicalCPU >= - 1) // >1 Doesn't mean HT is enabled in the BIOS - { - HANDLE hCurrentProcessHandle; -#ifndef _WIN64 -#define DWORD_PTR DWORD -#endif - DWORD_PTR dwProcessAffinity; - DWORD_PTR dwSystemAffinity; - DWORD dwAffinityMask; - - // Calculate the appropriate shifts and mask based on the - // number of logical processors. - unsigned int i = 1; - unsigned char PHY_ID_MASK = 0xFF; - // unsigned char PHY_ID_SHIFT = 0; - - while (i < this->NumberOfLogicalCPU) { - i *= 2; - PHY_ID_MASK <<= 1; - // PHY_ID_SHIFT++; - } - - hCurrentProcessHandle = GetCurrentProcess(); - GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity, - &dwSystemAffinity); - // Check if available process affinity mask is equal to the - // available system affinity mask - if (dwProcessAffinity != dwSystemAffinity) { - StatusFlag = HT_CANNOT_DETECT; - this->NumberOfPhysicalCPU = (unsigned char)-1; - return StatusFlag; - } - - dwAffinityMask = 1; - while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity) { - // Check if this CPU is available - if (dwAffinityMask & dwProcessAffinity) { - if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) { - unsigned char APIC_ID, LOG_ID; - Sleep(0); // Give OS time to switch CPU - - APIC_ID = GetAPICId(); - LOG_ID = APIC_ID & ~PHY_ID_MASK; + typedef BOOL(WINAPI * GetLogicalProcessorInformationType)( + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD); + static GetLogicalProcessorInformationType pGetLogicalProcessorInformation = + (GetLogicalProcessorInformationType)GetProcAddress( + GetModuleHandleW(L"kernel32"), "GetLogicalProcessorInformation"); + + if (!pGetLogicalProcessorInformation) { + // Fallback to approximate implementation on ancient Windows versions. + SYSTEM_INFO info; + ZeroMemory(&info, sizeof(info)); + GetSystemInfo(&info); + this->NumberOfPhysicalCPU = + static_cast(info.dwNumberOfProcessors); + this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; + return; + } - if (LOG_ID != 0) { - HT_Enabled = 1; - } - } - } - dwAffinityMask = dwAffinityMask << 1; - } - // Reset the processor affinity - SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity); + std::vector ProcInfo; + { + DWORD Length = 0; + DWORD rc = pGetLogicalProcessorInformation(NULL, &Length); + assert(FALSE == rc); + (void)rc; // Silence unused variable warning in Borland C++ 5.81 + assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER); + ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + rc = pGetLogicalProcessorInformation(&ProcInfo[0], &Length); + assert(rc != FALSE); + (void)rc; // Silence unused variable warning in Borland C++ 5.81 + } + + typedef std::vector::iterator + pinfoIt_t; + for (pinfoIt_t it = ProcInfo.begin(); it != ProcInfo.end(); ++it) { + SYSTEM_LOGICAL_PROCESSOR_INFORMATION PInfo = *it; + if (PInfo.Relationship != RelationProcessorCore) { + continue; + } - if (this->NumberOfLogicalCPU == - 1) // Normal P4 : HT is disabled in hardware - { - StatusFlag = HT_DISABLED; - } else { - if (HT_Enabled) { - // Total physical processors in a Hyper-Threading enabled system. - this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU); - StatusFlag = HT_ENABLED; - } else { - StatusFlag = HT_SUPPORTED_NOT_ENABLED; - } - } + std::bitset::digits> ProcMask( + (unsigned long long)PInfo.ProcessorMask); + unsigned int count = (unsigned int)ProcMask.count(); + if (count == 0) { // I think this should never happen, but just to be safe. + continue; } - } else { - // Processors do not have Hyper-Threading technology - StatusFlag = HT_NOT_CAPABLE; - this->NumberOfLogicalCPU = 1; + this->NumberOfPhysicalCPU++; + this->NumberOfLogicalCPU += (unsigned int)count; + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count; } - return StatusFlag; + this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU); + this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU); #else - return 0; #endif } @@ -4559,8 +4442,14 @@ bool SystemInformationImplementation::ParseSysCtl() sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0); len = sizeof(this->NumberOfLogicalCPU); sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0); + + int cores_per_package = 0; + len = sizeof(cores_per_package); + err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len, + NULL, 0); + // That name was not found, default to 1 this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = - this->LogicalCPUPerPhysicalCPU(); + err != 0 ? 1 : static_cast(cores_per_package); len = sizeof(value); sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0); @@ -4697,10 +4586,10 @@ std::string SystemInformationImplementation::ExtractValueFromSysCtl( const char* word) { size_t pos = this->SysCtlBuffer.find(word); - if (pos != this->SysCtlBuffer.npos) { + if (pos != std::string::npos) { pos = this->SysCtlBuffer.find(": ", pos); size_t pos2 = this->SysCtlBuffer.find("\n", pos); - if (pos != this->SysCtlBuffer.npos && pos2 != this->SysCtlBuffer.npos) { + if (pos != std::string::npos && pos2 != std::string::npos) { return this->SysCtlBuffer.substr(pos + 2, pos2 - pos - 2); } } @@ -4772,14 +4661,14 @@ std::string SystemInformationImplementation::ParseValueFromKStat( args.push_back("-p"); std::string command = arguments; - size_t start = command.npos; + size_t start = std::string::npos; size_t pos = command.find(' ', 0); - while (pos != command.npos) { + while (pos != std::string::npos) { bool inQuotes = false; // Check if we are between quotes size_t b0 = command.find('"', 0); size_t b1 = command.find('"', b0 + 1); - while (b0 != command.npos && b1 != command.npos && b1 > b0) { + while (b0 != std::string::npos && b1 != std::string::npos && b1 > b0) { if (pos > b0 && pos < b1) { inQuotes = true; break; @@ -4793,7 +4682,7 @@ std::string SystemInformationImplementation::ParseValueFromKStat( // Remove the quotes if any size_t quotes = arg.find('"'); - while (quotes != arg.npos) { + while (quotes != std::string::npos) { arg.erase(quotes, 1); quotes = arg.find('"'); } @@ -4976,11 +4865,11 @@ bool SystemInformationImplementation::QueryQNXMemory() args.clear(); size_t pos = buffer.find("System RAM:"); - if (pos == buffer.npos) + if (pos == std::string::npos) return false; pos = buffer.find(":", pos); size_t pos2 = buffer.find("M (", pos); - if (pos2 == buffer.npos) + if (pos2 == std::string::npos) return false; pos++; @@ -5034,11 +4923,11 @@ bool SystemInformationImplementation::QueryQNXProcessor() args.clear(); size_t pos = buffer.find("Processor1:"); - if (pos == buffer.npos) + if (pos == std::string::npos) return false; size_t pos2 = buffer.find("MHz", pos); - if (pos2 == buffer.npos) + if (pos2 == std::string::npos) return false; size_t pos3 = pos2; @@ -5048,9 +4937,9 @@ bool SystemInformationImplementation::QueryQNXProcessor() this->CPUSpeedInMHz = atoi(buffer.substr(pos3 + 1, pos2 - pos3 - 1).c_str()); pos2 = buffer.find(" Stepping", pos); - if (pos2 != buffer.npos) { + if (pos2 != std::string::npos) { pos2 = buffer.find(" ", pos2 + 1); - if (pos2 != buffer.npos && pos2 < pos3) { + if (pos2 != std::string::npos && pos2 < pos3) { this->ChipID.Revision = atoi(buffer.substr(pos2 + 1, pos3 - pos2).c_str()); } @@ -5060,7 +4949,7 @@ bool SystemInformationImplementation::QueryQNXProcessor() do { pos = buffer.find("\nProcessor", pos + 1); ++this->NumberOfPhysicalCPU; - } while (pos != buffer.npos); + } while (pos != std::string::npos); this->NumberOfLogicalCPU = 1; return true; @@ -5436,10 +5325,20 @@ bool SystemInformationImplementation::QueryOSInformation() this->Hostname = name; const char* arch = getenv("PROCESSOR_ARCHITECTURE"); + const char* wow64 = getenv("PROCESSOR_ARCHITEW6432"); if (arch) { this->OSPlatform = arch; } + if (wow64) { + // the PROCESSOR_ARCHITEW6432 is only defined when running 32bit programs + // on 64bit OS + this->OSIs64Bit = true; + } else if (arch) { + // all values other than x86 map to 64bit architectures + this->OSIs64Bit = (strncmp(arch, "x86", 3) != 0); + } + #else struct utsname unameInfo; @@ -5450,6 +5349,12 @@ bool SystemInformationImplementation::QueryOSInformation() this->OSRelease = unameInfo.release; this->OSVersion = unameInfo.version; this->OSPlatform = unameInfo.machine; + + // This is still insufficient to capture 64bit architecture such + // powerpc and possible mips and sparc + if (this->OSPlatform.find_first_of("64") != std::string::npos) { + this->OSIs64Bit = true; + } } #ifdef __APPLE__ @@ -5503,6 +5408,6 @@ void SystemInformationImplementation::TrimNewline(std::string& output) /** Return true if the machine is 64 bits */ bool SystemInformationImplementation::Is64Bits() { - return (sizeof(void*) == 8); + return this->OSIs64Bit; } } diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index 0fc1067a3..516c505c5 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -25,6 +25,33 @@ class @KWSYS_NAMESPACE@_EXPORT SystemInformation friend class SystemInformationImplementation; SystemInformationImplementation* Implementation; +public: + // possible parameter values for DoesCPUSupportFeature() + static const long int CPU_FEATURE_MMX = 1 << 0; + static const long int CPU_FEATURE_MMX_PLUS = 1 << 1; + static const long int CPU_FEATURE_SSE = 1 << 2; + static const long int CPU_FEATURE_SSE2 = 1 << 3; + static const long int CPU_FEATURE_AMD_3DNOW = 1 << 4; + static const long int CPU_FEATURE_AMD_3DNOW_PLUS = 1 << 5; + static const long int CPU_FEATURE_IA64 = 1 << 6; + static const long int CPU_FEATURE_MP_CAPABLE = 1 << 7; + static const long int CPU_FEATURE_HYPERTHREAD = 1 << 8; + static const long int CPU_FEATURE_SERIALNUMBER = 1 << 9; + static const long int CPU_FEATURE_APIC = 1 << 10; + static const long int CPU_FEATURE_SSE_FP = 1 << 11; + static const long int CPU_FEATURE_SSE_MMX = 1 << 12; + static const long int CPU_FEATURE_CMOV = 1 << 13; + static const long int CPU_FEATURE_MTRR = 1 << 14; + static const long int CPU_FEATURE_L1CACHE = 1 << 15; + static const long int CPU_FEATURE_L2CACHE = 1 << 16; + static const long int CPU_FEATURE_L3CACHE = 1 << 17; + static const long int CPU_FEATURE_ACPI = 1 << 18; + static const long int CPU_FEATURE_THERMALMONITOR = 1 << 19; + static const long int CPU_FEATURE_TEMPSENSEDIODE = 1 << 20; + static const long int CPU_FEATURE_FREQUENCYID = 1 << 21; + static const long int CPU_FEATURE_VOLTAGEID_FREQUENCY = 1 << 22; + static const long int CPU_FEATURE_FPU = 1 << 23; + public: SystemInformation(); ~SystemInformation(); @@ -65,9 +92,10 @@ public: // on this system. std::string GetOSDescription(); + // returns if the operating system is 64bit or not. bool Is64Bits(); - unsigned int GetNumberOfLogicalCPU(); // per physical cpu + unsigned int GetNumberOfLogicalCPU(); unsigned int GetNumberOfPhysicalCPU(); bool DoesCPUSupportCPUID(); diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 97dd4ae57..1c4fe3389 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -22,6 +22,7 @@ #include KWSYS_HEADER(FStream.hxx) #include KWSYS_HEADER(Encoding.hxx) +#include #include #include #include @@ -54,7 +55,6 @@ #include #include #include -#include #include #if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__) @@ -217,12 +217,12 @@ static time_t windows_filetime_to_posix_time(const FILETIME& ft) inline int Mkdir(const std::string& dir) { return _wmkdir( - KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str()); + KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str()); } inline int Rmdir(const std::string& dir) { return _wrmdir( - KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str()); + KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str()); } inline const char* Getcwd(char* buf, unsigned int len) { @@ -548,15 +548,13 @@ bool SystemTools::HasEnv(const std::string& key) return SystemTools::HasEnv(key.c_str()); } -//---------------------------------------------------------------------------- - #if KWSYS_CXX_HAS_UNSETENV /* unsetenv("A") removes A from the environment. On older platforms it returns void instead of int. */ static int kwsysUnPutEnv(const std::string& env) { size_t pos = env.find('='); - if (pos != env.npos) { + if (pos != std::string::npos) { std::string name = env.substr(0, pos); unsetenv(name.c_str()); } else { @@ -572,7 +570,7 @@ static int kwsysUnPutEnv(const std::string& env) { int err = 0; size_t pos = env.find('='); - size_t const len = pos == env.npos ? env.size() : pos; + size_t const len = pos == std::string::npos ? env.size() : pos; size_t const sz = len + 1; char local_buf[256]; char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf; @@ -606,7 +604,7 @@ static int kwsysUnPutEnv(std::string const& env) { std::wstring wEnv = Encoding::ToWide(env); size_t const pos = wEnv.find('='); - size_t const len = pos == wEnv.npos ? wEnv.size() : pos; + size_t const len = pos == std::string::npos ? wEnv.size() : pos; wEnv.resize(len + 1, L'='); wchar_t* newEnv = _wcsdup(wEnv.c_str()); if (!newEnv) { @@ -622,7 +620,7 @@ static int kwsysUnPutEnv(std::string const& env) static int kwsysUnPutEnv(const std::string& env) { size_t pos = env.find('='); - size_t const len = pos == env.npos ? env.size() : pos; + size_t const len = pos == std::string::npos ? env.size() : pos; int in = 0; int out = 0; while (environ[in]) { @@ -640,8 +638,6 @@ static int kwsysUnPutEnv(const std::string& env) } #endif -//---------------------------------------------------------------------------- - #if KWSYS_CXX_HAS_SETENV /* setenv("A", "B", 1) will set A=B in the environment and makes its @@ -649,7 +645,7 @@ static int kwsysUnPutEnv(const std::string& env) bool SystemTools::PutEnv(const std::string& env) { size_t pos = env.find('='); - if (pos != env.npos) { + if (pos != std::string::npos) { std::string name = env.substr(0, pos); return setenv(name.c_str(), env.c_str() + pos + 1, 1) == 0; } else { @@ -732,8 +728,6 @@ bool SystemTools::UnPutEnv(const std::string& env) #endif -//---------------------------------------------------------------------------- - const char* SystemTools::GetExecutableExtension() { #if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS) @@ -746,7 +740,7 @@ const char* SystemTools::GetExecutableExtension() FILE* SystemTools::Fopen(const std::string& file, const char* mode) { #ifdef _WIN32 - return _wfopen(SystemTools::ConvertToWindowsExtendedPath(file).c_str(), + return _wfopen(Encoding::ToWindowsExtendedPath(file).c_str(), Encoding::ToWide(mode).c_str()); #else return fopen(file.c_str(), mode); @@ -1145,7 +1139,6 @@ bool SystemTools::SameFile(const std::string& file1, const std::string& file2) #endif } -//---------------------------------------------------------------------------- bool SystemTools::PathExists(const std::string& path) { if (path.empty()) { @@ -1160,8 +1153,7 @@ bool SystemTools::PathExists(const std::string& path) struct stat st; return lstat(path.c_str(), &st) == 0; #elif defined(_WIN32) - return (GetFileAttributesW( - SystemTools::ConvertToWindowsExtendedPath(path).c_str()) != + return (GetFileAttributesW(Encoding::ToWindowsExtendedPath(path).c_str()) != INVALID_FILE_ATTRIBUTES); #else struct stat st; @@ -1169,7 +1161,6 @@ bool SystemTools::PathExists(const std::string& path) #endif } -//---------------------------------------------------------------------------- bool SystemTools::FileExists(const char* filename) { if (!filename) { @@ -1178,7 +1169,6 @@ bool SystemTools::FileExists(const char* filename) return SystemTools::FileExists(std::string(filename)); } -//---------------------------------------------------------------------------- bool SystemTools::FileExists(const std::string& filename) { if (filename.empty()) { @@ -1192,9 +1182,9 @@ bool SystemTools::FileExists(const std::string& filename) } return access(filename.c_str(), R_OK) == 0; #elif defined(_WIN32) - return (GetFileAttributesW( - SystemTools::ConvertToWindowsExtendedPath(filename).c_str()) != - INVALID_FILE_ATTRIBUTES); + return ( + GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()) != + INVALID_FILE_ATTRIBUTES); #else // SCO OpenServer 5.0.7/3.2's command has 711 permission. #if defined(_SCO_DS) @@ -1205,7 +1195,6 @@ bool SystemTools::FileExists(const std::string& filename) #endif } -//---------------------------------------------------------------------------- bool SystemTools::FileExists(const char* filename, bool isFile) { if (!filename) { @@ -1214,7 +1203,6 @@ bool SystemTools::FileExists(const char* filename, bool isFile) return SystemTools::FileExists(std::string(filename), isFile); } -//---------------------------------------------------------------------------- bool SystemTools::FileExists(const std::string& filename, bool isFile) { if (SystemTools::FileExists(filename)) { @@ -1225,7 +1213,6 @@ bool SystemTools::FileExists(const std::string& filename, bool isFile) return false; } -//---------------------------------------------------------------------------- bool SystemTools::TestFileAccess(const char* filename, TestFilePermissions permissions) { @@ -1235,7 +1222,6 @@ bool SystemTools::TestFileAccess(const char* filename, return SystemTools::TestFileAccess(std::string(filename), permissions); } -//---------------------------------------------------------------------------- bool SystemTools::TestFileAccess(const std::string& filename, TestFilePermissions permissions) { @@ -1250,14 +1236,43 @@ bool SystemTools::TestFileAccess(const std::string& filename, permissions &= ~TEST_FILE_EXECUTE; permissions |= TEST_FILE_READ; } - return _waccess(SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), + return _waccess(Encoding::ToWindowsExtendedPath(filename).c_str(), permissions) == 0; #else return access(filename.c_str(), permissions) == 0; #endif } -//---------------------------------------------------------------------------- +int SystemTools::Stat(const char* path, SystemTools::Stat_t* buf) +{ + if (!path) { + errno = EFAULT; + return -1; + } + return SystemTools::Stat(std::string(path), buf); +} + +int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf) +{ + if (path.empty()) { + errno = ENOENT; + return -1; + } +#if defined(_WIN32) && !defined(__CYGWIN__) + // Ideally we should use Encoding::ToWindowsExtendedPath to support + // long paths, but _wstat64 rejects paths with '?' in them, thinking + // they are wildcards. + std::wstring const& wpath = Encoding::ToWide(path); +#if defined(__BORLANDC__) + return _wstati64(wpath.c_str(), buf); +#else + return _wstat64(wpath.c_str(), buf); +#endif +#else + return stat(path.c_str(), buf); +#endif +} + #ifdef __CYGWIN__ bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path) { @@ -1293,10 +1308,9 @@ bool SystemTools::Touch(const std::string& filename, bool create) } } #if defined(_WIN32) && !defined(__CYGWIN__) - HANDLE h = - CreateFileW(SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), - FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, 0); + HANDLE h = CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), + FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); if (!h) { return false; } @@ -1394,14 +1408,12 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2, // Windows version. Get the modification time from extended file attributes. WIN32_FILE_ATTRIBUTE_DATA f1d; WIN32_FILE_ATTRIBUTE_DATA f2d; - if (!GetFileAttributesExW( - SystemTools::ConvertToWindowsExtendedPath(f1).c_str(), - GetFileExInfoStandard, &f1d)) { + if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(), + GetFileExInfoStandard, &f1d)) { return false; } - if (!GetFileAttributesExW( - SystemTools::ConvertToWindowsExtendedPath(f2).c_str(), - GetFileExInfoStandard, &f2d)) { + if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(), + GetFileExInfoStandard, &f2d)) { return false; } @@ -1710,7 +1722,7 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len) size_t middle = max_len / 2; n += s.substr(0, middle); - n += s.substr(s.size() - (max_len - middle), std::string::npos); + n += s.substr(s.size() - (max_len - middle)); if (max_len > 2) { n[middle] = '.'; @@ -1725,7 +1737,6 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len) return n; } -//---------------------------------------------------------------------------- std::vector SystemTools::SplitString(const std::string& p, char sep, bool isPath) { @@ -1750,7 +1761,6 @@ std::vector SystemTools::SplitString(const std::string& p, return paths; } -//---------------------------------------------------------------------------- int SystemTools::EstimateFormatLength(const char* format, va_list ap) { if (!format) { @@ -1841,7 +1851,7 @@ static void ConvertVMSToUnix(std::string& path) { std::string::size_type rootEnd = path.find(":["); std::string::size_type pathEnd = path.find("]"); - if (rootEnd != path.npos) { + if (rootEnd != std::string::npos) { std::string root = path.substr(0, rootEnd); std::string pathPart = path.substr(rootEnd + 2, pathEnd - rootEnd - 2); const char* pathCString = pathPart.c_str(); @@ -1929,59 +1939,10 @@ void SystemTools::ConvertToUnixSlashes(std::string& path) } #ifdef _WIN32 -// Convert local paths to UNC style paths std::wstring SystemTools::ConvertToWindowsExtendedPath( const std::string& source) { - std::wstring wsource = Encoding::ToWide(source); - - // Resolve any relative paths - DWORD wfull_len; - - /* The +3 is a workaround for a bug in some versions of GetFullPathNameW that - * won't return a large enough buffer size if the input is too small */ - wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3; - std::vector wfull(wfull_len); - GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL); - - /* This should get the correct size without any extra padding from the - * previous size workaround. */ - wfull_len = static_cast(wcslen(&wfull[0])); - - if (wfull_len >= 2 && isalpha(wfull[0]) && - wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */ - return L"\\\\?\\" + std::wstring(&wfull[0]); - } else if (wfull_len >= 2 && wfull[0] == L'\\' && - wfull[1] == L'\\') { /* Starts with \\ */ - if (wfull_len >= 4 && wfull[2] == L'?' && - wfull[3] == L'\\') { /* Starts with \\?\ */ - if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' && - wfull[6] == L'C' && - wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */ - return std::wstring(&wfull[0]); - } else if (wfull_len >= 6 && isalpha(wfull[4]) && - wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */ - return std::wstring(&wfull[0]); - } else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */ - return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]); - } - } else if (wfull_len >= 4 && wfull[2] == L'.' && - wfull[3] == L'\\') { /* Starts with \\.\ a device name */ - if (wfull_len >= 6 && isalpha(wfull[4]) && - wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */ - return L"\\\\?\\" + std::wstring(&wfull[4]); - } else if (wfull_len >= - 5) { /* \\.\Foo\bar\ Device name is left unchanged */ - return std::wstring(&wfull[0]); - } - } else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */ - return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]); - } - } - - // If this case has been reached, then the path is invalid. Leave it - // unchanged - return Encoding::ToWide(source); + return Encoding::ToWindowsExtendedPath(source); } #endif @@ -2098,15 +2059,14 @@ bool SystemTools::FilesDiffer(const std::string& source, #if defined(_WIN32) WIN32_FILE_ATTRIBUTE_DATA statSource; - if (GetFileAttributesExW( - SystemTools::ConvertToWindowsExtendedPath(source).c_str(), - GetFileExInfoStandard, &statSource) == 0) { + if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(source).c_str(), + GetFileExInfoStandard, &statSource) == 0) { return true; } WIN32_FILE_ATTRIBUTE_DATA statDestination; if (GetFileAttributesExW( - SystemTools::ConvertToWindowsExtendedPath(destination).c_str(), + Encoding::ToWindowsExtendedPath(destination).c_str(), GetFileExInfoStandard, &statDestination) == 0) { return true; } @@ -2188,7 +2148,6 @@ bool SystemTools::FilesDiffer(const std::string& source, return false; } -//---------------------------------------------------------------------------- /** * Copy a file named by "source" to the file named by "destination". */ @@ -2230,8 +2189,7 @@ bool SystemTools::CopyFileAlways(const std::string& source, // Open files #if defined(_WIN32) kwsys::ifstream fin( - Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(source)) - .c_str(), + Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(), std::ios::in | std::ios::binary); #else kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary); @@ -2248,8 +2206,7 @@ bool SystemTools::CopyFileAlways(const std::string& source, #if defined(_WIN32) kwsys::ofstream fout( - Encoding::ToNarrow( - SystemTools::ConvertToWindowsExtendedPath(real_destination)) + Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(real_destination)) .c_str(), std::ios::out | std::ios::trunc | std::ios::binary); #else @@ -2294,7 +2251,6 @@ bool SystemTools::CopyFileAlways(const std::string& source, return true; } -//---------------------------------------------------------------------------- bool SystemTools::CopyAFile(const std::string& source, const std::string& destination, bool always) { @@ -2314,8 +2270,7 @@ bool SystemTools::CopyADirectory(const std::string& source, { Directory dir; #ifdef _WIN32 - dir.Load( - Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(source))); + dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source))); #else dir.Load(source); #endif @@ -2353,9 +2308,8 @@ unsigned long SystemTools::FileLength(const std::string& filename) unsigned long length = 0; #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA fs; - if (GetFileAttributesExW( - SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), - GetFileExInfoStandard, &fs) != 0) { + if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(), + GetFileExInfoStandard, &fs) != 0) { /* To support the full 64-bit file size, use fs.nFileSizeHigh * and fs.nFileSizeLow to construct the 64 bit size @@ -2389,9 +2343,8 @@ long int SystemTools::ModifiedTime(const std::string& filename) long int mt = 0; #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA fs; - if (GetFileAttributesExW( - SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), - GetFileExInfoStandard, &fs) != 0) { + if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(), + GetFileExInfoStandard, &fs) != 0) { mt = windows_filetime_to_posix_time(fs.ftLastWriteTime); } #else @@ -2409,9 +2362,8 @@ long int SystemTools::CreationTime(const std::string& filename) long int ct = 0; #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA fs; - if (GetFileAttributesExW( - SystemTools::ConvertToWindowsExtendedPath(filename).c_str(), - GetFileExInfoStandard, &fs) != 0) { + if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(), + GetFileExInfoStandard, &fs) != 0) { ct = windows_filetime_to_posix_time(fs.ftCreationTime); } #else @@ -2625,7 +2577,7 @@ static bool DeleteJunction(const std::wstring& source) bool SystemTools::RemoveFile(const std::string& source) { #ifdef _WIN32 - std::wstring const& ws = SystemTools::ConvertToWindowsExtendedPath(source); + std::wstring const& ws = Encoding::ToWindowsExtendedPath(source); if (DeleteFileW(ws.c_str())) { return true; } @@ -2675,8 +2627,7 @@ bool SystemTools::RemoveADirectory(const std::string& source) Directory dir; #ifdef _WIN32 - dir.Load( - Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(source))); + dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source))); #else dir.Load(source); #endif @@ -3033,8 +2984,8 @@ bool SystemTools::FileIsDirectory(const std::string& inName) // Now check the file node type. #if defined(_WIN32) - DWORD attr = GetFileAttributesW( - SystemTools::ConvertToWindowsExtendedPath(name).c_str()); + DWORD attr = + GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str()); if (attr != INVALID_FILE_ATTRIBUTES) { return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; #else @@ -3050,8 +3001,8 @@ bool SystemTools::FileIsDirectory(const std::string& inName) bool SystemTools::FileIsSymlink(const std::string& name) { #if defined(_WIN32) - DWORD attr = GetFileAttributesW( - SystemTools::ConvertToWindowsExtendedPath(name).c_str()); + DWORD attr = + GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str()); if (attr != INVALID_FILE_ATTRIBUTES) { return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } else { @@ -3067,6 +3018,28 @@ bool SystemTools::FileIsSymlink(const std::string& name) #endif } +bool SystemTools::FileIsFIFO(const std::string& name) +{ +#if defined(_WIN32) + HANDLE hFile = + CreateFileW(Encoding::ToWide(name).c_str(), GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + const DWORD type = GetFileType(hFile); + CloseHandle(hFile); + return type == FILE_TYPE_PIPE; +#else + struct stat fs; + if (lstat(name.c_str(), &fs) == 0) { + return S_ISFIFO(fs.st_mode); + } else { + return false; + } +#endif +} + #if defined(_WIN32) && !defined(__CYGWIN__) bool SystemTools::CreateSymlink(const std::string&, const std::string&) { @@ -3309,7 +3282,7 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path, SystemTools::SplitPath(in_path, path_components); // If the input path is relative, start with a base path. - if (path_components[0].length() == 0) { + if (path_components[0].empty()) { std::vector base_components; if (in_base) { // Use the given base path. @@ -3558,7 +3531,6 @@ static std::string GetCasePathName(std::string const& pathIn) } #endif -//---------------------------------------------------------------------------- std::string SystemTools::GetActualCaseForPath(const std::string& p) { #ifndef _WIN32 @@ -3579,7 +3551,6 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p) #endif } -//---------------------------------------------------------------------------- const char* SystemTools::SplitPathRootComponent(const std::string& p, std::string* root) { @@ -3646,7 +3617,6 @@ const char* SystemTools::SplitPathRootComponent(const std::string& p, return c; } -//---------------------------------------------------------------------------- void SystemTools::SplitPath(const std::string& p, std::vector& components, bool expand_home_dir) @@ -3703,13 +3673,11 @@ void SystemTools::SplitPath(const std::string& p, } } -//---------------------------------------------------------------------------- std::string SystemTools::JoinPath(const std::vector& components) { return SystemTools::JoinPath(components.begin(), components.end()); } -//---------------------------------------------------------------------------- std::string SystemTools::JoinPath( std::vector::const_iterator first, std::vector::const_iterator last) @@ -3741,7 +3709,16 @@ std::string SystemTools::JoinPath( return result; } -//---------------------------------------------------------------------------- +void SystemTools::RemoveEmptyPathElements(std::vector& path) +{ + if (path.empty()) { + return; + } + + path.erase(std::remove(path.begin() + 1, path.end(), std::string("")), + path.end()); +} + bool SystemTools::ComparePath(const std::string& c1, const std::string& c2) { #if defined(_WIN32) || defined(__APPLE__) @@ -3757,7 +3734,6 @@ bool SystemTools::ComparePath(const std::string& c1, const std::string& c2) #endif } -//---------------------------------------------------------------------------- bool SystemTools::Split(const std::string& str, std::vector& lines, char separator) { @@ -3778,7 +3754,6 @@ bool SystemTools::Split(const std::string& str, return true; } -//---------------------------------------------------------------------------- bool SystemTools::Split(const std::string& str, std::vector& lines) { @@ -4345,8 +4320,8 @@ bool SystemTools::GetPermissions(const char* file, mode_t& mode) bool SystemTools::GetPermissions(const std::string& file, mode_t& mode) { #if defined(_WIN32) - DWORD attr = GetFileAttributesW( - SystemTools::ConvertToWindowsExtendedPath(file).c_str()); + DWORD attr = + GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str()); if (attr == INVALID_FILE_ATTRIBUTES) { return false; } @@ -4362,7 +4337,7 @@ bool SystemTools::GetPermissions(const std::string& file, mode_t& mode) mode |= S_IFREG; } size_t dotPos = file.rfind('.'); - const char* ext = dotPos == file.npos ? 0 : (file.c_str() + dotPos); + const char* ext = dotPos == std::string::npos ? 0 : (file.c_str() + dotPos); if (ext && (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 || Strucmp(ext, ".cmd") == 0 || Strucmp(ext, ".bat") == 0)) { mode |= (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)); @@ -4398,8 +4373,7 @@ bool SystemTools::SetPermissions(const std::string& file, mode_t mode, mode &= ~currentMask; } #ifdef _WIN32 - if (_wchmod(SystemTools::ConvertToWindowsExtendedPath(file).c_str(), mode) < - 0) + if (_wchmod(Encoding::ToWindowsExtendedPath(file).c_str(), mode) < 0) #else if (chmod(file.c_str(), mode) < 0) #endif @@ -4716,7 +4690,6 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() return res; } -// ---------------------------------------------------------------------- bool SystemTools::ParseURLProtocol(const std::string& URL, std::string& protocol, std::string& dataglom) @@ -4735,7 +4708,6 @@ bool SystemTools::ParseURLProtocol(const std::string& URL, return true; } -// ---------------------------------------------------------------------- bool SystemTools::ParseURL(const std::string& URL, std::string& protocol, std::string& username, std::string& password, std::string& hostname, std::string& dataport, @@ -4766,7 +4738,6 @@ bool SystemTools::ParseURL(const std::string& URL, std::string& protocol, return true; } -// ---------------------------------------------------------------------- // These must NOT be initialized. Default initialization to zero is // necessary. static unsigned int SystemToolsManagerCount; diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index f3d06fe57..5e091c2af 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -13,6 +13,9 @@ #include <@KWSYS_NAMESPACE@/String.hxx> #include +// include sys/stat.h after sys/types.h +#include + #if !defined(_WIN32) || defined(__CYGWIN__) #include // For access permissions for use with access() #endif @@ -262,13 +265,7 @@ public: static void ConvertToUnixSlashes(std::string& path); #ifdef _WIN32 - /** - * Convert the path to an extended length path to avoid MAX_PATH length - * limitations on Windows. If the input is a local path the result will be - * prefixed with \\?\; if the input is instead a network path, the result - * will be prefixed with \\?\UNC\. All output will also be converted to - * absolute paths with Windows-style backslashes. - **/ + /** Calls Encoding::ToWindowsExtendedPath. */ static std::wstring ConvertToWindowsExtendedPath(const std::string&); #endif @@ -324,6 +321,27 @@ public: TestFilePermissions permissions); static bool TestFileAccess(const std::string& filename, TestFilePermissions permissions); +/** + * Cross platform wrapper for stat struct + */ +#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(__BORLANDC__) + typedef struct stati64 Stat_t; +#else + typedef struct _stat64 Stat_t; +#endif +#else + typedef struct stat Stat_t; +#endif + + /** + * Cross platform wrapper for stat system call + * + * On Windows this may not work for paths longer than 250 characters + * due to limitations of the underlying '_wstat64' call. + */ + static int Stat(const char* path, Stat_t* buf); + static int Stat(const std::string& path, Stat_t* buf); /** * Converts Cygwin path to Win32 path. Uses dictionary container for @@ -456,6 +474,10 @@ public: static std::string JoinPath(std::vector::const_iterator first, std::vector::const_iterator last); + /** Removes empty components from path. + */ + static void RemoveEmptyPathElements(std::vector& path); + /** * Compare a path or components of a path. */ @@ -653,6 +675,11 @@ public: */ static bool FileIsSymlink(const std::string& name); + /** + * Return true if the file is a FIFO + */ + static bool FileIsFIFO(const std::string& name); + /** * Return true if the file has a given signature (first set of bytes) */ diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c index c0b7f454b..eaa5c7d43 100644 --- a/Source/kwsys/Terminal.c +++ b/Source/kwsys/Terminal.c @@ -9,7 +9,6 @@ #include "Terminal.h.in" #endif -/*--------------------------------------------------------------------------*/ /* Configure support for this platform. */ #if defined(_WIN32) || defined(__CYGWIN__) #define KWSYS_TERMINAL_SUPPORT_CONSOLE @@ -18,7 +17,6 @@ #define KWSYS_TERMINAL_ISATTY_WORKS #endif -/*--------------------------------------------------------------------------*/ /* Include needed system APIs. */ #include /* va_list */ @@ -36,7 +34,6 @@ #include /* fstat */ #endif -/*--------------------------------------------------------------------------*/ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, int default_tty); static void kwsysTerminalSetVT100Color(FILE* stream, int color); @@ -47,7 +44,6 @@ static void kwsysTerminalSetConsoleColor(HANDLE hOut, FILE* stream, int color); #endif -/*--------------------------------------------------------------------------*/ void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...) { /* Setup the stream with the given color if possible. */ @@ -89,7 +85,6 @@ void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...) } } -/*--------------------------------------------------------------------------*/ /* Detect cases when a stream is definitely not interactive. */ #if !defined(KWSYS_TERMINAL_ISATTY_WORKS) static int kwsysTerminalStreamIsNotInteractive(FILE* stream) @@ -106,7 +101,6 @@ static int kwsysTerminalStreamIsNotInteractive(FILE* stream) } #endif -/*--------------------------------------------------------------------------*/ /* List of terminal names known to support VT100 color escape sequences. */ static const char* kwsysTerminalVT100Names[] = { "Eterm", "ansi", @@ -162,7 +156,6 @@ static const char* kwsysTerminalVT100Names[] = { "Eterm", "xterm-termite", 0 }; -/*--------------------------------------------------------------------------*/ /* Detect whether a stream is displayed in a VT100-compatible terminal. */ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, int default_tty) @@ -214,7 +207,6 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, #endif } -/*--------------------------------------------------------------------------*/ /* VT100 escape sequence strings. */ #define KWSYS_TERMINAL_VT100_NORMAL "\33[0m" #define KWSYS_TERMINAL_VT100_BOLD "\33[1m" @@ -238,7 +230,6 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100, #define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN "\33[46m" #define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE "\33[47m" -/*--------------------------------------------------------------------------*/ /* Write VT100 escape sequences to the stream for the given color. */ static void kwsysTerminalSetVT100Color(FILE* stream, int color) { @@ -307,7 +298,6 @@ static void kwsysTerminalSetVT100Color(FILE* stream, int color) } } -/*--------------------------------------------------------------------------*/ #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE) #define KWSYS_TERMINAL_MASK_FOREGROUND \ diff --git a/Source/kwsys/kwsysPlatformTestsC.c b/Source/kwsys/kwsysPlatformTestsC.c index d12fac0b6..64a361bbe 100644 --- a/Source/kwsys/kwsysPlatformTestsC.c +++ b/Source/kwsys/kwsysPlatformTestsC.c @@ -27,7 +27,6 @@ main(int argc, char* argv[]) #endif -/*--------------------------------------------------------------------------*/ #ifdef TEST_KWSYS_C_HAS_PTRDIFF_T #include int f(ptrdiff_t n) @@ -43,7 +42,6 @@ int KWSYS_PLATFORM_TEST_C_MAIN() } #endif -/*--------------------------------------------------------------------------*/ #ifdef TEST_KWSYS_C_HAS_SSIZE_T #include int f(ssize_t n) @@ -57,7 +55,6 @@ int KWSYS_PLATFORM_TEST_C_MAIN() } #endif -/*--------------------------------------------------------------------------*/ #ifdef TEST_KWSYS_C_TYPE_MACROS char* info_macros = #if defined(__SIZEOF_SHORT__) diff --git a/Source/kwsys/testConsoleBuf.cxx b/Source/kwsys/testConsoleBuf.cxx index 3b8cdab69..816a4338e 100644 --- a/Source/kwsys/testConsoleBuf.cxx +++ b/Source/kwsys/testConsoleBuf.cxx @@ -74,7 +74,6 @@ std::basic_streambuf* errstream(const wchar_t* unused) return std::wcerr.rdbuf(); } -//---------------------------------------------------------------------------- template static void dumpBuffers(const T* expected, const T* received, size_t size) { @@ -107,7 +106,6 @@ static void dumpBuffers(const T* expected, const T* received, size_t size) std::cerr << std::endl; } -//---------------------------------------------------------------------------- static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr) { BOOL bInheritHandles = FALSE; @@ -158,7 +156,6 @@ static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr) return success; } -//---------------------------------------------------------------------------- static void finishProcess(bool success) { if (success) { @@ -172,7 +169,6 @@ static void finishProcess(bool success) CloseHandle(processInfo.hThread); } -//---------------------------------------------------------------------------- static bool createPipe(PHANDLE readPipe, PHANDLE writePipe) { SECURITY_ATTRIBUTES securityAttributes; @@ -183,7 +179,6 @@ static bool createPipe(PHANDLE readPipe, PHANDLE writePipe) : true; } -//---------------------------------------------------------------------------- static void finishPipe(HANDLE readPipe, HANDLE writePipe) { if (readPipe != INVALID_HANDLE_VALUE) { @@ -194,7 +189,6 @@ static void finishPipe(HANDLE readPipe, HANDLE writePipe) } } -//---------------------------------------------------------------------------- static HANDLE createFile(LPCWSTR fileName) { SECURITY_ATTRIBUTES securityAttributes; @@ -218,7 +212,6 @@ static HANDLE createFile(LPCWSTR fileName) return file; } -//---------------------------------------------------------------------------- static void finishFile(HANDLE file) { if (file != INVALID_HANDLE_VALUE) { @@ -226,8 +219,6 @@ static void finishFile(HANDLE file) } } -//---------------------------------------------------------------------------- - #ifndef MAPVK_VK_TO_VSC #define MAPVK_VK_TO_VSC (0) #endif @@ -269,7 +260,6 @@ static void writeInputKeyEvent(INPUT_RECORD inputBuffer[], WCHAR chr) inputBuffer[1].Event.KeyEvent.dwControlKeyState = 0; } -//---------------------------------------------------------------------------- static int testPipe() { int didFail = 1; @@ -339,9 +329,8 @@ static int testPipe() throw std::runtime_error("ReadFile#3 failed!"); } buffer2[bytesRead] = 0; - didFail = - encodedTestString.compare(0, encodedTestString.npos, buffer2, - encodedTestString.size()) == 0 + didFail = encodedTestString.compare(0, std::string::npos, buffer2, + encodedTestString.size()) == 0 ? 0 : 1; } @@ -377,7 +366,6 @@ static int testPipe() return didFail; } -//---------------------------------------------------------------------------- static int testFile() { int didFail = 1; @@ -446,9 +434,8 @@ static int testFile() throw std::runtime_error("ReadFile#2 failed!"); } buffer2[bytesRead] = 0; - didFail = - encodedTestString.compare(0, encodedTestString.npos, buffer2, - encodedTestString.size()) == 0 + didFail = encodedTestString.compare(0, std::string::npos, buffer2, + encodedTestString.size()) == 0 ? 0 : 1; } @@ -487,7 +474,6 @@ static int testFile() #define _WIN32_WINNT_VISTA 0x0600 #endif -//---------------------------------------------------------------------------- static int testConsole() { int didFail = 1; @@ -748,7 +734,6 @@ static int testConsole() #endif -//---------------------------------------------------------------------------- int testConsoleBuf(int, char* []) { int ret = 0; diff --git a/Source/kwsys/testConsoleBufChild.cxx b/Source/kwsys/testConsoleBufChild.cxx index 83bf545c5..6a743edcd 100644 --- a/Source/kwsys/testConsoleBufChild.cxx +++ b/Source/kwsys/testConsoleBufChild.cxx @@ -16,7 +16,6 @@ #include "testConsoleBuf.hxx" -//---------------------------------------------------------------------------- int main(int argc, const char* argv[]) { #if defined(_WIN32) diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx index 03f2ec9e3..2c5ef46eb 100644 --- a/Source/kwsys/testEncoding.cxx +++ b/Source/kwsys/testEncoding.cxx @@ -22,7 +22,6 @@ #include "Encoding.hxx.in" #endif -//---------------------------------------------------------------------------- static const unsigned char helloWorldStrings[][32] = { // English { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 }, @@ -50,7 +49,6 @@ static const unsigned char helloWorldStrings[][32] = { { 0 } }; -//---------------------------------------------------------------------------- static int testHelloWorldEncoding() { int ret = 0; @@ -180,7 +178,88 @@ static int testCommandLineArguments() return status; } -//---------------------------------------------------------------------------- +static int testToWindowsExtendedPath() +{ +#ifdef _WIN32 + int ret = 0; + if (kwsys::Encoding::ToWindowsExtendedPath( + "L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") != + L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"" + << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath( + "L:/Local Mojo/Hex Power Pack/Iffy Voodoo") != + L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath( + "\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") != + L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"" + << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath( + "//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") != + L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\"" + << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath("//") != L"//") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"//\"" << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\") != L"\\\\.\\") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"\\\\.\\\"" << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X") != L"\\\\.\\X") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"\\\\.\\X\"" << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:") != L"\\\\?\\X:") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"\\\\.\\X:\"" << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:\\") != + L"\\\\?\\X:\\") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"\\\\.\\X:\\\"" << std::endl; + ++ret; + } + + if (kwsys::Encoding::ToWindowsExtendedPath("NUL") != L"\\\\.\\NUL") { + std::cout << "Problem with ToWindowsExtendedPath " + << "\"NUL\"" << std::endl; + ++ret; + } + + return ret; +#else + return 0; +#endif +} + int testEncoding(int, char* []) { const char* loc = setlocale(LC_ALL, ""); @@ -196,6 +275,7 @@ int testEncoding(int, char* []) ret |= testRobustEncoding(); ret |= testCommandLineArguments(); ret |= testWithNulls(); + ret |= testToWindowsExtendedPath(); return ret; } diff --git a/Source/kwsys/testFStream.cxx b/Source/kwsys/testFStream.cxx index 670f5e768..a92a781c3 100644 --- a/Source/kwsys/testFStream.cxx +++ b/Source/kwsys/testFStream.cxx @@ -20,7 +20,6 @@ #include -//---------------------------------------------------------------------------- static int testNoFile() { kwsys::ifstream in_file("NoSuchFile.txt"); @@ -69,7 +68,6 @@ static unsigned char file_data[num_test_files][max_test_file_size] = { 0x72, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x64 }, }; -//---------------------------------------------------------------------------- static int testBOM() { // test various encodings in binary mode @@ -104,7 +102,6 @@ static int testBOM() return 0; } -//---------------------------------------------------------------------------- int testFStream(int, char* []) { int ret = 0; diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 86a1e1e5f..3a9217f2c 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -52,6 +52,7 @@ int testSystemInformation(int, char* []) printMethod(info, GetOSRelease); printMethod(info, GetOSVersion); printMethod(info, GetOSPlatform); + printMethod(info, Is64Bits); printMethod(info, GetVendorString); printMethod(info, GetVendorID); printMethod(info, GetTypeID); @@ -63,7 +64,6 @@ int testSystemInformation(int, char* []) printMethod2(info, GetProcessorCacheSize, "KB"); printMethod(info, GetLogicalProcessorsPerPhysical); printMethod2(info, GetProcessorClockFrequency, "MHz"); - printMethod(info, Is64Bits); printMethod(info, GetNumberOfLogicalCPU); printMethod(info, GetNumberOfPhysicalCPU); printMethod(info, DoesCPUSupportCPUID); diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 8e1ea258a..e6fbf6cda 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -35,7 +35,6 @@ typedef unsigned short mode_t; #endif -//---------------------------------------------------------------------------- static const char* toUnixPaths[][2] = { { "/usr/local/bin/passwd", "/usr/local/bin/passwd" }, { "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" }, @@ -55,7 +54,8 @@ static const char* toUnixPaths[][2] = { { 0, 0 } }; -static bool CheckConvertToUnixSlashes(std::string input, std::string output) +static bool CheckConvertToUnixSlashes(std::string const& input, + std::string const& output) { std::string result = input; kwsys::SystemTools::ConvertToUnixSlashes(result); @@ -67,14 +67,14 @@ static bool CheckConvertToUnixSlashes(std::string input, std::string output) return true; } -//---------------------------------------------------------------------------- static const char* checkEscapeChars[][4] = { { "1 foo 2 bar 2", "12", "\\", "\\1 foo \\2 bar \\2" }, { " {} ", "{}", "#", " #{#} " }, { 0, 0, 0, 0 } }; -static bool CheckEscapeChars(std::string input, const char* chars_to_escape, - char escape_char, std::string output) +static bool CheckEscapeChars(std::string const& input, + const char* chars_to_escape, char escape_char, + std::string const& output) { std::string result = kwsys::SystemTools::EscapeChars( input.c_str(), chars_to_escape, escape_char); @@ -86,7 +86,6 @@ static bool CheckEscapeChars(std::string input, const char* chars_to_escape, return true; } -//---------------------------------------------------------------------------- static bool CheckFileOperations() { bool res = true; @@ -135,6 +134,19 @@ static bool CheckFileOperations() res = false; } + kwsys::SystemTools::Stat_t buf; + if (kwsys::SystemTools::Stat(testTxtFile.c_str(), &buf) != 0) { + std::cerr << "Problem with Stat - unable to stat text file: " + << testTxtFile << std::endl; + res = false; + } + + if (kwsys::SystemTools::Stat(testBinFile, &buf) != 0) { + std::cerr << "Problem with Stat - unable to stat bin file: " << testBinFile + << std::endl; + res = false; + } + if (!kwsys::SystemTools::MakeDirectory(testNewDir)) { std::cerr << "Problem with MakeDirectory for: " << testNewDir << std::endl; res = false; @@ -456,7 +468,6 @@ static bool CheckFileOperations() return res; } -//---------------------------------------------------------------------------- static bool CheckStringOperations() { bool res = true; @@ -572,85 +583,6 @@ static bool CheckStringOperations() res = false; } -#ifdef _WIN32 - if (kwsys::SystemTools::ConvertToWindowsExtendedPath( - "L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") != - L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"" - << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath( - "L:/Local Mojo/Hex Power Pack/Iffy Voodoo") != - L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath( - "\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") != - L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"" - << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath( - "//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") != - L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\"" - << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath("//") != L"//") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"//\"" << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\") != - L"\\\\.\\") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"\\\\.\\\"" << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X") != - L"\\\\.\\X") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"\\\\.\\X\"" << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:") != - L"\\\\?\\X:") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"\\\\.\\X:\"" << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:\\") != - L"\\\\?\\X:\\") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"\\\\.\\X:\\\"" << std::endl; - res = false; - } - - if (kwsys::SystemTools::ConvertToWindowsExtendedPath("NUL") != - L"\\\\.\\NUL") { - std::cerr << "Problem with ConvertToWindowsExtendedPath " - << "\"NUL\"" << std::endl; - res = false; - } - -#endif - if (kwsys::SystemTools::ConvertToWindowsOutputPath( "L://Local Mojo/Hex Power Pack/Iffy Voodoo") != "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") { @@ -679,8 +611,6 @@ static bool CheckStringOperations() return res; } -//---------------------------------------------------------------------------- - static bool CheckPutEnv(const std::string& env, const char* name, const char* value) { @@ -908,7 +838,6 @@ static bool CheckGetLineFromStream() return ret; } -//---------------------------------------------------------------------------- int testSystemTools(int, char* []) { bool res = true; diff --git a/Templates/MSBuild/nasm.props.in b/Templates/MSBuild/nasm.props.in new file mode 100644 index 000000000..3443108d1 --- /dev/null +++ b/Templates/MSBuild/nasm.props.in @@ -0,0 +1,17 @@ + + + + Midl + CustomBuild + + + + $(IntDir)%(FileName).obj + 0 + @CMAKE_ASM_NASM_COMPILER@ + 0 + "%(CompilerNasm)" [AllOptions] [AdditionalOptions] "%(FullPath)" + Assembling %(Filename)%(Extension) + + + diff --git a/Templates/MSBuild/nasm.targets b/Templates/MSBuild/nasm.targets new file mode 100644 index 000000000..eeeb613b6 --- /dev/null +++ b/Templates/MSBuild/nasm.targets @@ -0,0 +1,41 @@ + + + + + + _NASM + + + + + $(ComputeLinkInputsTargets); + ComputeNASMOutput; + + + $(ComputeLibInputsTargets); + ComputeNASMOutput; + + + + $(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml + + + + + + + + @(NASM, '|') + + + + + + + + + + + + + diff --git a/Templates/MSBuild/nasm.xml b/Templates/MSBuild/nasm.xml new file mode 100644 index 000000000..92f8548c3 --- /dev/null +++ b/Templates/MSBuild/nasm.xml @@ -0,0 +1,110 @@ + + + + + + + + + + General + + + + + Preprocessing Options + + + + + Assembler Options + + + + + Advanced + + + + + Command Line + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Execute Before + + + Specifies the targets for the build customization to run before. + + + + + + + + + + + Execute After + + + Specifies the targets for the build customization to run after. + + + + + + + + + + + + + Additional Options + + + Additional Options + + + + + + + diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in index ecf6fa14e..bf61be4c9 100644 --- a/Templates/TestDriver.cxx.in +++ b/Templates/TestDriver.cxx.in @@ -32,15 +32,15 @@ static functionMapEntry cmakeGeneratedFunctionMapEntries[] = { { NULL, NULL } /* NOLINT */ }; -static const int NumTests = - (sizeof(cmakeGeneratedFunctionMapEntries) / sizeof(functionMapEntry)) - 1; +static const int NumTests = CM_CAST(int, + sizeof(cmakeGeneratedFunctionMapEntries) / sizeof(functionMapEntry)) - 1; /* Allocate and create a lowercased copy of string (note that it has to be free'd manually) */ static char* lowercase(const char* string) { char *new_string, *p; - size_t stringSize = 0; + size_t stringSize; stringSize = CM_CAST(size_t, strlen(string) + 1); new_string = CM_CAST(char*, malloc(sizeof(char) * stringSize)); diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt index 9b48b143d..11978dbf8 100644 --- a/Tests/BuildDepends/CMakeLists.txt +++ b/Tests/BuildDepends/CMakeLists.txt @@ -42,7 +42,7 @@ list(APPEND _cmake_options "-DTEST_LINK_DEPENDS=${TEST_LINK_DEPENDS}") list(APPEND _cmake_options "-DCMAKE_FORCE_DEPFILES=1") -if(NOT CMAKE_GENERATOR MATCHES "Visual Studio ([^789]|[789][0-9])") +if(NOT CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])") set(TEST_MULTI3 1) list(APPEND _cmake_options "-DTEST_MULTI3=1") endif() diff --git a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt index 555a08f0a..5096a58bf 100644 --- a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt +++ b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt @@ -1,45 +1,65 @@ cmake_minimum_required(VERSION 3.0) +cmake_policy(SET CMP0057 NEW) project(target_compile_features) -if (NOT CMAKE_CXX_COMPILE_FEATURES AND NOT CMAKE_C_COMPILE_FEATURES) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_dummy.cpp" - "int main(int,char**) { return 0; }\n" - ) - add_executable(target_compile_features "${CMAKE_CURRENT_BINARY_DIR}/test_dummy.cpp") - return() -endif() - set(CMAKE_VERBOSE_MAKEFILE ON) -if (CMAKE_C_COMPILE_FEATURES) - add_executable(target_compile_features main.c) - target_compile_features(target_compile_features +if (c_restrict IN_LIST CMAKE_C_COMPILE_FEATURES) + add_executable(c_target_compile_features_specific main.c) + target_compile_features(c_target_compile_features_specific PRIVATE c_restrict ) - add_library(lib_restrict lib_restrict.c) - target_compile_features(lib_restrict + add_library(c_lib_restrict_specific lib_restrict.c) + target_compile_features(c_lib_restrict_specific PUBLIC c_restrict ) - add_executable(restrict_user restrict_user.c) - target_link_libraries(restrict_user lib_restrict) + add_executable(c_restrict_user_specific restrict_user.c) + target_link_libraries(c_restrict_user_specific c_lib_restrict_specific) endif() -if (CMAKE_CXX_COMPILE_FEATURES AND ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;") - if (CMAKE_C_COMPILE_FEATURES) - set(target_suffix _cxx) - endif() - add_executable(target_compile_features${target_suffix} main.cpp) - target_compile_features(target_compile_features${target_suffix} +if (c_std_99 IN_LIST CMAKE_C_COMPILE_FEATURES) + add_executable(c_target_compile_features_meta main.c) + target_compile_features(c_target_compile_features_meta + PRIVATE c_std_99 + ) + + add_library(c_lib_restrict_meta lib_restrict.c) + target_compile_features(c_lib_restrict_meta + PUBLIC c_std_99 + ) + + add_executable(c_restrict_user_meta restrict_user.c) + target_link_libraries(c_restrict_user_meta c_lib_restrict_meta) +endif() + +if (cxx_auto_type IN_LIST CMAKE_CXX_COMPILE_FEATURES) + add_executable(cxx_target_compile_features_specific main.cpp) + target_compile_features(cxx_target_compile_features_specific PRIVATE cxx_auto_type ) - add_library(lib_auto_type lib_auto_type.cpp) - target_compile_features(lib_auto_type + add_library(cxx_lib_auto_type_specific lib_auto_type.cpp) + target_compile_features(cxx_lib_auto_type_specific PUBLIC cxx_auto_type ) - add_executable(lib_user lib_user.cpp) - target_link_libraries(lib_user lib_auto_type) + add_executable(cxx_lib_user_specific lib_user.cpp) + target_link_libraries(cxx_lib_user_specific cxx_lib_auto_type_specific) +endif() + +if (cxx_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES) + add_executable(cxx_target_compile_features_meta main.cpp) + target_compile_features(cxx_target_compile_features_meta + PRIVATE cxx_std_11 + ) + + add_library(cxx_lib_auto_type_meta lib_auto_type.cpp) + target_compile_features(cxx_lib_auto_type_meta + PUBLIC cxx_std_11 + ) + + add_executable(cxx_lib_user_meta lib_user.cpp) + target_link_libraries(cxx_lib_user_meta cxx_lib_auto_type_meta) endif() diff --git a/Tests/CMakeCommands/target_compile_features/dummy.cpp b/Tests/CMakeCommands/target_compile_features/dummy.cpp deleted file mode 100644 index e9ad2573b..000000000 --- a/Tests/CMakeCommands/target_compile_features/dummy.cpp +++ /dev/null @@ -1,5 +0,0 @@ - -int main(int, char**) -{ - return 0; -} diff --git a/Tests/CMakeCommands/target_link_libraries/empty.cpp b/Tests/CMakeCommands/target_link_libraries/empty.cpp index ab32cf6c8..a6ecef81f 100644 --- a/Tests/CMakeCommands/target_link_libraries/empty.cpp +++ b/Tests/CMakeCommands/target_link_libraries/empty.cpp @@ -1 +1,3 @@ -// No content +// Solaris needs non-empty content so ensure +// we have at least one symbol +int Solaris_requires_a_symbol_here = 0; diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index d6802052e..d1a1df5ed 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -34,16 +34,6 @@ target_link_libraries(CMakeLibTests CMakeLib) add_executable(testEncoding testEncoding.cxx) target_link_libraries(testEncoding cmsys) -# Xcode 2.x forgets to create the output directory before linking -# the individual architectures. -if(CMAKE_OSX_ARCHITECTURES AND XCODE - AND NOT "${XCODE_VERSION}" MATCHES "^[^12]") - add_custom_command( - TARGET CMakeLibTests - PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}" - ) -endif() - foreach(test ${CMakeLib_TESTS}) add_test(CMakeLib.${test} CMakeLibTests ${test} ${${test}_ARGS}) endforeach() diff --git a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt index c53befcb8..7c84ee166 100644 --- a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt +++ b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt @@ -24,18 +24,3 @@ target_link_libraries(memcheck_fail CMakeLib) # output file. Need to be in their own subdirectory as they have the # same filenames. add_subdirectory(NoLog) - -# Xcode 2.x forgets to create the output directory before linking -# the individual architectures. -if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]") - foreach(t - memcheck_fail - pseudo_BC - pseudo_purify - pseudo_valgrind - ) - add_custom_command(TARGET ${t} - PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}" - ) - endforeach() -endif() diff --git a/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt b/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt index 3a45bfecc..e47b9db39 100644 --- a/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt +++ b/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt @@ -11,12 +11,4 @@ configure_file( foreach(_pseudo IN ITEMS valgrind purify BC) add_executable(pseudonl_${_pseudo} "${CMAKE_CURRENT_BINARY_DIR}/ret0.c") set_target_properties(pseudonl_${_pseudo} PROPERTIES OUTPUT_NAME ${_pseudo}) - - # Xcode 2.x forgets to create the output directory before linking - # the individual architectures. - if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]") - add_custom_command(TARGET pseudonl_${_pseudo} - PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}" - ) - endif() endforeach() diff --git a/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in b/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in index e2cdec89a..b4c6fae44 100644 --- a/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in +++ b/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in @@ -1,5 +1,5 @@ #include -#include +#include "cmsys/Encoding.hxx" #include #define RETVAL @_retval@ diff --git a/Tests/CMakeLib/run_compile_commands.cxx b/Tests/CMakeLib/run_compile_commands.cxx index 5d4ca707a..46431bc33 100644 --- a/Tests/CMakeLib/run_compile_commands.cxx +++ b/Tests/CMakeLib/run_compile_commands.cxx @@ -1,6 +1,6 @@ #include -#include +#include "cmsys/FStream.hxx" #include #include #include diff --git a/Tests/CMakeLib/testEncoding.cxx b/Tests/CMakeLib/testEncoding.cxx index 88743b08e..5e40638f7 100644 --- a/Tests/CMakeLib/testEncoding.cxx +++ b/Tests/CMakeLib/testEncoding.cxx @@ -1,8 +1,10 @@ -#include +#include "cmsys/FStream.hxx" #include #include -#include +#ifdef _WIN32 +#include "cmsys/ConsoleBuf.hxx" +#endif #ifdef _WIN32 void setEncoding(cmsys::ConsoleBuf::Manager& buf, UINT codepage) @@ -37,7 +39,7 @@ int main(int argc, char* argv[]) setEncoding(consoleOut, CP_OEMCP); } // else AUTO #endif - std::ifstream file(argv[2]); + cmsys::ifstream file(argv[2]); if (!file.is_open()) { std::cout << "Failed to open file: " << argv[2] << std::endl; return 2; diff --git a/Tests/CMakeLib/testRST.cxx b/Tests/CMakeLib/testRST.cxx index e1b0903e6..889127650 100644 --- a/Tests/CMakeLib/testRST.cxx +++ b/Tests/CMakeLib/testRST.cxx @@ -3,7 +3,7 @@ #include "cmRST.h" #include "cmSystemTools.h" -#include +#include "cmsys/FStream.hxx" #include #include diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 4945b3181..d16df1cf5 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1,6 +1,9 @@ # a macro for tests that have a simple format where the name matches the # directory and project -macro(ADD_TEST_MACRO NAME COMMAND) +macro(ADD_TEST_MACRO NAME) + if(${ARGC} GREATER 1) + set(_test_command --test-command ${ARGN}) + endif() string(REPLACE "." "/" dir "${NAME}") string(REGEX REPLACE "[^.]*\\." "" proj "${NAME}") add_test(NAME "${NAME}" COMMAND "${CMAKE_CTEST_COMMAND}" @@ -13,7 +16,8 @@ macro(ADD_TEST_MACRO NAME COMMAND) ${${NAME}_CTEST_OPTIONS} --build-options ${build_options} ${${NAME}_BUILD_OPTIONS} - --test-command ${COMMAND} ${ARGN}) + ${_test_command}) + unset(_test_command) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${dir}") endmacro() @@ -46,7 +50,7 @@ if(BUILD_TESTING) set(CMake_TEST_DEVENV "") if(CMAKE_VS_DEVENV_COMMAND) set(CMake_TEST_DEVENV "${CMAKE_VS_DEVENV_COMMAND}") - elseif(CMAKE_GENERATOR MATCHES "Visual Studio [7-9] " AND + elseif(CMAKE_GENERATOR MATCHES "Visual Studio [89] " AND NOT CMAKE_MAKE_PROGRAM MATCHES "[mM][sS][bB][uU][iI][lL][dD]\\.[eE][xX][eE]") set(CMake_TEST_DEVENV "${CMAKE_MAKE_PROGRAM}") endif() @@ -271,7 +275,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(SystemInformation SystemInformation) ADD_TEST_MACRO(MathTest MathTest) ADD_TEST_MACRO(CompileFeatures CompileFeatures) - ADD_TEST_MACRO(CMakeCommands.target_compile_features target_compile_features) + ADD_TEST_MACRO(CMakeCommands.target_compile_features) if(CMake_TEST_RESOURCES) ADD_TEST_MACRO(VSResource VSResource) @@ -325,8 +329,9 @@ if(BUILD_TESTING) endif() endif() - if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^789]|[789][0-9])") + if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])") ADD_TEST_MACRO(CSharpOnly CSharpOnly) + ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx) endif() ADD_TEST_MACRO(COnly COnly) @@ -477,6 +482,17 @@ if(BUILD_TESTING) ADD_TEST_MACRO(Module.CheckTypeSize CheckTypeSize) + set(Module.CheckIPOSupported-C_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_C=${CMake_TEST_IPO_WORKS_C}) + ADD_TEST_MACRO(Module.CheckIPOSupported-C CheckIPOSupported-C) + + set(Module.CheckIPOSupported-CXX_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_CXX=${CMake_TEST_IPO_WORKS_CXX}) + ADD_TEST_MACRO(Module.CheckIPOSupported-CXX CheckIPOSupported-CXX) + + if(CMAKE_Fortran_COMPILER) + set(Module.CheckIPOSupported-Fortran_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_Fortran=${CMake_TEST_IPO_WORKS_Fortran}) + ADD_TEST_MACRO(Module.CheckIPOSupported-Fortran CheckIPOSupported-Fortran) + endif() + add_test(Module.ExternalData ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/Module/ExternalData" @@ -615,8 +631,8 @@ if(BUILD_TESTING) endif() # test for correct sub-project generation - # not implemented in VS 7.0, Xcode, or Ninja - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio 7$|Xcode|Ninja") + # not implemented in Xcode or Ninja + if(NOT CMAKE_GENERATOR MATCHES "Xcode|Ninja") # run cmake and configure all of SubProject # but only build the independent executable car add_test(SubProject ${CMAKE_CTEST_COMMAND} @@ -1158,6 +1174,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CMakeTestAllGenerators") + # This test runs a lot of processes. Do not make them compete + # for resources with other tests. + set_property(TEST CMakeTestAllGenerators PROPERTY RUN_SERIAL 1) endif() if(NOT DEFINED CTEST_RUN_CMakeTestMultipleConfigures) @@ -1371,12 +1390,17 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindBZip2) endif() + if(CMake_TEST_FindDoxygen) + add_subdirectory(FindDoxygen) + endif() + if(CMake_TEST_FindGSL) add_subdirectory(FindGSL) endif() if(CMake_TEST_FindGTest) add_subdirectory(FindGTest) + add_subdirectory(GoogleTest) endif() if(CMake_TEST_FindICU) @@ -1407,14 +1431,26 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindOpenGL) endif() + if(CMake_TEST_FindOpenMP) + add_subdirectory(FindOpenMP) + endif() + if(CMake_TEST_FindOpenSSL) add_subdirectory(FindOpenSSL) endif() + if(CMake_TEST_FindMPI) + add_subdirectory(FindMPI) + endif() + if(CMake_TEST_FindPNG) add_subdirectory(FindPNG) endif() + if(CMake_TEST_FindProtobuf) + add_subdirectory(FindProtobuf) + endif() + if(CMake_TEST_FindTIFF) add_subdirectory(FindTIFF) endif() @@ -1697,6 +1733,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release if(CMake_TEST_XCODE_VERSION AND NOT CMake_TEST_XCODE_VERSION VERSION_LESS 5 AND OSX_VERSION MATCHES "^([0-9]+\\.[0-9]+)") + set(XCTest_CTEST_OPTIONS --build-config $) set(XCTest_BUILD_OPTIONS -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_MATCH_1} -DCMAKE_OSX_SYSROOT=macosx) ADD_TEST_MACRO(XCTest ${CMAKE_CTEST_COMMAND} -C $ -V) endif() @@ -1924,7 +1961,6 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release endif() if(MSVC AND NOT MSVC_VERSION LESS 1310 - AND NOT CMAKE_GENERATOR MATCHES "Visual Studio 7( |$)" AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio [89]( |$)" OR CMAKE_SIZEOF_VOID_P EQUAL 4) ) @@ -1936,7 +1972,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release ADD_TEST_MACRO(SBCS SBCS) endif() - if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio [789]( |$)" + if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio [89]( |$)" AND NOT CMAKE_GENERATOR_TOOLSET) ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx) endif() @@ -2043,7 +2079,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release set(reg_wp81 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\WindowsPhone\\v8.1;InstallationFolder]") select_wince_sdk(reg_wince wince_sdk) set(reg_tegra "[HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;sdkRoot]") - foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra) + set(reg_nasm "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]") + foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra nasm) get_filename_component(r "${reg_${reg}}" ABSOLUTE) if(IS_DIRECTORY "${r}") set(${reg} 1) @@ -2134,6 +2171,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release endif() endif() + if(CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])" AND nasm) + ADD_TEST_MACRO(VSNASM VSNASM) + endif() + if (CMake_TEST_GreenHillsMULTI) macro(add_test_GhsMulti name primaryTarget bspName) add_test(NAME GhsMulti.${name} COMMAND ${CMAKE_CTEST_COMMAND} @@ -3074,6 +3115,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release endif () endif () + if(CMake_TEST_EXTERNAL_CMAKE) + set(CMAKE_SKIP_BOOTSTRAP_TEST 1) + endif() if("${CMAKE_GENERATOR}" MATCHES Xcode) set(CMAKE_SKIP_BOOTSTRAP_TEST 1) endif() diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt index 8f842d6f5..443d366c4 100644 --- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt +++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt @@ -1,10 +1,6 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required(VERSION 2.8.4) # new enough for CMP0017 project(AllFindModules) -if (POLICY CMP0017) - cmake_policy(SET CMP0017 NEW) -endif () - # Avoid ctest truncation of output message(STATUS "CTEST_FULL_OUTPUT") @@ -56,7 +52,10 @@ if (NOT QT4_FOUND) endif () macro(check_version_string MODULE_NAME VERSION_VAR) - if (${MODULE_NAME}_FOUND) + string(FIND " ${CMake_TEST_CMakeOnly.AllFindModules_NO_VERSION} " " ${MODULE_NAME} " _exclude_pos) + if (NOT _exclude_pos EQUAL -1) + message(STATUS "excluding check of ${VERSION_VAR}='${${VERSION_VAR}}' due to local configuration") + elseif (${MODULE_NAME}_FOUND) if (DEFINED ${VERSION_VAR}) message(STATUS "${VERSION_VAR}='${${VERSION_VAR}}'") if (NOT ${VERSION_VAR} MATCHES "^[0-9]") diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index c692cbd58..c84fa748c 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -9,7 +9,14 @@ macro(add_CMakeOnly_test test) endmacro() add_CMakeOnly_test(LinkInterfaceLoop) -set_property(TEST CMakeOnly.LinkInterfaceLoop PROPERTY TIMEOUT 90) +# If a bug is introduced in CMake that causes an infinite loop while +# analyzing LinkInterfaceLoop then don't let the test run too long. +# Use an option to customize it so that the timeout can be extended +# on busy machines. +if(NOT DEFINED CMake_TEST_CMakeOnly.LinkInterfaceLoop_TIMEOUT) + set(CMake_TEST_CMakeOnly.LinkInterfaceLoop_TIMEOUT 90) +endif() +set_property(TEST CMakeOnly.LinkInterfaceLoop PROPERTY TIMEOUT ${CMake_TEST_CMakeOnly.LinkInterfaceLoop_TIMEOUT}) add_CMakeOnly_test(CheckSymbolExists) @@ -26,11 +33,15 @@ add_CMakeOnly_test(CompilerIdCXX) if(CMAKE_Fortran_COMPILER) add_CMakeOnly_test(CompilerIdFortran) endif() -if(CMAKE_GENERATOR MATCHES "Visual Studio ([^789]|[789][0-9])") +if(CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])") add_CMakeOnly_test(CompilerIdCSharp) endif() -add_CMakeOnly_test(AllFindModules) +add_test(CMakeOnly.AllFindModules ${CMAKE_CMAKE_COMMAND} + -DTEST=AllFindModules + -DCMAKE_ARGS=-DCMake_TEST_CMakeOnly.AllFindModules_NO_VERSION=${CMake_TEST_CMakeOnly.AllFindModules_NO_VERSION} + -P ${CMAKE_CURRENT_BINARY_DIR}/Test.cmake + ) add_CMakeOnly_test(SelectLibraryConfigurations) diff --git a/Tests/CMakeOnly/find_library/CMakeLists.txt b/Tests/CMakeOnly/find_library/CMakeLists.txt index 995865068..fe3815edd 100644 --- a/Tests/CMakeOnly/find_library/CMakeLists.txt +++ b/Tests/CMakeOnly/find_library/CMakeLists.txt @@ -24,7 +24,7 @@ endmacro() macro(test_find_library_subst expected) get_filename_component(dir ${expected} PATH) get_filename_component(name ${expected} NAME) - string(REGEX REPLACE "lib/?64" "lib" dir "${dir}") + string(REGEX REPLACE "lib/?[36Xx][24Y3][Z2]*" "lib" dir "${dir}") test_find_library(", searched as ${dir}" "${expected}" NAMES ${name} PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${dir} @@ -33,9 +33,11 @@ endmacro() set(CMAKE_FIND_LIBRARY_PREFIXES "lib") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") +set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS TRUE) set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE) set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE) +set(CMAKE_INTERNAL_PLATFORM_ABI "ELF") set(CMAKE_SIZEOF_VOID_P 4) foreach(lib lib/32/libtest5.a @@ -67,6 +69,20 @@ foreach(lib64 test_find_library_subst(${lib64}) endforeach() +set(CMAKE_INTERNAL_PLATFORM_ABI "ELF X32") +set(CMAKE_SIZEOF_VOID_P 4) +foreach(libx32 + lib/x32/libtest2.a + lib/A/libx32/libtest3.a + lib/libtest3.a + libx32/A/lib/libtest2.a + libx32/A/libx32/libtest1.a + libx32/A/libtest1.a + libx32/libtest1.a + ) + test_find_library_subst(${libx32}) +endforeach() + test_find_library("" A/libtestA.a NAMES testA testB PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B @@ -79,3 +95,16 @@ test_find_library("" A/libtestA.a NAMES testB testA NAMES_PER_DIR PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B ) + +set(CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX "XYZ") +foreach(libXYZ + lib/XYZ/libtest1.a + lib/A/libXYZ/libtest2.a + lib/libtest3.a + libXYZ/A/lib/libtest4.a + libXYZ/A/libXYZ/libtest5.a + libXYZ/A/libtest6.a + libXYZ/libtest7.a + ) + test_find_library_subst(${libXYZ}) +endforeach() diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/lib/A/libXYZ/libtest2.a similarity index 100% rename from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake rename to Tests/CMakeOnly/find_library/lib/A/libXYZ/libtest2.a diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON.cmake b/Tests/CMakeOnly/find_library/lib/A/libx32/libtest3.a similarity index 100% rename from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON.cmake rename to Tests/CMakeOnly/find_library/lib/A/libx32/libtest3.a diff --git a/Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a b/Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/lib/x32/libtest2.a b/Tests/CMakeOnly/find_library/lib/x32/libtest2.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a b/Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a b/Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a b/Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libXYZ/libtest7.a b/Tests/CMakeOnly/find_library/libXYZ/libtest7.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a b/Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libx32/A/libtest1.a b/Tests/CMakeOnly/find_library/libx32/A/libtest1.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a b/Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeOnly/find_library/libx32/libtest1.a b/Tests/CMakeOnly/find_library/libx32/libtest1.a new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/CMakeTestAllGenerators/RunCMake.cmake b/Tests/CMakeTestAllGenerators/RunCMake.cmake index 6d27d3be1..bfbb3a59f 100644 --- a/Tests/CMakeTestAllGenerators/RunCMake.cmake +++ b/Tests/CMakeTestAllGenerators/RunCMake.cmake @@ -9,42 +9,23 @@ endif() # Analyze 'cmake --help' output for list of available generators: # execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${dir}) -execute_process(COMMAND ${CMAKE_COMMAND} --help +execute_process(COMMAND ${CMAKE_COMMAND} -E capabilities RESULT_VARIABLE result OUTPUT_VARIABLE stdout ERROR_VARIABLE stderr WORKING_DIRECTORY ${dir}) -string(REPLACE ";" "\\;" stdout "${stdout}") -string(REPLACE "\n" "E;" stdout "${stdout}") - -set(collecting 0) set(generators) -foreach(eline ${stdout}) - string(REGEX REPLACE "^(.*)E$" "\\1" line "${eline}") - if(collecting AND NOT line STREQUAL "") - if(line MATCHES "=") - string(REGEX REPLACE "^ (.+)= (.*)$" "\\1" gen "${line}") - if(gen MATCHES "[A-Za-z]") - string(REGEX REPLACE "^(.*[^ ]) +$" "\\1" gen "${gen}") - if(gen) - set(generators ${generators} ${gen}) - endif() - endif() - else() - if(line MATCHES "^ [A-Za-z0-9]") - string(REGEX REPLACE "^ (.+)$" "\\1" gen "${line}") - string(REGEX REPLACE "^(.*[^ ]) +$" "\\1" gen "${gen}") - if(gen) - set(generators ${generators} ${gen}) - endif() - endif() +string(REGEX MATCHALL [["name":"[^"]+","platformSupport"]] generators_json "${stdout}") +foreach(gen_json IN LISTS generators_json) + if("${gen_json}" MATCHES [["name":"([^"]+)"]]) + set(gen "${CMAKE_MATCH_1}") + if(NOT gen MATCHES " (Win64|IA64|ARM)$") + list(APPEND generators "${gen}") endif() endif() - if(line STREQUAL "The following generators are available on this platform:") - set(collecting 1) - endif() endforeach() +list(REMOVE_DUPLICATES generators) # Also call with one non-existent generator: # @@ -60,28 +41,6 @@ message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") message(STATUS "CMake generators='${generators}'") -# If we'll be testing any of the MinGW Makefiles generators, adjust the -# ENV{PATH} to make sure libgmp-10.dll can be loaded as needed. But only if -# the testing machine has a default MinGW install... (If you have a -# non-default install, append to the PATH before running the test...) -# -if(generators MATCHES "MinGW Makefiles") - if(EXISTS "C:/MinGW/bin/libgmp-10.dll") - string(TOLOWER "$ENV{PATH}" path) - if(NOT path MATCHES "/mingw/bin") - if(UNIX) - set(sep ":") - set(mingw_bin "/mingw/bin") - else() - set(sep ";") - set(mingw_bin "C:/MinGW/bin") - endif() - set(ENV{PATH} "$ENV{PATH}${sep}${mingw_bin}") - message(STATUS "info: appending '${sep}${mingw_bin}' to the PATH") - endif() - endif() -endif() - # First setup a source tree to run CMake on. # execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index d5524c3ca..161908114 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -19,7 +19,6 @@ AddCMakeTest(GetFilenameComponentRealpath "") AddCMakeTest(Version "") AddCMakeTest(Message "") AddCMakeTest(File "") -AddCMakeTest(SeparateArguments "") AddCMakeTest(ImplicitLinkInfo "") AddCMakeTest(ModuleNotices "") AddCMakeTest(GetProperty "") @@ -53,10 +52,7 @@ set(EndStuff_PreArgs ) AddCMakeTest(EndStuff "${EndStuff_PreArgs}") -set(GetPrerequisites_PreArgs - "-DCTEST_CONFIGURATION_TYPE:STRING=\\\${CTEST_CONFIGURATION_TYPE}" - ) -AddCMakeTest(GetPrerequisites "${GetPrerequisites_PreArgs}") +AddCMakeTest(GetPrerequisites "-DConfiguration:STRING=$") if(GIT_EXECUTABLE) set(PolicyCheck_PreArgs diff --git a/Tests/CMakeTests/CompilerIdVendorTest.cmake.in b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in index 68f646212..9cf5321f2 100644 --- a/Tests/CMakeTests/CompilerIdVendorTest.cmake.in +++ b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in @@ -8,7 +8,6 @@ file(MAKE_DIRECTORY ${MY_BINARY_DIR}) set(CMAKE_MyLang_COMPILER ${CMAKE_COMMAND}) set(CMAKE_MyLang_COMPILER_ID_ARG1) -set(CMAKE_MyLang_COMPILER_ID_FLAGS_LIST) set(CMAKE_MyLang_COMPILER_ID_DIR ${MY_BINARY_DIR}) file(WRITE "${MY_BINARY_DIR}/BogusVendor.cmake" "message(\"This is a BogusVendor compiler\")") @@ -22,7 +21,8 @@ set(CMAKE_MyLang_COMPILER_ID_VENDOR_FLAGS_MyVendor -P MyVendor.cmake) set(CMAKE_MyLang_COMPILER_ID_VENDOR_REGEX_MyVendor MyVendor) set(CMAKE_BINARY_DIR ${MY_BINARY_DIR}) -cmake_determine_compiler_id_vendor(MyLang) +set(userflags) +cmake_determine_compiler_id_vendor(MyLang "${userflags}") if("${CMAKE_MyLang_COMPILER_ID}" STREQUAL "MyVendor") message(STATUS "Found MyVendor compiler id!") diff --git a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in index 4a47c0695..64b45ed4a 100644 --- a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in @@ -1,4 +1,7 @@ -set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") + set(slash /) +endif() +set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") file(DOWNLOAD diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in index 83ade2ba7..f6d9ad99b 100644 --- a/Tests/CMakeTests/FileDownloadTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadTest.cmake.in @@ -1,4 +1,7 @@ -set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") + set(slash /) +endif() +set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") message(STATUS "FileDownload:1") diff --git a/Tests/CMakeTests/FileUploadTest.cmake.in b/Tests/CMakeTests/FileUploadTest.cmake.in index 8577aefd2..9e2290988 100644 --- a/Tests/CMakeTests/FileUploadTest.cmake.in +++ b/Tests/CMakeTests/FileUploadTest.cmake.in @@ -10,7 +10,10 @@ endif() file(MAKE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/uploads") set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") -set(urlbase "file://@CMAKE_CURRENT_BINARY_DIR@/uploads") +if(NOT "@CMAKE_CURRENT_BINARY_DIR@" MATCHES "^/") + set(slash /) +endif() +set(urlbase "file://${slash}@CMAKE_CURRENT_BINARY_DIR@/uploads") message(STATUS "FileUpload:1") file(UPLOAD diff --git a/Tests/CMakeTests/GetPrerequisitesTest.cmake.in b/Tests/CMakeTests/GetPrerequisitesTest.cmake.in index 89ca735d3..7325b879d 100644 --- a/Tests/CMakeTests/GetPrerequisitesTest.cmake.in +++ b/Tests/CMakeTests/GetPrerequisitesTest.cmake.in @@ -2,18 +2,15 @@ # include(GetPrerequisites) -set(CMAKE_BUILD_TYPE "@CMAKE_BUILD_TYPE@") -set(CMAKE_CONFIGURATION_TYPES "@CMAKE_CONFIGURATION_TYPES@") set(CMAKE_EXECUTABLE_SUFFIX "@CMAKE_EXECUTABLE_SUFFIX@") message(STATUS "=============================================================================") message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") message(STATUS "") -message(STATUS "CMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}'") -message(STATUS "CMAKE_CONFIGURATION_TYPES='${CMAKE_CONFIGURATION_TYPES}'") +message(STATUS "Configuration '${Configuration}'") +message(STATUS "CMAKE_COMMAND='${CMAKE_COMMAND}'") message(STATUS "CMAKE_EXECUTABLE_SUFFIX='${CMAKE_EXECUTABLE_SUFFIX}'") -message(STATUS "CTEST_CONFIGURATION_TYPE='${CTEST_CONFIGURATION_TYPE}'") message(STATUS "") diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index 58e2bf969..d7d881e79 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -7,19 +7,19 @@ include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake) # gcc dummy.c -v set(linux64_gcc_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../.. -L/usr/lib/x86_64-linux-gnu /tmp/ccEO9iux.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crtn.o") -set(linux64_gcc_libs "c") +set(linux64_gcc_libs "gcc;gcc_s;c;gcc;gcc_s") set(linux64_gcc_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu") list(APPEND platforms linux64_gcc) # g++ dummy.cxx -v set(linux64_g++_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../.. -L/usr/lib/x86_64-linux-gnu /tmp/ccalRBlq.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crtn.o") -set(linux64_g++_libs "stdc++;m;c") +set(linux64_g++_libs "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") set(linux64_g++_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu") list(APPEND platforms linux64_g++) # f95 dummy.f -v set(linux64_f95_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../.. -L/usr/lib/x86_64-linux-gnu /tmp/ccAVcN7N.o -lgfortranbegin -lgfortran -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crtn.o") -set(linux64_f95_libs "gfortranbegin;gfortran;m;c") +set(linux64_f95_libs "gfortranbegin;gfortran;m;gcc_s;gcc;c;gcc_s;gcc") set(linux64_f95_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu") list(APPEND platforms linux64_f95) @@ -43,43 +43,43 @@ list(APPEND platforms linux64_sunf90) # icc dummy.c -v set(linux64_icc_text "ld /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/iccBP8OfN.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib -Bstatic -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -ldecimal -lirc -Bdynamic -lgcc_s -lgcc -Bstatic -lirc -Bdynamic -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o") -set(linux64_icc_libs "imf;svml;m;ipgo;decimal;irc;irc;c;irc_s;dl;c") +set(linux64_icc_libs "imf;svml;m;ipgo;decimal;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c") set(linux64_icc_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib") list(APPEND platforms linux64_icc) # icxx dummy.cxx -v set(linux64_icxx_text "ld /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/icpc270GoT.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib -Bstatic -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -ldecimal -Bdynamic -lstdc++ -Bstatic -lirc -Bdynamic -lgcc_s -lgcc -Bstatic -lirc -Bdynamic -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o") -set(linux64_icxx_libs "imf;svml;m;ipgo;decimal;stdc++;irc;irc;c;irc_s;dl;c") +set(linux64_icxx_libs "imf;svml;m;ipgo;decimal;stdc++;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c") set(linux64_icxx_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib") list(APPEND platforms linux64_icxx) # ifort dummy.f -v set(linux64_ifort_text "ld --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o /opt/compiler/intel/compiler/11.0/lib/intel64/for_main.o dum.cxx -Bstatic -lifport -lifcore -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -lirc -Bdynamic -lpthread -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o") -set(linux64_ifort_libs "ifport;ifcore;imf;svml;m;ipgo;irc;pthread;c;irc_s;dl;c") +set(linux64_ifort_libs "ifport;ifcore;imf;svml;m;ipgo;irc;pthread;c;gcc_s;gcc;irc_s;dl;c") set(linux64_ifort_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib") list(APPEND platforms linux64_ifort) # pgcc dummy.c -v set(linux64_pgcc_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgcc7OscXa5ur7Zk.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o") -set(linux64_pgcc_libs "nspgc;pgc;m;c") +set(linux64_pgcc_libs "nspgc;pgc;m;gcc;c;gcc") set(linux64_pgcc_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2") list(APPEND platforms linux64_pgcc) # pgCC dummy.cxx -v set(linux64_pgCC_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgCCFhjcDt1fs1Ki.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lstd -lC -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o") -set(linux64_pgCC_libs "std;C;nspgc;pgc;m;c") +set(linux64_pgCC_libs "std;C;nspgc;pgc;m;gcc;c;gcc") set(linux64_pgCC_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2") list(APPEND platforms linux64_pgCC) # pgf90 dummy.f -v set(linux64_pgf90_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o /opt/compiler/pgi/linux86-64/8.0-3/lib/f90main.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgf90QOIc_eB9xY5h.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lpgf90 -lpgf90_rpm1 -lpgf902 -lpgf90rtl -lpgftnrtl -lnspgc -lpgc -lrt -lpthread -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o") -set(linux64_pgf90_libs "pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;nspgc;pgc;rt;pthread;m;c") +set(linux64_pgf90_libs "pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;nspgc;pgc;rt;pthread;m;gcc;c;gcc") set(linux64_pgf90_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2") list(APPEND platforms linux64_pgf90) # nagfor dummy.f -Wl,-v set(linux64_nagfor_text " /usr/libexec/gcc/x86_64-redhat-linux/4.4.5/collect2 --no-add-needed --eh-frame-hdr --build-id -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../.. /usr/local/NAG/lib/f90_init.o /usr/local/NAG/lib/quickfit.o dummy.o -rpath /usr/local/NAG/lib /usr/local/NAG/lib/libf53.so /usr/local/NAG/lib/libf53.a -lm -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crtn.o") -set(linux64_nagfor_libs "/usr/local/NAG/lib/f90_init.o;/usr/local/NAG/lib/quickfit.o;/usr/local/NAG/lib/libf53.a;m;c") +set(linux64_nagfor_libs "/usr/local/NAG/lib/f90_init.o;/usr/local/NAG/lib/quickfit.o;/usr/local/NAG/lib/libf53.a;m;gcc;gcc_s;c;gcc;gcc_s") set(linux64_nagfor_dirs "/usr/lib/gcc/x86_64-redhat-linux/4.4.5;/usr/lib64;/lib64;/usr/lib") set(linux64_nagfor_obj_regex "^/usr/local/NAG/lib") list(APPEND platforms linux64_nagfor) @@ -87,7 +87,7 @@ list(APPEND platforms linux64_nagfor) # absoft dummy.f -X -v set(linux64_absoft_text "collect2 version 4.4.5 (x86-64 Linux/ELF) /usr/bin/ld --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.4.5/crtbegin.o -L/opt/absoft11.1/lib64 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.5 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.5 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../.. /tmp/E3Bii1/dummy.o -v -laf90math -lafio -lamisc -labsoftmain -laf77math -lm -lmv -lpthread -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.4.5/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crtn.o") -set(linux64_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;pthread;c") +set(linux64_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;pthread;gcc;gcc_s;c;gcc;gcc_s") set(linux64_absoft_dirs "/opt/absoft11.1/lib64;/usr/lib/gcc/x86_64-linux-gnu/4.4.5;/usr/lib;/lib") list(APPEND platforms linux64_absoft) @@ -108,13 +108,13 @@ list(APPEND platforms linux64_test2) # -specs=redhat-hardened-ld set(linux64_test3_text "COLLECT_GCC_OPTIONS='-specs=/usr/lib/rpm/redhat/redhat-hardened-ld' '-v' '-O2' '-g' '-pipe' '-Wall' '-Werror=format-security' '-fexceptions' '-fstack-protector-strong' '--param' 'ssp-buffer-size=4' '-grecord-gcc-switches' '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' '-m64' '-mtune=generic' '-I' '/usr/lib64/gfortran/modules' '-o' 'a.out' '-rdynamic' '-shared-libgcc' '-march=x86-64' '-pie' /usr/libexec/gcc/x86_64-redhat-linux/5.1.1/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/5.1.1/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/5.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccNzxFD8.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lquadmath -plugin-opt=-pass-through=-lm -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z now -pie -o a.out /usr/lib/gcc/x86_64-redhat-linux/5.1.1/../../../../lib64/Scrt1.o /usr/lib/gcc/x86_64-redhat-linux/5.1.1/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/5.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-redhat-linux/5.1.1 -L/usr/lib/gcc/x86_64-redhat-linux/5.1.1/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/5.1.1/../../.. -z relro dummy.o -lgfortran -lm -lgcc_s -lgcc -lquadmath -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/5.1.1/crtendS.o /usr/lib/gcc/x86_64-redhat-linux/5.1.1/../../../../lib64/crtn.o") -set(linux64_test3_libs "gfortran;m;quadmath;m;c") +set(linux64_test3_libs "gfortran;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc") set(linux64_test3_dirs "/usr/lib/gcc/x86_64-redhat-linux/5.1.1;/usr/lib64;/lib64;/usr/lib") list(APPEND platforms linux64_test3) # clang -fsanitize=memory set(linux64_clang_sanitize_memory_text [[ "/usr/bin/ld" --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../.. -L/usr/lib/llvm-3.8/bin/../lib -L/lib -L/usr/lib -whole-archive /usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/lib/linux/libclang_rt.msan-x86_64.a -no-whole-archive --dynamic-list=/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/lib/linux/libclang_rt.msan-x86_64.a.syms /tmp/dummy-27898d.o --no-as-needed -lpthread -lrt -lm -ldl -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crtn.o]]) -set(linux64_clang_sanitize_memory_libs "pthread;rt;m;dl;c") +set(linux64_clang_sanitize_memory_libs "pthread;rt;m;dl;gcc;gcc_s;c;gcc;gcc_s") set(linux64_clang_sanitize_memory_dirs "/usr/lib/gcc/x86_64-linux-gnu/5.4.0;/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu;/lib64;/usr/lib;/usr/lib/llvm-3.8/lib;/lib") list(APPEND platforms linux64_clang_sanitize_memory) @@ -137,14 +137,14 @@ Library search paths: Framework search paths: /Library/Frameworks/ /System/Library/Frameworks/") -set(mac_i686_gcc_Wlv_libs "") +set(mac_i686_gcc_Wlv_libs "gcc") set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_i686_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gcc_Wlv) # gcc -arch i686 dummy.c -v set(mac_i686_gcc_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem") -set(mac_i686_gcc_libs "") +set(mac_i686_gcc_libs "gcc") set(mac_i686_gcc_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_gcc) @@ -164,14 +164,14 @@ Library search paths: Framework search paths: /Library/Frameworks/ /System/Library/Frameworks/") -set(mac_i686_g++_Wlv_libs "stdc++") +set(mac_i686_g++_Wlv_libs "stdc++;gcc") set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_i686_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_g++_Wlv) # g++ -arch i686 dummy.cxx -v set(mac_i686_g++_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem") -set(mac_i686_g++_libs "stdc++") +set(mac_i686_g++_libs "stdc++;gcc") set(mac_i686_g++_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_g++) @@ -188,14 +188,14 @@ Library search paths: Framework search paths: /Library/Frameworks/ /System/Library/Frameworks/") -set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran") +set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc") set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib") set(mac_i686_gfortran_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gfortran_Wlv) # gfortran dummy.f -v set(mac_i686_gfortran_text " /usr/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/lib/gcc -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//ccgqbX5P.o -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem") -set(mac_i686_gfortran_libs "gfortranbegin;gfortran") +set(mac_i686_gfortran_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc") set(mac_i686_gfortran_dirs "/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/lib/gcc;/usr/lib") list(APPEND platforms mac_i686_gfortran) @@ -215,14 +215,14 @@ Library search paths: Framework search paths: /Library/Frameworks/ /System/Library/Frameworks/") -set(mac_ppc_gcc_Wlv_libs "") +set(mac_ppc_gcc_Wlv_libs "gcc") set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_ppc_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_gcc_Wlv) # gcc -arch ppc dummy.c -v set(mac_ppc_gcc_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccdcolsP.o -lgcc -lSystemStubs -lSystem") -set(mac_ppc_gcc_libs "") +set(mac_ppc_gcc_libs "gcc") set(mac_ppc_gcc_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_ppc_gcc) @@ -242,14 +242,14 @@ Library search paths: Framework search paths: /Library/Frameworks/ /System/Library/Frameworks/") -set(mac_ppc_g++_Wlv_libs "stdc++") +set(mac_ppc_g++_Wlv_libs "stdc++;gcc") set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_ppc_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_g++_Wlv) # g++ -arch ppc dummy.cxx -v set(mac_ppc_g++_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccbjB6Lj.o -lstdc++ -lgcc -lSystemStubs -lSystem") -set(mac_ppc_g++_libs "stdc++") +set(mac_ppc_g++_libs "stdc++;gcc") set(mac_ppc_g++_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_ppc_g++) @@ -257,7 +257,7 @@ list(APPEND platforms mac_ppc_g++) set(mac_absoft_text "collect2 version 4.2.1 (Apple Inc. build 5664) (i686 Darwin) /usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld -dynamic -arch i386 -macosx_version_min 10.6.6 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/Applications/Absoft11.1/lib -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/folders/04/04+Djjm8GZWBmuEdp2Gsw++++TM/-Tmp-//bTAoJc/dummy.o -v -Y 10 -laf90math -lafio -lamisc -labsoftmain -laf77math -lm -lmv -lSystem -lgcc -lSystem ") -set(mac_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv") +set(mac_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;gcc") set(mac_absoft_dirs "/Applications/Absoft11.1/lib;/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_absoft) @@ -485,13 +485,13 @@ list(APPEND platforms irix64_f90_64) # gcc dummy.c -v set(cygwin_gcc_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /home/user/AppData/Local/Temp/cczg1Arh.o -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc") -set(cygwin_gcc_libs "cygwin;user32;kernel32;advapi32;shell32") +set(cygwin_gcc_libs "gcc;cygwin;user32;kernel32;advapi32;shell32;gcc") set(cygwin_gcc_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib") list(APPEND platforms cygwin_gcc) # g++ dummy.cxx -v set(cygwin_g++_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /home/user/AppData/Local/Temp/ccsvcDO6.o -lstdc++ -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc") -set(cygwin_g++_libs "stdc++;cygwin;user32;kernel32;advapi32;shell32") +set(cygwin_g++_libs "stdc++;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc") set(cygwin_g++_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib") list(APPEND platforms cygwin_g++) @@ -499,7 +499,7 @@ list(APPEND platforms cygwin_g++) set(cygwin_gfortran_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe /usr/lib/gcc/i686-pc-cygwin/4.3.2/collect2.exe -Bdynamic --dll-search-prefix=cyg -u ___register_frame_info -u ___deregister_frame_info /usr/lib/gcc/i686-pc-cygwin/4.3.2/../../../crt0.o /usr/lib/gcc/i686-pc-cygwin/4.3.2/crtbegin.o -L/usr/lib/gcc/i686-pc-cygwin/4.3.2 -L/usr/lib/gcc/i686-pc-cygwin/4.3.2 -L/usr/lib/gcc/i686-pc-cygwin/4.3.2/../../.. /home/user/AppData/Local/Temp/ccqRWKWg.o -lgfortranbegin -lgfortran -lgcc_s -lgcc_s -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc_s -lgcc_s -lgcc /usr/lib/gcc/i686-pc-cygwin/4.3.2/crtend.o ") -set(cygwin_gfortran_libs "gfortranbegin;gfortran;cygwin;user32;kernel32;advapi32;shell32") +set(cygwin_gfortran_libs "gfortranbegin;gfortran;gcc_s;gcc_s;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc_s;gcc_s;gcc") set(cygwin_gfortran_dirs "/usr/lib/gcc/i686-pc-cygwin/4.3.2;/usr/lib") list(APPEND platforms cygwin_gfortran) @@ -508,19 +508,19 @@ list(APPEND platforms cygwin_gfortran) # gcc dummy.c -v set(msys_gcc_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/cckQmvRt.o -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtend.o") -set(msys_gcc_libs "mingw32;moldname;mingwex;msvcrt;user32;kernel32;advapi32;shell32;mingw32;moldname;mingwex;msvcrt") +set(msys_gcc_libs "mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex") set(msys_gcc_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib") list(APPEND platforms msys_gcc) # g++ dummy.cxx -v set(msys_g++_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/cci5hYPk.o -lstdc++ -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtend.o") -set(msys_g++_libs "stdc++;mingw32;moldname;mingwex;msvcrt;user32;kernel32;advapi32;shell32;mingw32;moldname;mingwex;msvcrt") +set(msys_g++_libs "stdc++;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex") set(msys_g++_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib") list(APPEND platforms msys_g++) # g77 dummy.f -v set(msys_g77_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/ccabRxQ1.o -lfrtbegin -lg2c -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtend.o") -set(msys_g77_libs "frtbegin;g2c;mingw32;moldname;mingwex;msvcrt;user32;kernel32;advapi32;shell32;mingw32;moldname;mingwex;msvcrt") +set(msys_g77_libs "frtbegin;g2c;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex") set(msys_g77_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib") list(APPEND platforms msys_g77) @@ -532,11 +532,56 @@ set(nvcc_msvc_libs "cudadevrt.lib;cudart_static.lib") set(nvcc_msvc_dirs "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/lib/x64") list(APPEND platforms nvcc_msvc) + +#----------------------------------------------------------------------------- +# PGI on Windows + +# Due to the different behavior of separate_arguments on non-Windows platforms, +# the following tests can only be performed on Windows +if(CMAKE_HOST_WIN32) + +# pgf95 dummy.f90 -v +set(windows_pgf95_text [[Writing to file C:\temp\pgf9510ipeUbTwN2V4pn.lnk +X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib\pgimainmx.obj C:\Program Files\PGICE/win64/17.4/lib\f90main.obj -incremental:no -debug -merge:__nv_module_id=.data -merge:.nvFatBinSegment=.data "-libpath:X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64" -libpath:X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib C:\temp\pgf959hxeUbfMYOLjUz.obj -out:dummy.exe -pdb:./dummy.pdb /DYNAMICBASE:NO -defaultlib:libpgmp -defaultlib:pg -defaultlib:libpgf90rtl -defaultlib:libpgf90 -defaultlib:libpgf90_rpm1 -defaultlib:libpgf902 -defaultlib:libpgf90rtl -defaultlib:libpgftnrtl -nodefaultlib:msvcrt -defaultlib:libvcruntime -defaultlib:libucrt -defaultlib:libcmt -defaultlib:libpgc14 -defaultlib:libnspgc -defaultlib:legacy_stdio_definitions -defaultlib:oldnames + +"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\link.exe" /NOLOGO @C:\temp\pgf9510ipeUbTwN2V4pn.lnk]]) +set(windows_pgf95_startfile "pgimain[mx][xpt]+[.]obj") +set(windows_pgf95_libs "libpgmp;pg;libpgf90rtl;libpgf90;libpgf90_rpm1;libpgf902;libpgf90rtl;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames") +set(windows_pgf95_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib") +list(APPEND platforms windows_pgf95) + +# pgf77 dummy.f77 -v +set(windows_pgf77_text [[Writing to file C:\temp\pgf776eC42buYRoCNJk.lnk +X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib\pgimainmx.obj C:\Program Files\PGICE/win64/17.4/lib\pgfmain.obj -incremental:no -debug -merge:__nv_module_id=.data -merge:.nvFatBinSegment=.data "-libpath:X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64" -libpath:X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib C:\temp\pgf775d842b0tH8AkdP.obj -out:dummy.exe -pdb:./dummy.pdb /DYNAMICBASE:NO -defaultlib:libpgmp -defaultlib:libpgftnrtl -nodefaultlib:msvcrt -defaultlib:libvcruntime -defaultlib:libucrt -defaultlib:libcmt -defaultlib:libpgc14 -defaultlib:libnspgc -defaultlib:legacy_stdio_definitions -defaultlib:oldnames + +"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\link.exe" /NOLOGO @C:\temp\pgf776eC42buYRoCNJk.lnk]]) +set(windows_pgf77_startfile "pgimain[mx][xpt]+[.]obj") +set(windows_pgf77_libs "libpgmp;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames") +set(windows_pgf77_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib") +list(APPEND platforms windows_pgf77) + +# pgcc dummy.c -v +set(windows_pgcc_text [[Writing to file C:\temp\pgcc6esqW26_ZNKyL.lnk +X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib\pgimainmx.obj -incremental:no -debug -merge:__nv_module_id=.data -merge:.nvFatBinSegment=.data "-libpath:X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64" -libpath:X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib C:\temp\pgcc5dcqWgQXeXPWd.obj -out:dummy.exe -pdb:./dummy.pdb /DYNAMICBASE:NO -defaultlib:libpgmp -nodefaultlib:msvcrt -defaultlib:libvcruntime -defaultlib:libucrt -defaultlib:libcmt -defaultlib:libpgc14 -defaultlib:libnspgc -defaultlib:legacy_stdio_definitions -defaultlib:oldnames + +"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\link.exe" /NOLOGO @C:\temp\pgcc6esqW26_ZNKyL.lnk]]) +set(windows_pgcc_startfile "pgimain[mx][xpt]+[.]obj") +set(windows_pgcc_libs "libpgmp;libpgc14;libnspgc;legacy_stdio_definitions;oldnames") +set(windows_pgcc_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib") +list(APPEND platforms windows_pgcc) + +endif() + #----------------------------------------------------------------------------- # Test parsing for all above examples. set(CMAKE_LINKER "not-a-linker[]().*+^$?") foreach(p IN LISTS platforms) + if(DEFINED ${p}_startfile) + set(CMAKE_LINK_STARTFILE "${${p}_startfile}") + else() + unset(CMAKE_LINK_STARTFILE) + endif() cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}") foreach(v libs dirs fwks) diff --git a/Tests/CMakeTests/SeparateArgumentsTest.cmake.in b/Tests/CMakeTests/SeparateArgumentsTest.cmake.in deleted file mode 100644 index 48964b8cb..000000000 --- a/Tests/CMakeTests/SeparateArgumentsTest.cmake.in +++ /dev/null @@ -1,25 +0,0 @@ -set(old_out "a b c") -separate_arguments(old_out) -set(old_exp "a;b;;c") - -set(unix_cmd "a \"b c\" 'd e' \";\" \\ \\'\\\" '\\'' \"\\\"\"") -set(unix_exp "a;b c;d e;\;; '\";';\"") -separate_arguments(unix_out UNIX_COMMAND "${unix_cmd}") - -set(windows_cmd "a \"b c\" 'd e' \";\" \\ \"c:\\windows\\path\\\\\" \\\"") -set(windows_exp "a;b c;'d;e';\;;\\;c:\\windows\\path\\;\"") -separate_arguments(windows_out WINDOWS_COMMAND "${windows_cmd}") - -foreach(mode old unix windows) - if(NOT "${${mode}_out}" STREQUAL "${${mode}_exp}") - message(FATAL_ERROR "separate_arguments ${mode}-style failed. " - "Expected\n [${${mode}_exp}]\nbut got\n [${${mode}_out}]\n") - endif() -endforeach() - -set(nothing) -separate_arguments(nothing) -if(DEFINED nothing) - message(FATAL_ERROR "separate_arguments null-case failed: " - "nothing=[${nothing}]") -endif() diff --git a/Tests/CMakeTests/ToolchainTest.cmake.in b/Tests/CMakeTests/ToolchainTest.cmake.in index 96e7196a5..ea44f42df 100644 --- a/Tests/CMakeTests/ToolchainTest.cmake.in +++ b/Tests/CMakeTests/ToolchainTest.cmake.in @@ -48,7 +48,6 @@ set(CMAKE_SYSTEM_NAME) set(CMAKE_SYSTEM_VERSION) set(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_HOST_SYSTEM) -set(CMAKE_HOST_SYSTEM_NAME) set(CMAKE_HOST_SYSTEM_VERSION) set(CMAKE_HOST_SYSTEM_PROCESSOR) diff --git a/Tests/CPackComponents/CMakeLists.txt b/Tests/CPackComponents/CMakeLists.txt index 3c8ae3524..5b03c9e42 100644 --- a/Tests/CPackComponents/CMakeLists.txt +++ b/Tests/CPackComponents/CMakeLists.txt @@ -79,7 +79,7 @@ set(CPACK_NSIS_MENU_LINKS ) # Suggested default root for end users of the installer: -set(CPACK_NSIS_INSTALL_ROOT "C:\\Program Files\\CMake Tests Install Root") +set(CPACK_NSIS_INSTALL_ROOT "C:/Program Files/CMake Tests Install Root") # Include CPack to introduce the appropriate targets include(CPack) diff --git a/Tests/CSharpLinkToCxx/CMakeLists.txt b/Tests/CSharpLinkToCxx/CMakeLists.txt new file mode 100644 index 000000000..c4269e0be --- /dev/null +++ b/Tests/CSharpLinkToCxx/CMakeLists.txt @@ -0,0 +1,17 @@ +# test if CSharp application correctly links +# to managed C++ binary +cmake_minimum_required(VERSION 3.9) +project (CSharpLinkToCxx CXX CSharp) + +# we have to change the default flags for the +# managed C++ project to build +string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) +string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + +add_library(CLIApp SHARED cli.hpp cli.cpp) + +target_compile_options(CLIApp PRIVATE "/clr") + +add_executable(CSharpLinkToCxx csharp.cs) + +target_link_libraries(CSharpLinkToCxx CLIApp) diff --git a/Tests/CSharpLinkToCxx/cli.cpp b/Tests/CSharpLinkToCxx/cli.cpp new file mode 100644 index 000000000..97ac7246a --- /dev/null +++ b/Tests/CSharpLinkToCxx/cli.cpp @@ -0,0 +1,10 @@ +#include "cli.hpp" + +using namespace System; + +namespace CLIApp { +void MyCli::testMyCli() +{ + Console::WriteLine("#message from CLIApp"); +} +} diff --git a/Tests/CSharpLinkToCxx/cli.hpp b/Tests/CSharpLinkToCxx/cli.hpp new file mode 100644 index 000000000..a8c116d4c --- /dev/null +++ b/Tests/CSharpLinkToCxx/cli.hpp @@ -0,0 +1,10 @@ +#pragma once + +namespace CLIApp { +public +ref class MyCli +{ +public: + void testMyCli(); +}; +} diff --git a/Tests/CSharpLinkToCxx/csharp.cs b/Tests/CSharpLinkToCxx/csharp.cs new file mode 100644 index 000000000..35c5cc3e8 --- /dev/null +++ b/Tests/CSharpLinkToCxx/csharp.cs @@ -0,0 +1,16 @@ +using System; +using CLIApp; + +namespace CSharpLinkToCxx +{ + internal class CSharpLinkToCxx + { + public static void Main(string[] args) + { + Console.WriteLine("#message from CSharpLinkToCxx"); + + var app = new MyCli(); + app.testMyCli(); + } + } +} diff --git a/Tests/CheckFortran.cmake b/Tests/CheckFortran.cmake index 93990ad30..b1652baf1 100644 --- a/Tests/CheckFortran.cmake +++ b/Tests/CheckFortran.cmake @@ -18,6 +18,8 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" execute_process( WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR} + -A "${CMAKE_GENERATOR_PLATFORM}" + -T "${CMAKE_GENERATOR_TOOLSET}" OUTPUT_VARIABLE output ERROR_VARIABLE output RESULT_VARIABLE result diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index 2a307d09c..4a5558d48 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -1,10 +1,11 @@ cmake_minimum_required(VERSION 3.1) +cmake_policy(SET CMP0057 NEW) project(CompileFeatures) macro(run_test feature lang) - if (";${CMAKE_${lang}_COMPILE_FEATURES};" MATCHES ${feature}) + if (${feature} IN_LIST CMAKE_${lang}_COMPILE_FEATURES) add_library(test_${feature} OBJECT ${feature}) set_property(TARGET test_${feature} PROPERTY COMPILE_FEATURES "${feature}" @@ -15,12 +16,13 @@ macro(run_test feature lang) endmacro() get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES) -list(REMOVE_ITEM c_features c_std_90 c_std_99 c_std_11) +list(FILTER c_features EXCLUDE REGEX "^c_std_[0-9][0-9]") foreach(feature ${c_features}) run_test(${feature} C) endforeach() + get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) -list(REMOVE_ITEM cxx_features cxx_std_98 cxx_std_11 cxx_std_14 cxx_std_17) +list(FILTER cxx_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]") foreach(feature ${cxx_features}) run_test(${feature} CXX) endforeach() @@ -171,12 +173,20 @@ if (CMAKE_C_COMPILER_ID STREQUAL "Intel") endif() endif() +if (CMAKE_C_COMPILE_FEATURES) + set(C_expected_features ${CMAKE_C_COMPILE_FEATURES}) + list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]") +endif() +if (CMAKE_CXX_COMPILE_FEATURES) + set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES}) + list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]") +endif () set(C_ext c) set(C_standard_flag 11) set(CXX_ext cpp) set(CXX_standard_flag 14) foreach(lang CXX C) - if (CMAKE_${lang}_COMPILE_FEATURES) + if (${lang}_expected_features) foreach(feature ${${lang}_non_features}) message("Testing feature : ${feature}") try_compile(${feature}_works @@ -198,7 +208,7 @@ foreach(lang CXX C) endif() endforeach() -if (CMAKE_C_COMPILE_FEATURES) +if (C_expected_features) if (CMAKE_C_STANDARD_DEFAULT) string(FIND "${CMAKE_C_FLAGS}" "-std=" std_flag_idx) if (std_flag_idx EQUAL -1) @@ -239,6 +249,16 @@ if (CMAKE_C_COMPILE_FEATURES) EXPECT_C_STATIC_ASSERT=0 ) endif() + elseif (CMAKE_C_COMPILER_ID STREQUAL "SunPro") + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.13) + list(APPEND expected_defs + EXPECT_C_STATIC_ASSERT=1 + ) + else() + list(APPEND expected_defs + EXPECT_C_STATIC_ASSERT=0 + ) + endif() endif() list(APPEND expected_defs @@ -270,7 +290,8 @@ if (CMAKE_CXX_COMPILE_FEATURES) endif () # always add a target "CompileFeatures" -if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;") +if ((NOT CXX_expected_features) OR + (NOT cxx_auto_type IN_LIST CXX_expected_features)) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp" "int main(int,char**) { return 0; }\n" ) diff --git a/Tests/CompileFeatures/default_dialect.c b/Tests/CompileFeatures/default_dialect.c index 0e670957d..4debd9410 100644 --- a/Tests/CompileFeatures/default_dialect.c +++ b/Tests/CompileFeatures/default_dialect.c @@ -11,7 +11,8 @@ #if !DEFAULT_C90 #error Buildsystem error #endif -#if defined(__STDC_VERSION__) +#if defined(__STDC_VERSION__) && \ + !(defined(__SUNPRO_C) && __STDC_VERSION__ == 199409L) #error Unexpected __STDC_VERSION__ definition #endif #endif diff --git a/Tests/Cuda/Complex/CMakeLists.txt b/Tests/Cuda/Complex/CMakeLists.txt index bff7d076d..450ef487c 100644 --- a/Tests/Cuda/Complex/CMakeLists.txt +++ b/Tests/Cuda/Complex/CMakeLists.txt @@ -32,9 +32,17 @@ add_library(CudaComplexSharedLib SHARED dynamic.cu) target_link_libraries(CudaComplexSharedLib PUBLIC CudaComplexCppBase) add_library(CudaComplexMixedLib SHARED mixed.cpp mixed.cu) +set_target_properties(CudaComplexMixedLib + PROPERTIES CUDA_SEPARABLE_COMPILATION ON) target_link_libraries(CudaComplexMixedLib PUBLIC CudaComplexSharedLib PRIVATE CudaComplexSeperableLib) add_executable(CudaComplex main.cpp) target_link_libraries(CudaComplex PUBLIC CudaComplexMixedLib) + +if(APPLE) + # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that + # the static cuda runtime can find it at runtime. + target_link_libraries(CudaComplex PRIVATE -Wl,-rpath,/usr/local/cuda/lib) +endif() diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index 82255c502..a76973d62 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -20,11 +20,50 @@ static __global__ void DetermineIfValidCudaDevice() { } +EXPORT int choose_cuda_device() +{ + int nDevices = 0; + cudaError_t err = cudaGetDeviceCount(&nDevices); + if (err != cudaSuccess) { + std::cerr << "Failed to retrieve the number of CUDA enabled devices" + << std::endl; + return 1; + } + for (int i = 0; i < nDevices; ++i) { + cudaDeviceProp prop; + cudaError_t err = cudaGetDeviceProperties(&prop, i); + if (err != cudaSuccess) { + std::cerr << "Could not retrieve properties from CUDA device " << i + << std::endl; + return 1; + } + if (prop.major >= 3) { + err = cudaSetDevice(i); + if (err != cudaSuccess) { + std::cout << "Could not select CUDA device " << i << std::endl; + } else { + return 0; + } + } + } + + std::cout << "Could not find a CUDA enabled card supporting compute >=3.0" + << std::endl; + + return 1; +} + EXPORT void cuda_dynamic_lib_func() { DetermineIfValidCudaDevice<<<1, 1>>>(); cudaError_t err = cudaGetLastError(); - if (err == cudaSuccess) { - std::cerr << cudaGetErrorString(err) << std::endl; + if (err != cudaSuccess) { + std::cerr << "DetermineIfValidCudaDevice [SYNC] failed: " + << cudaGetErrorString(err) << std::endl; + } + err = cudaDeviceSynchronize(); + if (err != cudaSuccess) { + std::cerr << "DetermineIfValidCudaDevice [ASYNC] failed: " + << cudaGetErrorString(cudaGetLastError()) << std::endl; } } diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu index 7c37d66be..d055b4299 100644 --- a/Tests/Cuda/Complex/file3.cu +++ b/Tests/Cuda/Complex/file3.cu @@ -7,20 +7,42 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -static __global__ void file3_kernel(result_type& r, int x) +static __global__ void file3_kernel(result_type* r, int x) { - r = file1_func(x); + *r = file1_func(x); result_type_dynamic rd = file2_func(x); } int file3_launch_kernel(int x) { - result_type r; + result_type* r; + cudaError_t err = cudaMallocManaged(&r, sizeof(result_type)); + if (err != cudaSuccess) { + std::cerr << "file3_launch_kernel: cudaMallocManaged failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } + file3_kernel<<<1, 1>>>(r, x); - cudaError_t err = cudaGetLastError(); - if (err == cudaSuccess) { - std::cerr << cudaGetErrorString(err) << std::endl; + err = cudaGetLastError(); + if (err != cudaSuccess) { + std::cerr << "file3_kernel [SYNC] failed: " << cudaGetErrorString(err) + << std::endl; + return x; + } + err = cudaDeviceSynchronize(); + if (err != cudaSuccess) { + std::cerr << "file3_kernel [ASYNC] failed: " + << cudaGetErrorString(cudaGetLastError()) << std::endl; + return x; + } + int result = r->sum; + err = cudaFree(r); + if (err != cudaSuccess) { + std::cerr << "file3_launch_kernel: cudaFree failed: " + << cudaGetErrorString(err) << std::endl; return x; } - return r.sum; + + return result; } diff --git a/Tests/Cuda/Complex/main.cpp b/Tests/Cuda/Complex/main.cpp index 5a3f820f4..249823535 100644 --- a/Tests/Cuda/Complex/main.cpp +++ b/Tests/Cuda/Complex/main.cpp @@ -9,12 +9,18 @@ #define IMPORT #endif +IMPORT int choose_cuda_device(); IMPORT int call_cuda_seperable_code(int x); IMPORT int mixed_launch_kernel(int x); int main(int argc, char** argv) { - call_cuda_seperable_code(42); - mixed_launch_kernel(42); - return 0; + int ret = choose_cuda_device(); + if (ret) { + return 0; + } + + int r1 = call_cuda_seperable_code(42); + int r2 = mixed_launch_kernel(42); + return (r1 == 42 || r2 == 42) ? 1 : 0; } diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu index 4bba07cc6..a81ccb731 100644 --- a/Tests/Cuda/Complex/mixed.cu +++ b/Tests/Cuda/Complex/mixed.cu @@ -17,9 +17,9 @@ result_type_dynamic __device__ file2_func(int x); IMPORT void __host__ cuda_dynamic_lib_func(); -static __global__ void mixed_kernel(result_type& r, int x) +static __global__ void mixed_kernel(result_type* r, int x) { - r = file1_func(x); + *r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -27,7 +27,35 @@ EXPORT int mixed_launch_kernel(int x) { cuda_dynamic_lib_func(); - result_type r; + result_type* r; + cudaError_t err = cudaMallocManaged(&r, sizeof(result_type)); + if (err != cudaSuccess) { + std::cerr << "mixed_launch_kernel: cudaMallocManaged failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } + mixed_kernel<<<1, 1>>>(r, x); - return r.sum; + err = cudaGetLastError(); + if (err != cudaSuccess) { + std::cerr << "mixed_kernel [SYNC] failed: " << cudaGetErrorString(err) + << std::endl; + return x; + } + err = cudaDeviceSynchronize(); + if (err != cudaSuccess) { + std::cerr << "mixed_kernel [ASYNC] failed: " + << cudaGetErrorString(cudaGetLastError()) << std::endl; + return x; + } + + int result = r->sum; + err = cudaFree(r); + if (err != cudaSuccess) { + std::cerr << "mixed_launch_kernel: cudaFree failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } + + return result; } diff --git a/Tests/Cuda/ObjectLibrary/CMakeLists.txt b/Tests/Cuda/ObjectLibrary/CMakeLists.txt index cbe1e67fd..1d93be732 100644 --- a/Tests/Cuda/ObjectLibrary/CMakeLists.txt +++ b/Tests/Cuda/ObjectLibrary/CMakeLists.txt @@ -10,3 +10,8 @@ add_library(CudaMixedObjectLib OBJECT static.cu static.cpp) add_executable(CudaObjectLibrary main.cpp $) +if(APPLE) + # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that + # the static cuda runtime can find it at runtime. + target_link_libraries(CudaObjectLibrary PRIVATE -Wl,-rpath,/usr/local/cuda/lib) +endif() diff --git a/Tests/Cuda/ObjectLibrary/main.cpp b/Tests/Cuda/ObjectLibrary/main.cpp index 1a70a9963..4d2f89028 100644 --- a/Tests/Cuda/ObjectLibrary/main.cpp +++ b/Tests/Cuda/ObjectLibrary/main.cpp @@ -4,14 +4,16 @@ int static_func(int); int file1_sq_func(int); -void test_functions() +int test_functions() { - file1_sq_func(static_func(42)); + return file1_sq_func(static_func(42)); } int main(int argc, char** argv) { - test_functions(); + if (test_functions() == 1) { + return 1; + } std::cout << "this executable doesn't use cuda code, just call methods defined" << std::endl; diff --git a/Tests/Cuda/ObjectLibrary/static.cu b/Tests/Cuda/ObjectLibrary/static.cu index cdf682bc1..aa357295a 100644 --- a/Tests/Cuda/ObjectLibrary/static.cu +++ b/Tests/Cuda/ObjectLibrary/static.cu @@ -9,8 +9,8 @@ int __host__ file1_sq_func(int x) int nDevices = 0; err = cudaGetDeviceCount(&nDevices); if (err != cudaSuccess) { - std::cout << "nDevices: " << nDevices << std::endl; - std::cout << "err: " << err << std::endl; + std::cerr << "nDevices: " << nDevices << std::endl; + std::cerr << "err: " << err << std::endl; return 1; } std::cout << "this library uses cuda code" << std::endl; diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt index 85a2051ed..5f456fcf4 100644 --- a/Tests/CudaOnly/CMakeLists.txt +++ b/Tests/CudaOnly/CMakeLists.txt @@ -1,4 +1,6 @@ ADD_TEST_MACRO(CudaOnly.EnableStandard CudaOnlyEnableStandard) +ADD_TEST_MACRO(CudaOnly.ExportPTX CudaOnlyExportPTX) ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation) ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs) +ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols) diff --git a/Tests/CudaOnly/ExportPTX/CMakeLists.txt b/Tests/CudaOnly/ExportPTX/CMakeLists.txt new file mode 100644 index 000000000..10249c614 --- /dev/null +++ b/Tests/CudaOnly/ExportPTX/CMakeLists.txt @@ -0,0 +1,82 @@ +cmake_minimum_required(VERSION 3.8) +project (CudaOnlyExportPTX CUDA) + +#Goal for this example: +# How to generate PTX files instead of OBJECT files +# How to reference PTX files for custom commands +# How to install PTX files + +add_library(CudaPTX OBJECT kernelA.cu kernelB.cu) +set_property(TARGET CudaPTX PROPERTY CUDA_PTX_COMPILATION ON) + +#Test ObjectFiles with file(GENERATE) +file(GENERATE + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gen_$/>path_to_objs.h + CONTENT [[ + +#include +#include + +#ifndef path_to_objs +#define path_to_objs + +static std::string ptx_paths = "$"; + +#endif + +]] +) +#We are going to need a wrapper around bin2c for multiple reasons +# 1. bin2c only converts a single file at a time +# 2. bin2c has only standard out support, so we have to manually +# redirect to a cmake buffer +# 3. We want to pack everything into a single output file, so we +# need to also pass the --name option +set(output_file ${CMAKE_CURRENT_BINARY_DIR}/embedded_objs.h) + +get_filename_component(cuda_compiler_bin "${CMAKE_CUDA_COMPILER}" DIRECTORY) +find_program(bin_to_c + NAMES bin2c + PATHS ${cuda_compiler_bin} + ) +if(NOT bin_to_c) + message(FATAL_ERROR + "bin2c not found:\n" + " CMAKE_CUDA_COMPILER='${CMAKE_CUDA_COMPILER}'\n" + " cuda_compiler_bin='${cuda_compiler_bin}'\n" + ) +endif() + +add_custom_command( + OUTPUT "${output_file}" + COMMAND ${CMAKE_COMMAND} + "-DBIN_TO_C_COMMAND=${bin_to_c}" + "-DOBJECTS=$" + "-DOUTPUT=${output_file}" + -P ${CMAKE_CURRENT_SOURCE_DIR}/bin2c_wrapper.cmake + VERBATIM + DEPENDS $ + COMMENT "Converting Object files to a C header" + ) + +add_executable(CudaOnlyExportPTX main.cu ${output_file}) +add_dependencies(CudaOnlyExportPTX CudaPTX) +target_include_directories(CudaOnlyExportPTX PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} ) +target_compile_definitions(CudaOnlyExportPTX PRIVATE + "CONFIG_TYPE=gen_$>") + +if(APPLE) + # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that + # the static cuda runtime can find it at runtime. + target_link_libraries(CudaOnlyExportPTX PRIVATE -Wl,-rpath,/usr/local/cuda/lib) +endif() + +#Verify that we can install object targets properly +install(TARGETS CudaPTX CudaOnlyExportPTX + EXPORT cudaPTX + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + OBJECTS DESTINATION objs + ) +install(EXPORT cudaPTX DESTINATION lib/cudaPTX) diff --git a/Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake b/Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake new file mode 100644 index 000000000..0baf93434 --- /dev/null +++ b/Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake @@ -0,0 +1,19 @@ + +set(file_contents) +foreach(obj ${OBJECTS}) + get_filename_component(obj_ext ${obj} EXT) + get_filename_component(obj_name ${obj} NAME_WE) + get_filename_component(obj_dir ${obj} DIRECTORY) + + if(obj_ext MATCHES ".ptx") + set(args --name ${obj_name} ${obj}) + execute_process(COMMAND "${BIN_TO_C_COMMAND}" ${args} + WORKING_DIRECTORY ${obj_dir} + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE error_var + ) + set(file_contents "${file_contents} \n${output}") + endif() +endforeach() +file(WRITE "${OUTPUT}" "${file_contents}") diff --git a/Tests/CudaOnly/ExportPTX/kernelA.cu b/Tests/CudaOnly/ExportPTX/kernelA.cu new file mode 100644 index 000000000..fbe0d26d7 --- /dev/null +++ b/Tests/CudaOnly/ExportPTX/kernelA.cu @@ -0,0 +1,7 @@ + +__global__ void kernelA(float* r, float* x, float* y, float* z, int size) +{ + for (int i = threadIdx.x; i < size; i += blockDim.x) { + r[i] = x[i] * y[i] + z[i]; + } +} diff --git a/Tests/CudaOnly/ExportPTX/kernelB.cu b/Tests/CudaOnly/ExportPTX/kernelB.cu new file mode 100644 index 000000000..11872e4c2 --- /dev/null +++ b/Tests/CudaOnly/ExportPTX/kernelB.cu @@ -0,0 +1,8 @@ + + +__global__ void kernelB(float* r, float* x, float* y, float* z, int size) +{ + for (int i = threadIdx.x; i < size; i += blockDim.x) { + r[i] = x[i] * y[i] + z[i]; + } +} diff --git a/Tests/CudaOnly/ExportPTX/main.cu b/Tests/CudaOnly/ExportPTX/main.cu new file mode 100644 index 000000000..132377c42 --- /dev/null +++ b/Tests/CudaOnly/ExportPTX/main.cu @@ -0,0 +1,28 @@ + +#include + +/* + Define GENERATED_HEADER macro to allow c++ files to include headers + generated based on different configuration types. +*/ + +/* clang-format off */ +#define GENERATED_HEADER(x) GENERATED_HEADER0(CONFIG_TYPE/x) +/* clang-format on */ +#define GENERATED_HEADER0(x) GENERATED_HEADER1(x) +#define GENERATED_HEADER1(x) + +#include GENERATED_HEADER(path_to_objs.h) + +#include "embedded_objs.h" + +int main(int argc, char** argv) +{ + (void)argc; + (void)argv; + + unsigned char* ka = kernelA; + unsigned char* kb = kernelB; + + return (ka != NULL && kb != NULL) ? 0 : 1; +} diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt new file mode 100644 index 000000000..b96bb984b --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.7) +project (CudaOnlyResolveDeviceSymbols CUDA) + +# Find nm and dumpbin +if(CMAKE_NM) + set(dump_command ${CMAKE_NM}) + set(dump_args -g) +else() + include(GetPrerequisites) + message(STATUS "calling list_prerequisites to find dumpbin") + list_prerequisites("${CMAKE_COMMAND}" 0 0 0) + if(gp_dumpbin) + set(dump_command ${gp_dumpbin}) + set(dump_args /ARCHIVEMEMBERS) + endif() +endif() + +#Goal for this example: +#Build a static library that defines multiple methods and kernels that +#use each other. +#Use a custom command to build an executable that uses this static library +#We do these together to verify that we can get a static library to do +#device symbol linking, and not have it done when the executable is made +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CUDA_STANDARD 11) + +add_library(CUDAResolveDeviceLib STATIC file1.cu file2.cu) +set_target_properties(CUDAResolveDeviceLib + PROPERTIES + CUDA_SEPARABLE_COMPILATION ON + CUDA_RESOLVE_DEVICE_SYMBOLS ON + POSITION_INDEPENDENT_CODE ON) + +if(dump_command) +add_custom_command(TARGET CUDAResolveDeviceLib POST_BUILD + COMMAND ${CMAKE_COMMAND} + -DDUMP_COMMAND=${dump_command} + -DDUMP_ARGS=${dump_args} + -DTEST_LIBRARY_PATH=$ + -P ${CMAKE_CURRENT_SOURCE_DIR}/verify.cmake + ) +endif() + +add_executable(CudaOnlyResolveDeviceSymbols main.cu) +target_link_libraries(CudaOnlyResolveDeviceSymbols PRIVATE CUDAResolveDeviceLib) + +if(APPLE) + # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that + # the static cuda runtime can find it at runtime. + target_link_libraries(CudaOnlyResolveDeviceSymbols PRIVATE -Wl,-rpath,/usr/local/cuda/lib) +endif() diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file1.cu b/Tests/CudaOnly/ResolveDeviceSymbols/file1.cu new file mode 100644 index 000000000..1ce63bf98 --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file1.cu @@ -0,0 +1,10 @@ + +#include "file1.h" + +result_type __device__ file1_func(int x) +{ + result_type r; + r.input = x; + r.sum = x * x; + return r; +} diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file1.h b/Tests/CudaOnly/ResolveDeviceSymbols/file1.h new file mode 100644 index 000000000..ff1945c0a --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file1.h @@ -0,0 +1,7 @@ + +#pragma once +struct result_type +{ + int input; + int sum; +}; diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu b/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu new file mode 100644 index 000000000..278fd6cce --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu @@ -0,0 +1,25 @@ + +#include "file2.h" + +result_type __device__ file1_func(int x); + +result_type_dynamic __device__ file2_func(int x) +{ + const result_type r = file1_func(x); + const result_type_dynamic rd{ r.input, r.sum, true }; + return rd; +} + +static __global__ void file2_kernel(result_type_dynamic& r, int x) +{ + // call static_func which is a method that is defined in the + // static library that is always out of date + r = file2_func(x); +} + +int file2_launch_kernel(int x) +{ + result_type_dynamic r; + file2_kernel<<<1, 1>>>(r, x); + return r.sum; +} diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file2.h b/Tests/CudaOnly/ResolveDeviceSymbols/file2.h new file mode 100644 index 000000000..d2dbaa4de --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file2.h @@ -0,0 +1,10 @@ + +#pragma once +#include "file1.h" + +struct result_type_dynamic +{ + int input; + int sum; + bool from_static; +}; diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/main.cu b/Tests/CudaOnly/ResolveDeviceSymbols/main.cu new file mode 100644 index 000000000..b4b5b9eac --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/main.cu @@ -0,0 +1,85 @@ + +#include + +#include "file1.h" +#include "file2.h" + +int file2_launch_kernel(int x); + +result_type_dynamic __device__ file2_func(int x); +static __global__ void main_kernel(result_type_dynamic& r, int x) +{ + // call function that was not device linked to us, this will cause + // a runtime failure of "invalid device function" + r = file2_func(x); +} + +int main_launch_kernel(int x) +{ + result_type_dynamic r; + main_kernel<<<1, 1>>>(r, x); + return r.sum; +} + +int choose_cuda_device() +{ + int nDevices = 0; + cudaError_t err = cudaGetDeviceCount(&nDevices); + if (err != cudaSuccess) { + std::cerr << "Failed to retrieve the number of CUDA enabled devices" + << std::endl; + return 1; + } + for (int i = 0; i < nDevices; ++i) { + cudaDeviceProp prop; + cudaError_t err = cudaGetDeviceProperties(&prop, i); + if (err != cudaSuccess) { + std::cerr << "Could not retrieve properties from CUDA device " << i + << std::endl; + return 1; + } + std::cout << "prop.major: " << prop.major << std::endl; + if (prop.major >= 3) { + err = cudaSetDevice(i); + if (err != cudaSuccess) { + std::cout << "Could not select CUDA device " << i << std::endl; + } else { + return 0; + } + } + } + + std::cout << "Could not find a CUDA enabled card supporting compute >=3.0" + << std::endl; + + return 1; +} + +int main(int argc, char** argv) +{ + int ret = choose_cuda_device(); + if (ret) { + return 0; + } + + cudaError_t err; + file2_launch_kernel(42); + err = cudaGetLastError(); + if (err != cudaSuccess) { + std::cerr << "file2_launch_kernel: kernel launch failed: " + << cudaGetErrorString(err) << std::endl; + return 1; + } + + main_launch_kernel(1); + err = cudaGetLastError(); + if (err == cudaSuccess) { + // This kernel launch should fail as the file2_func was device linked + // into the static library and is not usable by the executable + std::cerr << "main_launch_kernel: kernel launch should have failed" + << std::endl; + return 1; + } + + return 0; +} diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake b/Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake new file mode 100644 index 000000000..94d388b10 --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake @@ -0,0 +1,14 @@ +execute_process(COMMAND ${DUMP_COMMAND} ${DUMP_ARGS} ${TEST_LIBRARY_PATH} + RESULT_VARIABLE RESULT + OUTPUT_VARIABLE OUTPUT + ERROR_VARIABLE ERROR +) + +if(NOT "${RESULT}" STREQUAL "0") + message(FATAL_ERROR "${DUMP_COMMAND} failed [${RESULT}] [${OUTPUT}] [${ERROR}]") +endif() + +if(NOT "${OUTPUT}" MATCHES "(cmake_device_link|device-link)") + message(FATAL_ERROR + "No cuda device objects found, device linking did not occur") +endif() diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt index d134b969a..3d4a17073 100644 --- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt +++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt @@ -12,22 +12,44 @@ project (CudaOnlySeparateCompilation CUDA) string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD 11) -add_library(CUDASerarateLibA STATIC file1.cu file2.cu file3.cu) + +add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu) + +if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC") + # Test adding a flag that is not in our CUDA flag table for VS. + if(NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 8) + string(APPEND CMAKE_CUDA_FLAGS " --ftemplate-depth 50") + endif() + # Test adding a flag that nvcc should pass to the host compiler. + target_compile_options(CUDASeparateLibA PRIVATE -Xcompiler=-bigobj) +endif() #Having file4/file5 in a shared library causes serious problems #with the nvcc linker and it will generate bad entries that will #cause a segv when trying to run the executable # -add_library(CUDASerarateLibB STATIC file4.cu file5.cu) -target_link_libraries(CUDASerarateLibB PRIVATE CUDASerarateLibA) +add_library(CUDASeparateLibB STATIC file4.cu file5.cu) +target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA) add_executable(CudaOnlySeparateCompilation main.cu) -target_link_libraries(CudaOnlySeparateCompilation PRIVATE CUDASerarateLibB) +target_link_libraries(CudaOnlySeparateCompilation + PRIVATE CUDASeparateLibB) + +set_target_properties(CUDASeparateLibA + CUDASeparateLibB + PROPERTIES CUDA_SEPARABLE_COMPILATION ON + POSITION_INDEPENDENT_CODE ON) -set_target_properties( CUDASerarateLibA - CUDASerarateLibB - PROPERTIES CUDA_SEPARABLE_COMPILATION ON) +if (CMAKE_GENERATOR MATCHES "^Visual Studio") + #Visual Studio CUDA integration will not perform device linking + #on a target that itself does not have GenerateRelocatableDeviceCode + #enabled. + set_target_properties(CudaOnlySeparateCompilation + PROPERTIES CUDA_SEPARABLE_COMPILATION ON) +endif() -set_target_properties( CUDASerarateLibA - CUDASerarateLibB - PROPERTIES POSITION_INDEPENDENT_CODE ON) +if (APPLE) + # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that + # the static cuda runtime can find it at runtime. + target_link_libraries(CudaOnlySeparateCompilation PRIVATE -Wl,-rpath,/usr/local/cuda/lib) +endif() diff --git a/Tests/CudaOnly/SeparateCompilation/main.cu b/Tests/CudaOnly/SeparateCompilation/main.cu index 03e0921fc..40dbe5d7e 100644 --- a/Tests/CudaOnly/SeparateCompilation/main.cu +++ b/Tests/CudaOnly/SeparateCompilation/main.cu @@ -7,9 +7,62 @@ int file4_launch_kernel(int x); int file5_launch_kernel(int x); +int choose_cuda_device() +{ + int nDevices = 0; + cudaError_t err = cudaGetDeviceCount(&nDevices); + if (err != cudaSuccess) { + std::cerr << "Failed to retrieve the number of CUDA enabled devices" + << std::endl; + return 1; + } + for (int i = 0; i < nDevices; ++i) { + cudaDeviceProp prop; + cudaError_t err = cudaGetDeviceProperties(&prop, i); + if (err != cudaSuccess) { + std::cerr << "Could not retrieve properties from CUDA device " << i + << std::endl; + return 1; + } + if (prop.major >= 3) { + err = cudaSetDevice(i); + if (err != cudaSuccess) { + std::cout << "Could not select CUDA device " << i << std::endl; + } else { + return 0; + } + } + } + + std::cout << "Could not find a CUDA enabled card supporting compute >=3.0" + << std::endl; + + return 1; +} + int main(int argc, char** argv) { + int ret = choose_cuda_device(); + if (ret) { + return 0; + } + + cudaError_t err; file4_launch_kernel(42); + err = cudaGetLastError(); + if (err != cudaSuccess) { + std::cerr << "file4_launch_kernel: kernel launch failed: " + << cudaGetErrorString(err) << std::endl; + return 1; + } + file5_launch_kernel(42); + err = cudaGetLastError(); + if (err != cudaSuccess) { + std::cerr << "file5_launch_kernel: kernel launch failed: " + << cudaGetErrorString(err) << std::endl; + return 1; + } + return 0; } diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt index 2646d29a3..e25f141ea 100644 --- a/Tests/CudaOnly/WithDefs/CMakeLists.txt +++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt @@ -16,11 +16,19 @@ set(release_compile_defs DEFREL) #build a executable that needs to be passed a complex define through add_defintions #this verifies we can pass things such as '_','(' to nvcc add_definitions("-DPACKED_DEFINE=__attribute__((packed))") -set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA) -add_executable(CudaOnlyWithDefs main.notcu) + +if(CMAKE_GENERATOR MATCHES "Visual Studio") + # CUDA MSBuild rules do not pass '-x cu' to nvcc + set(main main_for_vs.cu) +else() + set(main main.notcu) + set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA) +endif() +add_executable(CudaOnlyWithDefs ${main}) target_compile_options(CudaOnlyWithDefs PRIVATE + -Xcompiler=-DHOST_DEFINE $<$:$> ) diff --git a/Tests/CudaOnly/WithDefs/main.notcu b/Tests/CudaOnly/WithDefs/main.notcu index 80ed3a505..d2eff3f4b 100644 --- a/Tests/CudaOnly/WithDefs/main.notcu +++ b/Tests/CudaOnly/WithDefs/main.notcu @@ -2,6 +2,10 @@ #include #include +#ifndef HOST_DEFINE +#error "HOST_DEFINE not defined!" +#endif + #ifndef PACKED_DEFINE #error "PACKED_DEFINE not defined!" #endif diff --git a/Tests/CudaOnly/WithDefs/main_for_vs.cu b/Tests/CudaOnly/WithDefs/main_for_vs.cu new file mode 100644 index 000000000..56078e7af --- /dev/null +++ b/Tests/CudaOnly/WithDefs/main_for_vs.cu @@ -0,0 +1 @@ +#include "main.notcu" diff --git a/Tests/CustomCommandByproducts/ninja-check.cmake b/Tests/CustomCommandByproducts/ninja-check.cmake index 2fc3cc217..a7beb3d64 100644 --- a/Tests/CustomCommandByproducts/ninja-check.cmake +++ b/Tests/CustomCommandByproducts/ninja-check.cmake @@ -4,7 +4,7 @@ if("${build_ninja}" MATCHES [====[ # Tell Ninja that they may appear as side effects of build rules # otherwise ordered by order-only dependencies. -((build [^:]*: phony [^\n]* +((build [^:]*: phony[^\n]* )*)# ========]====]) set(phony "${CMAKE_MATCH_1}") if(NOT phony) diff --git a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt index f917cd7f3..4975feb2d 100644 --- a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt +++ b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(working "${TestWorkingDir_BINARY_DIR}/working.c" add_custom_target( Custom ALL COMMAND "${CMAKE_COMMAND}" -E copy_if_different ./customTarget.c "${TestWorkingDir_BINARY_DIR}/customTarget.c" + BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/customTarget.c" WORKING_DIRECTORY "${TestWorkingDir_SOURCE_DIR}" ) @@ -36,6 +37,7 @@ add_executable(working2 working2.c ${TestWorkingDir_BINARY_DIR}/customTarget2.c) add_custom_target( Custom2 ALL COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${TestWorkingDir_SOURCE_DIR}/customTarget.c ../customTarget2.c + BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/customTarget2.c" WORKING_DIRECTORY work/ # Relative to build tree, trailing slash ) diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index f504c7be0..eeae3f006 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -79,6 +79,15 @@ set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_DEBUG testLib7D-$) set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_RELEASE testLib7R-$) set_property(TARGET testLib7 PROPERTY OUTPUT_NAME testLib7-$) +# Test exporting OBJECT targets +add_library(testLib8 OBJECT testLib8A.c testLib8B.c sub/testLib8C.c) + +if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]") + set(maybe_testLib8 testLib8) +else() + set(maybe_testLib8 "") +endif() + # Test using the target_link_libraries command to set the # LINK_INTERFACE_LIBRARIES* properties. We construct two libraries # providing the same two symbols. In each library one of the symbols @@ -474,7 +483,7 @@ install( TARGETS testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 testExe4 testExe2lib testLib4lib testLib4libdbg testLib4libopt - testLib6 testLib7 + testLib6 testLib7 ${maybe_testLib8} testLibCycleA testLibCycleB testLibNoSONAME cmp0022NEW cmp0022OLD @@ -483,6 +492,7 @@ install( RUNTIME DESTINATION $<1:bin> LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP ARCHIVE DESTINATION $<1:lib> + OBJECTS DESTINATION $<1:lib> FRAMEWORK DESTINATION Frameworks BUNDLE DESTINATION Applications ) @@ -535,6 +545,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3 FILE ExportBuildTree.cmake ) export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib + ${maybe_testLib8} testLib4lib testLib4libdbg testLib4libopt testLibCycleA testLibCycleB testLibNoSONAME diff --git a/Tests/ExportImport/Export/sub/testLib8C.c b/Tests/ExportImport/Export/sub/testLib8C.c new file mode 100644 index 000000000..a5568c73f --- /dev/null +++ b/Tests/ExportImport/Export/sub/testLib8C.c @@ -0,0 +1,4 @@ +int testLib8C(void) +{ + return 0; +} diff --git a/Tests/ExportImport/Export/testLib8A.c b/Tests/ExportImport/Export/testLib8A.c new file mode 100644 index 000000000..c64655a5d --- /dev/null +++ b/Tests/ExportImport/Export/testLib8A.c @@ -0,0 +1,4 @@ +int testLib8A(void) +{ + return 0; +} diff --git a/Tests/ExportImport/Export/testLib8B.c b/Tests/ExportImport/Export/testLib8B.c new file mode 100644 index 000000000..1be6c9cd0 --- /dev/null +++ b/Tests/ExportImport/Export/testLib8B.c @@ -0,0 +1,4 @@ +int testLib8B(void) +{ + return 0; +} diff --git a/Tests/ExportImport/Export/testLibNoSONAME.c b/Tests/ExportImport/Export/testLibNoSONAME.c index 30acc83a6..4d98562df 100644 --- a/Tests/ExportImport/Export/testLibNoSONAME.c +++ b/Tests/ExportImport/Export/testLibNoSONAME.c @@ -4,7 +4,7 @@ #define testLibNoSONAME_EXPORT #endif -testLibNoSONAME_EXPORT int testLibNoSONAME(void) +testLibNoSONAME_EXPORT int testLibNoSoName(void) { return 0; } diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 5ce962861..01960ea19 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -228,6 +228,16 @@ target_link_libraries(imp_lib1 exp_testLib2) add_library(imp_lib1b STATIC imp_lib1.c) target_link_libraries(imp_lib1b bld_testLib2) +if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]") + # Create a executable that is using objects imported from the install tree + add_executable(imp_testLib8 imp_testLib8.c $) + + if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT XCODE_VERSION VERSION_LESS 5) + # Create a executable that is using objects imported from the build tree + add_executable(imp_testLib8b imp_testLib8.c $) + endif() +endif() + #----------------------------------------------------------------------------- # Test that handling imported targets, including transitive dependencies, # works in CheckFunctionExists (...and hopefully all other try_compile() checks diff --git a/Tests/ExportImport/Import/A/imp_testExe1.c b/Tests/ExportImport/Import/A/imp_testExe1.c index 83a9bb5d6..348843928 100644 --- a/Tests/ExportImport/Import/A/imp_testExe1.c +++ b/Tests/ExportImport/Import/A/imp_testExe1.c @@ -1,15 +1,15 @@ -extern int generated_by_testExe1(); -extern int generated_by_testExe3(); -extern int generated_by_testExe4(); -extern int testLib2(); -extern int testLib3(); -extern int testLib4(); -extern int testLib4lib(); -extern int testLib5(); -extern int testLib6(); -extern int testLib7(); -extern int testLibCycleA1(); -extern int testLibPerConfigDest(); +extern int generated_by_testExe1(void); +extern int generated_by_testExe3(void); +extern int generated_by_testExe4(void); +extern int testLib2(void); +extern int testLib3(void); +extern int testLib4(void); +extern int testLib4lib(void); +extern int testLib5(void); +extern int testLib6(void); +extern int testLib7(void); +extern int testLibCycleA1(void); +extern int testLibPerConfigDest(void); /* Switch a symbol between debug and optimized builds to make sure the proper library is found from the testLib4 link interface. */ diff --git a/Tests/ExportImport/Import/A/imp_testLib8.c b/Tests/ExportImport/Import/A/imp_testLib8.c new file mode 100644 index 000000000..2749b178c --- /dev/null +++ b/Tests/ExportImport/Import/A/imp_testLib8.c @@ -0,0 +1,8 @@ + +int testLib8A(void); +int testLib8B(void); + +int main() +{ + return (testLib8A() + testLib8B()); +} diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt index 72c20eb1c..6b7356340 100644 --- a/Tests/ExternalProject/CMakeLists.txt +++ b/Tests/ExternalProject/CMakeLists.txt @@ -90,6 +90,16 @@ ExternalProject_Add(${proj} ) set_property(TARGET ${proj} PROPERTY FOLDER "") +set(proj NoExtractLogDownload) +ExternalProject_Add(${proj} + URL ${CMAKE_CURRENT_SOURCE_DIR}/gitrepo.tgz + DOWNLOAD_NO_EXTRACT 1 + LOG_DOWNLOAD 1 + BUILD_COMMAND "" + CONFIGURE_COMMAND "" + INSTALL_COMMAND "" +) + # CVS-based tests: # diff --git a/Tests/FindDoxygen/CMakeLists.txt b/Tests/FindDoxygen/CMakeLists.txt new file mode 100644 index 000000000..daceaa3e9 --- /dev/null +++ b/Tests/FindDoxygen/CMakeLists.txt @@ -0,0 +1,20 @@ +add_test(NAME FindDoxygen.SimpleTest COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindDoxygen/SimpleTest" + "${CMake_BINARY_DIR}/Tests/FindDoxygen/SimpleTest" + --build-target allDocTargets + ${build_generator_args} + --build-options ${build_options} +) + +if(CMake_TEST_FindDoxygen_Dot) + add_test(NAME FindDoxygen.DotComponentTest COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindDoxygen/DotComponentTestTest" + "${CMake_BINARY_DIR}/Tests/FindDoxygen/DotComponentTestTest" + ${build_generator_args} + --build-options ${build_options} + ) +endif() diff --git a/Tests/FindDoxygen/DotComponentTestTest/CMakeLists.txt b/Tests/FindDoxygen/DotComponentTestTest/CMakeLists.txt new file mode 100644 index 000000000..586f0ff66 --- /dev/null +++ b/Tests/FindDoxygen/DotComponentTestTest/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.8) +project(TestFindDoxygenDot VERSION 1.0 LANGUAGES NONE) + +# Testing a new signature w/ components +find_package(Doxygen REQUIRED COMPONENTS dot) + +# No backwards compatibility expected when component form is used +if(TARGET Doxygen::doxygen) + if(DOXYGEN) + message(FATAL_ERROR "DOXYGEN unexpectedly defined with component form") + endif() +else() + message(FATAL_ERROR "Import target Doxygen::doxygen not defined") +endif() + +if(NOT TARGET Doxygen::dot) + message(FATAL_ERROR "Import target Doxygen::dot not defined") +endif() diff --git a/Tests/FindDoxygen/SimpleTest/CMakeLists.txt b/Tests/FindDoxygen/SimpleTest/CMakeLists.txt new file mode 100644 index 000000000..332ceccdb --- /dev/null +++ b/Tests/FindDoxygen/SimpleTest/CMakeLists.txt @@ -0,0 +1,59 @@ +cmake_minimum_required(VERSION 3.8) +project(TestFindDoxygen VERSION 1.0 LANGUAGES NONE) + +# Testing backward compatible signature +find_package(Doxygen REQUIRED) + +if(TARGET Doxygen::doxygen) + # Check backward compatibility + if(NOT DOXYGEN_EXECUTABLE) + message(FATAL_ERROR "Backward compatibility broken: DOXYGEN_EXECUTABLE not set") + endif() + if(NOT DOXYGEN) + message(FATAL_ERROR "Backward compatibility broken: DOXYGEN not set") + endif() + # Check presence of expected generated files + foreach(file CMakeDoxyfile.in CMakeDoxygenDefaults.cmake) + if(NOT EXISTS "${PROJECT_BINARY_DIR}/${file}") + message(FATAL_ERROR "Missing generated file: ${file}") + endif() + endforeach() +else() + message(FATAL_ERROR "Import target Doxygen::doxygen not defined") +endif() + +doxygen_add_docs(docsNoArgs) +if(NOT EXISTS "${PROJECT_BINARY_DIR}/Doxyfile.docsNoArgs") + message(FATAL_ERROR "Missing generated file: Doxyfile.docsNoArgs") +endif() +if(NOT TARGET docsNoArgs) + message(FATAL_ERROR "Target docsNoArgs not created") +endif() + +configure_file(spaces_in_name.cpp.in "spaces in name.cpp" COPYONLY) +doxygen_add_docs(docsWithArgs + "${CMAKE_CURRENT_BINARY_DIR}/spaces in name.cpp" + main.cpp +) +if(NOT EXISTS "${PROJECT_BINARY_DIR}/Doxyfile.docsWithArgs") + message(FATAL_ERROR "Missing generated file: Doxyfile.docsWithArgs") +endif() +if(NOT TARGET docsWithArgs) + message(FATAL_ERROR "Target docsWithArgs not created") +endif() +# Note that CMake inserts at least one entry into SOURCES when a COMMAND or +# DEPENDS option is given to add_custom_target(), so rather than looking for an +# exact match, we only verify that the files we expect to be there are present +get_target_property(srcList docsWithArgs SOURCES) +set(expectedList + "${CMAKE_CURRENT_BINARY_DIR}/spaces in name.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +foreach(f IN LISTS expectedList) + if(NOT f IN_LIST srcList) + message(FATAL_ERROR "SOURCES missing file: ${f}") + endif() +endforeach() + +add_custom_target(allDocTargets) +add_dependencies(allDocTargets docsNoArgs docsWithArgs) diff --git a/Tests/FindDoxygen/SimpleTest/main.cpp b/Tests/FindDoxygen/SimpleTest/main.cpp new file mode 100644 index 000000000..925f0afe0 --- /dev/null +++ b/Tests/FindDoxygen/SimpleTest/main.cpp @@ -0,0 +1,4 @@ +/** + * \file + * \brief One C++ file w/ sample Doxygen comment just to produce any docs... + */ diff --git a/Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in b/Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in new file mode 100644 index 000000000..c1b9ffd9d --- /dev/null +++ b/Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in @@ -0,0 +1,4 @@ +/** + * \file + * \brief This file name contains spaces + */ diff --git a/Tests/FindGTest/Test/CMakeLists.txt b/Tests/FindGTest/Test/CMakeLists.txt index 99368ac71..b65b9d28f 100644 --- a/Tests/FindGTest/Test/CMakeLists.txt +++ b/Tests/FindGTest/Test/CMakeLists.txt @@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1) project(TestFindGTest CXX) include(CTest) -# CMake does not actually provide FindGTest publicly. -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules) - find_package(GTest REQUIRED) add_executable(test_gtest_tgt main.cxx) diff --git a/Tests/FindMPI/CMakeLists.txt b/Tests/FindMPI/CMakeLists.txt new file mode 100644 index 000000000..121d978a8 --- /dev/null +++ b/Tests/FindMPI/CMakeLists.txt @@ -0,0 +1,21 @@ +foreach(c C CXX Fortran) + if(CMake_TEST_FindMPI_${c}) + set(CMake_TEST_FindMPI_FLAG_${c} 1) + else() + set(CMake_TEST_FindMPI_FLAG_${c} 0) + endif() +endforeach() + +add_test(NAME FindMPI.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindMPI/Test" + "${CMake_BINARY_DIR}/Tests/FindMPI/Test" + ${build_generator_args} + --build-project TestFindMPI + --build-options ${build_options} + -DMPI_TEST_C=${CMake_TEST_FindMPI_FLAG_C} + -DMPI_TEST_CXX=${CMake_TEST_FindMPI_FLAG_CXX} + -DMPI_TEST_Fortran=${CMake_TEST_FindMPI_FLAG_Fortran} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) diff --git a/Tests/FindMPI/Test/CMakeLists.txt b/Tests/FindMPI/Test/CMakeLists.txt new file mode 100644 index 000000000..3910c254f --- /dev/null +++ b/Tests/FindMPI/Test/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.8) +project(TestFindMPI NONE) +include(CTest) + +macro(source_code_mapper_helper LANG_NAME) + if("${LANG_NAME}" STREQUAL "C") + set(MPITEST_SOURCE_FILE "main.c") + elseif("${LANG_NAME}" STREQUAL "CXX") + configure_file("main.c" "main.cxx" COPYONLY) + set(MPITEST_SOURCE_FILE "main.cxx") + elseif("${LANG_NAME}" STREQUAL "Fortran") + set(MPITEST_SOURCE_FILE "main.f90") + endif() +endmacro() + +foreach(c C CXX Fortran) + if("${MPI_TEST_${c}}") + message("Testing ${c}") + enable_language(${c}) + endif() +endforeach() + +find_package(MPI REQUIRED) + +foreach(c C CXX Fortran) + if(NOT "${MPI_TEST_${c}}") + continue() + endif() + source_code_mapper_helper(${c}) + add_executable(test_tgt_${c} ${MPITEST_SOURCE_FILE}) + target_link_libraries(test_tgt_${c} MPI::MPI_${c}) + add_test(NAME test_tgt_${c} COMMAND test_tgt_${c}) + + add_executable(test_var_${c} ${MPITEST_SOURCE_FILE}) + target_include_directories(test_var_${c} PRIVATE "${MPI_${c}_INCLUDE_PATH}") + target_link_libraries(test_var_${c} PRIVATE "${MPI_${c}_LINK_FLAGS}" "${MPI_${c}_LIBRARIES}") + set(copied_MPI_${c}_OPTIONS "${MPI_${c}_COMPILE_FLAGS}") + separate_arguments(copied_MPI_${c}_OPTIONS) + target_compile_options(test_var_${c} PRIVATE "${copied_MPI_${c}_OPTIONS}") + add_test(NAME test_var_${c} COMMAND test_var_${c}) +endforeach() diff --git a/Tests/FindMPI/Test/main.c b/Tests/FindMPI/Test/main.c new file mode 100644 index 000000000..7b7f17573 --- /dev/null +++ b/Tests/FindMPI/Test/main.c @@ -0,0 +1,7 @@ +#include + +int main(int argc, char** argv) +{ + MPI_Init(&argc, &argv); + MPI_Finalize(); +} diff --git a/Tests/FindMPI/Test/main.f90 b/Tests/FindMPI/Test/main.f90 new file mode 100644 index 000000000..6fb6fd36a --- /dev/null +++ b/Tests/FindMPI/Test/main.f90 @@ -0,0 +1,7 @@ +program mpi_test + include 'mpif.h' + integer ierror + + call MPI_INIT(ierror) + call MPI_FINALIZE(ierror) +end program mpi_test diff --git a/Tests/FindModulesExecuteAll/CMakeLists.txt b/Tests/FindModulesExecuteAll/CMakeLists.txt index 21b9d3897..4893bb335 100644 --- a/Tests/FindModulesExecuteAll/CMakeLists.txt +++ b/Tests/FindModulesExecuteAll/CMakeLists.txt @@ -6,8 +6,8 @@ # # I guess more things could be added, like checking whether variables are # defined after running the modules (e.g. FOO_FOUND etc.). +cmake_minimum_required(VERSION 2.8.4) # new enough for CMP0017 project(FindModulesExecuteAll) -cmake_minimum_required(VERSION 2.7) file(GLOB all_modules "${CMAKE_CURRENT_SOURCE_DIR}/../../Modules/Find*cmake") diff --git a/Tests/FindOpenMP/CMakeLists.txt b/Tests/FindOpenMP/CMakeLists.txt new file mode 100644 index 000000000..e64885d09 --- /dev/null +++ b/Tests/FindOpenMP/CMakeLists.txt @@ -0,0 +1,21 @@ +foreach(c C CXX Fortran) + if(CMake_TEST_FindOpenMP_${c}) + set(CMake_TEST_FindOpenMP_FLAG_${c} 1) + else() + set(CMake_TEST_FindOpenMP_FLAG_${c} 0) + endif() +endforeach() + +add_test(NAME FindOpenMP.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindOpenMP/Test" + "${CMake_BINARY_DIR}/Tests/FindOpenMP/Test" + ${build_generator_args} + --build-project TestFindOpenMP + --build-options ${build_options} + -DOpenMP_TEST_C=${CMake_TEST_FindOpenMP_FLAG_C} + -DOpenMP_TEST_CXX=${CMake_TEST_FindOpenMP_FLAG_CXX} + -DOpenMP_TEST_Fortran=${CMake_TEST_FindOpenMP_FLAG_Fortran} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) diff --git a/Tests/FindOpenMP/Test/CMakeLists.txt b/Tests/FindOpenMP/Test/CMakeLists.txt new file mode 100644 index 000000000..2692947ad --- /dev/null +++ b/Tests/FindOpenMP/Test/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.8) +project(TestFindOpenMP NONE) +include(CTest) + +macro(source_code_mapper_helper LANG_NAME SRC_FILE_NAME) + if("${LANG_NAME}" STREQUAL "C") + set(OpenMPTEST_SOURCE_FILE "${SRC_FILE_NAME}.c") + elseif("${LANG_NAME}" STREQUAL "CXX") + configure_file("${SRC_FILE_NAME}.c" "${SRC_FILE_NAME}.cxx" COPYONLY) + set(OpenMPTEST_SOURCE_FILE "${SRC_FILE_NAME}.cxx") + elseif("${LANG_NAME}" STREQUAL "Fortran") + set(OpenMPTEST_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/${SRC_FILE_NAME}.f90") + if(OpenMP_Fortran_HAVE_OMPLIB_MODULE) + set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none") + else() + set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'") + endif() + configure_file("${SRC_FILE_NAME}.f90.in" "${OpenMPTEST_SOURCE_FILE}" @ONLY) + endif() +endmacro() + +foreach(c C CXX Fortran) + if("${OpenMP_TEST_${c}}") + message("Testing ${c}") + enable_language(${c}) + endif() +endforeach() + +find_package(OpenMP REQUIRED) + +foreach(c C CXX Fortran) + if(NOT "${OpenMP_TEST_${c}}") + continue() + endif() + source_code_mapper_helper(${c} main) + add_executable(test_tgt_${c} ${OpenMPTEST_SOURCE_FILE}) + target_link_libraries(test_tgt_${c} PRIVATE OpenMP::OpenMP_${c}) + set_property(TARGET test_tgt_${c} PROPERTY LINKER_LANGUAGE ${c}) + add_test(NAME test_tgt_${c} COMMAND test_tgt_${c}) + + add_executable(test_var_${c} ${OpenMPTEST_SOURCE_FILE}) + separate_arguments(_OpenMP_${c}_OPTIONS NATIVE_COMMAND "${OpenMP_${c}_FLAGS}") + target_compile_options(test_var_${c} PRIVATE "${_OpenMP_${c}_OPTIONS}") + target_link_libraries(test_var_${c} PRIVATE "${OpenMP_${c}_FLAGS}") + set_property(TARGET test_var_${c} PROPERTY LINKER_LANGUAGE ${c}) + add_test(NAME test_var_${c} COMMAND test_var_${c}) + + source_code_mapper_helper(${c} scalprod) + add_library(scalprod_${c} STATIC ${OpenMPTEST_SOURCE_FILE}) + target_link_libraries(scalprod_${c} PRIVATE OpenMP::OpenMP_${c}) + set_property(TARGET scalprod_${c} PROPERTY LINKER_LANGUAGE ${c}) +endforeach() + +foreach(c C CXX Fortran) + if(NOT "${OpenMP_TEST_${c}}") + continue() + endif() + foreach(d C CXX Fortran) + if(NOT "${OpenMP_TEST_${d}}") + continue() + endif() + source_code_mapper_helper(${c} scaltest) + add_executable(scaltest_${c}_${d} ${OpenMPTEST_SOURCE_FILE}) + target_link_libraries(scaltest_${c}_${d} PRIVATE scalprod_${d}) + set_property(TARGET scaltest_${c}_${d} PROPERTY LINKER_LANGUAGE ${c}) + add_test(NAME test_omp_${c}_${d} COMMAND scaltest_${c}_${d}) + set_property(TEST test_omp_${c}_${d} PROPERTY PASS_REGULAR_EXPRESSION "^[ \t]*70\\.?0*") + endforeach() +endforeach() diff --git a/Tests/FindOpenMP/Test/main.c b/Tests/FindOpenMP/Test/main.c new file mode 100644 index 000000000..4f0e87483 --- /dev/null +++ b/Tests/FindOpenMP/Test/main.c @@ -0,0 +1,7 @@ +#include +int main() +{ +#ifndef _OPENMP + breaks_on_purpose +#endif +} diff --git a/Tests/FindOpenMP/Test/main.f90.in b/Tests/FindOpenMP/Test/main.f90.in new file mode 100644 index 000000000..9da22a1cc --- /dev/null +++ b/Tests/FindOpenMP/Test/main.f90.in @@ -0,0 +1,5 @@ + program test + @OpenMP_Fortran_INCLUDE_LINE@ + !$ integer :: n + n = omp_get_num_threads() + end program test diff --git a/Tests/FindOpenMP/Test/scalprod.c b/Tests/FindOpenMP/Test/scalprod.c new file mode 100644 index 000000000..24c4587af --- /dev/null +++ b/Tests/FindOpenMP/Test/scalprod.c @@ -0,0 +1,16 @@ +#include + +#ifdef __cplusplus +extern "C" +#endif + void + scalprod(int n, double* x, double* y, double* res) +{ + int i; + double res_v = 0.; +#pragma omp parallel for reduction(+ : res_v) + for (i = 0; i < n; ++i) { + res_v += x[i] * y[i]; + } + *res = res_v; +} diff --git a/Tests/FindOpenMP/Test/scalprod.f90.in b/Tests/FindOpenMP/Test/scalprod.f90.in new file mode 100644 index 000000000..efc7ea0e4 --- /dev/null +++ b/Tests/FindOpenMP/Test/scalprod.f90.in @@ -0,0 +1,19 @@ +subroutine scalprod(n, x_p, y_p, res) bind(c) + use iso_c_binding + implicit none + integer(c_int), intent(in), value :: n + type(c_ptr), intent(in), value :: x_p, y_p + real(c_double), pointer :: x(:), y(:) + integer :: i + + real(c_double) :: res + real(c_double) :: scalpt = 0 + call c_f_pointer(x_p, x, shape=[n]) + call c_f_pointer(y_p, y, shape=[n]) + res = 0 +!$omp parallel do private(scalpt), reduction(+:res) + do i=1,n + scalpt = y(i) * x(i) + res = res + scalpt + end do +end subroutine scalprod diff --git a/Tests/FindOpenMP/Test/scaltest.c b/Tests/FindOpenMP/Test/scaltest.c new file mode 100644 index 000000000..2ee57f833 --- /dev/null +++ b/Tests/FindOpenMP/Test/scaltest.c @@ -0,0 +1,20 @@ +#ifdef __cplusplus +#include +extern "C" +#else +#include +#endif +int scalprod(int n, double* x, double* y, double* res); + +int main() +{ + double a[5] = { 1., 2., 3., 4., 5. }; + double b[5] = { 2., 3., 4., 5., 6. }; + double rk; + scalprod(5, a, b, &rk); +#ifdef __cplusplus + std::cout << rk << std::endl; +#else + printf("%f\n", rk); +#endif +} diff --git a/Tests/FindOpenMP/Test/scaltest.f90.in b/Tests/FindOpenMP/Test/scaltest.f90.in new file mode 100644 index 000000000..64c20d285 --- /dev/null +++ b/Tests/FindOpenMP/Test/scaltest.f90.in @@ -0,0 +1,21 @@ +program scaltest + use iso_c_binding + implicit none + interface + subroutine scalprod(n, x_p, y_p, res) bind(c) + use iso_c_binding + integer(c_int), value :: n + type(c_ptr), value :: x_p, y_p + real(c_double) :: res + end subroutine scalprod + end interface + type(c_ptr) :: x_pt, y_pt + real(c_double), dimension(5), target :: a = (/ 1, 2, 3, 4, 5 /) + real(c_double), dimension(5), target :: b = (/ 2, 3, 4, 5, 6 /) + integer(c_int) :: n = size(a) + real(c_double) :: res + x_pt = c_loc(a) + y_pt = c_loc(b) + call scalprod(n, x_pt, y_pt, res) + print *, res +end program scaltest diff --git a/Tests/FindProtobuf/CMakeLists.txt b/Tests/FindProtobuf/CMakeLists.txt new file mode 100644 index 000000000..1cdb2ae13 --- /dev/null +++ b/Tests/FindProtobuf/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindProtobuf.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindProtobuf/Test" + "${CMake_BINARY_DIR}/Tests/FindProtobuf/Test" + ${build_generator_args} + --build-project TestFindProtobuf + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) diff --git a/Tests/FindProtobuf/Test/CMakeLists.txt b/Tests/FindProtobuf/Test/CMakeLists.txt new file mode 100644 index 000000000..8b6e38a8e --- /dev/null +++ b/Tests/FindProtobuf/Test/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.4) +project(TestFindProtobuf CXX) +include(CTest) + +find_package(Protobuf REQUIRED) + +add_executable(test_tgt main.cxx) +target_link_libraries(test_tgt protobuf::libprotobuf) +add_test(NAME test_tgt COMMAND test_tgt) + +add_executable(test_var main.cxx) +target_include_directories(test_var PRIVATE ${Protobuf_INCLUDE_DIRS}) +target_link_libraries(test_var PRIVATE ${Protobuf_LIBRARIES}) +add_test(NAME test_var COMMAND test_var) + +add_executable(test_tgt_lite main.cxx) +target_link_libraries(test_tgt_lite protobuf::libprotobuf-lite) +add_test(NAME test_tgt_lite COMMAND test_tgt_lite) + +add_executable(test_var_lite main.cxx) +target_include_directories(test_var_lite PRIVATE ${Protobuf_INCLUDE_DIRS}) +target_link_libraries(test_var_lite PRIVATE ${Protobuf_LITE_LIBRARIES}) +add_test(NAME test_var_lite COMMAND test_var_lite) + +add_executable(test_tgt_protoc main-protoc.cxx) +target_link_libraries(test_tgt_protoc protobuf::libprotoc) +add_test(NAME test_tgt_protoc COMMAND test_tgt_protoc) + +add_executable(test_var_protoc main-protoc.cxx) +target_include_directories(test_var_protoc PRIVATE ${Protobuf_INCLUDE_DIRS}) +target_link_libraries(test_var_protoc PRIVATE ${Protobuf_PROTOC_LIBRARIES}) +add_test(NAME test_var_protoc COMMAND test_var_protoc) diff --git a/Tests/FindProtobuf/Test/main-protoc.cxx b/Tests/FindProtobuf/Test/main-protoc.cxx new file mode 100644 index 000000000..64e5ada4a --- /dev/null +++ b/Tests/FindProtobuf/Test/main-protoc.cxx @@ -0,0 +1,8 @@ +#include + +int main() +{ + google::protobuf::compiler::CommandLineInterface(); + + return 0; +} diff --git a/Tests/FindProtobuf/Test/main.cxx b/Tests/FindProtobuf/Test/main.cxx new file mode 100644 index 000000000..87d5c12e2 --- /dev/null +++ b/Tests/FindProtobuf/Test/main.cxx @@ -0,0 +1,8 @@ +#include + +int main() +{ + GOOGLE_PROTOBUF_VERIFY_VERSION; + + return 0; +} diff --git a/Tests/FindTIFF/Test/CMakeLists.txt b/Tests/FindTIFF/Test/CMakeLists.txt index 6985e3f9e..85453edbc 100644 --- a/Tests/FindTIFF/Test/CMakeLists.txt +++ b/Tests/FindTIFF/Test/CMakeLists.txt @@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1) project(TestFindTIFF C) include(CTest) -# CMake does not actually provide FindTIFF publicly. -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules) - find_package(TIFF REQUIRED) add_executable(test_tiff_tgt main.c) diff --git a/Tests/FindXalanC/Test/CMakeLists.txt b/Tests/FindXalanC/Test/CMakeLists.txt index b445e0e10..a8c2a0a8a 100644 --- a/Tests/FindXalanC/Test/CMakeLists.txt +++ b/Tests/FindXalanC/Test/CMakeLists.txt @@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1) project(TestFindXalanC CXX) include(CTest) -# CMake does not actually provide FindXalanC publicly. -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules) - find_package(XalanC REQUIRED) add_executable(test_xalanc_tgt main.cxx) diff --git a/Tests/FindXercesC/Test/CMakeLists.txt b/Tests/FindXercesC/Test/CMakeLists.txt index 8e7767cfd..267c6a907 100644 --- a/Tests/FindXercesC/Test/CMakeLists.txt +++ b/Tests/FindXercesC/Test/CMakeLists.txt @@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1) project(TestFindXercesC CXX) include(CTest) -# CMake does not actually provide FindXercesC publicly. -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules) - find_package(XercesC REQUIRED) add_executable(test_xercesc_tgt main.cxx) diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index adc87cdc4..8ac341912 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -292,3 +292,19 @@ set(CMP0044_TYPE NEW) add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-NEW) set(CMP0044_TYPE OLD) add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-OLD) + +if(NOT CMAKE_GENERATOR STREQUAL Xcode OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]") + add_library(objlib OBJECT objlib1.c objlib2.c) + file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$" + CONTENT "$,\n>\n" + ) + + add_custom_target(check_object_files ALL + COMMAND ${CMAKE_COMMAND} + "-DOBJLIB_LISTFILE=${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$" + -DEXPECTED_NUM_OBJECTFILES=2 + -P "${CMAKE_CURRENT_SOURCE_DIR}/check_object_files.cmake" + DEPENDS objlib + ) +endif() diff --git a/Tests/GeneratorExpression/check_object_files.cmake b/Tests/GeneratorExpression/check_object_files.cmake new file mode 100644 index 000000000..cfccd2961 --- /dev/null +++ b/Tests/GeneratorExpression/check_object_files.cmake @@ -0,0 +1,26 @@ + +if (NOT EXISTS ${OBJLIB_LISTFILE}) + message(SEND_ERROR "Object listing file \"${OBJLIB_LISTFILE}\" not found!") +endif() + +file(STRINGS ${OBJLIB_LISTFILE} objlib_files ENCODING UTF-8) + +list(LENGTH objlib_files num_objectfiles) +if (NOT EXPECTED_NUM_OBJECTFILES EQUAL num_objectfiles) + message(SEND_ERROR "Unexpected number of entries in object list file (${num_objectfiles} instead of ${EXPECTED_NUM_OBJECTFILES})") +endif() + +foreach(objlib_file ${objlib_files}) + set(file_exists False) + if (EXISTS ${objlib_file}) + set(file_exists True) + endif() + + if (NOT file_exists) + if(attempts) + list(REMOVE_DUPLICATES attempts) + set(tried " Tried ${attempts}") + endif() + message(SEND_ERROR "File \"${objlib_file}\" does not exist!${tried}") + endif() +endforeach() diff --git a/Tests/GeneratorExpression/objlib1.c b/Tests/GeneratorExpression/objlib1.c new file mode 100644 index 000000000..98a95a403 --- /dev/null +++ b/Tests/GeneratorExpression/objlib1.c @@ -0,0 +1,4 @@ + +void objlib1() +{ +} diff --git a/Tests/GeneratorExpression/objlib2.c b/Tests/GeneratorExpression/objlib2.c new file mode 100644 index 000000000..b2c1050ae --- /dev/null +++ b/Tests/GeneratorExpression/objlib2.c @@ -0,0 +1,4 @@ + +void objlib2() +{ +} diff --git a/Tests/GoogleTest/CMakeLists.txt b/Tests/GoogleTest/CMakeLists.txt new file mode 100644 index 000000000..21f8b8b8d --- /dev/null +++ b/Tests/GoogleTest/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME GoogleTest.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/GoogleTest/Test" + "${CMake_BINARY_DIR}/Tests/GoogleTest/Test" + ${build_generator_args} + --build-project TestGoogleTest + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) diff --git a/Tests/GoogleTest/Test/CMakeLists.txt b/Tests/GoogleTest/Test/CMakeLists.txt new file mode 100644 index 000000000..f798d313c --- /dev/null +++ b/Tests/GoogleTest/Test/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.8) +project(TestGoogleTest) +include(CTest) + +include(GoogleTest) + +find_package(GTest REQUIRED) + +add_executable(test_gtest1 main1.cxx) +target_link_libraries(test_gtest1 GTest::GTest) + +# Simple test of defaults +gtest_add_tests(TARGET test_gtest1 + TEST_LIST testList +) +set(expectedTests + GoogleTest.LinksAndRuns + GoogleTest.ConditionalFail +) +if(NOT testList STREQUAL "${expectedTests}") + message(FATAL_ERROR "Expected test list: ${expectedTests} +Actual test list: ${testList}") +endif() + + +# Same target, different arguments, so use test prefix and suffix to +# differentiate from the above test cases +gtest_add_tests(TARGET test_gtest1 + TEST_LIST testList + TEST_PREFIX "set2." + TEST_SUFFIX ".foo" + EXTRA_ARGS --forceFail +) + +set(expectedTests + set2.GoogleTest.LinksAndRuns.foo + set2.GoogleTest.ConditionalFail.foo +) +if(NOT testList STREQUAL "${expectedTests}") + message(FATAL_ERROR "Expected test list: ${expectedTests} +Actual test list: ${testList}") +endif() + +set_tests_properties(set2.GoogleTest.ConditionalFail.foo PROPERTIES WILL_FAIL YES) + + +# Search specific sources to get the test list +add_executable(test_gtest2 main2.cxx) +target_link_libraries(test_gtest2 GTest::Main) +gtest_add_tests(TARGET test_gtest2 + TEST_LIST testList + SOURCES main2.h +) +set(expectedTests + GoogleTest.SomethingElse + GoogleTest.OffTest1 + GoogleTest.OffTest2 + GoogleTest.OffTest3 +) +if(NOT testList STREQUAL "${expectedTests}") + message(FATAL_ERROR "Expected test list: ${expectedTests} +Actual test list: ${testList}") +endif() +set(disabledTests + GoogleTest.OffTest1 + GoogleTest.OffTest2 + GoogleTest.OffTest3 +) +foreach(T ${disabledTests}) + get_test_property(${T} DISABLED testDisabled) + if(NOT testDisabled) + message(FATAL_ERROR "Test ${T} should be disabled but is not") + endif() +endforeach() + +# Non-keyword form, auto-find sources +add_executable(test_gtest3 main3.cxx) +target_link_libraries(test_gtest3 GTest::Main) +gtest_add_tests(test_gtest3 "" AUTO) +if(NOT TEST GoogleTest.Foo) + message(FATAL_ERROR "Test case GoogleTest.Foo not defined") +endif() +if(NOT TEST GoogleTest.Bar) + message(FATAL_ERROR "Test case GoogleTest.Bar not defined") +endif() + + +# Non-keyword form, explicitly specified sources. Allows a non-target to be +# given for the executable. +add_executable(test_gtest4 main4.cxx) +target_link_libraries(test_gtest4 GTest::Main) +gtest_add_tests($ "" main4.h) +if(NOT TEST GoogleTest.NoKeywords) + message(FATAL_ERROR "Test case GoogleTest.NoKeywords not defined") +endif() diff --git a/Tests/GoogleTest/Test/main1.cxx b/Tests/GoogleTest/Test/main1.cxx new file mode 100644 index 000000000..03d604b91 --- /dev/null +++ b/Tests/GoogleTest/Test/main1.cxx @@ -0,0 +1,30 @@ +#include + +#include + +namespace { +bool shouldFail = false; +} + +TEST(GoogleTest, LinksAndRuns) +{ + ASSERT_TRUE(true); +} + +TEST(GoogleTest, ConditionalFail) +{ + ASSERT_FALSE(shouldFail); +} + +int main(int argc, char* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + if (argc > 1) { + if (argv[1] != std::string("--forceFail")) { + throw "Unexpected argument"; + } + shouldFail = true; + } + return RUN_ALL_TESTS(); +} diff --git a/Tests/GoogleTest/Test/main2.cxx b/Tests/GoogleTest/Test/main2.cxx new file mode 100644 index 000000000..05ffb4ac5 --- /dev/null +++ b/Tests/GoogleTest/Test/main2.cxx @@ -0,0 +1 @@ +#include "main2.h" diff --git a/Tests/GoogleTest/Test/main2.h b/Tests/GoogleTest/Test/main2.h new file mode 100644 index 000000000..7881c4fd8 --- /dev/null +++ b/Tests/GoogleTest/Test/main2.h @@ -0,0 +1,21 @@ +#include + +TEST(GoogleTest, SomethingElse) +{ + ASSERT_TRUE(true); +} + +TEST(GoogleTest, DISABLED_OffTest1) +{ + ASSERT_TRUE(true); +} + +TEST(DISABLED_GoogleTest, OffTest2) +{ + ASSERT_TRUE(true); +} + +TEST(DISABLED_GoogleTest, DISABLED_OffTest3) +{ + ASSERT_TRUE(true); +} diff --git a/Tests/GoogleTest/Test/main3.cxx b/Tests/GoogleTest/Test/main3.cxx new file mode 100644 index 000000000..98ce13c4f --- /dev/null +++ b/Tests/GoogleTest/Test/main3.cxx @@ -0,0 +1,11 @@ +#include + +TEST(GoogleTest, Foo) +{ + ASSERT_TRUE(true); +} + +TEST(GoogleTest, Bar) +{ + ASSERT_TRUE(true); +} diff --git a/Tests/GoogleTest/Test/main4.cxx b/Tests/GoogleTest/Test/main4.cxx new file mode 100644 index 000000000..8023bc13f --- /dev/null +++ b/Tests/GoogleTest/Test/main4.cxx @@ -0,0 +1 @@ +#include "main4.h" diff --git a/Tests/GoogleTest/Test/main4.h b/Tests/GoogleTest/Test/main4.h new file mode 100644 index 000000000..19da12a73 --- /dev/null +++ b/Tests/GoogleTest/Test/main4.h @@ -0,0 +1,6 @@ +#include + +TEST(GoogleTest, NoKeywords) +{ + ASSERT_TRUE(true); +} diff --git a/Tests/JavaExportImport/BuildExport/CMakeLists.txt b/Tests/JavaExportImport/BuildExport/CMakeLists.txt index 953f9d005..fa7e5016d 100644 --- a/Tests/JavaExportImport/BuildExport/CMakeLists.txt +++ b/Tests/JavaExportImport/BuildExport/CMakeLists.txt @@ -7,4 +7,7 @@ find_package(Java COMPONENTS Development) include(UseJava) add_jar(${PROJECT_NAME} Foo.java) -export_jars(TARGETS ${PROJECT_NAME} FILE JavaBuildExportTestConfig.cmake) +export_jars( + TARGETS ${PROJECT_NAME} + NAMESPACE foo:: + FILE JavaBuildExportTestConfig.cmake) diff --git a/Tests/JavaExportImport/Import/CMakeLists.txt b/Tests/JavaExportImport/Import/CMakeLists.txt index 79a14477a..13ec05dc4 100644 --- a/Tests/JavaExportImport/Import/CMakeLists.txt +++ b/Tests/JavaExportImport/Import/CMakeLists.txt @@ -11,4 +11,4 @@ find_package(JavaInstallExportTest REQUIRED) add_jar(${PROJECT_NAME} SOURCES Import.java - INCLUDE_JARS foo bar) + INCLUDE_JARS foo::foo bar::bar) diff --git a/Tests/JavaExportImport/InstallExport/CMakeLists.txt b/Tests/JavaExportImport/InstallExport/CMakeLists.txt index 0a9afd9cf..2923bebb2 100644 --- a/Tests/JavaExportImport/InstallExport/CMakeLists.txt +++ b/Tests/JavaExportImport/InstallExport/CMakeLists.txt @@ -10,5 +10,6 @@ add_jar(${PROJECT_NAME} Bar.java) install_jar(${PROJECT_NAME} DESTINATION share/java) install_jar_exports( TARGETS ${PROJECT_NAME} + NAMESPACE bar:: FILE JavaInstallExportTestConfig.cmake DESTINATION share/cmake) diff --git a/Tests/Module/CheckIPOSupported-C/CMakeLists.txt b/Tests/Module/CheckIPOSupported-C/CMakeLists.txt new file mode 100644 index 000000000..607dcd33a --- /dev/null +++ b/Tests/Module/CheckIPOSupported-C/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.8) +project(CheckIPOSupported-C LANGUAGES C) + +cmake_policy(SET CMP0069 NEW) + +include(CheckIPOSupported) +check_ipo_supported(RESULT ipo_supported) +if(ipo_supported) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) +elseif(CMake_TEST_IPO_WORKS_C) + message(FATAL_ERROR "IPO expected to work") +endif() + +add_library(foo foo.c) +add_executable(CheckIPOSupported-C main.c) +target_link_libraries(CheckIPOSupported-C PUBLIC foo) + +enable_testing() +add_test(NAME CheckIPOSupported-C COMMAND CheckIPOSupported-C) diff --git a/Tests/Module/CheckIPOSupported-C/foo.c b/Tests/Module/CheckIPOSupported-C/foo.c new file mode 100644 index 000000000..1e5659789 --- /dev/null +++ b/Tests/Module/CheckIPOSupported-C/foo.c @@ -0,0 +1,4 @@ +int foo() +{ + return 0x42; +} diff --git a/Tests/Module/CheckIPOSupported-C/main.c b/Tests/Module/CheckIPOSupported-C/main.c new file mode 100644 index 000000000..99204abce --- /dev/null +++ b/Tests/Module/CheckIPOSupported-C/main.c @@ -0,0 +1,9 @@ +int foo(); + +int main() +{ + if (foo() == 0) { + return 1; + } + return 0; +} diff --git a/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt b/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt new file mode 100644 index 000000000..2dede930b --- /dev/null +++ b/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.8) +project(CheckIPOSupported-CXX LANGUAGES CXX) + +cmake_policy(SET CMP0069 NEW) + +include(CheckIPOSupported) +check_ipo_supported(RESULT ipo_supported) +if(ipo_supported) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) +elseif(CMake_TEST_IPO_WORKS_CXX) + message(FATAL_ERROR "IPO expected to work") +endif() + +add_library(foo foo.cpp) +add_executable(CheckIPOSupported-CXX main.cpp) +target_link_libraries(CheckIPOSupported-CXX PUBLIC foo) + +enable_testing() +add_test(NAME CheckIPOSupported-CXX COMMAND CheckIPOSupported-CXX) diff --git a/Tests/Module/CheckIPOSupported-CXX/foo.cpp b/Tests/Module/CheckIPOSupported-CXX/foo.cpp new file mode 100644 index 000000000..1e5659789 --- /dev/null +++ b/Tests/Module/CheckIPOSupported-CXX/foo.cpp @@ -0,0 +1,4 @@ +int foo() +{ + return 0x42; +} diff --git a/Tests/Module/CheckIPOSupported-CXX/main.cpp b/Tests/Module/CheckIPOSupported-CXX/main.cpp new file mode 100644 index 000000000..99204abce --- /dev/null +++ b/Tests/Module/CheckIPOSupported-CXX/main.cpp @@ -0,0 +1,9 @@ +int foo(); + +int main() +{ + if (foo() == 0) { + return 1; + } + return 0; +} diff --git a/Tests/Module/CheckIPOSupported-Fortran/CMakeLists.txt b/Tests/Module/CheckIPOSupported-Fortran/CMakeLists.txt new file mode 100644 index 000000000..dee5c25bd --- /dev/null +++ b/Tests/Module/CheckIPOSupported-Fortran/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.8) +project(CheckIPOSupported-Fortran LANGUAGES Fortran) + +cmake_policy(SET CMP0069 NEW) + +include(CheckIPOSupported) +check_ipo_supported(RESULT ipo_supported) +if(ipo_supported) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) +elseif(CMake_TEST_IPO_WORKS_Fortran) + message(FATAL_ERROR "IPO expected to work") +endif() + +add_library(foo foo.f) +add_executable(CheckIPOSupported-Fortran main.f) +target_link_libraries(CheckIPOSupported-Fortran PUBLIC foo) + +enable_testing() +add_test(NAME CheckIPOSupported-Fortran COMMAND CheckIPOSupported-Fortran) diff --git a/Tests/Module/CheckIPOSupported-Fortran/foo.f b/Tests/Module/CheckIPOSupported-Fortran/foo.f new file mode 100644 index 000000000..945d2d559 --- /dev/null +++ b/Tests/Module/CheckIPOSupported-Fortran/foo.f @@ -0,0 +1,2 @@ + SUBROUTINE FOO + END diff --git a/Tests/Module/CheckIPOSupported-Fortran/main.f b/Tests/Module/CheckIPOSupported-Fortran/main.f new file mode 100644 index 000000000..9d1de9f8a --- /dev/null +++ b/Tests/Module/CheckIPOSupported-Fortran/main.f @@ -0,0 +1,3 @@ + PROGRAM BOO + CALL FOO() + END diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index 2657aebb7..52d461350 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -48,7 +48,14 @@ macro(set_defines target true_defs false_defs) ) endmacro() +# Only run the compiler detection header test for compilers with +# detailed features tables, not just meta-features + if (CMAKE_C_COMPILE_FEATURES) + set(C_expected_features ${CMAKE_C_COMPILE_FEATURES}) + list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]") +endif() +if (C_expected_features) string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJOR "${CMAKE_C_COMPILER_VERSION}") string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" COMPILER_VERSION_MINOR "${CMAKE_C_COMPILER_VERSION}") string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_C_COMPILER_VERSION}") @@ -85,7 +92,11 @@ if (CMAKE_C_COMPILE_FEATURES) endif() endif() -if (NOT CMAKE_CXX_COMPILE_FEATURES) +if (CMAKE_CXX_COMPILE_FEATURES) + set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES}) + list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]") +endif() +if (NOT CXX_expected_features) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp" "int main(int,char**) { return 0; }\n" ) diff --git a/Tests/Module/WriteCompilerDetectionHeader/main.cpp b/Tests/Module/WriteCompilerDetectionHeader/main.cpp index 192094c1b..9979cbae6 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/main.cpp +++ b/Tests/Module/WriteCompilerDetectionHeader/main.cpp @@ -8,6 +8,9 @@ #error Expect no C features defined #endif +TEST_STATIC_ASSERT(true); +TEST_STATIC_ASSERT_MSG(true, "msg"); + int main() { return 0; diff --git a/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp b/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp index 1635091cb..d1f178f7c 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp +++ b/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp @@ -8,6 +8,9 @@ #error Expect no C features defined #endif +MULTI_STATIC_ASSERT(true); +MULTI_STATIC_ASSERT_MSG(true, "msg"); + int main() { return 0; diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt index bfbb343bc..e49ebea52 100644 --- a/Tests/ModuleDefinition/CMakeLists.txt +++ b/Tests/ModuleDefinition/CMakeLists.txt @@ -4,6 +4,8 @@ project(ModuleDefinition C) # Test .def file source recognition for DLLs. add_library(example_dll SHARED example_dll.c example_dll.def) +add_library(split_dll SHARED split_dll.c split_dll_1.def split_dll_2.def) + # Test generated .def file. add_custom_command(OUTPUT example_dll_gen.def DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/example_dll_gen.def.in @@ -24,7 +26,12 @@ endif() # Test .def file source recognition for EXEs. add_executable(example_exe example_exe.c example_exe.def) set_property(TARGET example_exe PROPERTY ENABLE_EXPORTS 1) -target_link_libraries(example_exe example_dll example_dll_gen ${example_dll_2}) +target_link_libraries(example_exe + example_dll + example_dll_gen + ${example_dll_2} + split_dll + ) # Test linking to the executable. add_library(example_mod_1 MODULE example_mod_1.c) diff --git a/Tests/ModuleDefinition/example_exe.c b/Tests/ModuleDefinition/example_exe.c index dff566f10..8e86fc454 100644 --- a/Tests/ModuleDefinition/example_exe.c +++ b/Tests/ModuleDefinition/example_exe.c @@ -3,15 +3,19 @@ extern int __declspec(dllimport) example_dll_gen_function(void); #ifdef EXAMPLE_DLL_2 extern int __declspec(dllimport) example_dll_2_function(void); #endif +extern int __declspec(dllimport) split_dll_1(void); +extern int __declspec(dllimport) split_dll_2(void); + int example_exe_function(void) { return 0; } + int main(void) { return example_dll_function() + example_dll_gen_function() + #ifdef EXAMPLE_DLL_2 example_dll_2_function() + #endif - example_exe_function(); + split_dll_1() + split_dll_2() + example_exe_function(); } diff --git a/Tests/ModuleDefinition/split_dll.c b/Tests/ModuleDefinition/split_dll.c new file mode 100644 index 000000000..1546a2dc9 --- /dev/null +++ b/Tests/ModuleDefinition/split_dll.c @@ -0,0 +1,9 @@ +int split_dll_1(void) +{ + return 0; +} + +int split_dll_2(void) +{ + return 0; +} diff --git a/Tests/ModuleDefinition/split_dll_1.def b/Tests/ModuleDefinition/split_dll_1.def new file mode 100644 index 000000000..ced9f1020 --- /dev/null +++ b/Tests/ModuleDefinition/split_dll_1.def @@ -0,0 +1,2 @@ +EXPORTS +split_dll_1 diff --git a/Tests/ModuleDefinition/split_dll_2.def b/Tests/ModuleDefinition/split_dll_2.def new file mode 100644 index 000000000..b072c506f --- /dev/null +++ b/Tests/ModuleDefinition/split_dll_2.def @@ -0,0 +1,2 @@ +EXPORTS +split_dll_2 diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt index e3476df11..4bffd1221 100644 --- a/Tests/ObjectLibrary/CMakeLists.txt +++ b/Tests/ObjectLibrary/CMakeLists.txt @@ -16,11 +16,7 @@ add_custom_command(TARGET UseCshared POST_BUILD COMMAND ${CMAKE_COMMAND} -P ${CM add_executable(UseCinternal main.c c.c $ $) -if("${CMAKE_GENERATOR}" MATCHES "^Visual Studio (7|7 .NET 2003)$") - # VS 7 generators do not add objects as sources so we need a - # dummy object to convince the IDE to build the targets below. - set(dummy dummy.obj) # In MinGW: gcc -c dummy.c -o dummy.obj -elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") +if("${CMAKE_GENERATOR}" MATCHES "Xcode") # Xcode does not seem to support targets without sources. set(dummy dummy.c) endif() diff --git a/Tests/Plugin/CMakeLists.txt b/Tests/Plugin/CMakeLists.txt index f52b47954..9e2b4abd9 100644 --- a/Tests/Plugin/CMakeLists.txt +++ b/Tests/Plugin/CMakeLists.txt @@ -2,6 +2,9 @@ cmake_minimum_required (VERSION 2.6) cmake_policy(SET CMP0054 NEW) project(Plugin) +# We need proper C++98 support from the compiler +set(CMAKE_CXX_STANDARD 98) + # Test per-target output directory properties. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${Plugin_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${Plugin_BINARY_DIR}/lib/plugin) @@ -25,9 +28,6 @@ include_directories( ${Plugin_SOURCE_DIR}/include ) -# We need proper C++98 support from the compiler -set(CMAKE_CXX_STANDARD 98) - # Those versions of the HP compiler that need a flag to get proper C++98 # template support also need a flag to use the newer C++ library. if (CMAKE_CXX_COMPILER_ID STREQUAL HP AND diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt index 807a4272c..8c2cdc9e7 100644 --- a/Tests/Preprocess/CMakeLists.txt +++ b/Tests/Preprocess/CMakeLists.txt @@ -25,9 +25,6 @@ endif() if("${CMAKE_GENERATOR}" MATCHES "Watcom WMake") set(PP_WATCOM 1) endif() -if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 7$") - set(PP_VS70 1) -endif() if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") set(PP_VS 1) endif() @@ -46,14 +43,11 @@ endif() # must not have it escaped inside the configured header. set(STRING_EXTRA "") -if(NOT BORLAND AND NOT PP_VS70) - # Borland, VS70 IDE: ; +if(NOT BORLAND) + # Borland: ; # The Borland compiler will simply not accept a non-escaped semicolon # on the command line. If it is escaped \; then the escape character # shows up in the preprocessing output too. - # - # The VS 7.0 IDE separates definitions on semicolons and commas with - # no regard for quotes. Fortunately VS 7.1 and above are okay. set(SEMICOLON "\;") endif() diff --git a/Tests/QtAutoUicInterface/CMakeLists.txt b/Tests/QtAutoUicInterface/CMakeLists.txt index 70175fb67..3ea12943a 100644 --- a/Tests/QtAutoUicInterface/CMakeLists.txt +++ b/Tests/QtAutoUicInterface/CMakeLists.txt @@ -53,6 +53,12 @@ set_property(TARGET KI18n APPEND PROPERTY # END upstream +if(${CMAKE_GENERATOR} MATCHES "Visual Studio") +set(INC_DIR "include_${CMAKE_BUILD_TYPE}" ) +else() +set(INC_DIR "include" ) +endif() + add_library(LibWidget libwidget.cpp) target_link_libraries(LibWidget KI18n ${QT_GUI_TARGET}) set_property(TARGET LibWidget PROPERTY NO_KUIT_SEMANTIC ON) @@ -64,6 +70,6 @@ target_link_libraries(MyWidget KI18n ${QT_GUI_TARGET}) add_executable(QtAutoUicInterface main.cpp) target_compile_definitions(QtAutoUicInterface PRIVATE - UI_LIBWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/LibWidget_autogen/include/ui_libwidget.h" - UI_MYWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/MyWidget_autogen/include/ui_mywidget.h" + UI_LIBWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/LibWidget_autogen/${INC_DIR}/ui_libwidget.h" + UI_MYWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/MyWidget_autogen/${INC_DIR}/ui_mywidget.h" ) diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 4b90ad8ed..073c5fdef 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -46,26 +46,26 @@ endif() get_property(QT_COMPILE_FEATURES TARGET ${QT_QTCORE_TARGET} PROPERTY INTERFACE_COMPILE_FEATURES) -# -- Test: AUTORCC +# -- Test # RCC only add_executable(rccOnly rccOnly.cpp rccOnlyRes.qrc) set_property(TARGET rccOnly PROPERTY AUTORCC ON) target_link_libraries(rccOnly ${QT_QTCORE_TARGET}) -# -- Test: AUTORCC +# -- Test # RCC empty add_executable(rccEmpty rccEmpty.cpp rccEmptyRes.qrc) set_property(TARGET rccEmpty PROPERTY AUTORCC ON) target_link_libraries(rccEmpty ${QT_QTCORE_TARGET}) -# -- Test: AUTOUIC +# -- Test # UIC only qtx_wrap_cpp(uicOnlyMoc uicOnlySource/uiconly.h) add_executable(uicOnly uicOnlySource/uiconly.cpp ${uicOnlyMoc}) set_property(TARGET uicOnly PROPERTY AUTOUIC ON) target_link_libraries(uicOnly ${QT_LIBRARIES}) -# -- Test: AUTOMOC, AUTORCC +# -- Test # Add not_generated_file.qrc to the source list to get the file-level # dependency, but don't generate a c++ file from it. Disable the AUTORCC # feature for this target. This tests that qrc files in the sources don't @@ -80,66 +80,134 @@ set_target_properties(no_link_language PROPERTIES AUTOMOC TRUE) target_compile_features(no_link_language PRIVATE ${QT_COMPILE_FEATURES}) target_compile_features(empty PRIVATE ${QT_COMPILE_FEATURES}) -# -- Test: AUTORCC +# -- Test # When a file listed in a .qrc file changes the target must be rebuilt +set(timeformat "%Y%j%H%M%S") +set(RCC_DEPENDS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/rccDepends") +set(RCC_DEPENDS_BIN "${CMAKE_CURRENT_BINARY_DIR}/rccDepends") +configure_file(${RCC_DEPENDS_SRC}/res1a.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY) +configure_file(${RCC_DEPENDS_SRC}/res2a.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY) try_compile(RCC_DEPENDS - "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" - "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends" - autorcc_depends - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + "${RCC_DEPENDS_BIN}" + "${RCC_DEPENDS_SRC}" + rccDepends + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) if (NOT RCC_DEPENDS) - message(SEND_ERROR "Initial build of autorcc_depends failed. Output: ${output}") + message(SEND_ERROR "Initial build of rccDepends failed. Output: ${output}") endif() - -file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends/info_file.txt" qrc_files) - -list(GET qrc_files 0 qrc_file1) - -set(timeformat "%Y%j%H%M%S") - -file(TIMESTAMP "${qrc_file1}" file1_before "${timeformat}") - +# Get name and timestamp of the output binary +file(STRINGS "${RCC_DEPENDS_BIN}/target.txt" targetList) +list(GET targetList 0 rccDependsBin) +file(TIMESTAMP "${rccDependsBin}" timeBegin "${timeformat}") +# Sleep, touch regular qrc input file, rebuild and compare timestamp execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends/res1/input.txt") - -execute_process(COMMAND "${CMAKE_COMMAND}" --build . - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" -) - -file(TIMESTAMP "${qrc_file1}" file1_step1 "${timeformat}") - -if (NOT file1_step1 GREATER file1_before) - message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first step!") +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/input.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Second build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep1 "${timeformat}") +if (NOT timeStep1 GREATER timeBegin) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the first step!") +endif() +# Sleep, update regular qrc file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +configure_file(${RCC_DEPENDS_SRC}/res1b.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY) +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Third build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep2 "${timeformat}") +if (NOT timeStep2 GREATER timeStep1) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the second step!") +endif() +# Sleep, touch regular qrc newly added input file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/inputAdded.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Fourth build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep3 "${timeformat}") +if (NOT timeStep3 GREATER timeStep2) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the third step!") +endif() +# Sleep, touch generated qrc input file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/input.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Fifth build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep4 "${timeformat}") +if (NOT timeStep4 GREATER timeStep3) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fourth step!") +endif() +# Sleep, update generated qrc file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +configure_file(${RCC_DEPENDS_SRC}/res2b.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY) +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Sixth build of rccDepends failed.") endif() +file(TIMESTAMP "${rccDependsBin}" timeStep5 "${timeformat}") +if (NOT timeStep5 GREATER timeStep4) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fitfh step!") +endif() +# Sleep, touch generated qrc newly added input file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/inputAdded.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Seventh build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep6 "${timeformat}") +if (NOT timeStep6 GREATER timeStep5) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the sixth step!") +endif() + -# -- Test: AUTOMOC +# -- Test # Ensure a repeated build succeeds when a header containing a QObject changes +set(timeformat "%Y%j%H%M%S") +configure_file(mocRerun/test1a.h.in mocRerun/test1.h COPYONLY) try_compile(MOC_RERUN - "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" - "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun" - automoc_rerun - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" + "${CMAKE_CURRENT_SOURCE_DIR}/mocRerun" + mocRerun + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) if (NOT MOC_RERUN) - message(SEND_ERROR "Initial build of automoc_rerun failed. Output: ${output}") + message(SEND_ERROR "Initial build of mocRerun failed. Output: ${output}") endif() - -configure_file(automoc_rerun/test1.h.in2 automoc_rerun/test1.h COPYONLY) - +# Get name and timestamp of the output binary +file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/mocRerun/target1.txt" target1List) +list(GET target1List 0 binFile) +file(TIMESTAMP "${binFile}" timeBegin "${timeformat}") +# Change file content and rebuild +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) +configure_file(mocRerun/test1b.h.in mocRerun/test1.h COPYONLY) execute_process(COMMAND "${CMAKE_COMMAND}" --build . - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" - RESULT_VARIABLE automoc_rerun_result + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" + RESULT_VARIABLE mocRerun_result ) -if (automoc_rerun_result) - message(SEND_ERROR "Second build of automoc_rerun failed.") +if (mocRerun_result) + message(SEND_ERROR "Second build of mocRerun failed.") +endif() +# Compare timestamps +file(TIMESTAMP "${binFile}" timeStep1 "${timeformat}") +if (NOT timeStep1 GREATER timeBegin) + message(SEND_ERROR "File (${binFile}) should have changed in the first step!") endif() -# -- Test: AUTOMOC, SKIP_AUTOMOC +# -- Test # Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target qtx_wrap_cpp(skipMocWrapMoc skipSource/qItemA.hpp @@ -161,7 +229,7 @@ set_property(TARGET skipMocB PROPERTY AUTOMOC ON) set_property(TARGET skipMocB PROPERTY AUTOUIC ON) target_link_libraries(skipMocB ${QT_LIBRARIES}) -# -- Test: AUTOUIC, SKIP_AUTOUIC +# -- Test # Test for SKIP_AUTOUIC and SKIP_AUTOGEN on an AUTOUIC enabled target set(skipUicSources skipUic.cpp @@ -181,7 +249,7 @@ set_property(TARGET skipUicB PROPERTY AUTOUIC ON) set_property(TARGET skipUicB PROPERTY AUTOMOC ON) target_link_libraries(skipUicB ${QT_LIBRARIES}) -# -- Test: AUTORCC, SKIP_AUTORCC +# -- Test # Test for SKIP_AUTORCC and SKIP_AUTOGEN on an AUTORCC enabled target set(skipRccSources skipRcc.cpp @@ -202,10 +270,96 @@ set_property(TARGET skipRccB PROPERTY AUTOUIC ON) set_property(TARGET skipRccB PROPERTY AUTOMOC ON) target_link_libraries(skipRccB ${QT_LIBRARIES}) -# -- Test: AUTOMOC AUTORCC +# -- Test # Source files with the same basename in different subdirectories add_subdirectory(sameName) -# -- Test: AUTOMOC AUTORCC AUTOUIC +# -- Test +# Tests AUTOMOC with generated sources +add_subdirectory(mocDepends) + +# -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeStrict) + +# -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeRelaxed) + +# -- Test +# Tests Q_PLUGIN_METADATA json file change detection +if (NOT QT_TEST_VERSION STREQUAL 4) + try_compile(MOC_PLUGIN + "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" + "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin" + mocPlugin + CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" + OUTPUT_VARIABLE output + ) + if (NOT MOC_PLUGIN) + message(SEND_ERROR "Initial build of mocPlugin failed. Output: ${output}") + endif() + + set(timeformat "%Y%j%H%M%S") + set(mocPlugSrcDir "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin") + set(mocPlugBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") + find_library(plAFile "PlugA" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plBFile "PlugB" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plCFile "PlugC" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plDFile "PlugD" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + + file(TIMESTAMP "${plAFile}" plABefore "${timeformat}") + file(TIMESTAMP "${plBFile}" plBBefore "${timeformat}") + file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}") + file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}") + + # Ensure that the timestamp will change and change the json files + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC.json") + configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD.json") + execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}") + + file(TIMESTAMP "${plAFile}" plAAfter "${timeformat}") + file(TIMESTAMP "${plBFile}" plBAfter "${timeformat}") + file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}") + file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}") + + if (plAAfter GREATER plABefore) + message(SEND_ERROR "file (${plAFile}) should not have changed!") + endif() + if (plBAfter GREATER plBBefore) + message(SEND_ERROR "file (${plBFile}) should not have changed!") + endif() + if (NOT plCAfter GREATER plCBefore) + message(SEND_ERROR "file (${plCFile}) should have changed!") + endif() + if (NOT plDAfter GREATER plDBefore) + message(SEND_ERROR "file (${plDFile}) should have changed!") + endif() + + # Test custom macro + file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}") + file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}") + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC_Custom.json") + configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD_Custom.json") + execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}") + file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}") + file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}") + if (NOT plCAfter GREATER plCBefore) + message(SEND_ERROR "file (${plCFile}) should have changed!") + endif() + if (NOT plDAfter GREATER plDBefore) + message(SEND_ERROR "file (${plDFile}) should have changed!") + endif() + +endif() + +# -- Test +# Tests various .ui include directories +add_subdirectory(uicInclude) + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/automoc_rerun/CMakeLists.txt b/Tests/QtAutogen/automoc_rerun/CMakeLists.txt deleted file mode 100644 index 92a682baf..000000000 --- a/Tests/QtAutogen/automoc_rerun/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 3.7) -project(automoc_rerun CXX) - -if (QT_TEST_VERSION STREQUAL 4) - find_package(Qt4 REQUIRED) - set(QT_CORE_TARGET Qt4::QtCore) -else() - if (NOT QT_TEST_VERSION STREQUAL 5) - message(SEND_ERROR "Invalid Qt version specified.") - endif() - - find_package(Qt5Core REQUIRED) - set(QT_CORE_TARGET Qt5::Core) -endif() - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - -configure_file(test1.h.in1 test1.h COPYONLY) - -add_executable(test1 - ${CMAKE_CURRENT_BINARY_DIR}/test1.h - test1.cpp - res1.qrc - ) -target_include_directories(test1 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -target_link_libraries(test1 ${QT_CORE_TARGET}) diff --git a/Tests/QtAutogen/automoc_rerun/test1.cpp b/Tests/QtAutogen/automoc_rerun/test1.cpp deleted file mode 100644 index 4316a91cb..000000000 --- a/Tests/QtAutogen/automoc_rerun/test1.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "test1.h" -int main() -{ - return 0; -} diff --git a/Tests/QtAutogen/automoc_rerun/test1.h.in1 b/Tests/QtAutogen/automoc_rerun/test1.h.in1 deleted file mode 100644 index fee2c096b..000000000 --- a/Tests/QtAutogen/automoc_rerun/test1.h.in1 +++ /dev/null @@ -1,8 +0,0 @@ -#include -class test1 : public QObject -{ - Q_OBJECT - public slots: - void onTst1() {} - void onTst2() {} -}; diff --git a/Tests/QtAutogen/automoc_rerun/test1.h.in2 b/Tests/QtAutogen/automoc_rerun/test1.h.in2 deleted file mode 100644 index 6531d10d5..000000000 --- a/Tests/QtAutogen/automoc_rerun/test1.h.in2 +++ /dev/null @@ -1,7 +0,0 @@ -#include -class test1 : public QObject -{ - Q_OBJECT - public slots: - void onTst1() {} -}; diff --git a/Tests/QtAutogen/autorcc_depends/CMakeLists.txt b/Tests/QtAutogen/autorcc_depends/CMakeLists.txt deleted file mode 100644 index 7b51e11ad..000000000 --- a/Tests/QtAutogen/autorcc_depends/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 3.7) -project(autorcc_depends) - -set(CMAKE_AUTORCC ON) - -if (QT_TEST_VERSION STREQUAL 4) - find_package(Qt4 REQUIRED) - set(QT_CORE_TARGET Qt4::QtCore) -else() - if (NOT QT_TEST_VERSION STREQUAL 5) - message(SEND_ERROR "Invalid Qt version specified.") - endif() - - find_package(Qt5Core REQUIRED) - set(QT_CORE_TARGET Qt5::Core) -endif() - -configure_file(res1.qrc.in res1.qrc @ONLY) -configure_file(res1/input.txt.in res1/input.txt @ONLY) - -add_executable(test_res1 - test_res1.cpp - ${CMAKE_CURRENT_BINARY_DIR}/res1.qrc -) -target_link_libraries(test_res1 ${QT_CORE_TARGET}) -add_custom_command(TARGET test_res1 POST_BUILD COMMAND - ${CMAKE_COMMAND} -E echo "$" > info_file.txt) diff --git a/Tests/QtAutogen/mocDepends/CMakeLists.txt b/Tests/QtAutogen/mocDepends/CMakeLists.txt new file mode 100644 index 000000000..a67dcfe1a --- /dev/null +++ b/Tests/QtAutogen/mocDepends/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.7) +project(mocDepends) + +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + set(QT_CORE_TARGET Qt4::QtCore) +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + + find_package(Qt5Core REQUIRED) + set(QT_CORE_TARGET Qt5::Core) +endif() + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# -- Test 1 using generated header +# This tests the dependency of AUTOMOC of mocDepends1 to the generated object.hpp +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/object.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp + ) + +add_executable(mocDepends1 test1.cpp + ${CMAKE_CURRENT_BINARY_DIR}/object.hpp +) +target_link_libraries(mocDepends1 ${QT_CORE_TARGET}) +set_target_properties(mocDepends1 PROPERTIES AUTOMOC TRUE) +set_property(TARGET mocDepends1 PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1) + +# -- Test 2 using generated library +# This tests the dependency of AUTOMOC of mocDepends2 to the +# generated simpleLib.hpp which belongs to a linked library of mocDepends2 +add_custom_command(OUTPUT simpleLib.hpp simpleLib.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp + ) +add_library(SimpleLib STATIC simpleLib.hpp simpleLib.cpp) + +add_executable(mocDepends2 test2.cpp ) +target_link_libraries(mocDepends2 SimpleLib ${QT_CORE_TARGET}) +set_target_properties(mocDepends2 PROPERTIES AUTOMOC TRUE) +set_property(TARGET mocDepends2 PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1) diff --git a/Tests/QtAutogen/mocDepends/invalid.hpp.in b/Tests/QtAutogen/mocDepends/invalid.hpp.in new file mode 100644 index 000000000..854d9a143 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/invalid.hpp.in @@ -0,0 +1 @@ +#ifndef diff --git a/Tests/QtAutogen/mocDepends/object.hpp.in b/Tests/QtAutogen/mocDepends/object.hpp.in new file mode 100644 index 000000000..f364f7c97 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/object.hpp.in @@ -0,0 +1,14 @@ +#ifndef OBJECT_HPP +#define OBJECT_HPP + +#include + +class Object : public QObject +{ + Q_OBJECT +public: + Q_SLOT + void aSlot(){}; +}; + +#endif diff --git a/Tests/QtAutogen/mocDepends/simpleLib.cpp.in b/Tests/QtAutogen/mocDepends/simpleLib.cpp.in new file mode 100644 index 000000000..fa33bd375 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/simpleLib.cpp.in @@ -0,0 +1,9 @@ +#include "simpleLib.hpp" + +SimpleLib::SimpleLib() +{ +} + +SimpleLib::~SimpleLib() +{ +} diff --git a/Tests/QtAutogen/mocDepends/simpleLib.hpp.in b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in new file mode 100644 index 000000000..758f1f671 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in @@ -0,0 +1,11 @@ +#ifndef SIMPLE_LIB_H +#define SIMPLE_LIB_H + +class SimpleLib +{ +public: + SimpleLib(); + ~SimpleLib(); +}; + +#endif diff --git a/Tests/QtAutogen/mocDepends/test1.cpp b/Tests/QtAutogen/mocDepends/test1.cpp new file mode 100644 index 000000000..92c259c09 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/test1.cpp @@ -0,0 +1,9 @@ + +#include "object.hpp" + +int main() +{ + Object obj; + + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/test2.cpp b/Tests/QtAutogen/mocDepends/test2.cpp new file mode 100644 index 000000000..155b19b75 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/test2.cpp @@ -0,0 +1,10 @@ + +#include "test2.hpp" + +int main() +{ + SimpleLib obj; + LObject lobject; + + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/test2.hpp b/Tests/QtAutogen/mocDepends/test2.hpp new file mode 100644 index 000000000..0125f07b8 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/test2.hpp @@ -0,0 +1,16 @@ +#ifndef TEST2_HPP +#define TEST2_HPP + +#include "simpleLib.hpp" +#include + +// This object triggers the AUTOMOC on this file +class LObject : public QObject +{ + Q_OBJECT +public: + Q_SLOT + void aSlot(){}; +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp new file mode 100644 index 000000000..1b0311d30 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.cpp @@ -0,0 +1,24 @@ +#include "ObjA.hpp" + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() {} + ~SubObjA() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjA::aSlot() +{ +} + +void ObjA::go() +{ + SubObjA subObj; +} + +#include "ObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp new file mode 100644 index 000000000..281e90d86 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.hpp @@ -0,0 +1,13 @@ +#ifndef OBJA_HPP +#define OBJA_HPP + +#include + +class ObjA : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp new file mode 100644 index 000000000..5ff315dc7 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.cpp @@ -0,0 +1,25 @@ +#include "ObjB.hpp" + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() {} + ~SubObjB() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjB::aSlot() +{ +} + +void ObjB::go() +{ + SubObjB subObj; +} + +#include "ObjB.moc" +#include "moc_ObjB.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp new file mode 100644 index 000000000..94f3d498c --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.hpp @@ -0,0 +1,13 @@ +#ifndef OBJB_HPP +#define OBJB_HPP + +#include + +class ObjB : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp new file mode 100644 index 000000000..8ca34cbb4 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.cpp @@ -0,0 +1,26 @@ +#include "ObjC.hpp" + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() {} + ~SubObjC() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjC::aSlot() +{ +} + +void ObjC::go() +{ + SubObjC subObj; +} + +#include "ObjC.moc" +// Not the own header +#include "moc_ObjD.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjC.hpp b/Tests/QtAutogen/mocInclude/ObjC.hpp new file mode 100644 index 000000000..a8e98eb1e --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.hpp @@ -0,0 +1,13 @@ +#ifndef OBJC_HPP +#define OBJC_HPP + +#include + +class ObjC : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjD.cpp b/Tests/QtAutogen/mocInclude/ObjD.cpp new file mode 100644 index 000000000..c18aec152 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.cpp @@ -0,0 +1,26 @@ +#include "ObjD.hpp" + +class SubObjD : public QObject +{ + Q_OBJECT + +public: + SubObjD() {} + ~SubObjD() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjD::aSlot() +{ +} + +void ObjD::go() +{ + SubObjD subObj; +} + +#include "ObjD.moc" +// Header in subdirectory +#include "subA/moc_SubObjA.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjD.hpp b/Tests/QtAutogen/mocInclude/ObjD.hpp new file mode 100644 index 000000000..b6ee09808 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.hpp @@ -0,0 +1,13 @@ +#ifndef OBJD_HPP +#define OBJD_HPP + +#include + +class ObjD : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp new file mode 100644 index 000000000..a05f6e37e --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp @@ -0,0 +1,27 @@ +#include "SubObjA.hpp" + +namespace subA { + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() {} + ~SubObjA() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjA::aSlot() +{ +} + +void ObjA::go() +{ + SubObjA subObj; +} +} + +#include "SubObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp new file mode 100644 index 000000000..31a18b618 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJA_HPP +#define SUBOBJA_HPP + +#include + +namespace subA { + +class ObjA : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp new file mode 100644 index 000000000..1e77639b2 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp @@ -0,0 +1,27 @@ +#include "SubObjB.hpp" + +namespace subB { + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() {} + ~SubObjB() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjB::aSlot() +{ +} + +void ObjB::go() +{ + SubObjB subObj; +} +} + +#include "SubObjB.moc" diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp new file mode 100644 index 000000000..3f29fa289 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJB_HPP +#define SUBOBJB_HPP + +#include + +namespace subB { + +class ObjB : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp new file mode 100644 index 000000000..c2d94ef26 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp @@ -0,0 +1,27 @@ +#include "SubObjC.hpp" + +namespace subC { + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() {} + ~SubObjC() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjC::aSlot() +{ +} + +void ObjC::go() +{ + SubObjC subObj; +} +} + +#include "SubObjC.moc" diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp new file mode 100644 index 000000000..dc251fd61 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJC_HPP +#define SUBOBJC_HPP + +#include + +namespace subC { + +class ObjC : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt new file mode 100644 index 000000000..6a0829df7 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE TRUE) + +include_directories("../mocInclude") + +add_executable(mocIncludeRelaxed + ../mocInclude/ObjA.cpp + ../mocInclude/ObjB.cpp + ../mocInclude/ObjC.cpp + ../mocInclude/ObjD.cpp + ../mocInclude/subA/SubObjA.cpp + ../mocInclude/subB/SubObjB.cpp + ../mocInclude/subC/SubObjC.cpp + main.cpp +) +target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES}) +set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp new file mode 100644 index 000000000..142d59e69 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt new file mode 100644 index 000000000..22e93a8ba --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE FALSE) + +include_directories("../mocInclude") + +add_executable(mocIncludeStrict + ../mocInclude/ObjA.cpp + ../mocInclude/ObjB.cpp + ../mocInclude/ObjC.cpp + ../mocInclude/ObjD.cpp + ../mocInclude/subA/SubObjA.cpp + ../mocInclude/subB/SubObjB.cpp + ../mocInclude/subC/SubObjC.cpp + main.cpp +) +target_link_libraries(mocIncludeStrict ${QT_LIBRARIES}) +set_target_properties(mocIncludeStrict PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp new file mode 100644 index 000000000..142d59e69 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt new file mode 100644 index 000000000..f80aa2934 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.8) +project(mocPlugin CXX) + +set(CMAKE_AUTOMOC_DEPEND_FILTERS + "A_CUSTOM_MACRO" + "[\n][ \t]*A_CUSTOM_MACRO[ \t\r\n]*\\([^,]+,[ \t\r\n]*\"([^\"]+)\"" + ) + +if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") +endif() +find_package(Qt5Widgets REQUIRED) + +if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) +endif() + +configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json) +configure_file(jsonIn/StyleC.json jsonFiles/StyleC_Custom.json) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD_Custom.json) + +# Enable automoc +set(CMAKE_AUTOMOC TRUE) + +include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles") +link_libraries(Qt5::Widgets) + +add_library(PlugA STATIC StyleA.cpp) +add_library(PlugB STATIC StyleB.cpp) +add_library(PlugC STATIC StyleC.cpp) +add_library(PlugD STATIC StyleD.cpp) +add_library(PlugE STATIC StyleE.cpp) diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogen/mocPlugin/StyleA.cpp new file mode 100644 index 000000000..b5e87533c --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +QStyle* StyleA::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp new file mode 100644 index 000000000..1b6154d16 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp @@ -0,0 +1,17 @@ +#ifndef STYLEA_HPP +#define STYLEA_HPP + +#include "StyleCommon.hpp" +#include + +class StyleA : public QStylePlugin +{ + Q_OBJECT + // Json file in local directory + Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json") + A_CUSTOM_MACRO(SomeArg, "StyleA_Custom.json", AnotherArg) +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogen/mocPlugin/StyleA.json new file mode 100644 index 000000000..cc3395369 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "Starbuster" ] } diff --git a/Tests/QtAutogen/mocPlugin/StyleA_Custom.json b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json new file mode 100644 index 000000000..cc3395369 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "Starbuster" ] } diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogen/mocPlugin/StyleB.cpp new file mode 100644 index 000000000..17d440035 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.cpp @@ -0,0 +1,6 @@ +#include "StyleB.hpp" + +QStyle* StyleB::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp new file mode 100644 index 000000000..163c9b20a --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp @@ -0,0 +1,17 @@ +#ifndef STYLEB_HPP +#define STYLEB_HPP + +#include "StyleCommon.hpp" +#include + +class StyleB : public QStylePlugin +{ + Q_OBJECT + // Json file in local subdirectory + Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json") + A_CUSTOM_MACRO(SomeArg, "jsonIn/StyleB_Custom.json", AnotherArg) +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogen/mocPlugin/StyleC.cpp new file mode 100644 index 000000000..37e756487 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.cpp @@ -0,0 +1,6 @@ +#include "StyleC.hpp" + +QStyle* StyleC::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp new file mode 100644 index 000000000..52a887acf --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp @@ -0,0 +1,17 @@ +#ifndef STYLEC_HPP +#define STYLEC_HPP + +#include "StyleCommon.hpp" +#include + +class StyleC : public QStylePlugin +{ + Q_OBJECT + // Json file in global root directory + Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json") + A_CUSTOM_MACRO(SomeArg, "StyleC_Custom.json", AnotherArg) +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleCommon.hpp b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp new file mode 100644 index 000000000..f1a7ec60d --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp @@ -0,0 +1,7 @@ +#ifndef STYLECOMMON_HPP +#define STYLECOMMON_HPP + +// Empty test macro definition +#define A_CUSTOM_MACRO(name, jsonFile, pluginRegistrations) + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp new file mode 100644 index 000000000..7e4b121fc --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -0,0 +1,6 @@ +#include "StyleD.hpp" + +QStyle* StyleD::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp new file mode 100644 index 000000000..df8a4399d --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -0,0 +1,17 @@ +#ifndef STYLED_HPP +#define STYLED_HPP + +#include "StyleCommon.hpp" +#include + +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") + A_CUSTOM_MACRO(SomeArg, "sub/StyleD_Custom.json", AnotherArg) +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogen/mocPlugin/StyleE.cpp new file mode 100644 index 000000000..8fc9a7f68 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.cpp @@ -0,0 +1,6 @@ +#include "StyleE.hpp" + +QStyle* StyleE::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp new file mode 100644 index 000000000..e7915a8e5 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp @@ -0,0 +1,17 @@ +#ifndef STYLEE_HPP +#define STYLEE_HPP + +#include "StyleCommon.hpp" +#include + +class StyleE : public QStylePlugin +{ + Q_OBJECT + // No Json file + Q_PLUGIN_METADATA(IID "org.styles.E") + A_CUSTOM_MACRO(SomeArg, InvalidFileArg, AnotherArg) +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json new file mode 100644 index 000000000..129cac41f --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterB" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json new file mode 100644 index 000000000..129cac41f --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterB" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json new file mode 100644 index 000000000..119aaa4b7 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json @@ -0,0 +1 @@ +{ "Keys": [ "Boat", "Ship" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json new file mode 100644 index 000000000..732c547ab --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json @@ -0,0 +1 @@ +{ "Keys": [ "Bike", "Car" ] } diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogen/mocPlugin/main.cpp new file mode 100644 index 000000000..3ba2ddc6d --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/main.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +int main(int argv, char** args) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocRerun/CMakeLists.txt b/Tests/QtAutogen/mocRerun/CMakeLists.txt new file mode 100644 index 000000000..14b077b38 --- /dev/null +++ b/Tests/QtAutogen/mocRerun/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.7) +project(mocRerun CXX) + +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + set(QT_CORE_TARGET Qt4::QtCore) +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + + find_package(Qt5Core REQUIRED) + set(QT_CORE_TARGET Qt5::Core) +endif() + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +# Generated source file +add_custom_command(OUTPUT main.cpp + COMMAND ${CMAKE_COMMAND} -E sleep 2 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + ) + +add_executable(mocRerun + ${CMAKE_CURRENT_BINARY_DIR}/test1.h + ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + res1.qrc + ) +set_property(TARGET mocRerun PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1) +target_include_directories(mocRerun PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +target_link_libraries(mocRerun ${QT_CORE_TARGET}) +# Write target name to text file +add_custom_command(TARGET mocRerun POST_BUILD COMMAND + ${CMAKE_COMMAND} -E echo "$" > target1.txt) diff --git a/Tests/QtAutogen/automoc_rerun/input.txt b/Tests/QtAutogen/mocRerun/input.txt similarity index 100% rename from Tests/QtAutogen/automoc_rerun/input.txt rename to Tests/QtAutogen/mocRerun/input.txt diff --git a/Tests/QtAutogen/mocRerun/main.cpp.in b/Tests/QtAutogen/mocRerun/main.cpp.in new file mode 100644 index 000000000..b37ff61e2 --- /dev/null +++ b/Tests/QtAutogen/mocRerun/main.cpp.in @@ -0,0 +1,18 @@ +#include "test1.h" + +class Test2 : public QObject +{ + Q_OBJECT +public slots: + void onTst1() {} +}; + +int main() +{ + Test1 test1; + Test2 test2; + + return 0; +} + +#include "main.moc" diff --git a/Tests/QtAutogen/automoc_rerun/res1.qrc b/Tests/QtAutogen/mocRerun/res1.qrc similarity index 100% rename from Tests/QtAutogen/automoc_rerun/res1.qrc rename to Tests/QtAutogen/mocRerun/res1.qrc diff --git a/Tests/QtAutogen/mocRerun/test1a.h.in b/Tests/QtAutogen/mocRerun/test1a.h.in new file mode 100644 index 000000000..a335046ba --- /dev/null +++ b/Tests/QtAutogen/mocRerun/test1a.h.in @@ -0,0 +1,8 @@ +#include +class Test1 : public QObject +{ + Q_OBJECT +public slots: + void onTst1() {} + void onTst2() {} +}; diff --git a/Tests/QtAutogen/mocRerun/test1b.h.in b/Tests/QtAutogen/mocRerun/test1b.h.in new file mode 100644 index 000000000..6128eeba1 --- /dev/null +++ b/Tests/QtAutogen/mocRerun/test1b.h.in @@ -0,0 +1,7 @@ +#include +class Test1 : public QObject +{ + Q_OBJECT +public slots: + void onTst1() {} +}; diff --git a/Tests/QtAutogen/rccDepends/CMakeLists.txt b/Tests/QtAutogen/rccDepends/CMakeLists.txt new file mode 100644 index 000000000..878ae5d35 --- /dev/null +++ b/Tests/QtAutogen/rccDepends/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.7) +project(rccDepends) + +set(CMAKE_AUTORCC ON) + +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + set(QT_CORE_TARGET Qt4::QtCore) +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + + find_package(Qt5Core REQUIRED) + set(QT_CORE_TARGET Qt5::Core) +endif() + +configure_file(res/input1.txt.in res1/input.txt COPYONLY) +configure_file(res/input1.txt.in res1/inputAdded.txt COPYONLY) +configure_file(res/input2.txt.in res2/input.txt COPYONLY) +configure_file(res/input2.txt.in res2/inputAdded.txt COPYONLY) +# Dependency generated qrc file +add_custom_command(OUTPUT res2.qrc + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc.in + COMMAND ${CMAKE_COMMAND} -E sleep 2 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc + ) + +add_executable(rccDepends + main.cpp + ${CMAKE_CURRENT_BINARY_DIR}/res1.qrc + ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc ) +target_link_libraries(rccDepends ${QT_CORE_TARGET}) +add_custom_command(TARGET rccDepends POST_BUILD COMMAND + ${CMAKE_COMMAND} -E echo "$" > target.txt) diff --git a/Tests/QtAutogen/autorcc_depends/test_res1.cpp b/Tests/QtAutogen/rccDepends/main.cpp similarity index 100% rename from Tests/QtAutogen/autorcc_depends/test_res1.cpp rename to Tests/QtAutogen/rccDepends/main.cpp diff --git a/Tests/QtAutogen/autorcc_depends/res1/input.txt.in b/Tests/QtAutogen/rccDepends/res/input1.txt.in similarity index 100% rename from Tests/QtAutogen/autorcc_depends/res1/input.txt.in rename to Tests/QtAutogen/rccDepends/res/input1.txt.in diff --git a/Tests/QtAutogen/rccDepends/res/input2.txt.in b/Tests/QtAutogen/rccDepends/res/input2.txt.in new file mode 100644 index 000000000..08e14b7bd --- /dev/null +++ b/Tests/QtAutogen/rccDepends/res/input2.txt.in @@ -0,0 +1 @@ +Res2 input. diff --git a/Tests/QtAutogen/autorcc_depends/res1.qrc.in b/Tests/QtAutogen/rccDepends/res1a.qrc.in similarity index 66% rename from Tests/QtAutogen/autorcc_depends/res1.qrc.in rename to Tests/QtAutogen/rccDepends/res1a.qrc.in index 2a5417bbb..d111ffbc7 100644 --- a/Tests/QtAutogen/autorcc_depends/res1.qrc.in +++ b/Tests/QtAutogen/rccDepends/res1a.qrc.in @@ -1,5 +1,5 @@ - + res1/input.txt diff --git a/Tests/QtAutogen/rccDepends/res1b.qrc.in b/Tests/QtAutogen/rccDepends/res1b.qrc.in new file mode 100644 index 000000000..4cb3f047c --- /dev/null +++ b/Tests/QtAutogen/rccDepends/res1b.qrc.in @@ -0,0 +1,6 @@ + + + res1/input.txt + res1/inputAdded.txt + + diff --git a/Tests/QtAutogen/rccDepends/res2a.qrc.in b/Tests/QtAutogen/rccDepends/res2a.qrc.in new file mode 100644 index 000000000..19f34ac90 --- /dev/null +++ b/Tests/QtAutogen/rccDepends/res2a.qrc.in @@ -0,0 +1,5 @@ + + + res2/input.txt + + diff --git a/Tests/QtAutogen/rccDepends/res2b.qrc.in b/Tests/QtAutogen/rccDepends/res2b.qrc.in new file mode 100644 index 000000000..19e8ba10c --- /dev/null +++ b/Tests/QtAutogen/rccDepends/res2b.qrc.in @@ -0,0 +1,6 @@ + + + res2/input.txt + res2/inputAdded.txt + + diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt index 9e47a3e64..4d2dcd9d2 100644 --- a/Tests/QtAutogen/sameName/CMakeLists.txt +++ b/Tests/QtAutogen/sameName/CMakeLists.txt @@ -18,3 +18,14 @@ add_executable(sameName ) target_link_libraries(sameName ${QT_LIBRARIES}) set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE) + +# Set different compression levels +if (QT_TEST_VERSION STREQUAL 4) + set(rccCompress "-compress") +else() + set(rccCompress "--compress") +endif() +set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" ) +set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" ) +set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" ) +set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" ) diff --git a/Tests/QtAutogen/uicInclude/CMakeLists.txt b/Tests/QtAutogen/uicInclude/CMakeLists.txt new file mode 100644 index 000000000..f62ebb039 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/CMakeLists.txt @@ -0,0 +1,8 @@ +# Test moc include patterns + +set(CMAKE_AUTOUIC_SEARCH_PATHS "dirA") + +add_executable(uicInclude main.cpp) +target_link_libraries(uicInclude ${QT_LIBRARIES}) +set_target_properties(uicInclude PROPERTIES AUTOUIC ON) +set_property(TARGET uicInclude APPEND PROPERTY AUTOUIC_SEARCH_PATHS "dirB") diff --git a/Tests/QtAutogen/uicInclude/PageC.ui b/Tests/QtAutogen/uicInclude/PageC.ui new file mode 100644 index 000000000..bb2fb5e6a --- /dev/null +++ b/Tests/QtAutogen/uicInclude/PageC.ui @@ -0,0 +1,24 @@ + + + PageC + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + + diff --git a/Tests/QtAutogen/uicInclude/dirA/PageA.ui b/Tests/QtAutogen/uicInclude/dirA/PageA.ui new file mode 100644 index 000000000..dd8180292 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/dirA/PageA.ui @@ -0,0 +1,24 @@ + + + PageA + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + + diff --git a/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui b/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui new file mode 100644 index 000000000..fa6dfa615 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui @@ -0,0 +1,24 @@ + + + PageB + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + + + + + diff --git a/Tests/QtAutogen/uicInclude/main.cpp b/Tests/QtAutogen/uicInclude/main.cpp new file mode 100644 index 000000000..4ca66a706 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/main.cpp @@ -0,0 +1,10 @@ + +#include "main.hpp" + +int main(int argv, char** args) +{ + return 0; +} + +#include "sub/ui_PageB.h" +#include "ui_PageC.h" diff --git a/Tests/QtAutogen/uicInclude/main.hpp b/Tests/QtAutogen/uicInclude/main.hpp new file mode 100644 index 000000000..58ddc261f --- /dev/null +++ b/Tests/QtAutogen/uicInclude/main.hpp @@ -0,0 +1,6 @@ +#ifndef MAIN_HPP +#define MAIN_HPP + +#include "ui_PageA.h" + +#endif diff --git a/Tests/RunCMake/Android/android_sysinc.c b/Tests/RunCMake/Android/android_sysinc.c new file mode 100644 index 000000000..18d73dbc8 --- /dev/null +++ b/Tests/RunCMake/Android/android_sysinc.c @@ -0,0 +1,7 @@ +#include + +#ifndef NOT_SYSTEM_DLFCN_HEADER +#error "sysroot /usr/include appears too early" +#endif + +#include "android.c" diff --git a/Tests/RunCMake/Android/android_sysinc.cxx b/Tests/RunCMake/Android/android_sysinc.cxx new file mode 100644 index 000000000..5c5694b8d --- /dev/null +++ b/Tests/RunCMake/Android/android_sysinc.cxx @@ -0,0 +1,7 @@ +#include + +#ifndef NOT_SYSTEM_DLFCN_HEADER +#error "sysroot /usr/include appears too early" +#endif + +#include "android.cxx" diff --git a/Tests/RunCMake/Android/common.cmake b/Tests/RunCMake/Android/common.cmake index bef2428cb..015f2029e 100644 --- a/Tests/RunCMake/Android/common.cmake +++ b/Tests/RunCMake/Android/common.cmake @@ -92,3 +92,19 @@ if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") endif() add_executable(android_c android.c) add_executable(android_cxx android.cxx) + +# Test that an explicit /usr/include is ignored in favor of +# appearing as a standard include directory at the end. +set(sysinc_dirs) +if(CMAKE_ANDROID_NDK) + if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) + list(APPEND sysinc_dirs ${CMAKE_SYSROOT_COMPILE}/usr/include) + else() + list(APPEND sysinc_dirs ${CMAKE_SYSROOT}/usr/include) + endif() +endif() +list(APPEND sysinc_dirs ${CMAKE_CURRENT_SOURCE_DIR}/sysinc) +add_executable(android_sysinc_c android_sysinc.c) +target_include_directories(android_sysinc_c SYSTEM PRIVATE ${sysinc_dirs}) +add_executable(android_sysinc_cxx android_sysinc.cxx) +target_include_directories(android_sysinc_cxx SYSTEM PRIVATE ${sysinc_dirs}) diff --git a/Tests/RunCMake/Android/sysinc/dlfcn.h b/Tests/RunCMake/Android/sysinc/dlfcn.h new file mode 100644 index 000000000..273306c0f --- /dev/null +++ b/Tests/RunCMake/Android/sysinc/dlfcn.h @@ -0,0 +1 @@ +#define NOT_SYSTEM_DLFCN_HEADER diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake index d37e8966f..a5500052b 100644 --- a/Tests/RunCMake/AutoExportDll/AutoExport.cmake +++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake @@ -11,5 +11,11 @@ if(MSVC) set_target_properties(say PROPERTIES ENABLE_EXPORTS ON) add_library(autoexport_for_exec SHARED hello2.c) target_link_libraries(autoexport_for_exec say) + if(NOT MSVC_VERSION VERSION_LESS 1600) + enable_language(ASM_MASM) + target_sources(autoexport PRIVATE nop.asm) + set_property(SOURCE nop.asm PROPERTY COMPILE_FLAGS /safeseh) + target_compile_definitions(say PRIVATE HAS_JUSTNOP) + endif() endif() target_link_libraries(say autoexport autoexport2) diff --git a/Tests/RunCMake/AutoExportDll/nop.asm b/Tests/RunCMake/AutoExportDll/nop.asm new file mode 100644 index 000000000..fd6892f5d --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/nop.asm @@ -0,0 +1,12 @@ +IFDEF RAX +ELSE +.MODEL FLAT,C +ENDIF + +SOME SEGMENT EXECUTE READ + +public justnop +justnop: + ret + +END diff --git a/Tests/RunCMake/AutoExportDll/say.cxx b/Tests/RunCMake/AutoExportDll/say.cxx index e966b1fdd..51060e8de 100644 --- a/Tests/RunCMake/AutoExportDll/say.cxx +++ b/Tests/RunCMake/AutoExportDll/say.cxx @@ -12,6 +12,7 @@ int WINAPI foo(); // test regular C int bar(); int objlib(); +void justnop(); } // test c++ functions @@ -42,5 +43,8 @@ int main() bar(); objlib(); printf("\n"); +#ifdef HAS_JUSTNOP + justnop(); +#endif return 0; } diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cmake b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cmake new file mode 100644 index 000000000..0f92e0edb --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cmake @@ -0,0 +1,13 @@ +add_custom_command( + OUTPUT output.cxx + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/MakeCustomIncludes.cxx output.cxx + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MakeCustomIncludes.cxx + IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/MakeCustomIncludes.cxx) +add_custom_target(generate ALL DEPENDS output.cxx) +set_property(TARGET generate PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) + +file(GENERATE OUTPUT check-$>.cmake CONTENT " +set(check_pairs + \"${CMAKE_CURRENT_BINARY_DIR}/output.cxx|${CMAKE_CURRENT_BINARY_DIR}/MakeCustomIncludes.h\" + ) +") diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx new file mode 100644 index 000000000..9a0edefad --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx @@ -0,0 +1,6 @@ +#include "MakeCustomIncludes.h" + +int main() +{ + return MakeCustomIncludes(); +} diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step1.cmake b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step1.cmake new file mode 100644 index 000000000..6bb01a6bc --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step1.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/MakeCustomIncludes.h" [[ +inline int MakeCustomIncludes() { return 1; } +]]) diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step2.cmake b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step2.cmake new file mode 100644 index 000000000..6b3151dc4 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step2.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/MakeCustomIncludes.h" [[ +inline int MakeCustomIncludes() { return 2; } +]]) diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index ffd3ae178..9941c70df 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -31,7 +31,7 @@ function(run_BuildDepends CASE) endfunction() run_BuildDepends(C-Exe) -if(NOT RunCMake_GENERATOR MATCHES "Visual Studio 7|Xcode") +if(NOT RunCMake_GENERATOR STREQUAL "Xcode") if(RunCMake_GENERATOR MATCHES "Visual Studio 10") # VS 10 forgets to re-link when a manifest changes set(run_BuildDepends_skip_step_2 1) @@ -43,9 +43,11 @@ endif() run_BuildDepends(Custom-Symbolic-and-Byproduct) run_BuildDepends(Custom-Always) -if(RunCMake_GENERATOR MATCHES "Make" AND - NOT "${RunCMake_BINARY_DIR}" STREQUAL "${RunCMake_SOURCE_DIR}") - run_BuildDepends(MakeInProjectOnly) +if(RunCMake_GENERATOR MATCHES "Make") + run_BuildDepends(MakeCustomIncludes) + if(NOT "${RunCMake_BINARY_DIR}" STREQUAL "${RunCMake_SOURCE_DIR}") + run_BuildDepends(MakeInProjectOnly) + endif() endif() function(run_ReGeneration) diff --git a/Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt b/Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt new file mode 100644 index 000000000..048762d00 --- /dev/null +++ b/Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0019-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0019 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/CMP0022/CMP0022-WARN-tll-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt index f6722853a..5d39214f4 100644 --- a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt @@ -4,13 +4,13 @@ CMake Warning \(dev\) in CMakeLists.txt: cmake_policy command to set the policy and suppress this warning. Target "bar" has an INTERFACE_LINK_LIBRARIES property which differs from - its LINK_INTERFACE_LIBRARIES properties. + its LINK_INTERFACE_LIBRARIES(_DEBUG)? properties. INTERFACE_LINK_LIBRARIES: foo - LINK_INTERFACE_LIBRARIES: + LINK_INTERFACE_LIBRARIES(_DEBUG)?: bat diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake index 11b4e22a9..03223e86a 100644 --- a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake +++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake @@ -5,7 +5,9 @@ add_library(foo SHARED empty_vs6_1.cpp) add_library(bar SHARED empty_vs6_2.cpp) add_library(bat SHARED empty_vs6_3.cpp) target_link_libraries(bar LINK_PUBLIC foo) +# Replace the compatibility values set by target_link_libraries set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES bat) +set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES_DEBUG bat) add_library(user SHARED empty.cpp) target_link_libraries(user bar) diff --git a/Tests/RunCMake/CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt b/Tests/RunCMake/CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt new file mode 100644 index 000000000..edeb33728 --- /dev/null +++ b/Tests/RunCMake/CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0026-CONFIG-LOCATION-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0026 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/CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt b/Tests/RunCMake/CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt new file mode 100644 index 000000000..32ff698f1 --- /dev/null +++ b/Tests/RunCMake/CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0026-LOCATION-CONFIG-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0026 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/CMP0026/CMP0026-OLD-stderr.txt b/Tests/RunCMake/CMP0026/CMP0026-OLD-stderr.txt new file mode 100644 index 000000000..b3f79fc4d --- /dev/null +++ b/Tests/RunCMake/CMP0026/CMP0026-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0026-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0026 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/CMP0026/CMP0026-OLD.cmake b/Tests/RunCMake/CMP0026/CMP0026-OLD.cmake new file mode 100644 index 000000000..80497a304 --- /dev/null +++ b/Tests/RunCMake/CMP0026/CMP0026-OLD.cmake @@ -0,0 +1,12 @@ +enable_language(CXX) + +cmake_policy(SET CMP0026 OLD) + +set(out ${CMAKE_CURRENT_BINARY_DIR}/out.txt) + +add_library(somelib empty.cpp ${out}) +get_target_property(_loc somelib LOCATION) + +file(WRITE "${out}" + "source file written by project code after getting target LOCATION\n" + ) diff --git a/Tests/RunCMake/CMP0026/RunCMakeTest.cmake b/Tests/RunCMake/CMP0026/RunCMakeTest.cmake index 633171739..047da283b 100644 --- a/Tests/RunCMake/CMP0026/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMP0026/RunCMakeTest.cmake @@ -1,6 +1,7 @@ include(RunCMake) run_cmake(CMP0026-WARN) +run_cmake(CMP0026-OLD) run_cmake(CMP0026-NEW) run_cmake(CMP0026-IMPORTED) run_cmake(CMP0026-CONFIG-LOCATION-NEW) diff --git a/Tests/RunCMake/CMP0026/clear-cached-information-stderr.txt b/Tests/RunCMake/CMP0026/clear-cached-information-stderr.txt new file mode 100644 index 000000000..157a0468a --- /dev/null +++ b/Tests/RunCMake/CMP0026/clear-cached-information-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at clear-cached-information.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0026 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/CMP0028/CMP0028-OLD-iface-stderr.txt b/Tests/RunCMake/CMP0028/CMP0028-OLD-iface-stderr.txt new file mode 100644 index 000000000..b7a07559f --- /dev/null +++ b/Tests/RunCMake/CMP0028/CMP0028-OLD-iface-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0028-OLD-iface.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0028 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/CMP0028/CMP0028-OLD-stderr.txt b/Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt new file mode 100644 index 000000000..586a876a0 --- /dev/null +++ b/Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0028-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0028 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/CMP0068/CMP0068-NEW-result.txt b/Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake b/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake new file mode 100644 index 000000000..eb8cfa1fb --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake @@ -0,0 +1,6 @@ + +cmake_policy(SET CMP0068 NEW) +cmake_policy(SET CMP0042 NEW) + +add_library(foo SHARED empty.cpp) +set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1) diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt b/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake b/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake new file mode 100644 index 000000000..cf1040f4c --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake @@ -0,0 +1,6 @@ + +cmake_policy(SET CMP0068 OLD) +cmake_policy(SET CMP0042 NEW) + +add_library(foo SHARED empty.cpp) +set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1) diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt b/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt b/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt new file mode 100644 index 000000000..3cb585482 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt @@ -0,0 +1,12 @@ +CMake Warning \(dev\): + Policy CMP0068 is not set: RPATH settings on macOS do not affect + install_name. Run "cmake --help-policy CMP0068" for policy details. Use + the cmake_policy command to set the policy and suppress this warning. + + For compatibility with older versions of CMake, the install_name fields for + the following targets are still affected by RPATH settings: + + foo3 + foo4 + +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake b/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake new file mode 100644 index 000000000..b7ec480d4 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake @@ -0,0 +1,12 @@ +cmake_policy(SET CMP0042 NEW) + +add_library(foo SHARED empty.cpp) +add_library(foo-static STATIC empty.cpp) +add_library(foo2 SHARED empty.cpp) +set_target_properties(foo2 PROPERTIES MACOSX_RPATH 1) +add_library(foo3 SHARED empty.cpp) +set_target_properties(foo3 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@loader_path") +add_library(foo4 SHARED empty.cpp) +set_target_properties(foo4 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath") +add_library(foo5 SHARED empty.cpp) +set_target_properties(foo5 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 BUILD_WITH_INSTALL_NAME_DIR 1 INSTALL_NAME_DIR "@rpath") diff --git a/Tests/RunCMake/CMP0068/CMakeLists.txt b/Tests/RunCMake/CMP0068/CMakeLists.txt new file mode 100644 index 000000000..375cbdb5f --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.8) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0068/RunCMakeTest.cmake b/Tests/RunCMake/CMP0068/RunCMakeTest.cmake new file mode 100644 index 000000000..88a622537 --- /dev/null +++ b/Tests/RunCMake/CMP0068/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0068-OLD) +run_cmake(CMP0068-NEW) +run_cmake(CMP0068-WARN) diff --git a/Tests/RunCMake/CMP0068/empty.cpp b/Tests/RunCMake/CMP0068/empty.cpp new file mode 100644 index 000000000..11ec041d1 --- /dev/null +++ b/Tests/RunCMake/CMP0068/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-result.txt similarity index 100% rename from Tests/RunCMake/ObjectLibrary/Export-result.txt rename to Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-result.txt diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt new file mode 100644 index 000000000..ddb3cae61 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at CMP0069-NEW-cmake\.cmake:[0-9]+ \(add_executable\): + CMake doesn't support IPO for current compiler +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake new file mode 100644 index 000000000..6968c8bbf --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake @@ -0,0 +1,6 @@ +cmake_policy(SET CMP0069 NEW) + +set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE NO) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/ObjectLibrary/Import-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-result.txt similarity index 100% rename from Tests/RunCMake/ObjectLibrary/Import-result.txt rename to Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-result.txt diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt new file mode 100644 index 000000000..8decfab3c --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at CMP0069-NEW-compiler\.cmake:[0-9]+ \(add_executable\): + Compiler doesn't support IPO +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake new file mode 100644 index 000000000..ecb197b39 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake @@ -0,0 +1,7 @@ +cmake_policy(SET CMP0069 NEW) + +set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE YES) +set(_CMAKE_CXX_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/ObjectLibrary/Install-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-result.txt similarity index 100% rename from Tests/RunCMake/ObjectLibrary/Install-result.txt rename to Tests/RunCMake/CMP0069/CMP0069-NEW-generator-result.txt diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt new file mode 100644 index 000000000..0e05ee783 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at CMP0069-NEW-generator\.cmake:[0-9]+ \(add_executable\): + CMake doesn't support IPO for current generator +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake new file mode 100644 index 000000000..80d4e1544 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake @@ -0,0 +1,7 @@ +cmake_policy(SET CMP0069 NEW) + +set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE YES) +set(_CMAKE_CXX_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake b/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake new file mode 100644 index 000000000..cfe1e9d06 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake @@ -0,0 +1,4 @@ +cmake_policy(SET CMP0069 OLD) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt new file mode 100644 index 000000000..314e18023 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt @@ -0,0 +1,9 @@ +^CMake Warning \(dev\) at CMP0069-WARN\.cmake:[0-9]+ \(add_executable\): + Policy CMP0069 is not set: INTERPROCEDURAL_OPTIMIZATION is enforced when + enabled. Run "cmake --help-policy CMP0069" for policy details\. Use the + cmake_policy command to set the policy and suppress this warning\. + + INTERPROCEDURAL_OPTIMIZATION property will be ignored for target 'foo'\. +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/CMP0069/CMP0069-WARN.cmake b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake new file mode 100644 index 000000000..2049c9e75 --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake @@ -0,0 +1,4 @@ +set(_CMAKE_CXX_IPO_LEGACY_BEHAVIOR NO) + +add_executable(foo main.cpp) +set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/Tests/RunCMake/CMP0069/CMakeLists.txt b/Tests/RunCMake/CMP0069/CMakeLists.txt new file mode 100644 index 000000000..375cbdb5f --- /dev/null +++ b/Tests/RunCMake/CMP0069/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.8) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0069/RunCMakeTest.cmake b/Tests/RunCMake/CMP0069/RunCMakeTest.cmake new file mode 100644 index 000000000..f44f84002 --- /dev/null +++ b/Tests/RunCMake/CMP0069/RunCMakeTest.cmake @@ -0,0 +1,10 @@ +include(RunCMake) + +run_cmake(CMP0069-OLD) +run_cmake(CMP0069-NEW-cmake) +run_cmake(CMP0069-NEW-compiler) +run_cmake(CMP0069-WARN) + +if(RunCMake_GENERATOR MATCHES "^Visual Studio ") + run_cmake(CMP0069-NEW-generator) +endif() diff --git a/Tests/RunCMake/CMP0069/main.cpp b/Tests/RunCMake/CMP0069/main.cpp new file mode 100644 index 000000000..5047a34e3 --- /dev/null +++ b/Tests/RunCMake/CMP0069/main.cpp @@ -0,0 +1,3 @@ +int main() +{ +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index a16efb399..79f487d41 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -63,15 +63,6 @@ if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 6.1) set(Swift_ARGS -DXCODE_BELOW_6_1=1) endif() -if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 3) - set(GeneratorToolset_ARGS -DXCODE_BELOW_3=1) -endif() - -if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 2) - set(TargetSources_ARGS -DXCODE_BELOW_2=1) - set(File_Generate_ARGS -DXCODE_BELOW_2=1) -endif() - # Test MSVC for older host CMake versions, and test # WIN32/CMAKE_C_COMPILER_ID to fix check on Intel for Windows. if(MSVC OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel")) @@ -104,6 +95,10 @@ add_RunCMake_test(CMP0057) add_RunCMake_test(CMP0059) add_RunCMake_test(CMP0060) add_RunCMake_test(CMP0064) +if(CMAKE_SYSTEM_NAME MATCHES Darwin AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG) + add_RunCMake_test(CMP0068) +endif() +add_RunCMake_test(CMP0069) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode @@ -115,6 +110,10 @@ if(CMAKE_GENERATOR MATCHES "Make") add_RunCMake_test(Make) endif() if(CMAKE_GENERATOR STREQUAL "Ninja") + set(Ninja_ARGS + -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION} + -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} + -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX}) add_RunCMake_test(Ninja) endif() add_RunCMake_test(CTest) @@ -148,7 +147,7 @@ endif() add_RunCMake_test(GeneratorExpression) add_RunCMake_test(GeneratorPlatform) add_RunCMake_test(GeneratorToolset) -add_RunCMake_test(GNUInstallDirs) +add_RunCMake_test(GNUInstallDirs -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(LinkStatic) @@ -199,6 +198,8 @@ endif() add_RunCMake_test(ctest_start) add_RunCMake_test(ctest_submit) add_RunCMake_test(ctest_test) +add_RunCMake_test(ctest_disabled_test) +add_RunCMake_test(ctest_skipped_test) add_RunCMake_test(ctest_upload) add_RunCMake_test(ctest_fixtures) add_RunCMake_test(file) @@ -216,6 +217,7 @@ add_RunCMake_test(list) add_RunCMake_test(message) add_RunCMake_test(project -DCMake_TEST_RESOURCES=${CMake_TEST_RESOURCES}) add_RunCMake_test(return) +add_RunCMake_test(separate_arguments) add_RunCMake_test(set_property) add_RunCMake_test(string) foreach(var @@ -265,17 +267,17 @@ endif() if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") add_RunCMake_test(include_external_msproject) - if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([789]|10)" AND NOT CMAKE_VS_DEVENV_COMMAND) + if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([89]|10)" AND NOT CMAKE_VS_DEVENV_COMMAND) set(NO_USE_FOLDERS 1) endif() add_RunCMake_test(VSSolution -DNO_USE_FOLDERS=${NO_USE_FOLDERS}) endif() -if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([^789]|[789][0-9])") +if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([^89]|[89][0-9])") add_RunCMake_test(VS10Project) endif() -if(XCODE_VERSION AND NOT "${XCODE_VERSION}" VERSION_LESS 3) +if(XCODE_VERSION) add_RunCMake_test(XcodeProject -DXCODE_VERSION=${XCODE_VERSION}) endif() @@ -290,7 +292,8 @@ add_RunCMake_test(target_link_libraries) add_RunCMake_test(target_compile_features) add_RunCMake_test(CheckModules) -add_RunCMake_test(CommandLine) +add_RunCMake_test(CheckIPOSupported) +add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(CommandLineTar) add_RunCMake_test(install) @@ -322,19 +325,6 @@ add_executable(pseudo_emulator_custom_command pseudo_emulator_custom_command.c) add_RunCMake_test(CrosscompilingEmulator -DPSEUDO_EMULATOR=$ -DPSEUDO_EMULATOR_CUSTOM_COMMAND=$) -# Xcode 2.x forgets to create the output directory before linking -# the individual architectures. -if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]") - add_custom_command( - TARGET pseudo_emulator - PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}" - ) - add_custom_command( - TARGET pseudo_emulator_custom_command - PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}" - ) -endif() - if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") if(UNIX AND NOT CYGWIN) execute_process(COMMAND ldd --help diff --git a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake index ce039f5be..99d3155dd 100644 --- a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake +++ b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake @@ -33,7 +33,7 @@ function(getPackageContentList FILE RESULT_VAR) endfunction() function(toExpectedContentList FILE_NO CONTENT_VAR) - findExpectedFile("${FILE_NO}" "file_") + findExpectedFile("${FILE_NO}" "file_" "glob_expr_") # component and monolithic packages differ for some reason by either having # package filename prefix in path or not diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 65399db2d..faf151a13 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -5,7 +5,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake") # run_cpack_test args: TEST_NAME "GENERATORS" RUN_CMAKE_BUILD_STEP "PACKAGING_TYPES" run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM" false "MONOLITHIC;COMPONENT") -run_cpack_test(CUSTOM_NAMES "RPM;DEB" true "COMPONENT") +run_cpack_test(CUSTOM_NAMES "RPM;DEB;TGZ" true "COMPONENT") run_cpack_test(DEBUGINFO "RPM" true "COMPONENT") run_cpack_test(DEPENDENCIES "RPM;DEB" true "COMPONENT") run_cpack_test(DIST "RPM" false "MONOLITHIC") @@ -21,7 +21,9 @@ run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384; run_cpack_test(PARTIALLY_RELOCATABLE_WARNING "RPM" false "COMPONENT") run_cpack_test(PER_COMPONENT_FIELDS "RPM;DEB" false "COMPONENT") run_cpack_test_subtests(SINGLE_DEBUGINFO "no_main_component;one_component;one_component_main;no_debuginfo;one_component_no_debuginfo;no_components;valid" "RPM" true "CUSTOM") +run_cpack_test(EXTRA_SLASH_IN_PATH "RPM" true "COMPONENT") run_cpack_source_test(SOURCE_PACKAGE "RPM") run_cpack_test(SUGGESTS "RPM" false "MONOLITHIC") +run_cpack_test(SYMLINKS "RPM;TGZ" false "MONOLITHIC;COMPONENT") run_cpack_test(USER_FILELIST "RPM" false "MONOLITHIC") run_cpack_test(MD5SUMS "DEB" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/STGZ/Helpers.cmake b/Tests/RunCMake/CPack/STGZ/Helpers.cmake index 08224d30c..68b1eabd2 100644 --- a/Tests/RunCMake/CPack/STGZ/Helpers.cmake +++ b/Tests/RunCMake/CPack/STGZ/Helpers.cmake @@ -35,7 +35,7 @@ function(getPackageContentList FILE RESULT_VAR) endfunction() function(toExpectedContentList FILE_NO CONTENT_VAR) - findExpectedFile("${FILE_NO}" "file_") + findExpectedFile("${FILE_NO}" "file_" "glob_expr_") get_filename_component(prefix_ "${file_}" NAME) # NAME_WE removes everything after the dot and dot is in version so replace instead diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake b/Tests/RunCMake/CPack/VerifyResult.cmake index 59751a729..470ebf7a8 100644 --- a/Tests/RunCMake/CPack/VerifyResult.cmake +++ b/Tests/RunCMake/CPack/VerifyResult.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION ${CMAKE_VERSION} FATAL_ERROR) -function(findExpectedFile FILE_NO RESULT_VAR) +function(findExpectedFile FILE_NO RESULT_VAR GLOBING_EXPR_VAR) if(NOT DEFINED EXPECTED_FILE_${FILE_NO}) # explicit file name regex was not provided - construct one from other data # set defaults if parameters are not provided if(NOT DEFINED EXPECTED_FILE_${FILE_NO}_NAME) @@ -21,6 +21,7 @@ function(findExpectedFile FILE_NO RESULT_VAR) file(GLOB found_file_ RELATIVE "${bin_dir}" "${EXPECTED_FILE_${FILE_NO}}") set(${RESULT_VAR} "${found_file_}" PARENT_SCOPE) + set(${GLOBING_EXPR_VAR} "${EXPECTED_FILE_${FILE_NO}}" PARENT_SCOPE) endfunction() include("${config_file}") @@ -39,7 +40,8 @@ include("${src_dir}/tests/${RunCMake_TEST_FILE_PREFIX}/ExpectedFiles.cmake") # check that expected generated files exist and contain expected content if(NOT EXPECTED_FILES_COUNT EQUAL 0) foreach(file_no_ RANGE 1 ${EXPECTED_FILES_COUNT}) - findExpectedFile("${file_no_}" "FOUND_FILE_${file_no_}") + findExpectedFile("${file_no_}" "FOUND_FILE_${file_no_}" + "EXPECTED_FILE_${file_no_}") list(APPEND foundFiles_ "${FOUND_FILE_${file_no_}}") list(LENGTH FOUND_FILE_${file_no_} foundFilesCount_) diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake index ae5f0af6e..5cb280cd6 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake @@ -9,4 +9,7 @@ set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt") if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM") string(TOLOWER "${GENERATOR_TYPE}" file_extension_) set(EXPECTED_FILE_3 "pkg_3_abc.${file_extension_}") +elseif(GENERATOR_TYPE STREQUAL "TGZ") + set(EXPECTED_FILE_2 "second.tar.gz") + set(EXPECTED_FILE_3 "pkg_3_abc.tar.gz") endif() diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake index 0c2b37b3e..4c20e4164 100644 --- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake +++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake @@ -7,6 +7,9 @@ if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM") set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PKG_2_PACKAGE_NAME "second") string(TOLOWER "${GENERATOR_TYPE}" file_extension_) set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PKG_3_FILE_NAME "pkg_3_abc.${file_extension_}") +elseif(GENERATOR_TYPE STREQUAL "TGZ") + set(CPACK_ARCHIVE_PKG_2_FILE_NAME "second") + set(CPACK_ARCHIVE_PKG_3_FILE_NAME "pkg_3_abc") endif() install(FILES CMakeLists.txt DESTINATION foo COMPONENT pkg_1) diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake index 06e56d3e6..3d8de74d4 100644 --- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake @@ -3,14 +3,16 @@ set(whitespaces_ "[\t\n\r ]*") set(EXPECTED_FILES_COUNT "5") set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) +set(EXPECTED_FILE_1_NAME "Debuginfo") set(EXPECTED_FILE_1_COMPONENT "applications") set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog") -set(EXPECTED_FILE_2 "debuginfo*-headers.rpm") +set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.rpm") set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt") -set(EXPECTED_FILE_3 "debuginfo*-libs.rpm") +set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.rpm") set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so") +set(EXPECTED_FILE_4_NAME "Debuginfo") set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo") set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*") -set(EXPECTED_FILE_5_COMPONENT "libs-debuginfo") +set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm") set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*") diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake index 0642d8306..f1b6738bd 100644 --- a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake +++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake @@ -25,6 +25,16 @@ install(TARGETS test_lib DESTINATION bas COMPONENT libs) set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT") set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON) + +# test that components with debuginfo enabled still honor +# CPACK_PACKAGE_FILE_NAME setting +set(CPACK_RPM_PACKAGE_NAME "Debuginfo") +set(CPACK_PACKAGE_FILE_NAME "TestDinfo-pkg") set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON) +# test debuginfo package rename +set(CPACK_RPM_DEBUGINFO_FILE_NAME + "@cpack_component@-DebugInfoPackage.rpm") +set(CPACK_RPM_APPLICATIONS_DEBUGINFO_FILE_NAME "RPM-DEFAULT") + set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/src") diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake new file mode 100644 index 000000000..a45b38ddd --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake @@ -0,0 +1,16 @@ +set(whitespaces_ "[\t\n\r ]*") + +set(EXPECTED_FILES_COUNT "5") +set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE) + +set(EXPECTED_FILE_1_COMPONENT "applications") +set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog") +set(EXPECTED_FILE_2 "extra_slash_in_path*-headers.rpm") +set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt") +set(EXPECTED_FILE_3 "extra_slash_in_path*-libs.rpm") +set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so") + +set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo") +set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*") +set(EXPECTED_FILE_5_COMPONENT "libs-debuginfo") +set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*") diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake new file mode 100644 index 000000000..bfef720e9 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake @@ -0,0 +1,7 @@ +# check that relocation path is /foo and not //foo +getPackageInfo("${FOUND_FILE_1}" "FILE_INFO_") +set(whitespaces_ "[\t\n\r ]*") +if(NOT FILE_INFO_ MATCHES "Relocations${whitespaces_}:${whitespaces_}/${whitespaces_}/foo") + message(FATAL_ERROR "Unexpected relocation path in file '${FOUND_FILE_1}';" + " file info: '${FILE_INFO_}'") +endif() diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake new file mode 100644 index 000000000..4fd1e810a --- /dev/null +++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake @@ -0,0 +1,37 @@ +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") + string(APPEND CMAKE_EXE_LINKER_FLAGS "-Wl,--build-id") + string(APPEND CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id") +endif() + +set(CMAKE_BUILD_TYPE Debug) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.hpp" + "int test_lib();\n") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp" + "#include \"test_lib.hpp\"\nint test_lib() {return 0;}\n") +add_library(test_lib SHARED "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp" + "#include \"test_lib.hpp\"\nint main() {return test_lib();}\n") +add_executable(test_prog "${CMAKE_CURRENT_BINARY_DIR}/main.cpp") +target_link_libraries(test_prog test_lib) + +install(TARGETS test_prog DESTINATION foo COMPONENT applications) +install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers) +install(TARGETS test_lib DESTINATION bas COMPONENT libs) + +set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT") +set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON) +set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON) + +# extra trailing slash at the end that should be removed +set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/src/") + +# combination should not cause //foo to apper as an relocation path +# should be only /foo (extra slashes cause path comparisons to fail) +set(CPACK_PACKAGING_INSTALL_PREFIX "/") +# extra trailing slash at the end that should be removed +set(CPACK_RPM_RELOCATION_PATHS "foo/") diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake new file mode 100644 index 000000000..05be748c1 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake @@ -0,0 +1,13 @@ +set(EXPECTED_FILES_COUNT "1") + +set(EXPECTED_FILE_CONTENT_1_LIST + "/usr" + "/usr/empty_dir" + "/usr/non_empty_dir" + "/usr/non_empty_dir/CMakeLists.txt" + "/usr/symlink_to_empty_dir" + "/usr/symlink_to_non_empty_dir") + +if(PACKAGING_TYPE STREQUAL "COMPONENT") + set(EXPECTED_FILE_1_COMPONENT "links") +endif() diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake new file mode 100644 index 000000000..f3df46b2a --- /dev/null +++ b/Tests/RunCMake/CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake @@ -0,0 +1,5 @@ +function(get_test_prerequirements found_var config_file) + if(UNIX) # limit test to platforms that support symlinks + set(${found_var} true PARENT_SCOPE) + endif() +endfunction() diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake new file mode 100644 index 000000000..0632319ab --- /dev/null +++ b/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake @@ -0,0 +1,26 @@ +set(whitespaces "[\\t\\n\\r ]*") + +####################### +# verify generated symbolic links +####################### +file(GLOB_RECURSE symlink_files RELATIVE "${bin_dir}" "${bin_dir}/*/symlink_*") + +foreach(check_symlink IN LISTS symlink_files) + get_filename_component(symlink_name "${check_symlink}" NAME) + execute_process(COMMAND ls -la "${check_symlink}" + WORKING_DIRECTORY "${bin_dir}" + OUTPUT_VARIABLE SYMLINK_POINT_ + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if("${symlink_name}" STREQUAL "symlink_to_empty_dir") + string(REGEX MATCH "^.*${whitespaces}->${whitespaces}empty_dir$" check_symlink "${SYMLINK_POINT_}") + elseif("${symlink_name}" STREQUAL "symlink_to_non_empty_dir") + string(REGEX MATCH "^.*${whitespaces}->${whitespaces}non_empty_dir$" check_symlink "${SYMLINK_POINT_}") + else() + message(FATAL_ERROR "error: unexpected rpm symbolic link '${check_symlink}'") + endif() + + if(NOT check_symlink) + message(FATAL_ERROR "symlink points to unexpected location '${SYMLINK_POINT_}'") + endif() +endforeach() diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake new file mode 100644 index 000000000..fef765ccd --- /dev/null +++ b/Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake @@ -0,0 +1,14 @@ +install(DIRECTORY DESTINATION empty_dir COMPONENT links) +install(FILES CMakeLists.txt DESTINATION non_empty_dir COMPONENT links) + +# test symbolic link to an empty dir +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink empty_dir symlink_to_empty_dir) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_to_empty_dir DESTINATION "." COMPONENT links) + +# test symbolic link to a non empty dir +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink non_empty_dir symlink_to_non_empty_dir) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_to_non_empty_dir DESTINATION "." COMPONENT links) + +if(PACKAGING_TYPE STREQUAL "COMPONENT") + set(CPACK_COMPONENTS_ALL links) +endif() diff --git a/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt new file mode 100644 index 000000000..4a13d29a0 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.0) +project(${RunCMake_TEST} NONE) + +cmake_policy(SET CMP0069 NEW) + +include(CheckIPOSupported) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake new file mode 100644 index 000000000..e14556944 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake @@ -0,0 +1,13 @@ +include(RunCMake) + +run_cmake(unparsed-arguments) +run_cmake(user-lang-unknown) +run_cmake(default-lang-none) +run_cmake(not-supported-by-cmake) +run_cmake(not-supported-by-compiler) +run_cmake(save-to-result) +run_cmake(cmp0069-is-old) + +if(RunCMake_GENERATOR MATCHES "^Visual Studio ") + run_cmake(not-supported-by-generator) +endif() diff --git a/Tests/RunCMake/TargetObjects/BadContext-result.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-result.txt similarity index 100% rename from Tests/RunCMake/TargetObjects/BadContext-result.txt rename to Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-result.txt diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt new file mode 100644 index 000000000..f183594e5 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + Policy CMP0069 set to OLD +Call Stack \(most recent call first\): + cmp0069-is-old\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake new file mode 100644 index 000000000..14fed0467 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake @@ -0,0 +1,6 @@ +project(${RunCMake_TEST} LANGUAGES C CXX) + +cmake_policy(SET CMP0069 OLD) + +include(CheckIPOSupported) +check_ipo_supported() diff --git a/Tests/RunCMake/find_dependency/EXACT-no-version-result.txt b/Tests/RunCMake/CheckIPOSupported/default-lang-none-result.txt similarity index 100% rename from Tests/RunCMake/find_dependency/EXACT-no-version-result.txt rename to Tests/RunCMake/CheckIPOSupported/default-lang-none-result.txt diff --git a/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt new file mode 100644 index 000000000..dc2c3ada9 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + IPO is not supported \(no C/CXX/Fortran languages found in ENABLED_LANGUAGES + global property\)\. +Call Stack \(most recent call first\): + .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) + default-lang-none\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/default-lang-none.cmake b/Tests/RunCMake/CheckIPOSupported/default-lang-none.cmake new file mode 100644 index 000000000..0a2ac695c --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/default-lang-none.cmake @@ -0,0 +1 @@ +check_ipo_supported() diff --git a/Tests/RunCMake/find_dependency/empty-arg-3-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-result.txt similarity index 100% rename from Tests/RunCMake/find_dependency/empty-arg-3-result.txt rename to Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-result.txt diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt new file mode 100644 index 000000000..c49a02439 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + IPO is not supported \(CMake doesn't support IPO for current C compiler\)\. +Call Stack \(most recent call first\): + .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) + not-supported-by-cmake\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake new file mode 100644 index 000000000..e583dd02c --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake @@ -0,0 +1,3 @@ +project(${RunCMake_TEST} LANGUAGES C) +set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE NO) +check_ipo_supported() diff --git a/Tests/RunCMake/find_dependency/empty-version-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-result.txt similarity index 100% rename from Tests/RunCMake/find_dependency/empty-version-result.txt rename to Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-result.txt diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt new file mode 100644 index 000000000..675c2d393 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + IPO is not supported \(C compiler doesn't support IPO\)\. +Call Stack \(most recent call first\): + .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) + not-supported-by-compiler\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake new file mode 100644 index 000000000..86c8f8d43 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake @@ -0,0 +1,4 @@ +project(${RunCMake_TEST} LANGUAGES C) +set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE YES) +set(_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) +check_ipo_supported() diff --git a/Tests/RunCMake/find_dependency/extra-args-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-result.txt similarity index 100% rename from Tests/RunCMake/find_dependency/extra-args-result.txt rename to Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-result.txt diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt new file mode 100644 index 000000000..a2aa58c7b --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + IPO is not supported \(CMake doesn't support IPO for current generator\)\. +Call Stack \(most recent call first\): + .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) + not-supported-by-generator\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake new file mode 100644 index 000000000..c32af6ed3 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake @@ -0,0 +1,6 @@ +project(${RunCMake_TEST} LANGUAGES C) + +set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE YES) +set(_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + +check_ipo_supported() diff --git a/Tests/RunCMake/CheckIPOSupported/save-to-result.cmake b/Tests/RunCMake/CheckIPOSupported/save-to-result.cmake new file mode 100644 index 000000000..f76db724d --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/save-to-result.cmake @@ -0,0 +1,22 @@ +project(${RunCMake_TEST} LANGUAGES C) +check_ipo_supported(RESULT result OUTPUT output) + +string(COMPARE EQUAL "${result}" "" is_empty) +if(is_empty) + message(FATAL_ERROR "Result variable is empty") +endif() + +string(COMPARE EQUAL "${result}" "YES" is_yes) +string(COMPARE EQUAL "${result}" "NO" is_no) + +if(is_yes) + # Compiler supports IPO +elseif(is_no) + # Compiler doesn't support IPO, output should not be empty. + string(COMPARE EQUAL "${output}" "" is_empty) + if(is_empty) + message(FATAL_ERROR "Output is empty") + endif() +else() + message(FATAL_ERROR "Unexpected result: ${result}") +endif() diff --git a/Tests/RunCMake/find_dependency/invalid-arg-3-result.txt b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-result.txt similarity index 100% rename from Tests/RunCMake/find_dependency/invalid-arg-3-result.txt rename to Tests/RunCMake/CheckIPOSupported/unparsed-arguments-result.txt diff --git a/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-stderr.txt b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-stderr.txt new file mode 100644 index 000000000..a3fee53f5 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + Unparsed arguments: xxx +Call Stack \(most recent call first\): + unparsed-arguments\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/unparsed-arguments.cmake b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments.cmake new file mode 100644 index 000000000..3ee732615 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments.cmake @@ -0,0 +1 @@ +check_ipo_supported(RESULT result OUTPUT output xxx) diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-stderr.txt b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-stderr.txt new file mode 100644 index 000000000..278ba0b05 --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): + IPO is not supported \(language\(s\) 'UnknownLanguage' not supported\)\. +Call Stack \(most recent call first\): + .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) + user-lang-unknown\.cmake:[0-9]+ \(check_ipo_supported\) + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-unknown.cmake b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown.cmake new file mode 100644 index 000000000..ac743ad8a --- /dev/null +++ b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown.cmake @@ -0,0 +1 @@ +check_ipo_supported(LANGUAGES UnknownLanguage) diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON-stderr.txt deleted file mode 100644 index 2cb01ffe3..000000000 --- a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -^CMake Warning: - The "Visual Studio 7 .NET 2003" generator is deprecated and will be removed - in a future version of CMake. - - Add CMAKE_WARN_VS71=OFF to the cache to disable this warning.$ diff --git a/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-OFF.cmake b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-OFF.cmake new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON-stderr.txt new file mode 100644 index 000000000..2f2cbd3c6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON-stderr.txt @@ -0,0 +1,5 @@ +^CMake Warning: + The "Visual Studio 8 2005" generator is deprecated and will be removed in a + future version of CMake. + + Add CMAKE_WARN_VS8=OFF to the cache to disable this warning.$ diff --git a/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON.cmake b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON.cmake new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 0c4f71c89..f94b10ac5 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.1) + include(RunCMake) run_cmake_command(NoArgs ${CMAKE_COMMAND}) @@ -76,11 +78,11 @@ if(RunCMake_GENERATOR STREQUAL "Ninja") unset(RunCMake_TEST_NO_CLEAN) endif() -if(RunCMake_GENERATOR STREQUAL "Visual Studio 7 .NET 2003") - set(RunCMake_WARN_VS71 1) - run_cmake(DeprecateVS71-WARN-ON) - unset(RunCMake_WARN_VS71) - run_cmake(DeprecateVS71-WARN-OFF) +if(RunCMake_GENERATOR MATCHES "^Visual Studio 8 2005") + set(RunCMake_WARN_VS8 1) + run_cmake(DeprecateVS8-WARN-ON) + unset(RunCMake_WARN_VS8) + run_cmake(DeprecateVS8-WARN-OFF) endif() if(UNIX) @@ -301,3 +303,14 @@ set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\") ) endfunction() run_cmake_depends() + +function(reject_fifo) + find_program(BASH_EXECUTABLE bash) + if(BASH_EXECUTABLE) + set(BASH_COMMAND_ARGUMENT "'${CMAKE_COMMAND}' -P <(echo 'return()')") + run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) + endif() +endfunction() +if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN") + reject_fifo() +endif() diff --git a/Tests/RunCMake/CommandLine/reject_fifo-result.txt b/Tests/RunCMake/CommandLine/reject_fifo-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt new file mode 100644 index 000000000..7a335c309 --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt @@ -0,0 +1,2 @@ +CMake Error in .* + Error while reading Byte-Order-Mark\. File not seekable\? diff --git a/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake b/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake index 2d14a9e59..b24a6801b 100644 --- a/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake +++ b/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake @@ -6,9 +6,10 @@ add_library(empty3 INTERFACE) target_compile_features(empty3 INTERFACE cxx_std_11) target_link_libraries(empty1 - # When starting, $ is '0', so 'freeze' the + # When starting, $ is '0', so 'freeze' the # CXX_STANDARD at 98 during computation. - $<$:empty2> + $<$:empty2> + # This would add cxx_std_11, but that would require CXX_STANDARD = 11, # which is not allowed after freeze. Report an error. empty3 diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake index 8dc627d45..5a70da2fa 100644 --- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake @@ -1,3 +1,4 @@ +cmake_policy(SET CMP0057 NEW) include(RunCMake) run_cmake(NotAFeature) @@ -28,13 +29,13 @@ endif() if (NOT CXX_FEATURES) run_cmake(NoSupportedCxxFeatures) run_cmake(NoSupportedCxxFeaturesGenex) -else() +elseif (cxx_std_98 IN_LIST CXX_FEATURES AND cxx_std_11 IN_LIST CXX_FEATURES) if(CXX_STANDARD_DEFAULT EQUAL 98) run_cmake(LinkImplementationFeatureCycle) endif() run_cmake(LinkImplementationFeatureCycleSolved) - if (";${CXX_FEATURES};" MATCHES ";cxx_final;") + if (cxx_final IN_LIST CXX_FEATURES) set(RunCMake_TEST_OPTIONS "-DHAVE_FINAL=1") endif() run_cmake(NonValidTarget1) diff --git a/Tests/RunCMake/DisallowedCommands/CMP0029-OLD-stderr.txt b/Tests/RunCMake/DisallowedCommands/CMP0029-OLD-stderr.txt new file mode 100644 index 000000000..430c86527 --- /dev/null +++ b/Tests/RunCMake/DisallowedCommands/CMP0029-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0029-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0029 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/DisallowedCommands/CMP0030-OLD-stderr.txt b/Tests/RunCMake/DisallowedCommands/CMP0030-OLD-stderr.txt index e95e16f86..d00b8272b 100644 --- a/Tests/RunCMake/DisallowedCommands/CMP0030-OLD-stderr.txt +++ b/Tests/RunCMake/DisallowedCommands/CMP0030-OLD-stderr.txt @@ -1,4 +1,15 @@ -^CMake Error at CMP0030-OLD.cmake:2 \(use_mangled_mesa\): +^CMake Deprecation Warning at CMP0030-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0030 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ +CMake Error at CMP0030-OLD.cmake:2 \(use_mangled_mesa\): use_mangled_mesa called with incorrect number of arguments Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt new file mode 100644 index 000000000..723c46753 --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt @@ -0,0 +1,91 @@ +-- The following TYPE1 packages have been found: + + \* Foo, The Foo package, + +-- The following TYPE2 packages have not been found: + + \* Bar + +-- The following TYPE3 packages have not been found: + + \* Baz + +--[ ] + \* Foo, The Foo package, + +--[ ] + \* Bar + +--[ ] + \* Baz + +-- TYPE1 pkgs found + + \* Foo, The Foo package, + +-- TYPE2 pkgs not found + + \* Bar + +-- TYPE3 pkgs not found + + \* Baz + +-- The following TYPE1 packages have been found: + + \* Foo, The Foo package, + +-- The following TYPE2 packages have not been found: + + \* Bar + +-- The following TYPE3 packages have not been found: + + \* Baz + +-- The following first type packages have been found: + + \* Foo, The Foo package, + +-- The following second type packages have not been found: + + \* Bar + +-- The following third type packages have not been found: + + \* Baz + +--[ ] + \* Foo, The Foo package, + +--[ ] + \* Bar + +--[ ] + \* Baz + +-- TYPE1 pkgs found + + \* Foo, The Foo package, + +-- TYPE2 pkgs not found + + \* Bar + +-- TYPE3 pkgs not found + + \* Baz + +-- The following first type packages have been found: + + \* Foo, The Foo package, + +-- The following second type packages have not been found: + + \* Bar + +-- The following third type packages have not been found: + + \* Baz + +-- Configuring done diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake new file mode 100644 index 000000000..e61b65281 --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake @@ -0,0 +1,158 @@ +include(FeatureSummary) +set_property(GLOBAL PROPERTY FeatureSummary_PKG_TYPES TYPE1 TYPE2 TYPE3) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +find_package(Foo) +find_package(Bar) +find_package(Baz) + +set_package_properties(Foo PROPERTIES TYPE TYPE1) +set_package_properties(Bar PROPERTIES TYPE TYPE2) +set_package_properties(Baz PROPERTIES TYPE TYPE3) + +feature_summary(WHAT ALL) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs found\n") +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs not found\n") +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs found\n") +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs not found\n") +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs found\n") +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs not found\n") + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) + +set_property(GLOBAL PROPERTY FeatureSummary_TYPE1_DESCRIPTION "first type packages") +set_property(GLOBAL PROPERTY FeatureSummary_TYPE2_DESCRIPTION "second type packages") +set_property(GLOBAL PROPERTY FeatureSummary_TYPE3_DESCRIPTION "third type packages") + +feature_summary(WHAT ALL) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs found\n") +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs not found\n") +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs found\n") +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs not found\n") +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs found\n") +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs not found\n") + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt new file mode 100644 index 000000000..47bdee38e --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt @@ -0,0 +1,46 @@ +-- The following RUNTIME packages have been found: + + \* Foo, The Foo package, + +-- The following OPTIONAL packages have not been found: + + \* Bar + +-- The following REQUIRED packages have not been found: + + \* Baz + +--[ ] + \* Foo, The Foo package, + +--[ ] + \* Bar + +--[ ] + \* Baz + +-- RUNTIME pkgs found + + \* Foo, The Foo package, + +-- OPTIONAL pkgs not found + + \* Bar + +-- REQUIRED pkgs not found + + \* Baz + +-- The following RUNTIME packages have been found: + + \* Foo, The Foo package, + +-- The following OPTIONAL packages have not been found: + + \* Bar + +-- The following REQUIRED packages have not been found: + + \* Baz + +-- Configuring done diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake new file mode 100644 index 000000000..536fe72c8 --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake @@ -0,0 +1,82 @@ +include(FeatureSummary) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +find_package(Foo) +find_package(Bar) +find_package(Baz) + +set_package_properties(Foo PROPERTIES TYPE RUNTIME) +set_package_properties(Bar PROPERTIES TYPE OPTIONAL) +set_package_properties(Baz PROPERTIES TYPE REQUIRED) + +feature_summary(WHAT ALL) + +feature_summary(WHAT RUNTIME_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT OPTIONAL_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT REQUIRED_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) + +feature_summary(WHAT RUNTIME_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "RUNTIME pkgs found\n") +feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "RUNTIME pkgs not found\n") +feature_summary(WHAT OPTIONAL_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "OPTIONAL pkgs found\n") +feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "OPTIONAL pkgs not found\n") +feature_summary(WHAT REQUIRED_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "REQUIRED pkgs found\n") +feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "REQUIRED pkgs not found\n") + +feature_summary(WHAT RUNTIME_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT OPTIONAL_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT REQUIRED_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) diff --git a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake index 9caee4c0e..c672c1640 100644 --- a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake +++ b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake @@ -14,8 +14,10 @@ run_cmake(FeatureSummaryFatalOnMissingRequiredPackages) run_cmake(FeatureSummaryIncludeQuietPackages) run_cmake(FeatureSummaryQuietOnEmpty) run_cmake(FeatureSummaryMultipleDepends) +run_cmake(FeatureSummaryDefaultDescription) run_cmake(FeatureSummaryCustomTypes) run_cmake(FeatureSummaryCustomBadDefault) run_cmake(FeatureSummaryCustomRequired) run_cmake(FeatureSummaryCustomRequiredListA) run_cmake(FeatureSummaryCustomRequiredListB) +run_cmake(FeatureSummaryCustomDescription) diff --git a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt index 0abb7df69..a24218004 100644 --- a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt +++ b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt @@ -1,5 +1,6 @@ CMake Error in CMakeLists.txt: - Evaluation file to be written multiple times for different configurations - or languages with different content: + Evaluation file to be written multiple times with different content. This + is generally caused by the content evaluating the configuration type, + language, or location of object files: .*output.txt diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt index d3aa97321..b08ef5a15 100644 --- a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt +++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt @@ -1,9 +1,8 @@ -CMake Error at OutputNameMatchesObjects.cmake:2 \(file\): +CMake Error at OutputNameMatchesObjects.cmake:[0-9]+ \(file\): Error evaluating generator expression: \$ - The evaluation of the TARGET_OBJECTS generator expression is only suitable - for consumption by CMake. It is not suitable for writing out elsewhere. + Objects of target "foo" referenced but is not an OBJECT library. Call Stack \(most recent call first\): - CMakeLists.txt:6 \(include\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake index d8074507b..daa7c49ca 100644 --- a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake +++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$>somefile.cpp" diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake index db344ef4b..82e903d82 100644 --- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake +++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake @@ -1,7 +1,7 @@ include(RunCMake) run_cmake(CommandConflict) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode" AND NOT XCODE_BELOW_2) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode") run_cmake(OutputConflict) endif() run_cmake(EmptyCondition1) diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake index 4a4153391..2687efefb 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake @@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME endif() else() # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) - if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake index b66d02f1a..74cda2588 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake @@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME endif() else() # not debian, check the FIND_LIBRARY_USE_LIB64_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) - if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake index bdecb8ae6..1defde840 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake @@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME endif() else() # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS propertie + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) - if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake index df6723597..166a617df 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake @@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME endif() else() # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) - if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig") + elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig") elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig") diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake index 1351b6fbf..e4673b3c1 100644 --- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake @@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME endif() else() # not debian, check the FIND_LIBRARY_USE_LIB64_PATHS and FIND_LIBRARY_USE_LIB32_PATHS properties + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) - if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat index f2f86b0a6..b03837030 100755 --- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat +++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat @@ -1,7 +1,11 @@ @ECHO OFF + +:LOOP + IF "%1"=="" ( EXIT /B 255 ) + IF "%1"=="--version" ( ECHO 0.0-cmake-dummy EXIT /B 0 @@ -13,6 +17,11 @@ IF "%1"=="--exists" ( ECHO Found: %PKG_CONFIG_PATH% IF NOT "%*"=="%PKG_CONFIG_PATH%" ( EXIT /B 1 + ) ELSE ( + EXIT /B 0 ) ) -EXIT /B 0 +SHIFT +IF NOT "%~1"=="" GOTO LOOP + +EXIT /B 255 diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh index abe14bf98..56bba30dd 100755 --- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh +++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh @@ -4,18 +4,20 @@ # to the --exists argument with the PKG_CONFIG_PATH environment variable # and returns 1 if they are different. -case $1 in - --version) - echo "0.0-cmake-dummy" - ;; - --exists) - shift - eval last=\${$#} - echo "Expected: ${last}" - echo "Found: ${PKG_CONFIG_PATH}" - [ "${last}" = "${PKG_CONFIG_PATH}" ] || exit 1 - ;; - *) - exit 255 - ;; -esac +while [ $# -gt 0 ]; do + case $1 in + --version) + echo "0.0-cmake-dummy" + exit 0 + ;; + --exists) + shift + eval last=\${$#} + echo "Expected: ${last}" + echo "Found: ${PKG_CONFIG_PATH}" + [ "${last}" = "${PKG_CONFIG_PATH}" ] && exit 0 || exit 1 + ;; + esac + shift +done +exit 255 diff --git a/Tests/RunCMake/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder b/Tests/RunCMake/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder b/Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/Framework/FrameworkLayout.cmake b/Tests/RunCMake/Framework/FrameworkLayout.cmake index ae32134b3..3d62a8af3 100644 --- a/Tests/RunCMake/Framework/FrameworkLayout.cmake +++ b/Tests/RunCMake/Framework/FrameworkLayout.cmake @@ -1,14 +1,25 @@ cmake_minimum_required(VERSION 3.4) enable_language(C) +set(CMAKE_CONFIGURATION_TYPES "Debug" CACHE INTERNAL "Supported configuration types") +set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) # get rid of ${EFFECTIVE_PLATFORM_NAME} + add_library(Framework ${FRAMEWORK_TYPE} foo.c foo.h - res.txt) + res.txt + flatresource.txt + deepresource.txt + some.txt) set_target_properties(Framework PROPERTIES FRAMEWORK TRUE PUBLIC_HEADER foo.h RESOURCE "res.txt") +set_source_files_properties(flatresource.txt PROPERTIES MACOSX_PACKAGE_LOCATION Resources) +set_source_files_properties(deepresource.txt PROPERTIES MACOSX_PACKAGE_LOCATION Resources/deep) +set_source_files_properties(some.txt PROPERTIES MACOSX_PACKAGE_LOCATION somedir) add_custom_command(TARGET Framework POST_BUILD COMMAND /usr/bin/file $) + +file(GENERATE OUTPUT FrameworkName.cmake CONTENT "set(framework-dir \"$\")\n") diff --git a/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt b/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt index 8d90f5f72..f664db91f 100644 --- a/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt +++ b/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt @@ -1 +1,3 @@ -.*/Framework: Mach-O[^\n]* dynamically linked shared library.* +.*/Framework:( Mach-O universal binary with [^ +]*)? Mach-O[^ +]* dynamically linked shared library.* diff --git a/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt b/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt index c9f50b6e8..532cfedcc 100644 --- a/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt +++ b/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt @@ -1 +1,2 @@ -.*/Framework: current ar archive random library.* +.*/Framework:( Mach-O universal binary with [^ +]*)? current ar archive random library.* diff --git a/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake b/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake index da1ccb40b..eb71394a9 100644 --- a/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake +++ b/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake @@ -1,8 +1,11 @@ -set(framework-dir "${RunCMake_TEST_BINARY_DIR}/Framework.framework") +include("${RunCMake_TEST_BINARY_DIR}/FrameworkName.cmake") set(framework-resources "${framework-dir}/Resources") set(framework-resource-file "${framework-resources}/res.txt") +set(framework-flat-resource-file "${framework-resources}/flatresource.txt") +set(framework-deep-resource-file "${framework-resources}/deep/deepresource.txt") set(framework-library "${framework-dir}/Framework") set(framework-versions "${framework-dir}/Versions") +set(framework-some-file "${framework-versions}/Current/somedir/some.txt") set(plist-file "${framework-resources}/Info.plist") set(framework-header "${framework-dir}/Headers/foo.h") @@ -22,6 +25,18 @@ if(NOT EXISTS ${framework-resource-file}) message(SEND_ERROR "Framework resource file not found at ${framework-resource-file}") endif() +if(NOT EXISTS ${framework-flat-resource-file}) + message(SEND_ERROR "Framework flat resource file not found at ${framework-flat-resource-file}") +endif() + +if(NOT EXISTS ${framework-deep-resource-file}) + message(SEND_ERROR "Framework deep resource file not found at ${framework-deep-resource-file}") +endif() + +if(NOT EXISTS ${framework-some-file}) + message(SEND_ERROR "Framework some file not found at ${framework-some-file}") +endif() + if(NOT EXISTS ${framework-versions}) message(SEND_ERROR "Framework versions not found at ${framework-versions}") endif() diff --git a/Tests/RunCMake/Framework/RunCMakeTest.cmake b/Tests/RunCMake/Framework/RunCMakeTest.cmake index e64892d2d..4fc83f801 100644 --- a/Tests/RunCMake/Framework/RunCMakeTest.cmake +++ b/Tests/RunCMake/Framework/RunCMakeTest.cmake @@ -13,13 +13,10 @@ function(framework_layout_test Name Toolchain Type) run_cmake_command(${Name} ${CMAKE_COMMAND} --build .) endfunction() -# build check cannot cope with multi-configuration generators directory layout -if(NOT RunCMake_GENERATOR STREQUAL "Xcode") - framework_layout_test(iOSFrameworkLayout-build ios SHARED) - framework_layout_test(iOSFrameworkLayout-build ios STATIC) - framework_layout_test(OSXFrameworkLayout-build osx SHARED) - framework_layout_test(OSXFrameworkLayout-build osx STATIC) -endif() +framework_layout_test(iOSFrameworkLayout-build ios SHARED) +framework_layout_test(iOSFrameworkLayout-build ios STATIC) +framework_layout_test(OSXFrameworkLayout-build osx SHARED) +framework_layout_test(OSXFrameworkLayout-build osx STATIC) function(framework_type_test Toolchain Type) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${Toolchain}${Type}FrameworkType-build) diff --git a/Tests/RunCMake/Framework/deepresource.txt b/Tests/RunCMake/Framework/deepresource.txt new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/Framework/flatresource.txt b/Tests/RunCMake/Framework/flatresource.txt new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake b/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake index b81a5f732..2da60d2a5 100644 --- a/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake +++ b/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake @@ -1,6 +1,9 @@ -set(framework-dir "${RunCMake_TEST_BINARY_DIR}/Framework.framework") +include("${RunCMake_TEST_BINARY_DIR}/FrameworkName.cmake") set(framework-resources "${framework-dir}/Resources") set(framework-resource-file "${framework-dir}/res.txt") +set(framework-flat-resource-file "${framework-dir}/flatresource.txt") +set(framework-deep-resource-file "${framework-dir}/deep/deepresource.txt") +set(framework-some-file "${framework-dir}/somedir/some.txt") set(framework-library "${framework-dir}/Framework") set(framework-versions "${framework-dir}/Versions") set(plist-file "${framework-dir}/Info.plist") @@ -22,6 +25,18 @@ if(NOT EXISTS ${framework-resource-file}) message(SEND_ERROR "Framework resource file not found at ${framework-resource-file}") endif() +if(NOT EXISTS ${framework-flat-resource-file}) + message(SEND_ERROR "Framework flat resource file not found at ${framework-flat-resource-file}") +endif() + +if(NOT EXISTS ${framework-deep-resource-file}) + message(SEND_ERROR "Framework deep resource file not found at ${framework-deep-resource-file}") +endif() + +if(NOT EXISTS ${framework-some-file}) + message(SEND_ERROR "Framework some file not found at ${framework-some-file}") +endif() + if(EXISTS ${framework-versions}) message(SEND_ERROR "Framework versions found at ${framework-versions}") endif() diff --git a/Tests/RunCMake/Framework/some.txt b/Tests/RunCMake/Framework/some.txt new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/GNUInstallDirs/Common.cmake b/Tests/RunCMake/GNUInstallDirs/Common.cmake index eff2d54b3..919cd91f4 100644 --- a/Tests/RunCMake/GNUInstallDirs/Common.cmake +++ b/Tests/RunCMake/GNUInstallDirs/Common.cmake @@ -1,8 +1,5 @@ set(CMAKE_SIZEOF_VOID_P 8) set(CMAKE_LIBRARY_ARCHITECTURE "arch") -if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") - set(CMAKE_SYSTEM_NAME "OpenBSD-Fake") -endif() include(GNUInstallDirs) set(dirs BINDIR @@ -15,6 +12,7 @@ set(dirs LIBEXECDIR LOCALEDIR LOCALSTATEDIR + RUNSTATEDIR MANDIR SBINDIR SHAREDSTATEDIR diff --git a/Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt new file mode 100644 index 000000000..09ae30334 --- /dev/null +++ b/Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt @@ -0,0 +1,30 @@ +^CMAKE_INSTALL_BINDIR='bin' +CMAKE_INSTALL_DATADIR='share' +CMAKE_INSTALL_DATAROOTDIR='share' +CMAKE_INSTALL_DOCDIR='share/doc/Opt' +CMAKE_INSTALL_INCLUDEDIR='include' +CMAKE_INSTALL_INFODIR='info' +CMAKE_INSTALL_LIBDIR='(lib|lib64)' +CMAKE_INSTALL_LIBEXECDIR='libexec' +CMAKE_INSTALL_LOCALEDIR='share/locale' +CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' +CMAKE_INSTALL_MANDIR='man' +CMAKE_INSTALL_SBINDIR='sbin' +CMAKE_INSTALL_SHAREDSTATEDIR='com' +CMAKE_INSTALL_SYSCONFDIR='etc' +CMAKE_INSTALL_FULL_BINDIR='/opt/Opt/bin' +CMAKE_INSTALL_FULL_DATADIR='/opt/Opt/share' +CMAKE_INSTALL_FULL_DATAROOTDIR='/opt/Opt/share' +CMAKE_INSTALL_FULL_DOCDIR='/opt/Opt/share/doc/Opt' +CMAKE_INSTALL_FULL_INCLUDEDIR='/opt/Opt/include' +CMAKE_INSTALL_FULL_INFODIR='/opt/Opt/info' +CMAKE_INSTALL_FULL_LIBDIR='/opt/Opt/(lib|lib64)' +CMAKE_INSTALL_FULL_LIBEXECDIR='/opt/Opt/libexec' +CMAKE_INSTALL_FULL_LOCALEDIR='/opt/Opt/share/locale' +CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var/opt/Opt' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run/opt/Opt' +CMAKE_INSTALL_FULL_MANDIR='/opt/Opt/man' +CMAKE_INSTALL_FULL_SBINDIR='/opt/Opt/sbin' +CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/opt/Opt/com' +CMAKE_INSTALL_FULL_SYSCONFDIR='/etc/opt/Opt'$ diff --git a/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt index aee8552c8..3e1841060 100644 --- a/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt +++ b/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt @@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='(lib|lib64)' CMAKE_INSTALL_LIBEXECDIR='libexec' CMAKE_INSTALL_LOCALEDIR='share/locale' CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' CMAKE_INSTALL_MANDIR='share/man' CMAKE_INSTALL_SBINDIR='sbin' CMAKE_INSTALL_SHAREDSTATEDIR='com' @@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/opt/Opt/(lib|lib64)' CMAKE_INSTALL_FULL_LIBEXECDIR='/opt/Opt/libexec' CMAKE_INSTALL_FULL_LOCALEDIR='/opt/Opt/share/locale' CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var/opt/Opt' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run/opt/Opt' CMAKE_INSTALL_FULL_MANDIR='/opt/Opt/share/man' CMAKE_INSTALL_FULL_SBINDIR='/opt/Opt/sbin' CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/opt/Opt/com' diff --git a/Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt new file mode 100644 index 000000000..4be66bcaf --- /dev/null +++ b/Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt @@ -0,0 +1,30 @@ +^CMAKE_INSTALL_BINDIR='usr/bin' +CMAKE_INSTALL_DATADIR='usr/share' +CMAKE_INSTALL_DATAROOTDIR='usr/share' +CMAKE_INSTALL_DOCDIR='usr/share/doc/Root' +CMAKE_INSTALL_INCLUDEDIR='usr/include' +CMAKE_INSTALL_INFODIR='usr/info' +CMAKE_INSTALL_LIBDIR='usr/(lib|lib64)' +CMAKE_INSTALL_LIBEXECDIR='usr/libexec' +CMAKE_INSTALL_LOCALEDIR='usr/share/locale' +CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' +CMAKE_INSTALL_MANDIR='usr/man' +CMAKE_INSTALL_SBINDIR='usr/sbin' +CMAKE_INSTALL_SHAREDSTATEDIR='usr/com' +CMAKE_INSTALL_SYSCONFDIR='etc' +CMAKE_INSTALL_FULL_BINDIR='/usr/bin' +CMAKE_INSTALL_FULL_DATADIR='/usr/share' +CMAKE_INSTALL_FULL_DATAROOTDIR='/usr/share' +CMAKE_INSTALL_FULL_DOCDIR='/usr/share/doc/Root' +CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/include' +CMAKE_INSTALL_FULL_INFODIR='/usr/info' +CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64)' +CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec' +CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale' +CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run' +CMAKE_INSTALL_FULL_MANDIR='/usr/man' +CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin' +CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com' +CMAKE_INSTALL_FULL_SYSCONFDIR='/etc'$ diff --git a/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt index a95400e86..8c133681f 100644 --- a/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt +++ b/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt @@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='usr/(lib|lib64)' CMAKE_INSTALL_LIBEXECDIR='usr/libexec' CMAKE_INSTALL_LOCALEDIR='usr/share/locale' CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' CMAKE_INSTALL_MANDIR='usr/share/man' CMAKE_INSTALL_SBINDIR='usr/sbin' CMAKE_INSTALL_SHAREDSTATEDIR='usr/com' @@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64)' CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec' CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale' CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run' CMAKE_INSTALL_FULL_MANDIR='/usr/share/man' CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin' CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com' diff --git a/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake b/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake index f88569a04..b544ba640 100644 --- a/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake +++ b/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake @@ -1,6 +1,17 @@ include(RunCMake) -run_cmake(Opt) -run_cmake(Root) -run_cmake(Usr) -run_cmake(UsrLocal) +if(SYSTEM_NAME MATCHES "^(.*BSD|DragonFly)$") + set(EXPECT_BSD 1) +endif() + +foreach(case + Opt + Root + Usr + UsrLocal + ) + if(EXPECT_BSD) + set(RunCMake-stderr-file ${case}-BSD-stderr.txt) + endif() + run_cmake(${case}) +endforeach() diff --git a/Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt new file mode 100644 index 000000000..3d7b4c853 --- /dev/null +++ b/Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt @@ -0,0 +1,30 @@ +^CMAKE_INSTALL_BINDIR='bin' +CMAKE_INSTALL_DATADIR='share' +CMAKE_INSTALL_DATAROOTDIR='share' +CMAKE_INSTALL_DOCDIR='share/doc/Usr' +CMAKE_INSTALL_INCLUDEDIR='include' +CMAKE_INSTALL_INFODIR='info' +CMAKE_INSTALL_LIBDIR='(lib|lib64|lib/arch)' +CMAKE_INSTALL_LIBEXECDIR='libexec' +CMAKE_INSTALL_LOCALEDIR='share/locale' +CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' +CMAKE_INSTALL_MANDIR='man' +CMAKE_INSTALL_SBINDIR='sbin' +CMAKE_INSTALL_SHAREDSTATEDIR='com' +CMAKE_INSTALL_SYSCONFDIR='etc' +CMAKE_INSTALL_FULL_BINDIR='/usr/bin' +CMAKE_INSTALL_FULL_DATADIR='/usr/share' +CMAKE_INSTALL_FULL_DATAROOTDIR='/usr/share' +CMAKE_INSTALL_FULL_DOCDIR='/usr/share/doc/Usr' +CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/include' +CMAKE_INSTALL_FULL_INFODIR='/usr/info' +CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64|lib/arch)' +CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec' +CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale' +CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run' +CMAKE_INSTALL_FULL_MANDIR='/usr/man' +CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin' +CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com' +CMAKE_INSTALL_FULL_SYSCONFDIR='/etc'$ diff --git a/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt index e10c4c595..a591436ba 100644 --- a/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt +++ b/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt @@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='(lib|lib64|lib/arch)' CMAKE_INSTALL_LIBEXECDIR='libexec' CMAKE_INSTALL_LOCALEDIR='share/locale' CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' CMAKE_INSTALL_MANDIR='share/man' CMAKE_INSTALL_SBINDIR='sbin' CMAKE_INSTALL_SHAREDSTATEDIR='com' @@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64|lib/arch)' CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec' CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale' CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run' CMAKE_INSTALL_FULL_MANDIR='/usr/share/man' CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin' CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com' diff --git a/Tests/RunCMake/GNUInstallDirs/UsrLocal-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/UsrLocal-BSD-stderr.txt new file mode 100644 index 000000000..e1425d574 --- /dev/null +++ b/Tests/RunCMake/GNUInstallDirs/UsrLocal-BSD-stderr.txt @@ -0,0 +1,30 @@ +^CMAKE_INSTALL_BINDIR='bin' +CMAKE_INSTALL_DATADIR='share' +CMAKE_INSTALL_DATAROOTDIR='share' +CMAKE_INSTALL_DOCDIR='share/doc/UsrLocal' +CMAKE_INSTALL_INCLUDEDIR='include' +CMAKE_INSTALL_INFODIR='info' +CMAKE_INSTALL_LIBDIR='(lib|lib64)' +CMAKE_INSTALL_LIBEXECDIR='libexec' +CMAKE_INSTALL_LOCALEDIR='share/locale' +CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' +CMAKE_INSTALL_MANDIR='man' +CMAKE_INSTALL_SBINDIR='sbin' +CMAKE_INSTALL_SHAREDSTATEDIR='com' +CMAKE_INSTALL_SYSCONFDIR='etc' +CMAKE_INSTALL_FULL_BINDIR='/usr/local/bin' +CMAKE_INSTALL_FULL_DATADIR='/usr/local/share' +CMAKE_INSTALL_FULL_DATAROOTDIR='/usr/local/share' +CMAKE_INSTALL_FULL_DOCDIR='/usr/local/share/doc/UsrLocal' +CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/local/include' +CMAKE_INSTALL_FULL_INFODIR='/usr/local/info' +CMAKE_INSTALL_FULL_LIBDIR='/usr/local/(lib|lib64)' +CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/local/libexec' +CMAKE_INSTALL_FULL_LOCALEDIR='/usr/local/share/locale' +CMAKE_INSTALL_FULL_LOCALSTATEDIR='/usr/local/var' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/usr/local/var/run' +CMAKE_INSTALL_FULL_MANDIR='/usr/local/man' +CMAKE_INSTALL_FULL_SBINDIR='/usr/local/sbin' +CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/local/com' +CMAKE_INSTALL_FULL_SYSCONFDIR='/usr/local/etc'$ diff --git a/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt b/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt index 8dcf25b6e..f957e0e53 100644 --- a/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt +++ b/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt @@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='(lib|lib64)' CMAKE_INSTALL_LIBEXECDIR='libexec' CMAKE_INSTALL_LOCALEDIR='share/locale' CMAKE_INSTALL_LOCALSTATEDIR='var' +CMAKE_INSTALL_RUNSTATEDIR='var/run' CMAKE_INSTALL_MANDIR='share/man' CMAKE_INSTALL_SBINDIR='sbin' CMAKE_INSTALL_SHAREDSTATEDIR='com' @@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/usr/local/(lib|lib64)' CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/local/libexec' CMAKE_INSTALL_FULL_LOCALEDIR='/usr/local/share/locale' CMAKE_INSTALL_FULL_LOCALSTATEDIR='/usr/local/var' +CMAKE_INSTALL_FULL_RUNSTATEDIR='/usr/local/var/run' CMAKE_INSTALL_FULL_MANDIR='/usr/local/share/man' CMAKE_INSTALL_FULL_SBINDIR='/usr/local/sbin' CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/local/com' diff --git a/Tests/RunCMake/GenerateExportHeader/GEH.cmake b/Tests/RunCMake/GenerateExportHeader/GEH.cmake index cddba2903..e0677a7a3 100644 --- a/Tests/RunCMake/GenerateExportHeader/GEH.cmake +++ b/Tests/RunCMake/GenerateExportHeader/GEH.cmake @@ -110,7 +110,7 @@ if (WIN32 OR CYGWIN) else() set(_platform WinEmpty) endif() -elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY) +elseif(COMPILER_HAS_HIDDEN_VISIBILITY) set(_platform UNIX) elseif(COMPILER_HAS_DEPRECATED) set(_platform UNIX_DeprecatedOnly) diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt new file mode 100644 index 000000000..854447f53 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake:[0-9]* \(add_custom_target\): + Error evaluating generator expression: + + \$ + + TARGET_BUNDLE_CONTENT_DIR not allowed for IMPORTED targets. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]* \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake new file mode 100644 index 000000000..ac2d3ce6a --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake @@ -0,0 +1,2 @@ +add_library(empty UNKNOWN IMPORTED) +add_custom_target(custom COMMAND echo $) diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-result.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt new file mode 100644 index 000000000..9b97df1a4 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at ImportedTarget-TARGET_BUNDLE_DIR.cmake:[0-9]* \(add_custom_target\): + Error evaluating generator expression: + + \$ + + TARGET_BUNDLE_DIR not allowed for IMPORTED targets. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]* \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR.cmake b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR.cmake new file mode 100644 index 000000000..17c81287c --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR.cmake @@ -0,0 +1,2 @@ +add_library(empty UNKNOWN IMPORTED) +add_custom_target(custom COMMAND echo $) diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt new file mode 100644 index 000000000..03c02d910 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake:[0-9]* \(file\): + Error evaluating generator expression: + + \$ + + TARGET_BUNDLE_CONTENT_DIR is allowed only for Bundle targets. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]* \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake new file mode 100644 index 000000000..63b3b1beb --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake @@ -0,0 +1,9 @@ + +enable_language(C) + +add_library(empty STATIC empty.c) + +file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt" + CONTENT "[$]" +) diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-result.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt new file mode 100644 index 000000000..f895c88b5 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at NonValidTarget-TARGET_BUNDLE_DIR.cmake:[0-9]* \(file\): + Error evaluating generator expression: + + \$ + + TARGET_BUNDLE_DIR is allowed only for Bundle targets. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]* \(include\) diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR.cmake new file mode 100644 index 000000000..19f333aa1 --- /dev/null +++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR.cmake @@ -0,0 +1,9 @@ + +enable_language(C) + +add_library(empty STATIC empty.c) + +file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt" + CONTENT "[$]" +) diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake index 084b5c336..63cd2daf7 100644 --- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake @@ -17,6 +17,8 @@ run_cmake(NonValidTarget-C_COMPILER_ID) run_cmake(NonValidTarget-CXX_COMPILER_ID) run_cmake(NonValidTarget-C_COMPILER_VERSION) run_cmake(NonValidTarget-CXX_COMPILER_VERSION) +run_cmake(NonValidTarget-TARGET_BUNDLE_DIR) +run_cmake(NonValidTarget-TARGET_BUNDLE_CONTENT_DIR) run_cmake(NonValidTarget-TARGET_PROPERTY) run_cmake(NonValidTarget-TARGET_POLICY) run_cmake(COMPILE_LANGUAGE-add_custom_target) @@ -32,6 +34,8 @@ run_cmake(OUTPUT_NAME-recursion) run_cmake(TARGET_PROPERTY-LOCATION) run_cmake(LINK_ONLY-not-linking) +run_cmake(ImportedTarget-TARGET_BUNDLE_DIR) +run_cmake(ImportedTarget-TARGET_BUNDLE_CONTENT_DIR) run_cmake(ImportedTarget-TARGET_PDB_FILE) if(LINKER_SUPPORTS_PDB) run_cmake(NonValidTarget-TARGET_PDB_FILE) diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt new file mode 100644 index 000000000..ab3a98fc8 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset specification + + Test Toolset,not_a_key + + that contains a field after the first ',' with no '='\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake new file mode 100644 index 000000000..2fc38e5c5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt index 5737e953e..bd0063a29 100644 --- a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt @@ -3,8 +3,8 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\): .* - does not recognize the toolset + given toolset specification Test Toolset,host=x6[45] - that was specified\.$ + that contains invalid field 'host=x6[45]'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt new file mode 100644 index 000000000..164d3aa79 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset specification + + Test Toolset,host=x64,host=x64 + + that contains duplicate field key 'host'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake new file mode 100644 index 000000000..2fc38e5c5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt new file mode 100644 index 000000000..5737e953e --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + does not recognize the toolset + + Test Toolset,host=x6[45] + + that was specified\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake new file mode 100644 index 000000000..2fc38e5c5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index e8ce47df0..f89100e84 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -3,9 +3,15 @@ include(RunCMake) set(RunCMake_GENERATOR_TOOLSET "") run_cmake(NoToolset) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_BELOW_3) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=Test Cuda") + run_cmake(TestToolsetCudaBoth) + set(RunCMake_GENERATOR_TOOLSET ",cuda=Test Cuda") + run_cmake(TestToolsetCudaOnly) + set(RunCMake_GENERATOR_TOOLSET "cuda=Test Cuda") + run_cmake(TestToolsetCudaOnly) if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(TestToolsetHostArchBoth) @@ -17,10 +23,19 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_ run_cmake(TestToolsetHostArchNone) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x65") run_cmake(BadToolsetHostArch) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x64") + run_cmake(BadToolsetHostArchTwice) else() set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(BadToolsetHostArch) endif() + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,not_a_key") + run_cmake(BadToolsetFormat) +elseif("${RunCMake_GENERATOR}" STREQUAL "Xcode") + set(RunCMake_GENERATOR_TOOLSET "Test Toolset") + run_cmake(TestToolset) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") + run_cmake(BadToolsetHostArchXcode) else() set(RunCMake_GENERATOR_TOOLSET "Bad Toolset") run_cmake(BadToolset) @@ -32,7 +47,7 @@ set(RunCMake_TEST_OPTIONS -T "Extra Toolset") run_cmake(TwoToolsets) unset(RunCMake_TEST_OPTIONS) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_BELOW_3) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode") set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestToolset-toolchain.cmake) run_cmake(TestToolsetToolchain) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt new file mode 100644 index 000000000..90503e2cc --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='Test Toolset' +-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake new file mode 100644 index 000000000..befa0af9d --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'") diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt new file mode 100644 index 000000000..94e1e43e4 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt @@ -0,0 +1,2 @@ +-- CMAKE_VS_PLATFORM_TOOLSET='(v[0-9]+|Windows7.1SDK)' +-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake new file mode 100644 index 000000000..befa0af9d --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake @@ -0,0 +1,2 @@ +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'") +message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'") diff --git a/Tests/RunCMake/Ninja/AssumedSources.cmake b/Tests/RunCMake/Ninja/AssumedSources.cmake new file mode 100644 index 000000000..5fb02199d --- /dev/null +++ b/Tests/RunCMake/Ninja/AssumedSources.cmake @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.8) +project(AssumedSources) + +set_source_files_properties( + "${CMAKE_CURRENT_BINARY_DIR}/target.c" + "${CMAKE_CURRENT_BINARY_DIR}/target-no-depends.c" + PROPERTIES GENERATED 1) + +add_executable(working + "${CMAKE_CURRENT_BINARY_DIR}/target.c" + "${CMAKE_CURRENT_BINARY_DIR}/target-no-depends.c") + +add_custom_target( + gen-target.c ALL + COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/dep.c" "${CMAKE_CURRENT_BINARY_DIR}/target.c") +add_custom_target( + gen-target-no-depends.c ALL + COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/dep.c" "${CMAKE_CURRENT_BINARY_DIR}/target-no-depends.c") + +add_dependencies(working gen-target.c) diff --git a/Tests/RunCMake/Ninja/CommandConcat.cmake b/Tests/RunCMake/Ninja/CommandConcat.cmake new file mode 100644 index 000000000..790cf9d25 --- /dev/null +++ b/Tests/RunCMake/Ninja/CommandConcat.cmake @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.7) +project(concat_cmd NONE) +set(output1 ${CMAKE_BINARY_DIR}/out1.txt) +set(output2 ${CMAKE_BINARY_DIR}/out2.txt) +file(REMOVE ${output1} ${output2}) +# Check that second command runs if first command contains "||" which has higher precedence than "&&" on Windows +add_custom_target(concat_cmd ALL + COMMAND ${CMAKE_COMMAND} -E echo "Hello || pipe world" && ${CMAKE_COMMAND} -E touch ${output1} || exit 1 + COMMAND ${CMAKE_COMMAND} -E touch ${output2}) +# Check output +add_custom_target(check_output ALL + COMMAND ${CMAKE_COMMAND} -E copy ${output1} ${output1}.copy + COMMAND ${CMAKE_COMMAND} -E copy ${output2} ${output2}.copy) +add_dependencies(check_output concat_cmd) diff --git a/Tests/RunCMake/Ninja/LooseObjectDepends.cmake b/Tests/RunCMake/Ninja/LooseObjectDepends.cmake new file mode 100644 index 000000000..360c7ba13 --- /dev/null +++ b/Tests/RunCMake/Ninja/LooseObjectDepends.cmake @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.8) +project(LooseObjectDepends C) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/command.h" + COMMAND "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/command.h" + COMMENT "Creating command.h") +add_custom_target(create-command.h + DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/command.h") + +add_custom_target(create-target.h + BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/target.h" + COMMAND "${CMAKE_COMMAND}" -E touch + "${CMAKE_CURRENT_BINARY_DIR}/target.h" + COMMENT "Creating target.h") + +add_library(dep SHARED dep.c) +add_dependencies(dep create-command.h create-target.h) +target_include_directories(dep + PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}") + +add_library(top top.c) +target_link_libraries(top PRIVATE dep) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 7b4e51e1f..b3720fb7a 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -40,6 +40,16 @@ run_CMP0058(NEW-by) run_cmake(CustomCommandDepfile) +function(run_CommandConcat) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CommandConcat-build) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + run_cmake(CommandConcat) + run_cmake_command(CommandConcat-build ${CMAKE_COMMAND} --build .) +endfunction() +run_CommandConcat() + function(run_SubDir) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SubDir-build) @@ -73,7 +83,7 @@ run_SubDir() function(run_ninja dir) execute_process( - COMMAND "${RunCMake_MAKE_PROGRAM}" + COMMAND "${RunCMake_MAKE_PROGRAM}" ${ARGN} WORKING_DIRECTORY "${dir}" OUTPUT_VARIABLE ninja_stdout ERROR_VARIABLE ninja_stderr @@ -95,6 +105,39 @@ ${ninja_stderr} endif() endfunction(run_ninja) +function (run_LooseObjectDepends) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LooseObjectDepends-build) + run_cmake(LooseObjectDepends) + run_ninja("${RunCMake_TEST_BINARY_DIR}" "CMakeFiles/top.dir/top.c${CMAKE_C_OUTPUT_EXTENSION}") + if (EXISTS "${RunCMake_TEST_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}dep${CMAKE_SHARED_LIBRARY_SUFFIX}") + message(FATAL_ERROR + "The `dep` library was created when requesting an object file to be " + "built; this should no longer be necessary.") + endif () + if (EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/dep.dir/dep.c${CMAKE_C_OUTPUT_EXTENSION}") + message(FATAL_ERROR + "The `dep.c` object file was created when requesting an object file to " + "be built; this should no longer be necessary.") + endif () +endfunction () +run_LooseObjectDepends() + +function (run_AssumedSources) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssumedSources-build) + run_cmake(AssumedSources) + run_ninja("${RunCMake_TEST_BINARY_DIR}" "target.c") + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/target.c") + message(FATAL_ERROR + "Dependencies for an assumed source did not hook up properly for 'target.c'.") + endif () + run_ninja("${RunCMake_TEST_BINARY_DIR}" "target-no-depends.c") + if (EXISTS "${RunCMake_TEST_BINARY_DIR}/target-no-depends.c") + message(FATAL_ERROR + "Dependencies for an assumed source were magically hooked up for 'target-no-depends.c'.") + endif () +endfunction () +run_AssumedSources() + function(sleep delay) execute_process( COMMAND ${CMAKE_COMMAND} -E sleep ${delay} diff --git a/Tests/RunCMake/Ninja/dep.c b/Tests/RunCMake/Ninja/dep.c new file mode 100644 index 000000000..728f03129 --- /dev/null +++ b/Tests/RunCMake/Ninja/dep.c @@ -0,0 +1,4 @@ +int dep() +{ + return 0; +} diff --git a/Tests/RunCMake/Ninja/top.c b/Tests/RunCMake/Ninja/top.c new file mode 100644 index 000000000..4a88eb28d --- /dev/null +++ b/Tests/RunCMake/Ninja/top.c @@ -0,0 +1,7 @@ +#include "command.h" +#include "target.h" + +int top() +{ + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/Dependencies.cmake b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake new file mode 100644 index 000000000..6ddf545c8 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake @@ -0,0 +1,7 @@ +add_library(myobj OBJECT ${CMAKE_BINARY_DIR}/depends_obj.c) +add_library(mylib STATIC $ depends_lib.c) +add_executable(myexe depends_main.c) +target_link_libraries(myexe mylib) + +enable_testing() +add_test(NAME myexe COMMAND $) diff --git a/Tests/RunCMake/ObjectLibrary/Export-stderr.txt b/Tests/RunCMake/ObjectLibrary/Export-stderr.txt deleted file mode 100644 index bdadca488..000000000 --- a/Tests/RunCMake/ObjectLibrary/Export-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -CMake Error at Export.cmake:2 \(export\): - export given OBJECT library "A" which may not be exported. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt new file mode 100644 index 000000000..542015984 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at ExportNotSupported.cmake:[0-9]+ \(export\): + export given OBJECT library "A" which may not be exported under Xcode with + multiple architectures. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake b/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake new file mode 100644 index 000000000..a3f104e29 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake @@ -0,0 +1,2 @@ +add_library(A OBJECT a.c) +export(TARGETS A FILE AExport.cmake) diff --git a/Tests/RunCMake/ObjectLibrary/Import.cmake b/Tests/RunCMake/ObjectLibrary/Import.cmake index 806b44a25..42f446866 100644 --- a/Tests/RunCMake/ObjectLibrary/Import.cmake +++ b/Tests/RunCMake/ObjectLibrary/Import.cmake @@ -1 +1,12 @@ + 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_property(TARGET A APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) +set_target_properties(A PROPERTIES + IMPORTED_OBJECTS_DEBUG "${CMAKE_CURRENT_BINARY_DIR}/does_not_exist.o" + IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/does_not_exist.o" + ) + +add_library(B $ b.c) diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/Import-stderr.txt b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt similarity index 55% rename from Tests/RunCMake/ObjectLibrary/Import-stderr.txt rename to Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt index 74b496ab8..0fadac208 100644 --- a/Tests/RunCMake/ObjectLibrary/Import-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt @@ -1,4 +1,5 @@ -CMake Error at Import.cmake:1 \(add_library\): - The OBJECT library type may not be used for IMPORTED libraries. +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 new file mode 100644 index 000000000..806b44a25 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake @@ -0,0 +1 @@ +add_library(A OBJECT IMPORTED) diff --git a/Tests/RunCMake/ObjectLibrary/InstallNotSupported-result.txt b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/Install-stderr.txt b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt similarity index 54% rename from Tests/RunCMake/ObjectLibrary/Install-stderr.txt rename to Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt index d2f9f4a37..35a0e4fdf 100644 --- a/Tests/RunCMake/ObjectLibrary/Install-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt @@ -1,4 +1,5 @@ -CMake Error at Install.cmake:2 \(install\): - install TARGETS given OBJECT library "A" which may not be installed. +CMake Error at InstallNotSupported.cmake:[0-9]+ \(install\): + install TARGETS given OBJECT library "A" which may not be installed under + Xcode with multiple architectures. Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/InstallNotSupported.cmake b/Tests/RunCMake/ObjectLibrary/InstallNotSupported.cmake new file mode 100644 index 000000000..c1d214bd4 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/InstallNotSupported.cmake @@ -0,0 +1,2 @@ +add_library(A OBJECT a.c) +install(TARGETS A DESTINATION lib) diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt new file mode 100644 index 000000000..40d650e21 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at OwnSources.cmake:[0-9]+ \(add_library\): + The SOURCES of "A" use a generator expression that depends on the SOURCES + themselves. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources.cmake b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake new file mode 100644 index 000000000..e7bdf8d83 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake @@ -0,0 +1,2 @@ +add_library(A OBJECT a.c) +target_sources(A PRIVATE $) diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index 42973f8af..b8eed73bb 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -5,14 +5,46 @@ run_cmake(BadSourceExpression2) run_cmake(BadSourceExpression3) run_cmake(BadObjSource1) run_cmake(BadObjSource2) -run_cmake(Export) -run_cmake(Import) -run_cmake(Install) +if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]") + run_cmake(ExportNotSupported) + run_cmake(ImportNotSupported) + run_cmake(InstallNotSupported) +else() + run_cmake(Export) + run_cmake(Import) + run_cmake(Install) +endif() run_cmake(LinkObjLHS) run_cmake(LinkObjRHS1) run_cmake(LinkObjRHS2) run_cmake(MissingSource) run_cmake(ObjWithObj) +run_cmake(OwnSources) run_cmake(PostBuild) run_cmake(PreBuild) run_cmake(PreLink) + +function(run_Dependencies) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Dependencies-build) + set(RunCMake_TEST_NO_CLEAN 1) + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR + RunCMake_GENERATOR STREQUAL "Watcom WMake") + set(fs_delay 3) + else() + set(fs_delay 1.125) + endif() + + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj1.c ${RunCMake_TEST_BINARY_DIR}/depends_obj.c) + run_cmake(Dependencies) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E sleep ${fs_delay}) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj0.c ${RunCMake_TEST_BINARY_DIR}/depends_obj.c) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(Dependencies-build ${CMAKE_CTEST_COMMAND} -C Debug -V) +endfunction() + +run_Dependencies() diff --git a/Tests/RunCMake/ObjectLibrary/b.c b/Tests/RunCMake/ObjectLibrary/b.c new file mode 100644 index 000000000..6751907b6 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/b.c @@ -0,0 +1,4 @@ +int b(void) +{ + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_lib.c b/Tests/RunCMake/ObjectLibrary/depends_lib.c new file mode 100644 index 000000000..a41b32c01 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_lib.c @@ -0,0 +1,7 @@ +#include +extern int myobj_foo(void); + +void mylib_foo(void) +{ + exit(myobj_foo()); +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_main.c b/Tests/RunCMake/ObjectLibrary/depends_main.c new file mode 100644 index 000000000..acc66c73c --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_main.c @@ -0,0 +1,7 @@ +extern void mylib_foo(void); + +int main(void) +{ + mylib_foo(); + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj0.c b/Tests/RunCMake/ObjectLibrary/depends_obj0.c new file mode 100644 index 000000000..649d507dc --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj0.c @@ -0,0 +1,4 @@ +int myobj_foo(void) +{ + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj1.c b/Tests/RunCMake/ObjectLibrary/depends_obj1.c new file mode 100644 index 000000000..e1f9f6a7c --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj1.c @@ -0,0 +1,4 @@ +int myobj_foo(void) +{ + return 1; +} diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 5f66da05f..26312c45c 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -51,8 +51,8 @@ function(run_cmake test) if(APPLE) list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0025=NEW) endif() - if(RunCMake_GENERATOR STREQUAL "Visual Studio 7 .NET 2003" AND NOT RunCMake_WARN_VS71) - list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_WARN_VS71=OFF) + if(RunCMake_GENERATOR MATCHES "^Visual Studio 8 2005" AND NOT RunCMake_WARN_VS8) + list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_WARN_VS8=OFF) endif() if(RunCMake_MAKE_PROGRAM) list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}") @@ -101,7 +101,7 @@ function(run_cmake test) endif() foreach(o out err) string(REGEX REPLACE "\r\n" "\n" actual_std${o} "${actual_std${o}}") - string(REGEX REPLACE "(^|\n)((==[0-9]+==|BullseyeCoverage|[a-z]+\\([0-9]+\\) malloc:|Error kstat returned|[^\n]*is a member of multiple groups|[^\n]*from Time Machine by path|[^\n]*Bullseye Testing Technology)[^\n]*\n)+" "\\1" actual_std${o} "${actual_std${o}}") + string(REGEX REPLACE "(^|\n)((==[0-9]+==|BullseyeCoverage|[a-z]+\\([0-9]+\\) malloc:|Error kstat returned|Hit xcodebuild bug|[^\n]*is a member of multiple groups|[^\n]*from Time Machine by path|[^\n]*Bullseye Testing Technology)[^\n]*\n)+" "\\1" actual_std${o} "${actual_std${o}}") string(REGEX REPLACE "\n+$" "" actual_std${o} "${actual_std${o}}") set(expect_${o} "") if(DEFINED expect_std${o}) diff --git a/Tests/RunCMake/TargetObjects/BadContext-stderr.txt b/Tests/RunCMake/TargetObjects/BadContext-stderr.txt deleted file mode 100644 index b78189eea..000000000 --- a/Tests/RunCMake/TargetObjects/BadContext-stderr.txt +++ /dev/null @@ -1,27 +0,0 @@ -(CMake Error at BadContext.cmake:4 \(file\): - Error evaluating generator expression: - - \$ - - The evaluation of the TARGET_OBJECTS generator expression is only suitable - for consumption by CMake. It is not suitable for writing out elsewhere. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) -*)+ -(CMake Error at BadContext.cmake:5 \(file\): - Error evaluating generator expression: - - \$ - - The evaluation of the TARGET_OBJECTS generator expression is only suitable - for consumption by CMake. It is not suitable for writing out elsewhere. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) -*)+ -CMake Error: - Error evaluating generator expression: - - \$ - - The evaluation of the TARGET_OBJECTS generator expression is only suitable - for consumption by CMake. It is not suitable for writing out elsewhere. diff --git a/Tests/RunCMake/TargetObjects/NoTarget-result.txt b/Tests/RunCMake/TargetObjects/NoTarget-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/NoTarget-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TargetObjects/NoTarget-stderr.txt b/Tests/RunCMake/TargetObjects/NoTarget-stderr.txt new file mode 100644 index 000000000..eadccaf12 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/NoTarget-stderr.txt @@ -0,0 +1,24 @@ +(CMake Error at NoTarget.cmake:4 \(file\): + Error evaluating generator expression: + + \$ + + Objects of target "NoTarget" referenced but no such target exists. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) +*)+ +(CMake Error at NoTarget.cmake:5 \(file\): + Error evaluating generator expression: + + \$ + + Objects of target "NoTarget" referenced but no such target exists. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) +*)+ +CMake Error: + Error evaluating generator expression: + + \$ + + Objects of target "NoTarget" referenced but no such target exists. diff --git a/Tests/RunCMake/TargetObjects/BadContext.cmake b/Tests/RunCMake/TargetObjects/NoTarget.cmake similarity index 100% rename from Tests/RunCMake/TargetObjects/BadContext.cmake rename to Tests/RunCMake/TargetObjects/NoTarget.cmake diff --git a/Tests/RunCMake/TargetObjects/NotObjlibTarget-result.txt b/Tests/RunCMake/TargetObjects/NotObjlibTarget-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/NotObjlibTarget-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt new file mode 100644 index 000000000..a66794ce8 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at NotObjlibTarget.cmake:3 \(file\): + Error evaluating generator expression: + + \$ + + Objects of target "StaticLib" referenced but is not an OBJECT library. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake b/Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake new file mode 100644 index 000000000..8e5fdd047 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake @@ -0,0 +1,3 @@ +add_library(StaticLib empty.cpp) + +file(GENERATE OUTPUT test_output CONTENT $) diff --git a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake index 85c76e240..30b9fee53 100644 --- a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake +++ b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake @@ -1,3 +1,4 @@ include(RunCMake) -run_cmake(BadContext) +run_cmake(NoTarget) +run_cmake(NotObjlibTarget) diff --git a/Tests/RunCMake/TargetObjects/empty.cpp b/Tests/RunCMake/TargetObjects/empty.cpp new file mode 100644 index 000000000..4086dcc87 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/empty.cpp @@ -0,0 +1,4 @@ +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 57047fb41..5f6be877b 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -20,6 +20,8 @@ \* CMP0060 \* CMP0063 \* CMP0065 + \* CMP0068 + \* CMP0069 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/TargetSources/CMP0026-LOCATION-stderr.txt b/Tests/RunCMake/TargetSources/CMP0026-LOCATION-stderr.txt new file mode 100644 index 000000000..d7ccedb1b --- /dev/null +++ b/Tests/RunCMake/TargetSources/CMP0026-LOCATION-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0026-LOCATION.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0026 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/TargetSources/RunCMakeTest.cmake b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake index 4416ef9f2..bb55a6ebd 100644 --- a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake +++ b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake @@ -1,6 +1,6 @@ include(RunCMake) -if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode" AND NOT XCODE_BELOW_2) +if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode") run_cmake(ConfigNotAllowed) run_cmake(OriginDebugIDE) else() diff --git a/Tests/RunCMake/VSSolution/MorePost-check.cmake b/Tests/RunCMake/VSSolution/MorePost-check.cmake index 0f7e37084..d239b28b6 100644 --- a/Tests/RunCMake/VSSolution/MorePost-check.cmake +++ b/Tests/RunCMake/VSSolution/MorePost-check.cmake @@ -1,5 +1,5 @@ parseGlobalSections(pre post MorePost) testGlobalSection(post TestSec2 Key1=Value1 "Key2=Value with spaces") testGlobalSection(post TestSec4 Key6=Value1 "Key7=Value with spaces" Key8=ValueWithoutSpaces) -testGlobalSection(post ExtensibilityGlobals) +testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}") testGlobalSection(post ExtensibilityAddIns) diff --git a/Tests/RunCMake/VSSolution/MorePre-check.cmake b/Tests/RunCMake/VSSolution/MorePre-check.cmake index 45e7419f9..89b3c7eb8 100644 --- a/Tests/RunCMake/VSSolution/MorePre-check.cmake +++ b/Tests/RunCMake/VSSolution/MorePre-check.cmake @@ -1,5 +1,5 @@ parseGlobalSections(pre post MorePre) testGlobalSection(pre TestSec1 Key1=Value1 "Key2=Value with spaces") testGlobalSection(pre TestSec3 Key3=Value1 "Key4=Value with spaces" Key5=ValueWithoutSpaces) -testGlobalSection(post ExtensibilityGlobals) +testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}") testGlobalSection(post ExtensibilityAddIns) diff --git a/Tests/RunCMake/VSSolution/OnePost-check.cmake b/Tests/RunCMake/VSSolution/OnePost-check.cmake index 6af51561b..f7d371260 100644 --- a/Tests/RunCMake/VSSolution/OnePost-check.cmake +++ b/Tests/RunCMake/VSSolution/OnePost-check.cmake @@ -1,4 +1,4 @@ parseGlobalSections(pre post OnePost) testGlobalSection(post TestSec2 Key1=Value1 "Key2=Value with spaces") -testGlobalSection(post ExtensibilityGlobals) +testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}") testGlobalSection(post ExtensibilityAddIns) diff --git a/Tests/RunCMake/VSSolution/OnePre-check.cmake b/Tests/RunCMake/VSSolution/OnePre-check.cmake index 70b18b272..c5db139aa 100644 --- a/Tests/RunCMake/VSSolution/OnePre-check.cmake +++ b/Tests/RunCMake/VSSolution/OnePre-check.cmake @@ -1,4 +1,4 @@ parseGlobalSections(pre post OnePre) testGlobalSection(pre TestSec1 Key1=Value1 "Key2=Value with spaces") -testGlobalSection(post ExtensibilityGlobals) +testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}") testGlobalSection(post ExtensibilityAddIns) diff --git a/Tests/RunCMake/VSSolution/Override1-check.cmake b/Tests/RunCMake/VSSolution/Override1-check.cmake index a19e2e1fe..5905204bd 100644 --- a/Tests/RunCMake/VSSolution/Override1-check.cmake +++ b/Tests/RunCMake/VSSolution/Override1-check.cmake @@ -1,4 +1,4 @@ parseGlobalSections(pre post Override1) testGlobalSection(post TestSec Key2=Value2 Key3=Value3) -testGlobalSection(post ExtensibilityGlobals Key1=Value1) +testGlobalSection(post ExtensibilityGlobals Key1=Value1 "SolutionGuid={00000000-0000-0000-0000-000000000000}") testGlobalSection(post ExtensibilityAddIns) diff --git a/Tests/RunCMake/VSSolution/Override2-check.cmake b/Tests/RunCMake/VSSolution/Override2-check.cmake index d9656e15e..c981ec0ef 100644 --- a/Tests/RunCMake/VSSolution/Override2-check.cmake +++ b/Tests/RunCMake/VSSolution/Override2-check.cmake @@ -1,4 +1,4 @@ parseGlobalSections(pre post Override2) testGlobalSection(pre TestSec Key2=Value2 Key3=Value3) -testGlobalSection(post ExtensibilityGlobals) +testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}") testGlobalSection(post ExtensibilityAddIns Key1=Value1) diff --git a/Tests/RunCMake/VSSolution/Override3-check.cmake b/Tests/RunCMake/VSSolution/Override3-check.cmake new file mode 100644 index 000000000..baee9edc0 --- /dev/null +++ b/Tests/RunCMake/VSSolution/Override3-check.cmake @@ -0,0 +1,3 @@ +parseGlobalSections(pre post Override3) +testGlobalSection(post ExtensibilityGlobals Key1=Value1 "SolutionGuid={custom-guid}") +testGlobalSection(post ExtensibilityAddIns) diff --git a/Tests/RunCMake/VSSolution/Override3.cmake b/Tests/RunCMake/VSSolution/Override3.cmake new file mode 100644 index 000000000..a59ce1904 --- /dev/null +++ b/Tests/RunCMake/VSSolution/Override3.cmake @@ -0,0 +1,4 @@ +set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_ExtensibilityGlobals + Key1=Value1 + SolutionGuid={custom-guid} + ) diff --git a/Tests/RunCMake/VSSolution/PrePost-check.cmake b/Tests/RunCMake/VSSolution/PrePost-check.cmake index 322a68931..957c964cf 100644 --- a/Tests/RunCMake/VSSolution/PrePost-check.cmake +++ b/Tests/RunCMake/VSSolution/PrePost-check.cmake @@ -2,5 +2,5 @@ parseGlobalSections(pre post PrePost) testGlobalSection(post Postsec Key1=Value2) testGlobalSection(pre Presec Key1=Value1 "Key2=Value with some spaces") testGlobalSection(post Emptysec) -testGlobalSection(post ExtensibilityGlobals) +testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}") testGlobalSection(post ExtensibilityAddIns) diff --git a/Tests/RunCMake/VSSolution/RunCMakeTest.cmake b/Tests/RunCMake/VSSolution/RunCMakeTest.cmake index 4ec3e3b37..c25833d95 100644 --- a/Tests/RunCMake/VSSolution/RunCMakeTest.cmake +++ b/Tests/RunCMake/VSSolution/RunCMakeTest.cmake @@ -8,10 +8,11 @@ run_cmake(MorePost) run_cmake(PrePost) run_cmake(Override1) run_cmake(Override2) +run_cmake(Override3) run_cmake(StartupProject) run_cmake(StartupProjectMissing) run_cmake(AddPackageToDefault) -if(RunCMake_GENERATOR MATCHES "Visual Studio ([^7]|[7][0-9])" AND NOT NO_USE_FOLDERS) +if(NOT NO_USE_FOLDERS) run_cmake(StartupProjectUseFolders) endif() diff --git a/Tests/RunCMake/VSSolution/solution_parsing.cmake b/Tests/RunCMake/VSSolution/solution_parsing.cmake index 4e5bb5908..4b2755005 100644 --- a/Tests/RunCMake/VSSolution/solution_parsing.cmake +++ b/Tests/RunCMake/VSSolution/solution_parsing.cmake @@ -44,6 +44,9 @@ macro(parseGlobalSections arg_out_pre arg_out_post testName) endif() string(STRIP "${CMAKE_MATCH_1}" key) string(STRIP "${CMAKE_MATCH_2}" value) + if(key STREQUAL "SolutionGuid" AND value MATCHES "^{[0-9A-F-]+}$") + set(value "{00000000-0000-0000-0000-000000000000}") + endif() list(APPEND ${out_${sectionType}}_${sectionName} "${key}=${value}") endif() endforeach() diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index f51a107b7..5f4bdc30d 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -187,3 +187,19 @@ if(NOT XCODE_VERSION VERSION_LESS 5) unset(RunCMake_TEST_NO_CLEAN) unset(RunCMake_TEST_OPTIONS) endif() + +function(XcodeSchemaGeneration) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeSchemaGeneration-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_OPTIONS "-DCMAKE_XCODE_GENERATE_SCHEME=ON") + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake(XcodeSchemaGeneration) + run_cmake_command(XcodeSchemaGeneration-build xcodebuild -scheme foo build) +endfunction() + +if(NOT XCODE_VERSION VERSION_LESS 7) + XcodeSchemaGeneration() +endif() diff --git a/Tests/RunCMake/XcodeProject/XcodeBundles.cmake b/Tests/RunCMake/XcodeProject/XcodeBundles.cmake index 833eb85b3..0b854d80a 100644 --- a/Tests/RunCMake/XcodeProject/XcodeBundles.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeBundles.cmake @@ -57,6 +57,10 @@ if(NOT TEST_IOS OR NOT XCODE_VERSION VERSION_LESS 6) set_target_properties(SharedFramework PROPERTIES FRAMEWORK TRUE) add_custom_target(SharedFrameworkTest ALL + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" COMMAND ${CMAKE_COMMAND} -E copy "$" "$.old") @@ -70,6 +74,10 @@ if(NOT TEST_IOS OR NOT XCODE_VERSION VERSION_LESS 6) install(TARGETS SharedFrameworkExt FRAMEWORK DESTINATION FooExtension) add_custom_target(SharedFrameworkExtTest ALL + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" COMMAND ${CMAKE_COMMAND} -E copy "$" "$.old") @@ -83,6 +91,10 @@ if(NOT XCODE_VERSION VERSION_LESS 6) set_target_properties(StaticFramework PROPERTIES FRAMEWORK TRUE) add_custom_target(StaticFrameworkTest ALL + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" COMMAND ${CMAKE_COMMAND} -E copy "$" "$.old") @@ -96,6 +108,10 @@ if(NOT XCODE_VERSION VERSION_LESS 6) install(TARGETS StaticFrameworkExt FRAMEWORK DESTINATION StaticFooExtension) add_custom_target(StaticFrameworkExtTest ALL + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" COMMAND ${CMAKE_COMMAND} -E copy "$" "$.old") @@ -109,6 +125,10 @@ if(NOT CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE) set_target_properties(Bundle PROPERTIES BUNDLE TRUE) add_custom_target(BundleTest ALL + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" COMMAND ${CMAKE_COMMAND} -E copy "$" "$.old") @@ -122,6 +142,10 @@ if(NOT CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE) install(TARGETS BundleExt LIBRARY DESTINATION FooExtension) add_custom_target(BundleExtTest ALL + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" + COMMAND ${CMAKE_COMMAND} -E copy + "$" "$.old" COMMAND ${CMAKE_COMMAND} -E copy "$" "$.old") diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake new file mode 100644 index 000000000..2fe5a9f83 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.7) + +project(XcodeSchemaGeneration CXX) + +add_executable(foo main.cpp) diff --git a/Tests/RunCMake/ctest_disabled_test/CMakeLists.txt.in b/Tests/RunCMake/ctest_disabled_test/CMakeLists.txt.in new file mode 100644 index 000000000..d34fcac6e --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/CMakeLists.txt.in @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.7) +project(@CASE_NAME@ NONE) +include(CTest) + +add_test(NAME SuccessfulTest COMMAND "${CMAKE_COMMAND}" --version) +@CASE_CMAKELISTS_SUFFIX_CODE@ diff --git a/Tests/RunCMake/ctest_disabled_test/CTestConfig.cmake.in b/Tests/RunCMake/ctest_disabled_test/CTestConfig.cmake.in new file mode 100644 index 000000000..c0d7e425f --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/CTestConfig.cmake.in @@ -0,0 +1 @@ +set(CTEST_PROJECT_NAME "@CASE_NAME@") diff --git a/Tests/RunCMake/ctest_disabled_test/DisableAllTests-result.txt b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-result.txt new file mode 100644 index 000000000..b57e2deb7 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stderr.txt b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stderr.txt new file mode 100644 index 000000000..eafba1c69 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stderr.txt @@ -0,0 +1 @@ +No tests were found!!! diff --git a/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stdout.txt new file mode 100644 index 000000000..6c824f656 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stdout.txt @@ -0,0 +1,2 @@ + Start 1: SuccessfulTest +1/1 Test #1: SuccessfulTest ...................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec diff --git a/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt new file mode 100644 index 000000000..9449e65b2 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt @@ -0,0 +1,11 @@ + Start 1: SuccessfulTest +1/2 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 2: CleanupTest +2/2 Test #2: CleanupTest ......................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- CleanupTest \(Disabled\) diff --git a/Tests/RunCMake/ctest_disabled_test/DisableFailingTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableFailingTest-stdout.txt new file mode 100644 index 000000000..486722ed9 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableFailingTest-stdout.txt @@ -0,0 +1,9 @@ +50% tests passed, 1 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*3 \- DisabledFailingTest \(Disabled\) ++ +The following tests FAILED: +.*2 \- FailingTest \(Failed\) diff --git a/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-result.txt b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-result.txt new file mode 100644 index 000000000..b57e2deb7 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stderr.txt b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stderr.txt new file mode 100644 index 000000000..83c332b0d --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stderr.txt @@ -0,0 +1 @@ +Unable to find executable: invalidCommand diff --git a/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stdout.txt new file mode 100644 index 000000000..9078aeb70 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stdout.txt @@ -0,0 +1,17 @@ + Start 1: SuccessfulTest +1/3 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 2: DisabledTest +2/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec + Start 3: NotRunTest +.* +3/3 Test #3: NotRunTest .......................\*\*\*\Not Run +[0-9.]+ sec ++ +50% tests passed, 1 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- DisabledTest \(Disabled\) ++ +The following tests FAILED: +.*3 - NotRunTest \(Not Run\) diff --git a/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt new file mode 100644 index 000000000..10d385e2e --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt @@ -0,0 +1,13 @@ + Start 1: SuccessfulTest +1/3 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 2: DisabledTest +2/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec + Start 3: SuccessfulCleanupTest +3/3 Test #3: SuccessfulCleanupTest ............ Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- DisabledTest \(Disabled\) diff --git a/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt new file mode 100644 index 000000000..2dfd10d3d --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt @@ -0,0 +1,13 @@ + Start 2: DisabledTest +1/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec + Start 1: SuccessfulTest +2/3 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 3: SuccessfulCleanupTest +3/3 Test #3: SuccessfulCleanupTest ............ Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- DisabledTest \(Disabled\) diff --git a/Tests/RunCMake/ctest_disabled_test/DisabledTest-result.txt b/Tests/RunCMake/ctest_disabled_test/DisabledTest-result.txt new file mode 100644 index 000000000..b57e2deb7 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisabledTest-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_disabled_test/DisabledTest-stderr.txt b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stderr.txt new file mode 100644 index 000000000..83c332b0d --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stderr.txt @@ -0,0 +1 @@ +Unable to find executable: invalidCommand diff --git a/Tests/RunCMake/ctest_disabled_test/DisabledTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stdout.txt new file mode 100644 index 000000000..9078aeb70 --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stdout.txt @@ -0,0 +1,17 @@ + Start 1: SuccessfulTest +1/3 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 2: DisabledTest +2/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec + Start 3: NotRunTest +.* +3/3 Test #3: NotRunTest .......................\*\*\*\Not Run +[0-9.]+ sec ++ +50% tests passed, 1 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- DisabledTest \(Disabled\) ++ +The following tests FAILED: +.*3 - NotRunTest \(Not Run\) diff --git a/Tests/RunCMake/ctest_disabled_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_disabled_test/RunCMakeTest.cmake new file mode 100644 index 000000000..12541c47e --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/RunCMakeTest.cmake @@ -0,0 +1,89 @@ +include(RunCTest) + +function(run_DisableNotRunTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME DisabledTest COMMAND notACommand --version) +add_test(NAME NotRunTest COMMAND invalidCommand --version) + +set_tests_properties(SuccessfulTest PROPERTIES DISABLED false) +set_tests_properties(DisabledTest PROPERTIES DISABLED true) + ]]) + run_ctest(DisableNotRunTest) +endfunction() +run_DisableNotRunTest() + +function(run_DisableFailingTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +set(someFile "${CMAKE_CURRENT_SOURCE_DIR}/test.cmake") +add_test(NAME FailingTest + COMMAND ${CMAKE_COMMAND} -E compare_files "${someFile}" "${someFile}xxx") +add_test(NAME DisabledFailingTest + COMMAND ${CMAKE_COMMAND} -E compare_files "${someFile}" "${someFile}xxx") + +set_tests_properties(FailingTest PROPERTIES DISABLED false) +set_tests_properties(DisabledFailingTest PROPERTIES DISABLED true) + ]]) + run_ctest(DisableFailingTest) +endfunction() +run_DisableFailingTest() + +function(run_DisableSetupTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME DisabledTest COMMAND "${CMAKE_COMMAND}" --version) +add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version) + +set_tests_properties(DisabledTest PROPERTIES DISABLED true + FIXTURES_SETUP "Foo") +set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo") +set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo") + ]]) +run_ctest(DisableSetupTest) +endfunction() +run_DisableSetupTest() + +function(run_DisableRequiredTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME DisabledTest COMMAND "${CMAKE_COMMAND}" --version) +add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version) + +set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_SETUP "Foo") +set_tests_properties(DisabledTest PROPERTIES DISABLED true + FIXTURES_REQUIRED "Foo") +set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo") + ]]) +run_ctest(DisableRequiredTest) +endfunction() +run_DisableRequiredTest() + +function(run_DisableCleanupTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME CleanupTest COMMAND "${CMAKE_COMMAND}" --version) + +set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo") +set_tests_properties(CleanupTest PROPERTIES DISABLED true + FIXTURES_CLEANUP "Foo") + ]]) +run_ctest(DisableCleanupTest) +endfunction() +run_DisableCleanupTest() + +# Consider a fixture that has a setup test, a cleanup test and a disabled test +# which requires that fixture. Limit the test list with a regular expression +# that matches the disabled test but not the setup or cleanup tests, so the +# initial set of tests to be executed contains just the disabled test. Since +# the only test requiring the fixture is disabled, CTest should not +# automatically add in the setup and cleanup tests for the fixture, since no +# enabled test requires them. +function(run_DisableAllTests) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME SetupTest COMMAND "${CMAKE_COMMAND}" --version) +add_test(NAME CleanupTest COMMAND "${CMAKE_COMMAND}" --version) + +set_tests_properties(SetupTest PROPERTIES FIXTURES_SETUP "Foo") +set_tests_properties(SuccessfulTest PROPERTIES DISABLED true + FIXTURES_REQUIRED "Foo") +set_tests_properties(CleanupTest PROPERTIES FIXTURES_CLEANUP "Foo") + ]]) +run_ctest(DisableAllTests -R Successful) +endfunction() +run_DisableAllTests() diff --git a/Tests/RunCMake/ctest_disabled_test/test.cmake.in b/Tests/RunCMake/ctest_disabled_test/test.cmake.in new file mode 100644 index 000000000..ca23c832f --- /dev/null +++ b/Tests/RunCMake/ctest_disabled_test/test.cmake.in @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.7) + +set(CTEST_SITE "test-site") +set(CTEST_BUILD_NAME "test-build-name") +set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@") +set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build") +set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") + +set(ctest_test_args "@CASE_CTEST_TEST_ARGS@") +ctest_start(Experimental) +ctest_configure() +ctest_build() +ctest_test(${ctest_test_args}) diff --git a/Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in b/Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in index ab50fdd67..5cb0b4ef6 100644 --- a/Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in +++ b/Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.6.2) +cmake_minimum_required (VERSION 3.8.0) project(ctest_fixtures LANGUAGES NONE) include(CTest) diff --git a/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake b/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake index 673cf571f..17542030e 100644 --- a/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake @@ -19,6 +19,41 @@ run_ctest_test(setupFoo INCLUDE setupFoo) run_ctest_test(wontRun INCLUDE wontRun) run_ctest_test(unused INCLUDE Unused) +run_ctest_test(exclude_setup_foo + INCLUDE "one|two" + EXCLUDE_FIXTURE_SETUP "Foo" +) + +run_ctest_test(exclude_setup_bar + INCLUDE "one|two" + EXCLUDE_FIXTURE_SETUP "Bar" +) + +run_ctest_test(exclude_cleanup_foo + INCLUDE "one|two" + EXCLUDE_FIXTURE_CLEANUP "Foo" +) + +run_ctest_test(exclude_cleanup_bar + INCLUDE "one|two" + EXCLUDE_FIXTURE_CLEANUP "Bar" +) + +run_ctest_test(exclude_any_foo + INCLUDE "one|two" + EXCLUDE_FIXTURE "Foo" +) + +run_ctest_test(exclude_any_bar + INCLUDE "one|two" + EXCLUDE_FIXTURE "Bar" +) + +run_ctest_test(exclude_any_foobar + INCLUDE "one|two" + EXCLUDE_FIXTURE "Foo|Bar" +) + #------------------------------------------------------------ # CMake configure will fail due to cyclic test dependencies #------------------------------------------------------------ @@ -35,3 +70,18 @@ set(CASE_CMAKELISTS_CYCLIC_CODE [[ FIXTURES_REQUIRED "Foo") ]]) run_ctest(cyclicCleanup) + +#------------------------------------------------------------ +# Repeat some of the exclusion tests with ctest command line +# options instead of arguments to ctest_test(). This verifies +# that the command line options make it through as well. +#------------------------------------------------------------ +unset(CASE_CMAKELISTS_CYCLIC_CODE) +set(CASE_CTEST_FIXTURES_ARGS "") + +run_ctest(exclude_setup_foo -R "one|two" -FS Foo) +run_ctest(exclude_setup_foo -R "one|two" --fixture-exclude-setup Foo) +run_ctest(exclude_cleanup_foo -R "one|two" -FC Foo) +run_ctest(exclude_cleanup_foo -R "one|two" --fixture-exclude-cleanup Foo) +run_ctest(exclude_any_foo -R "one|two" -FA Foo) +run_ctest(exclude_any_foo -R "one|two" --fixture-exclude-any Foo) diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt new file mode 100644 index 000000000..82663d58a --- /dev/null +++ b/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt @@ -0,0 +1,15 @@ +Test project .*/Tests/RunCMake/ctest_fixtures/exclude_any_bar-build + Start 3: setupFoo +1/5 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec + Start 2: setupBoth +2/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec + Start 1: one +3/5 Test #1: one +\.+ +Passed +[0-9.]+ sec + Start 5: cleanupFoo +4/5 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec + Start 6: two +5/5 Test #6: two +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 5 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt new file mode 100644 index 000000000..8c08d0882 --- /dev/null +++ b/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt @@ -0,0 +1,13 @@ +Test project .*/Tests/RunCMake/ctest_fixtures/exclude_any_foo-build + Start 2: setupBoth +1/4 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec + Start 1: one +2/4 Test #1: one +\.+ +Passed +[0-9.]+ sec + Start 6: two +3/4 Test #6: two +\.+ +Passed +[0-9.]+ sec + Start 7: cleanupBar +4/4 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 4 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt new file mode 100644 index 000000000..876768b70 --- /dev/null +++ b/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt @@ -0,0 +1,9 @@ +Test project .*/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-build + Start 1: one +1/2 Test #1: one +\.+ +Passed +[0-9.]+ sec + Start 6: two +2/2 Test #6: two +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt new file mode 100644 index 000000000..0d27198fa --- /dev/null +++ b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt @@ -0,0 +1,15 @@ +Test project .*/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-build + Start 3: setupFoo +1/5 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec + Start 2: setupBoth +2/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec + Start 1: one +3/5 Test #1: one +\.+ +Passed +[0-9.]+ sec + Start 5: cleanupFoo +4/5 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec + Start 6: two +5/5 Test #6: two +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 5 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt new file mode 100644 index 000000000..5b201a325 --- /dev/null +++ b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt @@ -0,0 +1,15 @@ +Test project .*/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-build + Start 3: setupFoo +1/5 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec + Start 2: setupBoth +2/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec + Start 1: one +3/5 Test #1: one +\.+ +Passed +[0-9.]+ sec + Start 6: two +4/5 Test #6: two +\.+ +Passed +[0-9.]+ sec + Start 7: cleanupBar +5/5 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 5 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt new file mode 100644 index 000000000..5357feffb --- /dev/null +++ b/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt @@ -0,0 +1,17 @@ +Test project .*/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-build + Start 3: setupFoo +1/6 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec + Start 2: setupBoth +2/6 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec + Start 1: one +3/6 Test #1: one +\.+ +Passed +[0-9.]+ sec + Start 5: cleanupFoo +4/6 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec + Start 6: two +5/6 Test #6: two +\.+ +Passed +[0-9.]+ sec + Start 7: cleanupBar +6/6 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 6 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt new file mode 100644 index 000000000..89f7f445a --- /dev/null +++ b/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt @@ -0,0 +1,15 @@ +Test project .*/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-build + Start 2: setupBoth +1/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec + Start 1: one +2/5 Test #1: one +\.+ +Passed +[0-9.]+ sec + Start 5: cleanupFoo +3/5 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec + Start 6: two +4/5 Test #6: two +\.+ +Passed +[0-9.]+ sec + Start 7: cleanupBar +5/5 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 5 ++ +Total Test time \(real\) = +[0-9.]+ sec$ diff --git a/Tests/RunCMake/ctest_fixtures/test.cmake.in b/Tests/RunCMake/ctest_fixtures/test.cmake.in index 43df17227..7067117c1 100644 --- a/Tests/RunCMake/ctest_fixtures/test.cmake.in +++ b/Tests/RunCMake/ctest_fixtures/test.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.6.2) +cmake_minimum_required(VERSION 3.8.0) set(CTEST_SITE "test-site") set(CTEST_BUILD_NAME "test-build-name") diff --git a/Tests/RunCMake/ctest_skipped_test/CMakeLists.txt.in b/Tests/RunCMake/ctest_skipped_test/CMakeLists.txt.in new file mode 100644 index 000000000..cc4b8ed18 --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/CMakeLists.txt.in @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.8) +project(@CASE_NAME@ C) +include(CTest) + +if (WIN32) + set(skip_command "@CMAKE_CURRENT_LIST_DIR@/skip.bat") +else () + set(skip_command "@CMAKE_CURRENT_LIST_DIR@/skip.sh") +endif () + +add_test(NAME SuccessfulTest COMMAND "${CMAKE_COMMAND}" --version) +@CASE_CMAKELISTS_SUFFIX_CODE@ diff --git a/Tests/RunCMake/ctest_skipped_test/CTestConfig.cmake.in b/Tests/RunCMake/ctest_skipped_test/CTestConfig.cmake.in new file mode 100644 index 000000000..c0d7e425f --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/CTestConfig.cmake.in @@ -0,0 +1 @@ +set(CTEST_PROJECT_NAME "@CASE_NAME@") diff --git a/Tests/RunCMake/ctest_skipped_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_skipped_test/RunCMakeTest.cmake new file mode 100644 index 000000000..dcf5cd4e2 --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/RunCMakeTest.cmake @@ -0,0 +1,51 @@ +include(RunCTest) + +function(run_SkipTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME SkipTest COMMAND ${skip_command}) + +set_tests_properties(SkipTest PROPERTIES SKIP_RETURN_CODE 125) + ]]) + run_ctest(SkipTest) +endfunction() +run_SkipTest() + +function(run_SkipSetupTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME SkipTest COMMAND ${skip_command}) +add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version) + +set_tests_properties(SkipTest PROPERTIES SKIP_RETURN_CODE 125 + FIXTURES_SETUP "Foo") +set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo") +set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo") + ]]) + run_ctest(SkipSetupTest) +endfunction() +run_SkipSetupTest() + +function(run_SkipRequiredTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME SkipTest COMMAND ${skip_command}) +add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version) + +set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_SETUP "Foo") +set_tests_properties(SkipTest PROPERTIES SKIP_RETURN_CODE 125 + FIXTURES_REQUIRED "Foo") +set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo") + ]]) + run_ctest(SkipRequiredTest) +endfunction() +run_SkipRequiredTest() + +function(run_SkipCleanupTest) + set(CASE_CMAKELISTS_SUFFIX_CODE [[ +add_test(NAME CleanupTest COMMAND ${skip_command}) + +set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo") +set_tests_properties(CleanupTest PROPERTIES SKIP_RETURN_CODE 125 + FIXTURES_CLEANUP "Foo") + ]]) + run_ctest(SkipCleanupTest) +endfunction() +run_SkipCleanupTest() diff --git a/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt new file mode 100644 index 000000000..3b14b7a1f --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt @@ -0,0 +1,11 @@ + Start 1: SuccessfulTest +1/2 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 2: CleanupTest +2/2 Test #2: CleanupTest ......................\*\*\*\Skipped +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- CleanupTest \(Skipped\) diff --git a/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt new file mode 100644 index 000000000..8ecc6e3c9 --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt @@ -0,0 +1,13 @@ + Start 1: SuccessfulTest +1/3 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 2: SkipTest +2/3 Test #2: SkipTest .........................\*\*\*\Skipped +[0-9.]+ sec + Start 3: SuccessfulCleanupTest +3/3 Test #3: SuccessfulCleanupTest ............ Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 3 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- SkipTest \(Skipped\) diff --git a/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt new file mode 100644 index 000000000..fe9bf34f8 --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt @@ -0,0 +1,13 @@ + Start 2: SkipTest +1/3 Test #2: SkipTest .........................\*\*\*\Skipped +[0-9.]+ sec + Start 1: SuccessfulTest +2/3 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 3: SuccessfulCleanupTest +3/3 Test #3: SuccessfulCleanupTest ............ Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 3 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- SkipTest \(Skipped\) diff --git a/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt new file mode 100644 index 000000000..52e7a0b30 --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt @@ -0,0 +1,11 @@ + Start 1: SuccessfulTest +1/2 Test #1: SuccessfulTest ................... Passed +[0-9.]+ sec + Start 2: SkipTest +2/2 Test #2: SkipTest .........................\*\*\*\Skipped +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 2 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests did not run: +.*2 \- SkipTest \(Skipped\) diff --git a/Tests/RunCMake/ctest_skipped_test/skip.bat b/Tests/RunCMake/ctest_skipped_test/skip.bat new file mode 100755 index 000000000..80e1290df --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/skip.bat @@ -0,0 +1 @@ +EXIT 125 diff --git a/Tests/RunCMake/ctest_skipped_test/skip.sh b/Tests/RunCMake/ctest_skipped_test/skip.sh new file mode 100755 index 000000000..f9c4603cc --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/skip.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 125 diff --git a/Tests/RunCMake/ctest_skipped_test/test.cmake.in b/Tests/RunCMake/ctest_skipped_test/test.cmake.in new file mode 100644 index 000000000..ca23c832f --- /dev/null +++ b/Tests/RunCMake/ctest_skipped_test/test.cmake.in @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.7) + +set(CTEST_SITE "test-site") +set(CTEST_BUILD_NAME "test-build-name") +set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@") +set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build") +set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") + +set(ctest_test_args "@CASE_CTEST_TEST_ARGS@") +ctest_start(Experimental) +ctest_configure() +ctest_build() +ctest_test(${ctest_test_args}) diff --git a/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-result.txt b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-result.txt new file mode 100644 index 000000000..b57e2deb7 --- /dev/null +++ b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stderr.txt b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stderr.txt new file mode 100644 index 000000000..4825d7a8e --- /dev/null +++ b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stderr.txt @@ -0,0 +1,3 @@ + *Error when uploading file: .*/Configure.xml + *Error message was: ([Cc]ould *n.t resolve host:? '?-no-site-'?.*|The requested URL returned error:.*) + *Problems when submitting via HTTP diff --git a/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stdout.txt b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stdout.txt new file mode 100644 index 000000000..3973872de --- /dev/null +++ b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stdout.txt @@ -0,0 +1 @@ +Add HTTP Header: "Authorization: Bearer asdf" diff --git a/Tests/RunCMake/ctest_submit/CDashUploadHeaders-result.txt b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-result.txt new file mode 100644 index 000000000..b57e2deb7 --- /dev/null +++ b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stderr.txt b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stderr.txt new file mode 100644 index 000000000..706e1f53c --- /dev/null +++ b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stderr.txt @@ -0,0 +1 @@ +Error in HttpRequest diff --git a/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stdout.txt b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stdout.txt new file mode 100644 index 000000000..3973872de --- /dev/null +++ b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stdout.txt @@ -0,0 +1 @@ +Add HTTP Header: "Authorization: Bearer asdf" diff --git a/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake b/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake index e104f8a47..b5d90d28c 100644 --- a/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake @@ -25,6 +25,8 @@ run_ctest_submit(CDashUploadNone CDASH_UPLOAD) run_ctest_submit(CDashUploadMissingFile CDASH_UPLOAD bad-upload) run_ctest_submit(CDashUploadRetry CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo RETRY_COUNT 2 RETRY_DELAY 1 INTERNAL_TEST_CHECKSUM) run_ctest_submit(CDashSubmitQuiet QUIET) +run_ctest_submit(CDashSubmitHeaders HTTPHEADER "Authorization: Bearer asdf") +run_ctest_submit(CDashUploadHeaders CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo HTTPHEADER "Authorization: Bearer asdf") function(run_ctest_CDashUploadFTP) set(CASE_DROP_METHOD ftp) diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake index ca72692c2..a91b217c2 100644 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") + set(slash /) +endif() file(DOWNLOAD - "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" ${CMAKE_CURRENT_BINARY_DIR}/hash-mismatch.txt EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567 STATUS status diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake index 2e3fbe1dd..2fa5482d2 100644 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") + set(slash /) +endif() file(DOWNLOAD - "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt new file mode 100644 index 000000000..9d5f876a5 --- /dev/null +++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt @@ -0,0 +1,15 @@ +^CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\): + file option FILES_FROM_DIR requires all files to be specified as relative + paths\. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ +CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\): + file INSTALL option RENAME may not be combined with FILES_FROM_DIR\. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ +CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\): + file option FILES_FROM_DIR may not appear after PATTERN or REGEX\. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake new file mode 100644 index 000000000..807b704e0 --- /dev/null +++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake @@ -0,0 +1,5 @@ +set(src ${CMAKE_CURRENT_SOURCE_DIR}/from) +set(dst ${CMAKE_CURRENT_BINARY_DIR}/from) +file(INSTALL FILES ${src}/a.txt FILES_FROM_DIR ${src} DESTINATION ${dst}) +file(INSTALL FILES a.txt FILES_FROM_DIR ${src} DESTINATION ${dst} RENAME b.txt) +file(INSTALL FILES a.txt DESTINATION ${dst} PATTERN *.txt FILES_FROM_DIR) diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt new file mode 100644 index 000000000..1c3c69303 --- /dev/null +++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt @@ -0,0 +1,8 @@ +-- Before Installing +-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt +-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt +-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt +-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt +-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt +-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt +-- After Installing diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake new file mode 100644 index 000000000..24e5282f3 --- /dev/null +++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake @@ -0,0 +1,7 @@ +set(src ${CMAKE_CURRENT_SOURCE_DIR}/from) +set(dst ${CMAKE_CURRENT_BINARY_DIR}/from) +file(REMOVE RECURSE ${dst}) +message(STATUS "Before Installing") +file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR ${src} DESTINATION ${dst}) +file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR from DESTINATION ${dst}) +message(STATUS "After Installing") diff --git a/Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt b/Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt new file mode 100644 index 000000000..9fb8e10b7 --- /dev/null +++ b/Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt @@ -0,0 +1,3 @@ +-- Before Installing +-- Installing: .*/Tests/RunCMake/file/INSTALL-SYMLINK-build/dst/current_dir_symlink +-- After Installing diff --git a/Tests/RunCMake/file/INSTALL-SYMLINK.cmake b/Tests/RunCMake/file/INSTALL-SYMLINK.cmake new file mode 100644 index 000000000..5a4284a63 --- /dev/null +++ b/Tests/RunCMake/file/INSTALL-SYMLINK.cmake @@ -0,0 +1,13 @@ +set(src "${CMAKE_CURRENT_BINARY_DIR}/src") +set(dst "${CMAKE_CURRENT_BINARY_DIR}/dst") +file(REMOVE RECURSE "${src}") +file(REMOVE RECURSE "${dst}") + +file(MAKE_DIRECTORY "${src}") +execute_process(COMMAND + ${CMAKE_COMMAND} -E create_symlink source "${src}/current_dir_symlink") + +message(STATUS "Before Installing") +file(INSTALL FILES "${src}/current_dir_symlink" + DESTINATION ${dst} TYPE DIRECTORY) +message(STATUS "After Installing") diff --git a/Tests/RunCMake/file/READ_ELF-result.txt b/Tests/RunCMake/file/READ_ELF-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/file/READ_ELF-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/READ_ELF-stderr.txt b/Tests/RunCMake/file/READ_ELF-stderr.txt new file mode 100644 index 000000000..7b328049b --- /dev/null +++ b/Tests/RunCMake/file/READ_ELF-stderr.txt @@ -0,0 +1,2 @@ +.*file READ_ELF must be called with at least three additional arguments\. +.*file READ_ELF given FILE "XXX" that does not exist\. diff --git a/Tests/RunCMake/file/READ_ELF.cmake b/Tests/RunCMake/file/READ_ELF.cmake new file mode 100644 index 000000000..cd02c9b62 --- /dev/null +++ b/Tests/RunCMake/file/READ_ELF.cmake @@ -0,0 +1,2 @@ +file(READ_ELF XXX) +file(READ_ELF XXX RPATH YYY) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 749754413..26051b4d7 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -8,6 +8,8 @@ run_cmake(UPLOAD-unused-argument) run_cmake(UPLOAD-httpheader-not-set) run_cmake(UPLOAD-pass-not-set) run_cmake(INSTALL-DIRECTORY) +run_cmake(INSTALL-FILES_FROM_DIR) +run_cmake(INSTALL-FILES_FROM_DIR-bad) run_cmake(INSTALL-MESSAGE-bad) run_cmake(FileOpenFailRead) run_cmake(LOCK) @@ -25,6 +27,7 @@ run_cmake(LOCK-error-no-timeout) run_cmake(LOCK-error-timeout) run_cmake(LOCK-error-unknown-option) run_cmake(LOCK-lowercase) +run_cmake(READ_ELF) run_cmake(GLOB) run_cmake(GLOB_RECURSE) # test is valid both for GLOB and GLOB_RECURSE @@ -35,4 +38,5 @@ run_cmake(GLOB-noexp-LIST_DIRECTORIES) if(NOT WIN32 OR CYGWIN) run_cmake(GLOB_RECURSE-cyclic-recursion) + run_cmake(INSTALL-SYMLINK) endif() diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake index 94ac9acc7..92c878c8e 100644 --- a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_BINARY_DIR}" MATCHES "^/") + set(slash /) +endif() file(UPLOAD "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-unused-argument.txt" - "file://${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" + "file://${slash}${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) diff --git a/Tests/RunCMake/file/from/a.txt b/Tests/RunCMake/file/from/a.txt new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/file/from/a/b.txt b/Tests/RunCMake/file/from/a/b.txt new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/file/from/a/b/c.txt b/Tests/RunCMake/file/from/a/b/c.txt new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_dependency/CMakeLists.txt b/Tests/RunCMake/find_dependency/CMakeLists.txt index 04d09f2ad..12cd3c775 100644 --- a/Tests/RunCMake/find_dependency/CMakeLists.txt +++ b/Tests/RunCMake/find_dependency/CMakeLists.txt @@ -1,4 +1,3 @@ cmake_minimum_required(VERSION 2.8.4) project(${RunCMake_TEST} NONE) -set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}") include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/find_dependency/EXACT-no-version-stderr.txt b/Tests/RunCMake/find_dependency/EXACT-no-version-stderr.txt deleted file mode 100644 index 348f8bb25..000000000 --- a/Tests/RunCMake/find_dependency/EXACT-no-version-stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\): - Invalid arguments to find_dependency. EXACT may only be specified if a - VERSION is specified -Call Stack \(most recent call first\): - EXACT-no-version.cmake:4 \(find_dependency\) - CMakeLists.txt:4 \(include\) diff --git a/Tests/RunCMake/find_dependency/EXACT-no-version.cmake b/Tests/RunCMake/find_dependency/EXACT-no-version.cmake deleted file mode 100644 index b05665b7e..000000000 --- a/Tests/RunCMake/find_dependency/EXACT-no-version.cmake +++ /dev/null @@ -1,4 +0,0 @@ - -include(CMakeFindDependencyMacro) - -find_dependency(Pack1 EXACT) diff --git a/Tests/RunCMake/find_dependency/RunCMakeTest.cmake b/Tests/RunCMake/find_dependency/RunCMakeTest.cmake index 9403136b7..a72d18962 100644 --- a/Tests/RunCMake/find_dependency/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_dependency/RunCMakeTest.cmake @@ -1,7 +1,10 @@ include(RunCMake) -run_cmake(EXACT-no-version) -run_cmake(empty-version) -run_cmake(empty-arg-3) -run_cmake(invalid-arg-3) -run_cmake(extra-args) +# Success tests +run_cmake(realistic) +run_cmake(basic) + +# Failure tests +run_cmake(invalid-arg) +run_cmake(bad-version-fuzzy) +run_cmake(bad-version-exact) diff --git a/Tests/RunCMake/find_dependency/bad-version-exact-result.txt b/Tests/RunCMake/find_dependency/bad-version-exact-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/find_dependency/bad-version-exact-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_dependency/bad-version-exact-stderr.txt b/Tests/RunCMake/find_dependency/bad-version-exact-stderr.txt new file mode 100644 index 000000000..0929f840d --- /dev/null +++ b/Tests/RunCMake/find_dependency/bad-version-exact-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at .*/Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(find_package\): + Could not find a configuration file for package "Pack1" that exactly + matches requested version "1.1". + + The following configuration files were considered but not accepted: + + .*/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake, version: 1.3 + +Call Stack \(most recent call first\): + bad-version-exact.cmake:5 \(find_dependency\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/find_dependency/bad-version-exact.cmake b/Tests/RunCMake/find_dependency/bad-version-exact.cmake new file mode 100644 index 000000000..c4ca5e29d --- /dev/null +++ b/Tests/RunCMake/find_dependency/bad-version-exact.cmake @@ -0,0 +1,5 @@ +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + +include(CMakeFindDependencyMacro) + +find_dependency(Pack1 1.1 EXACT REQUIRED) diff --git a/Tests/RunCMake/find_dependency/bad-version-fuzzy-result.txt b/Tests/RunCMake/find_dependency/bad-version-fuzzy-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/find_dependency/bad-version-fuzzy-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_dependency/bad-version-fuzzy-stderr.txt b/Tests/RunCMake/find_dependency/bad-version-fuzzy-stderr.txt new file mode 100644 index 000000000..c63256f44 --- /dev/null +++ b/Tests/RunCMake/find_dependency/bad-version-fuzzy-stderr.txt @@ -0,0 +1,11 @@ +CMake Error at .*/Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(find_package\): + Could not find a configuration file for package "Pack1" that is compatible + with requested version "1.4". + + The following configuration files were considered but not accepted: + + .*/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake, version: 1.3 + +Call Stack \(most recent call first\): + bad-version-fuzzy.cmake:5 \(find_dependency\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/find_dependency/bad-version-fuzzy.cmake b/Tests/RunCMake/find_dependency/bad-version-fuzzy.cmake new file mode 100644 index 000000000..c7cf4eef4 --- /dev/null +++ b/Tests/RunCMake/find_dependency/bad-version-fuzzy.cmake @@ -0,0 +1,5 @@ +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + +include(CMakeFindDependencyMacro) + +find_dependency(Pack1 1.4 REQUIRED) diff --git a/Tests/RunCMake/find_dependency/basic.cmake b/Tests/RunCMake/find_dependency/basic.cmake new file mode 100644 index 000000000..c7795f217 --- /dev/null +++ b/Tests/RunCMake/find_dependency/basic.cmake @@ -0,0 +1,5 @@ +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + +include(CMakeFindDependencyMacro) + +find_dependency(Pack1 1.1) diff --git a/Tests/RunCMake/find_dependency/empty-arg-3-stderr.txt b/Tests/RunCMake/find_dependency/empty-arg-3-stderr.txt deleted file mode 100644 index bf9b02b43..000000000 --- a/Tests/RunCMake/find_dependency/empty-arg-3-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\): - Invalid arguments to find_dependency -Call Stack \(most recent call first\): - empty-arg-3.cmake:4 \(find_dependency\) - CMakeLists.txt:4 \(include\) diff --git a/Tests/RunCMake/find_dependency/empty-arg-3.cmake b/Tests/RunCMake/find_dependency/empty-arg-3.cmake deleted file mode 100644 index b08200a5a..000000000 --- a/Tests/RunCMake/find_dependency/empty-arg-3.cmake +++ /dev/null @@ -1,4 +0,0 @@ - -include(CMakeFindDependencyMacro) - -find_dependency(Pack1 1.2 "") diff --git a/Tests/RunCMake/find_dependency/empty-version-stderr.txt b/Tests/RunCMake/find_dependency/empty-version-stderr.txt deleted file mode 100644 index b5e9f4643..000000000 --- a/Tests/RunCMake/find_dependency/empty-version-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -CMake Error at .*/Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\): - Invalid arguments to find_dependency. VERSION is empty -Call Stack \(most recent call first\): - empty-version.cmake:4 \(find_dependency\) - CMakeLists.txt:4 \(include\) diff --git a/Tests/RunCMake/find_dependency/empty-version.cmake b/Tests/RunCMake/find_dependency/empty-version.cmake deleted file mode 100644 index e6f17cd13..000000000 --- a/Tests/RunCMake/find_dependency/empty-version.cmake +++ /dev/null @@ -1,4 +0,0 @@ - -include(CMakeFindDependencyMacro) - -find_dependency(Pack1 "") diff --git a/Tests/RunCMake/find_dependency/extra-args-stderr.txt b/Tests/RunCMake/find_dependency/extra-args-stderr.txt deleted file mode 100644 index 83a7f0266..000000000 --- a/Tests/RunCMake/find_dependency/extra-args-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\): - Invalid arguments to find_dependency -Call Stack \(most recent call first\): - extra-args.cmake:4 \(find_dependency\) - CMakeLists.txt:4 \(include\) diff --git a/Tests/RunCMake/find_dependency/extra-args.cmake b/Tests/RunCMake/find_dependency/extra-args.cmake deleted file mode 100644 index 209645a5d..000000000 --- a/Tests/RunCMake/find_dependency/extra-args.cmake +++ /dev/null @@ -1,4 +0,0 @@ - -include(CMakeFindDependencyMacro) - -find_dependency(Pack1 1.2 EXACT PATHS "${CMAKE_BINARY_DIR}") diff --git a/Tests/RunCMake/find_dependency/invalid-arg-3-stderr.txt b/Tests/RunCMake/find_dependency/invalid-arg-3-stderr.txt deleted file mode 100644 index fee8d5db7..000000000 --- a/Tests/RunCMake/find_dependency/invalid-arg-3-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\): - Invalid arguments to find_dependency -Call Stack \(most recent call first\): - invalid-arg-3.cmake:4 \(find_dependency\) - CMakeLists.txt:4 \(include\) diff --git a/Tests/RunCMake/find_dependency/invalid-arg-result.txt b/Tests/RunCMake/find_dependency/invalid-arg-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/find_dependency/invalid-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_dependency/invalid-arg-stderr.txt b/Tests/RunCMake/find_dependency/invalid-arg-stderr.txt new file mode 100644 index 000000000..16077b291 --- /dev/null +++ b/Tests/RunCMake/find_dependency/invalid-arg-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(find_package\): + find_package called with invalid argument "EXACTYPO" +Call Stack \(most recent call first\): + invalid-arg.cmake:5 \(find_dependency\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/find_dependency/invalid-arg-3.cmake b/Tests/RunCMake/find_dependency/invalid-arg.cmake similarity index 57% rename from Tests/RunCMake/find_dependency/invalid-arg-3.cmake rename to Tests/RunCMake/find_dependency/invalid-arg.cmake index 40ede07f4..daaf5694a 100644 --- a/Tests/RunCMake/find_dependency/invalid-arg-3.cmake +++ b/Tests/RunCMake/find_dependency/invalid-arg.cmake @@ -1,3 +1,4 @@ +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}") include(CMakeFindDependencyMacro) diff --git a/Tests/RunCMake/find_dependency/realistic.cmake b/Tests/RunCMake/find_dependency/realistic.cmake new file mode 100644 index 000000000..e633a312b --- /dev/null +++ b/Tests/RunCMake/find_dependency/realistic.cmake @@ -0,0 +1,3 @@ +set(Pack2_DIR "${CMAKE_CURRENT_SOURCE_DIR}/share/cmake/Pack2") + +find_package(Pack2 1.2 REQUIRED) diff --git a/Tests/RunCMake/find_dependency/Pack1/Pack1Config.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake similarity index 100% rename from Tests/RunCMake/find_dependency/Pack1/Pack1Config.cmake rename to Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake diff --git a/Tests/RunCMake/find_dependency/Pack1/Pack1ConfigVersion.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1ConfigVersion.cmake similarity index 100% rename from Tests/RunCMake/find_dependency/Pack1/Pack1ConfigVersion.cmake rename to Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1ConfigVersion.cmake diff --git a/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2Config.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2Config.cmake new file mode 100644 index 000000000..7e8a60ba0 --- /dev/null +++ b/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2Config.cmake @@ -0,0 +1,6 @@ +include(CMakeFindDependencyMacro) + +find_dependency(Pack1 PATHS ${CMAKE_CURRENT_LIST_DIR}/..) + +add_library(Pack2::Lib INTERFACE IMPORTED) +set_target_properties(Pack2::Lib PROPERTIES INTERFACE_LINK_LIBRARIES Pack1::Lib) diff --git a/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2ConfigVersion.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2ConfigVersion.cmake new file mode 100644 index 000000000..dfb7b6c84 --- /dev/null +++ b/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2ConfigVersion.cmake @@ -0,0 +1,11 @@ + +set(PACKAGE_VERSION "1.3") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/Tests/RunCMake/find_package/MissingConfig-stderr.txt b/Tests/RunCMake/find_package/MissingConfig-stderr.txt index 1eae0bb0b..33ff5452e 100644 --- a/Tests/RunCMake/find_package/MissingConfig-stderr.txt +++ b/Tests/RunCMake/find_package/MissingConfig-stderr.txt @@ -1,18 +1,3 @@ -CMake Warning at MissingConfig.cmake:1 \(find_package\): - Could not find a package configuration file provided by "NotHere" with any - of the following names: - - NotHereConfig.cmake - nothere-config.cmake - - Add the installation prefix of "NotHere" to CMAKE_PREFIX_PATH or set - "NotHere_DIR" to a directory containing one of the above files. If - "NotHere" provides a separate development package or SDK, be sure it has - been installed. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) - - CMake Warning at MissingConfig.cmake:2 \(message\): This warning must be reachable. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/find_package/MissingConfig-stdout.txt b/Tests/RunCMake/find_package/MissingConfig-stdout.txt new file mode 100644 index 000000000..7af632b08 --- /dev/null +++ b/Tests/RunCMake/find_package/MissingConfig-stdout.txt @@ -0,0 +1 @@ +-- Could NOT find NotHere \(missing: NotHere_DIR\) diff --git a/Tests/RunCMake/find_package/MissingConfigNormal-stdout.txt b/Tests/RunCMake/find_package/MissingConfigNormal-stdout.txt new file mode 100644 index 000000000..7af632b08 --- /dev/null +++ b/Tests/RunCMake/find_package/MissingConfigNormal-stdout.txt @@ -0,0 +1 @@ +-- Could NOT find NotHere \(missing: NotHere_DIR\) diff --git a/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt b/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt deleted file mode 100644 index 10e71faa3..000000000 --- a/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt +++ /dev/null @@ -1,10 +0,0 @@ -CMake Warning at MissingConfigOneName.cmake:1 \(find_package\): - Could not find a package configuration file named "NotHereConfig.cmake" - provided by package "NotHere". - - Add the installation prefix of "NotHere" to CMAKE_PREFIX_PATH or set - "NotHere_DIR" to a directory containing one of the above files. If - "NotHere" provides a separate development package or SDK, be sure it has - been installed. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/find_package/MissingConfigOneName-stdout.txt b/Tests/RunCMake/find_package/MissingConfigOneName-stdout.txt new file mode 100644 index 000000000..7af632b08 --- /dev/null +++ b/Tests/RunCMake/find_package/MissingConfigOneName-stdout.txt @@ -0,0 +1 @@ +-- Could NOT find NotHere \(missing: NotHere_DIR\) diff --git a/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt b/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt deleted file mode 100644 index 2f5086ea8..000000000 --- a/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt +++ /dev/null @@ -1,13 +0,0 @@ -CMake Warning at MissingConfigVersion.cmake:1 \(find_package\): - Could not find a package configuration file provided by "NotHere" - \(requested version 1\.2\) with any of the following names: - - NotHereConfig.cmake - nothere-config.cmake - - Add the installation prefix of "NotHere" to CMAKE_PREFIX_PATH or set - "NotHere_DIR" to a directory containing one of the above files. If - "NotHere" provides a separate development package or SDK, be sure it has - been installed. -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/find_package/MissingConfigVersion-stdout.txt b/Tests/RunCMake/find_package/MissingConfigVersion-stdout.txt new file mode 100644 index 000000000..7af632b08 --- /dev/null +++ b/Tests/RunCMake/find_package/MissingConfigVersion-stdout.txt @@ -0,0 +1 @@ +-- Could NOT find NotHere \(missing: NotHere_DIR\) diff --git a/Tests/RunCMake/find_package/PackageRoot-stderr.txt b/Tests/RunCMake/find_package/PackageRoot-stderr.txt new file mode 100644 index 000000000..409fa899e --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot-stderr.txt @@ -0,0 +1,383 @@ +Foo_ROOT : +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND + +Foo_ROOT : +ENV{Foo_ROOT} : +Bar_ROOT : +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND +BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND +BAR_TEST_FILE_BAR :BAR_TEST_FILE_BAR-NOTFOUND +BAR_TEST_FILE_ZOT :BAR_TEST_FILE_ZOT-NOTFOUND +BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND +BAR_TEST_PATH_BAR :BAR_TEST_PATH_BAR-NOTFOUND +BAR_TEST_PATH_ZOT :BAR_TEST_PATH_ZOT-NOTFOUND +BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND +BAR_TEST_PROG_BAR :BAR_TEST_PROG_BAR-NOTFOUND + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_ROOT : +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT : +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/env_root/bin/bar.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT : +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +Foo_ROOT : +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND + +Foo_ROOT : +ENV{Foo_ROOT} : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND +BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +Foo_ROOT : +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND + +Foo_ROOT : +ENV{Foo_ROOT} : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND +BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +Foo_ROOT : +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND + +Foo_ROOT : +ENV{Foo_ROOT} : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND +BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe + +Foo_ROOT : +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe + +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe diff --git a/Tests/RunCMake/find_package/PackageRoot.cmake b/Tests/RunCMake/find_package/PackageRoot.cmake new file mode 100644 index 000000000..421c24339 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot.cmake @@ -0,0 +1,147 @@ +cmake_policy(SET CMP0057 NEW) +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) +set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) + +macro(CleanUpPackageRootTest) + unset(Foo_ROOT) + unset(ENV{Foo_ROOT}) + unset(Bar_ROOT) + unset(ENV{Bar_ROOT}) + unset(FOO_TEST_FILE_FOO) + unset(FOO_TEST_PATH_FOO) + unset(FOO_TEST_PROG_FOO) + unset(BAR_TEST_FILE_FOO) + unset(BAR_TEST_FILE_BAR) + unset(BAR_TEST_PATH_FOO) + unset(BAR_TEST_PATH_BAR) + unset(BAR_TEST_PROG_FOO) + unset(BAR_TEST_PROG_BAR) + unset(FOO_TEST_FILE_FOO CACHE) + unset(FOO_TEST_PATH_FOO CACHE) + unset(FOO_TEST_PROG_FOO CACHE) + unset(BAR_TEST_FILE_FOO CACHE) + unset(BAR_TEST_FILE_BAR CACHE) + unset(BAR_TEST_PATH_FOO CACHE) + unset(BAR_TEST_PATH_BAR CACHE) + unset(BAR_TEST_PROG_FOO CACHE) + unset(BAR_TEST_PROG_BAR CACHE) +endmacro() + +macro(RunPackageRootTest) + set(orig_foo_cmake_root ${Foo_ROOT}) + set(orig_foo_env_root $ENV{Foo_ROOT}) + set(orig_bar_cmake_root ${Bar_ROOT}) + set(orig_bar_env_root $ENV{Bar_ROOT}) + + find_package(Foo) + message("Foo_ROOT :${Foo_ROOT}") + message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}") + message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}") + message("FOO_TEST_FILE_ZOT :${FOO_TEST_FILE_ZOT}") + message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}") + message("FOO_TEST_PATH_ZOT :${FOO_TEST_PATH_ZOT}") + message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}") + CleanUpPackageRootTest() + message("") + + set(Foo_ROOT ${orig_foo_cmake_root}) + set(ENV{Foo_ROOT} ${orig_foo_env_root}) + set(Bar_ROOT ${orig_bar_cmake_root}) + set(ENV{Bar_ROOT} ${orig_bar_env_root}) + + find_package(Foo COMPONENTS Bar) + message("Foo_ROOT :${Foo_ROOT}") + message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}") + message("Bar_ROOT :${Bar_ROOT}") + message("ENV{Bar_ROOT} :$ENV{Bar_ROOT}") + message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}") + message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}") + message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}") + message("BAR_TEST_FILE_FOO :${BAR_TEST_FILE_FOO}") + message("BAR_TEST_FILE_BAR :${BAR_TEST_FILE_BAR}") + message("BAR_TEST_FILE_ZOT :${BAR_TEST_FILE_ZOT}") + message("BAR_TEST_PATH_FOO :${BAR_TEST_PATH_FOO}") + message("BAR_TEST_PATH_BAR :${BAR_TEST_PATH_BAR}") + message("BAR_TEST_PATH_ZOT :${BAR_TEST_PATH_ZOT}") + message("BAR_TEST_PROG_FOO :${BAR_TEST_PROG_FOO}") + message("BAR_TEST_PROG_BAR :${BAR_TEST_PROG_BAR}") + CleanUpPackageRootTest() + message("") + + unset(orig_foo_cmake_root) + unset(orig_foo_env_root) + unset(orig_bar_cmake_root) + unset(orig_bar_env_root) +endmacro() + +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +RunPackageRootTest() + +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +RunPackageRootTest() + +## + +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +## + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +## + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +## + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() diff --git a/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake b/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake new file mode 100644 index 000000000..72774a715 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake @@ -0,0 +1,8 @@ +find_file(BAR_TEST_FILE_FOO foo.h) +find_file(BAR_TEST_FILE_BAR bar.h) +find_file(BAR_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot) +find_path(BAR_TEST_PATH_FOO foo.h) +find_path(BAR_TEST_PATH_BAR bar.h) +find_path(BAR_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot) +find_program(BAR_TEST_PROG_FOO foo.exe) +find_program(BAR_TEST_PROG_BAR bar.exe) diff --git a/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake b/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake new file mode 100644 index 000000000..e160a1d68 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake @@ -0,0 +1,9 @@ +find_file(FOO_TEST_FILE_FOO foo.h) +find_file(FOO_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot) +find_path(FOO_TEST_PATH_FOO foo.h) +find_path(FOO_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot) +find_program(FOO_TEST_PROG_FOO foo.exe) + +if ("Bar" IN_LIST Foo_FIND_COMPONENTS) + find_package(Bar) +endif () diff --git a/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/bin/bar.exe b/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/bin/bar.exe new file mode 100755 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/bar.h b/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/bar.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/zot/zot.h b/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/zot/zot.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/bar/env_root/bin/bar.exe b/Tests/RunCMake/find_package/PackageRoot/bar/env_root/bin/bar.exe new file mode 100755 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/bar.h b/Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/bar.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/zot/zot.h b/Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/zot/zot.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/bar.exe b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/bar.exe new file mode 100755 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/foo.exe b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/foo.exe new file mode 100755 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/bar.h b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/bar.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/foo.h b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/foo.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/zot/zot.h b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/zot/zot.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/bar.exe b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/bar.exe new file mode 100755 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/foo.exe b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/foo.exe new file mode 100755 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/bar.h b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/bar.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/foo.h b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/foo.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/zot/zot.h b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/zot/zot.h new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index 81b29068c..7875db6f6 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -13,6 +13,9 @@ run_cmake(MissingConfigOneName) run_cmake(MissingConfigRequired) run_cmake(MissingConfigVersion) run_cmake(MixedModeOptions) +run_cmake(PackageRoot) run_cmake(PolicyPush) run_cmake(PolicyPop) run_cmake(SetFoundFALSE) +run_cmake(WrongVersion) +run_cmake(WrongVersionConfig) diff --git a/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfig.cmake b/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfig.cmake new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfigVersion.cmake b/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfigVersion.cmake new file mode 100644 index 000000000..2dbcfb265 --- /dev/null +++ b/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfigVersion.cmake @@ -0,0 +1,4 @@ +set(PACKAGE_VERSION 1) +if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 1) + set(PACKAGE_VERSION_COMPATIBLE 1) +endif() diff --git a/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfig.cmake b/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfig.cmake new file mode 100644 index 000000000..e69de29bb diff --git a/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfigVersion.cmake b/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfigVersion.cmake new file mode 100644 index 000000000..7eb833297 --- /dev/null +++ b/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfigVersion.cmake @@ -0,0 +1,4 @@ +set(PACKAGE_VERSION 2) +if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 2) + set(PACKAGE_VERSION_COMPATIBLE 1) +endif() diff --git a/Tests/RunCMake/find_package/WrongVersion-stderr.txt b/Tests/RunCMake/find_package/WrongVersion-stderr.txt new file mode 100644 index 000000000..ae9fc4aba --- /dev/null +++ b/Tests/RunCMake/find_package/WrongVersion-stderr.txt @@ -0,0 +1,11 @@ +^CMake Warning at WrongVersion.cmake:[0-9]+ \(find_package\): + Could not find a configuration file for package "VersionedA" that is + compatible with requested version "3". + + The following configuration files were considered but not accepted: + + .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12] + .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12] + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/find_package/WrongVersion.cmake b/Tests/RunCMake/find_package/WrongVersion.cmake new file mode 100644 index 000000000..5bc711fb4 --- /dev/null +++ b/Tests/RunCMake/find_package/WrongVersion.cmake @@ -0,0 +1,2 @@ +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +find_package(VersionedA 3) diff --git a/Tests/RunCMake/find_package/WrongVersionConfig-stderr.txt b/Tests/RunCMake/find_package/WrongVersionConfig-stderr.txt new file mode 100644 index 000000000..1b84233c3 --- /dev/null +++ b/Tests/RunCMake/find_package/WrongVersionConfig-stderr.txt @@ -0,0 +1,11 @@ +^CMake Warning at WrongVersionConfig.cmake:[0-9]+ \(find_package\): + Could not find a configuration file for package "VersionedA" that is + compatible with requested version "3". + + The following configuration files were considered but not accepted: + + .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12] + .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12] + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/find_package/WrongVersionConfig.cmake b/Tests/RunCMake/find_package/WrongVersionConfig.cmake new file mode 100644 index 000000000..5bc711fb4 --- /dev/null +++ b/Tests/RunCMake/find_package/WrongVersionConfig.cmake @@ -0,0 +1,2 @@ +set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +find_package(VersionedA 3) diff --git a/Tests/RunCMake/get_property/IsMultiConfig-stdout.txt b/Tests/RunCMake/get_property/IsMultiConfig-stdout.txt new file mode 100644 index 000000000..9808674a2 --- /dev/null +++ b/Tests/RunCMake/get_property/IsMultiConfig-stdout.txt @@ -0,0 +1 @@ +-- GENERATOR_IS_MULTI_CONFIG=1 diff --git a/Tests/RunCMake/get_property/IsMultiConfig.cmake b/Tests/RunCMake/get_property/IsMultiConfig.cmake new file mode 100644 index 000000000..64d5ff635 --- /dev/null +++ b/Tests/RunCMake/get_property/IsMultiConfig.cmake @@ -0,0 +1,2 @@ +get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +message(STATUS "GENERATOR_IS_MULTI_CONFIG=${is_multi_config}") diff --git a/Tests/RunCMake/get_property/NotMultiConfig-stdout.txt b/Tests/RunCMake/get_property/NotMultiConfig-stdout.txt new file mode 100644 index 000000000..8e0f89539 --- /dev/null +++ b/Tests/RunCMake/get_property/NotMultiConfig-stdout.txt @@ -0,0 +1 @@ +-- GENERATOR_IS_MULTI_CONFIG=0 diff --git a/Tests/RunCMake/get_property/NotMultiConfig.cmake b/Tests/RunCMake/get_property/NotMultiConfig.cmake new file mode 100644 index 000000000..59172d59f --- /dev/null +++ b/Tests/RunCMake/get_property/NotMultiConfig.cmake @@ -0,0 +1 @@ +include(IsMultiConfig.cmake) diff --git a/Tests/RunCMake/get_property/RunCMakeTest.cmake b/Tests/RunCMake/get_property/RunCMakeTest.cmake index 00eef34c0..017990fa9 100644 --- a/Tests/RunCMake/get_property/RunCMakeTest.cmake +++ b/Tests/RunCMake/get_property/RunCMakeTest.cmake @@ -22,3 +22,9 @@ run_cmake(NoTarget) run_cmake(NoSource) run_cmake(NoProperty) run_cmake(NoCache) + +if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode") + run_cmake(IsMultiConfig) +else() + run_cmake(NotMultiConfig) +endif() diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake index 077d00a05..f54edf7ed 100644 --- a/Tests/RunCMake/if/RunCMakeTest.cmake +++ b/Tests/RunCMake/if/RunCMakeTest.cmake @@ -3,7 +3,11 @@ include(RunCMake) run_cmake(InvalidArgument1) run_cmake(IsDirectory) run_cmake(IsDirectoryLong) +run_cmake(duplicate-deep-else) +run_cmake(duplicate-else) +run_cmake(duplicate-else-after-elseif) run_cmake(elseif-message) +run_cmake(misplaced-elseif) run_cmake(MatchesSelf) diff --git a/Tests/RunCMake/if/duplicate-deep-else-result.txt b/Tests/RunCMake/if/duplicate-deep-else-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/if/duplicate-deep-else-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/if/duplicate-deep-else-stderr.txt b/Tests/RunCMake/if/duplicate-deep-else-stderr.txt new file mode 100644 index 000000000..ac2335c05 --- /dev/null +++ b/Tests/RunCMake/if/duplicate-deep-else-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at duplicate-deep-else.cmake:[0-9]+ \(else\): + A duplicate ELSE command was found inside an IF block. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/if/duplicate-deep-else.cmake b/Tests/RunCMake/if/duplicate-deep-else.cmake new file mode 100644 index 000000000..94f06defb --- /dev/null +++ b/Tests/RunCMake/if/duplicate-deep-else.cmake @@ -0,0 +1,7 @@ +if(0) +else() + if(0) + else() + else() + endif() +endif() diff --git a/Tests/RunCMake/if/duplicate-else-after-elseif-result.txt b/Tests/RunCMake/if/duplicate-else-after-elseif-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/if/duplicate-else-after-elseif-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt b/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt new file mode 100644 index 000000000..ba6765c82 --- /dev/null +++ b/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at duplicate-else-after-elseif.cmake:[0-9]+ \(else\): + A duplicate ELSE command was found inside an IF block. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/if/duplicate-else-after-elseif.cmake b/Tests/RunCMake/if/duplicate-else-after-elseif.cmake new file mode 100644 index 000000000..d1d4ac18a --- /dev/null +++ b/Tests/RunCMake/if/duplicate-else-after-elseif.cmake @@ -0,0 +1,5 @@ +if(0) +elseif(0) +else() +else() +endif() diff --git a/Tests/RunCMake/if/duplicate-else-result.txt b/Tests/RunCMake/if/duplicate-else-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/if/duplicate-else-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/if/duplicate-else-stderr.txt b/Tests/RunCMake/if/duplicate-else-stderr.txt new file mode 100644 index 000000000..e0dd01f33 --- /dev/null +++ b/Tests/RunCMake/if/duplicate-else-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at duplicate-else.cmake:[0-9]+ \(else\): + A duplicate ELSE command was found inside an IF block. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/if/duplicate-else.cmake b/Tests/RunCMake/if/duplicate-else.cmake new file mode 100644 index 000000000..14a03ac57 --- /dev/null +++ b/Tests/RunCMake/if/duplicate-else.cmake @@ -0,0 +1,4 @@ +if(0) +else() +else() +endif() diff --git a/Tests/RunCMake/if/misplaced-elseif-result.txt b/Tests/RunCMake/if/misplaced-elseif-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/if/misplaced-elseif-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/if/misplaced-elseif-stderr.txt b/Tests/RunCMake/if/misplaced-elseif-stderr.txt new file mode 100644 index 000000000..c4b0266c7 --- /dev/null +++ b/Tests/RunCMake/if/misplaced-elseif-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at misplaced-elseif.cmake:[0-9]+ \(elseif\): + An ELSEIF command was found after an ELSE command. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/if/misplaced-elseif.cmake b/Tests/RunCMake/if/misplaced-elseif.cmake new file mode 100644 index 000000000..d27f24e18 --- /dev/null +++ b/Tests/RunCMake/if/misplaced-elseif.cmake @@ -0,0 +1,4 @@ +if(0) +else() +elseif(1) +endif() diff --git a/Tests/RunCMake/include_external_msproject/CustomConfig-check.cmake b/Tests/RunCMake/include_external_msproject/CustomConfig-check.cmake new file mode 100644 index 000000000..1a940b810 --- /dev/null +++ b/Tests/RunCMake/include_external_msproject/CustomConfig-check.cmake @@ -0,0 +1 @@ +check_project(CustomConfig external "aaa-bbb-ccc-000" "" "" "Custom - Release") diff --git a/Tests/RunCMake/include_external_msproject/CustomConfig.cmake b/Tests/RunCMake/include_external_msproject/CustomConfig.cmake new file mode 100644 index 000000000..1f935cd58 --- /dev/null +++ b/Tests/RunCMake/include_external_msproject/CustomConfig.cmake @@ -0,0 +1,3 @@ +include_external_msproject(external external.project + GUID aaa-bbb-ccc-000) +set_target_properties(external PROPERTIES MAP_IMPORTED_CONFIG_RELEASE "Custom - Release") diff --git a/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake b/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake index 68dec4c08..3747934db 100644 --- a/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake +++ b/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake @@ -1 +1 @@ -check_project(CustomGuid external "aaa-bbb-ccc-000" "" "") +check_project(CustomGuid external "aaa-bbb-ccc-000" "" "" "") diff --git a/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake b/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake index 614712ee6..0b2ac1db0 100644 --- a/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake +++ b/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake @@ -1 +1 @@ -check_project(CustomGuidTypePlatform external "aaa-bbb-ccc-111" "aaa-bbb-ccc-ddd-eee" "Custom Platform") +check_project(CustomGuidTypePlatform external "aaa-bbb-ccc-111" "aaa-bbb-ccc-ddd-eee" "Custom Platform" "") diff --git a/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake b/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake index 054eeb037..c431b03d6 100644 --- a/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake +++ b/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake @@ -1 +1 @@ -check_project(CustomTypePlatform external "" "aaa-bbb-ccc-ddd-eee" "Custom Platform") +check_project(CustomTypePlatform external "" "aaa-bbb-ccc-ddd-eee" "Custom Platform" "") diff --git a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake index 90710f9bf..47dac349f 100644 --- a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake +++ b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake @@ -4,3 +4,4 @@ include(${CMAKE_CURRENT_LIST_DIR}/check_utils.cmake) run_cmake(CustomGuid) run_cmake(CustomTypePlatform) run_cmake(CustomGuidTypePlatform) +run_cmake(CustomConfig) diff --git a/Tests/RunCMake/include_external_msproject/check_utils.cmake b/Tests/RunCMake/include_external_msproject/check_utils.cmake index 5dd92f9cc..e9e9cac72 100644 --- a/Tests/RunCMake/include_external_msproject/check_utils.cmake +++ b/Tests/RunCMake/include_external_msproject/check_utils.cmake @@ -71,8 +71,24 @@ function(check_custom_platform TARGET_FILE PROJECT_NAME PLATFORM_NAME RESULT) set(${RESULT} ${IS_FOUND} PARENT_SCOPE) endfunction() +# Search project's build configuration line by project name and target configuration name. +# Returns TRUE if found and FALSE otherwise +function(check_custom_configuration TARGET_FILE PROJECT_NAME SLN_CONFIG DST_CONFIG RESULT) + set(${RESULT} "FALSE" PARENT_SCOPE) + # extract project guid + parse_project_section(${TARGET_FILE} ${PROJECT_NAME}) + if(NOT IS_FOUND) + return() + endif() + + set(REG_EXP "^(\t)*\\{${FOUND_GUID}\\}\\.${SLN_CONFIG}[^ ]*\\.ActiveCfg = ${DST_CONFIG}\\|.*$") + check_line_exists(${TARGET_FILE} REG_EXP) + + set(${RESULT} ${IS_FOUND} PARENT_SCOPE) +endfunction() + # RunCMake test check helper -function(check_project test name guid type platform) +function(check_project test name guid type platform imported_release_config_name) set(sln "${RunCMake_TEST_BINARY_DIR}/${test}.sln") set(sep "") set(failed "") @@ -88,6 +104,9 @@ function(check_project test name guid type platform) set(platform "Win32") endif() endif() + if(NOT imported_release_config_name) + set(imported_release_config_name "Release") + endif() if(guid) check_project_guid("${sln}" "${name}" "${guid}" passed_guid) if(NOT passed_guid) @@ -107,5 +126,11 @@ function(check_project test name guid type platform) string(APPEND failed "${sep}${name} solution has no project with expected PLATFORM=${platform}") set(sep "\n") endif() + check_custom_configuration("${sln}" "${name}" "Release" "${imported_release_config_name}" passed_configuration) + if(NOT passed_configuration) + string(APPEND failed "${sep}${name} solution has no project with expected CONFIG=${imported_release_config_name}") + set(sep "\n") + endif() + set(RunCMake_TEST_FAILED "${failed}" PARENT_SCOPE) endfunction() diff --git a/Tests/RunCMake/install/EXPORT-OldIFace.cmake b/Tests/RunCMake/install/EXPORT-OldIFace.cmake index 033f68446..ee3fb2328 100644 --- a/Tests/RunCMake/install/EXPORT-OldIFace.cmake +++ b/Tests/RunCMake/install/EXPORT-OldIFace.cmake @@ -1,5 +1,6 @@ enable_language(C) set(CMAKE_BUILD_WITH_INSTALL_RPATH 1) +set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR 1) add_subdirectory(EXPORT-OldIFace) add_library(foo SHARED empty.c) target_link_libraries(foo bar) diff --git a/Tests/RunCMake/install/FILES-TARGET_OBJECTS-all-check.cmake b/Tests/RunCMake/install/FILES-TARGET_OBJECTS-all-check.cmake new file mode 100644 index 000000000..f7f2a3a94 --- /dev/null +++ b/Tests/RunCMake/install/FILES-TARGET_OBJECTS-all-check.cmake @@ -0,0 +1 @@ +check_installed([[^objs;objs/obj1(\.c)?\.(o|obj);objs/obj2(\.c)?\.(o|obj)$]]) diff --git a/Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake b/Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake new file mode 100644 index 000000000..40c58ad57 --- /dev/null +++ b/Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_library(objs OBJECT obj1.c obj2.c) +install(FILES $ DESTINATION objs) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 45693b550..1a60f0c27 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -13,12 +13,15 @@ function(run_install_test case) # Check "all" components. set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-all) run_cmake_command(${case}-all ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -P cmake_install.cmake) - # Check unspecified component. - set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-uns) - run_cmake_command(${case}-uns ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=Unspecified -P cmake_install.cmake) - # Check explicit component. - set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-exc) - run_cmake_command(${case}-exc ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=exc -P cmake_install.cmake) + + if(run_install_test_components) + # Check unspecified component. + set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-uns) + run_cmake_command(${case}-uns ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=Unspecified -P cmake_install.cmake) + # Check explicit component. + set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-exc) + run_cmake_command(${case}-exc ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=exc -P cmake_install.cmake) + endif() endfunction() # Function called in *-check.cmake scripts to check installed files. @@ -57,5 +60,10 @@ run_cmake(CMP0062-OLD) run_cmake(CMP0062-NEW) run_cmake(CMP0062-WARN) +if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]") + run_install_test(FILES-TARGET_OBJECTS) +endif() + +set(run_install_test_components 1) run_install_test(FILES-EXCLUDE_FROM_ALL) run_install_test(TARGETS-EXCLUDE_FROM_ALL) diff --git a/Tests/RunCMake/install/obj1.c b/Tests/RunCMake/install/obj1.c new file mode 100644 index 000000000..2411aab79 --- /dev/null +++ b/Tests/RunCMake/install/obj1.c @@ -0,0 +1,4 @@ +int obj1(void) +{ + return 0; +} diff --git a/Tests/RunCMake/install/obj2.c b/Tests/RunCMake/install/obj2.c new file mode 100644 index 000000000..2dad71edb --- /dev/null +++ b/Tests/RunCMake/install/obj2.c @@ -0,0 +1,4 @@ +int obj2(void) +{ + return 0; +} diff --git a/Tests/RunCMake/project/ProjectDescription-stdout.txt b/Tests/RunCMake/project/ProjectDescription-stdout.txt new file mode 100644 index 000000000..ffa90923e --- /dev/null +++ b/Tests/RunCMake/project/ProjectDescription-stdout.txt @@ -0,0 +1 @@ +PROJECT_DESCRIPTION=Test Project diff --git a/Tests/RunCMake/project/ProjectDescription.cmake b/Tests/RunCMake/project/ProjectDescription.cmake new file mode 100644 index 000000000..3a4736223 --- /dev/null +++ b/Tests/RunCMake/project/ProjectDescription.cmake @@ -0,0 +1,6 @@ +cmake_policy(SET CMP0048 NEW) +project(ProjectDescriptionTest VERSION 1.0.0 DESCRIPTION "Test Project" LANGUAGES) +if(NOT PROJECT_DESCRIPTION) + message(FATAL_ERROR "PROJECT_DESCRIPTION expected to be set") +endif() +message(STATUS "PROJECT_DESCRIPTION=${PROJECT_DESCRIPTION}") diff --git a/Tests/RunCMake/project/ProjectDescription2-result.txt b/Tests/RunCMake/project/ProjectDescription2-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/project/ProjectDescription2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/project/ProjectDescription2-stderr.txt b/Tests/RunCMake/project/ProjectDescription2-stderr.txt new file mode 100644 index 000000000..558e2dfbb --- /dev/null +++ b/Tests/RunCMake/project/ProjectDescription2-stderr.txt @@ -0,0 +1 @@ + DESCRITPION may be specified at most once. diff --git a/Tests/RunCMake/project/ProjectDescription2.cmake b/Tests/RunCMake/project/ProjectDescription2.cmake new file mode 100644 index 000000000..3f186ba19 --- /dev/null +++ b/Tests/RunCMake/project/ProjectDescription2.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0048 NEW) +project(ProjectDescriptionTest VERSION 1.0.0 DESCRIPTION "Test Project" DESCRIPTION "Only once allowed" LANGUAGES) diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake index dba97d2b2..3d13e2ef4 100644 --- a/Tests/RunCMake/project/RunCMakeTest.cmake +++ b/Tests/RunCMake/project/RunCMakeTest.cmake @@ -7,6 +7,8 @@ run_cmake(LanguagesImplicit) run_cmake(LanguagesEmpty) run_cmake(LanguagesNONE) run_cmake(LanguagesTwice) +run_cmake(ProjectDescription) +run_cmake(ProjectDescription2) run_cmake(VersionAndLanguagesEmpty) run_cmake(VersionEmpty) run_cmake(VersionInvalid) diff --git a/Tests/RunCMake/separate_arguments/CMakeLists.txt b/Tests/RunCMake/separate_arguments/CMakeLists.txt new file mode 100644 index 000000000..289710955 --- /dev/null +++ b/Tests/RunCMake/separate_arguments/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.0) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/separate_arguments/EmptyCommand.cmake b/Tests/RunCMake/separate_arguments/EmptyCommand.cmake new file mode 100644 index 000000000..895b6ac2e --- /dev/null +++ b/Tests/RunCMake/separate_arguments/EmptyCommand.cmake @@ -0,0 +1,6 @@ +set(nothing) +separate_arguments(nothing) +if(DEFINED nothing) + message(FATAL_ERROR "separate_arguments null-case failed: " + "nothing=[${nothing}]") +endif() diff --git a/Tests/RunCMake/separate_arguments/NativeCommand.cmake b/Tests/RunCMake/separate_arguments/NativeCommand.cmake new file mode 100644 index 000000000..1cb009e9f --- /dev/null +++ b/Tests/RunCMake/separate_arguments/NativeCommand.cmake @@ -0,0 +1,19 @@ +set(unix_cmd "a \"b c\" 'd e' \";\" \\ \\'\\\" '\\'' \"\\\"\"") +set(unix_exp "a;b c;d e;\;; '\";';\"") + +set(windows_cmd "a \"b c\" 'd e' \";\" \\ \"c:\\windows\\path\\\\\" \\\"") +set(windows_exp "a;b c;'d;e';\;;\\;c:\\windows\\path\\;\"") + +if(CMAKE_HOST_WIN32) + set(native_cmd "${windows_cmd}") + set(native_exp "${windows_exp}") +else() + set(native_cmd "${unix_cmd}") + set(native_exp "${unix_exp}") +endif() +separate_arguments(native_out NATIVE_COMMAND "${native_cmd}") + +if(NOT "${native_out}" STREQUAL "${native_exp}") + message(FATAL_ERROR "separate_arguments native-style failed. " + "Expected\n [${native_exp}]\nbut got\n [${native_out}]\n") +endif() diff --git a/Tests/RunCMake/separate_arguments/PlainCommand.cmake b/Tests/RunCMake/separate_arguments/PlainCommand.cmake new file mode 100644 index 000000000..311a99378 --- /dev/null +++ b/Tests/RunCMake/separate_arguments/PlainCommand.cmake @@ -0,0 +1,8 @@ +set(old_out "a b c") +separate_arguments(old_out) +set(old_exp "a;b;;c") + +if(NOT "${old_out}" STREQUAL "${old_exp}") + message(FATAL_ERROR "separate_arguments old-style failed. " + "Expected\n [${old_exp}]\nbut got\n [${old_out}]\n") +endif() diff --git a/Tests/RunCMake/separate_arguments/RunCMakeTest.cmake b/Tests/RunCMake/separate_arguments/RunCMakeTest.cmake new file mode 100644 index 000000000..07951bb59 --- /dev/null +++ b/Tests/RunCMake/separate_arguments/RunCMakeTest.cmake @@ -0,0 +1,7 @@ +include(RunCMake) + +run_cmake(EmptyCommand) +run_cmake(PlainCommand) +run_cmake(UnixCommand) +run_cmake(WindowsCommand) +run_cmake(NativeCommand) diff --git a/Tests/RunCMake/separate_arguments/UnixCommand.cmake b/Tests/RunCMake/separate_arguments/UnixCommand.cmake new file mode 100644 index 000000000..0b5767ac5 --- /dev/null +++ b/Tests/RunCMake/separate_arguments/UnixCommand.cmake @@ -0,0 +1,8 @@ +set(unix_cmd "a \"b c\" 'd e' \";\" \\ \\'\\\" '\\'' \"\\\"\"") +set(unix_exp "a;b c;d e;\;; '\";';\"") +separate_arguments(unix_out UNIX_COMMAND "${unix_cmd}") + +if(NOT "${unix_out}" STREQUAL "${unix_exp}") + message(FATAL_ERROR "separate_arguments unix-style failed. " + "Expected\n [${unix_exp}]\nbut got\n [${unix_out}]\n") +endif() diff --git a/Tests/RunCMake/separate_arguments/WindowsCommand.cmake b/Tests/RunCMake/separate_arguments/WindowsCommand.cmake new file mode 100644 index 000000000..86aa14ad0 --- /dev/null +++ b/Tests/RunCMake/separate_arguments/WindowsCommand.cmake @@ -0,0 +1,8 @@ +set(windows_cmd "a \"b c\" 'd e' \";\" \\ \"c:\\windows\\path\\\\\" \\\"") +set(windows_exp "a;b c;'d;e';\;;\\;c:\\windows\\path\\;\"") +separate_arguments(windows_out WINDOWS_COMMAND "${windows_cmd}") + +if(NOT "${windows_out}" STREQUAL "${windows_exp}") + message(FATAL_ERROR "separate_arguments windows-style failed. " + "Expected\n [${windows_exp}]\nbut got\n [${windows_out}]\n") +endif() diff --git a/Tests/RunCMake/target_compile_features/CMakeLists.txt b/Tests/RunCMake/target_compile_features/CMakeLists.txt index 3482e6baf..289710955 100644 --- a/Tests/RunCMake/target_compile_features/CMakeLists.txt +++ b/Tests/RunCMake/target_compile_features/CMakeLists.txt @@ -1,3 +1,3 @@ cmake_minimum_required(VERSION 3.0) -project(${RunCMake_TEST} CXX) +project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake index 33faf2bbb..1f67f11a0 100644 --- a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake @@ -11,3 +11,4 @@ run_cmake(not_a_cxx_feature) run_cmake(no_matching_cxx_feature) run_cmake(not_a_c_feature) run_cmake(no_matching_c_feature) +run_cmake(cxx_not_enabled) diff --git a/Tests/RunCMake/target_compile_features/alias_target-stderr.txt b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt index 417bf62aa..5ebe170c3 100644 --- a/Tests/RunCMake/target_compile_features/alias_target-stderr.txt +++ b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at alias_target.cmake:4 \(target_compile_features\): +CMake Error at alias_target.cmake:[0-9]+ \(target_compile_features\): target_compile_features can not be used on an ALIAS target. Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_compile_features/alias_target.cmake b/Tests/RunCMake/target_compile_features/alias_target.cmake index d35ddba54..6fcdadaa5 100644 --- a/Tests/RunCMake/target_compile_features/alias_target.cmake +++ b/Tests/RunCMake/target_compile_features/alias_target.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) add_executable(main empty.cpp) add_executable(Alias::Main ALIAS main) diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt b/Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt new file mode 100644 index 000000000..4f707c7b9 --- /dev/null +++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at cxx_not_enabled.cmake:[0-9]+ \(target_compile_features\): + target_compile_features cannot use features from non-enabled language CXX +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake b/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake new file mode 100644 index 000000000..b7e91196e --- /dev/null +++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake @@ -0,0 +1,2 @@ +add_executable(main empty.c) +target_compile_features(main PRIVATE cxx_decltype) diff --git a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt index c6ff5ec21..7a07427a0 100644 --- a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt +++ b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at imported_target.cmake:3 \(target_compile_features\): +CMake Error at imported_target.cmake:[0-9]+ \(target_compile_features\): Cannot specify compile features for imported target "main". Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_compile_features/imported_target.cmake b/Tests/RunCMake/target_compile_features/imported_target.cmake index e248c2fee..e886ce922 100644 --- a/Tests/RunCMake/target_compile_features/imported_target.cmake +++ b/Tests/RunCMake/target_compile_features/imported_target.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) add_library(main INTERFACE IMPORTED) target_compile_features(main INTERFACE cxx_delegating_constructors) diff --git a/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt index bd5b7b9d5..9917be77a 100644 --- a/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt +++ b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at invalid_args.cmake:3 \(target_compile_features\): +CMake Error at invalid_args.cmake:[0-9]+ \(target_compile_features\): target_compile_features called with invalid arguments Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_compile_features/invalid_args.cmake b/Tests/RunCMake/target_compile_features/invalid_args.cmake index 1a7fb3749..cc051a445 100644 --- a/Tests/RunCMake/target_compile_features/invalid_args.cmake +++ b/Tests/RunCMake/target_compile_features/invalid_args.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) add_executable(main empty.cpp) target_compile_features(main INVALID cxx_delegating_constructors) diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt index c30209a28..37089983a 100644 --- a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt +++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at invalid_args_on_interface.cmake:3 \(target_compile_features\): +CMake Error at invalid_args_on_interface.cmake:[0-9]+ \(target_compile_features\): target_compile_features may only be set INTERFACE properties on INTERFACE targets Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake index 324d0f384..49d2d827d 100644 --- a/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake +++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) add_library(main INTERFACE) target_compile_features(main PRIVATE cxx_delegating_constructors) diff --git a/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt b/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt index 96b959cf5..1875d1209 100644 --- a/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt +++ b/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at no_matching_c_feature.cmake:[0-9][0-9]? \((target_compile_features|message)\): +CMake Error at no_matching_c_feature.cmake:[0-9]+ \((target_compile_features|message)\): The compiler feature "gnu_c_dummy" is not known to C compiler "GNU" diff --git a/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake b/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake index a44caf29a..0e93b41ff 100644 --- a/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake +++ b/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) if (NOT ";${CMAKE_C_COMPILE_FEATURES};" MATCHES ";gnu_c_typeof;") # Simulate passing the test. diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt index f976dfeab..90d41c957 100644 --- a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt +++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at no_matching_cxx_feature.cmake:[0-9][0-9]? \((target_compile_features|message)\): +CMake Error at no_matching_cxx_feature.cmake:[0-9]+ \((target_compile_features|message)\): The compiler feature "[^"]+" is not known to CXX compiler "[^"]*" diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake index ab1fd7608..4ee3445e8 100644 --- a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake +++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";gnu_cxx_typeof;" AND NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";msvc_cxx_sealed;" ) diff --git a/Tests/RunCMake/target_compile_features/no_target-stderr.txt b/Tests/RunCMake/target_compile_features/no_target-stderr.txt index 323ba7a90..65974b4d6 100644 --- a/Tests/RunCMake/target_compile_features/no_target-stderr.txt +++ b/Tests/RunCMake/target_compile_features/no_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at no_target.cmake:2 \(target_compile_features\): +CMake Error at no_target.cmake:[0-9]+ \(target_compile_features\): Cannot specify compile features for target "main" which is not built by this project. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/target_compile_features/no_target.cmake b/Tests/RunCMake/target_compile_features/no_target.cmake index 3f0afe273..a514de86a 100644 --- a/Tests/RunCMake/target_compile_features/no_target.cmake +++ b/Tests/RunCMake/target_compile_features/no_target.cmake @@ -1,2 +1,3 @@ +enable_language(CXX) target_compile_features(main INTERFACE cxx_delegating_constructors) diff --git a/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt b/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt index 6dd00f359..493c5826c 100644 --- a/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt +++ b/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at not_a_c_feature.cmake:3 \(target_compile_features\): +CMake Error at not_a_c_feature.cmake:[0-9]+ \(target_compile_features\): target_compile_features specified unknown feature "c_not_a_feature" for target "main". Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake b/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake index 0420698bc..f5d70d093 100644 --- a/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake +++ b/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake @@ -1,3 +1,4 @@ +enable_language(C) add_executable(main empty.c) target_compile_features(main diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt index efa2bad5f..3dbf0e654 100644 --- a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt +++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at not_a_cxx_feature.cmake:3 \(target_compile_features\): +CMake Error at not_a_cxx_feature.cmake:[0-9]+ \(target_compile_features\): target_compile_features specified unknown feature "cxx_not_a_feature" for target "main". Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake index 0207b724d..bc3a8c4f6 100644 --- a/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake +++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) add_executable(main empty.cpp) target_compile_features(main diff --git a/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt index 2f8d81243..c0c2efac4 100644 --- a/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt +++ b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at not_enough_args.cmake:3 \(target_compile_features\): +CMake Error at not_enough_args.cmake:[0-9]+ \(target_compile_features\): target_compile_features called with incorrect number of arguments Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/target_compile_features/not_enough_args.cmake b/Tests/RunCMake/target_compile_features/not_enough_args.cmake index 95612300a..f5b719863 100644 --- a/Tests/RunCMake/target_compile_features/not_enough_args.cmake +++ b/Tests/RunCMake/target_compile_features/not_enough_args.cmake @@ -1,3 +1,4 @@ +enable_language(CXX) add_executable(main empty.cpp) target_compile_features(main) diff --git a/Tests/RunCMake/target_compile_features/utility_target-stderr.txt b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt index d23905995..ff03310d1 100644 --- a/Tests/RunCMake/target_compile_features/utility_target-stderr.txt +++ b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at utility_target.cmake:4 \(target_compile_features\): +CMake Error at utility_target.cmake:[0-9]+ \(target_compile_features\): target_compile_features called with non-compilable target type Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/Server/cmakelib.py b/Tests/Server/cmakelib.py index d11431d0c..78450d5bf 100644 --- a/Tests/Server/cmakelib.py +++ b/Tests/Server/cmakelib.py @@ -1,3 +1,4 @@ +from __future__ import print_function import sys, subprocess, json termwidth = 150 @@ -13,8 +14,8 @@ def ordered(obj): return obj def col_print(title, array): - print - print + print() + print() print(title) indentwidth = 4 diff --git a/Tests/Server/server-test.py b/Tests/Server/server-test.py index 14767f4cc..62d9008b2 100644 --- a/Tests/Server/server-test.py +++ b/Tests/Server/server-test.py @@ -1,3 +1,4 @@ +from __future__ import print_function import sys, cmakelib, json, os, shutil debug = True diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index 4cf73559b..f8068b143 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/Tests/SimpleInstall/CMakeLists.txt @@ -365,6 +365,7 @@ set(CPACK_PACKAGE_EXECUTABLES "SimpleInstall" "Simple Install") set(CMAKE_INSTALL_MFC_LIBRARIES 1) set(CMAKE_INSTALL_DEBUG_LIBRARIES 1) set(CMAKE_INSTALL_UCRT_LIBRARIES 1) +set(CMAKE_INSTALL_OPENMP_LIBRARIES 1) include(InstallRequiredSystemLibraries) if(CTEST_TEST_CPACK) diff --git a/Tests/SourceGroups/CMakeLists.txt b/Tests/SourceGroups/CMakeLists.txt index 9289e8444..4e4a030ce 100644 --- a/Tests/SourceGroups/CMakeLists.txt +++ b/Tests/SourceGroups/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 3.8) project(SourceGroups) # this is not really a test which can fail @@ -33,10 +33,11 @@ source_group(EmptyGroup) set(root ${CMAKE_CURRENT_SOURCE_DIR}) set(tree_files_without_prefix ${root}/sub1/tree_bar.c - ${root}/sub1/tree_baz.c - ${root}/sub1/tree_subdir/tree_foobar.c) + sub1/tree_baz.c + sub1/../sub1/tree_subdir/tree_foobar.c) -set(tree_files_with_prefix ${root}/tree_foo.c) +set(tree_files_with_prefix ${root}/tree_prefix_foo.c + tree_prefix_bar.c) source_group(TREE ${root} FILES ${tree_files_without_prefix}) diff --git a/Tests/SourceGroups/main.c b/Tests/SourceGroups/main.c index b88f2f8b3..4d84cf20e 100644 --- a/Tests/SourceGroups/main.c +++ b/Tests/SourceGroups/main.c @@ -5,7 +5,8 @@ extern int bar(void); extern int foobar(void); extern int barbar(void); extern int baz(void); -extern int tree_foo(void); +extern int tree_prefix_foo(void); +extern int tree_prefix_bar(void); extern int tree_bar(void); extern int tree_foobar(void); extern int tree_baz(void); @@ -15,7 +16,9 @@ int main() printf("foo: %d bar: %d foobar: %d barbar: %d baz: %d\n", foo(), bar(), foobar(), barbar(), baz()); - printf("tree_foo: %d tree_bar: %d tree_foobar: %d tree_baz: %d\n", - tree_foo(), tree_bar(), tree_foobar(), tree_baz()); + printf("tree_prefix_foo: %d tree_prefix_bar: %d tree_bar: %d tree_foobar: " + "%d tree_baz: %d\n", + tree_prefix_foo(), tree_prefix_bar(), tree_bar(), tree_foobar(), + tree_baz()); return 0; } diff --git a/Tests/SourceGroups/tree_foo.c b/Tests/SourceGroups/tree_foo.c deleted file mode 100644 index d392e41fd..000000000 --- a/Tests/SourceGroups/tree_foo.c +++ /dev/null @@ -1,4 +0,0 @@ -int tree_foo(void) -{ - return 6; -} diff --git a/Tests/SourceGroups/tree_prefix_bar.c b/Tests/SourceGroups/tree_prefix_bar.c new file mode 100644 index 000000000..bd98476ae --- /dev/null +++ b/Tests/SourceGroups/tree_prefix_bar.c @@ -0,0 +1,4 @@ +int tree_prefix_bar(void) +{ + return 66; +} diff --git a/Tests/SourceGroups/tree_prefix_foo.c b/Tests/SourceGroups/tree_prefix_foo.c new file mode 100644 index 000000000..92c2fd71e --- /dev/null +++ b/Tests/SourceGroups/tree_prefix_foo.c @@ -0,0 +1,4 @@ +int tree_prefix_foo(void) +{ + return 6; +} diff --git a/Tests/VSNASM/CMakeLists.txt b/Tests/VSNASM/CMakeLists.txt new file mode 100644 index 000000000..c2e29df25 --- /dev/null +++ b/Tests/VSNASM/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8.12) +project(VSNASM C ASM_NASM) +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + add_definitions(-DTESTx64) + string(APPEND CMAKE_ASM_NASM_FLAGS " -DTEST2x64") +else() + add_definitions(-DTESTi386) +endif() +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +add_executable(VSNASM main.c foo.asm) diff --git a/Tests/VSNASM/foo.asm b/Tests/VSNASM/foo.asm new file mode 100644 index 000000000..aba0673c0 --- /dev/null +++ b/Tests/VSNASM/foo.asm @@ -0,0 +1,7 @@ +section .text +%ifdef TEST2x64 +global foo +%else +global _foo +%endif +%include "foo-proc.asm" diff --git a/Tests/VSNASM/include/foo-proc.asm b/Tests/VSNASM/include/foo-proc.asm new file mode 100644 index 000000000..450a7919b --- /dev/null +++ b/Tests/VSNASM/include/foo-proc.asm @@ -0,0 +1,7 @@ +%ifdef TESTx64 +foo: +%else +_foo: +%endif + mov eax, 0 + ret diff --git a/Tests/VSNASM/main.c b/Tests/VSNASM/main.c new file mode 100644 index 000000000..18ddb7826 --- /dev/null +++ b/Tests/VSNASM/main.c @@ -0,0 +1,5 @@ +extern int foo(void); +int main(void) +{ + return foo(); +} diff --git a/Tests/VSResource/CMakeLists.txt b/Tests/VSResource/CMakeLists.txt index 3b9cfc396..718e62441 100644 --- a/Tests/VSResource/CMakeLists.txt +++ b/Tests/VSResource/CMakeLists.txt @@ -18,9 +18,8 @@ if(CMAKE_RC_COMPILER MATCHES windres) message(STATUS "CMAKE_RC_COMPILER MATCHES windres") add_definitions(/DCMAKE_RCDEFINE=test.txt) add_definitions(/DCMAKE_RCDEFINE_NO_QUOTED_STRINGS) - if(MSYS AND CMAKE_CURRENT_BINARY_DIR MATCHES " ") - # windres cannot handle spaces in include dir, and - # for the MSys shell we do not convert to shortpath. + if(CMAKE_CURRENT_BINARY_DIR MATCHES " ") + # windres cannot handle spaces in include dir set(CMAKE_RC_NO_INCLUDE 1) endif() elseif(MSVC60) @@ -51,5 +50,9 @@ add_library(ResourceLib STATIC lib.cpp lib.rc) add_executable(VSResource main.cpp test.rc) target_link_libraries(VSResource ResourceLib) +if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600) + set_property(SOURCE test.rc PROPERTY COMPILE_FLAGS /nologo) +endif() + set_property(TARGET VSResource PROPERTY VS_GLOBAL_CMakeTestVsGlobalVariable "test val") diff --git a/Tests/Wrapping/fakefluid.cxx b/Tests/Wrapping/fakefluid.cxx index 02c0c52df..a118bbd43 100644 --- a/Tests/Wrapping/fakefluid.cxx +++ b/Tests/Wrapping/fakefluid.cxx @@ -6,7 +6,9 @@ int main(int ac, char** av) if (strcmp(av[i], "-o") == 0 || strcmp(av[i], "-h") == 0) { fprintf(stdout, "fakefluid is creating file \"%s\"\n", av[i + 1]); FILE* file = fopen(av[i + 1], "w"); - fprintf(file, "// hello\n"); + fprintf(file, "// Solaris needs non-empty content so ensure\n" + "// we have at least one symbol\n" + "int Solaris_requires_a_symbol_here = 0;\n"); fclose(file); } } diff --git a/Tests/XCTest/CMakeLists.txt b/Tests/XCTest/CMakeLists.txt index e8666231b..d40c40e2a 100644 --- a/Tests/XCTest/CMakeLists.txt +++ b/Tests/XCTest/CMakeLists.txt @@ -55,3 +55,19 @@ xctest_add_bundle(CocoaExampleTests CocoaExample CocoaExampleTests/CocoaExampleTests.m) xctest_add_test(XCTest.CocoaExample CocoaExampleTests) + +# Static lib + +add_library(StaticLibExample STATIC + StaticLibExample/StaticLibExample.h + StaticLibExample/StaticLibExample.c +) + +target_include_directories(StaticLibExample PUBLIC .) + +# XCTest for Static lib + +xctest_add_bundle(StaticLibExampleTests StaticLibExample + StaticLibExampleTests/StaticLibExampleTests.m) + +xctest_add_test(XCTest.StaticLibExample StaticLibExampleTests) diff --git a/Tests/XCTest/StaticLibExample/StaticLibExample.c b/Tests/XCTest/StaticLibExample/StaticLibExample.c new file mode 100644 index 000000000..b198f80f3 --- /dev/null +++ b/Tests/XCTest/StaticLibExample/StaticLibExample.c @@ -0,0 +1,6 @@ +#include "StaticLibExample.h" + +int FourtyFour() +{ + return 44; +} diff --git a/Tests/XCTest/StaticLibExample/StaticLibExample.h b/Tests/XCTest/StaticLibExample/StaticLibExample.h new file mode 100644 index 000000000..147a909aa --- /dev/null +++ b/Tests/XCTest/StaticLibExample/StaticLibExample.h @@ -0,0 +1 @@ +int FourtyFour(); diff --git a/Tests/XCTest/StaticLibExampleTests/Info.plist b/Tests/XCTest/StaticLibExampleTests/Info.plist new file mode 100644 index 000000000..6ad9a27b5 --- /dev/null +++ b/Tests/XCTest/StaticLibExampleTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + StaticLibExampleTests + CFBundleIdentifier + org.cmake.StaticLibExampleTests + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + StaticLibExampleTests + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Tests/XCTest/StaticLibExampleTests/StaticLibExampleTests.m b/Tests/XCTest/StaticLibExampleTests/StaticLibExampleTests.m new file mode 100644 index 000000000..5f8a769f5 --- /dev/null +++ b/Tests/XCTest/StaticLibExampleTests/StaticLibExampleTests.m @@ -0,0 +1,16 @@ +#import + +#import "StaticLibExample/StaticLibExample.h" + +@interface StaticLibExampleTests : XCTestCase + +@end + +@implementation StaticLibExampleTests + +- (void)testFourtyFour { + // This is an example of a functional test case. + XCTAssertEqual(44, FourtyFour()); +} + +@end diff --git a/Utilities/.clang-tidy b/Utilities/.clang-tidy new file mode 100644 index 000000000..381a0f45a --- /dev/null +++ b/Utilities/.clang-tidy @@ -0,0 +1,6 @@ +--- +# We want to disable all checks for 3rd party code. However, clang-tidy will +# assume we did not configure it correctly. Just add one check that will never +# be found. +Checks: '-*,llvm-twine-local' +... diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 014204b00..056454019 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -29,3 +29,6 @@ endif() if(WIX_CUSTOM_ACTION_ENABLED) add_subdirectory(Release/WiX) endif() + +# Make sure generated files use the same clang-tidy checks (none). +configure_file(.clang-tidy .clang-tidy COPYONLY) diff --git a/Utilities/GitSetup/config b/Utilities/GitSetup/config index d69a6792f..2b4f03703 100644 --- a/Utilities/GitSetup/config +++ b/Utilities/GitSetup/config @@ -1,9 +1,2 @@ [hooks] - url = https://cmake.org/cmake.git -[ssh] - host = cmake.org - key = id_git_cmake - request-url = https://www.kitware.com/Admin/SendPassword.cgi -[stage] - url = git://cmake.org/stage/cmake.git - pushurl = git@cmake.org:stage/cmake.git + url = https://gitlab.kitware.com/utils/gitsetup.git diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp new file mode 100644 index 000000000..fe0f7df71 --- /dev/null +++ b/Utilities/IWYU/mapping.imp @@ -0,0 +1,161 @@ +[ + # C++ alternatives to C standard headers + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + { include: [ "", public, "", public ] }, + + # HACK: check whether this can be removed with next iwyu release. + { include: [ "", private, "", public ] }, + { include: [ "", private, "", public ] }, + { include: [ "", private, "", public ] }, + { include: [ "", private, "", public ] }, + { include: [ "", private, "", public ] }, + { include: [ "", private, "", public ] }, + { include: [ "", private, "", public ] }, + + # HACK: check whether this can be removed with next iwyu release. + { symbol: [ "__GLIBC__", private, "", public ] }, + { symbol: [ "_Noreturn", private, "", public ] }, + + # HACK: iwyu wrongly thinks that including is sufficient. + { symbol: [ "std::stringstream", private, "", public ] }, + { symbol: [ "std::istringstream", private, "", public ] }, + { symbol: [ "std::ostringstream", private, "", public ] }, + + # HACK: iwyu suggests those two files each time vector[] is used. + # https://github.com/include-what-you-use/include-what-you-use/issues/166 + { include: [ "", private, "", public ] }, + { include: [ "", public, "", public ] }, + + # TODO: enable this block and remove some includes? + #{ symbol: [ "std::pair", private, "", public ] }, + #{ symbol: [ "std::pair", private, "", public ] }, + #{ symbol: [ "std::pair", private, "", public ] }, + + # IWYU wrongly suggests to include "cm_auto_ptr.hxx" in some places. This + # might be a misinterpretation of a template specialization in . + # As a workaround, map the symbol auto_ptr to "cmConfigure.h". + # This will still correctly require "cm_auto_ptr.hxx" for CM_AUTO_PTR. + { symbol: [ "cm::auto_ptr", private, "\"cmConfigure.h\"", public ] }, + + # __decay_and_strip is used internally in the C++11 standard library. + # IWYU does not classify it as internal and suggests to add . + # To ignore it, we simply map it to a file that is included anyway. + # TODO: Can this be simplified with an @-expression? + #{ symbol: [ "@std::__decay_and_strip<.*>::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip &>::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip &>::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip<__gnu_cxx::__normal_iterator > > &>::__type", private, "\"cmConfigure.h\"", public ] }, + + # Wrappers for headers added in TR1 / C++11 + # { include: [ "", public, "\"cm_array.hxx\"", public ] }, + # { include: [ "", public, "\"cm_functional.hxx\"", public ] }, + # { include: [ "", public, "\"cm_memory.hxx\"", public ] }, + { include: [ "", public, "\"cm_unordered_map.hxx\"", public ] }, + { include: [ "", public, "\"cm_unordered_set.hxx\"", public ] }, + # { include: [ "", public, "\"cm_array.hxx\"", public ] }, + # { include: [ "", public, "\"cm_functional.hxx\"", public ] }, + # { include: [ "", public, "\"cm_memory.hxx\"", public ] }, + { include: [ "", public, "\"cm_unordered_map.hxx\"", public ] }, + { include: [ "", public, "\"cm_unordered_set.hxx\"", public ] }, + + # KWIML + { include: [ "", public, "\"cm_kwiml.h\"", public ] }, + { include: [ "", public, "\"cm_kwiml.h\"", public ] }, + + # Self-sufficient wrapper for + { include: [ "", public, "\"cm_sys_stat.h\"", public ] }, + { symbol: [ "mode_t", private, "\"cm_sys_stat.h\"", public ] }, + + # TODO: remove once TR1 / C++11 is required. + { include: [ "\"cmsys/hash_fun.hxx\"", private, "\"cm_unordered_map.hxx\"", public ] }, + { include: [ "\"cmsys/hash_fun.hxx\"", private, "\"cm_unordered_set.hxx\"", public ] }, + { include: [ "\"cmsys/hash_map.hxx\"", private, "\"cm_unordered_map.hxx\"", public ] }, + { include: [ "\"cmsys/hash_set.hxx\"", private, "\"cm_unordered_set.hxx\"", public ] }, + { include: [ "\"cmsys/hashtable.hxx\"", private, "\"cm_unordered_map.hxx\"", public ] }, + { include: [ "\"cmsys/hashtable.hxx\"", private, "\"cm_unordered_set.hxx\"", public ] }, + + # Wrappers for 3rd-party libraries used from the system. + { include: [ "", private, "\"cm_libarchive.h\"", public ] }, + { include: [ "", private, "\"cm_libarchive.h\"", public ] }, + { include: [ "@", private, "\"cm_curl.h\"", public ] }, + { include: [ "", private, "\"cm_expat.h\"", public ] }, + { include: [ "", private, "\"cm_expat.h\"", public ] }, + { include: [ "", private, "\"cm_jsoncpp_reader.h\"", public ] }, + { include: [ "", private, "\"cm_jsoncpp_value.h\"", public ] }, + { include: [ "", private, "\"cm_jsoncpp_writer.h\"", public ] }, + { include: [ "", private, "\"cm_rhash.h\"", public ] }, + { include: [ "", private, "\"cm_uv.h\"", public ] }, + { include: [ "@", private, "\"cm_uv.h\"", public ] }, + { include: [ "", private, "\"cm_kwiml.h\"", public ] }, + { include: [ "", private, "\"cm_kwiml.h\"", public ] }, + { include: [ "", private, "\"cm_xmlrpc.h\"", public ] }, + { include: [ "", private, "\"cm_xmlrpc.h\"", public ] }, + { include: [ "@", private, "\"cm_xmlrpc.h\"", public ] }, + { include: [ "", private, "\"cm_zlib.h\"", public ] }, + { include: [ "", private, "\"cm_zlib.h\"", public ] }, + + # Wrappers for bundled 3rd-party libraries. + { include: [ "\"cmlibarchive/libarchive/archive.h\"", private, "\"cm_libarchive.h\"", public ] }, + { include: [ "\"cmlibarchive/libarchive/archive_entry.h\"", private, "\"cm_libarchive.h\"", public ] }, + { include: [ "@\"cmcurl/include/curl/.+\\.h\"", private, "\"cm_curl.h\"", public ] }, + { include: [ "\"cmexpat/lib/expat.h\"", private, "\"cm_expat.h\"", public ] }, + { include: [ "\"cmexpat/lib/expat_external.h\"", private, "\"cm_expat.h\"", public ] }, + { include: [ "\"cmjsoncpp/include/json/reader.h\"", private, "\"cm_jsoncpp_reader.h\"", public ] }, + { include: [ "\"cmjsoncpp/include/json/value.h\"", private, "\"cm_jsoncpp_value.h\"", public ] }, + { include: [ "\"cmjsoncpp/include/json/writer.h\"", private, "\"cm_jsoncpp_writer.h\"", public ] }, + { include: [ "\"cmlibrhash/librhash/rhash.h\"", private, "\"cm_rhash.h\"", public ] }, + { include: [ "\"cmlibuv/include/uv.h\"", private, "\"cm_uv.h\"", public ] }, + { include: [ "@\"cmlibuv/include/uv-.+\\.h\"", private, "\"cm_uv.h\"", public ] }, + { include: [ "\"KWIML/include/kwiml/abi.h\"", private, "\"cm_kwiml.h\"", public ] }, + { include: [ "\"KWIML/include/kwiml/int.h\"", private, "\"cm_kwiml.h\"", public ] }, + { include: [ "\"cmzlib/cm_zlib_mangle.h\"", private, "\"cm_zlib.h\"", public ] }, + { include: [ "\"cmzlib/zconf.h\"", private, "\"cm_zlib.h\"", public ] }, + { include: [ "\"cmzlib/zlib.h\"", private, "\"cm_zlib.h\"", public ] }, + + # System symbols used by libuv + { symbol: [ "SIGHUP", private, "\"cm_uv.h\"", public ] }, + { symbol: [ "SIGINT", private, "\"cm_uv.h\"", public ] }, + { symbol: [ "ssize_t", private, "\"cm_uv.h\"", public ] }, + + { symbol: [ "std::ifstream", private, "\"cmsys/FStream.hxx\"", public ] }, + { symbol: [ "std::ofstream", private, "\"cmsys/FStream.hxx\"", public ] }, + { symbol: [ "cmsys::ifstream", private, "\"cmsys/FStream.hxx\"", public ] }, + { symbol: [ "cmsys::ofstream", private, "\"cmsys/FStream.hxx\"", public ] }, + + { include: [ "", public, "\"cmsys/FStream.hxx\"", public ] }, + { include: [ "", public, "\"cmsys/FStream.hxx\"", public ] }, + { include: [ "", public, "\"cmsys/FStream.hxx\"", public ] }, + + # major and minor are used as macro arguments. Those are false matches. + { symbol: [ "major", private, "\"cm_kwiml.h\"", public ] }, + { symbol: [ "minor", private, "\"cm_kwiml.h\"", public ] }, + { symbol: [ "major", private, "\"cmVersion.h\"", public ] }, + { symbol: [ "minor", private, "\"cmVersion.h\"", public ] }, + + { include: [ "", private, "\"cmCursesStandardIncludes.h\"", public ] }, + { include: [ "\"form.h\"", private, "\"cmCursesStandardIncludes.h\"", public ] }, + { include: [ "", private, "\"cmCursesStandardIncludes.h\"", public ] }, +] + +# vim: set ft=toml: diff --git a/Utilities/KWIML/test/CMakeLists.txt b/Utilities/KWIML/test/CMakeLists.txt index 1bf93bb4e..40fe62f20 100644 --- a/Utilities/KWIML/test/CMakeLists.txt +++ b/Utilities/KWIML/test/CMakeLists.txt @@ -38,6 +38,8 @@ endif() add_executable(kwiml_test ${test_srcs}) set_property(TARGET kwiml_test PROPERTY COMPILE_DEFINITIONS ${test_defs}) +set_property(TARGET kwiml_test PROPERTY C_INCLUDE_WHAT_YOU_USE "") +set_property(TARGET kwiml_test PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") set_property(TARGET kwiml_test PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_test(NAME ${KWIML_TEST_PREFIX}.test COMMAND kwiml_test) diff --git a/Utilities/Release/consolidate-relnotes.bash b/Utilities/Release/consolidate-relnotes.bash new file mode 100755 index 000000000..91307ac51 --- /dev/null +++ b/Utilities/Release/consolidate-relnotes.bash @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -e + +usage='usage: consolidate-relnotes.bash ' + +die() { + echo "$@" 1>&2; exit 1 +} + +test "$#" = 2 || die "$usage" + +files="$(ls Help/release/dev/* | grep -v Help/release/dev/0-sample-topic.rst)" +title="CMake $1 Release Notes" +underline="$(echo "$title" | sed 's/./*/g')" +echo "$title +$underline + +.. only:: html + + .. contents:: + +Changes made since CMake $2 include the following." > Help/release/"$1".rst +tail -q -n +3 $files >> Help/release/"$1".rst +sed -i "/^ $2 / i\\ + $1 <$1>" Help/release/index.rst +rm $files diff --git a/Utilities/Release/hythloth_release.cmake b/Utilities/Release/hythloth_release.cmake deleted file mode 100644 index d2f4ba58c..000000000 --- a/Utilities/Release/hythloth_release.cmake +++ /dev/null @@ -1,10 +0,0 @@ -set(PROCESSORS 2) -set(HOST hythloth) -set(MAKE_PROGRAM "make") -set(MAKE "${MAKE_PROGRAM} -j2") -set(INITIAL_CACHE " -CMAKE_BUILD_TYPE:STRING=Release -CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE -") -get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH) -include(${path}/release_cmake.cmake) diff --git a/Utilities/Release/linux64_release.cmake b/Utilities/Release/linux64_release.cmake index feba2a541..3d8ddba3c 100644 --- a/Utilities/Release/linux64_release.cmake +++ b/Utilities/Release/linux64_release.cmake @@ -35,6 +35,7 @@ OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.0.2j/lib/libssl.a PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 CPACK_SYSTEM_NAME:STRING=Linux-x86_64 BUILD_QtDialog:BOOL:=TRUE +CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE CMake_ENABLE_SERVER_MODE:BOOL=TRUE CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3 CMake_INSTALL_DEPENDENCIES:BOOL=ON diff --git a/Utilities/Release/osx_release.cmake b/Utilities/Release/osx_release.cmake index 88ea39b95..36498a7ce 100644 --- a/Utilities/Release/osx_release.cmake +++ b/Utilities/Release/osx_release.cmake @@ -27,7 +27,7 @@ CMAKE_SKIP_RPATH:BOOL=TRUE CMake_TEST_NO_FindPackageModeMakefileTest:BOOL=TRUE ") set(ENV [[ -export CMAKE_PREFIX_PATH='/Users/kitware/SDKs/qt-5.6.0-clang-x64' +export CMAKE_PREFIX_PATH='/Users/kitware/SDKs/qt-5.6.2-clang-x64' ]]) get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH) include(${path}/release_cmake.cmake) diff --git a/Utilities/Release/release_cmake.cmake b/Utilities/Release/release_cmake.cmake index 0db89b558..b2c21b7dc 100644 --- a/Utilities/Release/release_cmake.cmake +++ b/Utilities/Release/release_cmake.cmake @@ -32,9 +32,16 @@ if(NOT DEFINED GIT_COMMAND) set(GIT_COMMAND git) endif() -if(${CMAKE_CREATE_VERSION} MATCHES "^(release|maint|next|nightly)$") +if(CMAKE_CREATE_VERSION MATCHES "^(master|release)$") + set(GIT_FETCH "") set(GIT_BRANCH origin/${CMAKE_CREATE_VERSION}) +elseif(CMAKE_CREATE_VERSION STREQUAL "nightly") + set(nightly stage/master/nightly/latest) + set(GIT_FETCH "${GIT_COMMAND} fetch origin refs/${nightly}:refs/remotes/origin/${nightly}") + set(GIT_BRANCH origin/${nightly}) else() + set(stage stage/master/head) + set(GIT_FETCH "${GIT_COMMAND} fetch origin refs/${stage}:refs/remotes/origin/${stage}") set(GIT_BRANCH ${CMAKE_CREATE_VERSION}) endif() diff --git a/Utilities/Release/release_cmake.sh.in b/Utilities/Release/release_cmake.sh.in index 14651297b..f363b3d8a 100755 --- a/Utilities/Release/release_cmake.sh.in +++ b/Utilities/Release/release_cmake.sh.in @@ -94,13 +94,15 @@ cd @CMAKE_RELEASE_DIRECTORY@ if [ ! -z "@GIT_COMMAND@" ]; then # clone the repo without creating any source files in the directory # matching the branch being built (i.e. master CMake-2-8, etc) - @GIT_COMMAND@ clone -n git://cmake.org/cmake.git @CMAKE_CREATE_VERSION@ - check_exit_value $? "Checkout git cmake source" || exit 1 + @GIT_COMMAND@ clone -n https://gitlab.kitware.com/cmake/cmake.git @CMAKE_CREATE_VERSION@ + check_exit_value $? "git clone cmake source" || exit 1 # go into the git directory cd @CMAKE_CREATE_VERSION@ # run any extra commands if they exist @GIT_EXTRA@ check_exit_value $? "git extra cmake source" || exit 1 + @GIT_FETCH@ + check_exit_value $? "git extra fetch" || exit 1 # now checkout a copy on the local branch working @GIT_COMMAND@ checkout -b working @GIT_BRANCH@ check_exit_value $? "git checkout" || exit 1 diff --git a/Utilities/Release/upload_release.cmake b/Utilities/Release/upload_release.cmake index c49cb4fd3..5b2cc5732 100644 --- a/Utilities/Release/upload_release.cmake +++ b/Utilities/Release/upload_release.cmake @@ -1,6 +1,6 @@ set(CTEST_RUN_CURRENT_SCRIPT 0) if(NOT VERSION) - set(VERSION 3.8) + set(VERSION 3.9) endif() if(NOT DEFINED PROJECT_PREFIX) set(PROJECT_PREFIX cmake-${VERSION}) diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash index 22d1d8a39..465841a02 100755 --- a/Utilities/Scripts/update-curl.bash +++ b/Utilities/Scripts/update-curl.bash @@ -8,7 +8,7 @@ readonly name="curl" readonly ownership="Curl Upstream " readonly subtree="Utilities/cmcurl" readonly repo="https://github.com/curl/curl.git" -readonly tag="curl-7_51_0" +readonly tag="curl-7_54_1" readonly shortlog=false readonly paths=" CMake/* @@ -32,6 +32,7 @@ extract_source () { git_archive pushd "${extractdir}/${name}-reduced" rm lib/config-*.h + echo "* -whitespace" > .gitattributes popd } diff --git a/Utilities/Scripts/update-expat.bash b/Utilities/Scripts/update-expat.bash index 8a2a5fe4f..4cc864609 100755 --- a/Utilities/Scripts/update-expat.bash +++ b/Utilities/Scripts/update-expat.bash @@ -7,8 +7,8 @@ shopt -s dotglob readonly name="expat" readonly ownership="Expat Upstream " readonly subtree="Utilities/cmexpat" -readonly repo="http://git.code.sf.net/p/expat/code_git" -readonly tag="master" +readonly repo="https://github.com/libexpat/libexpat.git" +readonly tag="R_2_2_1" readonly shortlog=false readonly paths=" expat/lib/asciitab.h @@ -22,6 +22,7 @@ readonly paths=" expat/lib/utf8tab.h expat/lib/nametab.h expat/lib/ascii.h + expat/lib/siphash.h expat/lib/xmltok_impl.h expat/lib/xmltok_ns.c expat/lib/winconfig.h diff --git a/Utilities/Scripts/update-kwsys.bash b/Utilities/Scripts/update-kwsys.bash index 83da8a40e..dfbd3666b 100755 --- a/Utilities/Scripts/update-kwsys.bash +++ b/Utilities/Scripts/update-kwsys.bash @@ -15,6 +15,8 @@ readonly paths=" extract_source () { git_archive + sed -i -e '/import off/,/import on/d' "$extractdir/$name-reduced/.gitattributes" + sed -i -e 's/project=KWSys/project=PublicDashboard/' "$extractdir/$name-reduced/CTestConfig.cmake" } export HOOKS_ALLOW_KWSYS=1 diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash index 3b422692d..41c6a66d6 100755 --- a/Utilities/Scripts/update-libarchive.bash +++ b/Utilities/Scripts/update-libarchive.bash @@ -8,7 +8,7 @@ readonly name="LibArchive" readonly ownership="LibArchive Upstream " readonly subtree="Utilities/cmlibarchive" readonly repo="https://github.com/libarchive/libarchive.git" -readonly tag="master" +readonly tag="v3.3.1" readonly shortlog=false readonly paths=" CMakeLists.txt diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash index 3b8358e01..670946ef4 100644 --- a/Utilities/Scripts/update-third-party.bash +++ b/Utilities/Scripts/update-third-party.bash @@ -52,6 +52,14 @@ git_archive () { tar -C "$extractdir" -x } +disable_custom_gitattributes() { + pushd "${extractdir}/${name}-reduced" + # Git does not allow custom attributes in a subdirectory where we + # are about to merge the `.gitattributes` file, so disable them. + sed -i '/^\[attr\]/ {s/^/#/}' .gitattributes + popd +} + die () { echo >&2 "$@" exit 1 diff --git a/Utilities/SetupForDevelopment.sh b/Utilities/SetupForDevelopment.sh index 39152bcc4..ff64a8402 100755 --- a/Utilities/SetupForDevelopment.sh +++ b/Utilities/SetupForDevelopment.sh @@ -3,9 +3,6 @@ cd "${BASH_SOURCE%/*}/.." && Utilities/GitSetup/setup-user && echo && Utilities/GitSetup/setup-hooks && echo && -Utilities/GitSetup/setup-stage && echo && -(Utilities/GitSetup/setup-ssh || - echo 'Failed to setup SSH. Run this again to retry.') && echo && Utilities/GitSetup/tips # Rebase master by default @@ -13,5 +10,5 @@ git config rebase.stat true git config branch.master.rebase true # Record the version of this setup so Git/pre-commit can check it. -SetupForDevelopment_VERSION=1 +SetupForDevelopment_VERSION=2 git config hooks.SetupForDevelopment ${SetupForDevelopment_VERSION} diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index edb9469d3..a29380c95 100644 --- a/Utilities/Sphinx/CMakeLists.txt +++ b/Utilities/Sphinx/CMakeLists.txt @@ -128,18 +128,20 @@ endforeach() add_custom_target(documentation ALL DEPENDS ${doc_format_outputs}) -foreach(t - cmake - ccmake - cmake-gui - cpack - ctest - ) - if(TARGET ${t}) - # Build documentation after main executables. - add_dependencies(documentation ${t}) - endif() -endforeach() +if(CMake_SPHINX_DEPEND_ON_EXECUTABLES) + foreach(t + cmake + ccmake + cmake-gui + cpack + ctest + ) + if(TARGET ${t}) + # Build documentation after main executables. + add_dependencies(documentation ${t}) + endif() + endforeach() +endif() if(SPHINX_MAN) file(GLOB man_rst RELATIVE ${CMake_SOURCE_DIR}/Help/manual diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in index 958145863..7878ad20a 100644 --- a/Utilities/Sphinx/conf.py.in +++ b/Utilities/Sphinx/conf.py.in @@ -18,7 +18,9 @@ release = '@conf_release@' # full version string primary_domain = 'cmake' -exclude_patterns = [] +exclude_patterns = [ + 'dev', # ignore developer-only documentation + ] extensions = ['cmake'] templates_path = ['@conf_path@/templates'] @@ -52,6 +54,26 @@ html_show_sourcelink = True html_static_path = ['@conf_path@/static'] html_style = 'cmake.css' html_theme = 'default' +html_theme_options = { + 'footerbgcolor': '#00182d', + 'footertextcolor': '#ffffff', + 'sidebarbgcolor': '#e4ece8', + 'sidebarbtncolor': '#00a94f', + 'sidebartextcolor': '#333333', + 'sidebarlinkcolor': '#00a94f', + 'relbarbgcolor': '#00529b', + 'relbartextcolor': '#ffffff', + 'relbarlinkcolor': '#ffffff', + 'bgcolor': '#ffffff', + 'textcolor': '#444444', + 'headbgcolor': '#f2f2f2', + 'headtextcolor': '#003564', + 'headlinkcolor': '#3d8ff2', + 'linkcolor': '#2b63a8', + 'visitedlinkcolor': '#2b63a8', + 'codebgcolor': '#eeeeee', + 'codetextcolor': '#333333', +} html_title = 'CMake %s Documentation' % release html_short_title = '%s Documentation' % release html_favicon = '@conf_path@/static/cmake-favicon.ico' diff --git a/Utilities/Sphinx/templates/layout.html b/Utilities/Sphinx/templates/layout.html index 177e04455..be2660caa 100644 --- a/Utilities/Sphinx/templates/layout.html +++ b/Utilities/Sphinx/templates/layout.html @@ -8,10 +8,22 @@ CMake{{ reldelim1 }}
  • + {%- if versionswitch is defined %} + {{ release }} + {% trans %}Documentation{% endtrans %}{{ reldelim1 }} + {%- else %} {{ shorttitle|e }}{{ reldelim1 }} + {%- endif %}
  • {% endblock %} +{% block extrahead %} + {% if versionswitch is defined %} + + {% endif %} +{{ super() }} +{% endblock %} + {# Put some context in the html title element. Workaround for #} {# https://bitbucket.org/birkenfeld/sphinx/issue/1492/qthelp-generate-html-title-element-should #} {% block htmltitle %} diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c index ceff39151..bc36c8ef7 100644 --- a/Utilities/cmcurl/CMake/CurlTests.c +++ b/Utilities/cmcurl/CMake/CurlTests.c @@ -533,3 +533,19 @@ main () { return 0; } #endif +#ifdef HAVE_FSETXATTR_6 +#include /* header from libc, not from libattr */ +int +main() { + fsetxattr(0, 0, 0, 0, 0, 0); + return 0; +} +#endif +#ifdef HAVE_FSETXATTR_5 +#include /* header from libc, not from libattr */ +int +main() { + fsetxattr(0, 0, 0, 0, 0); + return 0; +} +#endif diff --git a/Utilities/cmcurl/CMake/FindGSS.cmake b/Utilities/cmcurl/CMake/FindGSS.cmake index dfaeaf307..60dcb73c9 100644 --- a/Utilities/cmcurl/CMake/FindGSS.cmake +++ b/Utilities/cmcurl/CMake/FindGSS.cmake @@ -12,7 +12,7 @@ # GSS_LINKER_FLAGS - Additional linker flags # GSS_COMPILER_FLAGS - Additional compiler flags # GSS_VERSION - This is set to version advertised by pkg-config or read from manifest. -# In case the library is found but no version info availabe it'll be set to "unknown" +# In case the library is found but no version info available it'll be set to "unknown" set(_MIT_MODNAME mit-krb5-gssapi) set(_HEIMDAL_MODNAME heimdal-gssapi) diff --git a/Utilities/cmcurl/CMake/FindMbedTLS.cmake b/Utilities/cmcurl/CMake/FindMbedTLS.cmake new file mode 100644 index 000000000..a91639589 --- /dev/null +++ b/Utilities/cmcurl/CMake/FindMbedTLS.cmake @@ -0,0 +1,13 @@ +find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) + +find_library(MBEDTLS_LIBRARY mbedtls) +find_library(MBEDX509_LIBRARY mbedx509) +find_library(MBEDCRYPTO_LIBRARY mbedcrypto) + +set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MBEDTLS DEFAULT_MSG + MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) + +mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake index d59949871..3b203c538 100644 --- a/Utilities/cmcurl/CMake/OtherTests.cmake +++ b/Utilities/cmcurl/CMake/OtherTests.cmake @@ -179,17 +179,20 @@ int main(void) { include(CheckCSourceRuns) -set(CMAKE_REQUIRED_FLAGS) -if(HAVE_SYS_POLL_H) - set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H") -endif(HAVE_SYS_POLL_H) -check_c_source_runs(" - #ifdef HAVE_SYS_POLL_H - # include - #endif - int main(void) { - return poll((void *)0, 0, 10 /*ms*/); - }" HAVE_POLL_FINE) +# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS +if(NOT APPLE) + set(CMAKE_REQUIRED_FLAGS) + if(HAVE_SYS_POLL_H) + set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H") + endif(HAVE_SYS_POLL_H) + check_c_source_runs(" + #ifdef HAVE_SYS_POLL_H + # include + #endif + int main(void) { + return poll((void *)0, 0, 10 /*ms*/); + }" HAVE_POLL_FINE) +endif() set(HAVE_SIG_ATOMIC_T 1) set(CMAKE_REQUIRED_FLAGS) diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake index 37cdfe3bf..8b6276df6 100644 --- a/Utilities/cmcurl/CMake/Utilities.cmake +++ b/Utilities/cmcurl/CMake/Utilities.cmake @@ -29,3 +29,16 @@ function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL) set(${RETVAL} TRUE PARENT_SCOPE) endif() endfunction() + +# Returns a list of arguments that evaluate to true +function(collect_true output_var output_count_var) + set(${output_var}) + foreach(option_var IN LISTS ARGN) + if(${option_var}) + list(APPEND ${output_var} ${option_var}) + endif() + endforeach() + set(${output_var} ${${output_var}} PARENT_SCOPE) + list(LENGTH ${output_var} ${output_count_var}) + set(${output_count_var} ${${output_count_var}} PARENT_SCOPE) +endfunction() diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index 262554d1f..d85f366c0 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -34,6 +34,29 @@ set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS look 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(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP") +if(CMAKE_USE_OPENSSL) +elseif(WIN32) + set(CMAKE_USE_WINSSL ON CACHE INTERNAL "enable Windows native SSL/TLS") + set(CURL_WINDOWS_SSPI ON CACHE INTERNAL "Use windows libraries to allow NTLM authentication without openssl") +elseif(APPLE) + # Use OS X SSL/TLS native implementation if available on target version. + if(CMAKE_OSX_DEPLOYMENT_TARGET) + set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET}) + else() + execute_process( + COMMAND sw_vers -productVersion + OUTPUT_VARIABLE OSX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + if(NOT OSX_VERSION VERSION_LESS 10.6 AND + CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang") + set(CMAKE_USE_DARWINSSL ON CACHE INTERNAL "enable Apple OS native SSL/TLS") + else() + set(CMAKE_USE_DARWINSSL OFF CACHE INTERNAL "enable Apple OS native SSL/TLS") + endif() +endif() +set(CMAKE_USE_MBEDTLS OFF CACHE INTERNAL "Enable mbedTLS for SSL/TLS") # Windows Vista and above have inet_pton, but this will link on # older versions and then the executable will fail to launch at @@ -291,6 +314,11 @@ if(ENABLE_MANUAL) endif() endif() +if(0) # This code not needed for building within CMake. +# Required for building manual, docs, tests +find_package(Perl REQUIRED) +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}) @@ -316,7 +344,7 @@ include (CheckCSourceCompiles) # On windows preload settings if(WIN32) - set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_") + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=") include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake) endif(WIN32) @@ -367,62 +395,101 @@ if(WIN32) check_library_exists_concat("winmm" getch HAVE_LIBWINMM) endif() -set(USE_OPENSSL OFF) -set(HAVE_LIBCRYPTO OFF) -set(HAVE_LIBSSL OFF) +# check SSL libraries +# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL -if(CMAKE_USE_OPENSSL) - find_package(OpenSSL) - if(OPENSSL_FOUND) - list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES}) - set(USE_OPENSSL ON) - set(HAVE_LIBCRYPTO ON) - set(HAVE_LIBSSL ON) - include_directories(${OPENSSL_INCLUDE_DIR}) - set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) - check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_H) - check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H) - check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H) - check_include_file("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H) - check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H) - check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H) - check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H) - check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H) - - # Optionally build with a specific CA cert bundle. - if(CURL_CA_BUNDLE) - add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}") - endif() - # Optionally build with a specific CA cert dir. - if(CURL_CA_PATH) - add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}") - endif() +if(APPLE) + option(CMAKE_USE_DARWINSSL "enable Apple OS native SSL/TLS" OFF) +endif() +if(WIN32) + option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF) + cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON + CMAKE_USE_WINSSL OFF) +endif() +option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF) + +set(openssl_default ON) +if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS) + set(openssl_default OFF) +endif() + +collect_true(enabled_ssl_options enabled_ssl_options_count + CMAKE_USE_WINSSL + CMAKE_USE_DARWINSSL + CMAKE_USE_OPENSSL + CMAKE_USE_MBEDTLS +) +if(enabled_ssl_options_count GREATER 1) + message(FATAL_ERROR "Multiple SSL options specified: ${enabled_ssl_options}. Please pick at most one and disable the rest.") +endif() + +if(CMAKE_USE_WINSSL) + set(SSL_ENABLED ON) + set(USE_SCHANNEL ON) # Windows native SSL/TLS support + set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI + list(APPEND CURL_LIBS "crypt32") +endif() +if(CURL_WINDOWS_SSPI) + set(USE_WINDOWS_SSPI ON) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32") +endif() + +if(CMAKE_USE_DARWINSSL) + find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation") + if(NOT COREFOUNDATION_FRAMEWORK) + message(FATAL_ERROR "CoreFoundation framework not found") endif() -elseif(WIN32) - # Use Windows SSL/TLS native implementation. - set(CURL_WINDOWS_SSPI ON) -elseif(APPLE) - # Use OS X SSL/TLS native implementation if available on target version. - if(CMAKE_OSX_DEPLOYMENT_TARGET) - set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET}) - else() - execute_process( - COMMAND sw_vers -productVersion - OUTPUT_VARIABLE OSX_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + + find_library(SECURITY_FRAMEWORK "Security") + if(NOT SECURITY_FRAMEWORK) + message(FATAL_ERROR "Security framework not found") endif() - if(NOT OSX_VERSION VERSION_LESS 10.6 AND - CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang") - add_definitions(-DUSE_DARWINSSL) - list(APPEND CURL_LIBS - "-framework CoreFoundation" - "-framework Security" - ) + + set(SSL_ENABLED ON) + set(USE_DARWINSSL ON) + list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}") +endif() + +if(CMAKE_USE_OPENSSL) + find_package(OpenSSL REQUIRED) + set(SSL_ENABLED ON) + set(USE_OPENSSL ON) + set(HAVE_LIBCRYPTO ON) + set(HAVE_LIBSSL ON) + list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES}) + include_directories(${OPENSSL_INCLUDE_DIR}) + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) + check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) + check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_H) + check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H) + check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H) + check_include_file("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H) + check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H) + check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H) + check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H) + check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H) + check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS) + check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN) + check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD) + + # Optionally build with a specific CA cert bundle. + if(CURL_CA_BUNDLE) + add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}") + endif() + # Optionally build with a specific CA cert dir. + if(CURL_CA_PATH) + add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}") endif() endif() +if(CMAKE_USE_MBEDTLS) + find_package(MbedTLS REQUIRED) + set(SSL_ENABLED ON) + set(USE_MBEDTLS ON) + list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES}) + include_directories(${MBEDTLS_INCLUDE_DIRS}) +endif() + option(USE_NGHTTP2 "Use Nghttp2 library" OFF) if(USE_NGHTTP2) find_package(NGHTTP2 REQUIRED) @@ -675,24 +742,88 @@ else() endif() +if(0) # This code not needed for building within CMake. +# +# CA handling +# +set(CURL_CA_BUNDLE "auto" CACHE STRING + "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") +set(CURL_CA_FALLBACK OFF CACHE BOOL + "Set ON to use built-in CA store of TLS backend. Defaults to OFF") +set(CURL_CA_PATH "auto" CACHE STRING + "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") + +if("${CURL_CA_BUNDLE}" STREQUAL "") + message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.") +elseif("${CURL_CA_BUNDLE}" STREQUAL "none") + unset(CURL_CA_BUNDLE CACHE) +elseif("${CURL_CA_BUNDLE}" STREQUAL "auto") + unset(CURL_CA_BUNDLE CACHE) + set(CURL_CA_BUNDLE_AUTODETECT TRUE) +else() + set(CURL_CA_BUNDLE_SET TRUE) +endif() + +if("${CURL_CA_PATH}" STREQUAL "") + message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.") +elseif("${CURL_CA_PATH}" STREQUAL "none") + unset(CURL_CA_PATH CACHE) +elseif("${CURL_CA_PATH}" STREQUAL "auto") + unset(CURL_CA_PATH CACHE) + set(CURL_CA_PATH_AUTODETECT TRUE) +else() + set(CURL_CA_PATH_SET TRUE) +endif() + +if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT) + # Skip autodetection of unset CA path because CA bundle is set explicitly +elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT) + # Skip autodetection of unset CA bundle because CA path is set explicitly +elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT) + # first try autodetecting a CA bundle, then a CA path + + if(CURL_CA_BUNDLE_AUTODETECT) + set(SEARCH_CA_BUNDLE_PATHS + /etc/ssl/certs/ca-certificates.crt + /etc/pki/tls/certs/ca-bundle.crt + /usr/share/ssl/certs/ca-bundle.crt + /usr/local/share/certs/ca-root-nss.crt + /etc/ssl/cert.pem) + + foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS}) + if(EXISTS "${SEARCH_CA_BUNDLE_PATH}") + message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}") + set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}") + set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set") + break() + endif() + endforeach() + endif() + + if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET)) + if(EXISTS "/etc/ssl/certs") + set(CURL_CA_PATH "/etc/ssl/certs") + set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set") + endif() + endif() +endif() + +if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS) + message(FATAL_ERROR + "CA path only supported by OpenSSL, GnuTLS or mbed TLS. " + "Set CURL_CA_PATH=none or enable one of those TLS backends.") +endif() +endif() + + # Check for header files if(NOT UNIX) check_include_file_concat("windows.h" HAVE_WINDOWS_H) check_include_file_concat("winsock.h" HAVE_WINSOCK_H) check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) - if(CURL_WINDOWS_SSPI) - set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32") - check_include_file_concat("sspi.h" HAVE_SSPI_H) - if(HAVE_SSPI_H) - check_include_file_concat("schannel.h" HAVE_SCHANNEL_H) - set(USE_WINDOWS_SSPI ON) - if(HAVE_SCHANNEL_H) - set(USE_SCHANNEL ON) - set(SSL_ENABLED ON) - set(CURL_LIBS ${CURL_LIBS} "crypt32") - endif() - endif() + if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL) + set(CURL_LIBS ${CURL_LIBS} "crypt32") endif() else() set(HAVE_WINDOWS_H 0) @@ -717,6 +848,7 @@ check_include_file_concat("sys/types.h" HAVE_SYS_TYPES_H) check_include_file_concat("sys/uio.h" HAVE_SYS_UIO_H) check_include_file_concat("sys/un.h" HAVE_SYS_UN_H) check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H) +check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H) check_include_file_concat("alloca.h" HAVE_ALLOCA_H) check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H) check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H) @@ -797,11 +929,17 @@ if(HAVE_LIBWS2_32) set(CMAKE_REQUIRED_LIBRARIES ws2_32) elseif(HAVE_LIBSOCKET) set(CMAKE_REQUIRED_LIBRARIES socket) +elseif(HAVE_LIBNETWORK) + set(CMAKE_REQUIRED_LIBRARIES network) endif() check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) -check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) +# poll on macOS is unreliable, it first did not exist, then was broken until +# fixed in 10.9 only to break again in 10.12. +if(NOT APPLE) + check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) +endif() check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT) check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP) check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR) @@ -833,14 +971,6 @@ check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT) check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID) check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID) check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME) -if(CMAKE_USE_OPENSSL) - check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS) - check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN) - check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD) - if(HAVE_LIBCRYPTO AND HAVE_LIBSSL) - set(USE_OPENSSL 1) - endif(HAVE_LIBCRYPTO AND HAVE_LIBSSL) -endif(CMAKE_USE_OPENSSL) check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R) check_symbol_exists(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R) @@ -875,6 +1005,13 @@ check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT) # symbol exists in win32, but function does not. check_function_exists(inet_pton HAVE_INET_PTON) +check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR) +if(HAVE_FSETXATTR) + foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6) + curl_internal_test_run(${CURL_TEST}) + endforeach(CURL_TEST) +endif(HAVE_FSETXATTR) + # sigaction and sigsetjmp are special. Use special mechanism for # detecting those, but only if previous attempt failed. if(HAVE_SIGNAL_H) @@ -1088,9 +1225,9 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE) string(REPLACE "$(top_srcdir)" "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) - string(REGEX REPLACE "\\\\\n" "§!§" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REGEX REPLACE "\\\\\n" "!Ï€!α!" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) - string(REPLACE "§!§" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REPLACE "!Ï€!α!" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace $() with ${} string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace @@ with ${}, even if that may not be read by CMake scripts. @@ -1098,6 +1235,9 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE) endfunction() +if(0) # This code not needed for building within CMake. +add_subdirectory(docs) +endif() add_subdirectory(lib) if(BUILD_CURL_EXE) add_subdirectory(src) @@ -1121,11 +1261,6 @@ if(BUILD_TESTING) add_subdirectory(tests) endif() -# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL, WINSSL, DARWINSSL -if(USE_OPENSSL) - set(SSL_ENABLED 1) -endif() - # Helper to populate a list (_items) with a label when conditions (the remaining # args) are satisfied function(_add_if label) @@ -1139,6 +1274,8 @@ endfunction() set(_items) _add_if("WinSSL" SSL_ENABLED AND USE_WINDOWS_SSPI) _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) +_add_if("DarwinSSL" SSL_ENABLED AND USE_DARWINSSL) +_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS) _add_if("IPv6" ENABLE_IPV6) _add_if("unix-sockets" USE_UNIX_SOCKETS) _add_if("libz" HAVE_LIBZ) @@ -1155,9 +1292,8 @@ _add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND _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, DARWINSSL -if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR - USE_WINDOWS_SSPI OR GNUTLS_ENABLED OR NSS_ENABLED OR DARWINSSL_ENABLED)) +# 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)) _add_if("NTLM" 1) # TODO missing option (autoconf: --enable-ntlm-wb) _add_if("NTLM_WB" NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) @@ -1206,8 +1342,6 @@ set(CC "${CMAKE_C_COMPILER}") set(CONFIGURE_OPTIONS "") # TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB? set(CPPFLAG_CURL_STATICLIB "") -# TODO need to set this (see CURL_CHECK_CA_BUNDLE in acinclude.m4) -set(CURL_CA_BUNDLE "") set(CURLVERSION "${CURL_VERSION}") set(ENABLE_SHARED "yes") if(CURL_STATICLIB) diff --git a/Utilities/cmcurl/COPYING b/Utilities/cmcurl/COPYING index a98663e94..1e45a5e2c 100644 --- a/Utilities/cmcurl/COPYING +++ b/Utilities/cmcurl/COPYING @@ -1,6 +1,6 @@ COPYRIGHT AND PERMISSION NOTICE -Copyright (c) 1996 - 2016, Daniel Stenberg, , and many +Copyright (c) 1996 - 2017, Daniel Stenberg, , 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 aa1034b86..395521202 100644 --- a/Utilities/cmcurl/include/curl/curl.h +++ b/Utilities/cmcurl/include/curl/curl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,6 +35,7 @@ #endif #include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ #include "cmcurl/include/curl/curlbuild.h" /* libcurl build definitions */ #include "curlrules.h" /* libcurl rules enforcement */ @@ -143,7 +144,7 @@ struct curl_httppost { char *buffer; /* pointer to allocated buffer contents */ long bufferlength; /* length of buffer field */ char *contenttype; /* Content-Type */ - struct curl_slist* contentheader; /* list of extra headers for this form */ + struct curl_slist *contentheader; /* list of extra headers for this form */ struct curl_httppost *more; /* if one field name has more than one file, this link should link to following files */ @@ -193,6 +194,11 @@ typedef int (*curl_xferinfo_callback)(void *clientp, curl_off_t ultotal, curl_off_t ulnow); +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + #ifndef CURL_MAX_WRITE_SIZE /* Tests have proven that 20K is a very bad buffer size for uploads on Windows, while 16K for some odd reason performed a lot better. @@ -270,7 +276,7 @@ struct curl_fileinfo { unsigned int flags; /* used internally */ - char * b_data; + char *b_data; size_t b_size; size_t b_used; }; @@ -479,7 +485,7 @@ typedef enum { CURLE_LDAP_CANNOT_BIND, /* 38 */ CURLE_LDAP_SEARCH_FAILED, /* 39 */ CURLE_OBSOLETE40, /* 40 - NOT USED */ - CURLE_FUNCTION_NOT_FOUND, /* 41 */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ CURLE_ABORTED_BY_CALLBACK, /* 42 */ CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ CURLE_OBSOLETE44, /* 44 - NOT USED */ @@ -640,6 +646,7 @@ typedef enum { CONNECT HTTP/1.1 */ CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already in 7.10 */ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ @@ -1206,7 +1213,8 @@ typedef enum { CINIT(SHARE, OBJECTPOINT, 100), /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), - CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ CINIT(PROXYTYPE, LONG, 101), /* Set the Accept-Encoding string. Use this to tell a server you would like @@ -1593,7 +1601,7 @@ typedef enum { CINIT(DNS_SERVERS, STRINGPOINT, 211), /* Time-out accept operations (currently for FTP only) after this amount - of miliseconds. */ + of milliseconds. */ CINIT(ACCEPTTIMEOUT_MS, LONG, 212), /* Set TCP keepalive */ @@ -1704,6 +1712,76 @@ typedef enum { * HTTP status code >= 300 */ CINIT(KEEP_SENDING_ON_ERROR, LONG, 245), + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAINFO, STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAPATH, STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CINIT(PROXY_SSL_VERIFYPEER, LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CINIT(PROXY_SSL_VERIFYHOST, LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CINIT(PROXY_SSLVERSION, LONG, 250), + + /* Set a username for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CINIT(PROXY_SSLCERT, STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CINIT(PROXY_SSLKEY, STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259), + + /* CRL file for proxy */ + CINIT(PROXY_CRLFILE, STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CINIT(PROXY_SSL_OPTIONS, LONG, 261), + + /* Name of pre proxy to use. */ + CINIT(PRE_PROXY, STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -1805,10 +1883,23 @@ enum { CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1, CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, CURL_SSLVERSION_LAST /* never use, keep last */ }; +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + enum CURL_TLSAUTH { CURL_TLSAUTH_NONE, CURL_TLSAUTH_SRP, @@ -1839,7 +1930,10 @@ typedef enum { /* curl_strequal() and curl_strnequal() are subject for removal in a future - libcurl, see lib/README.curlx for details */ + libcurl, see lib/README.curlx for details + + !checksrc! disable SPACEBEFOREPAREN 2 +*/ CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2); CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n); @@ -2157,6 +2251,7 @@ struct curl_tlssessioninfo { #define CURLINFO_LONG 0x200000 #define CURLINFO_DOUBLE 0x300000 #define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ #define CURLINFO_SOCKET 0x500000 #define CURLINFO_MASK 0x0fffff #define CURLINFO_TYPEMASK 0xf00000 @@ -2196,7 +2291,7 @@ typedef enum { CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, - CURLINFO_CERTINFO = CURLINFO_SLIST + 34, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, @@ -2205,13 +2300,16 @@ typedef enum { CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, - CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, - CURLINFO_TLS_SSL_PTR = CURLINFO_SLIST + 45, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, /* Fill in new entries below here! */ - CURLINFO_LASTONE = 46 + CURLINFO_LASTONE = 49 } CURLINFO; /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as @@ -2365,13 +2463,14 @@ typedef struct { #define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ #define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ #define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper - is suported */ + is supported */ #define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ #define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ #define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ #define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ #define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ /* * NAME curl_version_info() diff --git a/Utilities/cmcurl/include/curl/curlrules.h b/Utilities/cmcurl/include/curl/curlrules.h index 55d21f68f..0abd9f71d 100644 --- a/Utilities/cmcurl/include/curl/curlrules.h +++ b/Utilities/cmcurl/include/curl/curlrules.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -105,11 +105,6 @@ Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing #endif -#ifndef CURL_FORMAT_OFF_T -# error "CURL_FORMAT_OFF_T definition is missing!" - Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing -#endif - #ifndef CURL_SIZEOF_CURL_OFF_T # error "CURL_SIZEOF_CURL_OFF_T definition is missing!" Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing @@ -241,22 +236,4 @@ typedef char #undef CurlchkszEQ #undef CurlchkszGE -/* - * Get rid of macros not intended to exist beyond this point. - */ - -#undef CURL_PULL_WS2TCPIP_H -#undef CURL_PULL_SYS_TYPES_H -#undef CURL_PULL_SYS_SOCKET_H -#undef CURL_PULL_SYS_POLL_H -#undef CURL_PULL_STDINT_H -#undef CURL_PULL_INTTYPES_H - -#undef CURL_TYPEOF_CURL_SOCKLEN_T -#undef CURL_TYPEOF_CURL_OFF_T - -#ifdef CURL_NO_OLDIES -#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */ -#endif - #endif /* __CURL_CURLRULES_H */ diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h index 2415d1ab2..667b7eb13 100644 --- a/Utilities/cmcurl/include/curl/curlver.h +++ b/Utilities/cmcurl/include/curl/curlver.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,17 +26,17 @@ a script at release-time. This was made its own header file in 7.11.2 */ /* This is the global package copyright */ -#define LIBCURL_COPYRIGHT "1996 - 2016 Daniel Stenberg, ." +#define LIBCURL_COPYRIGHT "1996 - 2017 Daniel Stenberg, ." /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "7.51.0" +#define LIBCURL_VERSION "7.54.1" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 51 -#define LIBCURL_VERSION_PATCH 0 +#define LIBCURL_VERSION_MINOR 54 +#define LIBCURL_VERSION_PATCH 1 /* This is the numeric version of the libcurl version number, meant for easier parsing and comparions by programs. The LIBCURL_VERSION_NUM define will @@ -57,18 +57,18 @@ 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 0x073300 +#define LIBCURL_VERSION_NUM 0x073601 /* * This is the date and time when the full source package was created. The * timestamp is not stored in git, as the timestamp is properly set in the * tarballs by the maketgz script. * - * The format of the date should follow this template: + * The format of the date follows this template: * - * "Mon Feb 12 11:35:33 UTC 2007" + * "2007-11-23" */ -#define LIBCURL_TIMESTAMP "DEV" +#define LIBCURL_TIMESTAMP "[unreleased]" #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z) #define CURL_AT_LEAST_VERSION(x,y,z) \ diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h index afc766cd2..752c5049f 100644 --- a/Utilities/cmcurl/include/curl/easy.h +++ b/Utilities/cmcurl/include/curl/easy.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -58,7 +58,7 @@ CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); * curl_easy_duphandle() for each new thread to avoid a series of identical * curl_easy_setopt() invokes in every thread. */ -CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); /* * NAME curl_easy_reset() diff --git a/Utilities/cmcurl/include/curl/stdcheaders.h b/Utilities/cmcurl/include/curl/stdcheaders.h index 6f0f7f343..027b6f421 100644 --- a/Utilities/cmcurl/include/curl/stdcheaders.h +++ b/Utilities/cmcurl/include/curl/stdcheaders.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,8 +24,8 @@ #include -size_t fread (void *, size_t, size_t, FILE *); -size_t fwrite (const void *, size_t, size_t, FILE *); +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); int strcasecmp(const char *, const char *); int strncasecmp(const char *, const char *, size_t); diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h new file mode 100644 index 000000000..ed3a55c95 --- /dev/null +++ b/Utilities/cmcurl/include/curl/system.h @@ -0,0 +1,484 @@ +#ifndef __CURL_SYSTEM_H +#define __CURL_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , 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. + * + ***************************************************************************/ + +/* + * This header is supposed to eventually replace curlbuild.h. This little one + * is still learning. During the experimental phase, this header files + * defines symbols using the prefixes CURLSYS_ or curlsys_. When we feel + * confident enough, we replace curlbuild.h with this file and rename all + * prefixes to CURL_ and curl_. + */ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# else +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__SALFORDC__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# else +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T __int64 +# define CURLSYS_FORMAT_CURL_OFF_T "I64d" +# define CURLSYS_FORMAT_CURL_OFF_TU "I64u" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T i64 +# define CURLSYS_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__TURBOC__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T __int64 +# define CURLSYS_FORMAT_CURL_OFF_T "I64d" +# define CURLSYS_FORMAT_CURL_OFF_TU "I64u" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T i64 +# define CURLSYS_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T __int64 +# define CURLSYS_FORMAT_CURL_OFF_T "I64d" +# define CURLSYS_FORMAT_CURL_OFF_TU "I64u" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T i64 +# define CURLSYS_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__LCC__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T __int64 +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T unsigned int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__MWERKS__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(_WIN32_WCE) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T __int64 +# define CURLSYS_FORMAT_CURL_OFF_T "I64d" +# define CURLSYS_FORMAT_CURL_OFF_TU "I64u" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T i64 +# define CURLSYS_SUFFIX_CURL_OFF_TU ui64 +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__MINGW32__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "I64d" +# define CURLSYS_FORMAT_CURL_OFF_TU "I64u" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 +# define CURLSYS_PULL_SYS_TYPES_H 1 +# define CURLSYS_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# else +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T unsigned int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 +# define CURLSYS_PULL_SYS_TYPES_H 1 +# define CURLSYS_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# define CURLSYS_SIZEOF_LONG 4 +# elif defined(_LP64) +# define CURLSYS_SIZEOF_LONG 8 +# endif +# if defined(_LONG_LONG) +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# else +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 +# define CURLSYS_PULL_SYS_TYPES_H 1 +# define CURLSYS_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# define CURLSYS_SIZEOF_LONG 4 +# elif defined(_LP64) +# define CURLSYS_SIZEOF_LONG 8 +# endif +# if defined(_LONG_LONG) +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# else +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 +# define CURLSYS_PULL_SYS_TYPES_H 1 +# define CURLSYS_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURLSYS_SIZEOF_LONG 8 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +#elif defined(__TINYC__) /* also known as tcc */ + +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURLSYS_PULL_SYS_TYPES_H 1 +# define CURLSYS_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T __int64 +# define CURLSYS_FORMAT_CURL_OFF_T "I64d" +# define CURLSYS_FORMAT_CURL_OFF_TU "I64u" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T i64 +# define CURLSYS_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) +# if !defined(__LP64__) && (defined(__ILP32__) || \ + defined(__i386__) || defined(__ppc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__)) +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long long +# define CURLSYS_FORMAT_CURL_OFF_T "lld" +# define CURLSYS_FORMAT_CURL_OFF_TU "llu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T LL +# define CURLSYS_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) +# define CURLSYS_SIZEOF_LONG 8 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SIZEOF_CURL_OFF_T 8 +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# endif +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 +# define CURLSYS_PULL_SYS_TYPES_H 1 +# define CURLSYS_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURLSYS_SIZEOF_LONG 4 +# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4 +# define CURLSYS_SIZEOF_CURL_OFF_T 4 +# define CURLSYS_TYPEOF_CURL_OFF_T long +# define CURLSYS_FORMAT_CURL_OFF_T "ld" +# define CURLSYS_FORMAT_CURL_OFF_TU "lu" +# define CURLSYS_SUFFIX_CURL_OFF_T L +# define CURLSYS_SUFFIX_CURL_OFF_TU UL +# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int +#endif + +/* CURLSYS_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURLSYS_PULL_WS2TCPIP_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# include +# include +#endif + +/* CURLSYS_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURLSYS_PULL_SYS_TYPES_H +# include +#endif + +/* CURLSYS_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURLSYS_PULL_SYS_SOCKET_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURLSYS_TYPEOF_CURL_SOCKLEN_T + typedef CURLSYS_TYPEOF_CURL_SOCKLEN_T curlsys_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURLSYS_TYPEOF_CURL_OFF_T + typedef CURLSYS_TYPEOF_CURL_OFF_T curlsys_off_t; +#endif + +#endif /* __CURL_SYSTEM_H */ + diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h index 6ec8bcfd4..10b5de2ab 100644 --- a/Utilities/cmcurl/include/curl/typecheck-gcc.h +++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -40,7 +40,7 @@ */ #define curl_easy_setopt(handle, option, value) \ __extension__ ({ \ - __typeof__ (option) _curl_opt = option; \ + __typeof__(option) _curl_opt = option; \ if(__builtin_constant_p(_curl_opt)) { \ if(_curl_is_long_option(_curl_opt)) \ if(!_curl_is_long(value)) \ @@ -110,7 +110,7 @@ __extension__ ({ \ /* FIXME: don't allow const pointers */ #define curl_easy_getinfo(handle, info, arg) \ __extension__ ({ \ - __typeof__ (info) _curl_info = info; \ + __typeof__(info) _curl_info = info; \ if(__builtin_constant_p(_curl_info)) { \ if(_curl_is_string_info(_curl_info)) \ if(!_curl_is_arr((arg), char *)) \ @@ -124,6 +124,15 @@ __extension__ ({ \ if(_curl_is_slist_info(_curl_info)) \ if(!_curl_is_arr((arg), struct curl_slist *)) \ _curl_easy_getinfo_err_curl_slist(); \ + if(_curl_is_tlssessioninfo_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(_curl_is_certinfo_info(_curl_info)) \ + if(!_curl_is_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(_curl_is_socket_info(_curl_info)) \ + if(!_curl_is_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ } \ curl_easy_getinfo(handle, _curl_info, arg); \ }) @@ -151,7 +160,7 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_off_t, "curl_easy_setopt expects a curl_off_t argument for this option") _CURL_WARNING(_curl_easy_setopt_err_string, "curl_easy_setopt expects a " - "string (char* or char[]) argument for this option" + "string ('char *' or char[]) argument for this option" ) _CURL_WARNING(_curl_easy_setopt_err_write_callback, "curl_easy_setopt expects a curl_write_callback argument for this option") @@ -182,24 +191,33 @@ _CURL_WARNING(_curl_easy_setopt_err_error_buffer, "curl_easy_setopt expects a " "char buffer of CURL_ERROR_SIZE as argument for this option") _CURL_WARNING(_curl_easy_setopt_err_FILE, - "curl_easy_setopt expects a FILE* argument for this option") + "curl_easy_setopt expects a 'FILE *' argument for this option") _CURL_WARNING(_curl_easy_setopt_err_postfields, - "curl_easy_setopt expects a void* or char* argument for this option") + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") _CURL_WARNING(_curl_easy_setopt_err_curl_httpost, - "curl_easy_setopt expects a struct curl_httppost* argument for this option") + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") _CURL_WARNING(_curl_easy_setopt_err_curl_slist, - "curl_easy_setopt expects a struct curl_slist* argument for this option") + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") _CURL_WARNING(_curl_easy_setopt_err_CURLSH, "curl_easy_setopt expects a CURLSH* argument for this option") _CURL_WARNING(_curl_easy_getinfo_err_string, - "curl_easy_getinfo expects a pointer to char * for this info") + "curl_easy_getinfo expects a pointer to 'char *' for this info") _CURL_WARNING(_curl_easy_getinfo_err_long, "curl_easy_getinfo expects a pointer to long for this info") _CURL_WARNING(_curl_easy_getinfo_err_double, "curl_easy_getinfo expects a pointer to double for this info") _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, - "curl_easy_getinfo expects a pointer to struct curl_slist * for this info") + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +_CURL_WARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") /* groups of curl_easy_setops options that take the same type of argument */ @@ -218,7 +236,8 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, /* evaluates to true if option takes a char* argument */ #define _curl_is_string_option(option) \ - ((option) == CURLOPT_ACCEPT_ENCODING || \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ (option) == CURLOPT_CAINFO || \ (option) == CURLOPT_CAPATH || \ (option) == CURLOPT_COOKIE || \ @@ -247,11 +266,25 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, (option) == CURLOPT_NOPROXY || \ (option) == CURLOPT_PASSWORD || \ (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ (option) == CURLOPT_PROXY || \ (option) == CURLOPT_PROXYPASSWORD || \ (option) == CURLOPT_PROXYUSERNAME || \ (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ (option) == CURLOPT_RANDOM_FILE || \ (option) == CURLOPT_RANGE || \ (option) == CURLOPT_REFERER || \ @@ -346,8 +379,19 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) /* true if info expects a pointer to struct curl_slist * argument */ -#define _curl_is_slist_info(info) \ - (CURLINFO_SLIST < (info)) +#define _curl_is_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define _curl_is_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define _curl_is_socket_info(info) \ + (CURLINFO_SOCKET < (info)) /* typecheck helpers -- check whether given expression has requested type*/ @@ -363,7 +407,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, /* XXX: should evaluate to true iff expr is a pointer */ #define _curl_is_any_ptr(expr) \ - (sizeof(expr) == sizeof(void*)) + (sizeof(expr) == sizeof(void *)) /* evaluates to true if expr is NULL */ /* XXX: must not evaluate expr, so this check is not accurate */ @@ -426,8 +470,9 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, #endif /* evaluates to true if expr is of type FILE* */ -#define _curl_is_FILE(expr) \ - (__builtin_types_compatible_p(__typeof__(expr), FILE *)) +#define _curl_is_FILE(expr) \ + (_curl_is_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) /* evaluates to true if expr can be passed as POST data (void* or char*) */ #define _curl_is_postfields(expr) \ @@ -442,102 +487,102 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, * function pointers, hide it */ #define _curl_callback_compatible(func, type) \ (__builtin_types_compatible_p(__typeof__(func), type) || \ - __builtin_types_compatible_p(__typeof__(func), type*)) + __builtin_types_compatible_p(__typeof__(func) *, type)) /* evaluates to true if expr is of type curl_read_callback or "similar" */ #define _curl_is_read_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \ + _curl_callback_compatible((expr), __typeof__(fread) *) || \ + _curl_callback_compatible((expr), curl_read_callback) || \ _curl_callback_compatible((expr), _curl_read_callback1) || \ _curl_callback_compatible((expr), _curl_read_callback2) || \ _curl_callback_compatible((expr), _curl_read_callback3) || \ _curl_callback_compatible((expr), _curl_read_callback4) || \ _curl_callback_compatible((expr), _curl_read_callback5) || \ _curl_callback_compatible((expr), _curl_read_callback6)) -typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*); -typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*); -typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*); -typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*); -typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*); -typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*); +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); /* evaluates to true if expr is of type curl_write_callback or "similar" */ #define _curl_is_write_cb(expr) \ (_curl_is_read_cb(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \ + _curl_callback_compatible((expr), __typeof__(fwrite) *) || \ + _curl_callback_compatible((expr), curl_write_callback) || \ _curl_callback_compatible((expr), _curl_write_callback1) || \ _curl_callback_compatible((expr), _curl_write_callback2) || \ _curl_callback_compatible((expr), _curl_write_callback3) || \ _curl_callback_compatible((expr), _curl_write_callback4) || \ _curl_callback_compatible((expr), _curl_write_callback5) || \ _curl_callback_compatible((expr), _curl_write_callback6)) -typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*); -typedef size_t (_curl_write_callback2)(const char *, size_t, size_t, - const void*); -typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*); -typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*); -typedef size_t (_curl_write_callback5)(const void *, size_t, size_t, - const void*); -typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*); +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ #define _curl_is_ioctl_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \ + _curl_callback_compatible((expr), curl_ioctl_callback) || \ _curl_callback_compatible((expr), _curl_ioctl_callback1) || \ _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ _curl_callback_compatible((expr), _curl_ioctl_callback4)) -typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*); -typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*); -typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*); -typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*); +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ #define _curl_is_sockopt_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \ + _curl_callback_compatible((expr), curl_sockopt_callback) || \ _curl_callback_compatible((expr), _curl_sockopt_callback1) || \ _curl_callback_compatible((expr), _curl_sockopt_callback2)) -typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); -typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t, +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, curlsocktype); /* evaluates to true if expr is of type curl_opensocket_callback or "similar" */ #define _curl_is_opensocket_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\ + _curl_callback_compatible((expr), curl_opensocket_callback) || \ _curl_callback_compatible((expr), _curl_opensocket_callback1) || \ _curl_callback_compatible((expr), _curl_opensocket_callback2) || \ _curl_callback_compatible((expr), _curl_opensocket_callback3) || \ _curl_callback_compatible((expr), _curl_opensocket_callback4)) -typedef curl_socket_t (_curl_opensocket_callback1) +typedef curl_socket_t (*_curl_opensocket_callback1) (void *, curlsocktype, struct curl_sockaddr *); -typedef curl_socket_t (_curl_opensocket_callback2) +typedef curl_socket_t (*_curl_opensocket_callback2) (void *, curlsocktype, const struct curl_sockaddr *); -typedef curl_socket_t (_curl_opensocket_callback3) +typedef curl_socket_t (*_curl_opensocket_callback3) (const void *, curlsocktype, struct curl_sockaddr *); -typedef curl_socket_t (_curl_opensocket_callback4) +typedef curl_socket_t (*_curl_opensocket_callback4) (const void *, curlsocktype, const struct curl_sockaddr *); /* evaluates to true if expr is of type curl_progress_callback or "similar" */ #define _curl_is_progress_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \ + _curl_callback_compatible((expr), curl_progress_callback) || \ _curl_callback_compatible((expr), _curl_progress_callback1) || \ _curl_callback_compatible((expr), _curl_progress_callback2)) -typedef int (_curl_progress_callback1)(void *, +typedef int (*_curl_progress_callback1)(void *, double, double, double, double); -typedef int (_curl_progress_callback2)(const void *, +typedef int (*_curl_progress_callback2)(const void *, double, double, double, double); /* evaluates to true if expr is of type curl_debug_callback or "similar" */ #define _curl_is_debug_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \ + _curl_callback_compatible((expr), curl_debug_callback) || \ _curl_callback_compatible((expr), _curl_debug_callback1) || \ _curl_callback_compatible((expr), _curl_debug_callback2) || \ _curl_callback_compatible((expr), _curl_debug_callback3) || \ @@ -546,28 +591,28 @@ typedef int (_curl_progress_callback2)(const void *, _curl_callback_compatible((expr), _curl_debug_callback6) || \ _curl_callback_compatible((expr), _curl_debug_callback7) || \ _curl_callback_compatible((expr), _curl_debug_callback8)) -typedef int (_curl_debug_callback1) (CURL *, +typedef int (*_curl_debug_callback1) (CURL *, curl_infotype, char *, size_t, void *); -typedef int (_curl_debug_callback2) (CURL *, +typedef int (*_curl_debug_callback2) (CURL *, curl_infotype, char *, size_t, const void *); -typedef int (_curl_debug_callback3) (CURL *, +typedef int (*_curl_debug_callback3) (CURL *, curl_infotype, const char *, size_t, void *); -typedef int (_curl_debug_callback4) (CURL *, +typedef int (*_curl_debug_callback4) (CURL *, curl_infotype, const char *, size_t, const void *); -typedef int (_curl_debug_callback5) (CURL *, +typedef int (*_curl_debug_callback5) (CURL *, curl_infotype, unsigned char *, size_t, void *); -typedef int (_curl_debug_callback6) (CURL *, +typedef int (*_curl_debug_callback6) (CURL *, curl_infotype, unsigned char *, size_t, const void *); -typedef int (_curl_debug_callback7) (CURL *, +typedef int (*_curl_debug_callback7) (CURL *, curl_infotype, const unsigned char *, size_t, void *); -typedef int (_curl_debug_callback8) (CURL *, +typedef int (*_curl_debug_callback8) (CURL *, curl_infotype, const unsigned char *, size_t, const void *); /* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ /* this is getting even messier... */ #define _curl_is_ssl_ctx_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \ + _curl_callback_compatible((expr), curl_ssl_ctx_callback) || \ _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ @@ -576,18 +621,19 @@ typedef int (_curl_debug_callback8) (CURL *, _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ _curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) -typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *); -typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *); -typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *); -typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); #ifdef HEADER_SSL_H /* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX * this will of course break if we're included before OpenSSL headers... */ -typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); -typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); -typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); -typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, const void *); #else typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; @@ -599,7 +645,7 @@ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; /* evaluates to true if expr is of type curl_conv_callback or "similar" */ #define _curl_is_conv_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \ + _curl_callback_compatible((expr), curl_conv_callback) || \ _curl_callback_compatible((expr), _curl_conv_callback1) || \ _curl_callback_compatible((expr), _curl_conv_callback2) || \ _curl_callback_compatible((expr), _curl_conv_callback3) || \ @@ -612,7 +658,7 @@ typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); /* evaluates to true if expr is of type curl_seek_callback or "similar" */ #define _curl_is_seek_cb(expr) \ (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \ + _curl_callback_compatible((expr), curl_seek_callback) || \ _curl_callback_compatible((expr), _curl_seek_callback1) || \ _curl_callback_compatible((expr), _curl_seek_callback2)) typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc index 1328cadb0..19f58000a 100644 --- a/Utilities/cmcurl/lib/Makefile.inc +++ b/Utilities/cmcurl/lib/Makefile.inc @@ -51,7 +51,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \ openldap.c curl_gethostname.c gopher.c idn_win32.c \ http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \ - http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c \ + http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \ curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \ x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c @@ -72,7 +72,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \ curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \ x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ - curl_printf.h system_win32.h + curl_printf.h system_win32.h rand.h LIB_RCFILES = libcurl.rc diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c index 2aed94fe1..11a914f82 100644 --- a/Utilities/cmcurl/lib/asyn-ares.c +++ b/Utilities/cmcurl/lib/asyn-ares.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -169,7 +169,7 @@ int Curl_resolver_duphandle(void **to, void *from) return CURLE_OK; } -static void destroy_async_data (struct Curl_async *async); +static void destroy_async_data(struct Curl_async *async); /* * Cancel all possibly still on-going resolves for this connection. @@ -184,7 +184,7 @@ void Curl_resolver_cancel(struct connectdata *conn) /* * destroy_async_data() cleans up async resolver data. */ -static void destroy_async_data (struct Curl_async *async) +static void destroy_async_data(struct Curl_async *async) { free(async->hostname); @@ -232,7 +232,7 @@ int Curl_resolver_getsock(struct connectdata *conn, milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); if(milli == 0) milli += 10; - Curl_expire_latest(conn->data, milli); + Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME); return max; } @@ -358,14 +358,21 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, struct timeval now = Curl_tvnow(); struct Curl_dns_entry *temp_entry; + if(entry) + *entry = NULL; /* clear on entry */ + timeout = Curl_timeleft(data, &now, TRUE); + if(timeout < 0) { + /* already expired! */ + connclose(conn, "Timed out before name resolve started"); + return CURLE_OPERATION_TIMEDOUT; + } if(!timeout) timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */ /* Wait for the name resolve query to complete. */ - for(;;) { + while(!result) { struct timeval *tvp, tv, store; - long timediff; int itimeout; int timeout_ms; @@ -385,28 +392,30 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, timeout_ms = 1000; waitperform(conn, timeout_ms); - Curl_resolver_is_resolved(conn, &temp_entry); + result = Curl_resolver_is_resolved(conn, &temp_entry); - if(conn->async.done) + if(result || conn->async.done) break; - if(Curl_pgrsUpdate(conn)) { + if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; - timeout = -1; /* trigger the cancel below */ - } else { struct timeval now2 = Curl_tvnow(); - timediff = Curl_tvdiff(now2, now); /* spent time */ - timeout -= timediff?timediff:1; /* always deduct at least 1 */ + time_t timediff = Curl_tvdiff(now2, now); /* spent time */ + if(timediff <= 0) + timeout -= 1; /* always deduct at least 1 */ + else if(timediff > timeout) + timeout = -1; + else + timeout -= (long)timediff; now = now2; /* for next loop */ } - - if(timeout < 0) { - /* our timeout, so we cancel the ares operation */ - ares_cancel((ares_channel)data->state.resolver); - break; - } + if(timeout < 0) + result = CURLE_OPERATION_TIMEDOUT; } + if(result) + /* failure, so we cancel the ares operation */ + ares_cancel((ares_channel)data->state.resolver); /* Operation complete, if the lookup was successful we now have the entry in the cache. */ diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c index 7cce01aac..65fa6c5be 100644 --- a/Utilities/cmcurl/lib/asyn-thread.c +++ b/Utilities/cmcurl/lib/asyn-thread.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,6 +22,11 @@ #include "curl_setup.h" +/*********************************************************************** + * Only for threaded name resolves builds + **********************************************************************/ +#ifdef CURLRES_THREADED + #ifdef HAVE_NETINET_IN_H #include #endif @@ -74,11 +79,6 @@ #include "curl_memory.h" #include "memdebug.h" -/*********************************************************************** - * Only for threaded name resolves builds - **********************************************************************/ -#ifdef CURLRES_THREADED - /* * Curl_resolver_global_init() * Called from curl_global_init() to initialize global resolver environment. @@ -155,8 +155,8 @@ struct thread_sync_data { curl_mutex_t * mtx; int done; - char * hostname; /* hostname to resolve, Curl_async.hostname - duplicate */ + char *hostname; /* hostname to resolve, Curl_async.hostname + duplicate */ int port; int sock_error; Curl_addrinfo *res; @@ -169,7 +169,7 @@ struct thread_sync_data { struct thread_data { curl_thread_t thread_hnd; unsigned int poll_interval; - long interval_end; + time_t interval_end; struct thread_sync_data tsd; }; @@ -200,7 +200,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd) /* Initialize resolver thread synchronization data */ static int init_thread_sync_data(struct thread_data * td, - const char * hostname, + const char *hostname, int port, const struct addrinfo *hints) { @@ -263,7 +263,7 @@ static int getaddrinfo_complete(struct connectdata *conn) * For builds without ARES, but with ENABLE_IPV6, create a resolver thread * and wait on it. */ -static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) +static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) { struct thread_sync_data *tsd = (struct thread_sync_data*)arg; struct thread_data *td = tsd->td; @@ -303,7 +303,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) /* * gethostbyname_thread() resolves a name and then exits. */ -static unsigned int CURL_STDCALL gethostbyname_thread (void *arg) +static unsigned int CURL_STDCALL gethostbyname_thread(void *arg) { struct thread_sync_data *tsd = (struct thread_sync_data *)arg; struct thread_data *td = tsd->td; @@ -336,7 +336,7 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg) /* * destroy_async_data() cleans up async resolver data and thread handle. */ -static void destroy_async_data (struct Curl_async *async) +static void destroy_async_data(struct Curl_async *async) { if(async->os_specific) { struct thread_data *td = (struct thread_data*) async->os_specific; @@ -375,14 +375,14 @@ 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, - const char *hostname, int port, - const struct addrinfo *hints) +static bool init_resolve_thread(struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints) { struct thread_data *td = calloc(1, sizeof(struct thread_data)); int err = RESOLVER_ENOMEM; - conn->async.os_specific = (void*) td; + conn->async.os_specific = (void *)td; if(!td) goto err_exit; @@ -525,7 +525,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, } else { /* poll for name lookup done with exponential backoff up to 250ms */ - long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); + time_t elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); if(elapsed < 0) elapsed = 0; @@ -540,7 +540,7 @@ 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); + Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME); } return CURLE_OK; diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c index 01b1b449d..c79d22764 100644 --- a/Utilities/cmcurl/lib/conncache.c +++ b/Utilities/cmcurl/lib/conncache.c @@ -5,8 +5,8 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012, 2016, Linus Nielsen Feltzing, - * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -56,11 +56,7 @@ static CURLcode bundle_create(struct Curl_easy *data, (*cb_ptr)->num_connections = 0; (*cb_ptr)->multiuse = BUNDLE_UNKNOWN; - (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor); - if(!(*cb_ptr)->conn_list) { - Curl_safefree(*cb_ptr); - return CURLE_OUT_OF_MEMORY; - } + Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor); return CURLE_OK; } @@ -69,22 +65,18 @@ static void bundle_destroy(struct connectbundle *cb_ptr) if(!cb_ptr) return; - if(cb_ptr->conn_list) { - Curl_llist_destroy(cb_ptr->conn_list, NULL); - cb_ptr->conn_list = NULL; - } + Curl_llist_destroy(&cb_ptr->conn_list, NULL); + free(cb_ptr); } /* Add a connection to a bundle */ static CURLcode bundle_add_conn(struct connectbundle *cb_ptr, - struct connectdata *conn) + struct connectdata *conn) { - if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn)) - return CURLE_OUT_OF_MEMORY; - + Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn, + &conn->bundle_node); conn->bundle = cb_ptr; - cb_ptr->num_connections++; return CURLE_OK; } @@ -95,10 +87,10 @@ static int bundle_remove_conn(struct connectbundle *cb_ptr, { struct curl_llist_element *curr; - curr = cb_ptr->conn_list->head; + curr = cb_ptr->conn_list.head; while(curr) { if(curr->ptr == conn) { - Curl_llist_remove(cb_ptr->conn_list, curr, NULL); + Curl_llist_remove(&cb_ptr->conn_list, curr, NULL); cb_ptr->num_connections--; conn->bundle = NULL; return 1; /* we removed a handle */ @@ -127,19 +119,25 @@ void Curl_conncache_destroy(struct conncache *connc) Curl_hash_destroy(&connc->hash); } -/* returns an allocated key to find a bundle for this connection */ -static char *hashkey(struct connectdata *conn) +/* creates a key to find a bundle for this connection */ +static void hashkey(struct connectdata *conn, char *buf, + size_t len) /* something like 128 is fine */ { const char *hostname; - if(conn->bits.proxy) - hostname = conn->proxy.name; + if(conn->bits.socksproxy) + hostname = conn->socks_proxy.host.name; + else if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; else if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; else hostname = conn->host.name; - return aprintf("%s:%d", hostname, conn->port); + DEBUGASSERT(len > 32); + + /* put the number first so that the hostname gets cut off if too long */ + snprintf(buf, len, "%ld%s", conn->port, hostname); } /* Look up the bundle with all the connections to the same host this @@ -149,11 +147,9 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, { struct connectbundle *bundle = NULL; if(connc) { - char *key = hashkey(conn); - if(key) { - bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); - free(key); - } + char key[128]; + hashkey(conn, key, sizeof(key)); + bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); } return bundle; @@ -202,21 +198,16 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); if(!bundle) { - char *key; int rc; + char key[128]; result = bundle_create(data, &new_bundle); if(result) return result; - key = hashkey(conn); - if(!key) { - bundle_destroy(new_bundle); - return CURLE_OUT_OF_MEMORY; - } - + hashkey(conn, key, sizeof(key)); rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); - free(key); + if(!rc) { bundle_destroy(new_bundle); return CURLE_OUT_OF_MEMORY; @@ -290,7 +281,7 @@ void Curl_conncache_foreach(struct conncache *connc, bundle = he->ptr; he = Curl_hash_next_element(&iter); - curr = bundle->conn_list->head; + curr = bundle->conn_list.head; while(curr) { /* Yes, we need to update curr before calling func(), because func() might decide to remove the connection */ @@ -319,7 +310,7 @@ Curl_conncache_find_first_connection(struct conncache *connc) struct curl_llist_element *curr; bundle = he->ptr; - curr = bundle->conn_list->head; + curr = bundle->conn_list.head; if(curr) { return curr->ptr; } diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h index b1dadf990..f976cfdb4 100644 --- a/Utilities/cmcurl/lib/conncache.h +++ b/Utilities/cmcurl/lib/conncache.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015, Daniel Stenberg, , et al. + * Copyright (C) 2015 - 2017, Daniel Stenberg, , et al. * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, * * This software is licensed as described in the file COPYING, which @@ -38,7 +38,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 */ }; int Curl_conncache_init(struct conncache *, int size); diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c index 3df34d94a..d4fd52b99 100644 --- a/Utilities/cmcurl/lib/connect.c +++ b/Utilities/cmcurl/lib/connect.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -179,12 +179,12 @@ singleipconnect(struct connectdata *conn, * * @unittest: 1303 */ -long Curl_timeleft(struct Curl_easy *data, - struct timeval *nowp, - bool duringconnect) +time_t Curl_timeleft(struct Curl_easy *data, + struct timeval *nowp, + bool duringconnect) { int timeout_set = 0; - long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; + time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; struct timeval now; /* if a timeout is set, use the most restrictive one */ @@ -194,7 +194,7 @@ long Curl_timeleft(struct Curl_easy *data, if(duringconnect && (data->set.connecttimeout > 0)) timeout_set |= 2; - switch (timeout_set) { + switch(timeout_set) { case 1: timeout_ms = data->set.timeout; break; @@ -601,26 +601,28 @@ void Curl_persistconninfo(struct connectdata *conn) { 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; } /* retrieves ip address and port from a sockaddr structure */ -static bool getaddressinfo(struct sockaddr* sa, char* addr, - long* port) +static bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port) { unsigned short us_port; - struct sockaddr_in* si = NULL; + struct sockaddr_in *si = NULL; #ifdef ENABLE_IPV6 - struct sockaddr_in6* si6 = NULL; + struct sockaddr_in6 *si6 = NULL; #endif #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) - struct sockaddr_un* su = NULL; + struct sockaddr_un *su = NULL; #endif - switch (sa->sa_family) { + switch(sa->sa_family) { case AF_INET: - si = (struct sockaddr_in*)(void*) sa; + si = (struct sockaddr_in *)(void *) sa; if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) { us_port = ntohs(si->sin_port); @@ -630,7 +632,7 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, break; #ifdef ENABLE_IPV6 case AF_INET6: - si6 = (struct sockaddr_in6*)(void*) sa; + si6 = (struct sockaddr_in6 *)(void *) sa; if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, MAX_IPADR_LEN)) { us_port = ntohs(si6->sin6_port); @@ -722,7 +724,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, { struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; - long allow; + time_t allow; int error = 0; struct timeval now; int rc; @@ -808,8 +810,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } - else - infof(data, "Connection failed\n"); + infof(data, "Connection failed\n"); } else if(rc & CURL_CSELECT_ERR) (void)verifyconnect(conn->tempsock[i], &error); @@ -843,7 +844,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(result) { /* no more addresses to try */ - const char* hostname; + const char *hostname; /* if the first address family runs out of addresses to try before the happy eyeball timeout, go ahead and try the next family now */ @@ -853,8 +854,10 @@ CURLcode Curl_is_connected(struct connectdata *conn, return result; } - if(conn->bits.proxy) - hostname = conn->proxy.name; + if(conn->bits.socksproxy) + hostname = conn->socks_proxy.host.name; + else if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; else if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; else @@ -1067,7 +1070,7 @@ static CURLcode singleipconnect(struct connectdata *conn, conn->connecttime = Curl_tvnow(); if(conn->num_addr > 1) - Curl_expire_latest(data, conn->timeoutms_per_addr); + Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME); /* Connect TCP sockets, bind UDP */ if(!isconnected && (conn->socktype == SOCK_STREAM)) { @@ -1153,7 +1156,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct timeval before = Curl_tvnow(); CURLcode result = CURLE_COULDNT_CONNECT; - long timeout_ms = Curl_timeleft(data, &before, TRUE); + time_t timeout_ms = Curl_timeleft(data, &before, TRUE); if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ @@ -1166,7 +1169,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ conn->tempaddr[1] = NULL; conn->tempsock[0] = CURL_SOCKET_BAD; conn->tempsock[1] = CURL_SOCKET_BAD; - Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT); + Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS); /* Max time for the next connection attempt */ conn->timeoutms_per_addr = @@ -1243,24 +1246,6 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, /* only store this if the caller cares for it */ *connp = c; sockfd = c->sock[FIRSTSOCKET]; - /* we have a socket connected, let's determine if the server shut down */ - /* determine if ssl */ - if(c->ssl[FIRSTSOCKET].use) { - /* use the SSL context */ - if(!Curl_ssl_check_cxn(c)) - return CURL_SOCKET_BAD; /* FIN received */ - } -/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ -#ifdef MSG_PEEK - else if(sockfd != CURL_SOCKET_BAD) { - /* use the socket */ - char buf; - if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf, - (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { - return CURL_SOCKET_BAD; /* FIN received */ - } - } -#endif } else return CURL_SOCKET_BAD; @@ -1268,6 +1253,33 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, return sockfd; } +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn) +{ + /* First determine if ssl */ + if(conn->ssl[FIRSTSOCKET].use) { + /* use the SSL context */ + if(!Curl_ssl_check_cxn(conn)) + return false; /* FIN received */ + } +/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ +#ifdef MSG_PEEK + else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) + return false; + else { + /* use the socket */ + char buf; + if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { + return false; /* FIN received */ + } + } +#endif + return true; +} + /* * Close a socket. * @@ -1373,7 +1385,7 @@ CURLcode Curl_socket(struct connectdata *conn, */ void Curl_conncontrol(struct connectdata *conn, int ctrl /* see defines in header */ -#ifdef DEBUGBUILD +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) , const char *reason #endif ) @@ -1391,3 +1403,16 @@ void Curl_conncontrol(struct connectdata *conn, should assign this bit */ } } + +/* Data received can be cached at various levels, so check them all here. */ +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex) +{ + int readable; + + if(Curl_ssl_data_pending(conn, sockindex) || + Curl_recv_has_postponed_data(conn, sockindex)) + return true; + + readable = SOCKET_READABLE(conn->sock[sockindex], 0); + return (readable > 0 && (readable & CURL_CSELECT_IN)); +} diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h index a7cbc9bc2..44bdb1051 100644 --- a/Utilities/cmcurl/lib/connect.h +++ b/Utilities/cmcurl/lib/connect.h @@ -35,9 +35,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* generic function that returns how much time there's left to run, according to the timeouts set */ -long Curl_timeleft(struct Curl_easy *data, - struct timeval *nowp, - bool duringconnect); +time_t Curl_timeleft(struct Curl_easy *data, + struct timeval *nowp, + bool duringconnect); #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ #define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between @@ -52,6 +52,11 @@ long Curl_timeleft(struct Curl_easy *data, curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, struct connectdata **connp); +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn); + #ifdef USE_WINSOCK /* When you run a program that uses the Windows Sockets API, you may experience slow performance when you copy data to a TCP server. @@ -122,19 +127,21 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd); void Curl_conncontrol(struct connectdata *conn, int closeit -#ifdef DEBUGBUILD +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) , const char *reason #endif ); -#ifdef DEBUGBUILD +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y) #define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y) #define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y) -#else /* if !CURLDEBUG */ +#else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */ #define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM) #define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION) #define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP) #endif +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex); + #endif /* HEADER_CURL_CONNECT_H */ diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c index fa36aca4c..652ed9764 100644 --- a/Utilities/cmcurl/lib/content_encoding.c +++ b/Utilities/cmcurl/lib/content_encoding.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,8 +28,8 @@ #include #include "sendf.h" #include "content_encoding.h" +#include "strdup.h" #include "curl_memory.h" - #include "memdebug.h" /* Comment this out if zlib is always going to be at least ver. 1.2.0.4 @@ -69,11 +69,11 @@ process_zlib_error(struct connectdata *conn, z_stream *z) { struct Curl_easy *data = conn->data; if(z->msg) - failf (data, "Error while processing content unencoding: %s", - z->msg); + failf(data, "Error while processing content unencoding: %s", + z->msg); else - failf (data, "Error while processing content unencoding: " - "Unknown failure within decompression software."); + failf(data, "Error while processing content unencoding: " + "Unknown failure within decompression software."); return CURLE_BAD_CONTENT_ENCODING; } @@ -130,8 +130,7 @@ inflate_stream(struct connectdata *conn, free(decomp); if(inflateEnd(z) == Z_OK) return exit_zlib(z, &k->zlib_init, result); - else - return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); + return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); } /* Done with these bytes, exit */ @@ -314,7 +313,7 @@ Curl_unencode_gzip_write(struct connectdata *conn, #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(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND); + return exit_zlib(z, &k->zlib_init, CURLE_WRITE_ERROR); #else /* This next mess is to get around the potential case where there isn't @@ -327,14 +326,14 @@ Curl_unencode_gzip_write(struct connectdata *conn, * can handle the gzip header themselves. */ - switch (k->zlib_init) { + switch(k->zlib_init) { /* Skip over gzip header? */ case ZLIB_INIT: { /* Initial call state */ ssize_t hlen; - switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) { + switch(check_gzip_header((unsigned char *)k->str, nread, &hlen)) { case GZIP_OK: z->next_in = (Bytef *)k->str + hlen; z->avail_in = (uInt)(nread - hlen); @@ -371,18 +370,15 @@ Curl_unencode_gzip_write(struct connectdata *conn, { /* Need more gzip header data state */ ssize_t hlen; - unsigned char *oldblock = z->next_in; - z->avail_in += (uInt)nread; - z->next_in = realloc(z->next_in, z->avail_in); + z->next_in = Curl_saferealloc(z->next_in, z->avail_in); if(z->next_in == NULL) { - free(oldblock); return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ memcpy(z->next_in + z->avail_in - nread, k->str, nread); - switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) { + switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) { case GZIP_OK: /* This is the zlib stream data */ free(z->next_in); diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c index 1b3e6457b..6b678aeb8 100644 --- a/Utilities/cmcurl/lib/cookie.c +++ b/Utilities/cmcurl/lib/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -146,12 +146,12 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) * matching cookie path and url path * RFC6265 5.1.4 Paths and Path-Match */ -static bool pathmatch(const char* cookie_path, const char* request_uri) +static bool pathmatch(const char *cookie_path, const char *request_uri) { size_t cookie_path_len; size_t uri_path_len; - char* uri_path = NULL; - char* pos; + char *uri_path = NULL; + char *pos; bool ret = FALSE; /* cookie_path must not have last '/' separator. ex: /sample */ @@ -492,7 +492,6 @@ Curl_cookie_add(struct Curl_easy *data, } else if(strcasecompare("domain", name)) { bool is_ip; - const char *dotp; /* Now, we make sure that our host is within the given domain, or the given domain is not valid and thus cannot be set. */ @@ -500,12 +499,22 @@ Curl_cookie_add(struct Curl_easy *data, if('.' == whatptr[0]) whatptr++; /* ignore preceding dot */ - is_ip = isip(domain ? domain : whatptr); +#ifndef USE_LIBPSL + /* + * Without PSL we don't know when the incoming cookie is set on a + * TLD or otherwise "protected" suffix. To reduce risk, we require a + * dot OR the exact host name being "localhost". + */ + { + const char *dotp; + /* check for more dots */ + dotp = strchr(whatptr, '.'); + if(!dotp && !strcasecompare("localhost", whatptr)) + domain=":"; + } +#endif - /* check for more dots */ - dotp = strchr(whatptr, '.'); - if(!dotp) - domain=":"; + is_ip = isip(domain ? domain : whatptr); if(!domain || (is_ip && !strcmp(whatptr, domain)) @@ -798,8 +807,8 @@ Curl_cookie_add(struct Curl_easy *data, /* Check if the domain is a Public Suffix and if yes, ignore the cookie. This needs a libpsl compiled with builtin data. */ if(domain && co->domain && !isip(co->domain)) { - if(((psl = psl_builtin()) != NULL) - && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) { + psl = psl_builtin(); + if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) { infof(data, "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n", co->name, domain, co->domain); @@ -920,9 +929,8 @@ static char *get_line(char *buf, int len, FILE *input) } return b; } - else - /* read a partial, discard the next piece that ends with newline */ - partial = TRUE; + /* read a partial, discard the next piece that ends with newline */ + partial = TRUE; } else break; @@ -1055,16 +1063,16 @@ static int cookie_sort(const void *p1, const void *p2) #define CLONE(field) \ do { \ if(src->field) { \ - dup->field = strdup(src->field); \ - if(!dup->field) \ + d->field = strdup(src->field); \ + if(!d->field) \ goto fail; \ } \ } while(0) static struct Cookie *dup_cookie(struct Cookie *src) { - struct Cookie *dup = calloc(sizeof(struct Cookie), 1); - if(dup) { + struct Cookie *d = calloc(sizeof(struct Cookie), 1); + if(d) { CLONE(expirestr); CLONE(domain); CLONE(path); @@ -1073,16 +1081,16 @@ static struct Cookie *dup_cookie(struct Cookie *src) CLONE(value); CLONE(maxage); CLONE(version); - dup->expires = src->expires; - dup->tailmatch = src->tailmatch; - dup->secure = src->secure; - dup->livecookie = src->livecookie; - dup->httponly = src->httponly; + d->expires = src->expires; + d->tailmatch = src->tailmatch; + d->secure = src->secure; + d->livecookie = src->livecookie; + d->httponly = src->httponly; } - return dup; + return d; fail: - freecookie(dup); + freecookie(d); return NULL; } diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c index 35eb2ddb9..1adf3198a 100644 --- a/Utilities/cmcurl/lib/curl_addrinfo.c +++ b/Utilities/cmcurl/lib/curl_addrinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -47,6 +47,8 @@ # define in_addr_t unsigned long #endif +#include + #include "curl_addrinfo.h" #include "inet_pton.h" #include "warnless.h" @@ -146,7 +148,8 @@ Curl_getaddrinfo_ex(const char *nodename, if((size_t)ai->ai_addrlen < ss_size) continue; - if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) { + ca = malloc(sizeof(Curl_addrinfo)); + if(!ca) { error = EAI_MEMORY; break; } @@ -163,7 +166,8 @@ Curl_getaddrinfo_ex(const char *nodename, ca->ai_canonname = NULL; ca->ai_next = NULL; - if((ca->ai_addr = malloc(ss_size)) == NULL) { + ca->ai_addr = malloc(ss_size); + if(!ca->ai_addr) { error = EAI_MEMORY; free(ca); break; @@ -171,7 +175,8 @@ Curl_getaddrinfo_ex(const char *nodename, memcpy(ca->ai_addr, ai->ai_addr, ss_size); if(ai->ai_canonname != NULL) { - if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) { + ca->ai_canonname = strdup(ai->ai_canonname); + if(!ca->ai_canonname) { error = EAI_MEMORY; free(ca->ai_addr); free(ca); @@ -286,21 +291,24 @@ Curl_he2ai(const struct hostent *he, int port) size_t ss_size; #ifdef ENABLE_IPV6 if(he->h_addrtype == AF_INET6) - ss_size = sizeof (struct sockaddr_in6); + ss_size = sizeof(struct sockaddr_in6); else #endif - ss_size = sizeof (struct sockaddr_in); + ss_size = sizeof(struct sockaddr_in); - if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) { + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) { result = CURLE_OUT_OF_MEMORY; break; } - if((ai->ai_canonname = strdup(he->h_name)) == NULL) { + ai->ai_canonname = strdup(he->h_name); + if(!ai->ai_canonname) { result = CURLE_OUT_OF_MEMORY; free(ai); break; } - if((ai->ai_addr = calloc(1, ss_size)) == NULL) { + ai->ai_addr = calloc(1, ss_size); + if(!ai->ai_addr) { result = CURLE_OUT_OF_MEMORY; free(ai->ai_canonname); free(ai); @@ -325,7 +333,7 @@ Curl_he2ai(const struct hostent *he, int port) /* leave the rest of the struct filled with zero */ - switch (ai->ai_family) { + switch(ai->ai_family) { case AF_INET: addr = (void *)ai->ai_addr; /* storage area for this info */ @@ -461,7 +469,7 @@ Curl_addrinfo *Curl_str2addr(char *address, int port) /* This is a dotted IP address 123.123.123.123-style */ return Curl_ip2addr(AF_INET, &in, address, port); #ifdef ENABLE_IPV6 - else { + { struct in6_addr in6; if(Curl_inet_pton(AF_INET6, address, &in6) > 0) /* This is a dotted IPv6 address ::1-style */ @@ -475,34 +483,48 @@ Curl_addrinfo *Curl_str2addr(char *address, int port) /** * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo * struct initialized with this path. + * Set '*longpath' to TRUE if the error is a too long path. */ -Curl_addrinfo *Curl_unix2addr(const char *path) +Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) { Curl_addrinfo *ai; struct sockaddr_un *sa_un; size_t path_len; + *longpath = FALSE; + ai = calloc(1, sizeof(Curl_addrinfo)); if(!ai) return NULL; - if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) { + ai->ai_addr = calloc(1, sizeof(struct sockaddr_un)); + if(!ai->ai_addr) { free(ai); return NULL; } + + sa_un = (void *) ai->ai_addr; + sa_un->sun_family = AF_UNIX; + /* sun_path must be able to store the NUL-terminated path */ - path_len = strlen(path); - if(path_len >= sizeof(sa_un->sun_path)) { + path_len = strlen(path) + 1; + if(path_len > sizeof(sa_un->sun_path)) { free(ai->ai_addr); free(ai); + *longpath = TRUE; return NULL; } ai->ai_family = AF_UNIX; ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */ - ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un); - sa_un = (void *) ai->ai_addr; - sa_un->sun_family = AF_UNIX; - memcpy(sa_un->sun_path, path, path_len + 1); /* copy NUL byte */ + ai->ai_addrlen = (curl_socklen_t) + ((offsetof(struct sockaddr_un, sun_path) + path_len) & 0x7FFFFFFF); + + /* Abstract Unix domain socket have NULL prefix instead of suffix */ + if(abstract) + memcpy(sa_un->sun_path + 1, path, path_len - 1); + else + memcpy(sa_un->sun_path, path, path_len); /* copy NUL byte */ + return ai; } #endif @@ -576,7 +598,7 @@ void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port) struct sockaddr_in6 *addr6; #endif for(ca = addrinfo; ca != NULL; ca = ca->ai_next) { - switch (ca->ai_family) { + switch(ca->ai_family) { case AF_INET: addr = (void *)ca->ai_addr; /* storage area for this info */ addr->sin_port = htons((unsigned short)port); diff --git a/Utilities/cmcurl/lib/curl_addrinfo.h b/Utilities/cmcurl/lib/curl_addrinfo.h index 1a681e61e..8f6f3d106 100644 --- a/Utilities/cmcurl/lib/curl_addrinfo.h +++ b/Utilities/cmcurl/lib/curl_addrinfo.h @@ -80,7 +80,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); Curl_addrinfo *Curl_str2addr(char *dotted, int port); #ifdef USE_UNIX_SOCKETS -Curl_addrinfo *Curl_unix2addr(const char *path); +Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract); #endif #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake index 13f69b2eb..f9d54b4bd 100644 --- a/Utilities/cmcurl/lib/curl_config.h.cmake +++ b/Utilities/cmcurl/lib/curl_config.h.cmake @@ -512,6 +512,15 @@ /* Define to 1 if you have the send function. */ #cmakedefine HAVE_SEND 1 +/* Define to 1 if you have the 'fsetxattr' function. */ +#cmakedefine HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +#cmakedefine HAVE_FSETXATTR_5 1 + +/* fsetxattr() takes 6 args */ +#cmakedefine HAVE_FSETXATTR_6 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SETJMP_H 1 @@ -912,6 +921,9 @@ /* if PolarSSL is enabled */ #cmakedefine USE_POLARSSL 1 +/* if DarwinSSL is enabled */ +#cmakedefine USE_DARWINSSL 1 + /* if mbedTLS is enabled */ #cmakedefine USE_MBEDTLS 1 diff --git a/Utilities/cmcurl/lib/curl_des.c b/Utilities/cmcurl/lib/curl_des.c index 421c9f768..b123a00f0 100644 --- a/Utilities/cmcurl/lib/curl_des.c +++ b/Utilities/cmcurl/lib/curl_des.c @@ -34,7 +34,7 @@ * * The function is a port of the Java based oddParity() function over at: * - * http://davenport.sourceforge.net/ntlm.html + * https://davenport.sourceforge.io/ntlm.html * * Parameters: * diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c index 76deca6aa..c25db4956 100644 --- a/Utilities/cmcurl/lib/curl_endian.c +++ b/Utilities/cmcurl/lib/curl_endian.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,7 +37,7 @@ * * Returns the integer. */ -unsigned short Curl_read16_le(unsigned char *buf) +unsigned short Curl_read16_le(const unsigned char *buf) { return (unsigned short)(((unsigned short)buf[0]) | ((unsigned short)buf[1] << 8)); @@ -56,50 +56,12 @@ unsigned short Curl_read16_le(unsigned char *buf) * * Returns the integer. */ -unsigned int Curl_read32_le(unsigned char *buf) +unsigned int Curl_read32_le(const unsigned char *buf) { return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); } -#if (CURL_SIZEOF_CURL_OFF_T > 4) -/* - * Curl_read64_le() - * - * This function converts a 64-bit integer from the little endian format, as - * used in the incoming package to whatever endian format we're using - * natively. - * - * Parameters: - * - * buf [in] - A pointer to a 8 byte buffer. - * - * Returns the integer. - */ -#if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_le(unsigned char *buf) -{ - return ((unsigned long long)buf[0]) | - ((unsigned long long)buf[1] << 8) | - ((unsigned long long)buf[2] << 16) | - ((unsigned long long)buf[3] << 24) | - ((unsigned long long)buf[4] << 32) | - ((unsigned long long)buf[5] << 40) | - ((unsigned long long)buf[6] << 48) | - ((unsigned long long)buf[7] << 56); -} -#else -unsigned __int64 Curl_read64_le(unsigned char *buf) -{ - return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) | - ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) | - ((unsigned __int64)buf[4] << 32) | ((unsigned __int64)buf[5] << 40) | - ((unsigned __int64)buf[6] << 48) | ((unsigned __int64)buf[7] << 56); -} -#endif - -#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ - /* * Curl_read16_be() * @@ -113,86 +75,12 @@ unsigned __int64 Curl_read64_le(unsigned char *buf) * * Returns the integer. */ -unsigned short Curl_read16_be(unsigned char *buf) +unsigned short Curl_read16_be(const unsigned char *buf) { return (unsigned short)(((unsigned short)buf[0] << 8) | ((unsigned short)buf[1])); } -/* - * Curl_read32_be() - * - * This function converts a 32-bit integer from the big endian format, as - * used in the incoming package to whatever endian format we're using - * natively. - * - * Parameters: - * - * buf [in] - A pointer to a 4 byte buffer. - * - * Returns the integer. - */ -unsigned int Curl_read32_be(unsigned char *buf) -{ - return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) | - ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]); -} - -#if (CURL_SIZEOF_CURL_OFF_T > 4) -/* - * Curl_read64_be() - * - * This function converts a 64-bit integer from the big endian format, as - * used in the incoming package to whatever endian format we're using - * natively. - * - * Parameters: - * - * buf [in] - A pointer to a 8 byte buffer. - * - * Returns the integer. - */ -#if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_be(unsigned char *buf) -{ - return ((unsigned long long)buf[0] << 56) | - ((unsigned long long)buf[1] << 48) | - ((unsigned long long)buf[2] << 40) | - ((unsigned long long)buf[3] << 32) | - ((unsigned long long)buf[4] << 24) | - ((unsigned long long)buf[5] << 16) | - ((unsigned long long)buf[6] << 8) | - ((unsigned long long)buf[7]); -} -#else -unsigned __int64 Curl_read64_be(unsigned char *buf) -{ - return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) | - ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) | - ((unsigned __int64)buf[4] << 24) | ((unsigned __int64)buf[5] << 16) | - ((unsigned __int64)buf[6] << 8) | ((unsigned __int64)buf[7]); -} -#endif - -#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ - -/* - * Curl_write16_le() - * - * This function converts a 16-bit integer from the native endian format, - * to little endian format ready for sending down the wire. - * - * Parameters: - * - * value [in] - The 16-bit integer value. - * buffer [in] - A pointer to the output buffer. - */ -void Curl_write16_le(const short value, unsigned char *buffer) -{ - buffer[0] = (char)(value & 0x00FF); - buffer[1] = (char)((value & 0xFF00) >> 8); -} - /* * Curl_write32_le() * diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h index df8398c8c..4f345a6a2 100644 --- a/Utilities/cmcurl/lib/curl_endian.h +++ b/Utilities/cmcurl/lib/curl_endian.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,37 +23,13 @@ ***************************************************************************/ /* Converts a 16-bit integer from little endian */ -unsigned short Curl_read16_le(unsigned char *buf); +unsigned short Curl_read16_le(const unsigned char *buf); /* Converts a 32-bit integer from little endian */ -unsigned int Curl_read32_le(unsigned char *buf); - -#if (CURL_SIZEOF_CURL_OFF_T > 4) -/* Converts a 64-bit integer from little endian */ -#if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_le(unsigned char *buf); -#else -unsigned __int64 Curl_read64_le(unsigned char *buf); -#endif -#endif +unsigned int Curl_read32_le(const unsigned char *buf); /* Converts a 16-bit integer from big endian */ -unsigned short Curl_read16_be(unsigned char *buf); - -/* Converts a 32-bit integer from big endian */ -unsigned int Curl_read32_be(unsigned char *buf); - -#if (CURL_SIZEOF_CURL_OFF_T > 4) -/* Converts a 64-bit integer from big endian */ -#if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_be(unsigned char *buf); -#else -unsigned __int64 Curl_read64_be(unsigned char *buf); -#endif -#endif - -/* Converts a 16-bit integer to little endian */ -void Curl_write16_le(const short value, unsigned char *buffer); +unsigned short Curl_read16_be(const unsigned char *buf); /* Converts a 32-bit integer to little endian */ void Curl_write32_le(const int value, unsigned char *buffer); diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c index e8108bb10..46d3ada1e 100644 --- a/Utilities/cmcurl/lib/curl_fnmatch.c +++ b/Utilities/cmcurl/lib/curl_fnmatch.c @@ -145,8 +145,7 @@ static int setcharset(unsigned char **p, unsigned char *charset) else if(c == ']') { if(something_found) return SETCHARSET_OK; - else - something_found = TRUE; + something_found = TRUE; state = CURLFNM_SCHS_RIGHTBR; charset[c] = 1; (*p)++; @@ -244,7 +243,7 @@ static int setcharset(unsigned char **p, unsigned char *charset) if(c == ']') { return SETCHARSET_OK; } - else if(c == '\\') { + if(c == '\\') { c = *(++(*p)); if(ISPRINT(c)) { charset[c] = 1; @@ -345,8 +344,7 @@ static int loop(const unsigned char *pattern, const unsigned char *string) else if(*p == '\0') { if(*s == '\0') return CURL_FNMATCH_MATCH; - else - return CURL_FNMATCH_NOMATCH; + return CURL_FNMATCH_NOMATCH; } else if(*p == '\\') { state = CURLFNM_LOOP_BACKSLASH; diff --git a/Utilities/cmcurl/lib/curl_gethostname.c b/Utilities/cmcurl/lib/curl_gethostname.c index 2591fd886..8337c72e8 100644 --- a/Utilities/cmcurl/lib/curl_gethostname.c +++ b/Utilities/cmcurl/lib/curl_gethostname.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -48,8 +48,8 @@ * For libcurl static library release builds no overriding takes place. */ -int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) { - +int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) +{ #ifndef HAVE_GETHOSTNAME /* Allow compilation and return failure when unavailable */ @@ -59,7 +59,7 @@ int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) { #else int err; - char* dot; + char *dot; #ifdef DEBUGBUILD diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c index bf7c766eb..83f3fa0c4 100644 --- a/Utilities/cmcurl/lib/curl_gssapi.c +++ b/Utilities/cmcurl/lib/curl_gssapi.c @@ -94,7 +94,7 @@ static size_t display_gss_error(OM_uint32 status, int type, if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) { len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len, "%.*s. ", (int)status_string.length, - (char*)status_string.value); + (char *)status_string.value); } gss_release_buffer(&min_stat, &status_string); } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); diff --git a/Utilities/cmcurl/lib/curl_hmac.h b/Utilities/cmcurl/lib/curl_hmac.h index 41703b42f..756dc9e4c 100644 --- a/Utilities/cmcurl/lib/curl_hmac.h +++ b/Utilities/cmcurl/lib/curl_hmac.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,11 +24,11 @@ #ifndef CURL_DISABLE_CRYPTO_AUTH -typedef void (* HMAC_hinit_func)(void * context); -typedef void (* HMAC_hupdate_func)(void * context, - const unsigned char * data, +typedef void (* HMAC_hinit_func)(void *context); +typedef void (* HMAC_hupdate_func)(void *context, + const unsigned char *data, unsigned int len); -typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context); +typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context); /* Per-hash function HMAC parameters. */ @@ -46,21 +46,21 @@ typedef struct { /* HMAC computation context. */ typedef struct { - const HMAC_params * hmac_hash; /* Hash function definition. */ - void * hmac_hashctxt1; /* Hash function context 1. */ - void * hmac_hashctxt2; /* Hash function context 2. */ + const HMAC_params *hmac_hash; /* Hash function definition. */ + void *hmac_hashctxt1; /* Hash function context 1. */ + void *hmac_hashctxt2; /* Hash function context 2. */ } HMAC_context; /* Prototypes. */ -HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams, - const unsigned char * key, +HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams, + const unsigned char *key, unsigned int keylen); -int Curl_HMAC_update(HMAC_context * context, - const unsigned char * data, +int Curl_HMAC_update(HMAC_context *context, + const unsigned char *data, unsigned int len); -int Curl_HMAC_final(HMAC_context * context, unsigned char * result); +int Curl_HMAC_final(HMAC_context *context, unsigned char *result); #endif diff --git a/Utilities/cmcurl/lib/curl_md4.h b/Utilities/cmcurl/lib/curl_md4.h index 8c26d1222..e0690416d 100644 --- a/Utilities/cmcurl/lib/curl_md4.h +++ b/Utilities/cmcurl/lib/curl_md4.h @@ -24,12 +24,12 @@ #include "curl_setup.h" -/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so - * that we have a local implementation of it */ -#if defined(USE_NSS) || defined(USE_OS400CRYPTO) +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len); -#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */ +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) || + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */ #endif /* HEADER_CURL_MD4_H */ diff --git a/Utilities/cmcurl/lib/curl_memory.h b/Utilities/cmcurl/lib/curl_memory.h index 6f792fffd..fccf46879 100644 --- a/Utilities/cmcurl/lib/curl_memory.h +++ b/Utilities/cmcurl/lib/curl_memory.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -70,7 +70,7 @@ * * Programs and libraries in 'tests' subdirectories have specific * purposes and needs, and as such each one will use whatever fits - * best, depending additionally wether it links with libcurl or not. + * best, depending additionally whether it links with libcurl or not. * * Caveat emptor. Proper curlx_* separation is a work in progress * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c index 812a07313..aea545295 100644 --- a/Utilities/cmcurl/lib/curl_ntlm_core.c +++ b/Utilities/cmcurl/lib/curl_ntlm_core.c @@ -27,7 +27,7 @@ /* * NTLM details: * - * http://davenport.sourceforge.net/ntlm.html + * https://davenport.sourceforge.io/ntlm.html * https://www.innovation.ch/java/ntlm.html */ @@ -80,6 +80,9 @@ # include # include +# if !defined(MBEDTLS_MD4_C) +# include "curl_md4.h" +# endif #elif defined(USE_NSS) @@ -501,7 +504,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, return CURLE_OK; } -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES static void ascii_to_unicode_le(unsigned char *dest, const char *src, size_t srclen) { @@ -512,14 +515,14 @@ static void ascii_to_unicode_le(unsigned char *dest, const char *src, } } -#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI) +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) static void ascii_uppercase_to_unicode_le(unsigned char *dest, const char *src, size_t srclen) { size_t i; for(i = 0; i < srclen; i++) { - dest[2 * i] = (unsigned char)(toupper(src[i])); + dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i])); dest[2 * i + 1] = '\0'; } } @@ -566,12 +569,13 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, gcry_md_hd_t MD4pw; gcry_md_open(&MD4pw, GCRY_MD_MD4, 0); gcry_md_write(MD4pw, pw, 2 * len); - memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH); + memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH); gcry_md_close(MD4pw); +#elif defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) + Curl_md4it(ntbuffer, pw, 2 * len); #elif defined(USE_MBEDTLS) mbedtls_md4(pw, 2 * len, ntbuffer); -#elif defined(USE_NSS) || defined(USE_OS400CRYPTO) - Curl_md4it(ntbuffer, pw, 2 * len); #elif defined(USE_DARWINSSL) (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer); #elif defined(USE_WIN32_CRYPTO) @@ -597,7 +601,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, return CURLE_OK; } -#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI) +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) /* This returns the HMAC MD5 digest */ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, @@ -715,8 +719,10 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, /* Create the BLOB structure */ snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN, - NTLMv2_BLOB_SIGNATURE + "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ "%c%c%c%c", /* Reserved = 0 */ + NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], + NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3], 0, 0, 0, 0); Curl_write64_le(tw, ptr + 24); diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.h b/Utilities/cmcurl/lib/curl_ntlm_core.h index c5f90e778..4a83d40bc 100644 --- a/Utilities/cmcurl/lib/curl_ntlm_core.h +++ b/Utilities/cmcurl/lib/curl_ntlm_core.h @@ -33,31 +33,26 @@ !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H) # error "curl_ntlm_core.h shall not be included before OpenSSL headers." # endif -# ifdef OPENSSL_NO_MD4 -# define USE_NTRESPONSES 0 -# define USE_NTLM2SESSION 0 -# define USE_NTLM_V2 0 -# endif #endif -/* Define USE_NTRESPONSES to 1 in order to make the type-3 message include +/* Define USE_NTRESPONSES in order to make the type-3 message include * the NT response message. */ -#ifndef USE_NTRESPONSES -#define USE_NTRESPONSES 1 +#if !defined(USE_OPENSSL) || !defined(OPENSSL_NO_MD4) +#define USE_NTRESPONSES #endif -/* Define USE_NTLM2SESSION to 1 in order to make the type-3 message include the +/* Define USE_NTLM2SESSION in order to make the type-3 message include the NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a Crypto engine that we have curl_ssl_md5sum() for. */ -#if !defined(USE_NTLM2SESSION) && USE_NTRESPONSES && !defined(USE_WIN32_CRYPTO) -#define USE_NTLM2SESSION 1 +#if defined(USE_NTRESPONSES) && !defined(USE_WIN32_CRYPTO) +#define USE_NTLM2SESSION #endif -/* Define USE_NTLM_V2 to 1 in order to allow the type-3 message to include the +/* Define USE_NTLM_V2 in order to allow the type-3 message to include the LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 and support for 64-bit integers. */ -#if !defined(USE_NTLM_V2) && USE_NTRESPONSES && (CURL_SIZEOF_CURL_OFF_T > 4) -#define USE_NTLM_V2 1 +#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4) +#define USE_NTLM_V2 #endif void Curl_ntlm_core_lm_resp(const unsigned char *keys, @@ -68,12 +63,12 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, const char *password, unsigned char *lmbuffer /* 21 bytes */); -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, const char *password, unsigned char *ntbuffer /* 21 bytes */); -#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI) +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, const unsigned char *data, unsigned int datalen, diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c index afdea16c0..9f5b87bc3 100644 --- a/Utilities/cmcurl/lib/curl_ntlm_wb.c +++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c @@ -28,7 +28,7 @@ /* * NTLM details: * - * http://davenport.sourceforge.net/ntlm.html + * https://davenport.sourceforge.io/ntlm.html * https://www.innovation.ch/java/ntlm.html */ @@ -51,6 +51,7 @@ #include "curl_ntlm_wb.h" #include "url.h" #include "strerror.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -156,7 +157,8 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) } slash = strpbrk(username, "\\/"); if(slash) { - if((domain = strdup(username)) == NULL) + domain = strdup(username); + if(!domain) return CURLE_OUT_OF_MEMORY; slash = domain + (slash - username); *slash = '\0'; @@ -293,11 +295,10 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, buf[len_out - 1] = '\0'; break; } - newbuf = realloc(buf, len_out + NTLM_BUFSIZE); - if(!newbuf) { - free(buf); + newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE); + if(!newbuf) return CURLE_OUT_OF_MEMORY; - } + buf = newbuf; } @@ -349,7 +350,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(proxy) { allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; + userp = conn->http_proxy.user; ntlm = &conn->proxyntlm; authp = &conn->data->state.authproxy; } diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c index 06dd047a4..87a6caf9e 100644 --- a/Utilities/cmcurl/lib/curl_rtmp.c +++ b/Utilities/cmcurl/lib/curl_rtmp.c @@ -25,6 +25,7 @@ #ifdef USE_LIBRTMP +#include "curl_rtmp.h" #include "urldata.h" #include "nonblock.h" /* for curlx_nonblock */ #include "progress.h" /* for Curl_pgrsSetUploadSize */ diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c index 6b8696216..bd574b5e2 100644 --- a/Utilities/cmcurl/lib/curl_sasl.c +++ b/Utilities/cmcurl/lib/curl_sasl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -50,7 +50,7 @@ #include "memdebug.h" /* Supported mechanisms */ -const struct { +static const struct { const char *name; /* Name */ size_t len; /* Name length */ unsigned int bit; /* Flag bit */ @@ -262,10 +262,13 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, size_t len = 0; saslstate state1 = SASL_STOP; saslstate state2 = SASL_FINAL; + 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; #if defined(USE_KERBEROS5) - const char* service = data->set.str[STRING_SERVICE_NAME] ? - data->set.str[STRING_SERVICE_NAME] : - sasl->params->service; + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; #endif sasl->force_ir = force_ir; /* Latch for future use */ @@ -341,8 +344,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, if(force_ir || data->set.sasl_ir) result = Curl_auth_create_oauth_bearer_message(data, conn->user, - conn->host.name, - conn->port, + hostname, + port, conn->oauth_bearer, &resp, &len); } @@ -408,8 +411,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, struct Curl_easy *data = conn->data; saslstate newstate = SASL_FINAL; char *resp = NULL; + 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; #if !defined(CURL_DISABLE_CRYPTO_AUTH) - char *serverdata; char *chlg = NULL; size_t chlglen = 0; #endif @@ -417,6 +422,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, const char *service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : sasl->params->service; +#endif +#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \ + defined(USE_NTLM) + char *serverdata; #endif size_t len = 0; @@ -542,8 +551,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, /* Create the authorisation message */ if(sasl->authused == SASL_MECH_OAUTHBEARER) { result = Curl_auth_create_oauth_bearer_message(data, conn->user, - conn->host.name, - conn->port, + hostname, + port, conn->oauth_bearer, &resp, &len); diff --git a/Utilities/cmcurl/lib/curl_sec.h b/Utilities/cmcurl/lib/curl_sec.h index 3f94e1444..7bdde269b 100644 --- a/Utilities/cmcurl/lib/curl_sec.h +++ b/Utilities/cmcurl/lib/curl_sec.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,8 +30,8 @@ struct Curl_sec_client_mech { void (*end)(void *); int (*check_prot)(void *, int); int (*overhead)(void *, int, int); - int (*encode)(void *, const void*, int, int, void**); - int (*decode)(void *, void*, int, int, struct connectdata *); + int (*encode)(void *, const void *, int, int, void **); + int (*decode)(void *, void *, int, int, struct connectdata *); }; #define AUTH_OK 0 @@ -39,11 +39,11 @@ struct Curl_sec_client_mech { #define AUTH_ERROR 2 #ifdef HAVE_GSSAPI -int Curl_sec_read_msg (struct connectdata *conn, char *, - enum protection_level); -void Curl_sec_end (struct connectdata *); -CURLcode Curl_sec_login (struct connectdata *); -int Curl_sec_request_prot (struct connectdata *conn, const char *level); +int Curl_sec_read_msg(struct connectdata *conn, char *, + enum protection_level); +void Curl_sec_end(struct connectdata *); +CURLcode Curl_sec_login(struct connectdata *); +int Curl_sec_request_prot(struct connectdata *conn, const char *level); extern struct Curl_sec_client_mech Curl_krb5_client_mech; #endif diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h index 4eb17a161..a6268adf2 100644 --- a/Utilities/cmcurl/lib/curl_setup.h +++ b/Utilities/cmcurl/lib/curl_setup.h @@ -128,18 +128,7 @@ /* please, do it beyond the point further indicated in this file. */ /* ================================================================ */ -/* - * libcurl's external interface definitions are also used internally, - * and might also include required system header files to define them. - */ - -#include - -/* - * Compile time sanity checks must also be done when building the library. - */ - -#include +#include /* * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro @@ -482,8 +471,8 @@ # ifdef __minix /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ - extern char * strtok_r(char *s, const char *delim, char **last); - extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp); + extern char *strtok_r(char *s, const char *delim, char **last); + extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp); # endif # define DIR_CHAR "/" @@ -614,11 +603,15 @@ int netware_init(void); #endif #endif -#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) +#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN) /* The lib and header are present */ #define USE_LIBIDN2 #endif +#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN) +#error "Both libidn2 and WinIDN are enabled, choose one." +#endif + #ifndef SIZEOF_TIME_T /* assume default size of time_t to be 32 bit */ #define SIZEOF_TIME_T 4 @@ -649,14 +642,14 @@ int netware_init(void); #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \ - defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ + defined(USE_MBEDTLS) #define USE_NTLM -#elif defined(USE_MBEDTLS) +# if defined(USE_MBEDTLS) +/* Get definition of MBEDTLS_MD4_C */ # include -# if defined(MBEDTLS_MD4_C) -#define USE_NTLM # endif #endif diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h index 4da83499a..684187cae 100644 --- a/Utilities/cmcurl/lib/curl_setup_once.h +++ b/Utilities/cmcurl/lib/curl_setup_once.h @@ -196,7 +196,7 @@ struct timeval { /* */ #else #define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ - (SEND_TYPE_ARG2)(y), \ + (SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \ (SEND_TYPE_ARG3)(z), \ (SEND_TYPE_ARG4)(SEND_4TH_ARG)) #endif diff --git a/Utilities/cmcurl/lib/curl_threads.c b/Utilities/cmcurl/lib/curl_threads.c index c98d8bbad..a78eff5c2 100644 --- a/Utilities/cmcurl/lib/curl_threads.c +++ b/Utilities/cmcurl/lib/curl_threads.c @@ -59,7 +59,7 @@ static void *curl_thread_create_thunk(void *arg) return 0; } -curl_thread_t Curl_thread_create(unsigned int (*func) (void*), 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)); @@ -100,7 +100,8 @@ int Curl_thread_join(curl_thread_t *hnd) #elif defined(USE_THREADS_WIN32) -curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), void *arg) { #ifdef _WIN32_WCE diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h index 8cbac63a7..9e0d14a30 100644 --- a/Utilities/cmcurl/lib/curl_threads.h +++ b/Utilities/cmcurl/lib/curl_threads.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -50,7 +50,8 @@ #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) -curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), void *arg); void Curl_thread_destroy(curl_thread_t hnd); diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c index 69defc4cc..451ec389a 100644 --- a/Utilities/cmcurl/lib/dict.c +++ b/Utilities/cmcurl/lib/dict.c @@ -92,7 +92,7 @@ const struct Curl_handler Curl_handler_dict = { static char *unescape_word(struct Curl_easy *data, const char *inputbuff) { - char *newp; + char *newp = NULL; char *dictp; char *ptr; size_t len; diff --git a/Utilities/cmcurl/lib/dotdot.c b/Utilities/cmcurl/lib/dotdot.c index ea7c8a04f..20603bcab 100644 --- a/Utilities/cmcurl/lib/dotdot.c +++ b/Utilities/cmcurl/lib/dotdot.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -147,6 +147,7 @@ char *Curl_dedotdotify(const char *input) else if(!strcmp(".", clone) || !strcmp("..", clone)) { *clone=0; + *out=0; } else { diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c index eee1061e8..2b1ce9e8a 100644 --- a/Utilities/cmcurl/lib/easy.c +++ b/Utilities/cmcurl/lib/easy.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -179,7 +179,7 @@ curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; #endif #else /* - * Symbian OS doesn't support initialization to code in writeable static data. + * 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; @@ -561,7 +561,7 @@ static void events_setup(struct Curl_multi *multi, struct events *ev) static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) { bool done = FALSE; - CURLMcode mcode; + CURLMcode mcode = CURLM_OK; CURLcode result = CURLE_OK; while(!done) { @@ -615,12 +615,18 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) } } - if(!ev->msbump) + if(!ev->msbump) { /* If nothing updated the timeout, we decrease it by the spent time. * If it was updated, it has the new timeout time stored already. */ - ev->ms += curlx_tvdiff(after, before); - + time_t timediff = curlx_tvdiff(after, before); + if(timediff > 0) { + if(timediff > ev->ms) + ev->ms = 0; + else + ev->ms -= (long)timediff; + } + } } else return CURLE_RECV_ERROR; @@ -773,8 +779,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) curl_multi_cleanup(multi); if(mcode == CURLM_OUT_OF_MEMORY) return CURLE_OUT_OF_MEMORY; - else - return CURLE_FAILED_INIT; + return CURLE_FAILED_INIT; } sigpipe_ignore(data, &pipe_st); @@ -870,6 +875,11 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) * get setup on-demand in the code, as that would probably decrease * the likeliness of us forgetting to init a buffer here in the future. */ + outcurl->set.buffer_size = data->set.buffer_size; + outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1); + if(!outcurl->state.buffer) + goto fail; + outcurl->state.headerbuff = malloc(HEADERSIZE); if(!outcurl->state.headerbuff) goto fail; @@ -927,6 +937,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) Curl_convert_setup(outcurl); + Curl_initinfo(outcurl); + outcurl->magic = CURLEASY_MAGIC_NUMBER; /* we reach this point and thus we are OK */ @@ -938,6 +950,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) if(outcurl) { curl_slist_free_all(outcurl->change.cookielist); outcurl->change.cookielist = NULL; + Curl_safefree(outcurl->state.buffer); Curl_safefree(outcurl->state.headerbuff); Curl_safefree(outcurl->change.url); Curl_safefree(outcurl->change.referer); @@ -973,6 +986,10 @@ void curl_easy_reset(struct Curl_easy *data) data->progress.flags |= PGRS_HIDE; data->state.current_speed = -1; /* init to negative == impossible */ + + /* zero out authentication data: */ + memset(&data->state.authhost, 0, sizeof(struct auth)); + memset(&data->state.authproxy, 0, sizeof(struct auth)); } /* @@ -1000,19 +1017,32 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) /* put it back in the keepon */ k->keepon = newstate; - if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) { - /* we have a buffer for sending that we now seem to be able to deliver - since the receive pausing is lifted! */ - - /* get the pointer in local copy since the function may return PAUSE - again and then we'll get a new copy allocted and stored in - the tempwrite variables */ - char *tempwrite = data->state.tempwrite; - - data->state.tempwrite = NULL; - result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype, - tempwrite, data->state.tempwritesize); - free(tempwrite); + if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) { + /* there are buffers for sending that can be delivered as the receive + pausing is lifted! */ + unsigned int i; + unsigned int count = data->state.tempcount; + struct tempbuf writebuf[3]; /* there can only be three */ + + /* copy the structs to allow for immediate re-pausing */ + for(i=0; i < data->state.tempcount; i++) { + writebuf[i] = data->state.tempwrite[i]; + data->state.tempwrite[i].buf = NULL; + } + data->state.tempcount = 0; + + for(i=0; i < count; i++) { + /* even if one function returns error, this loops through and frees all + buffers */ + if(!result) + result = Curl_client_chop_write(data->easy_conn, + writebuf[i].type, + writebuf[i].buf, + writebuf[i].len); + free(writebuf[i].buf); + } + if(result) + return result; } /* if there's no error and we're not pausing both directions, we want @@ -1020,7 +1050,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action) if(!result && ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) - Curl_expire(data, 0); /* get this handle going again */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ return result; } diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c index 66570076e..973aeb6ea 100644 --- a/Utilities/cmcurl/lib/escape.c +++ b/Utilities/cmcurl/lib/escape.c @@ -31,6 +31,7 @@ #include "warnless.h" #include "non-ascii.h" #include "escape.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -42,7 +43,7 @@ */ static bool Curl_isunreserved(unsigned char in) { - switch (in) { + switch(in) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'b': case 'c': case 'd': case 'e': @@ -109,14 +110,10 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string, newlen += 2; /* the size grows with two, since this'll become a %XX */ if(newlen > alloc) { alloc *= 2; - testing_ptr = realloc(ns, alloc); - if(!testing_ptr) { - free(ns); + testing_ptr = Curl_saferealloc(ns, alloc); + if(!testing_ptr) return NULL; - } - else { - ns = testing_ptr; - } + ns = testing_ptr; } result = Curl_convert_to_network(data, &in, 1); diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c index 272289e0e..c804d75e1 100644 --- a/Utilities/cmcurl/lib/file.c +++ b/Utilities/cmcurl/lib/file.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -311,9 +311,8 @@ static CURLcode file_upload(struct connectdata *conn) size_t nread; size_t nwrite; curl_off_t bytecount = 0; - struct timeval now = Curl_tvnow(); struct_stat file_stat; - const char* buf2; + const char *buf2; /* * Since FILE: doesn't do the full init, we need to provide some extra @@ -355,13 +354,12 @@ static CURLcode file_upload(struct connectdata *conn) failf(data, "Can't get the size of %s", file->path); return CURLE_WRITE_ERROR; } - else - data->state.resume_from = (curl_off_t)file_stat.st_size; + data->state.resume_from = (curl_off_t)file_stat.st_size; } while(!result) { int readcount; - result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount); + result = Curl_fillreadbuffer(conn, (int)data->set.buffer_size, &readcount); if(result) break; @@ -400,7 +398,7 @@ static CURLcode file_upload(struct connectdata *conn) if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; else - result = Curl_speedcheck(data, now); + result = Curl_speedcheck(data, Curl_tvnow()); } if(!result && Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; @@ -437,7 +435,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done) char *buf = data->state.buffer; curl_off_t bytecount = 0; int fd; - struct timeval now = Curl_tvnow(); struct FILEPROTO *file; *done = TRUE; /* unconditionally */ @@ -476,9 +473,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done) time_t filetime; struct tm buffer; const struct tm *tm = &buffer; - snprintf(buf, sizeof(data->state.buffer), + char header[80]; + snprintf(header, sizeof(header), "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, header, 0); if(result) return result; @@ -493,7 +491,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done) return result; /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - snprintf(buf, BUFSIZE-1, + snprintf(header, sizeof(header), "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -519,8 +517,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done) failf(data, "Can't get the size of file."); return CURLE_READ_ERROR; } - else - data->state.resume_from += (curl_off_t)statbuf.st_size; + data->state.resume_from += (curl_off_t)statbuf.st_size; } if(data->state.resume_from <= expected_size) @@ -559,12 +556,11 @@ static CURLcode file_do(struct connectdata *conn, bool *done) size_t bytestoread; if(size_known) { - bytestoread = - (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ? - curlx_sotouz(expected_size) : BUFSIZE - 1; + bytestoread = (expected_size < data->set.buffer_size) ? + curlx_sotouz(expected_size) : (size_t)data->set.buffer_size; } else - bytestoread = BUFSIZE-1; + bytestoread = data->set.buffer_size-1; nread = read(fd, buf, bytestoread); @@ -587,7 +583,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done) if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; else - result = Curl_speedcheck(data, now); + result = Curl_speedcheck(data, Curl_tvnow()); } if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c index 144c65b1d..387298847 100644 --- a/Utilities/cmcurl/lib/fileinfo.c +++ b/Utilities/cmcurl/lib/fileinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2010 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,23 +28,19 @@ /* The last #include file should be: */ #include "memdebug.h" -struct curl_fileinfo *Curl_fileinfo_alloc(void) +struct fileinfo *Curl_fileinfo_alloc(void) { - struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo)); - if(!tmp) - return NULL; - memset(tmp, 0, sizeof(struct curl_fileinfo)); - return tmp; + return calloc(1, sizeof(struct fileinfo)); } void Curl_fileinfo_dtor(void *user, void *element) { - struct curl_fileinfo *finfo = element; + struct fileinfo *finfo = element; (void) user; if(!finfo) return; - Curl_safefree(finfo->b_data); + Curl_safefree(finfo->info.b_data); free(finfo); } diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h index 5324f1a40..c5d0ee5b6 100644 --- a/Utilities/cmcurl/lib/fileinfo.h +++ b/Utilities/cmcurl/lib/fileinfo.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010, Daniel Stenberg, , et al. + * Copyright (C) 2010, 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,11 +23,15 @@ ***************************************************************************/ #include +#include "llist.h" -struct curl_fileinfo *Curl_fileinfo_alloc(void); +struct fileinfo { + struct curl_fileinfo info; + struct curl_llist_element list; +}; -void Curl_fileinfo_dtor(void *, void *); +struct fileinfo *Curl_fileinfo_alloc(void); -struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src); +void Curl_fileinfo_dtor(void *, void *); #endif /* HEADER_CURL_FILEINFO_H */ diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c index 785f1a678..e48a6276c 100644 --- a/Utilities/cmcurl/lib/formdata.c +++ b/Utilities/cmcurl/lib/formdata.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -36,6 +36,7 @@ #include "strcase.h" #include "sendf.h" #include "strdup.h" +#include "rand.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -47,15 +48,12 @@ static char *Curl_basename(char *path); #endif static size_t readfromfile(struct Form *form, char *buffer, size_t size); -static char *formboundary(struct Curl_easy *data); +static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len); /* What kind of Content-Type to use on un-specified files with unrecognized extensions. */ #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream" -#define FORM_FILE_SEPARATOR ',' -#define FORM_TYPE_SEPARATOR ';' - #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS @@ -80,7 +78,7 @@ AddHttpPost(char *name, size_t namelength, char *buffer, size_t bufferlength, char *contenttype, long flags, - struct curl_slist* contentHeader, + struct curl_slist *contentHeader, char *showfilename, char *userp, struct curl_httppost *parent_post, struct curl_httppost **httppost, @@ -98,7 +96,7 @@ AddHttpPost(char *name, size_t namelength, post->contenttype = contenttype; post->contentheader = contentHeader; post->showfilename = showfilename; - post->userp = userp, + post->userp = userp; post->flags = flags | CURL_HTTPPOST_LARGE; } else @@ -315,7 +313,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, break; } - switch (option) { + switch(option) { case CURLFORM_ARRAY: if(array_state) /* we don't support an array from within an array */ @@ -341,6 +339,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, #else current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ #endif + /* FALLTHROUGH */ case CURLFORM_COPYNAME: if(current_form->name) return_value = CURL_FORMADD_OPTION_TWICE; @@ -547,9 +546,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, { /* this "cast increases required alignment of target type" but we consider it OK anyway */ - struct curl_slist* list = array_state? - (struct curl_slist*)(void*)array_value: - va_arg(params, struct curl_slist*); + struct curl_slist *list = array_state? + (struct curl_slist *)(void *)array_value: + va_arg(params, struct curl_slist *); if(current_form->contentheader) return_value = CURL_FORMADD_OPTION_TWICE; @@ -628,70 +627,68 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, return_value = CURL_FORMADD_INCOMPLETE; break; } - else { - if(((form->flags & HTTPPOST_FILENAME) || - (form->flags & HTTPPOST_BUFFER)) && - !form->contenttype) { - char *f = form->flags & HTTPPOST_BUFFER? - form->showfilename : form->value; - - /* our contenttype is missing */ - form->contenttype = strdup(ContentTypeForFilename(f, prevtype)); - if(!form->contenttype) { - return_value = CURL_FORMADD_MEMORY; - break; - } - form->contenttype_alloc = TRUE; + if(((form->flags & HTTPPOST_FILENAME) || + (form->flags & HTTPPOST_BUFFER)) && + !form->contenttype) { + char *f = form->flags & HTTPPOST_BUFFER? + form->showfilename : form->value; + + /* our contenttype is missing */ + form->contenttype = strdup(ContentTypeForFilename(f, prevtype)); + if(!form->contenttype) { + return_value = CURL_FORMADD_MEMORY; + break; } - if(!(form->flags & HTTPPOST_PTRNAME) && - (form == first_form) ) { - /* Note that there's small risk that form->name is NULL here if the - app passed in a bad combo, so we better check for that first. */ - if(form->name) { - /* copy name (without strdup; possibly contains null characters) */ - form->name = Curl_memdup(form->name, form->namelength? - form->namelength: - strlen(form->name)+1); - } - if(!form->name) { - return_value = CURL_FORMADD_MEMORY; - break; - } - form->name_alloc = TRUE; + form->contenttype_alloc = TRUE; + } + if(!(form->flags & HTTPPOST_PTRNAME) && + (form == first_form) ) { + /* Note that there's small risk that form->name is NULL here if the + app passed in a bad combo, so we better check for that first. */ + if(form->name) { + /* copy name (without strdup; possibly contains null characters) */ + form->name = Curl_memdup(form->name, form->namelength? + form->namelength: + strlen(form->name)+1); } - if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | - HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | - HTTPPOST_CALLBACK)) && form->value) { - /* copy value (without strdup; possibly contains null characters) */ - size_t clen = (size_t) form->contentslength; - if(!clen) - clen = strlen(form->value)+1; + if(!form->name) { + return_value = CURL_FORMADD_MEMORY; + break; + } + form->name_alloc = TRUE; + } + if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | + HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | + HTTPPOST_CALLBACK)) && form->value) { + /* copy value (without strdup; possibly contains null characters) */ + size_t clen = (size_t) form->contentslength; + if(!clen) + clen = strlen(form->value)+1; - form->value = Curl_memdup(form->value, clen); + form->value = Curl_memdup(form->value, clen); - if(!form->value) { - return_value = CURL_FORMADD_MEMORY; - break; - } - form->value_alloc = TRUE; - } - post = AddHttpPost(form->name, form->namelength, - form->value, form->contentslength, - form->buffer, form->bufferlength, - form->contenttype, form->flags, - form->contentheader, form->showfilename, - form->userp, - post, httppost, - last_post); - - if(!post) { + if(!form->value) { return_value = CURL_FORMADD_MEMORY; break; } - - if(form->contenttype) - prevtype = form->contenttype; + form->value_alloc = TRUE; } + post = AddHttpPost(form->name, form->namelength, + form->value, form->contentslength, + form->buffer, form->bufferlength, + form->contenttype, form->flags, + form->contentheader, form->showfilename, + form->userp, + post, httppost, + last_post); + + if(!post) { + return_value = CURL_FORMADD_MEMORY; + break; + } + + if(form->contenttype) + prevtype = form->contenttype; } if(CURL_FORMADD_OK != return_value) { /* On error, free allocated fields for nodes of the FormInfo linked @@ -761,8 +758,8 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost, * and CD/DVD images should be either a STREAM_LF format or a fixed format. * */ -curl_off_t VmsRealFileSize(const char * name, - const struct_stat * stat_buf) +curl_off_t VmsRealFileSize(const char *name, + const struct_stat *stat_buf) { char buffer[8192]; curl_off_t count; @@ -791,8 +788,8 @@ curl_off_t VmsRealFileSize(const char * name, * if not to call a routine to get the correct size. * */ -static curl_off_t VmsSpecialSize(const char * name, - const struct_stat * stat_buf) +static curl_off_t VmsSpecialSize(const char *name, + const struct_stat *stat_buf) { switch(stat_buf->st_fab_rfm) { case FAB$C_VAR: @@ -948,8 +945,8 @@ void Curl_formclean(struct FormData **form_ptr) if(form->type <= FORM_CONTENT) free(form->line); /* free the line */ free(form); /* free the struct */ - - } while((form = next) != NULL); /* continue */ + form = next; + } while(form); /* continue */ *form_ptr = NULL; } @@ -1030,8 +1027,8 @@ void curl_formfree(struct curl_httppost *form) free(form->contenttype); /* free the content type */ free(form->showfilename); /* free the faked file name */ free(form); /* free the struct */ - - } while((form = next) != NULL); /* continue */ + form = next; + } while(form); /* continue */ } #ifndef HAVE_BASENAME @@ -1162,20 +1159,19 @@ CURLcode Curl_getformdata(struct Curl_easy *data, struct FormData *firstform; struct curl_httppost *file; CURLcode result = CURLE_OK; - curl_off_t size = 0; /* support potentially ENORMOUS formposts */ - char *boundary; - char *fileboundary = NULL; - struct curl_slist* curList; + char fileboundary[42]; + struct curl_slist *curList; + char boundary[42]; *finalform = NULL; /* default form is empty */ if(!post) return result; /* no input => no output! */ - boundary = formboundary(data); - if(!boundary) - return CURLE_OUT_OF_MEMORY; + result = formboundary(data, boundary, sizeof(boundary)); + if(result) + return result; /* Make the first line of the output */ result = AddFormDataf(&form, NULL, @@ -1185,7 +1181,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data, boundary); if(result) { - free(boundary); return result; } /* we DO NOT include that line in the total size of the POST, since it'll be @@ -1228,10 +1223,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data, /* If used, this is a link to more file names, we must then do the magic to include several files with the same field name */ - free(fileboundary); - fileboundary = formboundary(data); - if(!fileboundary) { - result = CURLE_OUT_OF_MEMORY; + result = formboundary(data, fileboundary, sizeof(fileboundary)); + if(result) { break; } @@ -1331,7 +1324,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data, char buffer[512]; while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) { result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size); - if(result) + if(result || feof(fileread) || ferror(fileread)) break; } } @@ -1373,8 +1366,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data, if(result) break; } - - } while((post = post->next) != NULL); /* for each field */ + post = post->next; + } while(post); /* for each field */ /* end-boundary for everything */ if(!result) @@ -1382,16 +1375,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data, if(result) { Curl_formclean(&firstform); - free(fileboundary); - free(boundary); return result; } *sizep = size; - - free(fileboundary); - free(boundary); - *finalform = firstform; return result; @@ -1426,13 +1413,14 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata) * */ # define fopen_read vmsfopenread -static FILE * vmsfopenread(const char *file, const char *mode) { +static FILE * vmsfopenread(const char *file, const char *mode) +{ struct_stat statbuf; int result; result = stat(file, &statbuf); - switch (statbuf.st_fab_rfm) { + switch(statbuf.st_fab_rfm) { case FAB$C_VAR: case FAB$C_VFC: case FAB$C_STMCR: @@ -1460,8 +1448,7 @@ static size_t readfromfile(struct Form *form, char *buffer, if(callback) { if(form->fread_func == ZERO_NULL) return 0; - else - nread = form->fread_func(buffer, 1, size, form->data->line); + nread = form->fread_func(buffer, 1, size, form->data->line); } else { if(!form->fp) { @@ -1551,7 +1538,7 @@ char *Curl_formpostheader(void *formp, size_t *len) struct Form *form=(struct Form *)formp; if(!form->data) - return 0; /* nothing, ERROR! */ + return NULL; /* nothing, ERROR! */ header = form->data->line; *len = form->data->length; @@ -1565,12 +1552,18 @@ char *Curl_formpostheader(void *formp, size_t *len) * formboundary() creates a suitable boundary string and returns an allocated * one. */ -static char *formboundary(struct Curl_easy *data) +static CURLcode formboundary(struct Curl_easy *data, + char *buffer, size_t buflen) { /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615) combinations */ - return aprintf("------------------------%08x%08x", - Curl_rand(data), Curl_rand(data)); + if(buflen < 41) + return CURLE_BAD_FUNCTION_ARGUMENT; + + memset(buffer, '-', 24); + Curl_rand_hex(data, (unsigned char *)&buffer[24], 17); + + return CURLE_OK; } #else /* CURL_DISABLE_HTTP */ diff --git a/Utilities/cmcurl/lib/formdata.h b/Utilities/cmcurl/lib/formdata.h index 200470b50..69629f628 100644 --- a/Utilities/cmcurl/lib/formdata.h +++ b/Utilities/cmcurl/lib/formdata.h @@ -65,7 +65,7 @@ typedef struct FormInfo { file name will be used */ bool showfilename_alloc; char *userp; /* pointer for the read callback */ - struct curl_slist* contentheader; + struct curl_slist *contentheader; struct FormInfo *more; } FormInfo; diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c index 9d0a03ce9..783dbe124 100644 --- a/Utilities/cmcurl/lib/ftp.c +++ b/Utilities/cmcurl/lib/ftp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -384,10 +384,10 @@ static CURLcode AcceptServerConnect(struct connectdata *conn) * Curl_pgrsTime(..., TIMER_STARTACCEPT); * */ -static long ftp_timeleft_accept(struct Curl_easy *data) +static time_t ftp_timeleft_accept(struct Curl_easy *data) { - long timeout_ms = DEFAULT_ACCEPT_TIMEOUT; - long other; + time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; + time_t other; struct timeval now; if(data->set.accepttimeout > 0) @@ -430,7 +430,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; int result; - long timeout_ms; + time_t timeout_ms; ssize_t nread; int ftpcode; @@ -455,7 +455,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); /* see if the connection request is already here */ - switch (result) { + switch(result) { case -1: /* error */ /* let's die here */ failf(data, "Error while waiting for server connect"); @@ -499,7 +499,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) struct FTP *ftp = data->req.protop; CURLcode result = CURLE_OK; - if(conn->ssl[SECONDARYSOCKET].use) { + 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"); @@ -547,7 +547,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) { struct Curl_easy *data = conn->data; - long timeout_ms; + time_t timeout_ms; CURLcode result = CURLE_OK; *connected = FALSE; @@ -580,10 +580,8 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) else { /* Add timeout to multi handle and break out of the loop */ if(!result && *connected == FALSE) { - if(data->set.accepttimeout > 0) - Curl_expire(data, data->set.accepttimeout); - else - Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT); + Curl_expire(data, data->set.accepttimeout > 0 ? + data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0); } } @@ -687,8 +685,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ * line in a response or continue reading. */ curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - long timeout; /* timeout in milliseconds */ - long interval_ms; + time_t timeout; /* timeout in milliseconds */ + time_t interval_ms; struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -740,8 +738,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ * wait for more data anyway. */ } - else { - switch (SOCKET_READABLE(sockfd, interval_ms)) { + else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) { + switch(SOCKET_READABLE(sockfd, interval_ms)) { case -1: /* select() error, stop reading */ failf(data, "FTP response aborted due to select/poll error: %d", SOCKERRNO); @@ -916,8 +914,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, return bits; } - else - return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); } /* This is called after the FTP_QUOTE state is passed. @@ -1035,7 +1032,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(*string_ftpport == '[') { /* [ipv6]:port(-range) */ ip_start = string_ftpport + 1; - if((ip_end = strchr(string_ftpport, ']')) != NULL) + ip_end = strchr(string_ftpport, ']'); + if(ip_end) strncpy(addr, ip_start, ip_end - ip_start); } else @@ -1043,30 +1041,35 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(*string_ftpport == ':') { /* :port */ ip_end = string_ftpport; - } - else if((ip_end = strchr(string_ftpport, ':')) != NULL) { - /* either ipv6 or (ipv4|domain|interface):port(-range) */ -#ifdef ENABLE_IPV6 - if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { - /* ipv6 */ - port_min = port_max = 0; - strcpy(addr, string_ftpport); - ip_end = NULL; /* this got no port ! */ } - else + else { + ip_end = strchr(string_ftpport, ':'); + if(ip_end) { + /* either ipv6 or (ipv4|domain|interface):port(-range) */ +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { + /* ipv6 */ + port_min = port_max = 0; + strcpy(addr, string_ftpport); + ip_end = NULL; /* this got no port ! */ + } + else #endif - /* (ipv4|domain|interface):port(-range) */ - strncpy(addr, string_ftpport, ip_end - ip_start); - } - else - /* ipv4|interface */ - strcpy(addr, string_ftpport); + /* (ipv4|domain|interface):port(-range) */ + strncpy(addr, string_ftpport, ip_end - ip_start); + } + else + /* ipv4|interface */ + strcpy(addr, string_ftpport); + } /* parse the port */ if(ip_end != NULL) { - if((port_start = strchr(ip_end, ':')) != NULL) { + port_start = strchr(ip_end, ':'); + if(port_start) { port_min = curlx_ultous(strtoul(port_start+1, NULL, 10)); - if((port_sep = strchr(port_start, '-')) != NULL) { + port_sep = strchr(port_start, '-'); + if(port_sep) { port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); } else @@ -1203,7 +1206,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, possibly_non_local = FALSE; /* don't try this again */ continue; } - else if(error != EADDRINUSE && error != EACCES) { + if(error != EADDRINUSE && error != EACCES) { failf(data, "bind(port=%hu) failed: %s", port, Curl_strerror(conn, error) ); Curl_closesocket(conn, portsock); @@ -1301,7 +1304,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, } break; } - else if(PORT == fcmd) { + if(PORT == fcmd) { char *source = myhost; char *dest = tmp; @@ -1668,31 +1671,30 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, } if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed=0; if(seekerr != CURL_SEEKFUNC_CANTSEEK) { failf(data, "Could not seek stream"); return CURLE_FTP_COULDNT_USE_REST; } /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ - else { - curl_off_t passed=0; - do { - size_t readthisamountnow = - (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? - BUFSIZE : 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, "Failed to read data"); - return CURLE_FTP_COULDNT_USE_REST; - } - } while(passed < data->state.resume_from); - } + 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, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); } /* now, decrease the size of the read */ if(data->state.infilesize>0) { @@ -1751,7 +1753,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn, /* * This state uses: * 'count1' to iterate over the commands to send - * 'count2' to store wether to allow commands to fail + * 'count2' to store whether to allow commands to fail */ if(init) @@ -1850,84 +1852,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn) return result; } -/* - * Perform the necessary magic that needs to be done once the TCP connection - * to the proxy has completed. - */ -static CURLcode proxy_magic(struct connectdata *conn, - char *newhost, unsigned short newport, - bool *magicdone) -{ - CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - -#if defined(CURL_DISABLE_PROXY) - (void) newhost; - (void) newport; -#endif - - *magicdone = FALSE; - - switch(conn->proxytype) { - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, - newport, SECONDARYSOCKET, conn); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, FALSE); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4A: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, TRUE); - *magicdone = TRUE; - break; - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - failf(data, "unknown proxytype option given"); - result = CURLE_COULDNT_CONNECT; - break; - } - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* BLOCKING */ - /* We want "seamless" FTP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the - * member conn->proto.http; we want FTP through HTTP and we have to - * change the member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original - * struct FTP pointer - */ - struct HTTP http_proxy; - struct FTP *ftp_save = data->req.protop; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->req.protop = &http_proxy; - - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE); - - data->req.protop = ftp_save; - - if(result) - return result; - - if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) { - /* the CONNECT procedure is not complete, the tunnel is not yet up */ - state(conn, FTP_STOP); /* this phase is completed */ - return result; - } - else - *magicdone = TRUE; - } - - return result; -} static char *control_address(struct connectdata *conn) { @@ -1935,11 +1859,7 @@ static char *control_address(struct connectdata *conn) If a proxy tunnel is used, returns the original host name instead, because the effective control connection address is the proxy address, not the ftp host. */ - if(conn->bits.tunnel_proxy || - conn->proxytype == CURLPROXY_SOCKS5 || - conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME || - conn->proxytype == CURLPROXY_SOCKS4 || - conn->proxytype == CURLPROXY_SOCKS4A) + if(conn->bits.tunnel_proxy || conn->bits.socksproxy) return conn->host.name; return conn->ip_addr_str; @@ -2063,7 +1983,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, * here. We don't want to rely on a former host lookup that might've * expired now, instead we remake the lookup here and now! */ - rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr); + 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, &addr); if(rc == CURLRESOLV_PENDING) /* BLOCKING, ignores the return code but 'addr' will be NULL in case of failure */ @@ -2073,9 +1995,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, (unsigned short)conn->port; /* we connect to the proxy's port */ if(!addr) { - failf(data, "Can't resolve proxy host %s:%hu", - conn->proxy.name, connectport); - return CURLE_FTP_CANT_GET_HOST; + failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport); + return CURLE_COULDNT_RESOLVE_PROXY; } } else { @@ -2116,6 +2037,13 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); Curl_resolv_unlock(data, addr); /* we're done using this address */ + + Curl_safefree(conn->secondaryhostname); + conn->secondary_port = ftpc->newport; + conn->secondaryhostname = strdup(ftpc->newhost); + if(!conn->secondaryhostname) + return CURLE_OUT_OF_MEMORY; + conn->bits.do_more = TRUE; state(conn, FTP_STOP); /* this phase is completed */ @@ -2172,17 +2100,17 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the last .sss part is optional and means fractions of a second */ int year, month, day, hour, minute, second; - char *buf = data->state.buffer; - if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d", + if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d", &year, &month, &day, &hour, &minute, &second)) { /* we have a time, reformat it */ + char timebuf[24]; time_t secs=time(NULL); - /* using the good old yacc/bison yuck */ - snprintf(buf, sizeof(conn->data->state.buffer), + + snprintf(timebuf, sizeof(timebuf), "%04d%02d%02d %02d:%02d:%02d GMT", year, month, day, hour, minute, second); /* now, convert this into a time() value: */ - data->info.filetime = (long)curl_getdate(buf, &secs); + data->info.filetime = (long)curl_getdate(timebuf, &secs); } #ifdef CURL_FTP_HTTPSTYLE_HEAD @@ -2193,6 +2121,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, ftpc->file && data->set.get_filetime && (data->info.filetime>=0) ) { + char headerbuf[128]; time_t filetime = (time_t)data->info.filetime; struct tm buffer; const struct tm *tm = &buffer; @@ -2202,7 +2131,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, return result; /* format: "Tue, 15 Nov 1994 12:45:26" */ - snprintf(buf, BUFSIZE-1, + snprintf(headerbuf, sizeof(headerbuf), "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, @@ -2211,7 +2140,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, buf, 0); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0); if(result) return result; } /* end of a ridiculous amount of conditionals */ @@ -2389,9 +2318,10 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn, if(instate == FTP_SIZE) { #ifdef CURL_FTP_HTTPSTYLE_HEAD if(-1 != filesize) { - snprintf(buf, sizeof(data->state.buffer), + char clbuf[128]; + snprintf(clbuf, sizeof(clbuf), "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0); if(result) return result; } @@ -2480,8 +2410,7 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn, return CURLE_OK; } - else - return InitiateTransfer(conn); + return InitiateTransfer(conn); } /* for LIST and RETR responses */ @@ -2492,7 +2421,6 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn, CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; struct FTP *ftp = data->req.protop; - char *buf = data->state.buffer; if((ftpcode == 150) || (ftpcode == 125)) { @@ -2536,6 +2464,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn, * * Example D above makes this parsing a little tricky */ char *bytes; + char *buf = data->state.buffer; bytes=strstr(buf, " bytes"); if(bytes--) { long in=(long)(bytes-buf); @@ -2763,7 +2692,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) } #endif - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + if(data->set.use_ssl && + (!conn->ssl[FIRSTSOCKET].use || + (conn->bits.proxy_ssl_connected[FIRSTSOCKET] && + !conn->proxy_ssl[FIRSTSOCKET].use))) { /* We don't have a SSL/TLS connection yet, but FTPS is requested. Try a FTPS connection now */ @@ -2808,7 +2740,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) /* Curl_ssl_connect is BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(!result) { - conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */ + conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ result = ftp_state_user(conn); } } @@ -2850,7 +2782,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) case FTP_PROT: if(ftpcode/100 == 2) /* We have enabled SSL for the data connection! */ - conn->ssl[SECONDARYSOCKET].use = + conn->bits.ftp_use_data_ssl = (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; /* FTP servers typically responds with 500 if they decide to reject our 'P' request */ @@ -2891,6 +2823,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) case FTP_PWD: if(ftpcode == 257) { char *ptr=&data->state.buffer[4]; /* start on the first letter */ + const size_t buf_size = data->set.buffer_size; char *dir; char *store; @@ -2908,7 +2841,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) */ /* scan for the first double-quote for non-standard responses */ - while(ptr < &data->state.buffer[sizeof(data->state.buffer)] + while(ptr < &data->state.buffer[buf_size] && *ptr != '\n' && *ptr != '\0' && *ptr != '"') ptr++; @@ -2938,7 +2871,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) does not start with a '/'), we probably need some server-dependent adjustments. For example, this is the case when connecting to an OS400 FTP server: this server supports two name syntaxes, - the default one being incompatible with standard pathes. In + the default one being incompatible with standard paths. In addition, this server switches automatically to the regular path syntax when one is encountered in a command: this results in having an entrypath in the wrong syntax when later used in CWD. @@ -3012,12 +2945,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) state(conn, FTP_NAMEFMT); break; } - else { - /* Nothing special for the target server. */ - /* remember target server OS */ - Curl_safefree(ftpc->server_os); - ftpc->server_os = os; - } + /* Nothing special for the target server. */ + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; } else { /* Cannot identify server OS. Continue anyway and cross fingers. */ @@ -3250,7 +3181,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, ssize_t nread; int ftpcode; CURLcode result = CURLE_OK; - char *path; + char *path = NULL; const char *path_to_use = data->state.path; if(!ftp) @@ -3278,6 +3209,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, /* until we cope better with prematurely ended requests, let them * fallback as if in complete failure */ + /* FALLTHROUGH */ default: /* by default, an error means the control connection is wedged and should not be used anymore */ ftpc->ctl_valid = FALSE; @@ -3621,7 +3553,7 @@ static CURLcode ftp_range(struct connectdata *conn) " to %" CURL_FORMAT_CURL_OFF_T ", totally %" CURL_FORMAT_CURL_OFF_T " bytes\n", from, to, data->req.maxdownload)); - ftpc->dont_check = TRUE; /* dont check for successful transfer */ + ftpc->dont_check = TRUE; /* don't check for successful transfer */ } else data->req.maxdownload = -1; @@ -3656,7 +3588,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) { /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port aren't used so we blank their arguments. TODO: make this nicer */ - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE); + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); return result; } @@ -3666,10 +3598,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) /* Ready to do more? */ if(connected) { DEBUGF(infof(data, "DO-MORE connected phase starts\n")); - if(conn->bits.proxy) { - infof(data, "Connection to proxy confirmed\n"); - result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected); - } } else { if(result && (ftpc->count1 == 0)) { @@ -3681,6 +3609,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) } } + result = Curl_proxy_connect(conn, SECONDARYSOCKET); + if(result) + return result; + + if(CONNECT_SECONDARYSOCKET_PROXY_SSL()) + return result; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) + return result; + + if(ftpc->state) { /* already in a state so skip the initial commands. They are only done to kickstart the do_more state */ @@ -3856,12 +3796,10 @@ static CURLcode init_wc_data(struct connectdata *conn) result = ftp_parse_url_path(conn); return result; } - else { - wildcard->pattern = strdup(last_slash); - if(!wildcard->pattern) - return CURLE_OUT_OF_MEMORY; - last_slash[0] = '\0'; /* cut file from path */ - } + wildcard->pattern = strdup(last_slash); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + last_slash[0] = '\0'; /* cut file from path */ } else { /* there is only 'wildcard pattern' or nothing */ if(path[0]) { @@ -3940,14 +3878,13 @@ static CURLcode wc_statemach(struct connectdata *conn) struct WildcardData * const wildcard = &(conn->data->wildcard); CURLcode result = CURLE_OK; - switch (wildcard->state) { + switch(wildcard->state) { case CURLWC_INIT: result = init_wc_data(conn); if(wildcard->state == CURLWC_CLEAN) /* only listing! */ break; - else - wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; break; case CURLWC_MATCHING: { @@ -3965,7 +3902,7 @@ static CURLcode wc_statemach(struct connectdata *conn) wildcard->state = CURLWC_CLEAN; return wc_statemach(conn); } - else if(wildcard->filelist->size == 0) { + if(wildcard->filelist.size == 0) { /* no corresponding file */ wildcard->state = CURLWC_CLEAN; return CURLE_REMOTE_FILE_NOT_FOUND; @@ -3976,7 +3913,7 @@ static CURLcode wc_statemach(struct connectdata *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 curl_fileinfo *finfo = wildcard->filelist.head->ptr; char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); if(!tmp_path) @@ -3991,7 +3928,7 @@ static CURLcode wc_statemach(struct connectdata *conn) infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); if(conn->data->set.chunk_bgn) { long userresponse = conn->data->set.chunk_bgn( - finfo, wildcard->customptr, (int)wildcard->filelist->size); + finfo, wildcard->customptr, (int)wildcard->filelist.size); switch(userresponse) { case CURL_CHUNK_BGN_FUNC_SKIP: infof(conn->data, "Wildcard - \"%s\" skipped by user\n", @@ -4016,9 +3953,9 @@ static CURLcode wc_statemach(struct connectdata *conn) return result; /* we don't need the Curl_fileinfo of first file anymore */ - Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); - if(wildcard->filelist->size == 0) { /* remains only one file to down. */ + 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 */ @@ -4029,8 +3966,8 @@ static CURLcode wc_statemach(struct connectdata *conn) case CURLWC_SKIP: { if(conn->data->set.chunk_end) conn->data->set.chunk_end(conn->data->wildcard.customptr); - Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); - wildcard->state = (wildcard->filelist->size == 0) ? + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + wildcard->state = (wildcard->filelist.size == 0) ? CURLWC_CLEAN : CURLWC_DOWNLOADING; return wc_statemach(conn); } @@ -4046,6 +3983,7 @@ static CURLcode wc_statemach(struct connectdata *conn) case CURLWC_DONE: case CURLWC_ERROR: + case CURLWC_CLEAR: break; } @@ -4247,8 +4185,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) const char *cur_pos; const char *filename = NULL; - cur_pos = path_to_use; /* current position in path. point at the begin - of next path component */ + cur_pos = path_to_use; /* current position in path. point at the begin of + next path component */ ftpc->ctl_valid = FALSE; ftpc->cwdfail = FALSE; @@ -4343,7 +4281,6 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) &ftpc->dirs[ftpc->dirdepth], NULL, TRUE); if(result) { - free(ftpc->dirs[ftpc->dirdepth]); freedirs(ftpc); return result; } @@ -4568,7 +4505,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) command = Curl_raw_toupper(type[6]); conn->bits.type_set = TRUE; - switch (command) { + switch(command) { case 'A': /* ASCII mode */ data->set.prefer_ascii = TRUE; break; diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h index dbd8567f5..3bbf26206 100644 --- a/Utilities/cmcurl/lib/ftp.h +++ b/Utilities/cmcurl/lib/ftp.h @@ -143,7 +143,7 @@ struct ftp_conn { ftpstate state_saved; /* transfer type saved to be reloaded after data connection is established */ curl_off_t retr_size_saved; /* Size of retrieved file saved */ - char * server_os; /* The target server operating system. */ + char *server_os; /* The target server operating system. */ curl_off_t known_filesize; /* file size is different from -1, if wildcard LIST parsing was done and wc_statemach set it */ diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c index 747dbbad3..2acce31d8 100644 --- a/Utilities/cmcurl/lib/ftplistparser.c +++ b/Utilities/cmcurl/lib/ftplistparser.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -165,7 +165,7 @@ struct ftp_parselist_data { } state; CURLcode error; - struct curl_fileinfo *file_data; + struct fileinfo *file_data; unsigned int item_length; size_t item_offset; struct { @@ -275,14 +275,15 @@ static void PL_ERROR(struct connectdata *conn, CURLcode err) } static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, - struct curl_fileinfo *finfo) + struct fileinfo *infop) { curl_fnmatch_callback compare; struct WildcardData *wc = &conn->data->wildcard; struct ftp_wc_tmpdata *tmpdata = wc->tmp; - struct curl_llist *llist = wc->filelist; + struct curl_llist *llist = &wc->filelist; struct ftp_parselist_data *parser = tmpdata->parser; bool add = TRUE; + struct curl_fileinfo *finfo = &infop->info; /* move finfo pointers to b_data */ char *str = finfo->b_data; @@ -316,11 +317,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, } if(add) { - if(!Curl_llist_insert_next(llist, llist->tail, finfo)) { - Curl_fileinfo_dtor(NULL, finfo); - tmpdata->parser->file_data = NULL; - return CURLE_OUT_OF_MEMORY; - } + Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list); } else { Curl_fileinfo_dtor(NULL, finfo); @@ -337,6 +334,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, struct connectdata *conn = (struct connectdata *)connptr; struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; struct ftp_parselist_data *parser = tmpdata->parser; + struct fileinfo *infop; struct curl_fileinfo *finfo; unsigned long i = 0; CURLcode result; @@ -366,17 +364,18 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->error = CURLE_OUT_OF_MEMORY; return bufflen; } - parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE); - if(!parser->file_data->b_data) { + parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE); + if(!parser->file_data->info.b_data) { PL_ERROR(conn, CURLE_OUT_OF_MEMORY); return bufflen; } - parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE; + parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE; parser->item_offset = 0; parser->item_length = 0; } - finfo = parser->file_data; + infop = parser->file_data; + finfo = &infop->info; finfo->b_data[finfo->b_used++] = c; if(finfo->b_used >= finfo->b_size - 1) { @@ -396,9 +395,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } } - switch (parser->os_type) { + switch(parser->os_type) { case OS_TYPE_UNIX: - switch (parser->state.UNIX.main) { + switch(parser->state.UNIX.main) { case PL_UNIX_TOTALSIZE: switch(parser->state.UNIX.sub.total_dirsize) { case PL_UNIX_TOTALSIZE_INIT: @@ -433,10 +432,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; } - else { - parser->state.UNIX.main = PL_UNIX_FILETYPE; - finfo->b_used = 0; - } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + finfo->b_used = 0; } else { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); @@ -447,7 +444,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } break; case PL_UNIX_FILETYPE: - switch (c) { + switch(c) { case '-': finfo->filetype = CURLFILETYPE_FILE; break; @@ -500,8 +497,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; } - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM; - parser->file_data->perm = perm; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM; + parser->file_data->info.perm = perm; parser->offsets.perm = parser->item_offset; parser->item_length = 0; @@ -532,8 +529,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10); if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; - parser->file_data->hardlinks = hlinks; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; + parser->file_data->info.hardlinks = hlinks; } parser->item_length = 0; parser->item_offset = 0; @@ -615,8 +612,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10); if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && fsize != CURL_OFF_T_MIN) { - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; - parser->file_data->size = fsize; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->info.size = fsize; } parser->item_length = 0; parser->item_offset = 0; @@ -733,7 +730,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, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -745,7 +742,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, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -840,7 +837,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, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -852,7 +849,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, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -955,10 +952,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, return bufflen; } /* correct file type */ - parser->file_data->filetype = CURLFILETYPE_FILE; + parser->file_data->info.filetype = CURLFILETYPE_FILE; } - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; parser->item_length = 0; parser->state.NT.main = PL_WINNT_FILENAME; parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; @@ -967,7 +964,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } break; case PL_WINNT_FILENAME: - switch (parser->state.NT.sub.filename) { + switch(parser->state.NT.sub.filename) { case PL_WINNT_FILENAME_PRESPACE: if(c != ' ') { parser->item_offset = finfo->b_used -1; @@ -985,7 +982,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, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -997,7 +994,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, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c index 9641d79dc..a1ce5058e 100644 --- a/Utilities/cmcurl/lib/getinfo.c +++ b/Utilities/cmcurl/lib/getinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -36,8 +36,11 @@ #include "memdebug.h" /* - * This is supposed to be called in the beginning of a perform() session and - * in curl_easy_reset() and should reset all session-info variables. + * Initialize statistical and informational data. + * + * This function is called in curl_easy_reset, curl_easy_duphandle and at the + * beginning of a perform session. It must reset the session-info variables, + * in particular all variables in struct PureInfo. */ CURLcode Curl_initinfo(struct Curl_easy *data) { @@ -75,6 +78,9 @@ CURLcode Curl_initinfo(struct Curl_easy *data) info->conn_primary_port = 0; info->conn_local_port = 0; + info->conn_scheme = 0; + info->conn_protocol = 0; + #ifdef USE_SSL Curl_ssl_free_certinfo(data); #endif @@ -83,7 +89,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data) } static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, - char **param_charp) + const char **param_charp) { switch(info) { case CURLINFO_EFFECTIVE_URL: @@ -120,6 +126,9 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, case CURLINFO_RTSP_SESSION_ID: *param_charp = data->set.str[STRING_RTSP_SESSION_ID]; break; + case CURLINFO_SCHEME: + *param_charp = data->info.conn_scheme; + break; default: return CURLE_UNKNOWN_OPTION; @@ -157,6 +166,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, case CURLINFO_SSL_VERIFYRESULT: *param_longp = data->set.ssl.certverifyresult; break; + case CURLINFO_PROXY_SSL_VERIFYRESULT: + *param_longp = data->set.proxy_ssl.certverifyresult; + break; case CURLINFO_REDIRECT_COUNT: *param_longp = data->set.followlocation; break; @@ -208,7 +220,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, *param_longp = data->state.rtsp_CSeq_recv; break; case CURLINFO_HTTP_VERSION: - switch (data->info.httpversion) { + switch(data->info.httpversion) { case 10: *param_longp = CURL_HTTP_VERSION_1_0; break; @@ -223,6 +235,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, break; } break; + case CURLINFO_PROTOCOL: + *param_longp = data->info.conn_protocol; + break; default: return CURLE_UNKNOWN_OPTION; @@ -379,7 +394,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...) va_list arg; long *param_longp = NULL; double *param_doublep = NULL; - char **param_charp = NULL; + const char **param_charp = NULL; struct curl_slist **param_slistp = NULL; curl_socket_t *param_socketp = NULL; int type; @@ -393,7 +408,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...) type = CURLINFO_TYPEMASK & (int)info; switch(type) { case CURLINFO_STRING: - param_charp = va_arg(arg, char **); + param_charp = va_arg(arg, const char **); if(param_charp) result = getinfo_char(data, info, param_charp); break; diff --git a/Utilities/cmcurl/lib/gopher.c b/Utilities/cmcurl/lib/gopher.c index a073d0ba2..e6d274648 100644 --- a/Utilities/cmcurl/lib/gopher.c +++ b/Utilities/cmcurl/lib/gopher.c @@ -78,7 +78,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) curl_off_t *bytecount = &data->req.bytecount; char *path = data->state.path; - char *sel; + char *sel = NULL; char *sel_org = NULL; ssize_t amount, k; size_t len; @@ -106,8 +106,8 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) /* ... and finally unescape */ result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE); - if(!sel) - return CURLE_OUT_OF_MEMORY; + if(result) + return result; sel_org = sel; } diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c index 937381b65..6afeaa12c 100644 --- a/Utilities/cmcurl/lib/hash.c +++ b/Utilities/cmcurl/lib/hash.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,8 +37,6 @@ 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; - Curl_safefree(e->key); - if(e->ptr) { h->dtor(e->ptr); e->ptr = NULL; @@ -74,54 +72,32 @@ 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) { - for(i = 0; i < slots; ++i) { - h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor); - if(!h->table[i]) { - while(i--) { - Curl_llist_destroy(h->table[i], NULL); - h->table[i] = NULL; - } - free(h->table); - h->table = NULL; - h->slots = 0; - return 1; /* failure */ - } - } + for(i = 0; i < slots; ++i) + Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor); return 0; /* fine */ } - else { - h->slots = 0; - return 1; /* failure */ - } + h->slots = 0; + return 1; /* failure */ } static struct curl_hash_element * mk_hash_element(const void *key, size_t key_len, const void *p) { - struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element)); - + /* allocate the struct plus memory after it to store the key */ + struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element) + + key_len); if(he) { - void *dupkey = malloc(key_len); - if(dupkey) { - /* copy the key */ - memcpy(dupkey, key, key_len); - - he->key = dupkey; - he->key_len = key_len; - he->ptr = (void *) p; - } - else { - /* failed to duplicate the key, free memory and fail */ - free(he); - he = NULL; - } + /* copy the key */ + memcpy(he->key, key, key_len); + he->key_len = key_len; + he->ptr = (void *) p; } return he; } -#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)] +#define FETCH_LIST(x,y,z) &x->table[x->hash_func(y, z, x->slots)] /* Insert the data in the hash. If there already was a match in the hash, * that data is replaced. @@ -135,7 +111,7 @@ 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_llist *l = FETCH_LIST(h, key, key_len); for(le = l->head; le; le = le->next) { he = (struct curl_hash_element *) le->ptr; @@ -148,18 +124,9 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p) he = mk_hash_element(key, key_len, p); if(he) { - if(Curl_llist_insert_next(l, l->tail, he)) { - ++h->size; - return p; /* return the new entry */ - } - /* - * Couldn't insert it, destroy the 'he' element and the key again. We - * don't call hash_element_dtor() since that would also call the - * "destructor" for the actual data 'p'. When we fail, we shall not touch - * that data. - */ - free(he->key); - free(he); + Curl_llist_insert_next(l, l->tail, he, &he->list); + ++h->size; + return p; /* return the new entry */ } return NULL; /* failure */ @@ -243,8 +210,7 @@ Curl_hash_destroy(struct curl_hash *h) int i; for(i = 0; i < h->slots; ++i) { - Curl_llist_destroy(h->table[i], (void *) h); - h->table[i] = NULL; + Curl_llist_destroy(&h->table[i], (void *) h); } Curl_safefree(h->table); @@ -276,7 +242,7 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, return; for(i = 0; i < h->slots; ++i) { - list = h->table[i]; + list = &h->table[i]; le = list->head; /* get first list entry */ while(le) { struct curl_hash_element *he = le->ptr; @@ -291,9 +257,9 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, } } -size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num) +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num) { - const char* key_str = (const char *) key; + const char *key_str = (const char *) key; const char *end = key_str + key_length; unsigned long h = 5381; @@ -335,8 +301,8 @@ Curl_hash_next_element(struct curl_hash_iterator *iter) /* If we have reached the end of the list, find the next one */ if(!iter->current_element) { for(i = iter->slot_index;i < h->slots;i++) { - if(h->table[i]->head) { - iter->current_element = h->table[i]->head; + if(h->table[i].head) { + iter->current_element = h->table[i].head; iter->slot_index = i+1; break; } @@ -347,10 +313,8 @@ Curl_hash_next_element(struct curl_hash_iterator *iter) struct curl_hash_element *he = iter->current_element->ptr; return he; } - else { - iter->current_element = NULL; - return NULL; - } + iter->current_element = NULL; + return NULL; } #if 0 /* useful function for debugging hashes and their contents */ diff --git a/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h index 57a17f02a..90a25d1ca 100644 --- a/Utilities/cmcurl/lib/hash.h +++ b/Utilities/cmcurl/lib/hash.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,22 +29,22 @@ #include "llist.h" /* Hash function prototype */ -typedef size_t (*hash_function) (void* key, +typedef size_t (*hash_function) (void *key, size_t key_length, size_t slots_num); /* Comparator function prototype. Compares two keys. */ -typedef size_t (*comp_function) (void* key1, +typedef size_t (*comp_function) (void *key1, size_t key1_len, - void*key2, + void *key2, size_t key2_len); typedef void (*curl_hash_dtor)(void *); struct curl_hash { - struct curl_llist **table; + struct curl_llist *table; /* Hash function to be used for this hash table */ hash_function hash_func; @@ -57,9 +57,10 @@ struct curl_hash { }; struct curl_hash_element { + struct curl_llist_element list; void *ptr; - char *key; size_t key_len; + char key[1]; /* allocated memory following the struct */ }; struct curl_hash_iterator { @@ -76,7 +77,7 @@ int Curl_hash_init(struct curl_hash *h, 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_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)); int Curl_hash_count(struct curl_hash *h); @@ -84,10 +85,9 @@ 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 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 * diff --git a/Utilities/cmcurl/lib/hmac.c b/Utilities/cmcurl/lib/hmac.c index 3df471585..dae95054b 100644 --- a/Utilities/cmcurl/lib/hmac.c +++ b/Utilities/cmcurl/lib/hmac.c @@ -49,12 +49,12 @@ static const unsigned char hmac_opad = 0x5C; HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams, - const unsigned char * key, + const unsigned char *key, unsigned int keylen) { size_t i; - HMAC_context * ctxt; - unsigned char * hkey; + HMAC_context *ctxt; + unsigned char *hkey; unsigned char b; /* Create HMAC context. */ @@ -101,7 +101,7 @@ Curl_HMAC_init(const HMAC_params * hashparams, } int Curl_HMAC_update(HMAC_context * ctxt, - const unsigned char * data, + const unsigned char *data, unsigned int len) { /* Update first hash calculation. */ @@ -110,7 +110,7 @@ int Curl_HMAC_update(HMAC_context * ctxt, } -int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result) +int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result) { const HMAC_params * hashparams = ctxt->hmac_hash; diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c index f545254f3..156091ca8 100644 --- a/Utilities/cmcurl/lib/hostcheck.c +++ b/Utilities/cmcurl/lib/hostcheck.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,7 +22,10 @@ #include "curl_setup.h" -#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT) +#if defined(USE_OPENSSL) \ + || defined(USE_AXTLS) \ + || defined(USE_GSKIT) \ + || (defined(USE_SCHANNEL) && defined(_WIN32_WCE)) /* these backends use functions from this file */ #ifdef HAVE_NETINET_IN_H @@ -84,7 +87,7 @@ static int hostmatch(char *hostname, char *pattern) if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0) return CURL_HOST_NOMATCH; #ifdef ENABLE_IPV6 - else if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0) + if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0) return CURL_HOST_NOMATCH; #endif @@ -144,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) return res; } -#endif /* OPENSSL or AXTLS or GSKIT */ +#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */ diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c index 24a922eb2..619ec84b5 100644 --- a/Utilities/cmcurl/lib/hostip.c +++ b/Utilities/cmcurl/lib/hostip.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -143,7 +143,7 @@ void Curl_global_host_cache_dtor(void) } /* - * Return # of adresses in a Curl_addrinfo struct + * Return # of addresses in a Curl_addrinfo struct */ int Curl_num_addresses(const Curl_addrinfo *addr) { @@ -172,7 +172,7 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) const struct in6_addr *ipaddr6; #endif - switch (ai->ai_family) { + switch(ai->ai_family) { case AF_INET: sa4 = (const void *)ai->ai_addr; ipaddr4 = &sa4->sin_addr; @@ -538,7 +538,6 @@ RETSIGTYPE alarmfunc(int sig) /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ (void)sig; siglongjmp(curl_jmpenv, 1); - return; } #endif /* USE_ALARM_TIMEOUT */ @@ -568,12 +567,12 @@ int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **entry, - long timeoutms) + time_t timeoutms) { #ifdef USE_ALARM_TIMEOUT #ifdef HAVE_SIGACTION struct sigaction keep_sigact; /* store the old struct here */ - volatile bool keep_copysig = FALSE; /* wether old sigact has been saved */ + volatile bool keep_copysig = FALSE; /* whether old sigact has been saved */ struct sigaction sigact; #else #ifdef HAVE_SIGNAL @@ -597,7 +596,7 @@ int Curl_resolv_timeout(struct connectdata *conn, /* Ignore the timeout when signals are disabled */ timeout = 0; else - timeout = timeoutms; + timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms; if(!timeout) /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ @@ -689,10 +688,11 @@ clean_up: the time we spent until now! */ if(prev_alarm) { /* there was an alarm() set before us, now put it back */ - unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created); + unsigned long elapsed_secs = (unsigned long) (Curl_tvdiff(Curl_tvnow(), + conn->created) / 1000); /* the alarm period is counted in even number of seconds */ - unsigned long alarm_set = prev_alarm - elapsed_ms/1000; + unsigned long alarm_set = prev_alarm - elapsed_secs; if(!alarm_set || ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) { diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h index 9098ee39d..298eeeee3 100644 --- a/Utilities/cmcurl/lib/hostip.h +++ b/Utilities/cmcurl/lib/hostip.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -87,7 +87,7 @@ int Curl_resolv(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **dnsentry); int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **dnsentry, - long timeoutms); + time_t timeoutms); #ifdef CURLRES_IPV6 /* @@ -130,8 +130,8 @@ int Curl_mk_dnscache(struct curl_hash *hash); /* prune old entries from the DNS cache */ void Curl_hostcache_prune(struct Curl_easy *data); -/* Return # of adresses in a Curl_addrinfo struct */ -int Curl_num_addresses (const Curl_addrinfo *addr); +/* Return # of addresses in a Curl_addrinfo struct */ +int Curl_num_addresses(const Curl_addrinfo *addr); #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, @@ -143,7 +143,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, #endif /* IPv4 threadsafe resolve function used for synch and asynch builds */ -Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port); +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); CURLcode Curl_async_resolved(struct connectdata *conn, bool *protocol_connect); diff --git a/Utilities/cmcurl/lib/hostip4.c b/Utilities/cmcurl/lib/hostip4.c index 15895d7ce..e459328ac 100644 --- a/Utilities/cmcurl/lib/hostip4.c +++ b/Utilities/cmcurl/lib/hostip4.c @@ -291,7 +291,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, * gethostbyname() is the preferred one. */ else { - h = gethostbyname((void*)hostname); + h = gethostbyname((void *)hostname); #endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ } diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c index e7788e767..21574e21d 100644 --- a/Utilities/cmcurl/lib/http.c +++ b/Utilities/cmcurl/lib/http.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -76,6 +76,7 @@ #include "pipeline.h" #include "http2.h" #include "connect.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -284,11 +285,12 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) const char *user; const char *pwd; CURLcode result; + char *out; if(proxy) { userp = &conn->allocptr.proxyuserpwd; - user = conn->proxyuser; - pwd = conn->proxypasswd; + user = conn->http_proxy.user; + pwd = conn->http_proxy.passwd; } else { userp = &conn->allocptr.userpwd; @@ -296,26 +298,32 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) pwd = conn->passwd; } - snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); + out = aprintf("%s:%s", user, pwd); + if(!out) + return CURLE_OUT_OF_MEMORY; - result = Curl_base64_encode(data, - data->state.buffer, strlen(data->state.buffer), - &authorization, &size); + result = Curl_base64_encode(data, out, strlen(out), &authorization, &size); if(result) - return result; + goto fail; - if(!authorization) - return CURLE_REMOTE_ACCESS_DENIED; + if(!authorization) { + result = CURLE_REMOTE_ACCESS_DENIED; + goto fail; + } free(*userp); *userp = aprintf("%sAuthorization: Basic %s\r\n", proxy ? "Proxy-" : "", authorization); free(authorization); - if(!*userp) - return CURLE_OUT_OF_MEMORY; + if(!*userp) { + result = CURLE_OUT_OF_MEMORY; + goto fail; + } - return CURLE_OK; + fail: + free(out); + return result; } /* pickoneauth() selects the most favourable authentication method from the @@ -411,8 +419,6 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) case HTTPREQ_POST: if(data->state.infilesize != -1) expectsend = data->state.infilesize; - else if(data->set.postfields) - expectsend = (curl_off_t)strlen(data->set.postfields); break; case HTTPREQ_PUT: if(data->state.infilesize != -1) @@ -544,8 +550,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) } } if(http_should_fail(conn)) { - failf (data, "The requested URL returned error: %d", - data->req.httpcode); + failf(data, "The requested URL returned error: %d", + data->req.httpcode); result = CURLE_HTTP_RETURNED_ERROR; } @@ -641,12 +647,12 @@ output_auth_headers(struct connectdata *conn, if(auth) { infof(data, "%s auth using %s with user '%s'\n", proxy ? "Proxy" : "Server", auth, - proxy ? (conn->proxyuser ? conn->proxyuser : "") : + proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") : (conn->user ? conn->user : "")); - authstatus->multi = (!authstatus->done) ? TRUE : FALSE; + authstatus->multipass = (!authstatus->done) ? TRUE : FALSE; } else - authstatus->multi = FALSE; + authstatus->multipass = FALSE; return CURLE_OK; } @@ -839,9 +845,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, auth += strlen("NTLM"); while(*auth && ISSPACE(*auth)) auth++; - if(*auth) - if((conn->challenge_header = strdup(auth)) == NULL) + if(*auth) { + conn->challenge_header = strdup(auth); + if(!conn->challenge_header) return CURLE_OUT_OF_MEMORY; + } } } #endif @@ -1098,14 +1106,16 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, return result; } - if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) { + if((conn->handler->flags & PROTOPT_SSL || + conn->http_proxy.proxytype == CURLPROXY_HTTPS) + && conn->httpversion != 20) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk when we speak HTTPS, as if only a fraction of it is sent now, this data needs to fit into the normal read-callback buffer later on and that buffer is using this size. */ - sendsize = (size > CURL_MAX_WRITE_SIZE) ? CURL_MAX_WRITE_SIZE : size; + sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE); /* OpenSSL is very picky and we must send the SAME buffer pointer to the library when we attempt to re-send this buffer. Sending the same data @@ -1191,8 +1201,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, This needs FIXing. */ return CURLE_SEND_ERROR; - else - Curl_pipeline_leave_write(conn); + Curl_pipeline_leave_write(conn); } } Curl_add_buffer_free(in); @@ -1255,14 +1264,13 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) if(in->buffer) /* we have a buffer, enlarge the existing one */ - new_rb = realloc(in->buffer, new_size); + new_rb = Curl_saferealloc(in->buffer, new_size); else /* create a new buffer */ new_rb = malloc(new_size); if(!new_rb) { /* If we failed, we cleanup the whole buffer and return error */ - Curl_safefree(in->buffer); free(in); return CURLE_OUT_OF_MEMORY; } @@ -1350,15 +1358,22 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) connkeep(conn, "HTTP default"); /* the CONNECT procedure might not have been completed */ - result = Curl_proxy_connect(conn); + result = Curl_proxy_connect(conn, FIRSTSOCKET); if(result) return result; + if(conn->bits.proxy_connect_closed) + /* this is not an error, just part of the connection negotiation */ + return CURLE_OK; + + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */ + if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; - if(conn->given->flags & PROTOPT_SSL) { + if(conn->given->protocol & CURLPROTO_HTTPS) { /* perform SSL initialization */ result = https_connecting(conn, done); if(result) @@ -1396,50 +1411,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) return result; } -#endif -#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ - defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \ - defined(USE_MBEDTLS) -/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only. - It should be made to query the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - if(conn->handler->flags & PROTOPT_SSL) { - struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; - - if(!numsocks) - return GETSOCK_BLANK; - - if(connssl->connecting_state == ssl_connect_2_writing) { - /* write mode */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_WRITESOCK(0); - } - else if(connssl->connecting_state == ssl_connect_2_reading) { - /* read mode */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_READSOCK(0); - } - } - - return CURLE_OK; -} -#else -#ifdef USE_SSL -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - (void)conn; - (void)socks; - (void)numsocks; + if(conn->handler->flags & PROTOPT_SSL) + return Curl_ssl_getsock(conn, socks, numsocks); return GETSOCK_BLANK; } #endif /* USE_SSL */ -#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */ /* * Curl_http_done() gets called after a single HTTP request has been @@ -1452,7 +1433,10 @@ CURLcode Curl_http_done(struct connectdata *conn, struct Curl_easy *data = conn->data; struct HTTP *http = data->req.protop; - infof(data, "Curl_http_done: called premature == %d\n", premature); + /* 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); @@ -1538,6 +1522,20 @@ static bool use_http_1_1plus(const struct Curl_easy *data, (data->set.httpversion >= CURL_HTTP_VERSION_1_1)); } +static const char *get_http_string(const struct Curl_easy *data, + const struct connectdata *conn) +{ +#ifdef USE_NGHTTP2 + if(conn->proto.httpc.h2) + return "2"; +#endif + + if(use_http_1_1plus(data, conn)) + return "1.1"; + + return "1.0"; +} + /* check and possibly add an Expect: header */ static CURLcode expect100(struct Curl_easy *data, struct connectdata *conn, @@ -1695,9 +1693,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, Curl_send_buffer *req_buffer) { const struct tm *tm; - char *buf = data->state.buffer; struct tm keeptime; CURLcode result; + char datestr[80]; + const char *condp; if(data->set.timecondition == CURL_TIMECOND_NONE) /* no condition was asked for */ @@ -1710,6 +1709,21 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, } tm = &keeptime; + switch(data->set.timecondition) { + default: + return CURLE_BAD_FUNCTION_ARGUMENT; + + case CURL_TIMECOND_IFMODSINCE: + condp = "If-Modified-Since"; + break; + case CURL_TIMECOND_IFUNMODSINCE: + condp = "If-Unmodified-Since"; + break; + case CURL_TIMECOND_LASTMOD: + condp = "Last-Modified"; + break; + } + /* The If-Modified-Since header family should have their times set in * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be * represented in Greenwich Mean Time (GMT), without exception. For the @@ -1718,8 +1732,9 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, */ /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - snprintf(buf, BUFSIZE-1, - "%s, %02d %s %4d %02d:%02d:%02d GMT", + snprintf(datestr, sizeof(datestr), + "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + condp, Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], tm->tm_mday, Curl_month[tm->tm_mon], @@ -1728,22 +1743,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, tm->tm_min, tm->tm_sec); - switch(data->set.timecondition) { - default: - break; - case CURL_TIMECOND_IFMODSINCE: - result = Curl_add_bufferf(req_buffer, - "If-Modified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_IFUNMODSINCE: - result = Curl_add_bufferf(req_buffer, - "If-Unmodified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_LASTMOD: - result = Curl_add_bufferf(req_buffer, - "Last-Modified: %s\r\n", buf); - break; - } + result = Curl_add_buffer(req_buffer, datestr, strlen(datestr)); return result; } @@ -1876,7 +1876,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) return result; - if((data->state.authhost.multi || data->state.authproxy.multi) && + if((data->state.authhost.multipass || data->state.authproxy.multipass) && (httpreq != HTTPREQ_GET) && (httpreq != HTTPREQ_HEAD)) { /* Auth is required and we are not authenticated yet. Make a PUT or POST @@ -2092,7 +2092,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* when doing ftp, append ;type= if not present */ char *type = strstr(ppath, ";type="); if(type && type[6] && type[7] == 0) { - switch (Curl_raw_toupper(type[6])) { + switch(Curl_raw_toupper(type[6])) { case 'A': case 'D': case 'I': @@ -2161,32 +2161,32 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } 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) */ - else { - curl_off_t passed=0; - do { - size_t readthisamountnow = - (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? - BUFSIZE : 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); - } + 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 */ @@ -2252,9 +2252,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } } - /* Use 1.1 unless the user specifically asked for 1.0 or the server only - supports 1.0 */ - httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0"; + httpstring = get_http_string(data, conn); /* initialize a dynamic send-buffer */ req_buffer = Curl_add_buffer_init(); @@ -2321,20 +2319,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) te ); - /* clear userpwd to avoid re-using credentials from re-used connections */ + /* clear userpwd and proxyuserpwd to avoid re-using old credentials + * from re-used connections */ Curl_safefree(conn->allocptr.userpwd); - - /* - * Free proxyuserpwd for Negotiate/NTLM. Cannot reuse as it is associated - * with the connection and shouldn't be repeated over it either. - */ - switch (data->state.authproxy.picked) { - case CURLAUTH_NEGOTIATE: - case CURLAUTH_NTLM: - case CURLAUTH_NTLM_WB: - Curl_safefree(conn->allocptr.proxyuserpwd); - break; - } + Curl_safefree(conn->allocptr.proxyuserpwd); if(result) return result; @@ -2528,7 +2516,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) postsize = data->state.infilesize; if((postsize != -1) && !data->req.upload_chunky && - !Curl_checkheaders(conn, "Content-Length:")) { + (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) { /* only add Content-Length if not uploading chunked */ result = Curl_add_bufferf(req_buffer, "Content-Length: %" CURL_FORMAT_CURL_OFF_T @@ -2569,18 +2557,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->bits.authneg) postsize = 0; - else { - /* figure out the size of the postfields */ - postsize = (data->state.infilesize != -1)? - data->state.infilesize: - (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1); - } + else + /* the size of the post body */ + 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 && - !Curl_checkheaders(conn, "Content-Length:")) { + (conn->bits.authneg || !Curl_checkheaders(conn, "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_add_bufferf(req_buffer, @@ -2756,6 +2741,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->req.upload_done = TRUE; data->req.keepon &= ~KEEP_SEND; /* we're done writing */ data->req.exp100 = EXP100_SEND_DATA; /* already sent */ + Curl_expire_done(data, EXPIRE_100_TIMEOUT); } } @@ -2782,7 +2768,7 @@ checkhttpprefix(struct Curl_easy *data, /* convert from the network encoding using a scratch area */ char *scratch = strdup(s); if(NULL == scratch) { - failf (data, "Failed to allocate memory for conversion!"); + failf(data, "Failed to allocate memory for conversion!"); return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { @@ -2820,7 +2806,7 @@ checkrtspprefix(struct Curl_easy *data, /* convert from the network encoding using a scratch area */ char *scratch = strdup(s); if(NULL == scratch) { - failf (data, "Failed to allocate memory for conversion!"); + failf(data, "Failed to allocate memory for conversion!"); return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { @@ -2834,8 +2820,7 @@ checkrtspprefix(struct Curl_easy *data, #endif /* CURL_DOES_CONVERSIONS */ if(checkprefix("RTSP/", s)) return TRUE; - else - return FALSE; + return FALSE; } #endif /* CURL_DISABLE_RTSP */ @@ -2872,8 +2857,8 @@ static CURLcode header_append(struct Curl_easy *data, /* The reason to have a max limit for this is to avoid the risk of a bad server feeding libcurl with a never-ending header that will cause reallocs infinitely */ - failf (data, "Avoided giant realloc for header (max is %d)!", - CURL_MAX_HTTP_HEADER); + failf(data, "Avoided giant realloc for header (max is %d)!", + CURL_MAX_HTTP_HEADER); return CURLE_OUT_OF_MEMORY; } @@ -2881,7 +2866,7 @@ static CURLcode header_append(struct Curl_easy *data, hbufp_index = k->hbufp - data->state.headerbuff; newbuff = realloc(data->state.headerbuff, newsize); if(!newbuff) { - failf (data, "Failed to alloc memory for big header!"); + failf(data, "Failed to alloc memory for big header!"); return CURLE_OUT_OF_MEMORY; } data->state.headersize=newsize; @@ -3053,6 +3038,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(k->exp100 > EXP100_SEND_DATA) { k->exp100 = EXP100_SEND_DATA; k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); } break; case 101: @@ -3122,8 +3108,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * up and return an error. */ if(http_should_fail(conn)) { - failf (data, "The requested URL returned error: %d", - k->httpcode); + failf(data, "The requested URL returned error: %d", + k->httpcode); return CURLE_HTTP_RETURNED_ERROR; } @@ -3179,6 +3165,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * request body has been sent we stop sending and mark the * connection for closure after we've read the entire response. */ + Curl_expire_done(data, EXPIRE_100_TIMEOUT); if(!k->upload_done) { if(data->set.http_keep_sending_on_error) { infof(data, "HTTP error before end of send, keep sending\n"); @@ -3256,9 +3243,17 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, k->maxdownload = k->size; } - /* If max download size is *zero* (nothing) we already - have nothing and can safely return ok now! */ - if(0 == k->maxdownload) + /* If max download size is *zero* (nothing) we already have + nothing and can safely return ok now! But for HTTP/2, we'd + like to call http2_handle_stream_close to properly close a + stream. In order to do this, we keep reading until we + close the stream. */ + if(0 == k->maxdownload +#if defined(USE_NGHTTP2) + && !((conn->handler->protocol & PROTO_FAMILY_HTTP) && + conn->httpversion == 20) +#endif + ) *stop_reading = TRUE; if(*stop_reading) { @@ -3315,7 +3310,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, /* * https://tools.ietf.org/html/rfc7230#section-3.1.2 * - * The reponse code is always a three-digit number in HTTP as the spec + * The response code is always a three-digit number in HTTP as the spec * says. We try to allow any number here, but we cannot make * guarantees on future behaviors since it isn't within the protocol. */ diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h index 9fb669c9d..7ce4bd9a0 100644 --- a/Utilities/cmcurl/lib/http.h +++ b/Utilities/cmcurl/lib/http.h @@ -219,6 +219,10 @@ struct http_conn { /* this is a hash of all individual streams (Curl_easy structs) */ struct h2settings settings; + + /* list of settings that will be sent */ + nghttp2_settings_entry local_settings[3]; + size_t local_settings_num; #else int unused; /* prevent a compiler warning */ #endif diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c index cfdb3276a..f8e23c517 100644 --- a/Utilities/cmcurl/lib/http2.c +++ b/Utilities/cmcurl/lib/http2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,7 +35,7 @@ #include "url.h" #include "connect.h" #include "strtoofft.h" - +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -59,6 +59,12 @@ #define nghttp2_session_callbacks_set_error_callback(x,y) #endif +#if (NGHTTP2_VERSION_NUM >= 0x010c00) +#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1 +#endif + +#define HTTP2_HUGE_WINDOW_SIZE (1 << 30) + /* * Curl_http2_init_state() is called when the easy handle is created and * allows for HTTP/2 specific init of state. @@ -110,18 +116,11 @@ static int http2_getsock(struct connectdata *conn, return http2_perform_getsock(conn, sock, numsocks); } -static CURLcode http2_disconnect(struct connectdata *conn, - bool dead_connection) +/* + * http2_stream_free() free HTTP2 stream related data + */ +static void http2_stream_free(struct HTTP *http) { - struct HTTP *http = conn->data->req.protop; - struct http_conn *c = &conn->proto.httpc; - (void)dead_connection; - - DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); - - nghttp2_session_del(c->h2); - Curl_safefree(c->inbuf); - if(http) { Curl_add_buffer_free(http->header_recvbuf); http->header_recvbuf = NULL; /* clear the pointer */ @@ -133,6 +132,19 @@ static CURLcode http2_disconnect(struct connectdata *conn, free(http->push_headers); http->push_headers = NULL; } +} + +static CURLcode http2_disconnect(struct connectdata *conn, + bool dead_connection) +{ + struct http_conn *c = &conn->proto.httpc; + (void)dead_connection; + + DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); + + nghttp2_session_del(c->h2); + Curl_safefree(c->inbuf); + http2_stream_free(conn->data->req.protop); DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); @@ -153,7 +165,7 @@ void Curl_http2_setup_req(struct Curl_easy *data) http->closed = FALSE; http->close_handled = FALSE; http->mem = data->state.buffer; - http->len = BUFSIZE; + http->len = data->set.buffer_size; http->memlen = 0; } @@ -169,7 +181,7 @@ void Curl_http2_setup_conn(struct connectdata *conn) * but will be used at run-time when the protocol is dynamically switched from * HTTP to HTTP2. */ -const struct Curl_handler Curl_handler_http2 = { +static const struct Curl_handler Curl_handler_http2 = { "HTTP", /* scheme */ ZERO_NULL, /* setup_connection */ Curl_http, /* do_it */ @@ -189,7 +201,7 @@ const struct Curl_handler Curl_handler_http2 = { PROTOPT_STREAM /* flags */ }; -const struct Curl_handler Curl_handler_http2_ssl = { +static const struct Curl_handler Curl_handler_http2_ssl = { "HTTPS", /* scheme */ ZERO_NULL, /* setup_connection */ Curl_http, /* do_it */ @@ -223,7 +235,8 @@ int Curl_http2_ver(char *p, size_t len) https://tools.ietf.org/html/rfc7540#page-77 nghttp2_error_code enums are identical. */ -const char *Curl_http2_strerror(uint32_t err) { +const char *Curl_http2_strerror(uint32_t err) +{ #ifndef NGHTTP2_HAS_HTTP2_STRERROR const char *str[] = { "NO_ERROR", /* 0x0 */ @@ -395,6 +408,7 @@ static int push_promise(struct Curl_easy *data, stream = data->req.protop; if(!stream) { failf(data, "Internal NULL stream!\n"); + (void)Curl_close(newhandle); rv = 1; goto fail; } @@ -408,9 +422,11 @@ static int push_promise(struct Curl_easy *data, free(stream->push_headers[i]); free(stream->push_headers); stream->push_headers = NULL; + stream->push_headers_used = 0; if(rv) { /* denied, kill off the new handle again */ + http2_stream_free(newhandle->req.protop); (void)Curl_close(newhandle); goto fail; } @@ -425,6 +441,7 @@ 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); Curl_close(newhandle); rv = 1; goto fail; @@ -552,7 +569,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, /* if we receive data for another handle, wake that up */ if(conn_s->data != data_s) - Curl_expire(data_s, 0); + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); } break; case NGHTTP2_PUSH_PROMISE: @@ -580,6 +597,9 @@ static int on_invalid_frame_recv(nghttp2_session *session, { struct Curl_easy *data_s = NULL; (void)userp; +#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)lib_error_code; +#endif data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); if(data_s) { @@ -626,7 +646,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, /* if we receive data for another handle, wake that up */ if(conn->data != data_s) - Curl_expire(data_s, 0); + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); DEBUGF(infof(data_s, "%zu data received for stream %u " "(%zu left in buffer %p, total %zu)\n", @@ -690,6 +710,9 @@ static int on_frame_not_send(nghttp2_session *session, { struct Curl_easy *data_s; (void)userp; +#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS) + (void)lib_error_code; +#endif data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); if(data_s) { @@ -761,7 +784,7 @@ static int on_begin_headers(nghttp2_session *session, /* This is trailer HEADERS started. Allocate buffer for them. */ DEBUGF(infof(data_s, "trailer field started\n")); - assert(stream->trailer_recvbuf == NULL); + DEBUGASSERT(stream->trailer_recvbuf == NULL); stream->trailer_recvbuf = Curl_add_buffer_init(); if(!stream->trailer_recvbuf) { @@ -841,10 +864,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, stream->push_headers_alloc) { char **headp; stream->push_headers_alloc *= 2; - headp = realloc(stream->push_headers, - stream->push_headers_alloc * sizeof(char *)); + headp = Curl_saferealloc(stream->push_headers, + stream->push_headers_alloc * sizeof(char *)); if(!headp) { - free(stream->push_headers); stream->push_headers = NULL; return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } @@ -887,7 +909,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, Curl_add_buffer(stream->header_recvbuf, " \r\n", 3); /* if we receive data for another handle, wake that up */ if(conn->data != data_s) - Curl_expire(data_s, 0); + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n", stream->status_code, data_s)); @@ -903,7 +925,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, Curl_add_buffer(stream->header_recvbuf, "\r\n", 2); /* if we receive data for another handle, wake that up */ if(conn->data != data_s) - Curl_expire(data_s, 0); + Curl_expire(data_s, 0, EXPIRE_RUN_NOW); DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen, value)); @@ -961,14 +983,6 @@ static ssize_t data_source_read_callback(nghttp2_session *session, return nread; } -/* - * The HTTP2 settings we send in the Upgrade request - */ -static nghttp2_settings_entry settings[] = { - { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }, - { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE }, -}; - #define H2_BUFSIZE 32768 #ifdef NGHTTP2_HAS_ERROR_CALLBACK @@ -984,6 +998,23 @@ static int error_callback(nghttp2_session *session, } #endif +static void populate_settings(struct connectdata *conn, + struct http_conn *httpc) +{ + nghttp2_settings_entry *iv = httpc->local_settings; + + iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; + iv[0].value = 100; + + iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + iv[1].value = HTTP2_HUGE_WINDOW_SIZE; + + iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; + iv[2].value = conn->data->multi->push_cb != NULL; + + httpc->local_settings_num = 3; +} + void Curl_http2_done(struct connectdata *conn, bool premature) { struct Curl_easy *data = conn->data; @@ -1097,16 +1128,14 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, size_t blen; struct SingleRequest *k = &conn->data->req; uint8_t *binsettings = conn->proto.httpc.binsettings; + struct http_conn *httpc = &conn->proto.httpc; - /* As long as we have a fixed set of settings, we don't have to dynamically - * figure out the base64 strings since it'll always be the same. However, - * the settings will likely not be fixed every time in the future. - */ + populate_settings(conn, httpc); /* this returns number of bytes it wrote */ binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, - settings, - sizeof(settings)/sizeof(settings[0])); + httpc->local_settings, + httpc->local_settings_num); if(!binlen) { failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); return CURLE_FAILED_INIT; @@ -1424,7 +1453,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, infof(data, "%zu data bytes written\n", nread); if(stream->pauselen == 0) { DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id)); - assert(httpc->pause_stream_id == stream->stream_id); + DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); httpc->pause_stream_id = 0; stream->pausedata = NULL; @@ -1572,6 +1601,72 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, #define HEADER_OVERFLOW(x) \ (x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen) +/* + * Check header memory for the token "trailers". + * Parse the tokens as separated by comma and surrounded by whitespace. + * Returns TRUE if found or FALSE if not. + */ +static bool contains_trailers(const char *p, size_t len) +{ + const char *end = p + len; + for(;;) { + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || (size_t)(end - p) < sizeof("trailers") - 1) + return FALSE; + if(strncasecompare("trailers", p, sizeof("trailers") - 1)) { + p += sizeof("trailers") - 1; + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || *p == ',') + return TRUE; + } + /* skip to next token */ + for(; p != end && *p != ','; ++p) + ; + if(p == end) + return FALSE; + ++p; + } +} + +typedef enum { + /* Send header to server */ + HEADERINST_FORWARD, + /* Don't send header to server */ + HEADERINST_IGNORE, + /* Discard header, and replace it with "te: trailers" */ + HEADERINST_TE_TRAILERS +} header_instruction; + +/* Decides how to treat given header field. */ +static header_instruction inspect_header(const char *name, size_t namelen, + const char *value, size_t valuelen) { + switch(namelen) { + case 2: + if(!strncasecompare("te", name, namelen)) + return HEADERINST_FORWARD; + + return contains_trailers(value, valuelen) ? + HEADERINST_TE_TRAILERS : HEADERINST_IGNORE; + case 7: + return strncasecompare("upgrade", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 10: + return (strncasecompare("connection", name, namelen) || + strncasecompare("keep-alive", name, namelen)) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 16: + return strncasecompare("proxy-connection", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 17: + return strncasecompare("transfer-encoding", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + default: + return HEADERINST_FORWARD; + } +} + static ssize_t http2_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, CURLcode *err) { @@ -1587,7 +1682,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, size_t nheader; size_t i; size_t authority_idx; - char *hdbuf = (char*)mem; + char *hdbuf = (char *)mem; char *end, *line_end; nghttp2_data_provider data_prd; int32_t stream_id; @@ -1725,7 +1820,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, i = 3; while(i < nheader) { size_t hlen; - int skip = 0; hdbuf = line_end + 2; @@ -1743,12 +1837,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, goto fail; hlen = end - hdbuf; - if(hlen == 10 && strncasecompare("connection", hdbuf, 10)) { - /* skip Connection: headers! */ - skip = 1; - --nheader; - } - else if(hlen == 4 && strncasecompare("host", hdbuf, 4)) { + if(hlen == 4 && strncasecompare("host", hdbuf, 4)) { authority_idx = i; nva[i].name = (unsigned char *)":authority"; nva[i].namelen = strlen((char *)nva[i].name); @@ -1761,16 +1850,28 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, while(*hdbuf == ' ' || *hdbuf == '\t') ++hdbuf; end = line_end; - if(!skip) { + + switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf, + end - hdbuf)) { + case HEADERINST_IGNORE: + /* skip header fields prohibited by HTTP/2 specification. */ + --nheader; + continue; + case HEADERINST_TE_TRAILERS: + nva[i].value = (uint8_t*)"trailers"; + nva[i].valuelen = sizeof("trailers") - 1; + break; + default: nva[i].value = (unsigned char *)hdbuf; nva[i].valuelen = (size_t)(end - hdbuf); - nva[i].flags = NGHTTP2_NV_FLAG_NONE; - if(HEADER_OVERFLOW(nva[i])) { - failf(conn->data, "Failed sending HTTP request: Header overflow"); - goto fail; - } - ++i; } + + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[i])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + ++i; } /* :authority must come before non-pseudo header fields */ @@ -1784,28 +1885,22 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, /* Warn stream may be rejected if cumulative length of headers is too large. It appears nghttp2 will not send a header frame larger than 64KB. */ +#define MAX_ACC 60000 /* <64KB to account for some overhead */ { size_t acc = 0; - const size_t max_acc = 60000; /* <64KB to account for some overhead */ for(i = 0; i < nheader; ++i) { - if(nva[i].namelen > max_acc - acc) - break; - acc += nva[i].namelen; - - if(nva[i].valuelen > max_acc - acc) - break; - acc += nva[i].valuelen; + acc += nva[i].namelen + nva[i].valuelen; DEBUGF(infof(conn->data, "h2 header: %.*s:%.*s\n", nva[i].namelen, nva[i].name, nva[i].valuelen, nva[i].value)); } - if(i != nheader) { + if(acc > MAX_ACC) { infof(conn->data, "http2_send: Warning: The cumulative length of all " - "headers exceeds %zu bytes and that could cause the " - "stream to be rejected.\n", max_acc); + "headers exceeds %zu bytes and that could cause the " + "stream to be rejected.\n", MAX_ACC); } } @@ -1959,9 +2054,13 @@ CURLcode Curl_http2_switched(struct connectdata *conn, conn->data); } else { + populate_settings(conn, httpc); + /* stream ID is unknown at this point */ stream->stream_id = -1; - rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0); + rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, + httpc->local_settings, + httpc->local_settings_num); if(rv != 0) { failf(data, "nghttp2_submit_settings() failed: %s(%d)", nghttp2_strerror(rv), rv); @@ -1969,6 +2068,16 @@ CURLcode Curl_http2_switched(struct connectdata *conn, } } +#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE + rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0, + HTTP2_HUGE_WINDOW_SIZE); + if(rv != 0) { + failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } +#endif + /* we are going to copy mem to httpc->inbuf. This is required since mem is part of buffer pointed by stream->mem, and callbacks called by nghttp2_session_mem_recv() will write stream specific @@ -1984,7 +2093,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn, " after upgrade: len=%zu\n", nread); - memcpy(httpc->inbuf, mem, nread); + if(nread) + memcpy(httpc->inbuf, mem, nread); httpc->inbuflen = nread; nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf, @@ -2024,6 +2134,84 @@ CURLcode Curl_http2_switched(struct connectdata *conn, return CURLE_OK; } +void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child, + bool exclusive) +{ + if(parent) { + struct Curl_http2_dep **tail; + struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep)); + dep->data = child; + + if(parent->set.stream_dependents && exclusive) { + struct Curl_http2_dep *node = parent->set.stream_dependents; + while(node) { + node->data->set.stream_depends_on = child; + node = node->next; + } + + tail = &child->set.stream_dependents; + while(*tail) + tail = &(*tail)->next; + + DEBUGASSERT(!*tail); + *tail = parent->set.stream_dependents; + parent->set.stream_dependents = 0; + } + + tail = &parent->set.stream_dependents; + while(*tail) { + (*tail)->data->set.stream_depends_e = FALSE; + tail = &(*tail)->next; + } + + DEBUGASSERT(!*tail); + *tail = dep; + } + + child->set.stream_depends_on = parent; + child->set.stream_depends_e = exclusive; +} + +void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child) +{ + struct Curl_http2_dep *last = 0; + struct Curl_http2_dep *data = parent->set.stream_dependents; + DEBUGASSERT(child->set.stream_depends_on == parent); + + while(data && data->data != child) { + last = data; + data = data->next; + } + + DEBUGASSERT(data); + + if(data) { + if(last) { + last->next = data->next; + } + else { + parent->set.stream_dependents = data->next; + } + free(data); + } + + child->set.stream_depends_on = 0; + child->set.stream_depends_e = FALSE; +} + +void Curl_http2_cleanup_dependencies(struct Curl_easy *data) +{ + while(data->set.stream_dependents) { + struct Curl_easy *tmp = data->set.stream_dependents->data; + Curl_http2_remove_child(data, tmp); + if(data->set.stream_depends_on) + Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE); + } + + if(data->set.stream_depends_on) + Curl_http2_remove_child(data->set.stream_depends_on, data); +} + #else /* !USE_NGHTTP2 */ /* Satisfy external references even if http2 is not compiled in. */ diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h index 891753590..f405b3aeb 100644 --- a/Utilities/cmcurl/lib/http2.h +++ b/Utilities/cmcurl/lib/http2.h @@ -53,6 +53,11 @@ void Curl_http2_setup_conn(struct connectdata *conn); void Curl_http2_setup_req(struct Curl_easy *data); void Curl_http2_done(struct connectdata *conn, bool premature); CURLcode Curl_http2_done_sending(struct connectdata *conn); +void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child, + bool exclusive); +void Curl_http2_remove_child(struct Curl_easy *parent, + struct Curl_easy *child); +void Curl_http2_cleanup_dependencies(struct Curl_easy *data); #else /* USE_NGHTTP2 */ #define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL @@ -65,6 +70,9 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn); #define Curl_http2_init_userset(x) #define Curl_http2_done(x,y) #define Curl_http2_done_sending(x) +#define Curl_http2_add_child(x, y, z) +#define Curl_http2_remove_child(x, y) +#define Curl_http2_cleanup_dependencies(x) #endif #endif /* HEADER_CURL_HTTP2_H */ diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c index ea171092b..1bdf6974c 100644 --- a/Utilities/cmcurl/lib/http_chunks.c +++ b/Utilities/cmcurl/lib/http_chunks.c @@ -190,8 +190,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, /* Write the data portion available */ #ifdef HAVE_LIBZ - switch (conn->data->set.http_ce_skip? - IDENTITY : data->req.auto_decoding) { + switch(conn->data->set.http_ce_skip? + IDENTITY : data->req.auto_decoding) { case IDENTITY: #endif if(!k->ignorebody) { @@ -219,10 +219,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, break; default: - failf (conn->data, - "Unrecognized content encoding type. " - "libcurl understands `identity', `deflate' and `gzip' " - "content encodings."); + failf(conn->data, + "Unrecognized content encoding type. " + "libcurl understands `identity', `deflate' and `gzip' " + "content encodings."); return CHUNKE_BAD_ENCODING; } #endif @@ -360,7 +360,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, const char *Curl_chunked_strerror(CHUNKcode code) { - switch (code) { + switch(code) { default: return "OK"; case CHUNKE_TOO_LONG_HEX: diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c index 184d00b28..e2d865b0a 100644 --- a/Utilities/cmcurl/lib/http_digest.c +++ b/Utilities/cmcurl/lib/http_digest.c @@ -74,8 +74,8 @@ CURLcode Curl_output_digest(struct connectdata *conn, { CURLcode result; struct Curl_easy *data = conn->data; - unsigned char *path; - char *tmp; + unsigned char *path = NULL; + char *tmp = NULL; char *response; size_t len; bool have_chlg; @@ -95,8 +95,8 @@ CURLcode Curl_output_digest(struct connectdata *conn, if(proxy) { digest = &data->state.proxydigest; allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; - passwdp = conn->proxypasswd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; authp = &data->state.authproxy; } else { @@ -140,12 +140,14 @@ CURLcode Curl_output_digest(struct connectdata *conn, http://www.fngtps.com/2006/09/http-authentication */ - if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) { - size_t urilen = tmp - (char *)uripath; - - path = (unsigned char *) aprintf("%.*s", urilen, uripath); + if(authp->iestyle) { + tmp = strchr((char *)uripath, '?'); + if(tmp) { + size_t urilen = tmp - (char *)uripath; + path = (unsigned char *) aprintf("%.*s", urilen, uripath); + } } - else + if(!tmp) path = (unsigned char *) strdup((char *) uripath); if(!path) diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c index eb17ed4f2..51375e81d 100644 --- a/Utilities/cmcurl/lib/http_negotiate.c +++ b/Utilities/cmcurl/lib/http_negotiate.c @@ -37,6 +37,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *header) { + CURLcode result; struct Curl_easy *data = conn->data; size_t len; @@ -50,11 +51,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, struct negotiatedata *neg_ctx; if(proxy) { - userp = conn->proxyuser; - passwdp = conn->proxypasswd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; service = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; - host = conn->proxy.name; + host = conn->http_proxy.host.name; neg_ctx = &data->state.proxyneg; } else { @@ -89,8 +90,13 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, } /* Initilise the security context and decode our challenge */ - return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host, - header, neg_ctx); + result = Curl_auth_decode_spnego_message(data, userp, passwdp, service, + host, header, neg_ctx); + + if(result) + Curl_auth_spnego_cleanup(neg_ctx); + + return result; } CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c index e424040d9..8a78bd293 100644 --- a/Utilities/cmcurl/lib/http_ntlm.c +++ b/Utilities/cmcurl/lib/http_ntlm.c @@ -27,7 +27,7 @@ /* * NTLM details: * - * http://davenport.sourceforge.net/ntlm.html + * https://davenport.sourceforge.io/ntlm.html * https://www.innovation.ch/java/ntlm.html */ @@ -136,8 +136,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) if(proxy) { allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; - passwdp = conn->proxypasswd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; ntlm = &conn->proxyntlm; authp = &conn->data->state.authproxy; } diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c index 8f5e9b4e5..9894e2e5f 100644 --- a/Utilities/cmcurl/lib/http_proxy.c +++ b/Utilities/cmcurl/lib/http_proxy.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,14 +35,50 @@ #include "non-ascii.h" #include "connect.h" #include "curlx.h" +#include "vtls/vtls.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" -CURLcode Curl_proxy_connect(struct connectdata *conn) +/* + * Perform SSL initialization for HTTPS proxy. Sets + * proxy_ssl_connected connection bit when complete. Can be + * called multiple times. + */ +static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex) +{ +#ifdef USE_SSL + 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, + &conn->bits.proxy_ssl_connected[sockindex]); + if(result) + conn->bits.close = TRUE; /* a failed connection is marked for closure to + prevent (bad) re-use or similar */ + } + return result; +#else + (void) conn; + (void) sockindex; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex) { + if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) { + const CURLcode result = https_proxy_connect(conn, sockindex); + if(result) + return result; + if(!conn->bits.proxy_ssl_connected[sockindex]) + return result; /* wait for HTTPS proxy SSL initialization to complete */ + } + if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { #ifndef CURL_DISABLE_PROXY /* for [protocol] tunneled through HTTP proxy */ @@ -62,22 +98,31 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) * original pointer * * This function might be called several times in the multi interface case - * if the proxy's CONNTECT response is not instant. + * if the proxy's CONNECT response is not instant. */ prot_save = conn->data->req.protop; memset(&http_proxy, 0, sizeof(http_proxy)); conn->data->req.protop = &http_proxy; connkeep(conn, "HTTP proxy CONNECT"); + + /* for the secondary socket (FTP), use the "connect to host" + * but ignore the "connect to port" (use the secondary port) + */ + if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; + else if(sockindex == SECONDARYSOCKET) + hostname = conn->secondaryhostname; else hostname = conn->host.name; - if(conn->bits.conn_to_port) + + if(sockindex == SECONDARYSOCKET) + remote_port = conn->secondary_port; + else if(conn->bits.conn_to_port) remote_port = conn->conn_to_port; else remote_port = conn->remote_port; - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, hostname, - remote_port, FALSE); + result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port); conn->data->req.protop = prot_save; if(CURLE_OK != result) return result; @@ -90,20 +135,12 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) return CURLE_OK; } -/* - * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This - * function will issue the necessary commands to get a seamless tunnel through - * this proxy. After that, the socket can be used just as a normal socket. - * - * 'blocking' set to TRUE means that this function will do the entire CONNECT - * + response in a blocking fashion. Should be avoided! - */ +#define CONNECT_BUFFER_SIZE 16384 -CURLcode Curl_proxyCONNECT(struct connectdata *conn, - int sockindex, - const char *hostname, - int remote_port, - bool blocking) +static CURLcode CONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, + int remote_port) { int subversion=0; struct Curl_easy *data=conn->data; @@ -113,7 +150,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, curl_off_t cl=0; bool closeConnection = FALSE; bool chunked_encoding = FALSE; - long check; + time_t check; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -158,10 +195,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, free(host_port); if(!result) { - char *host=(char *)""; + char *host = NULL; const char *proxyconn=""; const char *useragent=""; - const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ? + const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1"; bool ipv6_ip = conn->bits.ipv6_ip; char *hostheader; @@ -201,13 +238,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, "%s", /* Proxy-Connection */ hostheader, http, - host, + host?host:"", conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd:"", useragent, proxyconn); - if(host && *host) + if(host) free(host); free(hostheader); @@ -243,15 +280,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, return CURLE_RECV_ERROR; } - if(!blocking) { - if(0 == SOCKET_READABLE(tunnelsocket, 0)) - /* return so we'll be called again polling-style */ - return CURLE_OK; - else { - DEBUGF(infof(data, - "Read response immediately from proxy CONNECT\n")); - } - } + if(!Curl_conn_data_pending(conn, sockindex)) + /* return so we'll be called again polling-style */ + return CURLE_OK; + DEBUGF(infof(data, "Read response immediately from proxy CONNECT\n")); /* at this point, the tunnel_connecting phase is over. */ @@ -263,13 +295,20 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, char *ptr; char *line_start; - ptr=data->state.buffer; + ptr = conn->connect_buffer; line_start = ptr; - nread=0; - perline=0; + nread = 0; + perline = 0; + + while(nread < (size_t)CONNECT_BUFFER_SIZE && keepon && !error) { + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; - while((nread= &conn->connect_buffer[CONNECT_BUFFER_SIZE]) { + failf(data, "CONNECT response too large!"); + return CURLE_RECV_ERROR; + } check = Curl_timeleft(data, NULL, TRUE); if(check <= 0) { @@ -278,253 +317,235 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, break; } - /* loop every second at least, less if the timeout is near */ - switch (SOCKET_READABLE(tunnelsocket, check<1000L?check:1000)) { - case -1: /* select() error, stop reading */ - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted due to select/poll error"); + /* 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, ptr, 1, &gotbytes); + if(result == CURLE_AGAIN) { + if(SOCKET_READABLE(tunnelsocket, check<1000L?check:1000) == -1) { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted due to select/poll error"); + break; + } + continue; + } + if(result) { + keepon = FALSE; break; - case 0: /* timeout */ + } + else if(gotbytes <= 0) { + if(data->set.proxyauth && data->state.authproxy.avail) { + /* proxy auth was requested and there was proxy auth available, + then deem this as "mere" proxy disconnect */ + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Proxy CONNECT connection closed\n"); + } + else { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } + keepon = FALSE; break; - default: - DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1); - result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, - &gotbytes); - if(result==CURLE_AGAIN) - continue; /* go loop yourself */ - else if(result) - keepon = FALSE; - else if(gotbytes <= 0) { - keepon = FALSE; - if(data->set.proxyauth && data->state.authproxy.avail) { - /* proxy auth was requested and there was proxy auth available, - then deem this as "mere" proxy disconnect */ - conn->bits.proxy_connect_closed = TRUE; - infof(data, "Proxy CONNECT connection closed\n"); - } - else { - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted"); + } + + /* We got a byte of data */ + nread++; + + if(keepon > TRUE) { + /* This means we are currently ignoring a response-body */ + + nread = 0; /* make next read start over in the read buffer */ + ptr = conn->connect_buffer; + if(cl) { + /* A Content-Length based body: simply count down the counter + and make sure to break out of the loop when we're done! */ + cl--; + if(cl <= 0) { + keepon = FALSE; + break; } } else { - /* - * We got a whole chunk of data, which can be anything from one - * byte to a set of lines and possibly just a piece of the last - * line. - */ - int i; - - nread += gotbytes; - - if(keepon > TRUE) { - /* This means we are currently ignoring a response-body */ - - nread = 0; /* make next read start over in the read buffer */ - ptr=data->state.buffer; - if(cl) { - /* A Content-Length based body: simply count down the counter - and make sure to break out of the loop when we're done! */ - cl -= gotbytes; - if(cl<=0) { - keepon = FALSE; - break; - } + /* chunked-encoded body, so we need to do the chunked dance + properly to know when the end of the body is reached */ + CHUNKcode r; + ssize_t tookcareof = 0; + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, ptr, 1, &tookcareof); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + /* we did the full CONNECT treatment, go COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; + } + } + continue; + } + + perline++; /* amount of bytes in this line so far */ + + /* if this is not the end of a header line then continue */ + if(*ptr != 0x0a) { + ptr++; + continue; + } + + /* convert from the network encoding */ + result = Curl_convert_from_network(data, line_start, perline); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* output debug if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + line_start, (size_t)perline, conn); + + if(!data->set.suppress_connect_headers) { + /* send the header to the callback */ + int writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + result = Curl_client_write(conn, writetype, line_start, 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 + as end-of-headers as well.*/ + + if(('\r' == line_start[0]) || + ('\n' == line_start[0])) { + /* end of response-headers from the proxy */ + nread = 0; /* make next read start over in the read + buffer */ + ptr = conn->connect_buffer; + if((407 == k->httpcode) && !data->state.authproblem) { + /* If we get a 407 response code with content length + when we have no auth problem, we must ignore the + whole response-body */ + keepon = 2; + + if(cl) { + infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T + " bytes of response-body\n", cl); + } + else if(chunked_encoding) { + CHUNKcode r; + + infof(data, "Ignore chunked response-body\n"); + + /* We set ignorebody true here since the chunked + decoder function will acknowledge that. Pay + attention so that this is cleared again when this + function returns! */ + k->ignorebody = TRUE; + + if(line_start[1] == '\n') { + /* this can only be a LF if the letter at index 0 + was a CR */ + line_start++; } - else { - /* chunked-encoded body, so we need to do the chunked dance - properly to know when the end of the body is reached */ - CHUNKcode r; - ssize_t tookcareof=0; - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - /* we did the full CONNECT treatment, go COMPLETE */ - conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - tookcareof); + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, line_start + 1, 1, &gotbytes); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + /* we did the full CONNECT treatment, go to + COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; } } - else - for(i = 0; i < gotbytes; ptr++, i++) { - perline++; /* amount of bytes in this line so far */ - if(*ptr == 0x0a) { - char letter; - int writetype; - - /* convert from the network encoding */ - result = Curl_convert_from_network(data, line_start, - perline); - /* Curl_convert_from_network calls failf if unsuccessful */ - if(result) - return result; - - /* output debug if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - line_start, (size_t)perline, conn); - - /* send the header to the callback */ - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - - result = Curl_client_write(conn, writetype, line_start, - perline); - - data->info.header_size += (long)perline; - data->req.headerbytecount += (long)perline; - - if(result) - return result; - - /* Newlines are CRLF, so the CR is ignored as the line isn't - really terminated until the LF comes. Treat a following CR - as end-of-headers as well.*/ - - if(('\r' == line_start[0]) || - ('\n' == line_start[0])) { - /* end of response-headers from the proxy */ - nread = 0; /* make next read start over in the read - buffer */ - ptr=data->state.buffer; - if((407 == k->httpcode) && !data->state.authproblem) { - /* If we get a 407 response code with content length - when we have no auth problem, we must ignore the - whole response-body */ - keepon = 2; - - if(cl) { - infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T - " bytes of response-body\n", cl); - - /* remove the remaining chunk of what we already - read */ - cl -= (gotbytes - i); - - if(cl<=0) - /* if the whole thing was already read, we are done! - */ - keepon=FALSE; - } - else if(chunked_encoding) { - CHUNKcode r; - /* We set ignorebody true here since the chunked - decoder function will acknowledge that. Pay - attention so that this is cleared again when this - function returns! */ - k->ignorebody = TRUE; - infof(data, "%zd bytes of chunk left\n", gotbytes-i); - - if(line_start[1] == '\n') { - /* this can only be a LF if the letter at index 0 - was a CR */ - line_start++; - i++; - } - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, line_start+1, - gotbytes -i, &gotbytes); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - /* we did the full CONNECT treatment, go to - COMPLETE */ - conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - gotbytes); - } - else { - /* 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 */ - keepon=FALSE; - } - } - else { - keepon = FALSE; - if(200 == data->info.httpproxycode) { - if(gotbytes - (i+1)) - failf(data, "Proxy CONNECT followed by %zd bytes " - "of opaque data. Data ignored (known bug #39)", - gotbytes - (i+1)); - } - } - /* we did the full CONNECT treatment, go to COMPLETE */ - conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; - break; /* breaks out of for-loop, not switch() */ - } - - /* keep a backup of the position we are about to blank */ - letter = line_start[perline]; - line_start[perline]=0; /* zero terminate the buffer */ - if((checkprefix("WWW-Authenticate:", line_start) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", line_start) && - (407 == k->httpcode))) { - - bool proxy = (k->httpcode == 407) ? TRUE : FALSE; - char *auth = Curl_copy_header_value(line_start); - if(!auth) - return CURLE_OUT_OF_MEMORY; - - result = Curl_http_input_auth(conn, proxy, auth); - - free(auth); - - if(result) - return result; - } - else if(checkprefix("Content-Length:", line_start)) { - cl = curlx_strtoofft(line_start + - strlen("Content-Length:"), NULL, 10); - } - else if(Curl_compareheader(line_start, - "Connection:", "close")) - closeConnection = TRUE; - else if(Curl_compareheader(line_start, - "Transfer-Encoding:", - "chunked")) { - infof(data, "CONNECT responded chunked\n"); - chunked_encoding = TRUE; - /* init our chunky engine */ - Curl_httpchunk_init(conn); - } - else if(Curl_compareheader(line_start, - "Proxy-Connection:", "close")) - closeConnection = TRUE; - else if(2 == sscanf(line_start, "HTTP/1.%d %d", - &subversion, - &k->httpcode)) { - /* store the HTTP code from the proxy */ - data->info.httpproxycode = k->httpcode; - } - /* put back the letter we blanked out before */ - line_start[perline]= letter; - - perline=0; /* line starts over here */ - line_start = ptr+1; /* this skips the zero byte we wrote */ - } - } + else { + /* 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 */ + keepon = FALSE; + } } - break; - } /* switch */ - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; + else + keepon = FALSE; + /* we did the full CONNECT treatment, go to COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; + continue; + } + + line_start[perline] = 0; /* zero terminate the buffer */ + if((checkprefix("WWW-Authenticate:", line_start) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", line_start) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(line_start); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + else if(checkprefix("Content-Length:", line_start)) { + if(k->httpcode/100 == 2) { + /* A client MUST ignore any Content-Length or Transfer-Encoding + header fields received in a successful response to CONNECT. + "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ + infof(data, "Ignoring Content-Length in CONNECT %03d response\n", + k->httpcode); + } + else { + cl = curlx_strtoofft(line_start + + strlen("Content-Length:"), NULL, 10); + } + } + else if(Curl_compareheader(line_start, "Connection:", "close")) + closeConnection = TRUE; + else if(checkprefix("Transfer-Encoding:", line_start)) { + if(k->httpcode/100 == 2) { + /* A client MUST ignore any Content-Length or Transfer-Encoding + header fields received in a successful response to CONNECT. + "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ + infof(data, "Ignoring Transfer-Encoding in " + "CONNECT %03d response\n", k->httpcode); + } + else if(Curl_compareheader(line_start, + "Transfer-Encoding:", "chunked")) { + infof(data, "CONNECT responded chunked\n"); + chunked_encoding = TRUE; + /* init our chunky engine */ + Curl_httpchunk_init(conn); + } + } + else if(Curl_compareheader(line_start, "Proxy-Connection:", "close")) + closeConnection = TRUE; + else if(2 == sscanf(line_start, "HTTP/1.%d %d", + &subversion, + &k->httpcode)) { + /* store the HTTP code from the proxy */ + data->info.httpproxycode = k->httpcode; + } + + perline = 0; /* line starts over here */ + ptr = conn->connect_buffer; + line_start = ptr; } /* while there's buffer left and loop is requested */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + if(error) return CURLE_RECV_ERROR; @@ -538,8 +559,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(conn->bits.close) /* the connection has been marked for closure, most likely in the Curl_http_auth_act() function and thus we can kill it at once - below - */ + below */ closeConnection = TRUE; } @@ -583,11 +603,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(conn->bits.proxy_connect_closed) /* this is not an error, just part of the connection negotiation */ return CURLE_OK; - else { - failf(data, "Received HTTP code %d from proxy after CONNECT", - data->req.httpcode); - return CURLE_RECV_ERROR; - } + failf(data, "Received HTTP code %d from proxy after CONNECT", + data->req.httpcode); + return CURLE_RECV_ERROR; } conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; @@ -600,10 +618,39 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, data->state.authproxy.done = TRUE; - infof (data, "Proxy replied OK to CONNECT request\n"); + infof(data, "Proxy replied OK to CONNECT request\n"); data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the document request */ return CURLE_OK; } + +/* + * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. + */ + +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, + int remote_port) +{ + CURLcode result; + if(TUNNEL_INIT == conn->tunnel_state[sockindex]) { + if(!conn->connect_buffer) { + conn->connect_buffer = malloc(CONNECT_BUFFER_SIZE); + if(!conn->connect_buffer) + return CURLE_OUT_OF_MEMORY; + } + } + result = CONNECT(conn, sockindex, hostname, remote_port); + + if(result || (TUNNEL_COMPLETE == conn->tunnel_state[sockindex])) + Curl_safefree(conn->connect_buffer); + + return result; +} + + #endif /* CURL_DISABLE_PROXY */ diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h index fd0433033..cbb1ab421 100644 --- a/Utilities/cmcurl/lib/http_proxy.h +++ b/Utilities/cmcurl/lib/http_proxy.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,17 +26,16 @@ /* ftp can use this as well */ CURLcode Curl_proxyCONNECT(struct connectdata *conn, int tunnelsocket, - const char *hostname, int remote_port, - bool blocking); + const char *hostname, int remote_port); /* Default proxy timeout in milliseconds */ #define PROXY_TIMEOUT (3600*1000) -CURLcode Curl_proxy_connect(struct connectdata *conn); +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex); #else -#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN -#define Curl_proxy_connect(x) CURLE_OK +#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN +#define Curl_proxy_connect(x,y) CURLE_OK #endif #endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/Utilities/cmcurl/lib/if2ip.c b/Utilities/cmcurl/lib/if2ip.c index e6faa4b80..4de81be60 100644 --- a/Utilities/cmcurl/lib/if2ip.c +++ b/Utilities/cmcurl/lib/if2ip.c @@ -68,7 +68,7 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa) #else if(sa->sa_family == AF_INET6) { const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa; - const unsigned char * b = sa6->sin6_addr.s6_addr; + const unsigned char *b = sa6->sin6_addr.s6_addr; unsigned short w = (unsigned short) ((b[0] << 8) | b[1]); switch(w & 0xFFC0) { @@ -239,7 +239,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, return IF2IP_NOT_FOUND; } - s = (struct sockaddr_in *)&req.ifr_addr; + s = (struct sockaddr_in *)(void *)&req.ifr_addr; memcpy(&in, &s->sin_addr, sizeof(in)); Curl_inet_ntop(s->sin_family, &in, buf, buf_size); diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c index 4aa7dcc95..b528f77d9 100644 --- a/Utilities/cmcurl/lib/imap.c +++ b/Utilities/cmcurl/lib/imap.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -107,7 +107,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn, const char *initresp); static CURLcode imap_continue_authenticate(struct connectdata *conn, const char *resp); -static void imap_get_message(char *buffer, char** outptr); +static void imap_get_message(char *buffer, char **outptr); /* * IMAP protocol handler. @@ -130,7 +130,8 @@ const struct Curl_handler Curl_handler_imap = { ZERO_NULL, /* readwrite */ PORT_IMAP, /* defport */ CURLPROTO_IMAP, /* protocol */ - PROTOPT_CLOSEACTION /* flags */ + PROTOPT_CLOSEACTION| /* flags */ + PROTOPT_URLOPTIONS }; #ifdef USE_SSL @@ -390,10 +391,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, * * Gets the authentication message from the response buffer. */ -static void imap_get_message(char *buffer, char** outptr) +static void imap_get_message(char *buffer, char **outptr) { size_t len = 0; - char* message = NULL; + char *message = NULL; /* Find the start of the message */ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++) @@ -952,7 +953,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, if(imapcode != 'O') { if(data->set.use_ssl != CURLUSESSL_TRY) { - failf(data, "STARTTLS denied. %c", imapcode); + failf(data, "STARTTLS denied"); result = CURLE_USE_SSL_FAILED; } else @@ -1748,7 +1749,7 @@ static CURLcode imap_setup_connection(struct connectdata *conn) * * imap_sendf() * - * Sends the formated string as an IMAP command to the server. + * Sends the formatted string as an IMAP command to the server. * * Designed to never block. */ diff --git a/Utilities/cmcurl/lib/inet_ntop.c b/Utilities/cmcurl/lib/inet_ntop.c index 416005c03..9afbdbb32 100644 --- a/Utilities/cmcurl/lib/inet_ntop.c +++ b/Utilities/cmcurl/lib/inet_ntop.c @@ -182,12 +182,12 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) */ char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size) { - switch (af) { + switch(af) { case AF_INET: - return inet_ntop4((const unsigned char*)src, buf, size); + return inet_ntop4((const unsigned char *)src, buf, size); #ifdef ENABLE_IPV6 case AF_INET6: - return inet_ntop6((const unsigned char*)src, buf, size); + return inet_ntop6((const unsigned char *)src, buf, size); #endif default: SET_ERRNO(EAFNOSUPPORT); diff --git a/Utilities/cmcurl/lib/inet_pton.c b/Utilities/cmcurl/lib/inet_pton.c index cf8b88a1d..475f44abc 100644 --- a/Utilities/cmcurl/lib/inet_pton.c +++ b/Utilities/cmcurl/lib/inet_pton.c @@ -65,7 +65,7 @@ static int inet_pton6(const char *src, unsigned char *dst); int Curl_inet_pton(int af, const char *src, void *dst) { - switch (af) { + switch(af) { case AF_INET: return (inet_pton4(src, (unsigned char *)dst)); #ifdef ENABLE_IPV6 @@ -103,7 +103,8 @@ inet_pton4(const char *src, unsigned char *dst) while((ch = *src++) != '\0') { const char *pch; - if((pch = strchr(digits, ch)) != NULL) { + pch = strchr(digits, ch); + if(pch) { unsigned int val = *tp * 10 + (unsigned int)(pch - digits); if(saw_digit && *tp == 0) @@ -169,7 +170,8 @@ inet_pton6(const char *src, unsigned char *dst) while((ch = *src++) != '\0') { const char *pch; - if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_l), ch); + if(!pch) pch = strchr((xdigits = xdigits_u), ch); if(pch != NULL) { val <<= 4; diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c index 5d5c00395..69a35979a 100644 --- a/Utilities/cmcurl/lib/krb5.c +++ b/Utilities/cmcurl/lib/krb5.c @@ -121,7 +121,7 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to) /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal * libraries modify the input buffer in gss_seal() */ - dec.value = (void*)from; + dec.value = (void *)from; dec.length = length; maj = gss_seal(&min, *context, level == PROT_PRIVATE, @@ -164,6 +164,7 @@ krb5_auth(void *app_data, struct connectdata *conn) size_t base64_sz = 0; struct sockaddr_in **remote_addr = (struct sockaddr_in **)&conn->ip_addr->ai_addr; + char *stringp; if(getsockname(conn->sock[FIRSTSOCKET], (struct sockaddr *)&conn->local_addr, &l) < 0) @@ -193,16 +194,19 @@ krb5_auth(void *app_data, struct connectdata *conn) return -1; } - input_buffer.value = data->state.buffer; - input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s", - service, host); + stringp = aprintf("%s@%s", service, host); + if(!stringp) + return -2; + + input_buffer.value = stringp; + input_buffer.length = strlen(stringp); maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE, &gssname); + free(stringp); if(maj != GSS_S_COMPLETE) { gss_release_name(&min, &gssname); if(service == srv_host) { - Curl_failf(data, "Error importing service name %s", - input_buffer.value); + Curl_failf(data, "Error importing service name %s@%s", service, host); return AUTH_ERROR; } service = srv_host; diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c index 7dbc1b0e6..79e84d94e 100644 --- a/Utilities/cmcurl/lib/ldap.c +++ b/Utilities/cmcurl/lib/ldap.c @@ -109,9 +109,9 @@ typedef struct { #undef LDAPURLDesc #define LDAPURLDesc CURL_LDAPURLDesc -static int _ldap_url_parse (const struct connectdata *conn, - LDAPURLDesc **ludp); -static void _ldap_free_urldesc (LDAPURLDesc *ludp); +static int _ldap_url_parse(const struct connectdata *conn, + LDAPURLDesc **ludp); +static void _ldap_free_urldesc(LDAPURLDesc *ludp); #undef ldap_free_urldesc #define ldap_free_urldesc _ldap_free_urldesc @@ -119,11 +119,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp); #ifdef DEBUG_LDAP #define LDAP_TRACE(x) do { \ - _ldap_trace ("%u: ", __LINE__); \ + _ldap_trace("%u: ", __LINE__); \ _ldap_trace x; \ } WHILE_FALSE - static void _ldap_trace (const char *fmt, ...); + static void _ldap_trace(const char *fmt, ...); #else #define LDAP_TRACE(x) Curl_nop_stmt #endif @@ -181,6 +181,81 @@ const struct Curl_handler Curl_handler_ldaps = { }; #endif +#if defined(USE_WIN32_LDAP) + +#if defined(USE_WINDOWS_SSPI) +static int ldap_win_bind_auth(LDAP *server, const char *user, + const char *passwd, unsigned long authflags) +{ + ULONG method = 0; + SEC_WINNT_AUTH_IDENTITY cred = { 0, }; + int rc = LDAP_AUTH_METHOD_NOT_SUPPORTED; + +#if defined(USE_SPNEGO) + if(authflags & CURLAUTH_NEGOTIATE) { + method = LDAP_AUTH_NEGOTIATE; + } + else +#endif +#if defined(USE_NTLM) + if(authflags & CURLAUTH_NTLM) { + method = LDAP_AUTH_NTLM; + } + else +#endif +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + if(authflags & CURLAUTH_DIGEST) { + method = LDAP_AUTH_DIGEST; + } + else +#endif + { + /* required anyway if one of upper preprocessor definitions enabled */ + } + + if(method && user && passwd) { + rc = Curl_create_sspi_identity(user, passwd, &cred); + if(!rc) { + rc = ldap_bind_s(server, NULL, (TCHAR *)&cred, method); + Curl_sspi_free_identity(&cred); + } + } + else { + /* proceed with current user credentials */ + method = LDAP_AUTH_NEGOTIATE; + rc = ldap_bind_s(server, NULL, NULL, method); + } + return rc; +} +#endif /* #if defined(USE_WINDOWS_SSPI) */ + +static int ldap_win_bind(struct connectdata *conn, LDAP *server, + const char *user, const char *passwd) +{ + int rc = LDAP_INVALID_CREDENTIALS; + ULONG method = LDAP_AUTH_SIMPLE; + + PTCHAR inuser = NULL; + PTCHAR inpass = NULL; + + if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) { + inuser = Curl_convert_UTF8_to_tchar((char *) user); + inpass = Curl_convert_UTF8_to_tchar((char *) passwd); + + rc = ldap_bind_s(server, inuser, inpass, method); + + Curl_unicodefree(inuser); + Curl_unicodefree(inpass); + } +#if defined(USE_WINDOWS_SSPI) + else { + rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth); + } +#endif + + return rc; +} +#endif /* #if defined(USE_WIN32_LDAP) */ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) { @@ -202,13 +277,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) #endif #if defined(USE_WIN32_LDAP) TCHAR *host = NULL; - TCHAR *user = NULL; - TCHAR *passwd = NULL; #else char *host = NULL; +#endif char *user = NULL; char *passwd = NULL; -#endif *done = TRUE; /* unconditionally */ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", @@ -239,24 +312,14 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) goto quit; } - - if(conn->bits.user_passwd) { - user = Curl_convert_UTF8_to_tchar(conn->user); - passwd = Curl_convert_UTF8_to_tchar(conn->passwd); - if(!user || !passwd) { - result = CURLE_OUT_OF_MEMORY; - - goto quit; - } - } #else host = conn->host.name; +#endif if(conn->bits.user_passwd) { user = conn->user; passwd = conn->passwd; } -#endif #ifdef LDAP_OPT_NETWORK_TIMEOUT ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); @@ -271,7 +334,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); #else int ldap_option; - char* ldap_ca = data->set.str[STRING_SSL_CAFILE]; + char *ldap_ca = conn->ssl_config.CAfile; #if defined(CURL_HAS_NOVELL_LDAPSDK) rc = ldapssl_client_init(NULL, NULL); if(rc != LDAP_SUCCESS) { @@ -279,11 +342,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = CURLE_SSL_CERTPROBLEM; goto quit; } - if(data->set.ssl.verifypeer) { + if(conn->ssl_config.verifypeer) { /* Novell SDK supports DER or BASE64 files. */ int cert_type = LDAPSSL_CERT_FILETYPE_B64; - if((data->set.str[STRING_CERT_TYPE]) && - (strcasecompare(data->set.str[STRING_CERT_TYPE], "DER"))) + if((data->set.ssl.cert_type) && + (strcasecompare(data->set.ssl.cert_type, "DER"))) cert_type = LDAPSSL_CERT_FILETYPE_DER; if(!ldap_ca) { failf(data, "LDAP local: ERROR %s CA cert not set!", @@ -321,10 +384,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) goto quit; } #elif defined(LDAP_OPT_X_TLS) - if(data->set.ssl.verifypeer) { + if(conn->ssl_config.verifypeer) { /* OpenLDAP SDK supports BASE64 files. */ - if((data->set.str[STRING_CERT_TYPE]) && - (!strcasecompare(data->set.str[STRING_CERT_TYPE], "PEM"))) { + if((data->set.ssl.cert_type) && + (!strcasecompare(data->set.ssl.cert_type, "PEM"))) { failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!"); result = CURLE_SSL_CERTPROBLEM; goto quit; @@ -402,11 +465,19 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); #endif +#ifdef USE_WIN32_LDAP + rc = ldap_win_bind(conn, server, user, passwd); +#else rc = ldap_simple_bind_s(server, user, passwd); +#endif if(!ldap_ssl && rc != 0) { 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); +#else rc = ldap_simple_bind_s(server, user, passwd); +#endif } if(rc != 0) { failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc)); @@ -655,7 +726,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) quit: if(ldapmsg) { ldap_msgfree(ldapmsg); - LDAP_TRACE (("Received %d entries\n", num)); + LDAP_TRACE(("Received %d entries\n", num)); } if(rc == LDAP_SIZELIMIT_EXCEEDED) infof(data, "There are more than %d entries\n", num); @@ -669,8 +740,6 @@ quit: #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ #if defined(USE_WIN32_LDAP) - Curl_unicodefree(passwd); - Curl_unicodefree(user); Curl_unicodefree(host); #endif @@ -682,7 +751,7 @@ quit: } #ifdef DEBUG_LDAP -static void _ldap_trace (const char *fmt, ...) +static void _ldap_trace(const char *fmt, ...) { static int do_trace = -1; va_list args; @@ -694,9 +763,9 @@ static void _ldap_trace (const char *fmt, ...) if(!do_trace) return; - va_start (args, fmt); - vfprintf (stderr, fmt, args); - va_end (args); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); } #endif @@ -705,7 +774,7 @@ static void _ldap_trace (const char *fmt, ...) /* * Return scope-value for a scope-string. */ -static int str2scope (const char *p) +static int str2scope(const char *p) { if(strcasecompare(p, "one")) return LDAP_SCOPE_ONELEVEL; @@ -799,7 +868,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) char *unescaped; CURLcode result; - LDAP_TRACE (("DN '%s'\n", dn)); + LDAP_TRACE(("DN '%s'\n", dn)); /* Unescape the DN */ result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE); @@ -864,7 +933,7 @@ 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[%d] '%s'\n", i, attributes[i])); /* Unescape the attribute */ result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL, @@ -917,7 +986,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) goto quit; } - LDAP_TRACE (("scope %d\n", ludp->lud_scope)); + LDAP_TRACE(("scope %d\n", ludp->lud_scope)); } p = q; @@ -934,7 +1003,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) char *unescaped; CURLcode result; - LDAP_TRACE (("filter '%s'\n", filter)); + LDAP_TRACE(("filter '%s'\n", filter)); /* Unescape the filter */ result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE); @@ -1009,7 +1078,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp) free(ludp->lud_attrs); } - free (ludp); + free(ludp); } #endif /* !HAVE_LDAP_URL_PARSE */ #endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ diff --git a/Utilities/cmcurl/lib/libcurl.rc b/Utilities/cmcurl/lib/libcurl.rc index c1efbadc6..3316fba19 100644 --- a/Utilities/cmcurl/lib/libcurl.rc +++ b/Utilities/cmcurl/lib/libcurl.rc @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -51,7 +51,7 @@ BEGIN VALUE "OriginalFilename", "libcurl.dll\0" VALUE "ProductName", "The curl library\0" VALUE "ProductVersion", LIBCURL_VERSION "\0" - VALUE "LegalCopyright", "© " LIBCURL_COPYRIGHT "\0" + VALUE "LegalCopyright", "\xa9 " LIBCURL_COPYRIGHT "\0" /* a9: Copyright symbol */ VALUE "License", "https://curl.haxx.se/docs/copyright.html\0" END END diff --git a/Utilities/cmcurl/lib/llist.c b/Utilities/cmcurl/lib/llist.c index 482aaa041..4bb0a51b8 100644 --- a/Utilities/cmcurl/lib/llist.c +++ b/Utilities/cmcurl/lib/llist.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -33,8 +33,8 @@ /* * @unittest: 1300 */ -static void -llist_init(struct curl_llist *l, curl_llist_dtor dtor) +void +Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor) { l->size = 0; l->dtor = dtor; @@ -42,20 +42,6 @@ llist_init(struct curl_llist *l, curl_llist_dtor dtor) l->tail = NULL; } -struct curl_llist * -Curl_llist_alloc(curl_llist_dtor dtor) -{ - struct curl_llist *list; - - list = malloc(sizeof(struct curl_llist)); - if(!list) - return NULL; - - llist_init(list, dtor); - - return list; -} - /* * Curl_llist_insert_next() * @@ -63,18 +49,15 @@ Curl_llist_alloc(curl_llist_dtor dtor) * entry is NULL and the list already has elements, the new one will be * inserted first in the list. * - * Returns: 1 on success and 0 on failure. + * The 'ne' argument should be a pointer into the object to store. * * @unittest: 1300 */ -int +void Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, - const void *p) + const void *p, + struct curl_llist_element *ne) { - struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element)); - if(!ne) - return 0; - ne->ptr = (void *) p; if(list->size == 0) { list->head = ne; @@ -101,19 +84,18 @@ Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, } ++list->size; - - return 1; } /* * @unittest: 1300 */ -int +void Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, void *user) { + void *ptr; if(e == NULL || list->size == 0) - return 1; + return; if(e == list->head) { list->head = e->next; @@ -131,16 +113,17 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, e->next->prev = e->prev; } - list->dtor(user, e->ptr); + ptr = e->ptr; e->ptr = NULL; e->prev = NULL; e->next = NULL; - free(e); --list->size; - return 1; + /* call the dtor() last for when it actually frees the 'e' memory itself */ + if(list->dtor) + list->dtor(user, ptr); } void @@ -149,8 +132,6 @@ Curl_llist_destroy(struct curl_llist *list, void *user) if(list) { while(list->size > 0) Curl_llist_remove(list, list->tail, user); - - free(list); } } @@ -163,13 +144,13 @@ Curl_llist_count(struct curl_llist *list) /* * @unittest: 1300 */ -int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, - struct curl_llist *to_list, - struct curl_llist_element *to_e) +void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, + struct curl_llist *to_list, + struct curl_llist_element *to_e) { /* Remove element from list */ if(e == NULL || list->size == 0) - return 0; + return; if(e == list->head) { list->head = e->next; @@ -209,6 +190,4 @@ int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, } ++to_list->size; - - return 1; } diff --git a/Utilities/cmcurl/lib/llist.h b/Utilities/cmcurl/lib/llist.h index 39ff408ee..6b644b99c 100644 --- a/Utilities/cmcurl/lib/llist.h +++ b/Utilities/cmcurl/lib/llist.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,7 +29,6 @@ typedef void (*curl_llist_dtor)(void *, void *); struct curl_llist_element { void *ptr; - struct curl_llist_element *prev; struct curl_llist_element *next; }; @@ -37,21 +36,19 @@ struct curl_llist_element { struct curl_llist { struct curl_llist_element *head; struct curl_llist_element *tail; - curl_llist_dtor dtor; - size_t size; }; -struct curl_llist *Curl_llist_alloc(curl_llist_dtor); -int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, - const void *); -int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, - void *); +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 *); -int Curl_llist_move(struct curl_llist *, struct curl_llist_element *, - struct curl_llist *, struct curl_llist_element *); +void Curl_llist_move(struct curl_llist *, struct curl_llist_element *, + struct curl_llist *, struct curl_llist_element *); #endif /* HEADER_CURL_LLIST_H */ diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c index 60f73a28b..2bb7dcc25 100644 --- a/Utilities/cmcurl/lib/md4.c +++ b/Utilities/cmcurl/lib/md4.c @@ -37,9 +37,10 @@ #include "curl_setup.h" -/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so - * that we have a local implementation of it */ -#if defined(USE_NSS) || defined(USE_OS400CRYPTO) +/* The NSS, OS/400 and sometimes mbed TLS crypto libraries do not provide the + * MD4 hash algorithm, so we have a local implementation of it */ +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) #include "curl_md4.h" #include "warnless.h" @@ -89,7 +90,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx); */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) #define SET(n) \ - (*(MD4_u32plus *)&ptr[(n) * 4]) + (*(MD4_u32plus *)(void *)&ptr[(n) * 4]) #define GET(n) \ SET(n) #else @@ -213,7 +214,8 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) unsigned long used, available; saved_lo = ctx->lo; - if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) ctx->hi++; ctx->hi += (MD4_u32plus)size >> 29; @@ -301,4 +303,5 @@ void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) MD4_Update(&ctx, input, curlx_uztoui(len)); MD4_Final(output, &ctx); } -#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */ +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) || + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */ diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c index f818d3288..80301a141 100644 --- a/Utilities/cmcurl/lib/md5.c +++ b/Utilities/cmcurl/lib/md5.c @@ -45,7 +45,7 @@ static void MD5_Init(MD5_CTX * ctx) } static void MD5_Update(MD5_CTX * ctx, - const unsigned char * input, + const unsigned char *input, unsigned int inputLen) { md5_update(ctx, inputLen, input); @@ -71,7 +71,7 @@ static void MD5_Init(MD5_CTX * ctx) } static void MD5_Update(MD5_CTX * ctx, - const unsigned char * input, + const unsigned char *input, unsigned int inputLen) { gcry_md_write(*ctx, input, inputLen); @@ -260,7 +260,7 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx); */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) #define SET(n) \ - (*(MD5_u32plus *)&ptr[(n) * 4]) + (*(MD5_u32plus *)(void *)&ptr[(n) * 4]) #define GET(n) \ SET(n) #else @@ -402,7 +402,8 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) unsigned long used, available; saved_lo = ctx->lo; - if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) ctx->hi++; ctx->hi += (MD5_u32plus)size >> 29; diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c index ccbf461be..2b8808ab0 100644 --- a/Utilities/cmcurl/lib/memdebug.c +++ b/Utilities/cmcurl/lib/memdebug.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,10 +35,6 @@ #include "curl_memory.h" #include "memdebug.h" -#ifndef HAVE_ASSERT_H -# define assert(x) Curl_nop_stmt -#endif - /* * Until 2011-08-17 libcurl's Memory Tracking feature also performed * automatic malloc and free filling operations using 0xA5 and 0x13 @@ -90,7 +86,7 @@ struct memdebug { union { curl_off_t o; double d; - void * p; + void *p; } mem[1]; /* I'm hoping this is the thing with the strictest alignment * requirements. That also means we waste some space :-( */ @@ -167,7 +163,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source) struct memdebug *mem; size_t size; - assert(wantedsize != 0); + DEBUGASSERT(wantedsize != 0); if(countcheck("malloc", line, source)) return NULL; @@ -196,8 +192,8 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size, struct memdebug *mem; size_t size, user_size; - assert(wanted_elements != 0); - assert(wanted_size != 0); + DEBUGASSERT(wanted_elements != 0); + DEBUGASSERT(wanted_size != 0); if(countcheck("calloc", line, source)) return NULL; @@ -223,7 +219,7 @@ char *curl_dostrdup(const char *str, int line, const char *source) char *mem; size_t len; - assert(str != NULL); + DEBUGASSERT(str != NULL); if(countcheck("strdup", line, source)) return NULL; @@ -236,7 +232,7 @@ char *curl_dostrdup(const char *str, int line, const char *source) if(source) curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n", - source, line, (void *)str, len, (void *)mem); + source, line, (const void *)str, len, (const void *)mem); return mem; } @@ -247,7 +243,7 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) wchar_t *mem; size_t wsiz, bsiz; - assert(str != NULL); + DEBUGASSERT(str != NULL); if(countcheck("wcsdup", line, source)) return NULL; @@ -276,7 +272,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize, size_t size = sizeof(struct memdebug)+wantedsize; - assert(wantedsize != 0); + DEBUGASSERT(wantedsize != 0); if(countcheck("realloc", line, source)) return NULL; @@ -445,7 +441,7 @@ int curl_fclose(FILE *file, int line, const char *source) { int res; - assert(file != NULL); + DEBUGASSERT(file != NULL); res=fclose(file); @@ -458,7 +454,7 @@ int curl_fclose(FILE *file, int line, const char *source) #define LOGLINE_BUFSIZE 1024 -/* this does the writting to the memory tracking log file */ +/* this does the writing to the memory tracking log file */ void curl_memlog(const char *format, ...) { char *buf; @@ -480,7 +476,7 @@ void curl_memlog(const char *format, ...) nchars = LOGLINE_BUFSIZE - 1; if(nchars > 0) - fwrite(buf, 1, nchars, logfile); + fwrite(buf, 1, (size_t)nchars, logfile); (Curl_cfree)(buf); } diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c index 3cdd41a4d..eb7ee0c6b 100644 --- a/Utilities/cmcurl/lib/mprintf.c +++ b/Utilities/cmcurl/lib/mprintf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1999 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1999 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -88,7 +88,8 @@ # define mp_uintmax_t unsigned long #endif -#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ +#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should + fit negative DBL_MAX (317 letters) */ #define MAX_PARAMETERS 128 /* lame static limit */ #ifdef __AMIGA__ @@ -299,7 +300,6 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, flags |= FLAGS_ALT; break; case '.': - flags |= FLAGS_PREC; if('*' == *fmt) { /* The precision is picked from a specified parameter */ @@ -498,7 +498,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, (mp_intmax_t)va_arg(arglist, int); } - switch (vto[i].type) { + switch(vto[i].type) { case FORMAT_STRING: vto[i].data.str = va_arg(arglist, char *); break; @@ -610,7 +610,7 @@ static int dprintf_formatf( int is_neg; /* Base of a number to be written. */ - long base; + unsigned long base; /* Integral values to be written. */ mp_uintmax_t num; @@ -688,7 +688,7 @@ static int dprintf_formatf( is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; - switch (p->type) { + switch(p->type) { case FORMAT_INT: num = p->data.num.as_unsigned; if(p->flags & FLAGS_CHAR) { @@ -913,12 +913,25 @@ static int dprintf_formatf( *fptr = 0; if(width >= 0) { + if(width >= (long)sizeof(work)) + width = sizeof(work)-1; /* RECURSIVE USAGE */ len = curl_msnprintf(fptr, left, "%ld", width); fptr += len; left -= len; } if(prec >= 0) { + /* for each digit in the integer part, we can have one less + precision */ + size_t maxprec = sizeof(work) - 2; + double val = p->data.dnum; + while(val >= 10.0) { + val /= 10; + maxprec--; + } + + if(prec > (long)maxprec) + prec = (long)maxprec-1; /* RECURSIVE USAGE */ len = curl_msnprintf(fptr, left, ".%ld", prec); fptr += len; @@ -938,7 +951,7 @@ static int dprintf_formatf( /* NOTE NOTE NOTE!! Not all sprintf implementations return number of output characters */ (sprintf)(work, formatbuf, p->data.dnum); - + DEBUGASSERT(strlen(work) <= sizeof(work)); for(fptr=work; *fptr; fptr++) OUTCHAR(*fptr); } @@ -1077,8 +1090,7 @@ char *curl_maprintf(const char *format, ...) info.buffer[info.len] = 0; /* we terminate this with a zero byte */ return info.buffer; } - else - return strdup(""); + return strdup(""); } char *curl_mvaprintf(const char *format, va_list ap_save) @@ -1102,8 +1114,7 @@ char *curl_mvaprintf(const char *format, va_list ap_save) info.buffer[info.len] = 0; /* we terminate this with a zero byte */ return info.buffer; } - else - return strdup(""); + return strdup(""); } static int storebuffer(int output, FILE *data) diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c index 2432b15d0..c3a0d122c 100644 --- a/Utilities/cmcurl/lib/multi.c +++ b/Utilities/cmcurl/lib/multi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -42,6 +42,7 @@ #include "multihandle.h" #include "pipeline.h" #include "sigpipe.h" +#include "vtls/vtls.h" #include "connect.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -98,8 +99,6 @@ static const char * const statename[]={ }; #endif -static void multi_freetimeout(void *a, void *b); - /* function pointer called once when switching TO a state */ typedef void (*init_multistate_func)(struct Curl_easy *data); @@ -279,9 +278,8 @@ static int sh_init(struct curl_hash *hash, int hashsize) static CURLMcode multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg) { - if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg)) - return CURLM_OUT_OF_MEMORY; - + Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg, + &msg->list); return CURLM_OK; } @@ -315,13 +313,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ if(Curl_conncache_init(&multi->conn_cache, chashsize)) goto error; - multi->msglist = Curl_llist_alloc(multi_freeamsg); - if(!multi->msglist) - goto error; - - multi->pending = Curl_llist_alloc(multi_freeamsg); - if(!multi->pending) - goto error; + Curl_llist_init(&multi->msglist, multi_freeamsg); + Curl_llist_init(&multi->pending, multi_freeamsg); /* allocate a new easy handle to use when closing cached connections */ multi->closure_handle = curl_easy_init(); @@ -344,8 +337,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */ Curl_conncache_destroy(&multi->conn_cache); Curl_close(multi->closure_handle); multi->closure_handle = NULL; - Curl_llist_destroy(multi->msglist, NULL); - Curl_llist_destroy(multi->pending, NULL); + Curl_llist_destroy(&multi->msglist, NULL); + Curl_llist_destroy(&multi->pending, NULL); free(multi); return NULL; @@ -360,8 +353,6 @@ struct Curl_multi *curl_multi_init(void) CURLMcode curl_multi_add_handle(struct Curl_multi *multi, struct Curl_easy *data) { - struct curl_llist *timeoutlist; - /* First, make some basic checks that the CURLM handle is a good handle */ if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -375,10 +366,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, if(data->multi) return CURLM_ADDED_ALREADY; - /* Allocate and initialize timeout list for easy handle */ - timeoutlist = Curl_llist_alloc(multi_freetimeout); - if(!timeoutlist) - return CURLM_OUT_OF_MEMORY; + /* Initialize timeout list for this handle */ + Curl_llist_init(&data->state.timeoutlist, NULL); /* * No failure allowed in this function beyond this point. And no @@ -387,10 +376,6 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, * function no matter what. */ - /* Make easy handle use timeout list initialized above */ - data->state.timeoutlist = timeoutlist; - timeoutlist = NULL; - /* set the easy handle */ multistate(data, CURLM_STATE_INIT); @@ -443,7 +428,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, sockets that time-out or have actions will be dealt with. Since this handle has no action yet, we make sure it times out to get things to happen. */ - Curl_expire(data, 0); + Curl_expire(data, 0, EXPIRE_RUN_NOW); /* increase the node-counter */ multi->num_easy++; @@ -531,6 +516,7 @@ static CURLcode multi_done(struct connectdata **connp, CURLcode result; struct connectdata *conn; struct Curl_easy *data; + unsigned int i; DEBUGASSERT(*connp); @@ -578,7 +564,7 @@ static CURLcode multi_done(struct connectdata **connp, result = CURLE_ABORTED_BY_CALLBACK; } - if(conn->send_pipe->size + conn->recv_pipe->size != 0 && + if(conn->send_pipe.size + conn->recv_pipe.size != 0 && !data->set.reuse_forbid && !conn->bits.close) { /* Stop if pipeline is not empty and we do not have to close @@ -597,9 +583,11 @@ static CURLcode multi_done(struct connectdata **connp, } /* if the transfer was completed in a paused state there can be buffered - data left to write and then kill */ - free(data->state.tempwrite); - data->state.tempwrite = NULL; + data left to free */ + for(i=0; i < data->state.tempcount; i++) { + free(data->state.tempwrite[i].buf); + } + data->state.tempcount = 0; /* if data->set.reuse_forbid is TRUE, it means the libcurl client has forced us to close this connection. This is ignored for requests taking @@ -637,7 +625,10 @@ static CURLcode multi_done(struct connectdata **connp, infof(data, "Connection #%ld to host %s left intact\n", conn->connection_id, - conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname); + conn->bits.socksproxy ? conn->socks_proxy.host.dispname : + conn->bits.httpproxy ? conn->http_proxy.host.dispname : + conn->bits.conn_to_host ? conn->conn_to_host.dispname : + conn->host.dispname); } else data->state.lastconnect = NULL; @@ -691,13 +682,13 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, if(data->easy_conn && data->mstate > CURLM_STATE_DO && data->mstate < CURLM_STATE_COMPLETED) { + /* Set connection owner so that the DONE function closes it. We can + safely do this here since connection is killed. */ + data->easy_conn->data = easy; /* If the handle is in a pipeline and has started sending off its request but not received its response yet, we need to close connection. */ streamclose(data->easy_conn, "Removed with partial response"); - /* Set connection owner so that the DONE function closes it. We can - safely do this here since connection is killed. */ - data->easy_conn->data = easy; easy_owns_conn = TRUE; } @@ -734,10 +725,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, /* destroy the timeout list that is held in the easy handle, do this *after* multi_done() as that may actually call Curl_expire that uses this */ - if(data->state.timeoutlist) { - Curl_llist_destroy(data->state.timeoutlist, NULL); - data->state.timeoutlist = NULL; - } + Curl_llist_destroy(&data->state.timeoutlist, NULL); /* as this was using a shared connection cache we clear the pointer to that since we're not part of that multi handle anymore */ @@ -760,11 +748,11 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, /* make sure there's no pending message in the queue sent from this easy handle */ - for(e = multi->msglist->head; e; e = e->next) { + for(e = multi->msglist.head; e; e = e->next) { struct Curl_message *msg = e->ptr; if(msg->extmsg.easy_handle == easy) { - Curl_llist_remove(multi->msglist, e, NULL); + Curl_llist_remove(&multi->msglist, e, NULL); /* there can only be one from this specific handle */ break; } @@ -812,6 +800,11 @@ static int waitconnect_getsock(struct connectdata *conn, if(!numsocks) return GETSOCK_BLANK; +#ifdef USE_SSL + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return Curl_ssl_getsock(conn, sock, numsocks); +#endif + for(i=0; i<2; i++) { if(conn->tempsock[i] != CURL_SOCKET_BAD) { sock[s] = conn->tempsock[i]; @@ -950,10 +943,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, if(s == CURL_SOCKET_BAD) /* this socket is unused, break out of loop */ break; - else { - if((int)s > this_max_fd) - this_max_fd = (int)s; - } + if((int)s > this_max_fd) + this_max_fd = (int)s; } data = data->next; /* check next handle */ @@ -964,6 +955,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, return CURLM_OK; } +#define NUM_POLLS_ON_STACK 10 + CURLMcode curl_multi_wait(struct Curl_multi *multi, struct curl_waitfd extra_fds[], unsigned int extra_nfds, @@ -977,8 +970,10 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, unsigned int nfds = 0; unsigned int curlfds; struct pollfd *ufds = NULL; + bool ufds_malloc = FALSE; long timeout_internal; int retcode = 0; + struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -1017,10 +1012,15 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, curlfds = nfds; /* number of internal file descriptors */ nfds += extra_nfds; /* add the externally provided ones */ - if(nfds || extra_nfds) { - ufds = malloc(nfds * sizeof(struct pollfd)); - if(!ufds) - return CURLM_OUT_OF_MEMORY; + if(nfds) { + if(nfds > NUM_POLLS_ON_STACK) { + ufds = malloc(nfds * sizeof(struct pollfd)); + if(!ufds) + return CURLM_OUT_OF_MEMORY; + ufds_malloc = TRUE; + } + else + ufds = &a_few_on_stack[0]; } nfds = 0; @@ -1098,7 +1098,8 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, } } - free(ufds); + if(ufds_malloc) + free(ufds); if(ret) *ret = retcode; return CURLM_OK; @@ -1300,7 +1301,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, CURLMcode rc; CURLcode result = CURLE_OK; struct SingleRequest *k; - long timeout_ms; + time_t timeout_ms; + time_t recv_timeout_ms; + time_t send_timeout_ms; int control; if(!GOOD_EASY_HANDLE(data)) @@ -1426,10 +1429,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, CURLM_STATE_CONNECT_PEND); /* add this handle to the list of connect-pending handles */ - if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data)) - result = CURLE_OUT_OF_MEMORY; - else - result = CURLE_OK; + Curl_llist_insert_next(&multi->pending, multi->pending.tail, data, + &data->connect_queue); + result = CURLE_OK; break; } @@ -1471,8 +1473,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, struct connectdata *conn = data->easy_conn; const char *hostname; - if(conn->bits.proxy) - hostname = conn->proxy.name; + if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; else if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; else @@ -1548,7 +1550,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, CURLM_STATE_CONNECT); } else if(!result) { - if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) { + if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS || + data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) && + (data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT)) { rc = CURLM_CALL_MULTI_PERFORM; /* initiate protocol connect phase */ multistate(data, CURLM_STATE_SENDPROTOCONNECT); @@ -1561,6 +1565,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* awaiting a completion of an asynch TCP connect */ result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected); if(connected && !result) { +#ifndef CURL_DISABLE_HTTP + if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS && + !data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) || + (data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) { + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + break; + } +#endif rc = CURLM_CALL_MULTI_PERFORM; multistate(data, data->easy_conn->bits.tunnel_proxy? CURLM_STATE_WAITPROXYCONNECT: @@ -1703,20 +1715,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, else { /* Follow failed */ result = drc; - free(newurl); } } else { /* done didn't return OK or SEND_ERROR */ result = drc; - free(newurl); } } else { /* Have error handler disconnect conn if we can't retry */ stream_error = TRUE; - free(newurl); } + free(newurl); } else { /* failure detected */ @@ -1810,19 +1820,30 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, else result = Curl_speedcheck(data, now); - if(( (data->set.max_send_speed == 0) || - (Curl_pgrsLimitWaitTime(data->progress.uploaded, - data->progress.ul_limit_size, - data->set.max_send_speed, - data->progress.ul_limit_start, - now) <= 0)) && - ( (data->set.max_recv_speed == 0) || - (Curl_pgrsLimitWaitTime(data->progress.downloaded, - data->progress.dl_limit_size, - data->set.max_recv_speed, - data->progress.dl_limit_start, - now) <= 0))) - multistate(data, CURLM_STATE_PERFORM); + if(!result) { + send_timeout_ms = 0; + if(data->set.max_send_speed > 0) + send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded, + data->progress.ul_limit_size, + data->set.max_send_speed, + data->progress.ul_limit_start, + now); + + recv_timeout_ms = 0; + if(data->set.max_recv_speed > 0) + recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded, + data->progress.dl_limit_size, + data->set.max_recv_speed, + data->progress.dl_limit_start, + now); + + if(send_timeout_ms <= 0 && recv_timeout_ms <= 0) + multistate(data, CURLM_STATE_PERFORM); + else if(send_timeout_ms >= recv_timeout_ms) + Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); + else + Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); + } break; case CURLM_STATE_PERFORM: @@ -1832,31 +1853,30 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, bool comeback = FALSE; /* check if over send speed */ - if(data->set.max_send_speed > 0) { - timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded, - data->progress.ul_limit_size, - data->set.max_send_speed, - data->progress.ul_limit_start, - now); - if(timeout_ms > 0) { - multistate(data, CURLM_STATE_TOOFAST); - Curl_expire_latest(data, timeout_ms); - break; - } - } + send_timeout_ms = 0; + if(data->set.max_send_speed > 0) + send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded, + data->progress.ul_limit_size, + data->set.max_send_speed, + data->progress.ul_limit_start, + now); /* check if over recv speed */ - if(data->set.max_recv_speed > 0) { - timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded, - data->progress.dl_limit_size, - data->set.max_recv_speed, - data->progress.dl_limit_start, - now); - if(timeout_ms > 0) { - multistate(data, CURLM_STATE_TOOFAST); - Curl_expire_latest(data, timeout_ms); - break; - } + recv_timeout_ms = 0; + if(data->set.max_recv_speed > 0) + recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded, + data->progress.dl_limit_size, + data->set.max_recv_speed, + data->progress.dl_limit_start, + now); + + if(send_timeout_ms > 0 || recv_timeout_ms > 0) { + multistate(data, CURLM_STATE_TOOFAST); + if(send_timeout_ms >= recv_timeout_ms) + Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST); + else + Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST); + break; } /* read/write data if it is ready to do so */ @@ -1912,11 +1932,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, Curl_posttransfer(data); /* we're no longer receiving */ - Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe); + Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe); /* expire the new receiving pipeline head */ - if(data->easy_conn->recv_pipe->head) - Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 0); + if(data->easy_conn->recv_pipe.head) + Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW); /* Check if we can move pending requests to send pipe */ Curl_multi_process_pending_handles(multi); @@ -1940,9 +1960,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(!result) { multistate(data, CURLM_STATE_CONNECT); rc = CURLM_CALL_MULTI_PERFORM; - newurl = NULL; /* handed over the memory ownership to - Curl_follow(), make sure we don't free() it - here */ } } } @@ -1956,9 +1973,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, newurl = data->req.location; data->req.location = NULL; result = Curl_follow(data, newurl, FOLLOW_FAKE); - if(!result) - newurl = NULL; /* allocation was handed over Curl_follow() */ - else + if(result) stream_error = TRUE; } @@ -1981,7 +1996,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, CURLcode res; /* Remove ourselves from the receive pipeline, if we are there. */ - Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe); + Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe); /* Check if we can move pending requests to send pipe */ Curl_multi_process_pending_handles(multi); @@ -2057,8 +2072,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* if this has a connection, unsubscribe from the pipelines */ Curl_pipeline_leave_write(data->easy_conn); Curl_pipeline_leave_read(data->easy_conn); - Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe); - Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe); + Curl_removeHandleFromPipeline(data, &data->easy_conn->send_pipe); + Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe); if(stream_error) { /* Don't attempt to send data over a connection that timed out */ @@ -2213,8 +2228,8 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_hash_destroy(&multi->sockhash); Curl_conncache_destroy(&multi->conn_cache); - Curl_llist_destroy(multi->msglist, NULL); - Curl_llist_destroy(multi->pending, NULL); + Curl_llist_destroy(&multi->msglist, NULL); + Curl_llist_destroy(&multi->pending, NULL); /* remove all easy handles */ data = multi->easyp; @@ -2246,8 +2261,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) return CURLM_OK; } - else - return CURLM_BAD_HANDLE; + return CURLM_BAD_HANDLE; } /* @@ -2266,24 +2280,23 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue) *msgs_in_queue = 0; /* default to none */ - if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) { + if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(&multi->msglist)) { /* there is one or more messages in the list */ struct curl_llist_element *e; /* extract the head of the list to return */ - e = multi->msglist->head; + e = multi->msglist.head; msg = e->ptr; /* remove the extracted entry */ - Curl_llist_remove(multi->msglist, e, NULL); + Curl_llist_remove(&multi->msglist, e, NULL); - *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist)); + *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist)); return &msg->extmsg; } - else - return NULL; + return NULL; } /* @@ -2378,7 +2391,7 @@ static void singlesocket(struct Curl_multi *multi, removed. */ struct connectdata *easy_conn = data->easy_conn; if(easy_conn) { - if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) { + if(easy_conn->recv_pipe.size > 1) { /* the handle should not be removed from the pipe yet */ remove_sock_from_hash = FALSE; @@ -2387,12 +2400,12 @@ static void singlesocket(struct Curl_multi *multi, isn't already) */ if(entry->easy == data) { if(Curl_recvpipe_head(data, easy_conn)) - entry->easy = easy_conn->recv_pipe->head->next->ptr; + entry->easy = easy_conn->recv_pipe.head->next->ptr; else - entry->easy = easy_conn->recv_pipe->head->ptr; + entry->easy = easy_conn->recv_pipe.head->ptr; } } - if(easy_conn->send_pipe && easy_conn->send_pipe->size > 1) { + if(easy_conn->send_pipe.size > 1) { /* the handle should not be removed from the pipe yet */ remove_sock_from_hash = FALSE; @@ -2401,9 +2414,9 @@ static void singlesocket(struct Curl_multi *multi, isn't already) */ if(entry->easy == data) { if(Curl_sendpipe_head(data, easy_conn)) - entry->easy = easy_conn->send_pipe->head->next->ptr; + entry->easy = easy_conn->send_pipe.head->next->ptr; else - entry->easy = easy_conn->send_pipe->head->ptr; + entry->easy = easy_conn->send_pipe.head->ptr; } } /* Don't worry about overwriting recv_pipe head with send_pipe_head, @@ -2459,8 +2472,6 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s) } } - - /* * add_next_timeout() * @@ -2478,15 +2489,18 @@ static CURLMcode add_next_timeout(struct timeval now, struct Curl_easy *d) { struct timeval *tv = &d->state.expiretime; - struct curl_llist *list = d->state.timeoutlist; + 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; - long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now); + time_t diff; + node = (struct time_node *)e->ptr; + diff = curlx_tvdiff(node->time, now); if(diff <= 0) /* remove outdated entry */ Curl_llist_remove(list, e, NULL); @@ -2504,7 +2518,7 @@ static CURLMcode add_next_timeout(struct timeval now, } else { /* copy the first entry to 'tv' */ - memcpy(tv, e->ptr, sizeof(*tv)); + memcpy(tv, &node->time, sizeof(*tv)); /* remove first entry from list */ Curl_llist_remove(list, e, NULL); @@ -2544,7 +2558,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi, /* or should we fall-through and do the timer-based stuff? */ return result; } - else if(s != CURL_SOCKET_TIMEOUT) { + if(s != CURL_SOCKET_TIMEOUT) { struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s); @@ -2569,13 +2583,11 @@ static CURLMcode multi_socket(struct Curl_multi *multi, head. If we should read from the socket, take the recv_pipe head. */ if(data->easy_conn) { if((ev_bitmask & CURL_POLL_OUT) && - data->easy_conn->send_pipe && - data->easy_conn->send_pipe->head) - data = data->easy_conn->send_pipe->head->ptr; + data->easy_conn->send_pipe.head) + data = data->easy_conn->send_pipe.head->ptr; else if((ev_bitmask & CURL_POLL_IN) && - data->easy_conn->recv_pipe && - data->easy_conn->recv_pipe->head) - data = data->easy_conn->recv_pipe->head->ptr; + data->easy_conn->recv_pipe.head) + data = data->easy_conn->recv_pipe.head->ptr; } if(data->easy_conn && @@ -2764,7 +2776,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi, if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) { /* some time left before expiration */ - *timeout_ms = curlx_tvdiff(multi->timetree->key, now); + *timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now); if(!*timeout_ms) /* * Since we only provide millisecond resolution on the returned value @@ -2832,17 +2844,23 @@ static int update_timer(struct Curl_multi *multi) } /* - * multi_freetimeout() + * multi_deltimeout() * - * Callback used by the llist system when a single timeout list entry is - * destroyed. + * Remove a given timestamp from the list of timeouts. */ -static void multi_freetimeout(void *user, void *entryptr) +static void +multi_deltimeout(struct Curl_easy *data, expire_id eid) { - (void)user; - - /* the entry was plain malloc()'ed */ - free(entryptr); + 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; + if(n->eid == eid) { + Curl_llist_remove(timeoutlist, e, NULL); + return; + } + } } /* @@ -2853,25 +2871,28 @@ static void multi_freetimeout(void *user, void *entryptr) * */ static CURLMcode -multi_addtimeout(struct curl_llist *timeoutlist, - struct timeval *stamp) +multi_addtimeout(struct Curl_easy *data, + struct timeval *stamp, + expire_id eid) { struct curl_llist_element *e; - struct timeval *timedup; + struct time_node *node; struct curl_llist_element *prev = NULL; + size_t n; + struct curl_llist *timeoutlist = &data->state.timeoutlist; - timedup = malloc(sizeof(*timedup)); - if(!timedup) - return CURLM_OUT_OF_MEMORY; + node = &data->state.expires[eid]; - /* copy the timestamp */ - memcpy(timedup, stamp, sizeof(*timedup)); + /* copy the timestamp and id */ + memcpy(&node->time, stamp, sizeof(*stamp)); + node->eid = eid; /* also marks it as in use */ - if(Curl_llist_count(timeoutlist)) { + n = Curl_llist_count(timeoutlist); + if(n) { /* find the correct spot in the list */ for(e = timeoutlist->head; e; e = e->next) { - struct timeval *checktime = e->ptr; - long diff = curlx_tvdiff(*checktime, *timedup); + struct time_node *check = (struct time_node *)e->ptr; + time_t diff = curlx_tvdiff(check->time, node->time); if(diff > 0) break; prev = e; @@ -2881,11 +2902,7 @@ multi_addtimeout(struct curl_llist *timeoutlist, /* else this is the first timeout on the list */ - if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) { - free(timedup); - return CURLM_OUT_OF_MEMORY; - } - + Curl_llist_insert_next(timeoutlist, prev, node, &node->list); return CURLM_OK; } @@ -2897,8 +2914,10 @@ multi_addtimeout(struct curl_llist *timeoutlist, * * The timeout will be added to a queue of timeouts if it defines a moment in * time that is later than the current head of queue. + * + * Expire replaces a former timeout using the same id if already set. */ -void Curl_expire(struct Curl_easy *data, long milli) +void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id) { struct Curl_multi *multi = data->multi; struct timeval *nowp = &data->state.expiretime; @@ -2910,9 +2929,11 @@ void Curl_expire(struct Curl_easy *data, long milli) if(!multi) return; + DEBUGASSERT(id < EXPIRE_LAST); + set = Curl_tvnow(); - set.tv_sec += milli/1000; - set.tv_usec += (milli%1000)*1000; + set.tv_sec += (long)(milli/1000); + set.tv_usec += (long)(milli%1000)*1000; if(set.tv_usec >= 1000000) { set.tv_sec++; @@ -2923,17 +2944,21 @@ void Curl_expire(struct Curl_easy *data, long milli) /* This means that the struct is added as a node in the splay tree. Compare if the new time is earlier, and only remove-old/add-new if it is. */ - long diff = curlx_tvdiff(set, *nowp); + time_t diff = curlx_tvdiff(set, *nowp); + + /* remove the previous timer first, if there */ + multi_deltimeout(data, id); + if(diff > 0) { /* the new expire time was later so just add it to the queue and get out */ - multi_addtimeout(data->state.timeoutlist, &set); + multi_addtimeout(data, &set, id); return; } /* the new time is newer than the presently set one, so add the current to the queue and update the head */ - multi_addtimeout(data->state.timeoutlist, nowp); + multi_addtimeout(data, nowp, 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 */ @@ -2951,46 +2976,17 @@ void Curl_expire(struct Curl_easy *data, long milli) } /* - * Curl_expire_latest() - * - * This is like Curl_expire() but will only add a timeout node to the list of - * timers if there is no timeout that will expire before the given time. + * Curl_expire_done() * - * Use this function if the code logic risks calling this function many times - * or if there's no particular conditional wait in the code for this specific - * time-out period to expire. + * Removes the expire timer. Marks it as done. * */ -void Curl_expire_latest(struct Curl_easy *data, long milli) +void Curl_expire_done(struct Curl_easy *data, expire_id id) { - struct timeval *expire = &data->state.expiretime; - - struct timeval set; - - set = Curl_tvnow(); - set.tv_sec += milli / 1000; - set.tv_usec += (milli % 1000) * 1000; - - if(set.tv_usec >= 1000000) { - set.tv_sec++; - set.tv_usec -= 1000000; - } - - if(expire->tv_sec || expire->tv_usec) { - /* This means that the struct is added as a node in the splay tree. - Compare if the new time is earlier, and only remove-old/add-new if it - is. */ - long diff = curlx_tvdiff(set, *expire); - if(diff > 0) - /* the new expire time was later than the top time, so just skip this */ - return; - } - - /* Just add the timeout like normal */ - Curl_expire(data, milli); + /* remove the timer, if there */ + multi_deltimeout(data, id); } - /* * Curl_expire_clear() * @@ -3010,7 +3006,7 @@ 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; rc = Curl_splayremovebyaddr(multi->timetree, &data->state.timenode, @@ -3019,8 +3015,9 @@ void Curl_expire_clear(struct Curl_easy *data) infof(data, "Internal error clearing splay node = %d\n", rc); /* flush the timeout list too */ - while(list->size > 0) + while(list->size > 0) { Curl_llist_remove(list, list->tail, NULL); + } #ifdef DEBUGBUILD infof(data, "Expire cleared\n"); @@ -3070,17 +3067,17 @@ curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi) struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi) { - return multi->pipelining_site_bl; + return &multi->pipelining_site_bl; } struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi) { - return multi->pipelining_server_bl; + return &multi->pipelining_server_bl; } void Curl_multi_process_pending_handles(struct Curl_multi *multi) { - struct curl_llist_element *e = multi->pending->head; + struct curl_llist_element *e = multi->pending.head; while(e) { struct Curl_easy *data = e->ptr; @@ -3090,10 +3087,10 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi) multistate(data, CURLM_STATE_CONNECT); /* Remove this node from the list */ - Curl_llist_remove(multi->pending, e, NULL); + Curl_llist_remove(&multi->pending, e, NULL); /* Make sure that the handle will be processed soonish. */ - Curl_expire_latest(data, 0); + Curl_expire(data, 0, EXPIRE_RUN_NOW); } e = next; /* operate on next handle */ diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h index c56b6aec1..e6ffbf5b6 100644 --- a/Utilities/cmcurl/lib/multihandle.h +++ b/Utilities/cmcurl/lib/multihandle.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -25,6 +25,7 @@ #include "conncache.h" struct Curl_message { + struct curl_llist_element list; /* the 'CURLMsg' is the part that is visible to the external user */ struct CURLMsg extmsg; }; @@ -38,7 +39,9 @@ typedef enum { CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ - CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */ + CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization + to complete and/or proxy CONNECT to + finalize */ CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect phase */ @@ -78,10 +81,10 @@ 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 - CURLM_STATE_CONNECT_PEND state */ + 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 */ curl_socket_callback socket_cb; @@ -136,11 +139,11 @@ struct Curl_multi { bigger than this is not considered for pipelining */ - struct curl_llist *pipelining_site_bl; /* List of sites that are blacklisted - from pipelining */ + struct curl_llist pipelining_site_bl; /* List of sites that are blacklisted + from pipelining */ - struct curl_llist *pipelining_server_bl; /* List of server types that are - blacklisted from pipelining */ + struct curl_llist pipelining_server_bl; /* List of server types that are + blacklisted from pipelining */ /* timer callback and user data pointer for the *socket() API */ curl_multi_timer_callback timer_cb; diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h index eaff496ea..a877571a0 100644 --- a/Utilities/cmcurl/lib/multiif.h +++ b/Utilities/cmcurl/lib/multiif.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -25,9 +25,10 @@ /* * Prototypes for library-wide functions provided by multi.c */ -void Curl_expire(struct Curl_easy *data, long milli); + +void Curl_expire(struct Curl_easy *data, time_t milli, expire_id); void Curl_expire_clear(struct Curl_easy *data); -void Curl_expire_latest(struct Curl_easy *data, long milli); +void Curl_expire_done(struct Curl_easy *data, expire_id id); bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits); void Curl_multi_handlePipeBreak(struct Curl_easy *data); diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c index ed1461807..2f5de4c68 100644 --- a/Utilities/cmcurl/lib/non-ascii.c +++ b/Utilities/cmcurl/lib/non-ascii.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -117,7 +117,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, /* call iconv */ input_ptr = output_ptr = buffer; in_bytes = out_bytes = length; - rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes, + rc = iconv(data->outbound_cd, (const char **)&input_ptr, &in_bytes, &output_ptr, &out_bytes); if((rc == ICONV_ERROR) || (in_bytes != 0)) { error = ERRNO; diff --git a/Utilities/cmcurl/lib/nonblock.c b/Utilities/cmcurl/lib/nonblock.c index b764278a5..5959281e5 100644 --- a/Utilities/cmcurl/lib/nonblock.c +++ b/Utilities/cmcurl/lib/nonblock.c @@ -58,8 +58,7 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ flags = sfcntl(sockfd, F_GETFL, 0); if(nonblock) return sfcntl(sockfd, F_SETFL, flags | O_NONBLOCK); - else - return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); + return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); #elif defined(HAVE_IOCTL_FIONBIO) diff --git a/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c index 42b6aa0da..290cbe31f 100644 --- a/Utilities/cmcurl/lib/nwlib.c +++ b/Utilities/cmcurl/lib/nwlib.c @@ -184,7 +184,8 @@ int GetOrSetUpData(int id, libdata_t **appData, */ NXLock(gLibLock); - if(!(app_data = (libdata_t *) get_app_data(id))) { + app_data = (libdata_t *) get_app_data(id); + if(!app_data) { app_data = malloc(sizeof(libdata_t)); if(app_data) { @@ -259,7 +260,8 @@ int GetOrSetUpData(int id, libdata_t **appData, err = ENOMEM; } - if((err = NXKeySetValue(key, thread_data))) { + err = NXKeySetValue(key, thread_data); + if(err) { free(thread_data->twentybytes); free(thread_data); thread_data = (libthreaddata_t *) NULL; @@ -303,14 +305,14 @@ void DisposeThreadData(void *data) /* For native CLib-based NLM seems we can do a bit more simple. */ #include -int main (void) +int main(void) { /* initialize any globals here... */ /* do this if any global initializing was done SynchronizeStart(); */ - ExitThread (TSR_THREAD, 0); + ExitThread(TSR_THREAD, 0); return 0; } diff --git a/Utilities/cmcurl/lib/nwos.c b/Utilities/cmcurl/lib/nwos.c index 385f9c8ad..c6c22ccbb 100644 --- a/Utilities/cmcurl/lib/nwos.c +++ b/Utilities/cmcurl/lib/nwos.c @@ -26,7 +26,7 @@ #ifdef __NOVELL_LIBC__ /* For native LibC-based NLM we need to do nothing. */ -int netware_init (void) +int netware_init(void) { return 0; } @@ -45,7 +45,7 @@ NETDB_DEFINE_CONTEXT #include NETINET_DEFINE_CONTEXT -int netware_init (void) +int netware_init(void) { int rc = 0; unsigned int myHandle = GetNLMHandle(); @@ -72,13 +72,13 @@ int netware_init (void) } /* dummy function to satisfy newer prelude */ -int __init_environment (void) +int __init_environment(void) { return 0; } /* dummy function to satisfy newer prelude */ -int __deinit_environment (void) +int __deinit_environment(void) { return 0; } diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c index bf2c8fd0a..5ed79b718 100644 --- a/Utilities/cmcurl/lib/pingpong.c +++ b/Utilities/cmcurl/lib/pingpong.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -44,12 +44,12 @@ /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -long Curl_pp_state_timeout(struct pingpong *pp) +time_t Curl_pp_state_timeout(struct pingpong *pp) { struct connectdata *conn = pp->conn; struct Curl_easy *data=conn->data; - long timeout_ms; /* in milliseconds */ - long timeout2_ms; /* in milliseconds */ + time_t timeout_ms; /* in milliseconds */ + time_t timeout2_ms; /* in milliseconds */ long response_time= (data->set.server_response_timeout)? data->set.server_response_timeout: pp->response_time; @@ -83,8 +83,8 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block) struct connectdata *conn = pp->conn; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int rc; - long interval_ms; - long timeout_ms = Curl_pp_state_timeout(pp); + time_t interval_ms; + time_t timeout_ms = Curl_pp_state_timeout(pp); struct Curl_easy *data=conn->data; CURLcode result = CURLE_OK; @@ -101,7 +101,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block) else interval_ms = 0; /* immediate */ - if(Curl_pp_moredata(pp)) + if(Curl_ssl_data_pending(conn, FIRSTSOCKET)) + rc = 1; + else if(Curl_pp_moredata(pp)) /* We are receiving and there is data in the cache so just read it */ rc = 1; else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET)) @@ -150,7 +152,7 @@ void Curl_pp_init(struct pingpong *pp) * * Curl_pp_vsendf() * - * Send the formated string as a command to a pingpong server. Note that + * Send the formatted string as a command to a pingpong server. Note that * the string should not have any CRLF appended, as this function will * append the necessary things itself. * @@ -237,7 +239,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp, * * Curl_pp_sendf() * - * Send the formated string as a command to a pingpong server. Note that + * Send the formatted string as a command to a pingpong server. Note that * the string should not have any CRLF appended, as this function will * append the necessary things itself. * @@ -284,7 +286,8 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, /* number of bytes in the current line, so far */ perline = (ssize_t)(ptr-pp->linestart_resp); - while((pp->nread_respnread_resp < (size_t)data->set.buffer_size) && + (keepon && !result)) { if(pp->cache) { /* we had data in the "cache", copy that instead of doing an actual @@ -294,7 +297,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, * it would have been populated with something of size int to begin * with, even though its datatype may be larger than an int. */ - DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1)); + DEBUGASSERT((ptr+pp->cache_size) <= (buf+data->set.buffer_size+1)); memcpy(ptr, pp->cache, pp->cache_size); gotbytes = (ssize_t)pp->cache_size; free(pp->cache); /* free the cache */ @@ -306,8 +309,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, enum protection_level prot = conn->data_prot; conn->data_prot = PROT_CLEAR; #endif - DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); - result = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, + DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <= + (buf + data->set.buffer_size + 1)); + result = Curl_read(conn, sockfd, ptr, + data->set.buffer_size - pp->nread_resp, &gotbytes); #ifdef HAVE_GSSAPI DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST); @@ -400,7 +405,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, } else if(keepon) { - if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) { + if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) { /* We got an excessive line without newlines and we need to deal with it. We keep the first bytes of the line then we throw away the rest. */ @@ -412,7 +417,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, interested in the first piece */ clipamount = 40; } - else if(pp->nread_resp > BUFSIZE/2) { + else if(pp->nread_resp > (size_t)data->set.buffer_size/2) { /* We got a large chunk of data and there's potentially still trailing data to take care of, so we put any such part in the "cache", clear the buffer to make space and restart. */ diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h index 2f649d5bf..ee1a59b51 100644 --- a/Utilities/cmcurl/lib/pingpong.h +++ b/Utilities/cmcurl/lib/pingpong.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -88,14 +88,14 @@ void Curl_pp_init(struct pingpong *pp); /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -long Curl_pp_state_timeout(struct pingpong *pp); +time_t Curl_pp_state_timeout(struct pingpong *pp); /*********************************************************************** * * Curl_pp_sendf() * - * Send the formated string as a command to a pingpong server. Note that + * Send the formatted string as a command to a pingpong server. Note that * the string should not have any CRLF appended, as this function will * append the necessary things itself. * @@ -108,7 +108,7 @@ CURLcode Curl_pp_sendf(struct pingpong *pp, * * Curl_pp_vsendf() * - * Send the formated string as a command to a pingpong server. Note that + * Send the formatted string as a command to a pingpong server. Note that * the string should not have any CRLF appended, as this function will * append the necessary things itself. * diff --git a/Utilities/cmcurl/lib/pipeline.c b/Utilities/cmcurl/lib/pipeline.c index 40a5e82d8..b8d203745 100644 --- a/Utilities/cmcurl/lib/pipeline.c +++ b/Utilities/cmcurl/lib/pipeline.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2013, Linus Nielsen Feltzing, - * Copyright (C) 2013-2016, Daniel Stenberg, , et al. + * Copyright (C) 2013 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -38,16 +38,15 @@ #include "memdebug.h" struct site_blacklist_entry { - char *hostname; + struct curl_llist_element list; unsigned short port; + char hostname[1]; }; static void site_blacklist_llist_dtor(void *user, void *element) { struct site_blacklist_entry *entry = element; (void)user; - - Curl_safefree(entry->hostname); free(entry); } @@ -69,8 +68,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data, curl_off_t recv_size = -2; /* Make it easy to spot in the log */ /* Find the head of the recv pipe, if any */ - if(conn->recv_pipe && conn->recv_pipe->head) { - struct Curl_easy *recv_handle = conn->recv_pipe->head->ptr; + if(conn->recv_pipe.head) { + struct Curl_easy *recv_handle = conn->recv_pipe.head->ptr; recv_size = recv_handle->req.size; @@ -94,8 +93,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data, static CURLcode addHandleToPipeline(struct Curl_easy *data, struct curl_llist *pipeline) { - if(!Curl_llist_insert_next(pipeline, pipeline->tail, data)) - return CURLE_OUT_OF_MEMORY; + Curl_llist_insert_next(pipeline, pipeline->tail, data, + &data->pipeline_queue); return CURLE_OK; } @@ -103,18 +102,18 @@ static CURLcode addHandleToPipeline(struct Curl_easy *data, CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle, struct connectdata *conn) { - struct curl_llist_element *sendhead = conn->send_pipe->head; + struct curl_llist_element *sendhead = conn->send_pipe.head; struct curl_llist *pipeline; CURLcode result; - pipeline = conn->send_pipe; + pipeline = &conn->send_pipe; result = addHandleToPipeline(handle, pipeline); - if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) { + if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) { /* this is a new one as head, expire it */ Curl_pipeline_leave_write(conn); /* not in use yet */ - Curl_expire(conn->send_pipe->head->ptr, 0); + Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW); } #if 0 /* enable for pipeline debugging */ @@ -135,21 +134,21 @@ void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle, { struct curl_llist_element *curr; - curr = conn->send_pipe->head; + curr = conn->send_pipe.head; while(curr) { if(curr->ptr == handle) { - Curl_llist_move(conn->send_pipe, curr, - conn->recv_pipe, conn->recv_pipe->tail); + Curl_llist_move(&conn->send_pipe, curr, + &conn->recv_pipe, conn->recv_pipe.tail); - if(conn->send_pipe->head) { + if(conn->send_pipe.head) { /* Since there's a new easy handle at the start of the send pipeline, set its timeout value to 1ms to make it trigger instantly */ Curl_pipeline_leave_write(conn); /* not used now */ #ifdef DEBUGBUILD infof(conn->data, "%p is at send pipe head B!\n", - (void *)conn->send_pipe->head->ptr); + (void *)conn->send_pipe.head->ptr); #endif - Curl_expire(conn->send_pipe->head->ptr, 0); + Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW); } /* The receiver's list is not really interesting here since either this @@ -191,36 +190,28 @@ bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle, } CURLMcode Curl_pipeline_set_site_blacklist(char **sites, - struct curl_llist **list_ptr) + struct curl_llist *list) { - struct curl_llist *old_list = *list_ptr; - struct curl_llist *new_list = NULL; + /* Free the old list */ + if(list->size) + Curl_llist_destroy(list, NULL); if(sites) { - new_list = Curl_llist_alloc((curl_llist_dtor) site_blacklist_llist_dtor); - if(!new_list) - return CURLM_OUT_OF_MEMORY; + Curl_llist_init(list, (curl_llist_dtor) site_blacklist_llist_dtor); /* Parse the URLs and populate the list */ while(*sites) { - char *hostname; char *port; struct site_blacklist_entry *entry; - hostname = strdup(*sites); - if(!hostname) { - Curl_llist_destroy(new_list, NULL); - return CURLM_OUT_OF_MEMORY; - } - - entry = malloc(sizeof(struct site_blacklist_entry)); + entry = malloc(sizeof(struct site_blacklist_entry) + strlen(*sites)); if(!entry) { - free(hostname); - Curl_llist_destroy(new_list, NULL); + Curl_llist_destroy(list, NULL); return CURLM_OUT_OF_MEMORY; } + strcpy(entry->hostname, *sites); - port = strchr(hostname, ':'); + port = strchr(entry->hostname, ':'); if(port) { *port = '\0'; port++; @@ -231,26 +222,11 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites, entry->port = 80; } - entry->hostname = hostname; - - if(!Curl_llist_insert_next(new_list, new_list->tail, entry)) { - site_blacklist_llist_dtor(NULL, entry); - Curl_llist_destroy(new_list, NULL); - return CURLM_OUT_OF_MEMORY; - } - + Curl_llist_insert_next(list, list->tail, entry, &entry->list); sites++; } } - /* Free the old list */ - if(old_list) { - Curl_llist_destroy(old_list, NULL); - } - - /* This might be NULL if sites == NULL, i.e the blacklist is cleared */ - *list_ptr = new_list; - return CURLM_OK; } @@ -283,44 +259,39 @@ bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle, return FALSE; } +struct blacklist_node { + struct curl_llist_element list; + char server_name[1]; +}; + CURLMcode Curl_pipeline_set_server_blacklist(char **servers, - struct curl_llist **list_ptr) + struct curl_llist *list) { - struct curl_llist *old_list = *list_ptr; - struct curl_llist *new_list = NULL; + /* Free the old list */ + if(list->size) + Curl_llist_destroy(list, NULL); if(servers) { - new_list = Curl_llist_alloc((curl_llist_dtor) server_blacklist_llist_dtor); - if(!new_list) - return CURLM_OUT_OF_MEMORY; + Curl_llist_init(list, (curl_llist_dtor) server_blacklist_llist_dtor); /* Parse the URLs and populate the list */ while(*servers) { - char *server_name; + struct blacklist_node *n; + size_t len = strlen(*servers); - server_name = strdup(*servers); - if(!server_name) { - Curl_llist_destroy(new_list, NULL); - return CURLM_OUT_OF_MEMORY; - } - - if(!Curl_llist_insert_next(new_list, new_list->tail, server_name)) { - Curl_llist_destroy(new_list, NULL); - Curl_safefree(server_name); + n = malloc(sizeof(struct blacklist_node) + len); + if(!n) { + Curl_llist_destroy(list, NULL); return CURLM_OUT_OF_MEMORY; } + strcpy(n->server_name, *servers); + Curl_llist_insert_next(list, list->tail, n->server_name, + &n->list); servers++; } } - /* Free the old list */ - if(old_list) { - Curl_llist_destroy(old_list, NULL); - } - - /* This might be NULL if sites == NULL, i.e the blacklist is cleared */ - *list_ptr = new_list; return CURLM_OK; } @@ -340,14 +311,14 @@ static bool pipe_head(struct Curl_easy *data, bool Curl_recvpipe_head(struct Curl_easy *data, struct connectdata *conn) { - return pipe_head(data, conn->recv_pipe); + return pipe_head(data, &conn->recv_pipe); } /* returns TRUE if the given handle is head of the send pipe */ bool Curl_sendpipe_head(struct Curl_easy *data, struct connectdata *conn) { - return pipe_head(data, conn->send_pipe); + return pipe_head(data, &conn->send_pipe); } diff --git a/Utilities/cmcurl/lib/pipeline.h b/Utilities/cmcurl/lib/pipeline.h index a64f71025..413ba31a0 100644 --- a/Utilities/cmcurl/lib/pipeline.h +++ b/Utilities/cmcurl/lib/pipeline.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2015, Daniel Stenberg, , et al. + * Copyright (C) 2015 - 2017, Daniel Stenberg, , et al. * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, * * This software is licensed as described in the file COPYING, which @@ -34,13 +34,13 @@ bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle, struct connectdata *conn); CURLMcode Curl_pipeline_set_site_blacklist(char **sites, - struct curl_llist **list_ptr); + struct curl_llist *list_ptr); bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle, char *server_name); CURLMcode Curl_pipeline_set_server_blacklist(char **servers, - struct curl_llist **list_ptr); + struct curl_llist *list_ptr); bool Curl_pipeline_checkget_write(struct Curl_easy *data, struct connectdata *conn); diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c index 8486519cd..3feb3be83 100644 --- a/Utilities/cmcurl/lib/pop3.c +++ b/Utilities/cmcurl/lib/pop3.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -104,7 +104,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn); static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, const char *initresp); static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp); -static void pop3_get_message(char *buffer, char** outptr); +static void pop3_get_message(char *buffer, char **outptr); /* * POP3 protocol handler. @@ -127,7 +127,8 @@ const struct Curl_handler Curl_handler_pop3 = { ZERO_NULL, /* readwrite */ PORT_POP3, /* defport */ CURLPROTO_POP3, /* protocol */ - PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ + PROTOPT_URLOPTIONS }; #ifdef USE_SSL @@ -153,7 +154,7 @@ const struct Curl_handler Curl_handler_pop3s = { PORT_POP3S, /* defport */ CURLPROTO_POP3S, /* protocol */ PROTOPT_CLOSEACTION | PROTOPT_SSL - | PROTOPT_NOURLQUERY /* flags */ + | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ }; #endif @@ -290,10 +291,10 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, * * Gets the authentication message from the response buffer. */ -static void pop3_get_message(char *buffer, char** outptr) +static void pop3_get_message(char *buffer, char **outptr) { size_t len = 0; - char* message = NULL; + char *message = NULL; /* Find the start of the message */ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++) @@ -799,7 +800,7 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn, if(pop3code != '+') { if(data->set.use_ssl != CURLUSESSL_TRY) { - failf(data, "STARTTLS denied. %c", pop3code); + failf(data, "STARTTLS denied"); result = CURLE_USE_SSL_FAILED; } else @@ -1572,7 +1573,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(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, strip_dot ? prev - 1 : prev); if(result) diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c index 0f67ef250..cfaf4049e 100644 --- a/Utilities/cmcurl/lib/progress.c +++ b/Utilities/cmcurl/lib/progress.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -229,16 +229,16 @@ void Curl_pgrsStartNow(struct Curl_easy *data) * need to wait until we're back under the speed limit, if needed. * * The way it works is by having a "starting point" (time & amount of data - * transfered by then) used in the speed computation, to be used instead of the - * start of the transfer. - * This starting point is regularly moved as transfer goes on, to keep getting - * accurate values (instead of average over the entire tranfer). + * transferred by then) used in the speed computation, to be used instead of + * the start of the transfer. This starting point is regularly moved as + * transfer goes on, to keep getting accurate values (instead of average over + * the entire transfer). * - * This function takes the current amount of data transfered, the amount at the - * starting point, the limit (in bytes/s), the time of the starting point and - * the current time. + * This function takes the current amount of data transferred, the amount at + * the starting point, the limit (in bytes/s), the time of the starting point + * and the current time. * - * Returns -1 if no waiting is needed (not enough data transfered since + * Returns -1 if no waiting is needed (not enough data transferred since * starting point yet), 0 when no waiting is needed but the starting point * should be reset (to current), or the number of milliseconds to wait to get * back under the speed limit. @@ -249,24 +249,26 @@ long Curl_pgrsLimitWaitTime(curl_off_t cursize, struct timeval start, struct timeval now) { - curl_off_t size = cursize - startsize; - long minimum, actual; + curl_off_t size = cursize - startsize; + time_t minimum; + time_t actual; - /* we don't have a starting point yet -- return 0 so it gets (re)set */ - if(start.tv_sec == 0 && start.tv_usec == 0) - return 0; + /* we don't have a starting point yet -- return 0 so it gets (re)set */ + if(start.tv_sec == 0 && start.tv_usec == 0) + return 0; - /* not enough data yet */ - if(size < limit) - return -1; + /* not enough data yet */ + if(size < limit) + return -1; - minimum = (long) (CURL_OFF_T_C(1000) * size / limit); - actual = Curl_tvdiff(now, start); + minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit); + actual = Curl_tvdiff(now, start); - if(actual < minimum) - return minimum - actual; - else - return 0; + if(actual < minimum) + /* this is a conversion on some systems (64bit time_t => 32bit long) */ + return (long)(minimum - actual); + + return 0; } void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) @@ -359,9 +361,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) now = Curl_tvnow(); /* what time is it */ /* The time spent so far (from the start) */ - data->progress.timespent = - (double)(now.tv_sec - data->progress.start.tv_sec) + - (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0; + data->progress.timespent = curlx_tvdiff_secs(now, data->progress.start); timespent = (curl_off_t)data->progress.timespent; /* The average download speed this far */ @@ -375,7 +375,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) (data->progress.timespent>0?data->progress.timespent:1)); /* Calculations done at most once a second, unless end is reached */ - if(data->progress.lastshow != (long)now.tv_sec) { + if(data->progress.lastshow != now.tv_sec) { shownow = TRUE; data->progress.lastshow = now.tv_sec; @@ -402,7 +402,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) /* first of all, we don't do this if there's no counted seconds yet */ if(countindex) { - long span_ms; + time_t span_ms; /* Get the index position to compare with the 'nowindex' position. Get the oldest entry possible. While we have less than CURR_TIME @@ -454,7 +454,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) failf(data, "Callback aborted"); return result; } - else if(data->set.fprogress) { + if(data->set.fprogress) { /* The older deprecated callback is set, call that */ result= data->set.fprogress(data->set.progress_client, (double)data->progress.size_dl, diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c new file mode 100644 index 000000000..b6f40ac0a --- /dev/null +++ b/Utilities/cmcurl/lib/rand.c @@ -0,0 +1,179 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , 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" + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include "vtls/vtls.h" +#include "sendf.h" +#include "rand.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) +{ + unsigned int r; + CURLcode result = CURLE_OK; + static unsigned int randseed; + static bool seeded = FALSE; + +#ifdef CURLDEBUG + char *force_entropy = getenv("CURL_ENTROPY"); + if(force_entropy) { + if(!seeded) { + unsigned int seed = 0; + size_t elen = strlen(force_entropy); + size_t clen = sizeof(seed); + size_t min = elen < clen ? elen : clen; + memcpy((char *)&seed, force_entropy, min); + randseed = ntohl(seed); + seeded = TRUE; + } + else + randseed++; + *rnd = randseed; + return CURLE_OK; + } +#endif + + /* data may be NULL! */ + result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd)); + if(result != CURLE_NOT_BUILT_IN) + /* only if there is no random function in the TLS backend do the non crypto + version, otherwise return result */ + return result; + + /* ---- non-cryptographic version following ---- */ + +#ifdef RANDOM_FILE + if(!seeded) { + /* if there's a random file to read a seed from, use it */ + int fd = open(RANDOM_FILE, O_RDONLY); + if(fd > -1) { + /* read random data into the randseed variable */ + ssize_t nread = read(fd, &randseed, sizeof(randseed)); + if(nread == sizeof(randseed)) + seeded = TRUE; + close(fd); + } + } +#endif + + if(!seeded) { + struct timeval now = curlx_tvnow(); + infof(data, "WARNING: Using weak random seed\n"); + randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + seeded = TRUE; + } + + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + *rnd = (r << 16) | ((r >> 16) & 0xFFFF); + return CURLE_OK; +} + +/* + * Curl_rand() stores 'num' number of random unsigned integers in the buffer + * 'rndptr' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit, PolarSSL or mbedTLS), this function will use + * "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ + +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + + DEBUGASSERT(num > 0); + + while(num) { + unsigned int r; + size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int); + + result = randit(data, &r); + if(result) + return result; + + while(left) { + *rnd++ = (unsigned char)(r & 0xFF); + r >>= 8; + --num; + --left; + } + } + + return result; +} + +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ + +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + const char *hex = "0123456789abcdef"; + unsigned char buffer[128]; + unsigned char *bufp = buffer; + DEBUGASSERT(num > 1); + + if((num/2 >= sizeof(buffer)) || !(num&1)) + /* make sure it fits in the local buffer and that it is an odd number! */ + return CURLE_BAD_FUNCTION_ARGUMENT; + + num--; /* save one for zero termination */ + + result = Curl_rand(data, buffer, num/2); + if(result) + return result; + + while(num) { + *rnd++ = hex[(*bufp & 0xF0)>>4]; + *rnd++ = hex[*bufp & 0x0F]; + bufp++; + num -= 2; + } + *rnd = 0; + + return result; +} diff --git a/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h new file mode 100644 index 000000000..c6fae3553 --- /dev/null +++ b/Utilities/cmcurl/lib/rand.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_RAND_H +#define HEADER_CURL_RAND_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , 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. + * + ***************************************************************************/ + +/* + * Curl_rand() stores 'num' number of random unsigned characters in the buffer + * 'rnd' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit, PolarSSL or mbedTLS), this function will use + * "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num); + +/* Same as above but outputs only random lowercase hex characters. + Does NOT terminate.*/ +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num); + +#endif /* HEADER_CURL_RAND_H */ diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c index d1bad19da..1810cdafb 100644 --- a/Utilities/cmcurl/lib/rtsp.c +++ b/Utilities/cmcurl/lib/rtsp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -36,6 +36,7 @@ #include "strcase.h" #include "select.h" #include "connect.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -139,7 +140,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn) * want to block the application forever while receiving a stream. Therefore, * we cannot assume that an RTSP socket is dead just because it is readable. * - * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket + * Instead, if it is readable, run Curl_connalive() to peek at the socket * and distinguish between closed and data. */ bool Curl_rtsp_connisdead(struct connectdata *check) @@ -156,12 +157,9 @@ bool Curl_rtsp_connisdead(struct connectdata *check) /* socket is in an error state */ ret_val = TRUE; } - else if((sval & CURL_CSELECT_IN) && check->data) { - /* readable with no error. could be closed or could be alive but we can - only check if we have a proper Curl_easy for the connection */ - curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check); - if(connectinfo != CURL_SOCKET_BAD) - ret_val = FALSE; + else if(sval & CURL_CSELECT_IN) { + /* readable with no error. could still be closed */ + ret_val = !Curl_connalive(check); } return ret_val; @@ -218,7 +216,7 @@ static CURLcode rtsp_done(struct connectdata *conn, CSeq_sent, CSeq_recv); return CURLE_RTSP_CSEQ_ERROR; } - else if(data->set.rtspreq == RTSPREQ_RECEIVE && + if(data->set.rtspreq == RTSPREQ_RECEIVE && (conn->proto.rtspc.rtp_channel == -1)) { infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); /* TODO CPC: Server -> Client logic here */ @@ -488,7 +486,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM * with basic and digest, it will be freed anyway by the next request */ - Curl_safefree (conn->allocptr.userpwd); + Curl_safefree(conn->allocptr.userpwd); conn->allocptr.userpwd = NULL; if(result) @@ -614,9 +612,9 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, if(rtspc->rtp_buf) { /* There was some leftover data the last time. Merge buffers */ - char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread); + char *newptr = Curl_saferealloc(rtspc->rtp_buf, + rtspc->rtp_bufsize + *nread); if(!newptr) { - Curl_safefree(rtspc->rtp_buf); rtspc->rtp_buf = NULL; rtspc->rtp_bufsize = 0; return CURLE_OUT_OF_MEMORY; @@ -650,31 +648,29 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, *readmore = TRUE; break; } - else { - /* We have the full RTP interleaved packet - * 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); - if(result) { - failf(data, "Got an error writing an RTP packet"); - *readmore = FALSE; - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; - return result; - } + /* We have the full RTP interleaved packet + * 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); + if(result) { + failf(data, "Got an error writing an RTP packet"); + *readmore = FALSE; + Curl_safefree(rtspc->rtp_buf); + rtspc->rtp_buf = NULL; + rtspc->rtp_bufsize = 0; + return result; + } - /* Move forward in the buffer */ - rtp_dataleft -= rtp_length + 4; - rtp += rtp_length + 4; + /* Move forward in the buffer */ + rtp_dataleft -= rtp_length + 4; + rtp += rtp_length + 4; - if(data->set.rtspreq == RTSPREQ_RECEIVE) { - /* If we are in a passive receive, give control back - * to the app as often as we can. - */ - k->keepon &= ~KEEP_RECV; - } + if(data->set.rtspreq == RTSPREQ_RECEIVE) { + /* If we are in a passive receive, give control back + * to the app as often as we can. + */ + k->keepon &= ~KEEP_RECV; } } else { @@ -705,20 +701,18 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, *nread = 0; return CURLE_OK; } - else { - /* Fix up k->str to point just after the last RTP packet */ - k->str += *nread - rtp_dataleft; + /* Fix up k->str to point just after the last RTP packet */ + k->str += *nread - rtp_dataleft; - /* either all of the data has been read or... - * rtp now points at the next byte to parse - */ - if(rtp_dataleft > 0) - DEBUGASSERT(k->str[0] == rtp[0]); + /* either all of the data has been read or... + * rtp now points at the next byte to parse + */ + if(rtp_dataleft > 0) + DEBUGASSERT(k->str[0] == rtp[0]); - DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */ + DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */ - *nread = rtp_dataleft; - } + *nread = rtp_dataleft; /* If we get here, we have finished with the leftover/merge buffer */ Curl_safefree(rtspc->rtp_buf); @@ -736,7 +730,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) curl_write_callback writeit; if(len == 0) { - failf (data, "Cannot write a 0 size RTP packet."); + failf(data, "Cannot write a 0 size RTP packet."); return CURLE_WRITE_ERROR; } @@ -744,12 +738,12 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) wrote = writeit(ptr, 1, len, data->set.rtp_out); if(CURL_WRITEFUNC_PAUSE == wrote) { - failf (data, "Cannot pause RTP"); + failf(data, "Cannot pause RTP"); return CURLE_WRITE_ERROR; } if(wrote != len) { - failf (data, "Failed writing RTP data"); + failf(data, "Failed writing RTP data"); return CURLE_WRITE_ERROR; } @@ -799,7 +793,7 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn, /* 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 seperator or end of + * 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. */ diff --git a/Utilities/cmcurl/lib/security.c b/Utilities/cmcurl/lib/security.c index ff2606669..f4a876341 100644 --- a/Utilities/cmcurl/lib/security.c +++ b/Utilities/cmcurl/lib/security.c @@ -62,7 +62,7 @@ #include "sendf.h" #include "strcase.h" #include "warnless.h" - +#include "strdup.h" /* The last #include file should be: */ #include "memdebug.h" @@ -88,7 +88,8 @@ name_to_level(const char *name) /* Convert a protocol |level| to its char representation. We take an int to catch programming mistakes. */ -static char level_to_char(int level) { +static char level_to_char(int level) +{ switch(level) { case PROT_CLEAR: return 'C'; @@ -202,7 +203,7 @@ static CURLcode read_data(struct connectdata *conn, if(len) { /* only realloc if there was a length */ len = ntohl(len); - tmp = realloc(buf->data, len); + tmp = Curl_saferealloc(buf->data, len); } if(tmp == NULL) return CURLE_OUT_OF_MEMORY; @@ -222,7 +223,7 @@ 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); + memcpy(data, (char *)buf->data + buf->index, len); buf->index += len; return len; } @@ -291,7 +292,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd, prot_level = conn->command_prot; } bytes = conn->mech->encode(conn->app_data, from, length, prot_level, - (void**)&buffer); + (void **)&buffer); if(!buffer || bytes <= 0) return; /* error */ @@ -366,6 +367,10 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, 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); @@ -411,7 +416,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, static int sec_set_protection_level(struct connectdata *conn) { int code; - char* pbsz; + char *pbsz; static unsigned int buffer_size = 1 << 20; /* 1048576 */ enum protection_level level = conn->request_data_prot; diff --git a/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c index d5caa70dd..443007227 100644 --- a/Utilities/cmcurl/lib/select.c +++ b/Utilities/cmcurl/lib/select.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -129,7 +129,7 @@ int Curl_wait_ms(int timeout_ms) * and a file descriptor is too large for FD_SETSIZE. * * A negative timeout value makes this function wait indefinitely, - * unles no valid file descriptor is given, when this happens the + * unless no valid file descriptor is given, when this happens the * negative timeout is ignored and the function times out immediately. * * Return values: @@ -145,7 +145,7 @@ int Curl_wait_ms(int timeout_ms) int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ curl_socket_t readfd1, curl_socket_t writefd, /* socket to write to */ - long timeout_ms) /* milliseconds to wait */ + time_t timeout_ms) /* milliseconds to wait */ { #ifdef HAVE_POLL_FINE struct pollfd pfd[3]; @@ -164,7 +164,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ int r; int ret; -#if SIZEOF_LONG != SIZEOF_INT +#if SIZEOF_TIME_T != SIZEOF_INT /* wrap-around precaution */ if(timeout_ms >= INT_MAX) timeout_ms = INT_MAX; @@ -380,7 +380,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ * select() is used instead. An error is returned if select() is * being used and a file descriptor is too large for FD_SETSIZE. * A negative timeout value makes this function wait indefinitely, - * unles no valid file descriptor is given, when this happens the + * unless no valid file descriptor is given, when this happens the * negative timeout is ignored and the function times out immediately. * * Return values: diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h index 1d26f4999..4ed5dd2f8 100644 --- a/Utilities/cmcurl/lib/select.h +++ b/Utilities/cmcurl/lib/select.h @@ -24,10 +24,10 @@ #include "curl_setup.h" -#ifdef HAVE_SYS_POLL_H -#include -#elif defined(HAVE_POLL_H) +#ifdef HAVE_POLL_H #include +#elif defined(HAVE_SYS_POLL_H) +#include #endif /* @@ -73,7 +73,7 @@ struct pollfd int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, curl_socket_t writefd, - long timeout_ms); + time_t timeout_ms); #define SOCKET_READABLE(x,z) \ Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z) diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c index 210179734..595c36177 100644 --- a/Utilities/cmcurl/lib/sendf.c +++ b/Utilities/cmcurl/lib/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -33,6 +33,7 @@ #include "non-ascii.h" #include "strerror.h" #include "select.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -122,6 +123,13 @@ static size_t convert_lineends(struct Curl_easy *data, #endif /* CURL_DO_LINEEND_CONV */ #ifdef USE_RECV_BEFORE_SEND_WORKAROUND +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + struct postponed_data * const psnd = &(conn->postponed[sockindex]); + return psnd->buffer && psnd->allocated_size && + psnd->recv_size > psnd->recv_processed; +} + static void pre_receive_plain(struct connectdata *conn, int num) { const curl_socket_t sockfd = conn->sock[num]; @@ -141,7 +149,7 @@ 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 * BUFSIZE; + psnd->allocated_size = 2 * conn->data->set.buffer_size; psnd->buffer = malloc(psnd->allocated_size); psnd->recv_size = 0; psnd->recv_processed = 0; @@ -201,6 +209,12 @@ static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf, } #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ /* Use "do-nothing" macros instead of functions when workaround not used */ +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + (void)conn; + (void)sockindex; + return false; +} #define pre_receive_plain(c,n) do {} WHILE_FALSE #define get_pre_recved(c,n,b,l) 0 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ @@ -229,27 +243,26 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) { va_list ap; size_t len; + char error[CURL_ERROR_SIZE + 2]; va_start(ap, fmt); - vsnprintf(data->state.buffer, BUFSIZE, fmt, ap); + vsnprintf(error, CURL_ERROR_SIZE, fmt, ap); + len = strlen(error); if(data->set.errorbuffer && !data->state.errorbuf) { - snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer); + strcpy(data->set.errorbuffer, error); data->state.errorbuf = TRUE; /* wrote error string */ } if(data->set.verbose) { - len = strlen(data->state.buffer); - if(len < BUFSIZE - 1) { - data->state.buffer[len] = '\n'; - data->state.buffer[++len] = '\0'; - } - Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL); + error[len] = '\n'; + error[++len] = '\0'; + Curl_debug(data, CURLINFO_TEXT, error, len, NULL); } va_end(ap); } -/* Curl_sendf() sends formated data to the server */ +/* Curl_sendf() sends formatted data to the server */ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, const char *fmt, ...) { @@ -461,21 +474,58 @@ static CURLcode pausewrite(struct Curl_easy *data, we want to send we need to dup it to save a copy for when the sending is again enabled */ struct SingleRequest *k = &data->req; - char *dupl = malloc(len); - if(!dupl) - return CURLE_OUT_OF_MEMORY; + struct UrlState *s = &data->state; + char *dupl; + unsigned int i; + bool newtype = TRUE; + + if(s->tempcount) { + for(i=0; i< s->tempcount; i++) { + if(s->tempwrite[i].type == type) { + /* data for this type exists */ + newtype = FALSE; + break; + } + } + DEBUGASSERT(i < 3); + } + else + i = 0; + + if(!newtype) { + /* append new data to old data */ + + /* figure out the new size of the data to save */ + size_t newlen = len + s->tempwrite[i].len; + /* allocate the new memory area */ + char *newptr = realloc(s->tempwrite[i].buf, newlen); + if(!newptr) + return CURLE_OUT_OF_MEMORY; + /* copy the new data to the end of the new area */ + memcpy(newptr + s->tempwrite[i].len, ptr, len); + + /* update the pointer and the size */ + s->tempwrite[i].buf = newptr; + s->tempwrite[i].len = newlen; + } + else { + dupl = Curl_memdup(ptr, len); + if(!dupl) + return CURLE_OUT_OF_MEMORY; - memcpy(dupl, ptr, len); + /* store this information in the state struct for later use */ + s->tempwrite[i].buf = dupl; + s->tempwrite[i].len = len; + s->tempwrite[i].type = type; - /* store this information in the state struct for later use */ - data->state.tempwrite = dupl; - data->state.tempwritesize = len; - data->state.tempwritetype = type; + if(newtype) + s->tempcount++; + } /* mark the connection as RECV paused */ k->keepon |= KEEP_RECV_PAUSE; - DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n", + DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n", len, type)); return CURLE_OK; @@ -488,7 +538,7 @@ static CURLcode pausewrite(struct Curl_easy *data, */ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, - char * ptr, + char *ptr, size_t len) { struct Curl_easy *data = conn->data; @@ -498,31 +548,10 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, if(!len) return CURLE_OK; - /* If reading is actually paused, we're forced to append this chunk of data - to the already held data, but only if it is the same type as otherwise it - can't work and it'll return error instead. */ - if(data->req.keepon & KEEP_RECV_PAUSE) { - size_t newlen; - char *newptr; - if(type != data->state.tempwritetype) - /* major internal confusion */ - return CURLE_RECV_ERROR; - - DEBUGASSERT(data->state.tempwrite); - - /* figure out the new size of the data to save */ - newlen = len + data->state.tempwritesize; - /* allocate the new memory area */ - newptr = realloc(data->state.tempwrite, newlen); - if(!newptr) - return CURLE_OUT_OF_MEMORY; - /* copy the new data to the end of the new area */ - memcpy(newptr + data->state.tempwritesize, ptr, len); - /* update the pointer and the size */ - data->state.tempwrite = newptr; - data->state.tempwritesize = newlen; - return CURLE_OK; - } + /* If reading is paused, append this data to the already held data for this + type. */ + if(data->req.keepon & KEEP_RECV_PAUSE) + return pausewrite(data, type, ptr, len); /* Determine the callback(s) to use. */ if(type & CLIENTWRITE_BODY) @@ -552,10 +581,9 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, failf(data, "Write callback asked for PAUSE when not supported!"); return CURLE_WRITE_ERROR; } - else - return pausewrite(data, type, ptr, len); + return pausewrite(data, type, ptr, len); } - else if(wrote != chunklen) { + if(wrote != chunklen) { failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen); return CURLE_WRITE_ERROR; } @@ -571,7 +599,7 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); if(wrote != chunklen) { - failf (data, "Failed writing header"); + failf(data, "Failed writing header"); return CURLE_WRITE_ERROR; } } @@ -603,6 +631,8 @@ CURLcode Curl_client_write(struct connectdata *conn, if(0 == len) len = strlen(ptr); + DEBUGASSERT(type <= 3); + /* FTP data may need conversion. */ if((type & CLIENTWRITE_BODY) && (conn->handler->protocol & PROTO_FAMILY_FTP) && @@ -639,8 +669,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd, #endif if(return_error) return CURLE_AGAIN; - else - return CURLE_RECV_ERROR; + return CURLE_RECV_ERROR; } /* we only return number of bytes read when we return OK */ @@ -664,9 +693,10 @@ 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; /* if HTTP/1 pipelining is both wanted and possible */ - bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) && + bool pipelining = Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) && (conn->bundle->multiuse == BUNDLE_PIPELINING); /* Set 'num' to 0 or 1, depending on which socket that has been sent here. @@ -692,13 +722,11 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ } /* If we come here, it means that there is no data to read from the buffer, * so we read from the socket */ - bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char)); + bytesfromsocket = CURLMIN(sizerequested, MASTERBUF_SIZE); buffertofill = conn->master_buffer; } else { - bytesfromsocket = CURLMIN((long)sizerequested, - conn->data->set.buffer_size ? - conn->data->set.buffer_size : BUFSIZE); + bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size); buffertofill = buf; } @@ -723,21 +751,19 @@ static int showit(struct Curl_easy *data, curl_infotype type, { static const char s_infotype[CURLINFO_END][3] = { "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; + int rc = 0; #ifdef CURL_DOES_CONVERSIONS - char buf[BUFSIZE+1]; + char *buf = NULL; size_t conv_size = 0; switch(type) { case CURLINFO_HEADER_OUT: - /* assume output headers are ASCII */ - /* copy the data into my buffer so the original is unchanged */ - if(size > BUFSIZE) { - size = BUFSIZE; /* truncate if necessary */ - buf[BUFSIZE] = '\0'; - } + buf = Curl_memdup(ptr, size); + if(!buf) + return 1; conv_size = size; - memcpy(buf, ptr, 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. @@ -765,26 +791,29 @@ static int showit(struct Curl_easy *data, curl_infotype type, #endif /* CURL_DOES_CONVERSIONS */ if(data->set.fdebug) - return (*data->set.fdebug)(data, type, ptr, size, - data->set.debugdata); - - 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); + rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata); + 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; + } } - return 0; +#ifdef CURL_DOES_CONVERSIONS + free(buf); +#endif + return rc; } int Curl_debug(struct Curl_easy *data, curl_infotype type, @@ -796,7 +825,7 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type, char buffer[160]; const char *t=NULL; const char *w="Data"; - switch (type) { + switch(type) { case CURLINFO_HEADER_IN: w = "Header"; /* FALLTHROUGH */ diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h index a951a0b4f..fbe4f99c8 100644 --- a/Utilities/cmcurl/lib/sendf.h +++ b/Utilities/cmcurl/lib/sendf.h @@ -56,6 +56,8 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr, CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, size_t len) WARN_UNUSED_RESULT; +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex); + /* internal read-function, does plain socket only */ CURLcode Curl_read_plain(curl_socket_t sockfd, char *buf, diff --git a/Utilities/cmcurl/lib/setup-os400.h b/Utilities/cmcurl/lib/setup-os400.h index e32b72f21..a3c2a7bdc 100644 --- a/Utilities/cmcurl/lib/setup-os400.h +++ b/Utilities/cmcurl/lib/setup-os400.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,18 +41,18 @@ typedef unsigned long u_int32_t; #include #include -extern int Curl_getaddrinfo_a(const char * nodename, - const char * servname, - const struct addrinfo * hints, - struct addrinfo * * res); +extern int Curl_getaddrinfo_a(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); #define getaddrinfo Curl_getaddrinfo_a -extern int Curl_getnameinfo_a(const struct sockaddr * sa, - curl_socklen_t salen, - char * nodename, curl_socklen_t nodenamelen, - char * servname, curl_socklen_t servnamelen, - int flags); +extern int Curl_getnameinfo_a(const struct sockaddr *sa, + curl_socklen_t salen, + char *nodename, curl_socklen_t nodenamelen, + char *servname, curl_socklen_t servnamelen, + int flags); #define getnameinfo Curl_getnameinfo_a @@ -79,7 +79,7 @@ extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle); extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID, - const char * buffer, + const char *buffer, int bufSize); #define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a @@ -95,29 +95,29 @@ extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle, extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle, GSK_CALLBACK_ID callBackID, - void * callBackAreaPtr); + void *callBackAreaPtr); #define gsk_attribute_set_callback Curl_gsk_attribute_set_callback extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID, - const char * * buffer, - int * bufSize); + const char **buffer, + int *bufSize); #define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID, - GSK_ENUM_VALUE * enumValue); + GSK_ENUM_VALUE *enumValue); #define gsk_attribute_get_enum Curl_gsk_attribute_get_enum extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle, GSK_NUM_ID numID, - int * numValue); + int *numValue); #define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle, GSK_CERT_ID certID, - const gsk_cert_data_elem * * certDataElem, - int * certDataElementCount); + const gsk_cert_data_elem **certDataElem, + int *certDataElementCount); #define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, @@ -125,13 +125,13 @@ extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, #define gsk_secure_soc_misc Curl_gsk_secure_soc_misc extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle, - char * readBuffer, - int readBufSize, int * amtRead); + char *readBuffer, + int readBufSize, int *amtRead); #define gsk_secure_soc_read Curl_gsk_secure_soc_read extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle, - char * writeBuffer, - int writeBufSize, int * amtWritten); + char *writeBuffer, + int writeBufSize, int *amtWritten); #define gsk_secure_soc_write Curl_gsk_secure_soc_write extern const char * Curl_gsk_strerror_a(int gsk_return_value); @@ -202,10 +202,10 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen); extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen); -extern int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags, - struct sockaddr * dstaddr, int addrlen); -extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, - struct sockaddr * fromaddr, int * addrlen); +extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, + struct sockaddr * dstaddr, int addrlen); +extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, + struct sockaddr *fromaddr, int *addrlen); #define connect Curl_os400_connect #define bind Curl_os400_bind diff --git a/Utilities/cmcurl/lib/setup-vms.h b/Utilities/cmcurl/lib/setup-vms.h index 4b78e0bf0..6c454aee6 100644 --- a/Utilities/cmcurl/lib/setup-vms.h +++ b/Utilities/cmcurl/lib/setup-vms.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,7 +41,7 @@ # endif #endif #include - char * decc$getenv(const char * __name); +char *decc$getenv(const char *__name); #include #include @@ -79,23 +79,24 @@ # if __INITIAL_POINTER_SIZE == 32 /* Translate the path, but only if the path is a VMS file specification */ /* The translation is usually only needed for older versions of VMS */ -static char * vms_translate_path(const char * path) { -char * unix_path; -char * test_str; - - /* See if the result is in VMS format, if not, we are done */ - /* Assume that this is a PATH, not just some data */ - test_str = strpbrk(path, ":[<^"); - if(test_str == NULL) { - return (char *)path; - } - - unix_path = decc$translate_vms(path); - - if((int)unix_path <= 0) { - /* We can not translate it, so return the original string */ - return (char *)path; - } +static char *vms_translate_path(const char *path) +{ + char *unix_path; + char *test_str; + + /* See if the result is in VMS format, if not, we are done */ + /* Assume that this is a PATH, not just some data */ + test_str = strpbrk(path, ":[<^"); + if(test_str == NULL) { + return (char *)path; + } + + unix_path = decc$translate_vms(path); + + if((int)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return (char *)path; + } } # else /* VMS translate path is actually not needed on the current 64 bit */ @@ -111,74 +112,74 @@ char * test_str; # endif #endif -static char * vms_getenv(const char * envvar) { +static char *vms_getenv(const char *envvar) +{ + char *result; + char *vms_path; -char * result; -char * vms_path; - - /* first use the DECC getenv() function */ - result = decc$getenv(envvar); - if(result == NULL) { - return result; - } + /* first use the DECC getenv() function */ + result = decc$getenv(envvar); + if(result == NULL) { + return result; + } - vms_path = result; - result = vms_translate_path(vms_path); + vms_path = result; + result = vms_translate_path(vms_path); - /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ - /* may do a malloc(2048) for each call to getenv(), so you will need */ - /* to add a free(vms_path) */ - /* Do not do a free() for DEC C RTL builds, which should be used for */ - /* VMS 5.5-2 and later, even if using GCC */ + /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ + /* may do a malloc(2048) for each call to getenv(), so you will need */ + /* to add a free(vms_path) */ + /* Do not do a free() for DEC C RTL builds, which should be used for */ + /* VMS 5.5-2 and later, even if using GCC */ - return result; + return result; } static struct passwd vms_passwd_cache; -static struct passwd * vms_getpwuid(uid_t uid) { - -struct passwd * my_passwd; +static struct passwd * vms_getpwuid(uid_t uid) +{ + struct passwd * my_passwd; /* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */ #ifdef __DECC # if __INITIAL_POINTER_SIZE -__char_ptr32 unix_path; + __char_ptr32 unix_path; # else -char * unix_path; + char *unix_path; # endif #else -char * unix_path; + char *unix_path; #endif - my_passwd = decc_getpwuid(uid); - if(my_passwd == NULL) { - return my_passwd; - } - - unix_path = vms_translate_path(my_passwd->pw_dir); - - if((long)unix_path <= 0) { - /* We can not translate it, so return the original string */ - return my_passwd; - } - - /* If no changes needed just return it */ - if(unix_path == my_passwd->pw_dir) { - return my_passwd; - } - - /* Need to copy the structure returned */ - /* Since curl is only using pw_dir, no need to fix up * - /* the pw_shell when running under Bash */ - vms_passwd_cache.pw_name = my_passwd->pw_name; - vms_passwd_cache.pw_uid = my_passwd->pw_uid; - vms_passwd_cache.pw_gid = my_passwd->pw_uid; - vms_passwd_cache.pw_dir = unix_path; - vms_passwd_cache.pw_shell = my_passwd->pw_shell; - - return &vms_passwd_cache; + my_passwd = decc_getpwuid(uid); + if(my_passwd == NULL) { + return my_passwd; + } + + unix_path = vms_translate_path(my_passwd->pw_dir); + + if((long)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return my_passwd; + } + + /* If no changes needed just return it */ + if(unix_path == my_passwd->pw_dir) { + return my_passwd; + } + + /* Need to copy the structure returned */ + /* Since curl is only using pw_dir, no need to fix up */ + /* the pw_shell when running under Bash */ + vms_passwd_cache.pw_name = my_passwd->pw_name; + vms_passwd_cache.pw_uid = my_passwd->pw_uid; + vms_passwd_cache.pw_gid = my_passwd->pw_uid; + vms_passwd_cache.pw_dir = unix_path; + vms_passwd_cache.pw_shell = my_passwd->pw_shell; + + return &vms_passwd_cache; } #ifdef __DECC diff --git a/Utilities/cmcurl/lib/share.h b/Utilities/cmcurl/lib/share.h index e689ff2d2..c039a16cb 100644 --- a/Utilities/cmcurl/lib/share.h +++ b/Utilities/cmcurl/lib/share.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -54,8 +54,8 @@ struct Curl_share { long sessionage; }; -CURLSHcode Curl_share_lock (struct Curl_easy *, curl_lock_data, - curl_lock_access); -CURLSHcode Curl_share_unlock (struct Curl_easy *, curl_lock_data); +CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, + curl_lock_access); +CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data); #endif /* HEADER_CURL_SHARE_H */ diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c index 7cb0c9611..5b1ffa9b7 100644 --- a/Utilities/cmcurl/lib/smb.c +++ b/Utilities/cmcurl/lib/smb.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014, Bill Nagel , Exacq Technologies - * Copyright (C) 2015, Daniel Stenberg, , et al. + * Copyright (C) 2016-2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,8 +23,8 @@ #include "curl_setup.h" -#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ - (CURL_SIZEOF_CURL_OFF_T > 4) +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) @@ -32,8 +32,12 @@ #ifdef HAVE_PROCESS_H #include +#ifdef CURL_WINDOWS_APP +#define getpid GetCurrentProcessId +#else #define getpid _getpid #endif +#endif #include "smb.h" #include "urldata.h" @@ -117,18 +121,18 @@ const struct Curl_handler Curl_handler_smbs = { #define SERVICENAME "?????" /* Append a string to an SMB message */ -#define MSGCAT(str) \ - strcpy(p, (str)); \ +#define MSGCAT(str) \ + strcpy(p, (str)); \ p += strlen(str); /* Append a null-terminated string to an SMB message */ -#define MSGCATNULL(str) \ - strcpy(p, (str)); \ +#define MSGCATNULL(str) \ + strcpy(p, (str)); \ p += strlen(str) + 1; /* SMB is mostly little endian */ #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ - defined(__OS400__) + defined(__OS400__) static unsigned short smb_swap16(unsigned short x) { return (unsigned short) ((x << 8) | ((x >> 8) & 0xff)); @@ -137,20 +141,20 @@ static unsigned short smb_swap16(unsigned short x) static unsigned int smb_swap32(unsigned int x) { return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | - ((x >> 24) & 0xff); + ((x >> 24) & 0xff); } #ifdef HAVE_LONGLONG static unsigned long long smb_swap64(unsigned long long x) { return ((unsigned long long) smb_swap32((unsigned int) x) << 32) | - smb_swap32((unsigned int) (x >> 32)); + smb_swap32((unsigned int) (x >> 32)); } #else static unsigned __int64 smb_swap64(unsigned __int64 x) { return ((unsigned __int64) smb_swap32((unsigned int) x) << 32) | - smb_swap32((unsigned int) (x >> 32)); + smb_swap32((unsigned int) (x >> 32)); } #endif #else @@ -197,7 +201,7 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate) if(smb->state != newstate) infof(conn->data, "SMB conn %p state change from %s to %s\n", - (void *)smb, names[smb->state], names[newstate]); + (void *)smb, names[smb->state], names[newstate]); #endif smb->state = newstate; @@ -223,7 +227,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", - (void *)req, names[req->state], names[newstate]); + (void *)req, names[req->state], names[newstate]); #endif req->state = newstate; @@ -308,8 +312,9 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg) if(smbc->got < sizeof(unsigned int)) return CURLE_OK; - nbt_size = Curl_read16_be((unsigned char *)(buf + sizeof(unsigned short))) + - sizeof(unsigned int); + nbt_size = Curl_read16_be((const unsigned char *) + (buf + sizeof(unsigned short))) + + sizeof(unsigned int); if(smbc->got < nbt_size) return CURLE_OK; @@ -320,7 +325,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg) if(nbt_size >= msg_size + sizeof(unsigned short)) { /* Add the byte count */ msg_size += sizeof(unsigned short) + - Curl_read16_le((unsigned char *)&buf[msg_size]); + Curl_read16_le((const unsigned char *)&buf[msg_size]); if(nbt_size < msg_size) return CURLE_READ_ERROR; } @@ -441,7 +446,7 @@ static CURLcode smb_send_setup(struct connectdata *conn) Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash); Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm); -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash); Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt); #else @@ -602,8 +607,8 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg) /* Check if there is data in the transfer buffer */ if(!smbc->send_size && smbc->upload_size) { - int nread = smbc->upload_size > BUFSIZE ? BUFSIZE : - (int) smbc->upload_size; + int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE : + (int) smbc->upload_size; conn->data->req.upload_fromhere = conn->data->state.uploadbuffer; result = Curl_fillreadbuffer(conn, nread, &nread); if(result && result != CURLE_AGAIN) @@ -781,9 +786,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) next_state = SMB_CLOSE; break; } - len = Curl_read16_le(((unsigned char *) msg) + + len = Curl_read16_le(((const unsigned char *) msg) + sizeof(struct smb_header) + 11); - off = Curl_read16_le(((unsigned char *) msg) + + off = Curl_read16_le(((const unsigned char *) msg) + sizeof(struct smb_header) + 13); if(len > 0) { if(off + sizeof(unsigned int) + len > smbc->got) { @@ -812,7 +817,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) next_state = SMB_CLOSE; break; } - len = Curl_read16_le(((unsigned char *) msg) + + len = Curl_read16_le(((const unsigned char *) msg) + sizeof(struct smb_header) + 5); conn->data->req.bytecount += len; conn->data->req.offset += len; diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c index a4fc2c26e..fe064cb2f 100644 --- a/Utilities/cmcurl/lib/smtp.c +++ b/Utilities/cmcurl/lib/smtp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -103,7 +103,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn); static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, const char *initresp); static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); -static void smtp_get_message(char *buffer, char** outptr); +static void smtp_get_message(char *buffer, char **outptr); /* * SMTP protocol handler. @@ -126,7 +126,8 @@ const struct Curl_handler Curl_handler_smtp = { ZERO_NULL, /* readwrite */ PORT_SMTP, /* defport */ CURLPROTO_SMTP, /* protocol */ - PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ + PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ + PROTOPT_URLOPTIONS }; #ifdef USE_SSL @@ -152,7 +153,7 @@ const struct Curl_handler Curl_handler_smtps = { PORT_SMTPS, /* defport */ CURLPROTO_SMTPS, /* protocol */ PROTOPT_CLOSEACTION | PROTOPT_SSL - | PROTOPT_NOURLQUERY /* flags */ + | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ }; #endif @@ -278,10 +279,10 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, * * Gets the authentication message from the response buffer. */ -static void smtp_get_message(char *buffer, char** outptr) +static void smtp_get_message(char *buffer, char **outptr) { size_t len = 0; - char* message = NULL; + char *message = NULL; /* Find the start of the message */ for(message = buffer + 4; *message == ' ' || *message == '\t'; message++) @@ -692,7 +693,7 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn, if(smtpcode != 220) { if(data->set.use_ssl != CURLUSESSL_TRY) { - failf(data, "STARTTLS denied. %c", smtpcode); + failf(data, "STARTTLS denied, code %d", smtpcode); result = CURLE_USE_SSL_FAILED; } else @@ -1590,7 +1591,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) if(!scratch || data->set.crlf) { oldscratch = scratch; - scratch = newscratch = malloc(2 * BUFSIZE); + scratch = newscratch = malloc(2 * data->set.buffer_size); if(!newscratch) { failf(data, "Failed to alloc scratch buffer!"); diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c index 742d41156..97a44b296 100644 --- a/Utilities/cmcurl/lib/socks.c +++ b/Utilities/cmcurl/lib/socks.c @@ -57,7 +57,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ ssize_t nread; ssize_t allread = 0; int result; - long timeleft; + time_t timeleft; *n = 0; for(;;) { timeleft = Curl_timeleft(conn->data, NULL, TRUE); @@ -73,7 +73,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ result = Curl_read_plain(sockfd, buf, buffersize, &nread); if(CURLE_AGAIN == result) continue; - else if(result) + if(result) break; if(buffersize == nread) { @@ -109,9 +109,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, - bool protocol4a) + struct connectdata *conn) { + const bool protocol4a = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE; #define SOCKS4REQLEN 262 unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user id */ @@ -126,6 +127,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name, return CURLE_OPERATION_TIMEDOUT; } + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", + protocol4a ? "a" : "", hostname, remote_port); + (void)curlx_nonblock(sock, FALSE); infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); @@ -174,11 +179,11 @@ CURLcode Curl_SOCKS4(const char *proxy_name, if(hp->ai_family == AF_INET) { struct sockaddr_in *saddr_in; - saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr; - socksreq[4] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[0]; - socksreq[5] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[1]; - socksreq[6] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[2]; - socksreq[7] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[3]; + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; + socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0]; + socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1]; + socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2]; + socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3]; infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf); } @@ -219,7 +224,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name, ssize_t written; ssize_t hostnamelen = 0; int packetsize = 9 + - (int)strlen((char*)socksreq + 8); /* size including NUL */ + (int)strlen((char *)socksreq + 8); /* size including NUL */ /* If SOCKS4a, set special invalid IP address 0.0.0.x */ if(protocol4a) { @@ -230,7 +235,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name, /* If still enough room in buffer, also append hostname */ hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ if(packetsize + hostnamelen <= SOCKS4REQLEN) - strcpy((char*)socksreq + packetsize, hostname); + strcpy((char *)socksreq + packetsize, hostname); else hostnamelen = 0; /* Flag: hostname did not fit in buffer */ } @@ -376,11 +381,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name, CURLcode code; curl_socket_t sock = conn->sock[sockindex]; struct Curl_easy *data = conn->data; - long timeout; - bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE; + time_t timeout; + bool socks5_resolve_local = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE; const size_t hostname_len = strlen(hostname); ssize_t len = 0; + if(conn->bits.httpproxy) + infof(conn->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 " @@ -406,7 +416,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name, failf(conn->data, "SOCKS5: no connection here"); return CURLE_COULDNT_CONNECT; } - else if(0 == result) { + if(0 == result) { failf(conn->data, "SOCKS5: connection timeout"); return CURLE_OPERATION_TIMEDOUT; } @@ -447,7 +457,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name, failf(conn->data, "SOCKS5 nothing to read"); return CURLE_COULDNT_CONNECT; } - else if(0 == result) { + if(0 == result) { failf(conn->data, "SOCKS5 read timeout"); return CURLE_OPERATION_TIMEDOUT; } @@ -543,7 +553,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name, "SOCKS5 GSSAPI per-message authentication is not supported."); return CURLE_COULDNT_CONNECT; } - else if(socksreq[1] == 255) { + if(socksreq[1] == 255) { #endif if(!proxy_name || !*proxy_name) { failf(data, @@ -605,9 +615,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name, struct sockaddr_in *saddr_in; socksreq[len++] = 1; /* ATYP: IPv4 = 1 */ - saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr; + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; for(i = 0; i < 4; i++) { - socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i]; + socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; } infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf); @@ -617,9 +627,10 @@ CURLcode Curl_SOCKS5(const char *proxy_name, struct sockaddr_in6 *saddr_in6; socksreq[len++] = 4; /* ATYP: IPv6 = 4 */ - saddr_in6 = (struct sockaddr_in6*)(void*)hp->ai_addr; + saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr; for(i = 0; i < 16; i++) { - socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i]; + socksreq[len++] = + ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; } infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf); @@ -761,9 +772,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name, } return CURLE_COULDNT_CONNECT; } - else { - infof(data, "SOCKS5 request granted.\n"); - } + infof(data, "SOCKS5 request granted.\n"); (void)curlx_nonblock(sock, TRUE); return CURLE_OK; /* Proxy was successful! */ diff --git a/Utilities/cmcurl/lib/socks.h b/Utilities/cmcurl/lib/socks.h index a44ada6be..348707e74 100644 --- a/Utilities/cmcurl/lib/socks.h +++ b/Utilities/cmcurl/lib/socks.h @@ -25,7 +25,7 @@ #include "curl_setup.h" #ifdef CURL_DISABLE_PROXY -#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN #define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN #else /* @@ -49,8 +49,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, - bool protocol4a); + struct connectdata *conn); /* * This function logs in to a SOCKS5 proxy and sends the specifics to the diff --git a/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c index 369245a61..54d063504 100644 --- a/Utilities/cmcurl/lib/socks_gssapi.c +++ b/Utilities/cmcurl/lib/socks_gssapi.c @@ -46,7 +46,7 @@ static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; static int check_gss_err(struct Curl_easy *data, OM_uint32 major_status, OM_uint32 minor_status, - const char* function) + const char *function) { if(GSS_ERROR(major_status)) { OM_uint32 maj_stat, min_stat; @@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data, &msg_ctx, &status_string); if(maj_stat == GSS_S_COMPLETE) { if(sizeof(buf) > len + status_string.length + 1) { - strcpy(buf+len, (char*) status_string.value); + strcpy(buf+len, (char *) status_string.value); len += status_string.length; } gss_release_buffer(&min_stat, &status_string); @@ -86,7 +86,7 @@ static int check_gss_err(struct Curl_easy *data, &msg_ctx, &status_string); if(maj_stat == GSS_S_COMPLETE) { if(sizeof(buf) > len + status_string.length) - strcpy(buf+len, (char*) status_string.value); + strcpy(buf+len, (char *) status_string.value); gss_release_buffer(&min_stat, &status_string); break; } @@ -123,6 +123,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, unsigned char socksreq[4]; /* room for GSS-API exchange header only */ const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + const size_t serviceptr_length = strlen(serviceptr); /* GSS-API request looks like * +----+------+-----+----------------+ @@ -134,22 +135,23 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, /* prepare service name */ if(strchr(serviceptr, '/')) { - service.value = malloc(strlen(serviceptr)); + service.length = serviceptr_length; + service.value = malloc(service.length); if(!service.value) return CURLE_OUT_OF_MEMORY; - service.length = strlen(serviceptr); memcpy(service.value, serviceptr, service.length); gss_major_status = gss_import_name(&gss_minor_status, &service, (gss_OID) GSS_C_NULL_OID, &server); } else { - service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2); + service.value = malloc(serviceptr_length + + strlen(conn->socks_proxy.host.name)+2); if(!service.value) return CURLE_OUT_OF_MEMORY; - service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1; + service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1; snprintf(service.value, service.length+1, "%s@%s", - serviceptr, conn->proxy.name); + serviceptr, conn->socks_proxy.host.name); gss_major_status = gss_import_name(&gss_minor_status, &service, GSS_C_NT_HOSTBASED_SERVICE, &server); @@ -290,9 +292,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_release_name(&gss_status, &server); /* Everything is good so far, user was authenticated! */ - gss_major_status = gss_inquire_context (&gss_minor_status, gss_context, - &gss_client_name, NULL, NULL, NULL, - NULL, NULL, NULL); + gss_major_status = gss_inquire_context(&gss_minor_status, gss_context, + &gss_client_name, NULL, NULL, NULL, + NULL, NULL, NULL); if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_inquire_context")) { 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 605349038..edc73ad2e 100644 --- a/Utilities/cmcurl/lib/socks_sspi.c +++ b/Utilities/cmcurl/lib/socks_sspi.c @@ -45,7 +45,7 @@ */ static int check_sspi_err(struct connectdata *conn, SECURITY_STATUS status, - const char* function) + const char *function) { if(status != SEC_E_OK && status != SEC_I_COMPLETE_AND_CONTINUE && @@ -86,6 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, 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"; + const size_t service_length = strlen(service); /* GSS-API request looks like * +----+------+-----+----------------+ @@ -102,11 +103,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OUT_OF_MEMORY; } else { - service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2); + service_name = malloc(service_length + + strlen(conn->socks_proxy.host.name) + 2); if(!service_name) return CURLE_OUT_OF_MEMORY; - snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2, - "%s/%s", service, conn->proxy.name); + snprintf(service_name, service_length + + strlen(conn->socks_proxy.host.name)+2, "%s/%s", + service, conn->socks_proxy.host.name); } input_desc.cBuffers = 1; diff --git a/Utilities/cmcurl/lib/speedcheck.c b/Utilities/cmcurl/lib/speedcheck.c index 13c34af96..8addedde5 100644 --- a/Utilities/cmcurl/lib/speedcheck.c +++ b/Utilities/cmcurl/lib/speedcheck.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -33,42 +33,41 @@ void Curl_speedinit(struct Curl_easy *data) memset(&data->state.keeps_speed, 0, sizeof(struct timeval)); } +/* + * @unittest: 1606 + */ CURLcode Curl_speedcheck(struct Curl_easy *data, struct timeval now) { - if((data->progress.current_speed >= 0) && - data->set.low_speed_time && - (Curl_tvlong(data->state.keeps_speed) != 0) && - (data->progress.current_speed < data->set.low_speed_limit)) { - long howlong = Curl_tvdiff(now, data->state.keeps_speed); - long nextcheck = (data->set.low_speed_time * 1000) - howlong; + 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) + /* under the limit at this very moment */ + data->state.keeps_speed = now; + else { + /* how long has it been under the limit */ + time_t howlong = Curl_tvdiff(now, data->state.keeps_speed); - /* We are now below the "low speed limit". If we are below it - for "low speed time" seconds we consider that enough reason - to abort the download. */ - if(nextcheck <= 0) { - /* we have been this slow for long enough, now die */ - failf(data, - "Operation too slow. " - "Less than %ld bytes/sec transferred the last %ld seconds", - data->set.low_speed_limit, - data->set.low_speed_time); - return CURLE_OPERATION_TIMEDOUT; - } - else { - /* wait complete low_speed_time */ - Curl_expire_latest(data, nextcheck); + if(howlong >= data->set.low_speed_time * 1000) { + /* too long */ + failf(data, + "Operation too slow. " + "Less than %ld bytes/sec transferred the last %ld seconds", + data->set.low_speed_limit, + data->set.low_speed_time); + return CURLE_OPERATION_TIMEDOUT; + } + } } + else + /* faster right now */ + data->state.keeps_speed.tv_sec = 0; } - else { - /* we keep up the required speed all right */ - data->state.keeps_speed = now; - if(data->set.low_speed_limit) - /* if there is a low speed limit enabled, we set the expire timer to - make this connection's speed get checked again no later than when - this time is up */ - Curl_expire_latest(data, data->set.low_speed_time*1000); - } + if(data->set.low_speed_limit) + /* if low speed limit is enabled, set the expire timer to make this + connection's speed get checked again in a second */ + Curl_expire(data, 1000, EXPIRE_SPEEDCHECK); + return CURLE_OK; } diff --git a/Utilities/cmcurl/lib/splay.c b/Utilities/cmcurl/lib/splay.c index 7aa2e4bac..1b301f95d 100644 --- a/Utilities/cmcurl/lib/splay.c +++ b/Utilities/cmcurl/lib/splay.c @@ -110,22 +110,17 @@ struct Curl_tree *Curl_splayinsert(struct timeval i, t = Curl_splay(i, t); if(compare(i, t->key)==0) { /* There already exists a node in the tree with the very same key. Build - a linked list of nodes. We make the new 'node' struct the new master - node and make the previous node the first one in the 'same' list. */ + a doubly-linked circular list of nodes. We add the new 'node' struct + to the end of this list. */ - node->same = t; - node->key = i; - node->smaller = t->smaller; - node->larger = t->larger; - - t->smaller = node; /* in the sub node for this same key, we use the - smaller pointer to point back to the master - node */ - - t->key = KEY_NOTUSED; /* and we set the key in the sub node to NOTUSED + node->key = KEY_NOTUSED; /* we set the key in the sub node to NOTUSED to quickly identify this node as a subnode */ + node->samen = t; + node->samep = t->samep; + t->samep->samen = node; + t->samep = node; - return node; /* new root node */ + return t; /* the root node always stays the same */ } } @@ -145,16 +140,20 @@ struct Curl_tree *Curl_splayinsert(struct timeval i, } node->key = i; - node->same = NULL; /* no identical node (yet) */ + /* no identical nodes (yet), we are the only one in the list of nodes */ + node->samen = node; + node->samep = node; return node; } /* Finds and deletes the best-fit node from the tree. Return a pointer to the - resulting tree. best-fit means the node with the given or lower key */ + resulting tree. best-fit means the smallest node if it is not larger than + the key */ struct Curl_tree *Curl_splaygetbest(struct timeval i, - struct Curl_tree *t, - struct Curl_tree **removed) + struct Curl_tree *t, + struct Curl_tree **removed) { + static struct timeval tv_zero = {0, 0}; struct Curl_tree *x; if(!t) { @@ -162,49 +161,36 @@ struct Curl_tree *Curl_splaygetbest(struct timeval i, return NULL; } - t = Curl_splay(i, t); + /* find smallest */ + t = Curl_splay(tv_zero, t); if(compare(i, t->key) < 0) { - /* too big node, try the smaller chain */ - if(t->smaller) - t=Curl_splay(t->smaller->key, t); - else { - /* fail */ - *removed = NULL; - return t; - } + /* even the smallest is too big */ + *removed = NULL; + return t; } - if(compare(i, t->key) >= 0) { /* found it */ - /* FIRST! Check if there is a list with identical keys */ - x = t->same; - if(x) { - /* there is, pick one from the list */ + /* FIRST! Check if there is a list with identical keys */ + x = t->samen; + if(x != t) { + /* there is, pick one from the list */ - /* 'x' is the new root node */ + /* 'x' is the new root node */ - x->key = t->key; - x->larger = t->larger; - x->smaller = t->smaller; - - *removed = t; - return x; /* new root */ - } + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + x->samep = t->samep; + t->samep->samen = x; - if(t->smaller == NULL) { - x = t->larger; - } - else { - x = Curl_splay(i, t->smaller); - x->larger = t->larger; - } *removed = t; - - return x; - } - else { - *removed = NULL; /* no match */ - return t; /* It wasn't there */ + return x; /* new root */ } + + /* we splayed the tree to the smallest element, there is no smaller */ + x = t->larger; + *removed = t; + + return x; } @@ -231,19 +217,17 @@ int Curl_splayremovebyaddr(struct Curl_tree *t, if(compare(KEY_NOTUSED, removenode->key) == 0) { /* Key set to NOTUSED means it is a subnode within a 'same' linked list - and thus we can unlink it easily. The 'smaller' link of a subnode - links to the parent node. */ - if(removenode->smaller == NULL) + and thus we can unlink it easily. */ + if(removenode->samen == removenode) + /* A non-subnode should never be set to KEY_NOTUSED */ return 3; - removenode->smaller->same = removenode->same; - if(removenode->same) - removenode->same->smaller = removenode->smaller; + removenode->samep->samen = removenode->samen; + removenode->samen->samep = removenode->samep; /* Ensures that double-remove gets caught. */ - removenode->smaller = NULL; + removenode->samen = removenode; - /* voila, we're done! */ *newroot = t; /* return the same root */ return 0; } @@ -262,14 +246,16 @@ int Curl_splayremovebyaddr(struct Curl_tree *t, /* Check if there is a list with identical sizes, as then we're trying to remove the root node of a list of nodes with identical keys. */ - x = t->same; - if(x) { + x = t->samen; + if(x != t) { /* 'x' is the new root node, we just make it use the root node's smaller/larger links */ x->key = t->key; x->larger = t->larger; x->smaller = t->smaller; + x->samep = t->samep; + t->samep->samen = x; } else { /* Remove the root node */ diff --git a/Utilities/cmcurl/lib/splay.h b/Utilities/cmcurl/lib/splay.h index 427bfc8eb..da81894d1 100644 --- a/Utilities/cmcurl/lib/splay.h +++ b/Utilities/cmcurl/lib/splay.h @@ -26,7 +26,8 @@ struct Curl_tree { struct Curl_tree *smaller; /* smaller node */ struct Curl_tree *larger; /* larger node */ - struct Curl_tree *same; /* points to a node with identical key */ + struct Curl_tree *samen; /* points to the next node with identical key */ + struct Curl_tree *samep; /* points to the prev node with identical key */ struct timeval key; /* this node's "sort" key */ void *payload; /* data the splay code doesn't care about */ }; diff --git a/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c index 43c82839d..00aeca978 100644 --- a/Utilities/cmcurl/lib/ssh.c +++ b/Utilities/cmcurl/lib/ssh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -71,7 +71,7 @@ #include "url.h" #include "speedcheck.h" #include "getinfo.h" - +#include "strdup.h" #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" @@ -113,6 +113,7 @@ libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \ (t), (m), LIBSSH2_SFTP_REALPATH) + /* Local functions: */ static const char *sftp_libssh2_strerror(int err); static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); @@ -239,7 +240,7 @@ kbd_callback(const char *name, int name_len, const char *instruction, static CURLcode sftp_libssh2_error_to_CURLE(int err) { - switch (err) { + switch(err) { case LIBSSH2_FX_OK: return CURLE_OK; @@ -271,7 +272,7 @@ static CURLcode sftp_libssh2_error_to_CURLE(int err) static CURLcode libssh2_session_error_to_CURLE(int err) { - switch (err) { + switch(err) { /* Ordered by order of appearance in libssh2.h */ case LIBSSH2_ERROR_NONE: return CURLE_OK; @@ -676,7 +677,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn) * against a known fingerprint, if available. */ if(pubkey_md5 && strlen(pubkey_md5) == 32) { - if(!fingerprint || strcmp(md5buffer, pubkey_md5)) { + if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) { if(fingerprint) failf(data, "Denied establishing ssh session: mismatch md5 fingerprint. " @@ -688,14 +689,11 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn) sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; return sshc->actualcode; } - else { - infof(data, "MD5 checksum match!\n"); - /* as we already matched, we skip the check for known hosts */ - return CURLE_OK; - } + infof(data, "MD5 checksum match!\n"); + /* as we already matched, we skip the check for known hosts */ + return CURLE_OK; } - else - return ssh_knownhost(conn); + return ssh_knownhost(conn); } /* @@ -738,7 +736,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc) { + if(rc) { failf(data, "Failure establishing ssh session"); state(conn, SSH_SESSION_FREE); sshc->actualcode = CURLE_FAILED_INIT; @@ -782,16 +780,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) state(conn, SSH_AUTH_DONE); break; } - else if((err = libssh2_session_last_errno(sshc->ssh_session)) == - LIBSSH2_ERROR_EAGAIN) { + err = libssh2_session_last_errno(sshc->ssh_session); + if(err == LIBSSH2_ERROR_EAGAIN) rc = LIBSSH2_ERROR_EAGAIN; - break; - } else { state(conn, SSH_SESSION_FREE); sshc->actualcode = libssh2_session_error_to_CURLE(err); - break; } + break; } infof(data, "SSH authentication methods available: %s\n", sshc->authlist); @@ -874,7 +870,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; } - sshc->passphrase = data->set.str[STRING_KEY_PASSWD]; + sshc->passphrase = data->set.ssl.key_passwd; if(!sshc->passphrase) sshc->passphrase = ""; @@ -918,6 +914,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) &err_msg, NULL, 0); infof(data, "SSH public key authentication failed: %s\n", err_msg); state(conn, SSH_AUTH_PASS_INIT); + rc = 0; /* clear rc and continue */ } break; @@ -928,6 +925,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } else { state(conn, SSH_AUTH_HOST_INIT); + rc = 0; /* clear rc and continue */ } break; @@ -940,7 +938,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc == 0) { + if(rc == 0) { sshc->authed = TRUE; infof(data, "Initialized password authentication\n"); state(conn, SSH_AUTH_DONE); @@ -989,6 +987,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc < 0) { infof(data, "Failure connecting to agent\n"); state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ } else { state(conn, SSH_AUTH_AGENT_LIST); @@ -1008,6 +1007,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc < 0) { infof(data, "Failure requesting identities to agent\n"); state(conn, SSH_AUTH_KEY_INIT); + rc = 0; /* clear rc and continue */ } else { state(conn, SSH_AUTH_AGENT); @@ -1077,7 +1077,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc == 0) { + if(rc == 0) { sshc->authed = TRUE; infof(data, "Initialized keyboard interactive authentication\n"); } @@ -1116,21 +1116,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) */ sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session); if(!sshc->sftp_session) { + char *err_msg; if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN) { rc = LIBSSH2_ERROR_EAGAIN; break; } - else { - char *err_msg; - (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); - sshc->actualcode = CURLE_FAILED_INIT; - break; - } + (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); + sshc->actualcode = CURLE_FAILED_INIT; + break; } state(conn, SSH_SFTP_REALPATH); break; @@ -1147,7 +1145,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc > 0) { + if(rc > 0) { /* It seems that this string is not always NULL terminated */ tempHome[rc] = '\0'; sshc->homedir = strdup(tempHome); @@ -1261,7 +1259,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) state(conn, SSH_SFTP_NEXT_QUOTE); break; } - else if(cmd) { + if(cmd) { /* * the arguments following the command must be separated from the * command with a space so we can check for it unconditionally @@ -1321,7 +1319,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) state(conn, SSH_SFTP_QUOTE_STAT); break; } - else if(strncasecompare(cmd, "ln ", 3) || + if(strncasecompare(cmd, "ln ", 3) || strncasecompare(cmd, "symlink ", 8)) { /* symbolic linking */ /* sshc->quote_path1 is the source */ @@ -1443,7 +1441,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */ + if(rc != 0 && !sshc->acceptfail) { /* get those attributes */ err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1514,7 +1512,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { + if(rc != 0 && !sshc->acceptfail) { err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1537,7 +1535,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { + if(rc != 0 && !sshc->acceptfail) { err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1558,7 +1556,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { + if(rc != 0 && !sshc->acceptfail) { err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err)); @@ -1582,7 +1580,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { + if(rc != 0 && !sshc->acceptfail) { err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -1601,7 +1599,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { + if(rc != 0 && !sshc->acceptfail) { err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err)); @@ -1619,7 +1617,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { + if(rc != 0 && !sshc->acceptfail) { err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", sftp_libssh2_strerror(err)); @@ -1642,7 +1640,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc != 0 && !sshc->acceptfail) { + if(rc != 0 && !sshc->acceptfail) { err = sftp_libssh2_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err)); @@ -1705,7 +1703,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc == 0) { + if(rc == 0) { data->info.filetime = (long)attrs.mtime; } @@ -1743,7 +1741,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc) { + if(rc) { data->state.resume_from = 0; } else { @@ -1778,47 +1776,47 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(LIBSSH2_ERROR_EAGAIN == rc) break; - else { - if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) - /* only when there was an SFTP protocol error can we extract - the sftp error! */ - err = sftp_libssh2_last_error(sshc->sftp_session); - else - err = -1; /* not an sftp error at all */ - if(sshc->secondCreateDirs) { - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = err>= LIBSSH2_FX_OK? - sftp_libssh2_error_to_CURLE(err):CURLE_SSH; - failf(data, "Creating the dir/file failed: %s", - sftp_libssh2_strerror(err)); - break; - } - else if(((err == LIBSSH2_FX_NO_SUCH_FILE) || - (err == LIBSSH2_FX_FAILURE) || - (err == LIBSSH2_FX_NO_SUCH_PATH)) && - (data->set.ftp_create_missing_dirs && - (strlen(sftp_scp->path) > 1))) { - /* try to create the path remotely */ - sshc->secondCreateDirs = 1; - state(conn, SSH_SFTP_CREATE_DIRS_INIT); - break; - } + if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) + /* only when there was an SFTP protocol error can we extract + the sftp error! */ + err = sftp_libssh2_last_error(sshc->sftp_session); + else + err = -1; /* not an sftp error at all */ + + if(sshc->secondCreateDirs) { state(conn, SSH_SFTP_CLOSE); sshc->actualcode = err>= LIBSSH2_FX_OK? sftp_libssh2_error_to_CURLE(err):CURLE_SSH; - if(!sshc->actualcode) { - /* Sometimes, for some reason libssh2_sftp_last_error() returns - zero even though libssh2_sftp_open() failed previously! We need - to work around that! */ - sshc->actualcode = CURLE_SSH; - err=-1; - } - failf(data, "Upload failed: %s (%d/%d)", - err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", - err, rc); + failf(data, "Creating the dir/file failed: %s", + sftp_libssh2_strerror(err)); + break; + } + if(((err == LIBSSH2_FX_NO_SUCH_FILE) || + (err == LIBSSH2_FX_FAILURE) || + (err == LIBSSH2_FX_NO_SUCH_PATH)) && + (data->set.ftp_create_missing_dirs && + (strlen(sftp_scp->path) > 1))) { + /* try to create the path remotely */ + rc = 0; /* clear rc and continue */ + sshc->secondCreateDirs = 1; + state(conn, SSH_SFTP_CREATE_DIRS_INIT); break; } + state(conn, SSH_SFTP_CLOSE); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + if(!sshc->actualcode) { + /* Sometimes, for some reason libssh2_sftp_last_error() returns + zero even though libssh2_sftp_open() failed previously! We need + to work around that! */ + sshc->actualcode = CURLE_SSH; + err=-1; + } + failf(data, "Upload failed: %s (%d/%d)", + err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", + err, rc); + break; } /* If we have a restart point then we need to seek to the correct @@ -1831,32 +1829,31 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } if(seekerr != CURL_SEEKFUNC_OK) { + curl_off_t passed=0; if(seekerr != CURL_SEEKFUNC_CANTSEEK) { failf(data, "Could not seek stream"); return CURLE_FTP_COULDNT_USE_REST; } /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ - else { - curl_off_t passed=0; - do { - size_t readthisamountnow = - (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? - BUFSIZE : 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, "Failed to read data"); - return CURLE_FTP_COULDNT_USE_REST; - } - } while(passed < data->state.resume_from); - } + 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, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); } /* now, decrease the size of the read */ @@ -1895,7 +1892,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* since we don't really wait for anything at this point, we want the state machine to move on as soon as possible so we set a very short timeout here */ - Curl_expire(data, 0); + Curl_expire(data, 0, EXPIRE_RUN_NOW); state(conn, SSH_STOP); } @@ -1921,9 +1918,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); break; } - else { - state(conn, SSH_SFTP_UPLOAD_INIT); - } + state(conn, SSH_SFTP_UPLOAD_INIT); break; case SSH_SFTP_CREATE_DIRS_MKDIR: @@ -1936,7 +1931,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } *sshc->slash_pos = '/'; ++sshc->slash_pos; - if(rc == -1) { + if(rc < 0) { /* * Abort if failure wasn't that the dir already exists or the * permission was denied (creation might succeed further down the @@ -1951,6 +1946,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) sshc->actualcode = result?result:CURLE_SSH; break; } + rc = 0; /* clear rc and continue */ } state(conn, SSH_SFTP_CREATE_DIRS); break; @@ -1977,22 +1973,22 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) rc = LIBSSH2_ERROR_EAGAIN; break; } - else { - err = sftp_libssh2_last_error(sshc->sftp_session); - failf(data, "Could not open directory for reading: %s", - sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - result = sftp_libssh2_error_to_CURLE(err); - sshc->actualcode = result?result:CURLE_SSH; - break; - } + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open directory for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; } - if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) { + sshc->readdir_filename = malloc(PATH_MAX+1); + if(!sshc->readdir_filename) { state(conn, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) { + sshc->readdir_longentry = malloc(PATH_MAX+1); + if(!sshc->readdir_longentry) { Curl_safefree(sshc->readdir_filename); state(conn, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; @@ -2112,9 +2108,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* get room for the filename and extra output */ sshc->readdir_totalLen += 4 + sshc->readdir_len; - new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen); + new_readdir_line = Curl_saferealloc(sshc->readdir_line, + sshc->readdir_totalLen); if(!new_readdir_line) { - Curl_safefree(sshc->readdir_line); + sshc->readdir_line = NULL; Curl_safefree(sshc->readdir_filename); Curl_safefree(sshc->readdir_longentry); state(conn, SSH_SFTP_CLOSE); @@ -2189,15 +2186,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) rc = LIBSSH2_ERROR_EAGAIN; break; } - else { - err = sftp_libssh2_last_error(sshc->sftp_session); - failf(data, "Could not open remote file for reading: %s", - sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - result = sftp_libssh2_error_to_CURLE(err); - sshc->actualcode = result?result:CURLE_SSH; - break; - } + err = sftp_libssh2_last_error(sshc->sftp_session); + failf(data, "Could not open remote file for reading: %s", + sftp_libssh2_strerror(err)); + state(conn, SSH_SFTP_CLOSE); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; + break; } state(conn, SSH_SFTP_DOWNLOAD_STAT); break; @@ -2212,7 +2207,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc || + if(rc || !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) || (attrs.filesize == 0)) { /* @@ -2310,18 +2305,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) state(conn, SSH_STOP); break; } - else { - Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, - FALSE, NULL, -1, NULL); + Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, + FALSE, NULL, -1, NULL); - /* not set by Curl_setup_transfer to preserve keepon bits */ - conn->writesockfd = conn->sockfd; + /* not set by Curl_setup_transfer to preserve keepon bits */ + conn->writesockfd = conn->sockfd; + + /* we want to use the _receiving_ function even when the socket turns + out writableable as the underlying libssh2 recv function will deal + with both accordingly */ + conn->cselect_bits = CURL_CSELECT_IN; - /* we want to use the _receiving_ function even when the socket turns - out writableable as the underlying libssh2 recv function will deal - with both accordingly */ - conn->cselect_bits = CURL_CSELECT_IN; - } if(result) { /* this should never occur; the close state should be entered at the time the error occurs */ @@ -2339,7 +2333,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to close libssh2 file\n"); } sshc->sftp_handle = NULL; @@ -2373,7 +2367,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to close libssh2 file\n"); } sshc->sftp_handle = NULL; @@ -2383,7 +2377,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to stop libssh2 sftp subsystem\n"); } sshc->sftp_session = NULL; @@ -2428,22 +2422,21 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, data->state.infilesize); if(!sshc->ssh_channel) { + int ssh_err; + char *err_msg; + if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN) { rc = LIBSSH2_ERROR_EAGAIN; break; } - else { - int ssh_err; - char *err_msg; - 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); - sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); - break; - } + 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); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + break; } /* upload data */ @@ -2498,22 +2491,22 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) #endif if(!sshc->ssh_channel) { + int ssh_err; + char *err_msg; + if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN) { rc = LIBSSH2_ERROR_EAGAIN; break; } - else { - int ssh_err; - char *err_msg; - 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); - sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); - break; - } + + 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); + sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + break; } /* download data */ @@ -2551,7 +2544,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc) { + if(rc) { infof(data, "Failed to send libssh2 channel EOF\n"); } } @@ -2564,7 +2557,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc) { + if(rc) { infof(data, "Failed to get channel EOF: %d\n", rc); } } @@ -2577,7 +2570,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc) { + if(rc) { infof(data, "Channel failed to close: %d\n", rc); } } @@ -2590,7 +2583,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to free libssh2 scp subsystem\n"); } sshc->ssh_channel = NULL; @@ -2612,7 +2605,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to free libssh2 scp subsystem\n"); } sshc->ssh_channel = NULL; @@ -2623,7 +2616,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to disconnect libssh2 session\n"); } } @@ -2648,10 +2641,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to disconnect from libssh2 agent\n"); } - libssh2_agent_free (sshc->ssh_agent); + libssh2_agent_free(sshc->ssh_agent); sshc->ssh_agent = NULL; /* NB: there is no need to free identities, they are part of internal @@ -2666,7 +2659,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) if(rc == LIBSSH2_ERROR_EAGAIN) { break; } - else if(rc < 0) { + if(rc < 0) { infof(data, "Failed to free libssh2 session\n"); } sshc->ssh_session = NULL; @@ -2788,13 +2781,16 @@ static int ssh_getsock(struct connectdata *conn, static void ssh_block2waitfor(struct connectdata *conn, bool block) { struct ssh_conn *sshc = &conn->proto.sshc; - int dir; - if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) { - /* translate the libssh2 define bits into our own bit defines */ - conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | - ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); + int dir = 0; + if(block) { + dir = libssh2_session_block_directions(sshc->ssh_session); + if(dir) { + /* translate the libssh2 define bits into our own bit defines */ + conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | + ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); + } } - else + if(!dir) /* It didn't block or libssh2 didn't reveal in which direction, put back the original set */ conn->waitfor = sshc->orig_waitfor; @@ -2820,7 +2816,7 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) } static CURLcode ssh_block_statemach(struct connectdata *conn, - bool duringconnect) + bool disconnect) { struct ssh_conn *sshc = &conn->proto.sshc; CURLcode result = CURLE_OK; @@ -2828,25 +2824,26 @@ static CURLcode ssh_block_statemach(struct connectdata *conn, while((sshc->state != SSH_STOP) && !result) { bool block; - long left; + time_t left = 1000; + struct timeval now = Curl_tvnow(); result = ssh_statemach_act(conn, &block); if(result) break; - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; - else { - struct timeval now = Curl_tvnow(); + if(!disconnect) { + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + result = Curl_speedcheck(data, now); if(result) break; - } - left = Curl_timeleft(data, NULL, duringconnect); - if(left < 0) { - failf(data, "Operation timed out"); - return CURLE_OPERATION_TIMEDOUT; + left = Curl_timeleft(data, NULL, FALSE); + if(left < 0) { + failf(data, "Operation timed out"); + return CURLE_OPERATION_TIMEDOUT; + } } #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION @@ -2860,8 +2857,8 @@ static CURLcode ssh_block_statemach(struct connectdata *conn, if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) fd_write = sock; /* wait for the socket to become ready */ - Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, - left>1000?1000:left); /* ignore result */ + (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, + left>1000?1000:left); /* ignore result */ } #endif @@ -3062,7 +3059,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) state(conn, SSH_SESSION_DISCONNECT); - result = ssh_block_statemach(conn, FALSE); + result = ssh_block_statemach(conn, TRUE); } return result; @@ -3216,7 +3213,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) if(conn->proto.sshc.ssh_session) { /* only if there's a session still around to use! */ state(conn, SSH_SFTP_SHUTDOWN); - result = ssh_block_statemach(conn, FALSE); + result = ssh_block_statemach(conn, TRUE); } DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); @@ -3383,7 +3380,7 @@ get_pathname(const char **cpp, char **path) static const char *sftp_libssh2_strerror(int err) { - switch (err) { + switch(err) { case LIBSSH2_FX_NO_SUCH_FILE: return "No such file or directory"; diff --git a/Utilities/cmcurl/lib/strcase.c b/Utilities/cmcurl/lib/strcase.c index 807689ef8..a74a4be57 100644 --- a/Utilities/cmcurl/lib/strcase.c +++ b/Utilities/cmcurl/lib/strcase.c @@ -34,7 +34,7 @@ char Curl_raw_toupper(char in) if(in >= 'a' && in <= 'z') return (char)('A' + in - 'a'); #else - switch (in) { + switch(in) { case 'a': return 'A'; case 'b': @@ -120,6 +120,16 @@ int Curl_strcasecompare(const char *first, const char *second) return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); } +int Curl_safe_strcasecompare(const char *first, const char *second) +{ + if(first && second) + /* both pointers point to something then compare them */ + return Curl_strcasecompare(first, second); + + /* if both pointers are NULL then treat them as equal */ + return (NULL == first && NULL == second); +} + /* * @unittest: 1301 */ diff --git a/Utilities/cmcurl/lib/strcase.h b/Utilities/cmcurl/lib/strcase.h index bf057b1ff..ea2abc8b6 100644 --- a/Utilities/cmcurl/lib/strcase.h +++ b/Utilities/cmcurl/lib/strcase.h @@ -36,6 +36,7 @@ #define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c) int Curl_strcasecompare(const char *first, const char *second); +int Curl_safe_strcasecompare(const char *first, const char *second); int Curl_strncasecompare(const char *first, const char *second, size_t max); char Curl_raw_toupper(char in); diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c index 5a15c2b16..136b69377 100644 --- a/Utilities/cmcurl/lib/strdup.c +++ b/Utilities/cmcurl/lib/strdup.c @@ -75,3 +75,26 @@ void *Curl_memdup(const void *src, size_t length) return buffer; } + +/*************************************************************************** + * + * Curl_saferealloc(ptr, size) + * + * Does a normal realloc(), but will free the data pointer if the realloc + * fails. If 'size' is zero, it will free the data and return a failure. + * + * This convenience function is provided and used to help us avoid a common + * mistake pattern when we could pass in a zero, catch the NULL return and end + * up free'ing the memory twice. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_saferealloc(void *ptr, size_t size) +{ + void *datap = realloc(ptr, size); + if(size && !datap) + /* only free 'ptr' if size was non-zero */ + free(ptr); + return datap; +} diff --git a/Utilities/cmcurl/lib/strdup.h b/Utilities/cmcurl/lib/strdup.h index c74a3b730..ae3d5d011 100644 --- a/Utilities/cmcurl/lib/strdup.h +++ b/Utilities/cmcurl/lib/strdup.h @@ -27,5 +27,6 @@ extern char *curlx_strdup(const char *str); #endif void *Curl_memdup(const void *src, size_t buffer_length); +void *Curl_saferealloc(void *ptr, size_t size); #endif /* HEADER_CURL_STRDUP_H */ diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c index db50c7d1a..7e5cde47b 100644 --- a/Utilities/cmcurl/lib/strerror.c +++ b/Utilities/cmcurl/lib/strerror.c @@ -53,7 +53,7 @@ const char * curl_easy_strerror(CURLcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { + switch(error) { case CURLE_OK: return "No error"; @@ -348,7 +348,7 @@ const char * curl_multi_strerror(CURLMcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { + switch(error) { case CURLM_CALL_MULTI_PERFORM: return "Please call curl_multi_perform() soon"; @@ -393,7 +393,7 @@ const char * curl_share_strerror(CURLSHcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { + switch(error) { case CURLSHE_OK: return "No error"; @@ -435,7 +435,7 @@ get_winsock_error (int err, char *buf, size_t len) const char *p; #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (err) { + switch(err) { case WSAEINTR: p = "Call interrupted"; break; @@ -609,7 +609,7 @@ get_winsock_error (int err, char *buf, size_t len) else p = "error"; #endif - strncpy (buf, p, len); + strncpy(buf, p, len); buf [len-1] = '\0'; return buf; } @@ -715,10 +715,12 @@ const char *Curl_strerror(struct connectdata *conn, int err) buf[max] = '\0'; /* make sure the string is zero terminated */ /* strip trailing '\r\n' or '\n'. */ - if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2) - *p = '\0'; - if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1) - *p = '\0'; + p = strrchr(buf, '\n'); + if(p && (p - buf) >= 2) + *p = '\0'; + p = strrchr(buf, '\r'); + if(p && (p - buf) >= 1) + *p = '\0'; if(old_errno != ERRNO) SET_ERRNO(old_errno); @@ -750,7 +752,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) old_errno = ERRNO; - switch (err) { + switch(err) { case SEC_E_OK: txt = "No error"; break; @@ -1035,10 +1037,12 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) if(msg_formatted) { msgbuf[sizeof(msgbuf)-1] = '\0'; /* strip trailing '\r\n' or '\n' */ - if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2) - *p = '\0'; - if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1) - *p = '\0'; + p = strrchr(msgbuf, '\n'); + if(p && (p - msgbuf) >= 2) + *p = '\0'; + p = strrchr(msgbuf, '\r'); + if(p && (p - msgbuf) >= 1) + *p = '\0'; msg = msgbuf; } if(msg) diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c index 6d5d2d5c5..b854bf4de 100644 --- a/Utilities/cmcurl/lib/strtoofft.c +++ b/Utilities/cmcurl/lib/strtoofft.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -165,7 +165,7 @@ static int get_char(char c, int base) value = c - 'a' + 10; } #else - const char * cp; + const char *cp; int value; cp = memchr(valchars, c, 10 + 26 + 26); diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c index 78737593a..cfbbf3279 100644 --- a/Utilities/cmcurl/lib/system_win32.c +++ b/Utilities/cmcurl/lib/system_win32.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2016, Steve Holme, . + * Copyright (C) 2016 - 2017, Steve Holme, . * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -68,7 +68,7 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); * * majorVersion [in] - The major version number. * minorVersion [in] - The minor version number. - * platform [in] - The optional platform identifer. + * platform [in] - The optional platform identifier. * condition [in] - The test condition used to specifier whether we are * checking a version less then, equal to or greater than * what is specified in the major and minor version diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c index c37242db6..155d4b260 100644 --- a/Utilities/cmcurl/lib/telnet.c +++ b/Utilities/cmcurl/lib/telnet.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,17 +81,19 @@ } WHILE_FALSE #define CURL_SB_GET(x) ((*x->subpointer++)&0xff) -#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) -#define CURL_SB_EOF(x) (x->subpointer >= x->subend) #define CURL_SB_LEN(x) (x->subend - x->subpointer) +/* For posterity: +#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) +#define CURL_SB_EOF(x) (x->subpointer >= x->subend) */ + #ifdef CURL_DISABLE_VERBOSE_STRINGS #define printoption(a,b,c,d) Curl_nop_stmt #endif #ifdef USE_WINSOCK typedef FARPROC WSOCK2_FUNC; -static CURLcode check_wsock2 (struct Curl_easy *data); +static CURLcode check_wsock2(struct Curl_easy *data); #endif static @@ -872,7 +874,7 @@ static CURLcode check_telnet_options(struct connectdata *conn) continue; } - /* Window Size */ + /* Window Size */ if(strcasecompare(option_keyword, "WS")) { if(sscanf(option_arg, "%hu%*[xX]%hu", &tn->subopt_wsx, &tn->subopt_wsy) == 2) @@ -899,11 +901,9 @@ static CURLcode check_telnet_options(struct connectdata *conn) result = CURLE_UNKNOWN_TELNET_OPTION; break; } - else { - failf(data, "Syntax error in telnet option: %s", head->data); - result = CURLE_TELNET_OPTION_SYNTAX; - break; - } + failf(data, "Syntax error in telnet option: %s", head->data); + result = CURLE_TELNET_OPTION_SYNTAX; + break; } if(result) { @@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn) struct TELNET *tn = (struct TELNET *)data->req.protop; printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2); - switch (CURL_SB_GET(tn)) { + switch(CURL_SB_GET(tn)) { case CURL_TELOPT_TTYPE: len = strlen(tn->subopt_ttype) + 4 + 2; snprintf((char *)temp, sizeof(temp), @@ -1004,24 +1004,24 @@ static void sendsuboption(struct connectdata *conn, int option) ssize_t bytes_written; int err; unsigned short x, y; - unsigned char*uc1, *uc2; + unsigned char *uc1, *uc2; struct Curl_easy *data = conn->data; struct TELNET *tn = (struct TELNET *)data->req.protop; - switch (option) { + switch(option) { case CURL_TELOPT_NAWS: /* We prepare data to be sent */ CURL_SB_CLEAR(tn); CURL_SB_ACCUM(tn, CURL_IAC); CURL_SB_ACCUM(tn, CURL_SB); CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS); - /* We must deal either with litte or big endien processors */ + /* We must deal either with litte or big endian processors */ /* Window size must be sent according to the 'network order' */ x=htons(tn->subopt_wsx); y=htons(tn->subopt_wsy); - uc1 = (unsigned char*)&x; - uc2 = (unsigned char*)&y; + uc1 = (unsigned char *)&x; + uc2 = (unsigned char *)&y; CURL_SB_ACCUM(tn, uc1[0]); CURL_SB_ACCUM(tn, uc1[1]); CURL_SB_ACCUM(tn, uc2[0]); @@ -1087,7 +1087,7 @@ CURLcode telrcv(struct connectdata *conn, while(count--) { c = inbuf[in]; - switch (tn->telrcv_state) { + switch(tn->telrcv_state) { case CURL_TS_CR: tn->telrcv_state = CURL_TS_DATA; if(c == '\0') { @@ -1111,7 +1111,7 @@ CURLcode telrcv(struct connectdata *conn, case CURL_TS_IAC: process_iac: DEBUGASSERT(startwrite < 0); - switch (c) { + switch(c) { case CURL_WILL: tn->telrcv_state = CURL_TS_WILL; break; @@ -1186,7 +1186,7 @@ CURLcode telrcv(struct connectdata *conn, * IAC SE was left off, or another option got inserted into the * suboption are all possibilities. If we assume that the IAC was * not doubled, and really the IAC SE was left off, we could get - * into an infinate loop here. So, instead, we terminate the + * into an infinite loop here. So, instead, we terminate the * suboption, and process the partial suboption if we can. */ CURL_SB_ACCUM(tn, CURL_IAC); @@ -1220,43 +1220,63 @@ CURLcode telrcv(struct connectdata *conn, } /* Escape and send a telnet data block */ -/* TODO: write large chunks of data instead of one byte at a time */ static CURLcode send_telnet_data(struct connectdata *conn, char *buffer, ssize_t nread) { - unsigned char outbuf[2]; - ssize_t bytes_written, total_written; - int out_count; + ssize_t escapes, i, j, outlen; + unsigned char *outbuf = NULL; CURLcode result = CURLE_OK; + ssize_t bytes_written, total_written; - while(!result && nread--) { - outbuf[0] = *buffer++; - out_count = 1; - if(outbuf[0] == CURL_IAC) - outbuf[out_count++] = CURL_IAC; - - total_written = 0; - do { - /* Make sure socket is writable to avoid EWOULDBLOCK condition */ - struct pollfd pfd[1]; - pfd[0].fd = conn->sock[FIRSTSOCKET]; - pfd[0].events = POLLOUT; - switch (Curl_poll(pfd, 1, -1)) { - case -1: /* error, abort writing */ - case 0: /* timeout (will never happen) */ - result = CURLE_SEND_ERROR; - break; - default: /* write! */ - bytes_written = 0; - result = Curl_write(conn, conn->sock[FIRSTSOCKET], - outbuf+total_written, out_count-total_written, - &bytes_written); - total_written += bytes_written; - break; - } - /* handle partial write */ - } while(!result && total_written < out_count); + /* Determine size of new buffer after escaping */ + escapes = 0; + for(i = 0; i < nread; i++) + if((unsigned char)buffer[i] == CURL_IAC) + escapes++; + outlen = nread + escapes; + + if(outlen == nread) + outbuf = (unsigned char *)buffer; + else { + outbuf = malloc(nread + escapes + 1); + if(!outbuf) + return CURLE_OUT_OF_MEMORY; + + j = 0; + for(i = 0; i < nread; i++) { + outbuf[j++] = buffer[i]; + if((unsigned char)buffer[i] == CURL_IAC) + outbuf[j++] = CURL_IAC; + } + outbuf[j] = '\0'; + } + + total_written = 0; + while(!result && total_written < outlen) { + /* Make sure socket is writable to avoid EWOULDBLOCK condition */ + struct pollfd pfd[1]; + pfd[0].fd = conn->sock[FIRSTSOCKET]; + pfd[0].events = POLLOUT; + switch(Curl_poll(pfd, 1, -1)) { + case -1: /* error, abort writing */ + case 0: /* timeout (will never happen) */ + result = CURLE_SEND_ERROR; + break; + default: /* write! */ + bytes_written = 0; + result = Curl_write(conn, conn->sock[FIRSTSOCKET], + outbuf + total_written, + outlen - total_written, + &bytes_written); + total_written += bytes_written; + break; + } } + + /* Free malloc copy if escaped */ + if(outbuf != (unsigned char *)buffer) + free(outbuf); + return result; } @@ -1326,7 +1346,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) #ifdef USE_WINSOCK /* ** This functionality only works with WinSock >= 2.0. So, - ** make sure have it. + ** make sure we have it. */ result = check_wsock2(data); if(result) @@ -1416,28 +1436,29 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) /* Keep on listening and act on events */ while(keepon) { + const DWORD buf_size = (DWORD)data->set.buffer_size; waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout); switch(waitret) { case WAIT_TIMEOUT: { for(;;) { if(data->set.is_fread_set) { + size_t n; /* read from user-supplied method */ - result = (int)data->state.fread_func(buf, 1, BUFSIZE - 1, - data->state.in); - if(result == CURL_READFUNC_ABORT) { + n = data->state.fread_func(buf, 1, buf_size, data->state.in); + if(n == CURL_READFUNC_ABORT) { keepon = FALSE; result = CURLE_READ_ERROR; break; } - if(result == CURL_READFUNC_PAUSE) + if(n == CURL_READFUNC_PAUSE) break; - if(result == 0) /* no bytes */ + if(n == 0) /* no bytes */ break; - readfile_read = result; /* fall thru with number of bytes read */ + readfile_read = (DWORD)n; /* fall thru with number of bytes read */ } else { /* read from stdin */ @@ -1451,7 +1472,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) if(!readfile_read) break; - if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), + if(!ReadFile(stdin_handle, buf, buf_size, &readfile_read, NULL)) { keepon = FALSE; result = CURLE_READ_ERROR; @@ -1470,7 +1491,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) case WAIT_OBJECT_0 + 1: { - if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), + if(!ReadFile(stdin_handle, buf, buf_size, &readfile_read, NULL)) { keepon = FALSE; result = CURLE_READ_ERROR; @@ -1489,7 +1510,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) events.lNetworkEvents = 0; if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { - if((err = SOCKERRNO) != EINPROGRESS) { + err = SOCKERRNO; + if(err != EINPROGRESS) { infof(data, "WSAEnumNetworkEvents failed (%d)", err); keepon = FALSE; result = CURLE_READ_ERROR; @@ -1498,7 +1520,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, BUFSIZE - 1, &nread); + result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); /* read would've blocked. Loop again */ if(result == CURLE_AGAIN) break; @@ -1576,7 +1598,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } while(keepon) { - switch (Curl_poll(pfd, poll_cnt, interval_ms)) { + switch(Curl_poll(pfd, poll_cnt, interval_ms)) { case -1: /* error, stop reading */ keepon = FALSE; continue; @@ -1587,12 +1609,12 @@ 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, BUFSIZE - 1, &nread); + result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread); /* read would've blocked. Loop again */ if(result == CURLE_AGAIN) break; /* returned not-zero, this an error */ - else if(result) { + if(result) { keepon = FALSE; break; } @@ -1623,12 +1645,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) nread = 0; if(poll_cnt == 2) { if(pfd[1].revents & POLLIN) { /* read from in file */ - nread = read(pfd[1].fd, buf, BUFSIZE - 1); + nread = read(pfd[1].fd, buf, data->set.buffer_size); } } else { /* read from user-supplied method */ - nread = (int)data->state.fread_func(buf, 1, BUFSIZE - 1, + nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size, data->state.in); if(nread == CURL_READFUNC_ABORT) { keepon = FALSE; diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c index deee39471..b2b3efe0c 100644 --- a/Utilities/cmcurl/lib/tftp.c +++ b/Utilities/cmcurl/lib/tftp.c @@ -199,7 +199,7 @@ const struct Curl_handler Curl_handler_tftp = { static CURLcode tftp_set_timeouts(tftp_state_data_t *state) { time_t maxtime, timeout; - long timeout_ms; + time_t timeout_ms; bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; time(&state->start_time); @@ -304,7 +304,7 @@ static unsigned short getrpacketblock(const tftp_packet_t *packet) static size_t Curl_strnlen(const char *string, size_t maxlen) { - const char *end = memchr (string, '\0', maxlen); + const char *end = memchr(string, '\0', maxlen); return end ? (size_t) (end - string) : maxlen; } @@ -359,7 +359,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state, failf(data, "invalid blocksize value in OACK packet"); return CURLE_TFTP_ILLEGAL; } - else if(blksize > TFTP_BLKSIZE_MAX) { + if(blksize > TFTP_BLKSIZE_MAX) { failf(data, "%s (%d)", "blksize is larger than max supported", TFTP_BLKSIZE_MAX); return CURLE_TFTP_ILLEGAL; @@ -1119,7 +1119,8 @@ static CURLcode tftp_receive_packet(struct connectdata *conn) } else { /* The event is given by the TFTP packet time */ - state->event = (tftp_event_t)getrpacketevent(&state->rpacket); + unsigned short event = getrpacketevent(&state->rpacket); + state->event = (tftp_event_t)event; switch(state->event) { case TFTP_EVENT_DATA: @@ -1138,9 +1139,12 @@ static CURLcode tftp_receive_packet(struct connectdata *conn) } break; case TFTP_EVENT_ERROR: - state->error = (tftp_error_t)getrpacketblock(&state->rpacket); + { + unsigned short error = getrpacketblock(&state->rpacket); + state->error = (tftp_error_t)error; infof(data, "%s\n", (const char *)state->rpacket.data+4); break; + } case TFTP_EVENT_ACK: break; case TFTP_EVENT_OACK: @@ -1189,7 +1193,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) state->state = TFTP_STATE_FIN; return 0; } - else if(current > state->rx_time+state->retry_time) { + if(current > state->rx_time+state->retry_time) { if(event) *event = TFTP_EVENT_TIMEOUT; time(&state->rx_time); /* update even though we received nothing */ @@ -1223,7 +1227,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) failf(data, "TFTP response timeout"); return CURLE_OPERATION_TIMEDOUT; } - else if(event != TFTP_EVENT_NONE) { + if(event != TFTP_EVENT_NONE) { result = tftp_state_machine(state, event); if(result) return result; @@ -1356,7 +1360,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done) static CURLcode tftp_setup_connection(struct connectdata * conn) { struct Curl_easy *data = conn->data; - char * type; + char *type; char command; conn->socktype = SOCK_DGRAM; /* UDP datagram based */ @@ -1372,7 +1376,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn) *type = 0; /* it was in the middle of the hostname */ command = Curl_raw_toupper(type[6]); - switch (command) { + switch(command) { case 'A': /* ASCII mode */ case 'N': /* NETASCII mode */ data->set.prefer_ascii = TRUE; diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c index 629f1c8f0..bed44c573 100644 --- a/Utilities/cmcurl/lib/timeval.c +++ b/Utilities/cmcurl/lib/timeval.c @@ -116,7 +116,7 @@ struct timeval curlx_tvnow(void) * Returns: the time difference in number of milliseconds. For large diffs it * returns 0x7fffffff on 32bit time_t systems. */ -long curlx_tvdiff(struct timeval newer, struct timeval older) +time_t curlx_tvdiff(struct timeval newer, struct timeval older) { #if SIZEOF_TIME_T < 8 /* for 32bit time_t systems, add a precaution to avoid overflow for really @@ -126,7 +126,7 @@ long curlx_tvdiff(struct timeval newer, struct timeval older) return 0x7fffffff; #endif return (newer.tv_sec-older.tv_sec)*1000+ - (long)(newer.tv_usec-older.tv_usec)/1000; + (time_t)(newer.tv_usec-older.tv_usec)/1000; } /* @@ -139,12 +139,5 @@ double curlx_tvdiff_secs(struct timeval newer, struct timeval older) if(newer.tv_sec != older.tv_sec) return (double)(newer.tv_sec-older.tv_sec)+ (double)(newer.tv_usec-older.tv_usec)/1000000.0; - else - return (double)(newer.tv_usec-older.tv_usec)/1000000.0; -} - -/* return the number of seconds in the given input timeval struct */ -long Curl_tvlong(struct timeval t1) -{ - return t1.tv_sec; + return (double)(newer.tv_usec-older.tv_usec)/1000000.0; } diff --git a/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h index 50c31a252..33969354d 100644 --- a/Utilities/cmcurl/lib/timeval.h +++ b/Utilities/cmcurl/lib/timeval.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,7 +37,7 @@ struct timeval curlx_tvnow(void); * * Returns: the time difference in number of milliseconds. */ -long curlx_tvdiff(struct timeval t1, struct timeval t2); +time_t curlx_tvdiff(struct timeval t1, struct timeval t2); /* * Same as curlx_tvdiff but with full usec resolution. @@ -46,8 +46,6 @@ long curlx_tvdiff(struct timeval t1, struct timeval t2); */ double curlx_tvdiff_secs(struct timeval t1, struct timeval t2); -long Curl_tvlong(struct timeval t1); - /* These two defines below exist to provide the older API for library internals only. */ #define Curl_tvnow() curlx_tvnow() diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c index 6245ee402..43e8f64aa 100644 --- a/Utilities/cmcurl/lib/transfer.c +++ b/Utilities/cmcurl/lib/transfer.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -117,7 +117,8 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) *nreadp = 0; return CURLE_ABORTED_BY_CALLBACK; } - else if(nread == CURL_READFUNC_PAUSE) { + if(nread == CURL_READFUNC_PAUSE) { + struct SingleRequest *k = &data->req; if(conn->handler->flags & PROTOPT_NONETWORK) { /* protocols that work without network cannot be paused. This is @@ -126,16 +127,15 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) failf(data, "Read callback asked for PAUSE when not supported!"); return CURLE_READ_ERROR; } - else { - struct SingleRequest *k = &data->req; - /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ - k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ - if(data->req.upload_chunky) { + + /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ + k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ + if(data->req.upload_chunky) { /* Back out the preallocation done above */ - data->req.upload_fromhere -= (8 + 2); - } - *nreadp = 0; + data->req.upload_fromhere -= (8 + 2); } + *nreadp = 0; + return CURLE_OK; /* nothing was read */ } else if((size_t)nread > buffersize) { @@ -405,8 +405,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, /* This is where we loop until we have read everything there is to read or we get a CURLE_AGAIN */ do { - size_t buffersize = data->set.buffer_size? - data->set.buffer_size : BUFSIZE; + size_t buffersize = data->set.buffer_size; size_t bytestoread = buffersize; if( @@ -642,7 +641,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res)); return CURLE_RECV_ERROR; } - else if(CHUNKE_STOP == res) { + if(CHUNKE_STOP == res) { size_t dataleft; /* we're done reading chunks! */ k->keepon &= ~KEEP_RECV; /* read no more */ @@ -681,8 +680,6 @@ static CURLcode readwrite_data(struct Curl_easy *data, excess = (size_t)(k->bytecount + nread - k->maxdownload); if(excess > 0 && !k->ignorebody) { if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) { - /* The 'excess' amount below can't be more than BUFSIZE which - always will fit in a size_t */ infof(data, "Rewinding stream by : %zu" " bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T @@ -741,8 +738,8 @@ static CURLcode readwrite_data(struct Curl_easy *data, Make sure that ALL_CONTENT_ENCODINGS contains all the encodings handled here. */ #ifdef HAVE_LIBZ - switch (conn->data->set.http_ce_skip ? - IDENTITY : k->auto_decoding) { + switch(conn->data->set.http_ce_skip ? + IDENTITY : k->auto_decoding) { case IDENTITY: #endif /* This is the default when the server sends no @@ -775,9 +772,9 @@ static CURLcode readwrite_data(struct Curl_easy *data, break; default: - failf (data, "Unrecognized content encoding type. " - "libcurl understands `identity', `deflate' and `gzip' " - "content encodings."); + failf(data, "Unrecognized content encoding type. " + "libcurl understands `identity', `deflate' and `gzip' " + "content encodings."); result = CURLE_BAD_CONTENT_ENCODING; break; } @@ -853,7 +850,6 @@ static CURLcode done_sending(struct connectdata *conn, */ static CURLcode readwrite_upload(struct Curl_easy *data, struct connectdata *conn, - struct SingleRequest *k, int *didwhat) { ssize_t i, si; @@ -861,6 +857,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, CURLcode result; ssize_t nread; /* number of bytes read */ bool sending_http_headers = FALSE; + struct SingleRequest *k = &data->req; if((k->bytecount == 0) && (k->writebytecount == 0)) Curl_pgrsTime(data, TIMER_STARTTRANSFER); @@ -871,15 +868,15 @@ static CURLcode readwrite_upload(struct Curl_easy *data, /* only read more data if there's no upload data already present in the upload buffer */ - if(0 == data->req.upload_present) { + if(0 == k->upload_present) { /* init the "upload from here" pointer */ - data->req.upload_fromhere = k->uploadbuf; + k->upload_fromhere = data->state.uploadbuffer; if(!k->upload_done) { /* HTTP pollution, this should be written nicer to become more protocol agnostic. */ int fillcount; - struct HTTP *http = data->req.protop; + struct HTTP *http = k->protop; if((k->exp100 == EXP100_SENDING_REQUEST) && (http->sending == HTTPSEND_BODY)) { @@ -892,7 +889,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, *didwhat &= ~KEEP_SEND; /* we didn't write anything actually */ /* set a timeout for the multi interface */ - Curl_expire(data, data->set.expect_100_timeout); + Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT); break; } @@ -905,7 +902,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, sending_http_headers = FALSE; } - result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount); + result = Curl_fillreadbuffer(conn, UPLOAD_BUFSIZE, &fillcount); if(result) return result; @@ -918,7 +915,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, /* this is a paused transfer */ break; } - else if(nread<=0) { + if(nread<=0) { result = done_sending(conn, k); if(result) return result; @@ -926,7 +923,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, } /* store number of bytes available for upload */ - data->req.upload_present = nread; + k->upload_present = nread; /* convert LF to CRLF if so asked */ if((!sending_http_headers) && ( @@ -937,7 +934,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, (data->set.crlf))) { /* Do we need to allocate a scratch buffer? */ if(!data->state.scratch) { - data->state.scratch = malloc(2 * BUFSIZE); + data->state.scratch = malloc(2 * data->set.buffer_size); if(!data->state.scratch) { failf(data, "Failed to alloc scratch buffer!"); @@ -952,7 +949,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, * must be used instead of the escape sequences \r & \n. */ for(i = 0, si = 0; i < nread; i++, si++) { - if(data->req.upload_fromhere[i] == 0x0a) { + if(k->upload_fromhere[i] == 0x0a) { data->state.scratch[si++] = 0x0d; data->state.scratch[si] = 0x0a; if(!data->set.crlf) { @@ -963,7 +960,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, } } else - data->state.scratch[si] = data->req.upload_fromhere[i]; + data->state.scratch[si] = k->upload_fromhere[i]; } if(si != nread) { @@ -972,10 +969,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data, nread = si; /* upload from the new (replaced) buffer instead */ - data->req.upload_fromhere = data->state.scratch; + k->upload_fromhere = data->state.scratch; /* set the new amount too */ - data->req.upload_present = nread; + k->upload_present = nread; } } @@ -986,7 +983,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, return result; } #endif /* CURL_DISABLE_SMTP */ - } /* if 0 == data->req.upload_present */ + } /* if 0 == k->upload_present */ else { /* We have a partial buffer left from a previous "round". Use that instead of reading more data */ @@ -994,17 +991,17 @@ static CURLcode readwrite_upload(struct Curl_easy *data, /* write to socket (send away data) */ result = Curl_write(conn, - conn->writesockfd, /* socket to send to */ - data->req.upload_fromhere, /* buffer pointer */ - data->req.upload_present, /* buffer size */ - &bytes_written); /* actually sent */ + conn->writesockfd, /* socket to send to */ + k->upload_fromhere, /* buffer pointer */ + k->upload_present, /* buffer size */ + &bytes_written); /* actually sent */ if(result) return result; if(data->set.verbose) /* show the data before we change the pointer upload_fromhere */ - Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere, + Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere, (size_t)bytes_written, conn); k->writebytecount += bytes_written; @@ -1015,20 +1012,20 @@ static CURLcode readwrite_upload(struct Curl_easy *data, infof(data, "We are completely uploaded and fine\n"); } - if(data->req.upload_present != bytes_written) { + if(k->upload_present != bytes_written) { /* we only wrote a part of the buffer (if anything), deal with it! */ /* store the amount of bytes left in the buffer to write */ - data->req.upload_present -= bytes_written; + k->upload_present -= bytes_written; /* advance the pointer where to find the buffer when the next send is to happen */ - data->req.upload_fromhere += bytes_written; + k->upload_fromhere += bytes_written; } else { /* we've uploaded that buffer now */ - data->req.upload_fromhere = k->uploadbuf; - data->req.upload_present = 0; /* no more bytes left */ + k->upload_fromhere = data->state.uploadbuffer; + k->upload_present = 0; /* no more bytes left */ if(k->upload_done) { result = done_sending(conn, k); @@ -1108,7 +1105,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) { /* write */ - result = readwrite_upload(data, conn, k, &didwhat); + result = readwrite_upload(data, conn, &didwhat); if(result) return result; } @@ -1137,11 +1134,12 @@ CURLcode Curl_readwrite(struct connectdata *conn, */ - long ms = Curl_tvdiff(k->now, k->start100); + time_t ms = Curl_tvdiff(k->now, k->start100); if(ms >= data->set.expect_100_timeout) { /* we've waited long enough, continue anyway */ k->exp100 = EXP100_SEND_DATA; k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); infof(data, "Done waiting for 100-continue\n"); } } @@ -1186,15 +1184,13 @@ CURLcode Curl_readwrite(struct connectdata *conn, */ (k->bytecount != (k->size + data->state.crlf_conversions)) && #endif /* CURL_DO_LINEEND_CONV */ - !data->req.newurl) { + !k->newurl) { failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T - " bytes remaining to read", - k->size - k->bytecount); + " bytes remaining to read", k->size - k->bytecount); return CURLE_PARTIAL_FILE; } - else if(!(data->set.opt_no_body) && - k->chunk && - (conn->chunk.state != CHUNK_STOP)) { + if(!(data->set.opt_no_body) && k->chunk && + (conn->chunk.state != CHUNK_STOP)) { /* * In chunked mode, return an error if the connection is closed prior to * the empty (terminating) chunk is read. @@ -1296,7 +1292,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) /* Init the SSL session ID cache here. We do it here since we want to do it after the *_setopt() calls (that could specify the size of the cache) but before any transfer takes place. */ - result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions); + result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions); if(result) return result; @@ -1313,8 +1309,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) if(data->set.httpreq == HTTPREQ_PUT) data->state.infilesize = data->set.filesize; - else + else { data->state.infilesize = data->set.postfieldsize; + if(data->set.postfields && (data->state.infilesize == -1)) + data->state.infilesize = (curl_off_t)strlen(data->set.postfields); + } /* If there is a list of cookie files to read, do it now! */ if(data->change.cookielist) @@ -1343,10 +1342,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) Curl_pgrsStartNow(data); if(data->set.timeout) - Curl_expire(data, data->set.timeout); + Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT); if(data->set.connecttimeout) - Curl_expire(data, data->set.connecttimeout); + Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT); /* In case the handle is re-used and an authentication method was picked in the session we need to make sure we only use the one(s) we now @@ -1356,13 +1355,12 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) if(data->set.wildcardmatch) { struct WildcardData *wc = &data->wildcard; - if(!wc->filelist) { + if(wc->state < CURLWC_INIT) { result = Curl_wildcard_init(wc); /* init wildcard structures */ if(result) return CURLE_OUT_OF_MEMORY; } } - } return result; @@ -1629,9 +1627,7 @@ static char *concat_url(const char *base, const char *relurl) * as given by the remote server and set up the new URL to request. */ CURLcode Curl_follow(struct Curl_easy *data, - char *newurl, /* this 'newurl' is the Location: string, - and it must be malloc()ed before passed - here */ + char *newurl, /* the Location: string */ followtype type) /* see transfer.h */ { #ifdef CURL_DISABLE_HTTP @@ -1644,33 +1640,36 @@ CURLcode Curl_follow(struct Curl_easy *data, /* Location: redirect */ bool disallowport = FALSE; + bool reachedmax = FALSE; if(type == FOLLOW_REDIR) { if((data->set.maxredirs != -1) && - (data->set.followlocation >= data->set.maxredirs)) { - failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs); - return CURLE_TOO_MANY_REDIRECTS; + (data->set.followlocation >= data->set.maxredirs)) { + reachedmax = TRUE; + type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected + to URL */ } + else { + /* mark the next request as a followed location: */ + data->state.this_is_a_follow = TRUE; - /* mark the next request as a followed location: */ - data->state.this_is_a_follow = TRUE; + data->set.followlocation++; /* count location-followers */ - data->set.followlocation++; /* count location-followers */ + if(data->set.http_auto_referer) { + /* We are asked to automatically set the previous URL as the referer + when we get the next URL. We pick the ->url field, which may or may + not be 100% correct */ - if(data->set.http_auto_referer) { - /* We are asked to automatically set the previous URL as the referer - when we get the next URL. We pick the ->url field, which may or may - not be 100% correct */ + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } - if(data->change.referer_alloc) { - Curl_safefree(data->change.referer); - data->change.referer_alloc = FALSE; + data->change.referer = strdup(data->change.url); + if(!data->change.referer) + return CURLE_OUT_OF_MEMORY; + data->change.referer_alloc = TRUE; /* yes, free this later */ } - - data->change.referer = strdup(data->change.url); - if(!data->change.referer) - return CURLE_OUT_OF_MEMORY; - data->change.referer_alloc = TRUE; /* yes, free this later */ } } @@ -1682,7 +1681,6 @@ CURLcode Curl_follow(struct Curl_easy *data, char *absolute = concat_url(data->change.url, newurl); if(!absolute) return CURLE_OUT_OF_MEMORY; - free(newurl); newurl = absolute; } else { @@ -1698,8 +1696,6 @@ CURLcode Curl_follow(struct Curl_easy *data, if(!newest) return CURLE_OUT_OF_MEMORY; strcpy_url(newest, newurl); /* create a space-free URL */ - - free(newurl); /* that was no good */ newurl = newest; /* use this instead now */ } @@ -1708,6 +1704,11 @@ CURLcode Curl_follow(struct Curl_easy *data, /* we're only figuring out the new url if we would've followed locations but now we're done so we can get out! */ data->info.wouldredirect = newurl; + + if(reachedmax) { + failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs); + return CURLE_TOO_MANY_REDIRECTS; + } return CURLE_OK; } @@ -1721,7 +1722,6 @@ CURLcode Curl_follow(struct Curl_easy *data, data->change.url = newurl; data->change.url_alloc = TRUE; - newurl = NULL; /* don't free! */ infof(data, "Issue another request to this URL: '%s'\n", data->change.url); @@ -1795,7 +1795,7 @@ CURLcode Curl_follow(struct Curl_easy *data, break; case 303: /* See Other */ - /* Disable both types of POSTs, unless the user explicitely + /* Disable both types of POSTs, unless the user explicitly asks for POST after POST */ if(data->set.httpreq != HTTPREQ_GET && !(data->set.keep_post & CURL_REDIR_POST_303)) { @@ -1843,12 +1843,17 @@ CURLcode Curl_retry_request(struct connectdata *conn, return CURLE_OK; if((data->req.bytecount + data->req.headerbytecount == 0) && - conn->bits.reuse && - (data->set.rtspreq != RTSPREQ_RECEIVE)) { - /* We didn't get a single byte when we attempted to re-use a - connection. This might happen if the connection was left alive when we - were done using it before, but that was closed when we wanted to use it - again. Bad luck. Retry the same request on a fresh connect! */ + conn->bits.reuse && + (!data->set.opt_no_body + || (conn->handler->protocol & PROTO_FAMILY_HTTP)) && + (data->set.rtspreq != RTSPREQ_RECEIVE)) { + /* We got no data, we attempted to re-use a connection. For HTTP this + can be a retry so we try again regardless if we expected a body. + For other protocols we only try again only if we expected a body. + + This might happen if the connection was left alive when we were + done using it before, but that was closed when we wanted to read from + it again. Bad luck. Retry the same request on a fresh connect! */ infof(conn->data, "Connection died, retrying a fresh connect\n"); *url = strdup(conn->data->change.url); if(!*url) @@ -1943,7 +1948,7 @@ Curl_setup_transfer( /* Set a timeout for the multi interface. Add the inaccuracy margin so that we don't fire slightly too early and get denied to run. */ - Curl_expire(data, data->set.expect_100_timeout); + Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT); } else { if(data->state.expect100header) diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c index b997f419b..87446dbca 100644 --- a/Utilities/cmcurl/lib/url.c +++ b/Utilities/cmcurl/lib/url.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -92,6 +92,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "warnless.h" #include "non-ascii.h" #include "inet_pton.h" +#include "getinfo.h" /* And now for the protocols */ #include "ftp.h" @@ -139,6 +140,19 @@ static CURLcode parse_login_details(const char *login, const size_t len, char **optionsptr); static unsigned int get_protocol_family(unsigned int protocol); +#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE +#define READBUFFER_MAX CURL_MAX_READ_SIZE +#define READBUFFER_MIN 1024 + +/* 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 + * bad things will happen. + */ +#if READBUFFER_SIZE < READBUFFER_MIN +# error READBUFFER_SIZE is too small +#endif + + /* * Protocol table. */ @@ -410,10 +424,7 @@ CURLcode Curl_close(struct Curl_easy *data) /* Destroy the timeout list that is held in the easy handle. It is /normally/ done by curl_multi_remove_handle() but this is "just in case" */ - if(data->state.timeoutlist) { - Curl_llist_destroy(data->state.timeoutlist, NULL); - data->state.timeoutlist = NULL; - } + Curl_llist_destroy(&data->state.timeoutlist, NULL); data->magic = 0; /* force a clear AFTER the possibly enforced removal from the multi handle, since that function uses the magic @@ -451,6 +462,7 @@ CURLcode Curl_close(struct Curl_easy *data) } data->change.url = NULL; + Curl_safefree(data->state.buffer); Curl_safefree(data->state.headerbuff); Curl_flush_cookies(data, 1); @@ -463,6 +475,7 @@ CURLcode Curl_close(struct Curl_easy *data) /* this destroys the channel and we cannot use it anymore after this */ Curl_resolver_cleanup(data->state.resolver); + Curl_http2_cleanup_dependencies(data); Curl_convert_close(data); /* No longer a dirty share, if it exists */ @@ -525,9 +538,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ /* Set the default size of the SSL session ID cache */ - set->ssl.max_ssl_sessions = 5; + set->general_ssl.max_ssl_sessions = 5; - set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */ + set->proxyport = 0; set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ set->httpauth = CURLAUTH_BASIC; /* defaults to basic */ set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ @@ -539,14 +552,16 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) * libcurl 7.10 introduced SSL verification *by default*! This needs to be * switched off unless wanted. */ - set->ssl.verifypeer = TRUE; - set->ssl.verifyhost = TRUE; + set->ssl.primary.verifypeer = TRUE; + set->ssl.primary.verifyhost = TRUE; #ifdef USE_TLS_SRP set->ssl.authtype = CURL_TLSAUTH_NONE; #endif set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth type */ - set->ssl.sessionid = TRUE; /* session ID caching enabled by default */ + set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by + default */ + set->proxy_ssl = set->ssl; set->new_file_perms = 0644; /* Default permissions */ set->new_directory_perms = 0755; /* Default permissions */ @@ -569,12 +584,20 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) /* This is our preferred CA cert bundle/path since install time */ #if defined(CURL_CA_BUNDLE) - result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE); + result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE); + if(result) + return result; + + result = setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE); if(result) return result; #endif #if defined(CURL_CA_PATH) - result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH); + result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH); + if(result) + return result; + + result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH); if(result) return result; #endif @@ -597,6 +620,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) set->expect_100_timeout = 1000L; /* Wait for a second by default. */ set->sep_headers = TRUE; /* separated header lists by default */ + set->buffer_size = READBUFFER_SIZE; Curl_http2_init_userset(set); return result; @@ -634,6 +658,12 @@ CURLcode Curl_open(struct Curl_easy **curl) /* We do some initial setup here, all those fields that can't be just 0 */ + data->state.buffer = malloc(READBUFFER_SIZE + 1); + if(!data->state.buffer) { + DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + data->state.headerbuff = malloc(HEADERSIZE); if(!data->state.headerbuff) { DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n")); @@ -646,14 +676,13 @@ CURLcode Curl_open(struct Curl_easy **curl) Curl_convert_init(data); + Curl_initinfo(data); + /* most recent connection is not yet defined */ data->state.lastconnect = NULL; data->progress.flags |= PGRS_HIDE; data->state.current_speed = -1; /* init to negative == impossible */ - - data->wildcard.state = CURLWC_INIT; - data->wildcard.filelist = NULL; data->set.fnmatch = ZERO_NULL; data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */ @@ -662,6 +691,7 @@ CURLcode Curl_open(struct Curl_easy **curl) if(result) { Curl_resolver_cleanup(data->state.resolver); + free(data->state.buffer); free(data->state.headerbuff); Curl_freeset(data); free(data); @@ -673,6 +703,9 @@ CURLcode Curl_open(struct Curl_easy **curl) return result; } +#define C_SSLVERSION_VALUE(x) (x & 0xffff) +#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000) + CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, va_list param) { @@ -694,7 +727,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; case CURLOPT_SSL_CIPHER_LIST: /* set a list of cipher we want to use in the SSL connection */ - result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], + result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection for proxy */ + result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY], va_arg(param, char *)); break; @@ -900,7 +938,22 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * implementations are lame. */ #ifdef USE_SSL - data->set.ssl.version = va_arg(param, long); + arg = va_arg(param, long); + data->set.ssl.primary.version = C_SSLVERSION_VALUE(arg); + data->set.ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg); +#else + result = CURLE_UNKNOWN_OPTION; +#endif + break; + case CURLOPT_PROXY_SSLVERSION: + /* + * Set explicit SSL version to try to connect with for proxy, as some SSL + * implementations are lame. + */ +#ifdef USE_SSL + arg = va_arg(param, long); + data->set.proxy_ssl.primary.version = C_SSLVERSION_VALUE(arg); + data->set.proxy_ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg); #else result = CURLE_UNKNOWN_OPTION; #endif @@ -970,8 +1023,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303 * other - POST is kept as POST after 301 and 302 */ - int postRedir = curlx_sltosi(va_arg(param, long)); - data->set.keep_post = postRedir & CURL_REDIR_POST_ALL; + arg = va_arg(param, long); + data->set.keep_post = arg & CURL_REDIR_POST_ALL; } break; @@ -1007,7 +1060,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) result = CURLE_OUT_OF_MEMORY; else { - char * p; + char *p; (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); @@ -1434,18 +1487,30 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, case CURLOPT_PROXY: /* - * Set proxy server:port to use as HTTP proxy. + * Set proxy server:port to use as proxy. * - * If the proxy is set to "" we explicitly say that we don't want to use a - * proxy (even though there might be environment variables saying so). + * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL) + * we explicitly say that we don't want to use a proxy + * (even though there might be environment variables saying so). * * Setting it to NULL, means no proxy but allows the environment variables - * to decide for us. + * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL). */ result = setstropt(&data->set.str[STRING_PROXY], va_arg(param, char *)); break; + case CURLOPT_PRE_PROXY: + /* + * Set proxy server:port to use as SOCKS proxy. + * + * If the proxy is set to "" or NULL we explicitly say that we don't want + * to use the socks proxy. + */ + result = setstropt(&data->set.str[STRING_PRE_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_PROXYTYPE: /* * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME @@ -1457,7 +1522,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * set transfer mode (;type=) when doing FTP via an HTTP proxy */ - switch (va_arg(param, long)) { + switch(va_arg(param, long)) { case 0: data->set.proxy_transfer_mode = FALSE; break; @@ -1910,35 +1975,70 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * String that holds file name of the SSL certificate to use */ - result = setstropt(&data->set.str[STRING_CERT], + result = setstropt(&data->set.str[STRING_CERT_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLCERT: + /* + * String that holds file name of the SSL certificate to use for proxy + */ + result = setstropt(&data->set.str[STRING_CERT_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLCERTTYPE: /* * String that holds file type of the SSL certificate to use */ - result = setstropt(&data->set.str[STRING_CERT_TYPE], + result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use for proxy + */ + result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLKEY: /* * String that holds file name of the SSL key to use */ - result = setstropt(&data->set.str[STRING_KEY], + result = setstropt(&data->set.str[STRING_KEY_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLKEY: + /* + * String that holds file name of the SSL key to use for proxy + */ + result = setstropt(&data->set.str[STRING_KEY_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLKEYTYPE: /* * String that holds file type of the SSL key to use */ - result = setstropt(&data->set.str[STRING_KEY_TYPE], + result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use for proxy + */ + result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], va_arg(param, char *)); break; case CURLOPT_KEYPASSWD: /* * String that holds the SSL or SSH private key password. */ - result = setstropt(&data->set.str[STRING_KEY_PASSWD], + result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_KEYPASSWD: + /* + * String that holds the SSL private key password for proxy. + */ + result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLENGINE: @@ -1975,13 +2075,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * Set what local port to bind the socket to when performing an operation. */ - data->set.localport = curlx_sltous(va_arg(param, long)); + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localport = curlx_sltous(arg); break; case CURLOPT_LOCALPORTRANGE: /* * Set number of local ports to try, starting with CURLOPT_LOCALPORT. */ - data->set.localportrange = curlx_sltosi(va_arg(param, long)); + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localportrange = curlx_sltosi(arg); break; case CURLOPT_KRBLEVEL: /* @@ -2001,7 +2107,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * Enable peer SSL verifying. */ - data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + case CURLOPT_PROXY_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying for proxy. + */ + data->set.proxy_ssl.primary.verifypeer = + (0 != va_arg(param, long))?TRUE:FALSE; break; case CURLOPT_SSL_VERIFYHOST: /* @@ -2019,7 +2133,25 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, return CURLE_BAD_FUNCTION_ARGUMENT; } - data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE; + data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE; + break; + case CURLOPT_PROXY_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate for proxy + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE; break; case CURLOPT_SSL_VERIFYSTATUS: /* @@ -2030,7 +2162,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; } - data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; case CURLOPT_SSL_CTX_FUNCTION: #ifdef have_curlssl_ssl_ctx @@ -2076,7 +2209,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * Set pinned public key for SSL connection. * Specify file name of the public key in DER format. */ - result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY], + result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG], + va_arg(param, char *)); +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_PROXY_PINNEDPUBLICKEY: +#ifdef have_curlssl_pinnedpubkey /* only by supported backends */ + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ + result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY], va_arg(param, char *)); #else result = CURLE_NOT_BUILT_IN; @@ -2086,7 +2231,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * Set CA info for SSL connection. Specify file name of the CA certificate */ - result = setstropt(&data->set.str[STRING_SSL_CAFILE], + result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CAINFO: + /* + * Set CA info SSL connection for proxy. Specify file name of the + * CA certificate + */ + result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], va_arg(param, char *)); break; case CURLOPT_CAPATH: @@ -2096,7 +2249,20 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * certificates which have been prepared using openssl c_rehash utility. */ /* This does not work on windows. */ - result = setstropt(&data->set.str[STRING_SSL_CAPATH], + result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG], + va_arg(param, char *)); +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_PROXY_CAPATH: +#ifdef have_curlssl_ca_path /* not supported by all backends */ + /* + * Set CA path info for SSL connection proxy. Specify directory name of the + * CA certificates which have been prepared using openssl c_rehash utility. + */ + /* This does not work on windows. */ + result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], va_arg(param, char *)); #else result = CURLE_NOT_BUILT_IN; @@ -2107,7 +2273,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * Set CRL file info for SSL connection. Specify file name of the CRL * to check certificates revocation */ - result = setstropt(&data->set.str[STRING_SSL_CRLFILE], + result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CRLFILE: + /* + * Set CRL file info for SSL connection for proxy. Specify file name of the + * CRL to check certificates revocation + */ + result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], va_arg(param, char *)); break; case CURLOPT_ISSUERCERT: @@ -2115,7 +2289,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * Set Issuer certificate file * to check certificates issuer */ - result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT], + result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG], va_arg(param, char *)); break; case CURLOPT_TELNETOPTIONS: @@ -2130,11 +2304,26 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * The application kindly asks for a differently sized receive buffer. * If it seems reasonable, we'll use it. */ - data->set.buffer_size = va_arg(param, long); + arg = va_arg(param, long); - if((data->set.buffer_size> (BUFSIZE -1)) || - (data->set.buffer_size < 1)) - data->set.buffer_size = 0; /* huge internal default */ + if(arg > READBUFFER_MAX) + arg = READBUFFER_MAX; + else if(arg < 1) + arg = READBUFFER_SIZE; + else if(arg < READBUFFER_MIN) + arg = READBUFFER_MIN; + + /* Resize if new size */ + if(arg != data->set.buffer_size) { + 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; @@ -2196,7 +2385,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, } #endif /* CURL_DISABLE_HTTP */ if(data->share->sslsession) { - data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions; + data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; data->state.session = data->share->sslsession; } Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); @@ -2231,8 +2420,14 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); - data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); - data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; + + case CURLOPT_PROXY_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); break; #endif @@ -2328,7 +2523,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; case CURLOPT_SSL_SESSIONID_CACHE: - data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ? + TRUE : FALSE; + data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid; break; #ifdef USE_LIBSSH2 @@ -2419,7 +2616,10 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * know that an unsigned int will always hold the value so we blindly * typecast to this type */ - data->set.scope_id = curlx_sltoui(va_arg(param, long)); + arg = va_arg(param, long); + if((arg < 0) || (arg > 0xf)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.scope_id = curlx_sltoui(arg); break; case CURLOPT_PROTOCOLS: @@ -2595,23 +2795,47 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; #ifdef USE_TLS_SRP case CURLOPT_TLSAUTH_USERNAME: - result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], + result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; + case CURLOPT_PROXY_TLSAUTH_USERNAME: + result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; case CURLOPT_TLSAUTH_PASSWORD: - result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], + result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; case CURLOPT_TLSAUTH_TYPE: - if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP"))) + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) data->set.ssl.authtype = CURL_TLSAUTH_SRP; else data->set.ssl.authtype = CURL_TLSAUTH_NONE; break; + case CURLOPT_PROXY_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE; + break; #endif case CURLOPT_DNS_SERVERS: result = Curl_set_dns_servers(data, va_arg(param, char *)); @@ -2651,6 +2875,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, #ifdef USE_UNIX_SOCKETS case CURLOPT_UNIX_SOCKET_PATH: + data->set.abstract_unix_socket = FALSE; + result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; + case CURLOPT_ABSTRACT_UNIX_SOCKET: + data->set.abstract_unix_socket = TRUE; result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], va_arg(param, char *)); break; @@ -2678,9 +2908,11 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, return CURLE_NOT_BUILT_IN; #else struct Curl_easy *dep = va_arg(param, struct Curl_easy *); - if(dep && GOOD_EASY_HANDLE(dep)) { - data->set.stream_depends_on = dep; - data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E); + if(!dep || GOOD_EASY_HANDLE(dep)) { + if(data->set.stream_depends_on) { + Curl_http2_remove_child(data->set.stream_depends_on, data); + } + Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E)); } break; #endif @@ -2688,6 +2920,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, case CURLOPT_CONNECT_TO: data->set.connect_to = va_arg(param, struct curl_slist *); break; + case CURLOPT_SUPPRESS_CONNECT_HEADERS: + data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE; + break; default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; @@ -2718,10 +2953,10 @@ static void conn_reset_postponed_data(struct connectdata *conn, int num) #endif /* DEBUGBUILD */ } else { - DEBUGASSERT (psnd->allocated_size == 0); - DEBUGASSERT (psnd->recv_size == 0); - DEBUGASSERT (psnd->recv_processed == 0); - DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD); + DEBUGASSERT(psnd->allocated_size == 0); + DEBUGASSERT(psnd->recv_size == 0); + DEBUGASSERT(psnd->recv_processed == 0); + DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD); } } @@ -2731,8 +2966,7 @@ static void conn_reset_all_postponed_data(struct connectdata *conn) conn_reset_postponed_data(conn, 1); } #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ -/* Use "do-nothing" macros instead of functions when workaround not used */ -#define conn_reset_postponed_data(c,n) do {} WHILE_FALSE +/* Use "do-nothing" macro instead of function when workaround not used */ #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ @@ -2768,8 +3002,10 @@ static void conn_free(struct connectdata *conn) Curl_safefree(conn->passwd); Curl_safefree(conn->oauth_bearer); Curl_safefree(conn->options); - Curl_safefree(conn->proxyuser); - Curl_safefree(conn->proxypasswd); + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); Curl_safefree(conn->allocptr.proxyuserpwd); Curl_safefree(conn->allocptr.uagent); Curl_safefree(conn->allocptr.userpwd); @@ -2783,19 +3019,24 @@ static void conn_free(struct connectdata *conn) Curl_safefree(conn->trailer); Curl_safefree(conn->host.rawalloc); /* host name buffer */ Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ - Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */ + Curl_safefree(conn->secondaryhostname); + Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ + Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ Curl_safefree(conn->master_buffer); + Curl_safefree(conn->connect_buffer); conn_reset_all_postponed_data(conn); - Curl_llist_destroy(conn->send_pipe, NULL); - Curl_llist_destroy(conn->recv_pipe, NULL); - - conn->send_pipe = NULL; - conn->recv_pipe = NULL; + Curl_llist_destroy(&conn->send_pipe, NULL); + Curl_llist_destroy(&conn->recv_pipe, NULL); Curl_safefree(conn->localdev); - Curl_free_ssl_config(&conn->ssl_config); + Curl_free_primary_ssl_config(&conn->ssl_config); + Curl_free_primary_ssl_config(&conn->proxy_ssl_config); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(conn->unix_domain_socket); +#endif free(conn); /* free all the connection oriented data */ } @@ -2827,9 +3068,9 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection) * are other users of it */ if(!conn->bits.close && - (conn->send_pipe->size + conn->recv_pipe->size)) { + (conn->send_pipe.size + conn->recv_pipe.size)) { DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n", - conn->send_pipe->size + conn->recv_pipe->size)); + conn->send_pipe.size + conn->recv_pipe.size)); return CURLE_OK; } @@ -2855,14 +3096,15 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection) free_fixed_hostname(&conn->host); free_fixed_hostname(&conn->conn_to_host); - free_fixed_hostname(&conn->proxy); + free_fixed_hostname(&conn->http_proxy.host); + free_fixed_hostname(&conn->socks_proxy.host); Curl_ssl_close(conn, FIRSTSOCKET); /* Indicate to all handles on the pipe that we're dead */ if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) { - signalPipeClose(conn->send_pipe, TRUE); - signalPipeClose(conn->recv_pipe, TRUE); + signalPipeClose(&conn->send_pipe, TRUE); + signalPipeClose(&conn->recv_pipe, TRUE); } conn_free(conn); @@ -2889,12 +3131,16 @@ static bool SocketIsDead(curl_socket_t sock) } /* - * IsPipeliningPossible() returns TRUE if the options set would allow - * pipelining/multiplexing and the connection is using a HTTP protocol. + * IsPipeliningPossible() + * + * Return a bitmask with the available pipelining and multiplexing options for + * the given requested connection. */ -static bool IsPipeliningPossible(const struct Curl_easy *handle, - const struct connectdata *conn) +static int IsPipeliningPossible(const struct Curl_easy *handle, + const struct connectdata *conn) { + int avail = 0; + /* If a HTTP protocol and pipelining is enabled */ if((conn->handler->protocol & PROTO_FAMILY_HTTP) && (!conn->bits.protoconnstart || !conn->bits.close)) { @@ -2904,14 +3150,14 @@ static bool IsPipeliningPossible(const struct Curl_easy *handle, (handle->set.httpreq == HTTPREQ_GET || handle->set.httpreq == HTTPREQ_HEAD)) /* didn't ask for HTTP/1.0 and a GET or HEAD */ - return TRUE; + avail |= CURLPIPE_HTTP1; if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) && (handle->set.httpversion >= CURL_HTTP_VERSION_2)) /* allows HTTP/2 */ - return TRUE; + avail |= CURLPIPE_MULTIPLEX; } - return FALSE; + return avail; } int Curl_removeHandleFromPipeline(struct Curl_easy *handle, @@ -2967,9 +3213,9 @@ void Curl_getoff_all_pipelines(struct Curl_easy *data, bool send_head = (conn->writechannel_inuse && Curl_sendpipe_head(data, conn)); - if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head) + if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head) Curl_pipeline_leave_read(conn); - if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head) + if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head) Curl_pipeline_leave_write(conn); } @@ -3014,8 +3260,8 @@ Curl_oldest_idle_connection(struct Curl_easy *data) struct curl_hash_iterator iter; struct curl_llist_element *curr; struct curl_hash_element *he; - long highscore=-1; - long score; + time_t highscore=-1; + time_t score; struct timeval now; struct connectdata *conn_candidate = NULL; struct connectbundle *bundle; @@ -3030,7 +3276,7 @@ Curl_oldest_idle_connection(struct Curl_easy *data) bundle = he->ptr; - curr = bundle->conn_list->head; + curr = bundle->conn_list.head; while(curr) { conn = curr->ptr; @@ -3052,6 +3298,19 @@ Curl_oldest_idle_connection(struct Curl_easy *data) return conn_candidate; } +static bool +proxy_info_matches(const struct proxy_info* data, + const struct proxy_info* needle) +{ + if((data->proxytype == needle->proxytype) && + (data->port == needle->port) && + Curl_safe_strcasecompare(data->host.name, needle->host.name)) + return TRUE; + + return FALSE; +} + + /* * This function finds the connection in the connection * bundle that has been unused for the longest time. @@ -3064,8 +3323,8 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data, struct connectbundle *bundle) { struct curl_llist_element *curr; - long highscore=-1; - long score; + time_t highscore=-1; + time_t score; struct timeval now; struct connectdata *conn_candidate = NULL; struct connectdata *conn; @@ -3074,7 +3333,7 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data, now = Curl_tvnow(); - curr = bundle->conn_list->head; + curr = bundle->conn_list.head; while(curr) { conn = curr->ptr; @@ -3102,7 +3361,7 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data, static bool disconnect_if_dead(struct connectdata *conn, struct Curl_easy *data) { - size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size; + size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size; if(!pipeLen && !conn->inuse) { /* The check for a dead socket makes sense only if there are no handles in pipeline and the connection isn't already marked in @@ -3147,7 +3406,7 @@ static int call_disconnect_if_dead(struct connectdata *conn, static void prune_dead_connections(struct Curl_easy *data) { struct timeval now = Curl_tvnow(); - long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup); + time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup); if(elapsed >= 1000L) { Curl_conncache_foreach(data->state.conn_cache, data, @@ -3185,7 +3444,7 @@ ConnectionExists(struct Curl_easy *data, struct connectdata *check; struct connectdata *chosen = 0; bool foundPendingCandidate = FALSE; - bool canPipeline = IsPipeliningPossible(data, needle); + int canpipe = IsPipeliningPossible(data, needle); struct connectbundle *bundle; #ifdef USE_NTLM @@ -3201,10 +3460,10 @@ ConnectionExists(struct Curl_easy *data, *force_reuse = FALSE; *waitpipe = FALSE; - /* We can't pipe if the site is blacklisted */ - if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) { - canPipeline = FALSE; - } + /* We can't pipeline if the site is blacklisted */ + if((canpipe & CURLPIPE_HTTP1) && + Curl_pipeline_site_blacklisted(data, needle)) + canpipe &= ~ CURLPIPE_HTTP1; /* Look up the bundle with all the connections to this particular host */ @@ -3215,22 +3474,17 @@ ConnectionExists(struct Curl_easy *data, max_pipeline_length(data->multi):0; size_t best_pipe_len = max_pipe_len; struct curl_llist_element *curr; - const char *hostname; - - if(needle->bits.conn_to_host) - hostname = needle->conn_to_host.name; - else - hostname = needle->host.name; infof(data, "Found bundle for host %s: %p [%s]\n", - hostname, (void *)bundle, - (bundle->multiuse== BUNDLE_PIPELINING? - "can pipeline": - (bundle->multiuse== BUNDLE_MULTIPLEX? - "can multiplex":"serially"))); - - /* We can't pipe if we don't know anything about the server */ - if(canPipeline) { + (needle->bits.conn_to_host ? needle->conn_to_host.name : + needle->host.name), (void *)bundle, + (bundle->multiuse == BUNDLE_PIPELINING ? + "can pipeline" : + (bundle->multiuse == BUNDLE_MULTIPLEX ? + "can multiplex" : "serially"))); + + /* We can't pipeline if we don't know anything about the server */ + if(canpipe) { if(bundle->multiuse <= BUNDLE_UNKNOWN) { if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) { infof(data, "Server doesn't support multi-use yet, wait\n"); @@ -3239,22 +3493,22 @@ ConnectionExists(struct Curl_easy *data, } infof(data, "Server doesn't support multi-use (yet)\n"); - canPipeline = FALSE; + canpipe = 0; } if((bundle->multiuse == BUNDLE_PIPELINING) && !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) { /* not asked for, switch off */ infof(data, "Could pipeline, but not asked to!\n"); - canPipeline = FALSE; + canpipe = 0; } else if((bundle->multiuse == BUNDLE_MULTIPLEX) && !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) { infof(data, "Could multiplex, but not asked to!\n"); - canPipeline = FALSE; + canpipe = 0; } } - curr = bundle->conn_list->head; + curr = bundle->conn_list.head; while(curr) { bool match = FALSE; size_t pipeLen; @@ -3269,22 +3523,23 @@ ConnectionExists(struct Curl_easy *data, if(disconnect_if_dead(check, data)) continue; - pipeLen = check->send_pipe->size + check->recv_pipe->size; + pipeLen = check->send_pipe.size + check->recv_pipe.size; - if(canPipeline) { + if(canpipe) { if(check->bits.protoconnstart && check->bits.close) continue; if(!check->bits.multiplex) { - /* If not multiplexing, make sure the pipe has only GET requests */ - struct Curl_easy* sh = gethandleathead(check->send_pipe); - struct Curl_easy* rh = gethandleathead(check->recv_pipe); + /* If not multiplexing, make sure the connection is fine for HTTP/1 + pipelining */ + struct Curl_easy* sh = gethandleathead(&check->send_pipe); + struct Curl_easy* rh = gethandleathead(&check->recv_pipe); if(sh) { - if(!IsPipeliningPossible(sh, check)) + if(!(IsPipeliningPossible(sh, check) & CURLPIPE_HTTP1)) continue; } else if(rh) { - if(!IsPipeliningPossible(rh, check)) + if(!(IsPipeliningPossible(rh, check) & CURLPIPE_HTTP1)) continue; } } @@ -3316,7 +3571,7 @@ ConnectionExists(struct Curl_easy *data, infof(data, "Connection #%ld isn't open enough, can't reuse\n", check->connection_id); #ifdef DEBUGBUILD - if(check->recv_pipe->size > 0) { + if(check->recv_pipe.size > 0) { infof(data, "BAD! Unconnected #%ld has a non-empty recv pipeline!\n", check->connection_id); @@ -3326,6 +3581,19 @@ ConnectionExists(struct Curl_easy *data, } } +#ifdef USE_UNIX_SOCKETS + if(needle->unix_domain_socket) { + if(!check->unix_domain_socket) + continue; + if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) + continue; + if(needle->abstract_unix_socket != check->abstract_unix_socket) + continue; + } + else if(check->unix_domain_socket) + continue; +#endif + if((needle->handler->flags&PROTOPT_SSL) != (check->handler->flags&PROTOPT_SSL)) /* don't do mixed SSL and non-SSL connections */ @@ -3334,23 +3602,12 @@ ConnectionExists(struct Curl_easy *data, /* except protocols that have been upgraded via TLS */ continue; - if(needle->handler->flags&PROTOPT_SSL) { - if((data->set.ssl.verifypeer != check->verifypeer) || - (data->set.ssl.verifyhost != check->verifyhost)) - continue; - } - - if(needle->bits.proxy != check->bits.proxy) - /* don't do mixed proxy and non-proxy connections */ + if(needle->bits.httpproxy != check->bits.httpproxy || + needle->bits.socksproxy != check->bits.socksproxy) continue; - if(needle->bits.proxy && - (needle->proxytype != check->proxytype || - needle->bits.httpproxy != check->bits.httpproxy || - needle->bits.tunnel_proxy != check->bits.tunnel_proxy || - !strcasecompare(needle->proxy.name, check->proxy.name) || - needle->port != check->port)) - /* don't mix connections that use different proxies */ + if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) continue; if(needle->bits.conn_to_host != check->bits.conn_to_host) @@ -3363,7 +3620,34 @@ ConnectionExists(struct Curl_easy *data, * connections that don't use this feature */ continue; - if(!canPipeline && check->inuse) + if(needle->bits.httpproxy) { + if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) + continue; + + if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) + continue; + + if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) { + /* use https proxy */ + if(needle->handler->flags&PROTOPT_SSL) { + /* use double layer ssl */ + if(!Curl_ssl_config_matches(&needle->proxy_ssl_config, + &check->proxy_ssl_config)) + continue; + if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + else { + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) + continue; + if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + } + } + + if(!canpipe && check->inuse) /* this request can't be pipelined but the checked connection is already in use so we skip it */ continue; @@ -3382,9 +3666,8 @@ ConnectionExists(struct Curl_easy *data, */ if((check->localport != needle->localport) || (check->localportrange != needle->localportrange) || - !check->localdev || - !needle->localdev || - strcmp(check->localdev, needle->localdev)) + (needle->localdev && + (!check->localdev || strcmp(check->localdev, needle->localdev)))) continue; } @@ -3399,10 +3682,11 @@ ConnectionExists(struct Curl_easy *data, } if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) || - (needle->bits.httpproxy && needle->bits.tunnel_proxy)) { + needle->bits.tunnel_proxy) { /* The requested connection does not use a HTTP proxy or it uses SSL or - it is a non-SSL protocol tunneled over the same HTTP proxy name and - port number */ + it is a non-SSL protocol tunneled or it is a non-SSL protocol which + is allowed to be upgraded via TLS */ + if((strcasecompare(needle->handler->scheme, check->handler->scheme) || (get_protocol_family(check->handler->protocol) == needle->handler->protocol && check->tls_upgraded)) && @@ -3426,7 +3710,7 @@ ConnectionExists(struct Curl_easy *data, check->connection_id)); continue; } - else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) { + if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) { foundPendingCandidate = TRUE; DEBUGF(infof(data, "Connection #%ld has not started SSL connect, " @@ -3463,12 +3747,13 @@ ConnectionExists(struct Curl_easy *data, /* Same for Proxy NTLM authentication */ if(wantProxyNTLMhttp) { - /* Both check->proxyuser and check->proxypasswd can be NULL */ - if(!check->proxyuser || !check->proxypasswd) + /* Both check->http_proxy.user and check->http_proxy.passwd can be + * NULL */ + if(!check->http_proxy.user || !check->http_proxy.passwd) continue; - if(strcmp(needle->proxyuser, check->proxyuser) || - strcmp(needle->proxypasswd, check->proxypasswd)) + if(strcmp(needle->http_proxy.user, check->http_proxy.user) || + strcmp(needle->http_proxy.passwd, check->http_proxy.passwd)) continue; } else if(check->proxyntlm.state != NTLMSTATE_NONE) { @@ -3493,7 +3778,7 @@ ConnectionExists(struct Curl_easy *data, continue; } #endif - if(canPipeline) { + if(canpipe) { /* We can pipeline if we want to. Let's continue looking for the optimal connection to use, i.e the shortest pipe that is not blacklisted. */ @@ -3572,51 +3857,50 @@ ConnectionExists(struct Curl_easy *data, Note: this function's sub-functions call failf() */ -CURLcode Curl_connected_proxy(struct connectdata *conn, - int sockindex) +CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex) { - if(!conn->bits.proxy || sockindex) - /* this magic only works for the primary socket as the secondary is used - for FTP only and it has FTP specific magic in ftp.c */ - return CURLE_OK; + CURLcode result = CURLE_OK; - switch(conn->proxytype) { + if(conn->bits.socksproxy) { #ifndef CURL_DISABLE_PROXY - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, - conn->bits.conn_to_host ? conn->conn_to_host.name : - conn->host.name, - conn->bits.conn_to_port ? conn->conn_to_port : - conn->remote_port, - FIRSTSOCKET, conn); - - case CURLPROXY_SOCKS4: - return Curl_SOCKS4(conn->proxyuser, - conn->bits.conn_to_host ? conn->conn_to_host.name : - conn->host.name, - conn->bits.conn_to_port ? conn->conn_to_port : - conn->remote_port, - FIRSTSOCKET, conn, FALSE); - - case CURLPROXY_SOCKS4A: - return Curl_SOCKS4(conn->proxyuser, - conn->bits.conn_to_host ? conn->conn_to_host.name : - conn->host.name, - conn->bits.conn_to_port ? conn->conn_to_port : - conn->remote_port, - FIRSTSOCKET, conn, TRUE); + /* for the secondary socket (FTP), use the "connect to host" + * but ignore the "connect to port" (use the secondary port) + */ + const char * const host = conn->bits.httpproxy ? + conn->http_proxy.host.name : + conn->bits.conn_to_host ? + conn->conn_to_host.name : + sockindex == SECONDARYSOCKET ? + conn->secondaryhostname : conn->host.name; + const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port : + sockindex == SECONDARYSOCKET ? conn->secondary_port : + conn->bits.conn_to_port ? conn->conn_to_port : + conn->remote_port; + conn->bits.socksproxy_connecting = TRUE; + 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); + break; + + case CURLPROXY_SOCKS4: + case CURLPROXY_SOCKS4A: + result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex, + conn); + break; + default: + failf(conn->data, "unknown proxytype option given"); + result = CURLE_COULDNT_CONNECT; + } /* switch proxytype */ + conn->bits.socksproxy_connecting = FALSE; +#else + (void)sockindex; #endif /* CURL_DISABLE_PROXY */ - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - break; - } /* switch proxytype */ + } - return CURLE_OK; + return result; } /* @@ -3627,7 +3911,10 @@ void Curl_verboseconnect(struct connectdata *conn) { if(conn->data->set.verbose) infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", - conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname, + conn->bits.socksproxy ? conn->socks_proxy.host.dispname : + conn->bits.httpproxy ? conn->http_proxy.host.dispname : + conn->bits.conn_to_host ? conn->conn_to_host.dispname : + conn->host.dispname, conn->ip_addr_str, conn->port, conn->connection_id); } #endif @@ -3717,10 +4004,14 @@ CURLcode Curl_protocol_connect(struct connectdata *conn, if(!conn->bits.protoconnstart) { - result = Curl_proxy_connect(conn); + result = Curl_proxy_connect(conn, FIRSTSOCKET); if(result) return result; + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + /* wait for HTTPS proxy SSL initialization to complete */ + return CURLE_OK; + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE)) /* when using an HTTP tunnel proxy, await complete tunnel establishment @@ -3746,11 +4037,11 @@ CURLcode Curl_protocol_connect(struct connectdata *conn, } /* - * Helpers for IDNA convertions. + * Helpers for IDNA conversions. */ static bool is_ASCII_name(const char *hostname) { - const unsigned char *ch = (const unsigned char*)hostname; + const unsigned char *ch = (const unsigned char *)hostname; while(*ch) { if(*ch++ & 0x80) @@ -3788,7 +4079,15 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host) #ifdef USE_LIBIDN2 if(idn2_check_version(IDN2_VERSION)) { char *ace_hostname = NULL; - int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, 0); +#if IDN2_VERSION_NUMBER >= 0x00140000 + /* IDN2_NFC_INPUT: Normalize input string using normalization form C. + IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional + processing. */ + int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL; +#else + int flags = IDN2_NFC_INPUT; +#endif + int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags); if(rc == IDN2_OK) { host->encalloc = (char *)ace_hostname; /* change the name pointer to point to the encoded hostname */ @@ -3862,7 +4161,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */ conn->connection_id = -1; /* no ID */ conn->port = -1; /* unknown at this point */ - conn->remote_port = -1; /* unknown */ + conn->remote_port = -1; /* unknown at this point */ #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD) conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */ conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */ @@ -3879,12 +4178,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->data = data; /* Setup the association between this connection and the Curl_easy */ - conn->proxytype = data->set.proxytype; /* type */ + conn->http_proxy.proxytype = data->set.proxytype; + conn->socks_proxy.proxytype = CURLPROXY_SOCKS4; #ifdef CURL_DISABLE_PROXY conn->bits.proxy = FALSE; conn->bits.httpproxy = FALSE; + conn->bits.socksproxy = FALSE; conn->bits.proxy_user_passwd = FALSE; conn->bits.tunnel_proxy = FALSE; @@ -3895,11 +4196,20 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->bits.proxy = (data->set.str[STRING_PROXY] && *data->set.str[STRING_PROXY]) ? TRUE : FALSE; conn->bits.httpproxy = (conn->bits.proxy && - (conn->proxytype == CURLPROXY_HTTP || - conn->proxytype == CURLPROXY_HTTP_1_0)) ? - TRUE : FALSE; - conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ? - TRUE : FALSE; + (conn->http_proxy.proxytype == CURLPROXY_HTTP || + conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 || + conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ? + TRUE : FALSE; + conn->bits.socksproxy = (conn->bits.proxy && + !conn->bits.httpproxy) ? TRUE : FALSE; + + if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) { + conn->bits.proxy = TRUE; + conn->bits.socksproxy = TRUE; + } + + conn->bits.proxy_user_passwd = + (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE; conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; #endif /* CURL_DISABLE_PROXY */ @@ -3908,8 +4218,13 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; - conn->verifypeer = data->set.ssl.verifypeer; - conn->verifyhost = data->set.ssl.verifyhost; + conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus; + conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; + conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; + conn->proxy_ssl_config.verifystatus = + data->set.proxy_ssl.primary.verifystatus; + conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; + conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; conn->ip_version = data->set.ipver; @@ -3924,16 +4239,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) && !conn->master_buffer) { /* Allocate master_buffer to be used for HTTP/1 pipelining */ - conn->master_buffer = calloc(BUFSIZE, sizeof (char)); + conn->master_buffer = calloc(MASTERBUF_SIZE, sizeof(char)); if(!conn->master_buffer) goto error; } /* Initialize the pipeline lists */ - conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); - conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); - if(!conn->send_pipe || !conn->recv_pipe) - goto error; + Curl_llist_init(&conn->send_pipe, (curl_llist_dtor) llist_dtor); + Curl_llist_init(&conn->recv_pipe, (curl_llist_dtor) llist_dtor); #ifdef HAVE_GSSAPI conn->data_prot = PROT_CLEAR; @@ -3956,11 +4269,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) return conn; error: - Curl_llist_destroy(conn->send_pipe, NULL); - Curl_llist_destroy(conn->recv_pipe, NULL); - - conn->send_pipe = NULL; - conn->recv_pipe = NULL; + Curl_llist_destroy(&conn->send_pipe, NULL); + Curl_llist_destroy(&conn->recv_pipe, NULL); free(conn->master_buffer); free(conn->localdev); @@ -4023,11 +4333,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, char *fragment; char *path = data->state.path; char *query; + int i; int rc; - char protobuf[16] = ""; const char *protop = ""; CURLcode result; bool rebuild_url = FALSE; + bool url_has_scheme = FALSE; + char protobuf[16]; *prot_missing = FALSE; @@ -4046,10 +4358,47 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, * proxy -- and we don't know if we will need to use SSL until we parse the * url ... ************************************************************/ - if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]", - protobuf, path)) && - strcasecompare(protobuf, "file")) { - if(path[0] == '/' && path[1] == '/') { + if(data->change.url[0] == ':') { + failf(data, "Bad URL, colon is first character"); + return CURLE_URL_MALFORMAT; + } + + /* Make sure we don't mistake a drive letter for a scheme, for example: + curld --proto-default file c:/foo/bar.txt */ + if((('a' <= data->change.url[0] && data->change.url[0] <= 'z') || + ('A' <= data->change.url[0] && data->change.url[0] <= 'Z')) && + data->change.url[1] == ':' && data->set.str[STRING_DEFAULT_PROTOCOL] && + strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file")) { + ; /* do nothing */ + } + else { /* check for a scheme */ + for(i = 0; i < 16 && data->change.url[i]; ++i) { + if(data->change.url[i] == '/') + break; + if(data->change.url[i] == ':') { + url_has_scheme = TRUE; + break; + } + } + } + + /* handle the file: scheme */ + if((url_has_scheme && strncasecompare(data->change.url, "file:", 5)) || + (!url_has_scheme && data->set.str[STRING_DEFAULT_PROTOCOL] && + strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file"))) { + bool path_has_drive = FALSE; + + if(url_has_scheme) + rc = sscanf(data->change.url, "%*15[^\n/:]:%[^\n]", path); + else + rc = sscanf(data->change.url, "%[^\n]", path); + + if(rc != 1) { + failf(data, "Bad URL"); + return CURLE_URL_MALFORMAT; + } + + if(url_has_scheme && path[0] == '/' && path[1] == '/') { /* Allow omitted hostname (e.g. file:/). This is not strictly * speaking a valid file: URL by RFC 1738, but treating file:/ as * file://localhost/ is similar to how other schemes treat missing @@ -4059,42 +4408,65 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, memory areas overlap! */ memmove(path, path + 2, strlen(path + 2)+1); } + + /* the path may start with a drive letter. for backwards compatibility + we skip some processing on those paths. */ + path_has_drive = (('a' <= path[0] && path[0] <= 'z') || + ('A' <= path[0] && path[0] <= 'Z')) && path[1] == ':'; + /* * we deal with file:/// differently since it supports no * hostname other than "localhost" and "127.0.0.1", which is unique among * the URL protocols specified in RFC 1738 */ - if(path[0] != '/') { - /* the URL included a host name, we ignore host names in file:// URLs - as the standards don't define what to do with them */ - char *ptr=strchr(path, '/'); - if(ptr) { - /* there was a slash present + if(path[0] != '/' && !path_has_drive) { + /* the URL includes a host name, it must match "localhost" or + "127.0.0.1" to be valid */ + char *ptr; + if(!checkprefix("localhost/", path) && + !checkprefix("127.0.0.1/", path)) { + failf(data, "Invalid file://hostname/, " + "expected localhost or 127.0.0.1 or none"); + return CURLE_URL_MALFORMAT; + } + ptr = &path[9]; /* now points to the slash after the host */ - RFC1738 (section 3.1, page 5) says: + /* there was a host name and slash present - The rest of the locator consists of data specific to the scheme, - and is known as the "url-path". It supplies the details of how the - specified resource can be accessed. Note that the "/" between the - host (or port) and the url-path is NOT part of the url-path. + RFC1738 (section 3.1, page 5) says: - As most agents use file://localhost/foo to get '/foo' although the - slash preceding foo is a separator and not a slash for the path, - a URL as file://localhost//foo must be valid as well, to refer to - the same file with an absolute path. - */ + The rest of the locator consists of data specific to the scheme, + and is known as the "url-path". It supplies the details of how the + specified resource can be accessed. Note that the "/" between the + host (or port) and the url-path is NOT part of the url-path. - if(ptr[1] && ('/' == ptr[1])) - /* if there was two slashes, we skip the first one as that is then - used truly as a separator */ - ptr++; + As most agents use file://localhost/foo to get '/foo' although the + slash preceding foo is a separator and not a slash for the path, + a URL as file://localhost//foo must be valid as well, to refer to + the same file with an absolute path. + */ - /* This cannot be made with strcpy, as the memory chunks overlap! */ - memmove(path, ptr, strlen(ptr)+1); - } + if('/' == ptr[1]) + /* if there was two slashes, we skip the first one as that is then + used truly as a separator */ + ptr++; + + /* This cannot be made with strcpy, as the memory chunks overlap! */ + memmove(path, ptr, strlen(ptr)+1); + + path_has_drive = (('a' <= path[0] && path[0] <= 'z') || + ('A' <= path[0] && path[0] <= 'Z')) && path[1] == ':'; + } + +#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__) + if(path_has_drive) { + failf(data, "File drive letters are only accepted in MSDOS/Windows."); + return CURLE_URL_MALFORMAT; } +#endif protop = "file"; /* protocol string */ + *prot_missing = !url_has_scheme; } else { /* clear path */ @@ -4102,7 +4474,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, path[0]=0; rc = sscanf(data->change.url, - "%15[^\n:]:%3[/]%[^\n/?#]%[^\n]", + "%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]", protobuf, slashbuf, conn->host.name, path); if(2 == rc) { failf(data, "Bad URL"); @@ -4258,14 +4630,30 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, size_t plen = strlen(path); /* new path, should be 1 byte longer than the original */ - size_t urllen = strlen(data->change.url); /* original URL length */ - size_t prefixlen = strlen(conn->host.name); - if(!*prot_missing) - prefixlen += strlen(protop) + strlen("://"); + if(!*prot_missing) { + size_t protolen = strlen(protop); + + if(curl_strnequal(protop, data->change.url, protolen)) + prefixlen += protolen; + else { + failf(data, " malformed"); + return CURLE_URL_MALFORMAT; + } + + if(curl_strnequal("://", &data->change.url[protolen], 3)) + prefixlen += 3; + /* only file: is allowed to omit one or both slashes */ + else if(curl_strnequal("file:", data->change.url, 5)) + prefixlen += 1 + (data->change.url[5] == '/'); + else { + failf(data, " malformed"); + return CURLE_URL_MALFORMAT; + } + } - reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */ + reurl = malloc(prefixlen + plen + 1); if(!reurl) return CURLE_OUT_OF_MEMORY; @@ -4287,6 +4675,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, data->change.url_alloc = TRUE; /* free this later */ } + result = findprotocol(data, conn, protop); + if(result) + return result; + /* * Parse the login details from the URL and strip them out of * the host name @@ -4373,8 +4765,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, * conn->host.name is B * data->state.path is /C */ - - return findprotocol(data, conn, protop); + return CURLE_OK; } /* @@ -4473,7 +4864,7 @@ void Curl_free_request_state(struct Curl_easy *data) * Checks if the host is in the noproxy list. returns true if it matches * and therefore the proxy should NOT be used. ****************************************************************/ -static bool check_noproxy(const char* name, const char* no_proxy) +static bool check_noproxy(const char *name, const char *no_proxy) { /* no_proxy=domain1.dom,host.domain2.dom * (a comma-separated list of hosts which should @@ -4482,7 +4873,7 @@ static bool check_noproxy(const char* name, const char* no_proxy) */ size_t tok_start; size_t tok_end; - const char* separator = ", "; + const char *separator = ", "; size_t no_proxy_len; size_t namelen; char *endptr; @@ -4543,6 +4934,7 @@ static bool check_noproxy(const char* name, const char* no_proxy) return FALSE; } +#ifndef CURL_DISABLE_HTTP /**************************************************************** * Detect what (if any) proxy to use. Remember that this selects a host * name and is not limited to HTTP proxies only. @@ -4552,7 +4944,6 @@ static char *detect_proxy(struct connectdata *conn) { char *proxy = NULL; -#ifndef CURL_DISABLE_HTTP /* If proxy was not specified, we check for default proxy environment * variables, to enable i.e Lynx compliance: * @@ -4570,65 +4961,50 @@ static char *detect_proxy(struct connectdata *conn) * For compatibility, the all-uppercase versions of these variables are * checked if the lowercase versions don't exist. */ - char *no_proxy=NULL; char proxy_env[128]; + const char *protop = conn->handler->scheme; + char *envp = proxy_env; + char *prox; - no_proxy=curl_getenv("no_proxy"); - if(!no_proxy) - no_proxy=curl_getenv("NO_PROXY"); - - if(!check_noproxy(conn->host.name, no_proxy)) { - /* It was not listed as without proxy */ - const char *protop = conn->handler->scheme; - char *envp = proxy_env; - char *prox; + /* Now, build _proxy and check for such a one to use */ + while(*protop) + *envp++ = (char)tolower((int)*protop++); - /* Now, build _proxy and check for such a one to use */ - while(*protop) - *envp++ = (char)tolower((int)*protop++); + /* append _proxy */ + strcpy(envp, "_proxy"); - /* append _proxy */ - strcpy(envp, "_proxy"); + /* read the protocol proxy: */ + prox=curl_getenv(proxy_env); - /* read the protocol proxy: */ + /* + * We don't try the uppercase version of HTTP_PROXY because of + * security reasons: + * + * When curl is used in a webserver application + * environment (cgi or php), this environment variable can + * be controlled by the web server user by setting the + * http header 'Proxy:' to some value. + * + * This can cause 'internal' http/ftp requests to be + * arbitrarily redirected by any external attacker. + */ + if(!prox && !strcasecompare("http_proxy", proxy_env)) { + /* There was no lowercase variable, try the uppercase version: */ + Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env)); prox=curl_getenv(proxy_env); + } - /* - * We don't try the uppercase version of HTTP_PROXY because of - * security reasons: - * - * When curl is used in a webserver application - * environment (cgi or php), this environment variable can - * be controlled by the web server user by setting the - * http header 'Proxy:' to some value. - * - * This can cause 'internal' http/ftp requests to be - * arbitrarily redirected by any external attacker. - */ - if(!prox && !strcasecompare("http_proxy", proxy_env)) { - /* There was no lowercase variable, try the uppercase version: */ - Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env)); - prox=curl_getenv(proxy_env); - } - - if(prox) - proxy = prox; /* use this */ - else { - proxy = curl_getenv("all_proxy"); /* default proxy to use */ - if(!proxy) - proxy=curl_getenv("ALL_PROXY"); - } - } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified - non-proxy */ - free(no_proxy); - -#else /* !CURL_DISABLE_HTTP */ - - (void)conn; -#endif /* CURL_DISABLE_HTTP */ + if(prox) + proxy = prox; /* use this */ + else { + proxy = curl_getenv("all_proxy"); /* default proxy to use */ + if(!proxy) + proxy=curl_getenv("ALL_PROXY"); + } return proxy; } +#endif /* CURL_DISABLE_HTTP */ /* * If this is supposed to use a proxy, we need to figure out the proxy @@ -4636,7 +5012,8 @@ static char *detect_proxy(struct connectdata *conn) * that may exist registered to the same proxy host. */ static CURLcode parse_proxy(struct Curl_easy *data, - struct connectdata *conn, char *proxy) + struct connectdata *conn, char *proxy, + curl_proxytype proxytype) { char *prox_portno; char *endofprot; @@ -4645,6 +5022,10 @@ static CURLcode parse_proxy(struct Curl_easy *data, char *proxyptr; char *portptr; char *atsign; + long port = -1; + char *proxyuser = NULL; + char *proxypasswd = NULL; + bool sockstype; /* We do the proxy host string parsing here. We want the host name and the * port name. Accept a protocol:// prefix @@ -4654,14 +5035,16 @@ static CURLcode parse_proxy(struct Curl_easy *data, endofprot = strstr(proxy, "://"); if(endofprot) { proxyptr = endofprot+3; - if(checkprefix("socks5h", proxy)) - conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME; + if(checkprefix("https", proxy)) + proxytype = CURLPROXY_HTTPS; + else if(checkprefix("socks5h", proxy)) + proxytype = CURLPROXY_SOCKS5_HOSTNAME; else if(checkprefix("socks5", proxy)) - conn->proxytype = CURLPROXY_SOCKS5; + proxytype = CURLPROXY_SOCKS5; else if(checkprefix("socks4a", proxy)) - conn->proxytype = CURLPROXY_SOCKS4A; + proxytype = CURLPROXY_SOCKS4A; else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy)) - conn->proxytype = CURLPROXY_SOCKS4; + proxytype = CURLPROXY_SOCKS4; else if(checkprefix("http:", proxy)) ; /* leave it as HTTP or HTTP/1.0 */ else { @@ -4673,54 +5056,28 @@ static CURLcode parse_proxy(struct Curl_easy *data, else proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */ +#ifndef HTTPS_PROXY_SUPPORT + if(proxytype == CURLPROXY_HTTPS) { + failf(data, "Unsupported proxy \'%s\'" + ", libcurl is built without the HTTPS-proxy support.", proxy); + return CURLE_NOT_BUILT_IN; + } +#endif + + sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME || + proxytype == CURLPROXY_SOCKS5 || + proxytype == CURLPROXY_SOCKS4A || + proxytype == CURLPROXY_SOCKS4; + /* Is there a username and password given in this proxy url? */ atsign = strchr(proxyptr, '@'); if(atsign) { - char *proxyuser = NULL; - char *proxypasswd = NULL; CURLcode result = parse_login_details(proxyptr, atsign - proxyptr, - &proxyuser, &proxypasswd, NULL); - if(!result) { - /* found user and password, rip them out. note that we are - unescaping them, as there is otherwise no way to have a - username or password with reserved characters like ':' in - them. */ - Curl_safefree(conn->proxyuser); - if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH) - result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, - FALSE); - else { - conn->proxyuser = strdup(""); - if(!conn->proxyuser) - result = CURLE_OUT_OF_MEMORY; - } - - if(!result) { - Curl_safefree(conn->proxypasswd); - if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH) - result = Curl_urldecode(data, proxypasswd, 0, - &conn->proxypasswd, NULL, FALSE); - else { - conn->proxypasswd = strdup(""); - if(!conn->proxypasswd) - result = CURLE_OUT_OF_MEMORY; - } - } - - if(!result) { - conn->bits.proxy_user_passwd = TRUE; /* enable it */ - atsign++; /* the right side of the @-letter */ - - proxyptr = atsign; /* now use this instead */ - } - } - - free(proxyuser); - free(proxypasswd); - + &proxyuser, &proxypasswd, NULL); if(result) return result; + proxyptr = atsign + 1; } /* start scanning for port number at this point */ @@ -4757,7 +5114,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, prox_portno = strchr(portptr, ':'); if(prox_portno) { char *endp = NULL; - long port = 0; + *prox_portno = 0x0; /* cut off number from host name */ prox_portno ++; /* now set the local port number */ @@ -4791,15 +5148,63 @@ static CURLcode parse_proxy(struct Curl_easy *data, if(data->set.proxyport) /* None given in the proxy string, then get the default one if it is given */ - conn->port = data->set.proxyport; + port = data->set.proxyport; + else { + if(proxytype == CURLPROXY_HTTPS) + port = CURL_DEFAULT_HTTPS_PROXY_PORT; + else + port = CURL_DEFAULT_PROXY_PORT; + } } - /* now, clone the cleaned proxy host name */ - conn->proxy.rawalloc = strdup(proxyptr); - conn->proxy.name = conn->proxy.rawalloc; + if(*proxyptr) { + struct proxy_info *proxyinfo = + sockstype ? &conn->socks_proxy : &conn->http_proxy; + proxyinfo->proxytype = proxytype; - if(!conn->proxy.rawalloc) - return CURLE_OUT_OF_MEMORY; + if(proxyuser) { + /* found user and password, rip them out. note that we are unescaping + them, as there is otherwise no way to have a username or password + with reserved characters like ':' in them. */ + Curl_safefree(proxyinfo->user); + proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL); + Curl_safefree(proxyuser); + + if(!proxyinfo->user) { + Curl_safefree(proxypasswd); + return CURLE_OUT_OF_MEMORY; + } + + Curl_safefree(proxyinfo->passwd); + if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH) + proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL); + else + proxyinfo->passwd = strdup(""); + Curl_safefree(proxypasswd); + + if(!proxyinfo->passwd) + return CURLE_OUT_OF_MEMORY; + + conn->bits.proxy_user_passwd = TRUE; /* enable it */ + } + + if(port >= 0) { + proxyinfo->port = port; + if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc) + conn->port = port; + } + + /* now, clone the cleaned proxy host name */ + Curl_safefree(proxyinfo->host.rawalloc); + proxyinfo->host.rawalloc = strdup(proxyptr); + proxyinfo->host.name = proxyinfo->host.rawalloc; + + if(!proxyinfo->host.rawalloc) + return CURLE_OUT_OF_MEMORY; + } + + Curl_safefree(proxyuser); + Curl_safefree(proxypasswd); return CURLE_OK; } @@ -4825,10 +5230,173 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data, proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ } - result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE); + result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL, + FALSE); if(!result) - result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL, - FALSE); + result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd, + NULL, FALSE); + return result; +} + +/* 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) +{ + 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 + *************************************************************/ + if(conn->bits.proxy_user_passwd) { + result = parse_proxy_auth(data, conn); + if(result) + goto out; + } + + /************************************************************* + * Detect what (if any) proxy to use + *************************************************************/ + if(data->set.str[STRING_PROXY]) { + proxy = strdup(data->set.str[STRING_PROXY]); + /* if global proxy is set, this is it */ + if(NULL == proxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + + if(data->set.str[STRING_PRE_PROXY]) { + socksproxy = strdup(data->set.str[STRING_PRE_PROXY]); + /* if global socks proxy is set, this is it */ + if(NULL == socksproxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + + no_proxy = curl_getenv("no_proxy"); + if(!no_proxy) + no_proxy = curl_getenv("NO_PROXY"); + + if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY]) || + (!data->set.str[STRING_NOPROXY] && + check_noproxy(conn->host.name, no_proxy))) { + Curl_safefree(proxy); + Curl_safefree(socksproxy); + } + else if(!proxy && !socksproxy) +#ifndef CURL_DISABLE_HTTP + /* if the host is not in the noproxy list, detect proxy. */ + proxy = detect_proxy(conn); +#else /* !CURL_DISABLE_HTTP */ + proxy = NULL; +#endif /* CURL_DISABLE_HTTP */ + + Curl_safefree(no_proxy); + +#ifdef USE_UNIX_SOCKETS + /* For the time being do not mix proxy and unix domain sockets. See #1274 */ + if(proxy && conn->unix_domain_socket) { + free(proxy); + proxy = NULL; + } +#endif + + if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { + free(proxy); /* Don't bother with an empty proxy string or if the + protocol doesn't work with network */ + proxy = NULL; + } + if(socksproxy && (!*socksproxy || + (conn->handler->flags & PROTOPT_NONETWORK))) { + free(socksproxy); /* Don't bother with an empty socks proxy string or if + the protocol doesn't work with network */ + socksproxy = NULL; + } + + /*********************************************************************** + * If this is supposed to use a proxy, we need to figure out the proxy host + * name, proxy type and port number, so that we can re-use an existing + * connection that may exist registered to the same proxy host. + ***********************************************************************/ + if(proxy || socksproxy) { + if(proxy) { + result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype); + Curl_safefree(proxy); /* parse_proxy copies the proxy string */ + if(result) + goto out; + } + + if(socksproxy) { + result = parse_proxy(data, conn, socksproxy, + conn->socks_proxy.proxytype); + /* parse_proxy copies the socks proxy string */ + Curl_safefree(socksproxy); + if(result) + goto out; + } + + if(conn->http_proxy.host.rawalloc) { +#ifdef CURL_DISABLE_HTTP + /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ + result = CURLE_UNSUPPORTED_PROTOCOL; + goto out; +#else + /* force this connection's protocol to become HTTP if not already + compatible - if it isn't tunneling through */ + if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) && + !conn->bits.tunnel_proxy) + conn->handler = &Curl_handler_http; + + conn->bits.httpproxy = TRUE; +#endif + } + else { + conn->bits.httpproxy = FALSE; /* not a HTTP proxy */ + conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */ + } + + if(conn->socks_proxy.host.rawalloc) { + if(!conn->http_proxy.host.rawalloc) { + /* once a socks proxy */ + if(!conn->socks_proxy.user) { + conn->socks_proxy.user = conn->http_proxy.user; + conn->http_proxy.user = NULL; + Curl_safefree(conn->socks_proxy.passwd); + conn->socks_proxy.passwd = conn->http_proxy.passwd; + conn->http_proxy.passwd = NULL; + } + } + conn->bits.socksproxy = TRUE; + } + else + conn->bits.socksproxy = FALSE; /* not a socks proxy */ + } + else { + conn->bits.socksproxy = FALSE; + conn->bits.httpproxy = FALSE; + } + conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy; + + if(!conn->bits.proxy) { + /* we aren't using the proxy after all... */ + conn->bits.proxy = FALSE; + conn->bits.httpproxy = FALSE; + conn->bits.socksproxy = FALSE; + conn->bits.proxy_user_passwd = FALSE; + conn->bits.tunnel_proxy = FALSE; + } + +out: + + free(socksproxy); + free(proxy); return result; } #endif /* CURL_DISABLE_PROXY */ @@ -4871,6 +5439,7 @@ static CURLcode parse_url_login(struct Curl_easy *data, DEBUGASSERT(!**user); DEBUGASSERT(!**passwd); DEBUGASSERT(!**options); + DEBUGASSERT(conn->handler); if(!ptr) goto out; @@ -4889,9 +5458,12 @@ static CURLcode parse_url_login(struct Curl_easy *data, if(data->set.use_netrc == CURL_NETRC_REQUIRED) goto out; - /* We could use the login information in the URL so extract it */ + /* We could use the login information in the URL so extract it. Only parse + options if the handler says we should. */ result = parse_login_details(login, ptr - login - 1, - &userp, &passwdp, &optionsp); + &userp, &passwdp, + (conn->handler->flags & PROTOPT_URLOPTIONS)? + &optionsp:NULL); if(result) goto out; @@ -5121,7 +5693,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data, } #endif - portptr = strrchr(conn->host.name, ':'); + portptr = strchr(conn->host.name, ':'); } if(data->set.use_port && data->state.allow_port) { @@ -5176,15 +5748,21 @@ static CURLcode parse_remote_port(struct Curl_easy *data, return CURLE_URL_MALFORMAT; } - else if(rest != &portptr[1]) { + if(rest[0]) { + failf(data, "Port number ended with '%c'", rest[0]); + return CURLE_URL_MALFORMAT; + } + + if(rest != &portptr[1]) { *portptr = '\0'; /* cut off the name there */ conn->remote_port = curlx_ultous(port); } - else + else { /* 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 and Chrome both do that. */ *portptr = '\0'; + } } /* only if remote_port was not already parsed off the URL we use the @@ -5313,6 +5891,10 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, char *portptr; int port = -1; +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) data; +#endif + *hostname_result = NULL; *port_result = -1; @@ -5404,6 +5986,9 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data, int host_match = FALSE; int port_match = FALSE; + *host_result = NULL; + *port_result = -1; + if(*ptr == ':') { /* an empty hostname always matches */ host_match = TRUE; @@ -5466,28 +6051,25 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, { CURLcode result = CURLE_OK; char *host = NULL; - int port = 0; + int port = -1; - while(conn_to_host && !host) { + while(conn_to_host && !host && port == -1) { result = parse_connect_to_string(data, conn, conn_to_host->data, &host, &port); if(result) return result; if(host && *host) { - bool ipv6host; conn->conn_to_host.rawalloc = host; conn->conn_to_host.name = host; conn->bits.conn_to_host = TRUE; - ipv6host = strchr(host, ':') != NULL; - infof(data, "Connecting to hostname: %s%s%s\n", - ipv6host ? "[" : "", host, ipv6host ? "]" : ""); + infof(data, "Connecting to hostname: %s\n", host); } else { /* no "connect to host" */ conn->bits.conn_to_host = FALSE; - free(host); + Curl_safefree(host); } if(port >= 0) { @@ -5498,6 +6080,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, else { /* no "connect to port" */ conn->bits.conn_to_port = FALSE; + port = -1; } conn_to_host = conn_to_host->next; @@ -5514,7 +6097,7 @@ static CURLcode resolve_server(struct Curl_easy *data, bool *async) { CURLcode result=CURLE_OK; - long timeout_ms = Curl_timeleft(data, NULL, TRUE); + time_t timeout_ms = Curl_timeleft(data, NULL, TRUE); /************************************************************* * Resolve the name of the server or proxy @@ -5531,32 +6114,37 @@ static CURLcode resolve_server(struct Curl_easy *data, struct Curl_dns_entry *hostaddr; #ifdef USE_UNIX_SOCKETS - if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + if(conn->unix_domain_socket) { /* Unix domain sockets are local. The host gets ignored, just use the * specified domain socket address. Do not cache "DNS entries". There is * no DNS involved and we already have the filesystem path available */ - const char *path = data->set.str[STRING_UNIX_SOCKET_PATH]; + const char *path = conn->unix_domain_socket; hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); if(!hostaddr) result = CURLE_OUT_OF_MEMORY; - else if((hostaddr->addr = Curl_unix2addr(path)) != NULL) - hostaddr->inuse++; else { - /* Long paths are not supported for now */ - if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) { - failf(data, "Unix socket path too long: '%s'", path); - result = CURLE_COULDNT_RESOLVE_HOST; + bool longpath = FALSE; + hostaddr->addr = Curl_unix2addr(path, &longpath, + conn->abstract_unix_socket); + if(hostaddr->addr) + hostaddr->inuse++; + else { + /* Long paths are not supported for now */ + if(longpath) { + failf(data, "Unix socket path too long: '%s'", path); + result = CURLE_COULDNT_RESOLVE_HOST; + } + else + result = CURLE_OUT_OF_MEMORY; + free(hostaddr); + hostaddr = NULL; } - else - result = CURLE_OUT_OF_MEMORY; - free(hostaddr); - hostaddr = NULL; } } else #endif - if(!conn->proxy.name || !*conn->proxy.name) { + if(!conn->bits.proxy) { struct hostname *connhost; if(conn->bits.conn_to_host) connhost = &conn->conn_to_host; @@ -5568,7 +6156,7 @@ static CURLcode resolve_server(struct Curl_easy *data, if(conn->bits.conn_to_port) conn->port = conn->conn_to_port; else - conn->port = conn->remote_port; /* it is the same port */ + conn->port = conn->remote_port; /* Resolve target host right on */ rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port, @@ -5588,8 +6176,11 @@ static CURLcode resolve_server(struct Curl_easy *data, else { /* This is a proxy that hasn't been resolved yet. */ + struct hostname * const host = conn->bits.socksproxy ? + &conn->socks_proxy.host : &conn->http_proxy.host; + /* resolve proxy */ - rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port, + rc = Curl_resolv_timeout(conn, host->name, (int)conn->port, &hostaddr, timeout_ms); if(rc == CURLRESOLV_PENDING) @@ -5599,7 +6190,7 @@ static CURLcode resolve_server(struct Curl_easy *data, result = CURLE_OPERATION_TIMEDOUT; else if(!hostaddr) { - failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname); + failf(data, "Couldn't resolve proxy '%s'", host->dispname); result = CURLE_COULDNT_RESOLVE_PROXY; /* don't return yet, we need to clean up the timeout first */ } @@ -5619,12 +6210,16 @@ static CURLcode resolve_server(struct Curl_easy *data, static void reuse_conn(struct connectdata *old_conn, struct connectdata *conn) { - free_fixed_hostname(&old_conn->proxy); - free(old_conn->proxy.rawalloc); + free_fixed_hostname(&old_conn->http_proxy.host); + free_fixed_hostname(&old_conn->socks_proxy.host); + + free(old_conn->http_proxy.host.rawalloc); + free(old_conn->socks_proxy.host.rawalloc); /* free the SSL config struct from this connection struct as this was allocated in vain and is targeted for destruction */ - Curl_free_ssl_config(&old_conn->ssl_config); + Curl_free_primary_ssl_config(&old_conn->ssl_config); + Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config); conn->data = old_conn->data; @@ -5644,12 +6239,18 @@ static void reuse_conn(struct connectdata *old_conn, conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd; if(conn->bits.proxy_user_passwd) { /* use the new proxy user name and proxy password though */ - Curl_safefree(conn->proxyuser); - Curl_safefree(conn->proxypasswd); - conn->proxyuser = old_conn->proxyuser; - conn->proxypasswd = old_conn->proxypasswd; - old_conn->proxyuser = NULL; - old_conn->proxypasswd = NULL; + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); + conn->http_proxy.user = old_conn->http_proxy.user; + conn->socks_proxy.user = old_conn->socks_proxy.user; + conn->http_proxy.passwd = old_conn->http_proxy.passwd; + conn->socks_proxy.passwd = old_conn->socks_proxy.passwd; + old_conn->http_proxy.user = NULL; + old_conn->socks_proxy.user = NULL; + old_conn->http_proxy.passwd = NULL; + old_conn->socks_proxy.passwd = NULL; } /* host can change, when doing keepalive with a proxy or if the case is @@ -5668,24 +6269,26 @@ static void reuse_conn(struct connectdata *old_conn, Curl_persistconninfo(conn); conn_reset_all_postponed_data(old_conn); /* free buffers */ - conn_reset_all_postponed_data(conn); /* reset unprocessed data */ /* re-use init */ conn->bits.reuse = TRUE; /* yes, we're re-using here */ Curl_safefree(old_conn->user); Curl_safefree(old_conn->passwd); - Curl_safefree(old_conn->proxyuser); - Curl_safefree(old_conn->proxypasswd); + Curl_safefree(old_conn->http_proxy.user); + Curl_safefree(old_conn->socks_proxy.user); + Curl_safefree(old_conn->http_proxy.passwd); + Curl_safefree(old_conn->socks_proxy.passwd); Curl_safefree(old_conn->localdev); - Curl_llist_destroy(old_conn->send_pipe, NULL); - Curl_llist_destroy(old_conn->recv_pipe, NULL); - - old_conn->send_pipe = NULL; - old_conn->recv_pipe = NULL; + Curl_llist_destroy(&old_conn->send_pipe, NULL); + Curl_llist_destroy(&old_conn->recv_pipe, NULL); Curl_safefree(old_conn->master_buffer); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(old_conn->unix_domain_socket); +#endif } /** @@ -5716,7 +6319,6 @@ static CURLcode create_conn(struct Curl_easy *data, char *passwd = NULL; char *options = NULL; bool reuse; - char *proxy = NULL; bool prot_missing = FALSE; bool connections_available = TRUE; bool force_reuse = FALSE; @@ -5860,95 +6462,24 @@ static CURLcode create_conn(struct Curl_easy *data, } } -#ifndef CURL_DISABLE_PROXY - /************************************************************* - * Extract the user and password from the authentication string - *************************************************************/ - if(conn->bits.proxy_user_passwd) { - result = parse_proxy_auth(data, conn); - if(result) - goto out; - } - - /************************************************************* - * Detect what (if any) proxy to use - *************************************************************/ - if(data->set.str[STRING_PROXY]) { - proxy = strdup(data->set.str[STRING_PROXY]); - /* if global proxy is set, this is it */ - if(NULL == proxy) { - failf(data, "memory shortage"); +#ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); + if(conn->unix_domain_socket == NULL) { result = CURLE_OUT_OF_MEMORY; goto out; } - } - - if(data->set.str[STRING_NOPROXY] && - check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) { - free(proxy); /* proxy is in exception list */ - proxy = NULL; - } - else if(!proxy) - proxy = detect_proxy(conn); - -#ifdef USE_UNIX_SOCKETS - if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) { - free(proxy); /* Unix domain sockets cannot be proxied, so disable it */ - proxy = NULL; + conn->abstract_unix_socket = data->set.abstract_unix_socket; } #endif - if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { - free(proxy); /* Don't bother with an empty proxy string or if the - protocol doesn't work with network */ - proxy = NULL; - } - - /*********************************************************************** - * If this is supposed to use a proxy, we need to figure out the proxy host - * name, proxy type and port number, so that we can re-use an existing - * connection that may exist registered to the same proxy host. - ***********************************************************************/ - if(proxy) { - result = parse_proxy(data, conn, proxy); - - free(proxy); /* parse_proxy copies the proxy string */ - proxy = NULL; - - if(result) - goto out; - - if((conn->proxytype == CURLPROXY_HTTP) || - (conn->proxytype == CURLPROXY_HTTP_1_0)) { -#ifdef CURL_DISABLE_HTTP - /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ - result = CURLE_UNSUPPORTED_PROTOCOL; - goto out; -#else - /* force this connection's protocol to become HTTP if not already - compatible - if it isn't tunneling through */ - if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) && - !conn->bits.tunnel_proxy) - conn->handler = &Curl_handler_http; - - conn->bits.httpproxy = TRUE; + /* 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); + if(result) + goto out; #endif - } - else { - conn->bits.httpproxy = FALSE; /* not a HTTP proxy */ - conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */ - } - conn->bits.proxy = TRUE; - } - else { - /* we aren't using the proxy after all... */ - conn->bits.proxy = FALSE; - conn->bits.httpproxy = FALSE; - conn->bits.proxy_user_passwd = FALSE; - conn->bits.tunnel_proxy = FALSE; - } - -#endif /* CURL_DISABLE_PROXY */ /************************************************************* * If the protocol is using SSL and HTTP proxy is used, we set @@ -5987,12 +6518,14 @@ static CURLcode create_conn(struct Curl_easy *data, fix_hostname(conn, &conn->host); if(conn->bits.conn_to_host) fix_hostname(conn, &conn->conn_to_host); - if(conn->proxy.name && *conn->proxy.name) - fix_hostname(conn, &conn->proxy); + if(conn->bits.httpproxy) + fix_hostname(conn, &conn->http_proxy.host); + if(conn->bits.socksproxy) + fix_hostname(conn, &conn->socks_proxy.host); /************************************************************* * Check whether the host and the "connect to host" are equal. - * Do this after the hostnames have been IDN-fixed . + * Do this after the hostnames have been IDN-fixed. *************************************************************/ if(conn->bits.conn_to_host && strcasecompare(conn->conn_to_host.name, conn->host.name)) { @@ -6079,20 +6612,51 @@ static CURLcode create_conn(struct Curl_easy *data, that will be freed as part of the Curl_easy struct, but all cloned copies will be separately allocated. */ - data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH]; - data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE]; - data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE]; - data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; - data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; - data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; - data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; - data->set.ssl.clientcert = data->set.str[STRING_CERT]; + data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG]; + data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; + data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG]; + data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.proxy_ssl.primary.random_file = + data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_ORIG]; + data->set.proxy_ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; + + data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG]; + data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; + data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG]; + data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; + data->set.ssl.cert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY]; + data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG]; + data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; + data->set.ssl.key = data->set.str[STRING_KEY_ORIG]; + data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; + data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; + data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG]; + data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; + data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; #ifdef USE_TLS_SRP - data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME]; - data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG]; + data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG]; + data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; #endif - if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) { + if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, + &conn->ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary, + &conn->proxy_ssl_config)) { result = CURLE_OUT_OF_MEMORY; goto out; } @@ -6117,7 +6681,7 @@ static CURLcode create_conn(struct Curl_easy *data, /* If we found a reusable connection, we may still want to open a new connection if we are pipelining. */ if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) { - size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size; + size_t pipelen = conn_temp->send_pipe.size + conn_temp->recv_pipe.size; if(pipelen > 0) { infof(data, "Found connection %ld, with requests in the pipe (%zu)\n", conn_temp->connection_id, pipelen); @@ -6149,7 +6713,9 @@ static CURLcode create_conn(struct Curl_easy *data, infof(data, "Re-using existing connection! (#%ld) with %s %s\n", conn->connection_id, conn->bits.proxy?"proxy":"host", - conn->proxy.name?conn->proxy.dispname:conn->host.dispname); + conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname : + conn->http_proxy.host.name ? conn->http_proxy.host.dispname : + conn->host.dispname); } else { /* We have decided that we want a new connection. However, we may not @@ -6275,12 +6841,11 @@ static CURLcode create_conn(struct Curl_easy *data, *************************************************************/ result = resolve_server(data, conn, async); - out: +out: free(options); free(passwd); free(user); - free(proxy); return result; } @@ -6384,7 +6949,7 @@ CURLcode Curl_connect(struct Curl_easy *data, if(!result) { /* no error */ - if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size) + if((*in_connect)->send_pipe.size || (*in_connect)->recv_pipe.size) /* pipelining */ *protocol_done = TRUE; else if(!*asyncp) { @@ -6449,7 +7014,6 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) k->bytecount = 0; k->buf = data->state.buffer; - k->uploadbuf = data->state.uploadbuffer; k->hbufp = data->state.headerbuff; k->ignorebody=FALSE; @@ -6473,7 +7037,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) * Returns the family as a single bit protocol identifier. */ -unsigned int get_protocol_family(unsigned int protocol) +static unsigned int get_protocol_family(unsigned int protocol) { unsigned int family; diff --git a/Utilities/cmcurl/lib/url.h b/Utilities/cmcurl/lib/url.h index 90d9db3c3..f13c8e664 100644 --- a/Utilities/cmcurl/lib/url.h +++ b/Utilities/cmcurl/lib/url.h @@ -67,6 +67,8 @@ void Curl_getoff_all_pipelines(struct Curl_easy *data, void Curl_close_connections(struct Curl_easy *data); #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ +#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless + specified */ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); @@ -76,5 +78,16 @@ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); void Curl_verboseconnect(struct connectdata *conn); #endif +#define CONNECT_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[sockindex]) + +#define CONNECT_FIRSTSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[FIRSTSOCKET]) + +#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[SECONDARYSOCKET]) #endif /* HEADER_CURL_URL_H */ diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h index 7c7bf1ba0..d4a4a98dc 100644 --- a/Utilities/cmcurl/lib/urldata.h +++ b/Utilities/cmcurl/lib/urldata.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -136,8 +136,10 @@ #undef realloc #endif /* USE_AXTLS */ -#ifdef USE_SCHANNEL +#if defined(USE_SCHANNEL) || defined(USE_WINDOWS_SSPI) #include "curl_sspi.h" +#endif +#ifdef USE_SCHANNEL #include #include #endif @@ -198,9 +200,12 @@ #include #endif /* HAVE_LIBSSH2_H */ -/* Download buffer size, keep it fairly big for speed reasons */ -#undef BUFSIZE -#define BUFSIZE CURL_MAX_WRITE_SIZE +/* The 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 */ +#define UPLOAD_BUFSIZE CURL_MAX_WRITE_SIZE + +/* The "master buffer" is for HTTP pipelining */ +#define MASTERBUF_SIZE 16384 /* Initial size of the buffer to store headers in, it'll be enlarged in case of need. */ @@ -311,11 +316,13 @@ struct ssl_connect_data { PRFileDesc *handle; char *client_nickname; struct Curl_easy *data; - struct curl_llist *obj_list; + struct curl_llist obj_list; PK11GenericObject *obj_clicert; #elif defined(USE_GSKIT) gsk_handle handle; int iocport; + int localfd; + int remotefd; #elif defined(USE_AXTLS) SSL_CTX* ssl_ctx; SSL* ssl; @@ -326,6 +333,11 @@ struct ssl_connect_data { size_t encdata_length, decdata_length; size_t encdata_offset, decdata_offset; unsigned char *encdata_buffer, *decdata_buffer; + /* encdata_is_incomplete: if encdata contains only a partial record that + can't be decrypted without another Curl_read_plain (that is, status is + SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes + more bytes into encdata then set this back to false. */ + bool encdata_is_incomplete; unsigned long req_flags, ret_flags; CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */ bool recv_sspi_close_notify; /* true if connection closed by close_notify */ @@ -341,28 +353,40 @@ struct ssl_connect_data { #endif }; -struct ssl_config_data { +struct ssl_primary_config { long version; /* what version the client wants to use */ - long certverifyresult; /* result from the certificate verification */ - + long version_max; /* max supported version the client wants to use*/ bool verifypeer; /* set TRUE if this is desired */ bool verifyhost; /* set TRUE if CN/SAN must match hostname */ bool verifystatus; /* set TRUE if certificate status must be checked */ char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ - const char *CRLfile; /* CRL to check certificate revocation */ - const char *issuercert;/* optional issuer certificate filename */ char *clientcert; char *random_file; /* path to file containing "random" data */ char *egdsocket; /* path to file containing the EGD daemon socket */ char *cipher_list; /* list of ciphers to use */ - size_t max_ssl_sessions; /* SSL session id cache size */ + bool sessionid; /* cache session IDs or not */ +}; + +struct ssl_config_data { + struct ssl_primary_config primary; + bool enable_beast; /* especially allow this flaw for interoperability's + sake*/ + bool no_revoke; /* disable SSL certificate revocation checks */ + long certverifyresult; /* result from the certificate verification */ + char *CRLfile; /* CRL to check certificate revocation */ + char *issuercert;/* optional issuer certificate filename */ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ void *fsslctxp; /* parameter for call back */ - bool sessionid; /* cache session IDs or not */ bool certinfo; /* gather lots of certificate info */ bool falsestart; + char *cert; /* client certificate file name */ + char *cert_type; /* format for certificate (default: PEM)*/ + char *key; /* private key file name */ + char *key_type; /* format for private key (default: PEM) */ + char *key_passwd; /* plain text private key password */ + #ifdef USE_TLS_SRP char *username; /* TLS username (for, e.g., SRP) */ char *password; /* TLS password (for, e.g., SRP) */ @@ -370,6 +394,10 @@ struct ssl_config_data { #endif }; +struct ssl_general_config { + size_t max_ssl_sessions; /* SSL session id cache size */ +}; + /* information stored about one single SSL session */ struct curl_ssl_session { char *name; /* host name for which this ID was used */ @@ -380,7 +408,7 @@ struct curl_ssl_session { long age; /* just a number, the higher the more recent */ int remote_port; /* remote port */ int conn_to_port; /* remote port for the connection (may be -1) */ - struct ssl_config_data ssl_config; /* setup for this session */ + struct ssl_primary_config ssl_config; /* setup for this session */ }; /* Struct used for Digest challenge-response authentication */ @@ -388,6 +416,7 @@ struct digestdata { #if defined(USE_WINDOWS_SSPI) BYTE *input_token; size_t input_token_len; + CtxtHandle *http_context; #else char *nonce; char *cnonce; @@ -451,7 +480,7 @@ struct ntlmdata { #else unsigned int flags; unsigned char nonce[8]; - void* target_info; /* TargetInfo received in the ntlm type-2 message */ + void *target_info; /* TargetInfo received in the ntlm type-2 message */ unsigned int target_info_len; #endif }; @@ -497,6 +526,7 @@ struct ConnectBits { that overrides the port in the URL (remote port) */ bool proxy; /* if set, this transfer is done through a proxy - any type */ bool httpproxy; /* if set, this transfer is done through a http proxy */ + bool socksproxy; /* if set, this transfer is done through a socks proxy */ bool user_passwd; /* do we use user+password for this connection? */ bool proxy_user_passwd; /* user+password for the proxy? */ bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6 @@ -531,6 +561,7 @@ struct ConnectBits { bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out EPRT doesn't work we disable it for the forthcoming requests */ + bool ftp_use_data_ssl; /* Enabled SSL for the data connection */ bool netrc; /* name+password provided by netrc */ bool userpwd_in_url; /* name+password found in url */ bool stream_was_rewound; /* Indicates that the stream was rewound after a @@ -547,6 +578,9 @@ struct ConnectBits { bool tcp_fastopen; /* use TCP Fast Open */ bool tls_enable_npn; /* TLS NPN extension? */ bool tls_enable_alpn; /* TLS ALPN extension? */ + bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy + is complete */ + bool socksproxy_connecting; /* connecting through a socks proxy */ }; struct hostname { @@ -687,7 +721,6 @@ struct SingleRequest { long bodywrites; char *buf; - char *uploadbuf; curl_socket_t maxfd; int keepon; @@ -732,7 +765,7 @@ struct SingleRequest { */ struct Curl_handler { - const char * scheme; /* URL scheme name. */ + const char *scheme; /* URL scheme name. */ /* Complement to setup_connection_internals(). */ CURLcode (*setup_connection)(struct connectdata *); @@ -820,6 +853,8 @@ struct Curl_handler { request instead of per connection */ #define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */ #define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */ +#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field + of the URL */ /* return the count of bytes sent, or -1 on error */ typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ @@ -849,6 +884,14 @@ struct postponed_data { }; #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ +struct proxy_info { + struct hostname host; + long port; + curl_proxytype proxytype; /* what kind of proxy that is in use */ + char *user; /* proxy user name string, allocated */ + char *passwd; /* proxy password string, allocated */ +}; + /* * The connectdata struct contains all fields and variables that should be * unique for an entire connection. @@ -859,6 +902,8 @@ struct connectdata { connection is used! */ struct Curl_easy *data; + 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 and a HTTP proxy may in fact respond using chunked encoding */ @@ -898,14 +943,19 @@ struct connectdata { int socktype; /* SOCK_STREAM or SOCK_DGRAM */ struct hostname host; + char *secondaryhostname; /* secondary socket host name (ftp) */ struct hostname conn_to_host; /* the host to connect to. valid only if bits.conn_to_host is set */ - struct hostname proxy; + + struct proxy_info socks_proxy; + struct proxy_info http_proxy; long port; /* which port to use locally */ int remote_port; /* the remote port, not the proxy port! */ int conn_to_port; /* the remote port to connect to. valid only if bits.conn_to_port is set */ + unsigned short secondary_port; /* secondary socket remote port to connect to + (ftp) */ /* 'primary_ip' and 'primary_port' get filled with peer's numerical ip address and port number whenever an outgoing connection is @@ -930,10 +980,6 @@ struct connectdata { char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */ - char *proxyuser; /* proxy user name string, allocated */ - char *proxypasswd; /* proxy password string, allocated */ - curl_proxytype proxytype; /* what kind of proxy that is in use */ - int httpversion; /* the HTTP version*10 reported by the server */ int rtspversion; /* the RTSP version*10 reported by the server */ @@ -951,7 +997,9 @@ struct connectdata { struct postponed_data postponed[2]; /* two buffers for two sockets */ #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ - struct ssl_config_data ssl_config; + struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */ + struct ssl_primary_config ssl_config; + struct ssl_primary_config proxy_ssl_config; bool tls_upgraded; struct ConnectBits bits; /* various state-flags for this connection */ @@ -962,8 +1010,8 @@ struct connectdata { struct timeval connecttime; /* The two fields below get set in Curl_connecthost */ int num_addr; /* number of addresses to try to connect to */ - long timeoutms_per_addr; /* how long time in milliseconds to spend on - trying to connect to each IP address */ + time_t timeoutms_per_addr; /* how long time in milliseconds to spend on + trying to connect to each IP address */ const struct Curl_handler *handler; /* Connection's protocol handler */ const struct Curl_handler *given; /* The protocol first given */ @@ -1016,11 +1064,11 @@ struct connectdata { handle */ bool writechannel_inuse; /* whether the write channel is in use by an easy handle */ - struct curl_llist *send_pipe; /* List of handles waiting to - send on this pipeline */ - struct curl_llist *recv_pipe; /* List of handles waiting to read - their responses on this pipeline */ - char* master_buffer; /* The master buffer allocated on-demand; + struct curl_llist send_pipe; /* List of handles waiting to send on this + pipeline */ + struct curl_llist recv_pipe; /* List of handles waiting to read their + responses on this pipeline */ + char *master_buffer; /* The master buffer allocated on-demand; used for pipelining. */ size_t read_pos; /* Current read position in the master buffer */ size_t buf_len; /* Length of the buffer?? */ @@ -1041,8 +1089,8 @@ struct connectdata { /* used for communication with Samba's winbind daemon helper ntlm_auth */ curl_socket_t ntlm_auth_hlpr_socket; pid_t ntlm_auth_hlpr_pid; - char* challenge_header; - char* response_header; + char *challenge_header; + char *response_header; #endif #endif @@ -1078,9 +1126,6 @@ struct connectdata { int socks5_gssapi_enctype; #endif - bool verifypeer; - bool verifyhost; - /* 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 @@ -1099,13 +1144,19 @@ struct connectdata { struct connectbundle *bundle; /* The bundle we are member of */ int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ + char *connect_buffer; /* for CONNECT business */ + +#ifdef USE_UNIX_SOCKETS + char *unix_domain_socket; + bool abstract_unix_socket; +#endif }; /* The end of connectdata. */ /* * Struct to keep statistical and informational data. - * All variables in this struct must be reset in Curl_initinfo(). + * All variables in this struct must be initialized/reset in Curl_initinfo(). */ struct PureInfo { int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */ @@ -1139,6 +1190,9 @@ struct PureInfo { char conn_local_ip[MAX_IPADR_LEN]; long conn_local_port; + const char *conn_scheme; + unsigned int conn_protocol; + struct curl_certinfo certs; /* info about the certs, only populated in OpenSSL builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ @@ -1146,8 +1200,8 @@ struct PureInfo { struct Progress { - long lastshow; /* time() of the last displayed progress meter or NULL to - force redraw at next call */ + time_t lastshow; /* time() of the last displayed progress meter or NULL to + force redraw at next call */ curl_off_t size_dl; /* total expected size */ curl_off_t size_ul; /* total expected size */ curl_off_t downloaded; /* transferred so far */ @@ -1236,12 +1290,54 @@ struct auth { this resource */ bool done; /* TRUE when the auth phase is done and ready to do the *actual* request */ - bool multi; /* TRUE if this is not yet authenticated but within the auth - multipass negotiation */ + bool multipass; /* TRUE if this is not yet authenticated but within the + auth multipass negotiation */ bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should be RFC compliant */ }; +struct Curl_http2_dep { + struct Curl_http2_dep *next; + struct Curl_easy *data; +}; + +/* + * This struct is for holding data that was attemped to get sent to the user's + * callback but is held due to pausing. One instance per type (BOTH, HEADER, + * BODY). + */ +struct tempbuf { + char *buf; /* allocated buffer to keep data in when a write callback + returns to make the connection paused */ + size_t len; /* size of the 'tempwrite' allocated buffer */ + int type; /* type of the 'tempwrite' buffer as a bitmask that is used with + Curl_client_write() */ +}; + +/* Timers */ +typedef enum { + EXPIRE_100_TIMEOUT, + EXPIRE_ASYNC_NAME, + EXPIRE_CONNECTTIMEOUT, + EXPIRE_DNS_PER_NAME, + EXPIRE_HAPPY_EYEBALLS, + EXPIRE_MULTI_PENDING, + EXPIRE_RUN_NOW, + EXPIRE_SPEEDCHECK, + EXPIRE_TIMEOUT, + EXPIRE_TOOFAST, + EXPIRE_LAST /* not an actual timer, used as a marker only */ +} expire_id; + +/* + * One instance for each timeout an easy handle can set. + */ +struct time_node { + struct curl_llist_element list; + struct timeval time; + expire_id eid; +}; + struct UrlState { /* Points to the connection cache */ @@ -1260,9 +1356,9 @@ struct UrlState { char *headerbuff; /* allocated buffer to store headers in */ size_t headersize; /* size of the allocation */ - char buffer[BUFSIZE+1]; /* download buffer */ - char uploadbuffer[BUFSIZE+1]; /* upload buffer */ - curl_off_t current_speed; /* the ProgressShow() funcion sets this, + char *buffer; /* download buffer */ + char uploadbuffer[UPLOAD_BUFSIZE+1]; /* upload buffer */ + curl_off_t current_speed; /* the ProgressShow() function sets this, bytes / second */ bool this_is_a_follow; /* this is a followed Location: request */ @@ -1275,12 +1371,9 @@ struct UrlState { int first_remote_port; /* remote port of the first (not followed) request */ struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ long sessionage; /* number of the most recent session */ - char *tempwrite; /* allocated buffer to keep data in when a write - callback returns to make the connection paused */ - size_t tempwritesize; /* size of the 'tempwrite' allocated buffer */ - int tempwritetype; /* type of the 'tempwrite' buffer as a bitmask that is - used with Curl_client_write() */ - char *scratch; /* huge buffer[BUFSIZE*2] when doing upload CRLF replacing */ + 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 */ bool errorbuf; /* Set to TRUE if the error buffer is already filled in. This must be set to FALSE every time _easy_perform() is called. */ @@ -1312,7 +1405,8 @@ struct UrlState { #endif /* USE_OPENSSL */ struct timeval 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 */ char *most_recent_ftp_entrypath; @@ -1402,8 +1496,10 @@ struct DynamicStatic { struct Curl_multi; /* declared and used only in multi.c */ enum dupstring { - STRING_CERT, /* client certificate file name */ - STRING_CERT_TYPE, /* format for certificate (default: PEM)*/ + STRING_CERT_ORIG, /* client certificate file name */ + STRING_CERT_PROXY, /* client certificate file name */ + STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/ + STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/ STRING_COOKIE, /* HTTP cookie string to send */ STRING_COOKIEJAR, /* dump all cookies to this file */ STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */ @@ -1413,25 +1509,35 @@ enum dupstring { STRING_FTP_ACCOUNT, /* ftp account data */ STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ STRING_FTPPORT, /* port to send with the FTP PORT command */ - STRING_KEY, /* private key file name */ - STRING_KEY_PASSWD, /* plain text private key password */ - STRING_KEY_TYPE, /* format for private key (default: PEM) */ + STRING_KEY_ORIG, /* private key file name */ + STRING_KEY_PROXY, /* private key file name */ + STRING_KEY_PASSWD_ORIG, /* plain text private key password */ + STRING_KEY_PASSWD_PROXY, /* plain text private key password */ + STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */ + STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */ STRING_KRB_LEVEL, /* krb security level */ STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find $HOME/.netrc */ STRING_PROXY, /* proxy to use */ + STRING_PRE_PROXY, /* pre socks proxy to use */ STRING_SET_RANGE, /* range, if used */ STRING_SET_REFERER, /* custom string for the HTTP referer field */ STRING_SET_URL, /* what original URL to work on */ - STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */ - STRING_SSL_CAFILE, /* certificate file to verify peer against */ - STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */ - STRING_SSL_CIPHER_LIST, /* list of ciphers to use */ + STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */ + STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ + STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */ + STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */ STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ STRING_USERAGENT, /* User-Agent string */ - STRING_SSL_CRLFILE, /* crl file to check certificate */ - STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ + STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */ + STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */ + STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */ + STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */ STRING_USERNAME, /* , if used */ STRING_PASSWORD, /* , if used */ STRING_OPTIONS, /* , if used */ @@ -1459,8 +1565,10 @@ enum dupstring { STRING_MAIL_AUTH, #ifdef USE_TLS_SRP - STRING_TLSAUTH_USERNAME, /* TLS auth */ - STRING_TLSAUTH_PASSWORD, /* TLS auth */ + STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth */ + STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth */ #endif STRING_BEARER, /* , if used */ #ifdef USE_UNIX_SOCKETS @@ -1524,10 +1632,10 @@ struct UserDefined { curl_opensocket_callback fopensocket; /* function for checking/translating the address and opening the socket */ - void* opensocket_client; + void *opensocket_client; curl_closesocket_callback fclosesocket; /* function for closing the socket */ - void* closesocket_client; + void *closesocket_client; void *seek_client; /* pointer to pass to the seek callback */ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ @@ -1578,6 +1686,8 @@ struct UserDefined { 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 */ + struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ + 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 */ @@ -1642,9 +1752,6 @@ struct UserDefined { bool ftp_skip_ip; /* skip the IP address the FTP server passes on to us */ bool connect_only; /* make connection, let application use the socket */ - bool ssl_enable_beast; /* especially allow this flaw for interoperability's - sake*/ - bool ssl_no_revoke; /* disable SSL certificate revocation checks */ long ssh_auth_types; /* allowed SSH auth types */ bool http_te_skip; /* pass the raw body data to the user, even when transfer-encoded (chunked, compressed) */ @@ -1691,10 +1798,16 @@ struct UserDefined { bool pipewait; /* wait for pipe/multiplex status before starting a new connection */ long expect_100_timeout; /* in milliseconds */ + bool suppress_connect_headers; /* suppress proxy CONNECT response headers + from user callbacks */ struct Curl_easy *stream_depends_on; bool stream_depends_e; /* set or don't set the Exclusive bit */ int stream_weight; + + struct Curl_http2_dep *stream_dependents; + + bool abstract_unix_socket; }; struct Names { @@ -1723,6 +1836,8 @@ struct Curl_easy { struct Curl_easy *prev; struct connectdata *easy_conn; /* the "unit's" connection */ + struct curl_llist_element connect_queue; + struct curl_llist_element pipeline_queue; CURLMstate mstate; /* the handle's state */ CURLcode result; /* previous result */ diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c index 6df419a64..a761ae784 100644 --- a/Utilities/cmcurl/lib/vauth/cleartext.c +++ b/Utilities/cmcurl/lib/vauth/cleartext.c @@ -66,16 +66,27 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, char *plainauth; size_t ulen; size_t plen; + size_t plainlen; + *outlen = 0; + *outptr = NULL; ulen = strlen(userp); plen = strlen(passwdp); - plainauth = malloc(2 * ulen + plen + 2); - if(!plainauth) { - *outlen = 0; - *outptr = NULL; + /* Compute binary message length, checking for overflows. */ + plainlen = 2 * ulen; + if(plainlen < ulen) + return CURLE_OUT_OF_MEMORY; + plainlen += plen; + if(plainlen < plen) + return CURLE_OUT_OF_MEMORY; + plainlen += 2; + if(plainlen < 2) + return CURLE_OUT_OF_MEMORY; + + plainauth = malloc(plainlen); + if(!plainauth) return CURLE_OUT_OF_MEMORY; - } /* Calculate the reply */ memcpy(plainauth, userp, ulen); @@ -85,8 +96,7 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, memcpy(plainauth + 2 * ulen + 2, passwdp, plen); /* Base64 encode the reply */ - result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr, - outlen); + result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen); free(plainauth); return result; diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c index 0a11a308d..185098ed6 100644 --- a/Utilities/cmcurl/lib/vauth/digest.c +++ b/Utilities/cmcurl/lib/vauth/digest.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -40,6 +40,7 @@ #include "strcase.h" #include "non-ascii.h" /* included for Curl_convert_... prototypes */ #include "curl_printf.h" +#include "rand.h" /* The last #include files should be: */ #include "curl_memory.h" @@ -59,7 +60,7 @@ what ultimately goes over the network. */ #define CURL_OUTPUT_DIGEST_CONV(a, b) \ - result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \ + result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \ if(result) { \ free(b); \ return result; \ @@ -204,7 +205,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value) { char *tmp; char *token; - char *tok_buf; + char *tok_buf = NULL; /* Initialise the output */ *value = 0; @@ -236,7 +237,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value) * auth_decode_digest_md5_message() * * This is used internally to decode an already encoded DIGEST-MD5 challenge - * message into the seperate attributes. + * message into the separate attributes. * * Parameters: * @@ -359,13 +360,12 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, char qop_options[64]; int qop_values; char cnonce[33]; - unsigned int entropy[4]; char nonceCount[] = "00000001"; char method[] = "AUTHENTICATE"; char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; char *spn = NULL; - /* Decode the challange message */ + /* Decode the challenge message */ result = auth_decode_digest_md5_message(chlg64, nonce, sizeof(nonce), realm, sizeof(realm), algorithm, sizeof(algorithm), @@ -386,15 +386,10 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) return CURLE_BAD_CONTENT_ENCODING; - /* Generate 16 bytes of random data */ - entropy[0] = Curl_rand(data); - entropy[1] = Curl_rand(data); - entropy[2] = Curl_rand(data); - entropy[3] = Curl_rand(data); - - /* Convert the random data into a 32 byte hex string */ - snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x", - entropy[0], entropy[1], entropy[2], entropy[3]); + /* Generate 32 random hex chars, 32 bytes + 1 zero termination */ + result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce)); + if(result) + return result; /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); @@ -502,7 +497,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* * Curl_auth_decode_digest_http_message() * - * This is used to decode a HTTP DIGEST challenge message into the seperate + * This is used to decode a HTTP DIGEST challenge message into the separate * attributes. * * Parameters: @@ -563,7 +558,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, return CURLE_OUT_OF_MEMORY; } else if(strcasecompare(value, "qop")) { - char *tok_buf; + char *tok_buf = NULL; /* Tokenize the list and choose auth if possible, use a temporary clone of the buffer since strtok_r() ruins it */ tmp = strdup(content); @@ -684,9 +679,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, digest->nc = 1; if(!digest->cnonce) { - snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x", - Curl_rand(data), Curl_rand(data), - Curl_rand(data), Curl_rand(data)); + result = Curl_rand_hex(data, (unsigned char *)cnoncebuf, + sizeof(cnoncebuf)); + if(result) + return result; result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce, &cnonce_sz); diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c index 29526fc64..0bd94442d 100644 --- a/Utilities/cmcurl/lib/vauth/digest_sspi.c +++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014 - 2016, Steve Holme, . - * Copyright (C) 2015, Daniel Stenberg, , et al. + * Copyright (C) 2015 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -320,7 +320,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg, /* * Curl_auth_decode_digest_http_message() * - * This is used to decode a HTTP DIGEST challenge message into the seperate + * This is used to decode a HTTP DIGEST challenge message into the separate * attributes. * * Parameters: @@ -335,13 +335,44 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, { size_t chlglen = strlen(chlg); - /* We had an input token before and we got another one now. This means we - provided bad credentials in the previous request. */ - if(digest->input_token) - return CURLE_BAD_CONTENT_ENCODING; + /* We had an input token before so if there's another one now that means we + provided bad credentials in the previous request or it's stale. */ + if(digest->input_token) { + bool stale = false; + const char *p = chlg; + + /* Check for the 'stale' directive */ + for(;;) { + char value[DIGEST_MAX_VALUE_LENGTH]; + char content[DIGEST_MAX_CONTENT_LENGTH]; + + while(*p && ISSPACE(*p)) + p++; + + if(!Curl_auth_digest_get_pair(p, value, content, &p)) + break; + + if(Curl_strcasecompare(value, "stale") + && Curl_strcasecompare(content, "true")) { + stale = true; + break; + } + + while(*p && ISSPACE(*p)) + p++; + + if(',' == *p) + p++; + } + + if(stale) + Curl_auth_digest_cleanup(digest); + else + return CURLE_LOGIN_DENIED; + } - /* Simply store the challenge for use later */ - digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen); + /* Store the challenge for use later */ + digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen + 1); if(!digest->input_token) return CURLE_OUT_OF_MEMORY; @@ -379,21 +410,13 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, char **outptr, size_t *outlen) { size_t token_max; - CredHandle credentials; - CtxtHandle context; char *resp; BYTE *output_token; + size_t output_token_len = 0; PSecPkgInfo SecurityPackage; - SEC_WINNT_AUTH_IDENTITY identity; - SEC_WINNT_AUTH_IDENTITY *p_identity; - SecBuffer chlg_buf[3]; - SecBuffer resp_buf; + SecBuffer chlg_buf[5]; SecBufferDesc chlg_desc; - SecBufferDesc resp_desc; SECURITY_STATUS status; - unsigned long attrs; - TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ - TCHAR *spn; (void) data; @@ -408,123 +431,168 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, /* Release the package buffer as it is not required anymore */ s_pSecFn->FreeContextBuffer(SecurityPackage); - if(userp && *userp) { - /* Populate our identity structure */ - if(Curl_create_sspi_identity(userp, passwdp, &identity)) - return CURLE_OUT_OF_MEMORY; - - /* Populate our identity domain */ - if(Curl_override_sspi_http_realm((const char*) digest->input_token, - &identity)) - return CURLE_OUT_OF_MEMORY; + /* Allocate the output buffer according to the max token size as indicated + by the security package */ + output_token = malloc(token_max); + if(!output_token) { + return CURLE_OUT_OF_MEMORY; + } - /* Allow proper cleanup of the identity structure */ - p_identity = &identity; + if(digest->http_context) { + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 5; + chlg_desc.pBuffers = chlg_buf; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = NULL; + chlg_buf[0].cbBuffer = 0; + chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[1].pvBuffer = (void *) request; + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[2].pvBuffer = (void *) uripath; + chlg_buf[2].cbBuffer = curlx_uztoul(strlen((const char *) uripath)); + chlg_buf[3].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[3].pvBuffer = NULL; + chlg_buf[3].cbBuffer = 0; + chlg_buf[4].BufferType = SECBUFFER_PADDING; + chlg_buf[4].pvBuffer = output_token; + chlg_buf[4].cbBuffer = curlx_uztoul(token_max); + + status = s_pSecFn->MakeSignature(digest->http_context, 0, &chlg_desc, 0); + if(status == SEC_E_OK) + output_token_len = chlg_buf[4].cbBuffer; + else { /* delete the context so a new one can be made */ + infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx\n", + (long)status); + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } } - else - /* Use the current Windows user */ - p_identity = NULL; - /* Acquire our credentials handle */ - status = s_pSecFn->AcquireCredentialsHandle(NULL, - (TCHAR *) TEXT(SP_NAME_DIGEST), - SECPKG_CRED_OUTBOUND, NULL, - p_identity, NULL, NULL, - &credentials, &expiry); - if(status != SEC_E_OK) { - Curl_sspi_free_identity(p_identity); + if(!digest->http_context) { + CredHandle credentials; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + SecBuffer resp_buf; + SecBufferDesc resp_desc; + unsigned long attrs; + TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */ + TCHAR *spn; + + if(userp && *userp) { + /* Populate our identity structure */ + if(Curl_create_sspi_identity(userp, passwdp, &identity)) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } - return CURLE_LOGIN_DENIED; - } + /* Populate our identity domain */ + if(Curl_override_sspi_http_realm((const char *) digest->input_token, + &identity)) { + free(output_token); + return CURLE_OUT_OF_MEMORY; + } - /* Allocate the output buffer according to the max token size as indicated - by the security package */ - output_token = malloc(token_max); - if(!output_token) { - s_pSecFn->FreeCredentialsHandle(&credentials); + /* Allow proper cleanup of the identity structure */ + p_identity = &identity; + } + else + /* Use the current Windows user */ + p_identity = NULL; + + /* Acquire our credentials handle */ + status = s_pSecFn->AcquireCredentialsHandle(NULL, + (TCHAR *) TEXT(SP_NAME_DIGEST), + SECPKG_CRED_OUTBOUND, NULL, + p_identity, NULL, NULL, + &credentials, &expiry); + if(status != SEC_E_OK) { + Curl_sspi_free_identity(p_identity); + free(output_token); - Curl_sspi_free_identity(p_identity); + return CURLE_LOGIN_DENIED; + } - return CURLE_OUT_OF_MEMORY; - } + /* Setup the challenge "input" security buffer if present */ + chlg_desc.ulVersion = SECBUFFER_VERSION; + chlg_desc.cBuffers = 3; + chlg_desc.pBuffers = chlg_buf; + chlg_buf[0].BufferType = SECBUFFER_TOKEN; + chlg_buf[0].pvBuffer = digest->input_token; + chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len); + chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[1].pvBuffer = (void *) request; + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; + chlg_buf[2].pvBuffer = NULL; + chlg_buf[2].cbBuffer = 0; + + /* Setup the response "output" security buffer */ + resp_desc.ulVersion = SECBUFFER_VERSION; + resp_desc.cBuffers = 1; + resp_desc.pBuffers = &resp_buf; + resp_buf.BufferType = SECBUFFER_TOKEN; + resp_buf.pvBuffer = output_token; + resp_buf.cbBuffer = curlx_uztoul(token_max); + + spn = Curl_convert_UTF8_to_tchar((char *) uripath); + if(!spn) { + s_pSecFn->FreeCredentialsHandle(&credentials); + + Curl_sspi_free_identity(p_identity); + free(output_token); - /* Setup the challenge "input" security buffer if present */ - chlg_desc.ulVersion = SECBUFFER_VERSION; - chlg_desc.cBuffers = 3; - chlg_desc.pBuffers = chlg_buf; - chlg_buf[0].BufferType = SECBUFFER_TOKEN; - chlg_buf[0].pvBuffer = digest->input_token; - chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len); - chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; - chlg_buf[1].pvBuffer = (void *) request; - chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); - chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; - chlg_buf[2].pvBuffer = NULL; - chlg_buf[2].cbBuffer = 0; + return CURLE_OUT_OF_MEMORY; + } - /* Setup the response "output" security buffer */ - resp_desc.ulVersion = SECBUFFER_VERSION; - resp_desc.cBuffers = 1; - resp_desc.pBuffers = &resp_buf; - resp_buf.BufferType = SECBUFFER_TOKEN; - resp_buf.pvBuffer = output_token; - resp_buf.cbBuffer = curlx_uztoul(token_max); + /* Allocate our new context handle */ + digest->http_context = calloc(1, sizeof(CtxtHandle)); + if(!digest->http_context) + return CURLE_OUT_OF_MEMORY; - spn = Curl_convert_UTF8_to_tchar((char *) uripath); - if(!spn) { - s_pSecFn->FreeCredentialsHandle(&credentials); + /* Generate our response message */ + status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, + spn, + ISC_REQ_USE_HTTP_STYLE, 0, 0, + &chlg_desc, 0, + digest->http_context, + &resp_desc, &attrs, &expiry); + Curl_unicodefree(spn); + + if(status == SEC_I_COMPLETE_NEEDED || + status == SEC_I_COMPLETE_AND_CONTINUE) + s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); + else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { + s_pSecFn->FreeCredentialsHandle(&credentials); + + Curl_sspi_free_identity(p_identity); + free(output_token); - Curl_sspi_free_identity(p_identity); - free(output_token); + Curl_safefree(digest->http_context); - return CURLE_OUT_OF_MEMORY; - } + return CURLE_OUT_OF_MEMORY; + } - /* Generate our reponse message */ - status = s_pSecFn->InitializeSecurityContext(&credentials, NULL, - spn, - ISC_REQ_USE_HTTP_STYLE, 0, 0, - &chlg_desc, 0, &context, - &resp_desc, &attrs, &expiry); - Curl_unicodefree(spn); + output_token_len = resp_buf.cbBuffer; - if(status == SEC_I_COMPLETE_NEEDED || - status == SEC_I_COMPLETE_AND_CONTINUE) - s_pSecFn->CompleteAuthToken(&credentials, &resp_desc); - else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { s_pSecFn->FreeCredentialsHandle(&credentials); - Curl_sspi_free_identity(p_identity); - free(output_token); - - return CURLE_OUT_OF_MEMORY; } - resp = malloc(resp_buf.cbBuffer + 1); + resp = malloc(output_token_len + 1); if(!resp) { - s_pSecFn->DeleteSecurityContext(&context); - s_pSecFn->FreeCredentialsHandle(&credentials); - - Curl_sspi_free_identity(p_identity); free(output_token); return CURLE_OUT_OF_MEMORY; } - /* Copy the generated reponse */ - memcpy(resp, resp_buf.pvBuffer, resp_buf.cbBuffer); - resp[resp_buf.cbBuffer] = 0x00; + /* Copy the generated response */ + memcpy(resp, output_token, output_token_len); + resp[output_token_len] = 0; /* Return the response */ *outptr = resp; - *outlen = resp_buf.cbBuffer; - - /* Free our handles */ - s_pSecFn->DeleteSecurityContext(&context); - s_pSecFn->FreeCredentialsHandle(&credentials); - - /* Free the identity structure */ - Curl_sspi_free_identity(p_identity); + *outlen = output_token_len; /* Free the response buffer */ free(output_token); @@ -549,6 +617,12 @@ void Curl_auth_digest_cleanup(struct digestdata *digest) /* Reset any variables */ digest->input_token_len = 0; + + /* Delete security context */ + if(digest->http_context) { + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); + } } #endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */ diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c index c754fae45..560ecc5bc 100644 --- a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c +++ b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2016, Steve Holme, . + * Copyright (C) 2014 - 2017, Steve Holme, . * Copyright (C) 2015, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which @@ -68,7 +68,7 @@ bool Curl_auth_is_gssapi_supported(void) * passdwp [in] - The user's password. * service [in] - The service type such as http, smtp, pop or imap. * host [in[ - The host name. - * mutual_auth [in] - Flag specifing whether or not mutual authentication + * mutual_auth [in] - Flag specifying whether or not mutual authentication * is enabled. * chlg64 [in] - Pointer to the optional base64 encoded challenge * message. diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c index 151794e61..1b4cef486 100644 --- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c +++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2014 - 2016, Steve Holme, . + * Copyright (C) 2014 - 2017, Steve Holme, . * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -74,7 +74,7 @@ bool Curl_auth_is_gssapi_supported(void) * passdwp [in] - The user's password. * service [in] - The service type such as http, smtp, pop or imap. * host [in] - The host name. - * mutual_auth [in] - Flag specifing whether or not mutual authentication + * mutual_auth [in] - Flag specifying whether or not mutual authentication * is enabled. * chlg64 [in] - The optional base64 encoded challenge message. * krb5 [in/out] - The Kerberos 5 data struct being used and modified. diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c index b484a011a..42196455f 100644 --- a/Utilities/cmcurl/lib/vauth/ntlm.c +++ b/Utilities/cmcurl/lib/vauth/ntlm.c @@ -27,7 +27,7 @@ /* * NTLM details: * - * http://davenport.sourceforge.net/ntlm.html + * https://davenport.sourceforge.io/ntlm.html * https://www.innovation.ch/java/ntlm.html */ @@ -41,7 +41,7 @@ #include "curl_gethostname.h" #include "curl_multibyte.h" #include "warnless.h" - +#include "rand.h" #include "vtls/vtls.h" #ifdef USE_NSS @@ -394,7 +394,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(const char *userp, /* Clean up any former leftovers and initialise to defaults */ Curl_auth_ntlm_cleanup(ntlm); -#if USE_NTRESPONSES && USE_NTLM2SESSION +#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY #else #define NTLM2FLAG 0 @@ -509,7 +509,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, unsigned char ntlmbuf[NTLM_BUFSIZE]; int lmrespoff; unsigned char lmresp[24]; /* fixed-size */ -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES int ntrespoff; unsigned int ntresplen = 24; unsigned char ntresp[24]; /* fixed-size */ @@ -552,14 +552,15 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, hostlen = strlen(host); } -#if USE_NTRESPONSES && USE_NTLM_V2 +#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2) if(ntlm->target_info_len) { unsigned char ntbuffer[0x18]; - unsigned int entropy[2]; + unsigned char entropy[8]; unsigned char ntlmv2hash[0x18]; - entropy[0] = Curl_rand(data); - entropy[1] = Curl_rand(data); + result = Curl_rand(data, entropy, 8); + if(result) + return result; result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(result) @@ -571,15 +572,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, return result; /* LMv2 response */ - result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, - (unsigned char *)&entropy[0], + result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, &ntlm->nonce[0], lmresp); if(result) return result; /* NTLMv2 response */ - result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, - (unsigned char *)&entropy[0], + result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, ntlm, &ntlmv2resp, &ntresplen); if(result) return result; @@ -589,17 +588,18 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, else #endif -#if USE_NTRESPONSES && USE_NTLM2SESSION +#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION) /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { unsigned char ntbuffer[0x18]; unsigned char tmp[0x18]; unsigned char md5sum[MD5_DIGEST_LENGTH]; - unsigned int entropy[2]; + unsigned char entropy[8]; /* Need to create 8 bytes random data */ - entropy[0] = Curl_rand(data); - entropy[1] = Curl_rand(data); + result = Curl_rand(data, entropy, 8); + if(result) + return result; /* 8 bytes random data as challenge in lmresp */ memcpy(lmresp, entropy, 8); @@ -628,12 +628,12 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, #endif { -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES unsigned char ntbuffer[0x18]; #endif unsigned char lmbuffer[0x18]; -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(result) return result; @@ -649,7 +649,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, /* A safer but less compatible alternative is: * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); - * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ + * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */ } if(unicode) { @@ -659,7 +659,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, } lmrespoff = 64; /* size of the message header */ -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES ntrespoff = lmrespoff + 0x18; domoff = ntrespoff + ntresplen; #else @@ -719,7 +719,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, SHORTPAIR(lmrespoff), 0x0, 0x0, -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES SHORTPAIR(ntresplen), /* NT-response length, twice */ SHORTPAIR(ntresplen), SHORTPAIR(ntrespoff), @@ -766,7 +766,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); }); -#if USE_NTRESPONSES +#ifdef USE_NTRESPONSES if(size < (NTLM_BUFSIZE - ntresplen)) { DEBUGASSERT(size == (size_t)ntrespoff); memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); diff --git a/Utilities/cmcurl/lib/vauth/ntlm.h b/Utilities/cmcurl/lib/vauth/ntlm.h index b14e7a56a..f906a3c7a 100644 --- a/Utilities/cmcurl/lib/vauth/ntlm.h +++ b/Utilities/cmcurl/lib/vauth/ntlm.h @@ -32,7 +32,7 @@ /* Stuff only required for curl_ntlm_msgs.c */ #ifdef BUILDING_CURL_NTLM_MSGS_C -/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */ +/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */ #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) /* Indicates that Unicode strings are supported for use in security buffer diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c index 672b43fa4..a6797cdaf 100644 --- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c +++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c @@ -34,6 +34,7 @@ #include "warnless.h" #include "curl_multibyte.h" #include "sendf.h" +#include "strerror.h" /* The last #include files should be: */ #include "curl_memory.h" @@ -224,6 +225,8 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, free(chlg); if(GSS_ERROR(nego->status)) { + failf(data, "InitializeSecurityContext failed: %s", + Curl_sspi_strerror(data->easy_conn, nego->status)); return CURLE_OUT_OF_MEMORY; } @@ -264,7 +267,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, /* Base64 encode the already generated response */ result = Curl_base64_encode(data, - (const char*) nego->output_token, + (const char *) nego->output_token, nego->output_token_length, outptr, outlen); diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c index a434a6287..3d1776813 100644 --- a/Utilities/cmcurl/lib/version.c +++ b/Utilities/cmcurl/lib/version.c @@ -323,6 +323,9 @@ static curl_version_info_data version_info = { #endif #if defined(USE_LIBPSL) | CURL_VERSION_PSL +#endif +#if defined(HTTPS_PROXY_SUPPORT) + | CURL_VERSION_HTTPS_PROXY #endif , NULL, /* ssl_version */ diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c index 85b8bc4f6..f0e376640 100644 --- a/Utilities/cmcurl/lib/vtls/axtls.c +++ b/Utilities/cmcurl/lib/vtls/axtls.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, DirecTV, Contact: Eric Hu, . - * Copyright (C) 2010 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -65,7 +65,7 @@ int Curl_axtls_cleanup(void) static CURLcode map_error_to_curl(int axtls_err) { - switch (axtls_err) { + switch(axtls_err) { case SSL_ERROR_NOT_SUPPORTED: case SSL_ERROR_INVALID_VERSION: case -70: /* protocol version alert from server */ @@ -121,7 +121,7 @@ static Curl_send axtls_send; static void free_ssl_structs(struct ssl_connect_data *connssl) { if(connssl->ssl) { - ssl_free (connssl->ssl); + ssl_free(connssl->ssl); connssl->ssl = NULL; } if(connssl->ssl_ctx) { @@ -156,9 +156,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) same connection */ return CURLE_OK; + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "axtls does not support CURL_SSLVERSION_MAX"); + return CURLE_SSL_CONNECT_ERROR; + } + + /* axTLS only supports TLSv1 */ /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: break; @@ -183,17 +189,17 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) conn->ssl[sockindex].ssl = NULL; /* Load the trusted CA cert bundle file */ - if(data->set.ssl.CAfile) { - if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) - != SSL_OK) { + if(SSL_CONN_CONFIG(CAfile)) { + if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, + SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) { infof(data, "error reading ca cert file %s \n", - data->set.ssl.CAfile); - if(data->set.ssl.verifypeer) { + SSL_CONN_CONFIG(CAfile)); + if(SSL_CONN_CONFIG(verifypeer)) { return CURLE_SSL_CACERT_BADFILE; } } else - infof(data, "found certificates in %s\n", data->set.ssl.CAfile); + infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile)); } /* gtls.c tasks we're skipping for now: @@ -205,15 +211,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) */ /* Load client certificate */ - if(data->set.str[STRING_CERT]) { + if(SSL_SET_OPTION(cert)) { i=0; /* Instead of trying to analyze cert type here, let axTLS try them all. */ while(cert_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], - data->set.str[STRING_CERT], NULL); + SSL_SET_OPTION(cert), NULL); if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read cert file %s \n", - data->set.str[STRING_CERT]); + SSL_SET_OPTION(cert)); break; } i++; @@ -221,7 +227,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) /* Tried all cert types, none worked. */ if(cert_types[i] == 0) { failf(data, "%s is not x509 or pkcs12 format", - data->set.str[STRING_CERT]); + SSL_SET_OPTION(cert)); return CURLE_SSL_CERTPROBLEM; } } @@ -229,15 +235,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) /* Load client key. If a pkcs12 file successfully loaded a cert, then there's nothing to do because the key has already been loaded. */ - if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) { + if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) { i=0; /* Instead of trying to analyze key type here, let axTLS try them all. */ while(key_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], - data->set.str[STRING_KEY], NULL); + SSL_SET_OPTION(key), NULL); if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read key file %s \n", - data->set.str[STRING_KEY]); + SSL_SET_OPTION(key)); break; } i++; @@ -245,7 +251,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) /* Tried all key types, none worked. */ if(key_types[i] == 0) { failf(data, "Failure: %s is not a supported key file", - data->set.str[STRING_KEY]); + SSL_SET_OPTION(key)); return CURLE_SSL_CONNECT_ERROR; } } @@ -256,23 +262,24 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) * 2) setting up callbacks. these seem gnutls specific */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { const uint8_t *ssl_sessionid; size_t ssl_idsize; /* In axTLS, handshaking happens inside ssl_client_new. */ Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) { + if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize, + sockindex)) { /* we got a session id, use it! */ - infof (data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID\n"); ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], - ssl_sessionid, (uint8_t)ssl_idsize); + ssl_sessionid, (uint8_t)ssl_idsize, NULL); } Curl_ssl_sessionid_unlock(conn); } if(!ssl) - ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); + ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL); conn->ssl[sockindex].ssl = ssl; return CURLE_OK; @@ -291,13 +298,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; + 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; /* Here, gtls.c gets the peer certificates and fails out depending on * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? */ /* Verify server's certificate */ - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { if(ssl_verify_cert(ssl) != SSL_OK) { Curl_axtls_close(conn, sockindex); failf(data, "server cert verify failed"); @@ -328,8 +339,8 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) found_subject_alt_names = 1; infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", - dns_altname, conn->host.name); - if(Curl_cert_hostcheck(dns_altname, conn->host.name)) { + dns_altname, hostname); + if(Curl_cert_hostcheck(dns_altname, hostname)) { found_subject_alt_name_matching_conn = 1; break; } @@ -337,23 +348,21 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) /* RFC2818 checks */ if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { - if(data->set.ssl.verifyhost) { + if(SSL_CONN_CONFIG(verifyhost)) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); - failf(data, "\tsubjectAltName(s) do not match %s\n", - conn->host.dispname); + failf(data, "\tsubjectAltName(s) do not match %s\n", dispname); return CURLE_PEER_FAILED_VERIFICATION; } else - infof(data, "\tsubjectAltName(s) do not match %s\n", - conn->host.dispname); + infof(data, "\tsubjectAltName(s) do not match %s\n", dispname); } else if(found_subject_alt_names == 0) { /* Per RFC2818, when no Subject Alt Names were available, examine the peer CN as a legacy fallback */ peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); if(peer_CN == NULL) { - if(data->set.ssl.verifyhost) { + if(SSL_CONN_CONFIG(verifyhost)) { Curl_axtls_close(conn, sockindex); failf(data, "unable to obtain common name from peer certificate"); return CURLE_PEER_FAILED_VERIFICATION; @@ -362,17 +371,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) infof(data, "unable to obtain common name from peer certificate"); } else { - if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { - if(data->set.ssl.verifyhost) { + if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { + if(SSL_CONN_CONFIG(verifyhost)) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", - peer_CN, conn->host.dispname); + peer_CN, dispname); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", - peer_CN, conn->host.dispname); + peer_CN, dispname); } } } @@ -383,13 +392,13 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) conn->send[sockindex] = axtls_send; /* Put our freshly minted SSL session in cache */ - if(conn->ssl_config.sessionid) { - const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl); - size_t ssl_idsize = ssl_get_session_id(ssl); + if(SSL_SET_OPTION(primary.sessionid)) { + const uint8_t *ssl_sessionid = ssl_get_session_id(ssl); + size_t ssl_idsize = ssl_get_session_id_size(ssl); Curl_ssl_sessionid_lock(conn); - if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) - != CURLE_OK) - infof (data, "failed to add session to cache\n"); + if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize, + sockindex) != CURLE_OK) + infof(data, "failed to add session to cache\n"); Curl_ssl_sessionid_unlock(conn); } @@ -437,7 +446,7 @@ CURLcode Curl_axtls_connect_nonblocking( return CURLE_OK; } } - infof (conn->data, "handshake completed successfully\n"); + infof(conn->data, "handshake completed successfully\n"); conn->ssl[sockindex].connecting_state = ssl_connect_3; } @@ -503,7 +512,7 @@ Curl_axtls_connect(struct connectdata *conn, /* TODO: avoid polling */ Curl_wait_ms(10); } - infof (conn->data, "handshake completed successfully\n"); + infof(conn->data, "handshake completed successfully\n"); conn_step = connect_finish(conn, sockindex); if(conn_step != CURLE_OK) { @@ -677,9 +686,9 @@ size_t Curl_axtls_version(char *buffer, size_t size) return snprintf(buffer, size, "axTLS/%s", ssl_version()); } -int Curl_axtls_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +CURLcode Curl_axtls_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { static bool ssl_seeded = FALSE; (void)data; @@ -691,7 +700,7 @@ int Curl_axtls_random(struct Curl_easy *data, RNG_initialize(); } get_random((int)length, entropy); - return 0; + return CURLE_OK; } #endif /* USE_AXTLS */ diff --git a/Utilities/cmcurl/lib/vtls/axtls.h b/Utilities/cmcurl/lib/vtls/axtls.h index b16d051aa..53797eadb 100644 --- a/Utilities/cmcurl/lib/vtls/axtls.h +++ b/Utilities/cmcurl/lib/vtls/axtls.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, DirecTV, Contact: Eric Hu - * Copyright (C) 2010 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2010 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -42,9 +42,9 @@ void Curl_axtls_session_free(void *ptr); size_t Curl_axtls_version(char *buffer, size_t size); int Curl_axtls_shutdown(struct connectdata *conn, int sockindex); int Curl_axtls_check_cxn(struct connectdata *conn); -int Curl_axtls_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length); +CURLcode Curl_axtls_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length); /* Set the API backend definition to axTLS */ #define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c index 5d6dbfb8c..01bfdabd1 100644 --- a/Utilities/cmcurl/lib/vtls/cyassl.c +++ b/Utilities/cmcurl/lib/vtls/cyassl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -44,6 +44,38 @@ and that's a problem since options.h hasn't been included yet. */ #include #endif +/* To determine what functions are available we rely on one or both of: + - the user's options.h generated by CyaSSL/wolfSSL + - the symbols detected by curl's configure + Since they are markedly different from one another, and one or the other may + not be available, we do some checking below to bring things in sync. */ + +/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ +#ifndef HAVE_ALPN +#ifdef HAVE_WOLFSSL_USEALPN +#define HAVE_ALPN +#endif +#endif + +/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in + options.h, but is only seen in >= 3.6.6 since that's when they started + disabling SSLv3 by default. */ +#ifndef WOLFSSL_ALLOW_SSLV3 +#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \ + defined(HAVE_WOLFSSLV3_CLIENT_METHOD) +#define WOLFSSL_ALLOW_SSLV3 +#endif +#endif + +/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC + supported curve extension in options.h. Note ECC is enabled separately. */ +#ifndef HAVE_SUPPORTED_CURVES +#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \ + defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE) +#define HAVE_SUPPORTED_CURVES +#endif +#endif + #ifdef HAVE_LIMITS_H #include #endif @@ -78,38 +110,6 @@ and that's a problem since options.h hasn't been included yet. */ #define CYASSL_MAX_ERROR_SZ 80 #endif -/* To determine what functions are available we rely on one or both of: - - the user's options.h generated by CyaSSL/wolfSSL - - the symbols detected by curl's configure - Since they are markedly different from one another, and one or the other may - not be available, we do some checking below to bring things in sync. */ - -/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ -#ifndef HAVE_ALPN -#ifdef HAVE_WOLFSSL_USEALPN -#define HAVE_ALPN -#endif -#endif - -/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in - options.h, but is only seen in >= 3.6.6 since that's when they started - disabling SSLv3 by default. */ -#ifndef WOLFSSL_ALLOW_SSLV3 -#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \ - defined(HAVE_WOLFSSLV3_CLIENT_METHOD) -#define WOLFSSL_ALLOW_SSLV3 -#endif -#endif - -/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC - supported curve extension in options.h. Note ECC is enabled separately. */ -#ifndef HAVE_SUPPORTED_CURVES -#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \ - defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE) -#define HAVE_SUPPORTED_CURVES -#endif -#endif - static Curl_recv cyassl_recv; static Curl_send cyassl_send; @@ -134,6 +134,7 @@ cyassl_connect_step1(struct connectdata *conn, int sockindex) { char error_buffer[CYASSL_MAX_ERROR_SZ]; + char *ciphers; struct Curl_easy *data = conn->data; struct ssl_connect_data* conssl = &conn->ssl[sockindex]; SSL_METHOD* req_method = NULL; @@ -148,8 +149,13 @@ cyassl_connect_step1(struct connectdata *conn, if(conssl->state == ssl_connection_complete) return CURLE_OK; + if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { + failf(data, "CyaSSL does not support to set maximum SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: #if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ @@ -174,12 +180,15 @@ cyassl_connect_step1(struct connectdata *conn, req_method = TLSv1_2_client_method(); use_sni(TRUE); break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "CyaSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_SSLv3: #ifdef WOLFSSL_ALLOW_SSLV3 req_method = SSLv3_client_method(); use_sni(FALSE); #else - failf(data, "No support for SSLv3"); + failf(data, "CyaSSL does not support SSLv3"); return CURLE_NOT_BUILT_IN; #endif break; @@ -205,7 +214,7 @@ cyassl_connect_step1(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: #if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ @@ -226,20 +235,29 @@ cyassl_connect_step1(struct connectdata *conn, break; } + ciphers = SSL_CONN_CONFIG(cipher_list); + if(ciphers) { + if(!SSL_CTX_set_cipher_list(conssl->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s\n", ciphers); + } + #ifndef NO_FILESYSTEM /* load trusted cacert */ - if(data->set.str[STRING_SSL_CAFILE]) { + if(SSL_CONN_CONFIG(CAfile)) { if(1 != SSL_CTX_load_verify_locations(conssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { - if(data->set.ssl.verifypeer) { + SSL_CONN_CONFIG(CAfile), + 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", - data->set.str[STRING_SSL_CAFILE]? - data->set.str[STRING_SSL_CAFILE]: "none", - data->set.str[STRING_SSL_CAPATH]? - data->set.str[STRING_SSL_CAPATH] : "none"); + SSL_CONN_CONFIG(CAfile)? + SSL_CONN_CONFIG(CAfile): "none", + SSL_CONN_CONFIG(CApath)? + SSL_CONN_CONFIG(CApath) : "none"); return CURLE_SSL_CACERT_BADFILE; } else { @@ -256,25 +274,25 @@ cyassl_connect_step1(struct connectdata *conn, infof(data, " CAfile: %s\n" " CApath: %s\n", - data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: + SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none", - data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: + SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): "none"); } /* Load the client certificate, and private key */ - if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) { - int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]); + if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { + int file_type = do_file_type(SSL_SET_OPTION(cert_type)); - if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT], + if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert), file_type) != 1) { failf(data, "unable to use client certificate (no key or wrong pass" " phrase?)"); return CURLE_SSL_CONNECT_ERROR; } - file_type = do_file_type(data->set.str[STRING_KEY_TYPE]); - if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY], + file_type = do_file_type(SSL_SET_OPTION(key_type)); + if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key), file_type) != 1) { failf(data, "unable to set private key"); return CURLE_SSL_CONNECT_ERROR; @@ -287,7 +305,8 @@ cyassl_connect_step1(struct connectdata *conn, * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ SSL_CTX_set_verify(conssl->ctx, - data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, + SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER: + SSL_VERIFY_NONE, NULL); #ifdef HAVE_SNI @@ -296,13 +315,15 @@ cyassl_connect_step1(struct connectdata *conn, #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif - size_t hostname_len = strlen(conn->host.name); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + size_t hostname_len = strlen(hostname); if((hostname_len < USHRT_MAX) && - (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) && + (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && #ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) && + (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && #endif - (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name, + (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname, (unsigned short)hostname_len) != 1)) { infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); @@ -331,7 +352,7 @@ cyassl_connect_step1(struct connectdata *conn, } } #ifdef NO_FILESYSTEM - else if(data->set.ssl.verifypeer) { + else if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built" " with \"no filesystem\". Either disable peer verification" " (insecure) or if you are building an application with libcurl you" @@ -377,11 +398,11 @@ cyassl_connect_step1(struct connectdata *conn, #endif /* HAVE_ALPN */ /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(conssl->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); @@ -391,7 +412,7 @@ cyassl_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ - infof (data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); } @@ -414,13 +435,20 @@ cyassl_connect_step2(struct connectdata *conn, int ret = -1; struct Curl_easy *data = conn->data; struct ssl_connect_data* conssl = &conn->ssl[sockindex]; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; conn->recv[sockindex] = cyassl_recv; conn->send[sockindex] = cyassl_send; /* Enable RFC2818 checks */ - if(data->set.ssl.verifyhost) { - ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name); + if(SSL_CONN_CONFIG(verifyhost)) { + ret = CyaSSL_check_domain_name(conssl->handle, hostname); if(ret == SSL_FAILURE) return CURLE_OUT_OF_MEMORY; } @@ -444,31 +472,31 @@ cyassl_connect_step2(struct connectdata *conn, else if(DOMAIN_NAME_MISMATCH == detail) { #if 1 failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", - conn->host.dispname); + dispname); return CURLE_PEER_FAILED_VERIFICATION; #else /* When the CyaSSL_check_domain_name() is used and you desire to continue - * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0', + * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0', * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only * way to do this is currently to switch the CyaSSL_check_domain_name() - * in and out based on the 'data->set.ssl.verifyhost' value. */ - if(data->set.ssl.verifyhost) { + * in and out based on the 'conn->ssl_config.verifyhost' value. */ + if(SSL_CONN_CONFIG(verifyhost)) { failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", - conn->host.dispname); + dispname); return CURLE_PEER_FAILED_VERIFICATION; } else { infof(data, "\tsubject alt name(s) and/or common name do not match \"%s\"\n", - conn->host.dispname); + dispname); return CURLE_OK; } #endif } #if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ else if(ASN_NO_SIGNER_E == detail) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "\tCA signer not available for verification\n"); return CURLE_SSL_CACERT_BADFILE; } @@ -487,7 +515,7 @@ cyassl_connect_step2(struct connectdata *conn, } } - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + if(pinnedpubkey) { #ifdef KEEP_PEER_CERT X509 *x509; const char *x509_der; @@ -509,7 +537,8 @@ cyassl_connect_step2(struct connectdata *conn, } memset(&x509_parsed, 0, sizeof x509_parsed); - Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len); + if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; pubkey = &x509_parsed.subjectPublicKeyInfo; if(!pubkey->header || pubkey->end <= pubkey->header) { @@ -518,7 +547,7 @@ cyassl_connect_step2(struct connectdata *conn, } result = Curl_pin_peer_pubkey(data, - data->set.str[STRING_SSL_PINNEDPUBLICKEY], + pinnedpubkey, (const unsigned char *)pubkey->header, (size_t)(pubkey->end - pubkey->header)); if(result) { @@ -567,7 +596,13 @@ cyassl_connect_step2(struct connectdata *conn, #endif /* HAVE_ALPN */ conssl->connecting_state = ssl_connect_3; +#if (LIBCYASSL_VERSION_HEX >= 0x03009010) + infof(data, "SSL connection using %s / %s\n", + wolfSSL_get_version(conssl->handle), + wolfSSL_get_cipher_name(conssl->handle)); +#else infof(data, "SSL connected\n"); +#endif return CURLE_OK; } @@ -583,7 +618,7 @@ cyassl_connect_step3(struct connectdata *conn, DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { bool incache; SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -591,7 +626,8 @@ cyassl_connect_step3(struct connectdata *conn, our_ssl_sessionid = SSL_get_session(connssl->handle); Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + incache = !(Curl_ssl_getsessionid(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"); @@ -602,7 +638,7 @@ cyassl_connect_step3(struct connectdata *conn, if(!incache) { result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */); + 0 /* unknown size */, sockindex); if(result) { Curl_ssl_sessionid_unlock(conn); failf(data, "failed to store ssl session"); @@ -654,11 +690,11 @@ void Curl_cyassl_close(struct connectdata *conn, int sockindex) if(conssl->handle) { (void)SSL_shutdown(conssl->handle); - SSL_free (conssl->handle); + SSL_free(conssl->handle); conssl->handle = NULL; } if(conssl->ctx) { - SSL_CTX_free (conssl->ctx); + SSL_CTX_free(conssl->ctx); conssl->ctx = NULL; } } @@ -705,7 +741,9 @@ void Curl_cyassl_session_free(void *ptr) size_t Curl_cyassl_version(char *buffer, size_t size) { -#ifdef WOLFSSL_VERSION +#if LIBCYASSL_VERSION_HEX >= 0x03006000 + return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version()); +#elif defined(WOLFSSL_VERSION) return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION); #elif defined(CYASSL_VERSION) return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); @@ -740,7 +778,7 @@ int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; if(connssl->handle) { - SSL_free (connssl->handle); + SSL_free(connssl->handle); connssl->handle = NULL; } return retval; @@ -757,7 +795,7 @@ cyassl_connect_common(struct connectdata *conn, struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; + time_t timeout_ms; int what; /* check if the connection has already been established */ @@ -886,19 +924,19 @@ Curl_cyassl_connect(struct connectdata *conn, return CURLE_OK; } -int Curl_cyassl_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +CURLcode Curl_cyassl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { RNG rng; (void)data; if(InitRng(&rng)) - return 1; + return CURLE_FAILED_INIT; if(length > UINT_MAX) - return 1; + return CURLE_FAILED_INIT; if(RNG_GenerateBlock(&rng, entropy, (unsigned)length)) - return 1; - return 0; + return CURLE_FAILED_INIT; + return CURLE_OK; } void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ diff --git a/Utilities/cmcurl/lib/vtls/cyassl.h b/Utilities/cmcurl/lib/vtls/cyassl.h index 508dfaaf0..f47719e4e 100644 --- a/Utilities/cmcurl/lib/vtls/cyassl.h +++ b/Utilities/cmcurl/lib/vtls/cyassl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -51,15 +51,15 @@ int Curl_cyassl_init(void); CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done); -int Curl_cyassl_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length); +CURLcode Curl_cyassl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length); void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */ size_t tmplen, unsigned char *sha256sum, /* output */ size_t unused); -/* Set the API backend definition to Schannel */ +/* Set the API backend definition to CyaSSL */ #define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL /* this backend supports CURLOPT_SSL_CTX_* */ diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c index 66e74f1ba..041766541 100644 --- a/Utilities/cmcurl/lib/vtls/darwinssl.c +++ b/Utilities/cmcurl/lib/vtls/darwinssl.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2014, Nick Zitzmann, . - * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -113,6 +113,36 @@ #define ioErr -36 #define paramErr -50 +#ifdef DARWIN_SSL_PINNEDPUBKEY +/* both new and old APIs return rsa keys missing the spki header (not DER) */ +static const unsigned char rsa4096SpkiHeader[] = { + 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00}; + +static const unsigned char rsa2048SpkiHeader[] = { + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; +#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +/* the *new* version doesn't return DER encoded ecdsa certs like the old... */ +static const unsigned char ecDsaSecp256r1SpkiHeader[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00}; + +static const unsigned char ecDsaSecp384r1SpkiHeader[] = { + 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, + 0x00, 0x22, 0x03, 0x62, 0x00}; +#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */ +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + /* The following two functions were ripped from Apple sample code, * with some modifications: */ static OSStatus SocketRead(SSLConnectionRef connection, @@ -197,7 +227,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection, do { length = write(sock, - (char*)dataPtr + bytesSent, + (char *)dataPtr + bytesSent, dataLen - bytesSent); } while((length > 0) && ( (bytesSent += length) < dataLen) ); @@ -219,8 +249,10 @@ static OSStatus SocketWrite(SSLConnectionRef connection, return ortn; } -CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) { - switch (cipher) { +#ifndef CURL_DISABLE_VERBOSE_STRINGS +CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { /* SSL version 3.0 */ case SSL_RSA_WITH_NULL_MD5: return "SSL_RSA_WITH_NULL_MD5"; @@ -364,7 +396,8 @@ CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) { return "SSL_NULL_WITH_NULL_NULL"; } -CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { +CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) +{ switch(cipher) { /* TLS 1.0 with AES (RFC 3268) */ case TLS_RSA_WITH_AES_128_CBC_SHA: @@ -774,6 +807,7 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { } return "TLS_NULL_WITH_NULL_NULL"; } +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ #if CURL_BUILD_MAC CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) @@ -885,12 +919,17 @@ static OSStatus CopyIdentityWithLabel(char *label, OSStatus status = errSecItemNotFound; #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS + CFArrayRef keys_list; + CFIndex keys_list_count; + CFIndex i; + CFStringRef common_name; + /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. kSecClassIdentity was introduced in Lion. If both exist, let's use them to find the certificate. */ if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { - CFTypeRef keys[4]; - CFTypeRef values[4]; + CFTypeRef keys[5]; + CFTypeRef values[5]; CFDictionaryRef query_dict; CFStringRef label_cf = CFStringCreateWithCString(NULL, label, kCFStringEncodingUTF8); @@ -900,21 +939,60 @@ static OSStatus CopyIdentityWithLabel(char *label, keys[0] = kSecClass; values[1] = kCFBooleanTrue; /* we want a reference */ keys[1] = kSecReturnRef; - values[2] = kSecMatchLimitOne; /* one is enough, thanks */ + values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the + * label matching below worked correctly */ keys[2] = kSecMatchLimit; /* identity searches need a SecPolicyRef in order to work */ - values[3] = SecPolicyCreateSSL(false, label_cf); + values[3] = SecPolicyCreateSSL(false, NULL); keys[3] = kSecMatchPolicy; + /* match the name of the certificate (doesn't work in macOS 10.12.1) */ + values[4] = label_cf; + keys[4] = kSecAttrLabel; query_dict = CFDictionaryCreate(NULL, (const void **)keys, - (const void **)values, 4L, - &kCFCopyStringDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + (const void **)values, 5L, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); CFRelease(values[3]); - CFRelease(label_cf); /* Do we have a match? */ - status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key); + status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); + + /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, + * we need to find the correct identity ourselves */ + if(status == noErr) { + keys_list_count = CFArrayGetCount(keys_list); + *out_cert_and_key = NULL; + status = 1; + for(i=0; idata; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version << 16; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + +#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS + if(SSLSetProtocolVersionMax != NULL) { + SSLProtocol darwin_ver_min = kTLSProtocol1; + SSLProtocol darwin_ver_max = kTLSProtocol1; + CURLcode result = darwinssl_version_from_curl(&darwin_ver_min, + ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = darwinssl_version_from_curl(&darwin_ver_max, + ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max); + return result; + } + else { +#if CURL_SUPPORT_MAC_10_8 + long i = ssl_version; + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocolAll, + false); + for(; i <= (ssl_version_max >> 16); i++) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "DarwinSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ + failf(data, "DarwinSSL: cannot set SSL protocol"); + return CURLE_SSL_CONNECT_ERROR; +} + + static CURLcode darwinssl_connect_step1(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]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + char * const ssl_cert = SSL_SET_OPTION(cert); + 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; #ifdef ENABLE_IPV6 struct in6_addr addr; #else @@ -1052,40 +1239,41 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, /* check to see if we've been told to use an explicit SSL/TLS version */ #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS if(SSLSetProtocolVersionMax != NULL) { - switch(data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); - break; - case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1); - break; - case CURL_SSLVERSION_TLSv1_1: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11); - break; - case CURL_SSLVERSION_TLSv1_2: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); - break; - case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: + case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; break; - case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); + } + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } } else { @@ -1093,123 +1281,130 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); - switch (data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol1, - true); - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol11, - true); - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol12, - true); - break; - case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol1, - true); - break; - case CURL_SSLVERSION_TLSv1_1: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol11, - true); - break; - case CURL_SSLVERSION_TLSv1_2: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol12, - true); - break; - case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - } -#endif /* CURL_SUPPORT_MAC_10_8 */ - } -#else - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); - switch(data->set.ssl.version) { - default: + switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: - case CURL_SSLVERSION_TLSv1_0: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol1, true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); break; + case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: - failf(data, "Your version of the OS does not support TLSv1.1"); - return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_TLSv1_2: - failf(data, "Your version of the OS does not support TLSv1.2"); - return CURLE_SSL_CONNECT_ERROR; - case CURL_SSLVERSION_SSLv2: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv3: err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol2, + kSSLProtocol3, true); if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); + failf(data, "Your version of the OS does not support SSLv3"); return CURLE_SSL_CONNECT_ERROR; } break; - case CURL_SSLVERSION_SSLv3: + case CURL_SSLVERSION_SSLv2: err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol3, + kSSLProtocol2, true); if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); + failf(data, "Your version of the OS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) { + failf(data, "Your version of the OS does not support to set maximum" + " SSL/TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + failf(data, "Your version of the OS does not support TLSv1.1"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_2: + failf(data, "Your version of the OS does not support TLSv1.2"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - if(data->set.str[STRING_KEY]) { + if(SSL_SET_OPTION(key)) { infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " - "Transport. The private key must be in the Keychain.\n"); + "Transport. The private key must be in the Keychain.\n"); } - if(data->set.str[STRING_CERT]) { + if(ssl_cert) { SecIdentityRef cert_and_key = NULL; - bool is_cert_file = is_file(data->set.str[STRING_CERT]); + bool is_cert_file = is_file(ssl_cert); /* User wants to authenticate with a client cert. Look for it: If we detect that this is a file on disk, then let's load it. Otherwise, assume that the user wants to use an identity loaded from the Keychain. */ if(is_cert_file) { - if(!data->set.str[STRING_CERT_TYPE]) + if(!SSL_SET_OPTION(cert_type)) infof(data, "WARNING: SSL: Certificate type not set, assuming " "PKCS#12 format.\n"); - else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12", - strlen(data->set.str[STRING_CERT_TYPE])) != 0) + else if(strncmp(SSL_SET_OPTION(cert_type), "P12", + strlen(SSL_SET_OPTION(cert_type))) != 0) infof(data, "WARNING: SSL: The Security framework only supports " "loading identities that are in PKCS#12 format.\n"); - err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT], - data->set.str[STRING_KEY_PASSWD], &cert_and_key); + err = CopyIdentityFromPKCS12File(ssl_cert, + SSL_SET_OPTION(key_passwd), &cert_and_key); } else - err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key); + err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); - if(err == noErr) { + if(err == noErr && cert_and_key) { SecCertificateRef cert = NULL; CFTypeRef certs_c[1]; CFArrayRef certs; @@ -1246,27 +1441,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, } else { switch(err) { - case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ - failf(data, "SSL: Incorrect password for the certificate \"%s\" " - "and its private key.", data->set.str[STRING_CERT]); - break; - case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ - failf(data, "SSL: Couldn't make sense of the data in the " - "certificate \"%s\" and its private key.", - data->set.str[STRING_CERT]); - break; - case -25260: /* errSecPassphraseRequired */ - failf(data, "SSL The certificate \"%s\" requires a password.", - data->set.str[STRING_CERT]); - break; - case errSecItemNotFound: - failf(data, "SSL: Can't find the certificate \"%s\" and its private " - "key in the Keychain.", data->set.str[STRING_CERT]); - break; - default: - failf(data, "SSL: Can't load the certificate \"%s\" and its private " - "key: OSStatus %d", data->set.str[STRING_CERT], err); - break; + case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ + failf(data, "SSL: Incorrect password for the certificate \"%s\" " + "and its private key.", ssl_cert); + break; + case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ + failf(data, "SSL: Couldn't make sense of the data in the " + "certificate \"%s\" and its private key.", + ssl_cert); + break; + case -25260: /* errSecPassphraseRequired */ + failf(data, "SSL The certificate \"%s\" requires a password.", + ssl_cert); + break; + case errSecItemNotFound: + failf(data, "SSL: Can't find the certificate \"%s\" and its private " + "key in the Keychain.", ssl_cert); + break; + default: + failf(data, "SSL: Can't load the certificate \"%s\" and its private " + "key: OSStatus %d", ssl_cert, err); + break; } return CURLE_SSL_CERTPROBLEM; } @@ -1297,8 +1492,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #else if(SSLSetSessionOption != NULL) { #endif /* CURL_BUILD_MAC */ - bool break_on_auth = !data->set.ssl.verifypeer || - data->set.str[STRING_SSL_CAFILE]; + bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; err = SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionBreakOnServerAuth, break_on_auth); @@ -1310,7 +1504,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, else { #if CURL_SUPPORT_MAC_10_8 err = SSLSetEnableCertVerify(connssl->ssl_ctx, - data->set.ssl.verifypeer?true:false); + conn->ssl_config.verifypeer?true:false); if(err != noErr) { failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; @@ -1319,49 +1513,46 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, } #else err = SSLSetEnableCertVerify(connssl->ssl_ctx, - data->set.ssl.verifypeer?true:false); + conn->ssl_config.verifypeer?true:false); if(err != noErr) { failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; } #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ - if(data->set.str[STRING_SSL_CAFILE]) { - bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]); + if(ssl_cafile && verifypeer) { + bool is_cert_file = is_file(ssl_cafile); if(!is_cert_file) { - failf(data, "SSL: can't load CA certificate file %s", - data->set.str[STRING_SSL_CAFILE]); + failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); return CURLE_SSL_CACERT_BADFILE; } - if(!data->set.ssl.verifypeer) { - failf(data, "SSL: CA certificate set, but certificate verification " - "is disabled"); - return CURLE_SSL_CONNECT_ERROR; - } } /* Configure hostname check. SNI is used if available. * Both hostname check and SNI require SSLSetPeerDomainName(). * Also: the verifyhost setting influences SNI usage */ - if(data->set.ssl.verifyhost) { - err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name, - strlen(conn->host.name)); + if(conn->ssl_config.verifyhost) { + err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname, + strlen(hostname)); if(err != noErr) { infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", err); } - if((Curl_inet_pton(AF_INET, conn->host.name, &addr)) + if((Curl_inet_pton(AF_INET, hostname, &addr)) #ifdef ENABLE_IPV6 - || (Curl_inet_pton(AF_INET6, conn->host.name, &addr)) + || (Curl_inet_pton(AF_INET6, hostname, &addr)) #endif ) { - infof(data, "WARNING: using IP address, SNI is being disabled by " - "the OS.\n"); + infof(data, "WARNING: using IP address, SNI is being disabled by " + "the OS.\n"); } } + else { + infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); + } /* Disable cipher suites that ST supports but are not safe. These ciphers are unlikely to be used in any case since ST gives other ciphers a much @@ -1382,7 +1573,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, running in an affected version of OS X. */ if(darwinver_maj == 12 && darwinver_min <= 3 && all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { - continue; + continue; } #endif /* CURL_BUILD_MAC */ switch(all_ciphers[i]) { @@ -1474,21 +1665,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, /* We want to enable 1/n-1 when using a CBC cipher unless the user specifically doesn't want us doing that: */ if(SSLSetSessionOption != NULL) { + /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */ SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord, - !data->set.ssl_enable_beast); + !data->set.ssl.enable_beast); SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart, data->set.ssl.falsestart); /* false start support */ } #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { char *ssl_sessionid; size_t ssl_sessionid_len; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, - &ssl_sessionid_len)) { + &ssl_sessionid_len, sockindex)) { /* we got a session id, use it! */ err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); Curl_ssl_sessionid_unlock(conn); @@ -1504,9 +1696,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, else { CURLcode result; ssl_sessionid = - aprintf("%s:%d:%d:%s:%hu", data->set.str[STRING_SSL_CAFILE], - data->set.ssl.verifypeer, data->set.ssl.verifyhost, - conn->host.name, conn->remote_port); + aprintf("%s:%d:%d:%s:%hu", ssl_cafile, + verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); ssl_sessionid_len = strlen(ssl_sessionid); err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); @@ -1516,7 +1707,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } - result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len); + result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, + sockindex); Curl_ssl_sessionid_unlock(conn); if(result) { failf(data, "failed to store ssl session"); @@ -1820,7 +2012,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data, return sslerr_to_curlerr(data, ret); } - switch (trust_eval) { + switch(trust_eval) { case kSecTrustResultUnspecified: case kSecTrustResultProceed: return CURLE_OK; @@ -1834,6 +2026,112 @@ static int verify_cert(const char *cafile, struct Curl_easy *data, } } +#ifdef DARWIN_SSL_PINNEDPUBKEY +static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data, + SSLContextRef ctx, + const char *pinnedpubkey) +{ /* Scratch */ + size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24; + unsigned char *pubkey = NULL, *realpubkey = NULL, *spkiHeader = NULL; + CFDataRef publicKeyBits = NULL; + + /* Result is returned to caller */ + CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; + + /* if a path wasn't specified, don't pin */ + if(!pinnedpubkey) + return CURLE_OK; + + + if(!ctx) + return result; + + do { + SecTrustRef trust; + OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + if(ret != noErr || trust == NULL) + break; + + SecKeyRef keyRef = SecTrustCopyPublicKey(trust); + CFRelease(trust); + if(keyRef == NULL) + break; + +#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 + + publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); + CFRelease(keyRef); + if(publicKeyBits == NULL) + break; + +#elif DARWIN_SSL_PINNEDPUBKEY_V2 + + OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, + &publicKeyBits); + CFRelease(keyRef); + if(success != errSecSuccess || publicKeyBits == NULL) + break; + +#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ + + pubkeylen = CFDataGetLength(publicKeyBits); + pubkey = CFDataGetBytePtr(publicKeyBits); + + switch(pubkeylen) { + case 526: + /* 4096 bit RSA pubkeylen == 526 */ + spkiHeader = rsa4096SpkiHeader; + break; + case 270: + /* 2048 bit RSA pubkeylen == 270 */ + spkiHeader = rsa2048SpkiHeader; + break; +#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 + case 65: + /* ecDSA secp256r1 pubkeylen == 65 */ + spkiHeader = ecDsaSecp256r1SpkiHeader; + spkiHeaderLength = 26; + break; + case 97: + /* ecDSA secp384r1 pubkeylen == 97 */ + spkiHeader = ecDsaSecp384r1SpkiHeader; + spkiHeaderLength = 23; + break; + default: + infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); +#elif DARWIN_SSL_PINNEDPUBKEY_V2 + default: + /* ecDSA secp256r1 pubkeylen == 91 header already included? + * ecDSA secp384r1 header already included too + * we assume rest of algorithms do same, so do nothing + */ + result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, + pubkeylen); +#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ + continue; /* break from loop */ + } + + realpubkeylen = pubkeylen + spkiHeaderLength; + realpubkey = malloc(realpubkeylen); + if(!realpubkey) + break; + + memcpy(realpubkey, spkiHeader, spkiHeaderLength); + memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen); + + result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey, + realpubkeylen); + + } while(0); + + Curl_safefree(realpubkey); + if(publicKeyBits != NULL) + CFRelease(publicKeyBits); + + return result; +} +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + static CURLcode darwinssl_connect_step2(struct connectdata *conn, int sockindex) { @@ -1842,6 +2140,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) OSStatus err; SSLCipherSuite cipher; SSLProtocol protocol = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; DEBUGASSERT(ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state @@ -1851,7 +2151,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) err = SSLHandshake(connssl->ssl_ctx); if(err != noErr) { - switch (err) { + switch(err) { case errSSLWouldBlock: /* they're not done with us yet */ connssl->connecting_state = connssl->ssl_direction ? ssl_connect_2_writing : ssl_connect_2_reading; @@ -1860,8 +2160,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) /* The below is errSSLServerAuthCompleted; it's not defined in Leopard's headers */ case -9841: - if(data->set.str[STRING_SSL_CAFILE]) { - int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data, + if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { + int res = verify_cert(SSL_CONN_CONFIG(CAfile), data, connssl->ssl_ctx); if(res != CURLE_OK) return res; @@ -1930,7 +2230,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; default: failf(data, "Unknown SSL protocol error in connection to %s:%d", - conn->host.name, err); + hostname, err); return CURLE_SSL_CONNECT_ERROR; } } @@ -1938,10 +2238,21 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) /* we have been connected fine, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_3; +#ifdef DARWIN_SSL_PINNEDPUBKEY + if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { + CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx, + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); + if(result) { + failf(data, "SSL: public key does not match pinned public key!"); + return result; + } + } +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + /* Informational message */ (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher); (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol); - switch (protocol) { + switch(protocol) { case kSSLProtocol2: infof(data, "SSL 2.0 connection using %s\n", SSLCipherNameForNumber(cipher)); @@ -1973,9 +2284,11 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) } } -static CURLcode -darwinssl_connect_step3(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, + int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -1987,9 +2300,9 @@ darwinssl_connect_step3(struct connectdata *conn, CFIndex i, count; SecTrustRef trust = NULL; - /* There is no step 3! - * Well, okay, if verbose mode is on, let's print the details of the - * server certificates. */ + if(!connssl->ssl_ctx) + return; + #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS #if CURL_BUILD_IOS #pragma unused(server_certs) @@ -2086,6 +2399,23 @@ darwinssl_connect_step3(struct connectdata *conn, CFRelease(server_certs); } #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ +} +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +static CURLcode +darwinssl_connect_step3(struct connectdata *conn, + int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + + /* There is no step 3! + * Well, okay, if verbose mode is on, let's print the details of the + * server certificates. */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + if(data->set.verbose) + show_verbose_server_cert(conn, sockindex); +#endif connssl->connecting_state = ssl_connect_done; return CURLE_OK; @@ -2363,8 +2693,8 @@ bool Curl_darwinssl_data_pending(const struct connectdata *conn, return false; } -int Curl_darwinssl_random(unsigned char *entropy, - size_t length) +CURLcode Curl_darwinssl_random(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. */ @@ -2378,7 +2708,7 @@ int Curl_darwinssl_random(unsigned char *entropy, random_number >>= 8; } i = random_number = 0; - return 0; + return CURLE_OK; } void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ @@ -2390,7 +2720,17 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); } -bool Curl_darwinssl_false_start(void) { +void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) +{ + assert(sha256len >= SHA256_DIGEST_LENGTH); + (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); +} + +bool Curl_darwinssl_false_start(void) +{ #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 if(SSLSetSessionOption != NULL) return TRUE; @@ -2427,7 +2767,7 @@ static ssize_t darwinssl_send(struct connectdata *conn, if(connssl->ssl_write_buffered_length) { /* Write the buffered data: */ err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed); - switch (err) { + switch(err) { case noErr: /* processed is always going to be 0 because we didn't write to the buffer, so return how much was written to the socket */ @@ -2447,7 +2787,7 @@ static ssize_t darwinssl_send(struct connectdata *conn, /* We've got new data to write: */ err = SSLWrite(connssl->ssl_ctx, mem, len, &processed); if(err != noErr) { - switch (err) { + switch(err) { case errSSLWouldBlock: /* Data was buffered but not sent, we have to tell the caller to try sending again, and remember how much was buffered */ @@ -2476,7 +2816,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn, OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed); if(err != noErr) { - switch (err) { + switch(err) { case errSSLWouldBlock: /* return how much we read (if anything) */ if(processed) return (ssize_t)processed; diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.h b/Utilities/cmcurl/lib/vtls/darwinssl.h index 8b185b67f..fd372ffa0 100644 --- a/Utilities/cmcurl/lib/vtls/darwinssl.h +++ b/Utilities/cmcurl/lib/vtls/darwinssl.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2014, Nick Zitzmann, . - * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -42,17 +42,40 @@ int Curl_darwinssl_check_cxn(struct connectdata *conn); bool Curl_darwinssl_data_pending(const struct connectdata *conn, int connindex); -int Curl_darwinssl_random(unsigned char *entropy, - size_t length); +CURLcode Curl_darwinssl_random(unsigned char *entropy, + size_t length); void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ size_t md5len); +void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len); bool Curl_darwinssl_false_start(void); /* Set the API backend definition to SecureTransport */ #define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL +/* pinned public key support tests */ + +/* version 1 supports macOS 10.12+ and iOS 10+ */ +#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ + (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) +#define DARWIN_SSL_PINNEDPUBKEY_V1 1 +#endif + +/* version 2 supports MacOSX 10.7+ */ +#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) +#define DARWIN_SSL_PINNEDPUBKEY_V2 1 +#endif + +#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2) +/* this backend supports CURLOPT_PINNEDPUBLICKEY */ +#define DARWIN_SSL_PINNEDPUBKEY 1 +#define have_curlssl_pinnedpubkey 1 +#endif /* DARWIN_SSL_PINNEDPUBKEY */ + /* API setup for SecureTransport */ #define curlssl_init() (1) #define curlssl_cleanup() Curl_nop_stmt @@ -70,6 +93,7 @@ bool Curl_darwinssl_false_start(void); #define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y) #define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z)) #define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d) +#define curlssl_sha256sum(a,b,c,d) Curl_darwinssl_sha256sum(a,b,c,d) #define curlssl_false_start() Curl_darwinssl_false_start() #endif /* USE_DARWINSSL */ diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c index 3b0cfd5a0..bf75bddc2 100644 --- a/Utilities/cmcurl/lib/vtls/gskit.c +++ b/Utilities/cmcurl/lib/vtls/gskit.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,6 +81,10 @@ #include "memdebug.h" +/* Directions. */ +#define SOS_READ 0x01 +#define SOS_WRITE 0x02 + /* SSL version flags. */ #define CURL_GSKPROTO_SSLV2 0 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) @@ -151,7 +155,7 @@ static const gskit_cipher ciphertable[] = { static bool is_separator(char c) { /* Return whether character is a cipher list separator. */ - switch (c) { + switch(c) { case ' ': case '\t': case ':': @@ -167,7 +171,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, const char *procname, CURLcode defcode) { /* Process GSKit status and map it to a CURLcode. */ - switch (rc) { + switch(rc) { case GSK_OK: case GSK_OS400_ASYNCHRONOUS_SOC_INIT: return CURLE_OK; @@ -190,7 +194,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, case GSK_OS400_ERROR_NOT_REGISTERED: break; case GSK_ERROR_IO: - switch (errno) { + switch(errno) { case ENOMEM: return CURLE_OUT_OF_MEMORY; default: @@ -211,7 +215,7 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, { int rc = gsk_attribute_set_enum(h, id, value); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -233,7 +237,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, { int rc = gsk_attribute_set_buffer(h, id, buffer, 0); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -255,7 +259,7 @@ static CURLcode set_numeric(struct Curl_easy *data, { int rc = gsk_attribute_set_numeric_value(h, id, value); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -275,7 +279,7 @@ static CURLcode set_callback(struct Curl_easy *data, { int rc = gsk_attribute_set_callback(h, id, info); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -289,10 +293,11 @@ static CURLcode set_callback(struct Curl_easy *data, } -static CURLcode set_ciphers(struct Curl_easy *data, +static CURLcode set_ciphers(struct connectdata *conn, gsk_handle h, unsigned int *protoflags) { - const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST]; + struct Curl_easy *data = conn->data; + const char *cipherlist = SSL_CONN_CONFIG(cipher_list); const char *clp; const gskit_cipher *ctp; int i; @@ -315,7 +320,7 @@ static CURLcode set_ciphers(struct Curl_easy *data, /* We allocate GSKit buffers of the same size as the input string: since GSKit tokens are always shorter than their cipher names, allocated buffers - will always be large enough to accomodate the result. */ + will always be large enough to accommodate the result. */ l = strlen(cipherlist) + 1; memset((char *) ciphers, 0, sizeof ciphers); for(i = 0; i < CURL_GSKPROTO_LAST; i++) { @@ -340,7 +345,7 @@ static CURLcode set_ciphers(struct Curl_easy *data, break; /* Search the cipher in our table. */ for(ctp = ciphertable; ctp->name; ctp++) - if(strnequal(ctp->name, clp, l) && !ctp->name[l]) + if(strncasecompare(ctp->name, clp, l) && !ctp->name[l]) break; if(!ctp->name) { failf(data, "Unknown cipher %.*s", l, clp); @@ -448,7 +453,7 @@ static CURLcode init_environment(struct Curl_easy *data, /* Creates the GSKit environment. */ rc = gsk_environment_open(&h); - switch (rc) { + switch(rc) { case GSK_OK: break; case GSK_INSUFFICIENT_STORAGE: @@ -500,17 +505,195 @@ static void close_async_handshake(struct ssl_connect_data *connssl) connssl->iocport = -1; } +/* SSL over SSL + * Problems: + * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To + * pipe an SSL stream into another, it is therefore needed to have a pair + * of such communicating sockets and handle the pipelining explicitly. + * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot + * be used to produce the pipeline. + * The solution is to simulate socketpair() for AF_INET with low-level API + * listen(), bind() and connect(). + */ + +static int +inetsocketpair(int sv[2]) +{ + int lfd; /* Listening socket. */ + int sfd; /* Server socket. */ + int cfd; /* Client socket. */ + int len; + struct sockaddr_in addr1; + struct sockaddr_in addr2; + + /* Create listening socket on a local dynamic port. */ + lfd = socket(AF_INET, SOCK_STREAM, 0); + if(lfd < 0) + return -1; + memset((char *) &addr1, 0, sizeof addr1); + addr1.sin_family = AF_INET; + addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr1.sin_port = 0; + if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) || + listen(lfd, 2) < 0) { + close(lfd); + return -1; + } + + /* Get the allocated port. */ + len = sizeof addr1; + if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) { + close(lfd); + return -1; + } + + /* Create the client socket. */ + cfd = socket(AF_INET, SOCK_STREAM, 0); + if(cfd < 0) { + close(lfd); + return -1; + } + + /* Request unblocking connection to the listening socket. */ + curlx_nonblock(cfd, TRUE); + if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 && + errno != EINPROGRESS) { + close(lfd); + close(cfd); + return -1; + } + + /* Get the client dynamic port for intrusion check below. */ + len = sizeof addr2; + if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) { + close(lfd); + close(cfd); + return -1; + } + + /* Accept the incoming connection and get the server socket. */ + curlx_nonblock(lfd, TRUE); + for(;;) { + len = sizeof addr1; + sfd = accept(lfd, (struct sockaddr *) &addr1, &len); + if(sfd < 0) { + close(lfd); + close(cfd); + return -1; + } + + /* Check for possible intrusion from an external process. */ + if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr && + addr1.sin_port == addr2.sin_port) + break; + + /* Intrusion: reject incoming connection. */ + close(sfd); + } + + /* Done, return sockets and succeed. */ + close(lfd); + curlx_nonblock(cfd, FALSE); + sv[0] = cfd; + sv[1] = sfd; + return 0; +} + +static int pipe_ssloverssl(struct connectdata *conn, int sockindex, + int directions) +{ + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; + fd_set fds_read; + fd_set fds_write; + int n; + int m; + int i; + int ret = 0; + struct timeval tv = {0, 0}; + char buf[CURL_MAX_WRITE_SIZE]; + + if(!connssl->use || !connproxyssl->use) + return 0; /* No SSL over SSL: OK. */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + n = -1; + if(directions & SOS_READ) { + FD_SET(connssl->remotefd, &fds_write); + n = connssl->remotefd; + } + if(directions & SOS_WRITE) { + FD_SET(connssl->remotefd, &fds_read); + n = connssl->remotefd; + FD_SET(conn->sock[sockindex], &fds_write); + if(n < conn->sock[sockindex]) + n = conn->sock[sockindex]; + } + i = select(n + 1, &fds_read, &fds_write, NULL, &tv); + if(i < 0) + return -1; /* Select error. */ + + if(FD_ISSET(connssl->remotefd, &fds_write)) { + /* Try getting data from HTTPS proxy and pipe it upstream. */ + n = 0; + i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n); + switch(i) { + case GSK_OK: + if(n) { + i = write(connssl->remotefd, buf, n); + if(i < 0) + return -1; + ret = 1; + } + break; + case GSK_OS400_ERROR_TIMED_OUT: + case GSK_WOULD_BLOCK: + break; + default: + return -1; + } + } + + if(FD_ISSET(connssl->remotefd, &fds_read) && + FD_ISSET(conn->sock[sockindex], &fds_write)) { + /* Pipe data to HTTPS proxy. */ + n = read(connssl->remotefd, buf, sizeof buf); + if(n < 0) + return -1; + if(n) { + i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m); + if(i != GSK_OK || n != m) + return -1; + ret = 1; + } + } + + return ret; /* OK */ +} + -static void close_one(struct ssl_connect_data *conn, - struct Curl_easy *data) +static void close_one(struct ssl_connect_data *connssl, + struct connectdata *conn, int sockindex) { - if(conn->handle) { - gskit_status(data, gsk_secure_soc_close(&conn->handle), + if(connssl->handle) { + gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle), "gsk_secure_soc_close()", 0); - conn->handle = (gsk_handle) NULL; + /* Last chance to drain output. */ + while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) + ; + connssl->handle = (gsk_handle) NULL; + if(connssl->localfd >= 0) { + close(connssl->localfd); + connssl->localfd = -1; + } + if(connssl->remotefd >= 0) { + close(connssl->remotefd); + connssl->remotefd = -1; + } } - if(conn->iocport >= 0) - close_async_handshake(conn); + if(connssl->iocport >= 0) + close_async_handshake(connssl); } @@ -518,13 +701,18 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { struct Curl_easy *data = conn->data; - CURLcode cc; + CURLcode cc = CURLE_SEND_ERROR; int written; - cc = gskit_status(data, - gsk_secure_soc_write(conn->ssl[sockindex].handle, - (char *) mem, (int) len, &written), - "gsk_secure_soc_write()", CURLE_SEND_ERROR); + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) { + cc = gskit_status(data, + gsk_secure_soc_write(conn->ssl[sockindex].handle, + (char *) mem, (int) len, &written), + "gsk_secure_soc_write()", CURLE_SEND_ERROR); + if(cc == CURLE_OK) + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0) + cc = CURLE_SEND_ERROR; + } if(cc != CURLE_OK) { *curlcode = cc; written = -1; @@ -539,19 +727,61 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, struct Curl_easy *data = conn->data; int buffsize; int nread; - CURLcode cc; + CURLcode cc = CURLE_RECV_ERROR; - buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; - cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle, - buf, buffsize, &nread), - "gsk_secure_soc_read()", CURLE_RECV_ERROR); - if(cc != CURLE_OK) { + if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { + buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; + cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle, + buf, buffsize, &nread), + "gsk_secure_soc_read()", CURLE_RECV_ERROR); + } + switch(cc) { + case CURLE_OK: + break; + case CURLE_OPERATION_TIMEDOUT: + cc = CURLE_AGAIN; + default: *curlcode = cc; nread = -1; + break; } return (ssize_t) nread; } +static CURLcode +set_ssl_version_min_max(unsigned int *protoflags, 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; + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_TLSv1_2; + break; + } + for(; i <= (ssl_version_max >> 16); ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + *protoflags |= CURL_GSKPROTO_TLSV10_MASK; + break; + case CURL_SSLVERSION_TLSv1_1: + *protoflags |= CURL_GSKPROTO_TLSV11_MASK; + break; + case CURL_SSLVERSION_TLSv1_2: + *protoflags |= CURL_GSKPROTO_TLSV11_MASK; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "GSKit: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + + return CURLE_OK; +} static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) { @@ -560,18 +790,26 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) gsk_handle envir; CURLcode result; int rc; - char *keyringfile; - char *keyringpwd; - char *keyringlabel; - char *sni; - unsigned int protoflags; + 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 long int ssl_version = SSL_CONN_CONFIG(version); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char *sni; + unsigned int protoflags = 0; long timeout; Qso_OverlappedIO_t commarea; + int sockpair[2]; + static const int sobufsize = CURL_MAX_WRITE_SIZE; /* Create SSL environment, start (preferably asynchronous) handshake. */ connssl->handle = (gsk_handle) NULL; connssl->iocport = -1; + connssl->localfd = -1; + connssl->remotefd = -1; /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system @@ -586,9 +824,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) * application identifier mode is tried first, as recommended in IBM doc. */ - keyringfile = data->set.str[STRING_SSL_CAFILE]; - keyringpwd = data->set.str[STRING_KEY_PASSWD]; - keyringlabel = data->set.str[STRING_CERT]; envir = (gsk_handle) NULL; if(keyringlabel && *keyringlabel && !keyringpwd && @@ -613,32 +848,51 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) if(result) return result; + /* Establish a pipelining socket pair for SSL over SSL. */ + if(conn->proxy_ssl[sockindex].use) { + if(inetsocketpair(sockpair)) + return CURLE_SSL_CONNECT_ERROR; + connssl->localfd = sockpair[0]; + connssl->remotefd = sockpair[1]; + setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof sobufsize); + setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof sobufsize); + setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof sobufsize); + setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof sobufsize); + curlx_nonblock(connssl->localfd, TRUE); + curlx_nonblock(connssl->remotefd, TRUE); + } + /* Determine which SSL/TLS version should be enabled. */ - protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | - CURL_GSKPROTO_TLSV12_MASK; - sni = conn->host.name; - switch (data->set.ssl.version) { + sni = hostname; + switch(ssl_version) { case CURL_SSLVERSION_SSLv2: protoflags = CURL_GSKPROTO_SSLV2_MASK; - sni = (char *) NULL; + sni = NULL; break; case CURL_SSLVERSION_SSLv3: protoflags = CURL_GSKPROTO_SSLV3_MASK; - sni = (char *) NULL; + sni = NULL; break; + case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; break; case CURL_SSLVERSION_TLSv1_0: - protoflags = CURL_GSKPROTO_TLSV10_MASK; - break; case CURL_SSLVERSION_TLSv1_1: - protoflags = CURL_GSKPROTO_TLSV11_MASK; - break; case CURL_SSLVERSION_TLSv1_2: - protoflags = CURL_GSKPROTO_TLSV12_MASK; + case CURL_SSLVERSION_TLSv1_3: + result = set_ssl_version_min_max(&protoflags, conn); + if(result != CURLE_OK) + return result; break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ @@ -661,9 +915,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) (timeout + 999) / 1000); } if(!result) - result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); + result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1); if(!result) - result = set_ciphers(data, connssl->handle, &protoflags); + result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0? + connssl->localfd: conn->sock[sockindex]); + if(!result) + result = set_ciphers(conn, connssl->handle, &protoflags); if(!protoflags) { failf(data, "No SSL protocol/cipher combination enabled"); result = CURLE_SSL_CIPHER; @@ -706,7 +963,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) } if(!result) result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, - data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL: + verifypeer? GSK_SERVER_AUTH_FULL: GSK_SERVER_AUTH_PASSTHRU, FALSE); if(!result) { @@ -730,6 +987,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) else if(errno != ENOBUFS) result = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); + else if(conn->proxy_ssl[sockindex].use) { + /* Cannot pipeline while handshaking synchronously. */ + result = CURLE_SSL_CONNECT_ERROR; + } else { /* No more completion port available. Use synchronous IO. */ result = gskit_status(data, gsk_secure_soc_init(connssl->handle), @@ -742,7 +1003,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) } /* Error: rollback. */ - close_one(connssl, data); + close_one(connssl, conn, sockindex); return result; } @@ -765,7 +1026,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, timeout_ms = 0; stmv.tv_sec = timeout_ms / 1000; stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; - switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) { + switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) { case 1: /* Operation complete. */ break; case -1: /* An error occurred: handshake still in progress. */ @@ -822,7 +1083,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) infof(data, "Server certificate:\n"); p = cdev; for(i = 0; i++ < cdec; p++) - switch (p->cert_data_id) { + switch(p->cert_data_id) { case CERT_BODY_DER: cert = p->cert_data_p; certend = cert + cdev->cert_data_l; @@ -865,14 +1126,14 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) } /* Check pinned public key. */ - ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(!result && ptr) { curl_X509certificate x509; curl_asn1Element *p; - if(!cert) + if(Curl_parseX509(&x509, cert, certend)) return CURLE_SSL_PINNEDPUBKEYNOTMATCH; - Curl_parseX509(&x509, cert, certend); p = &x509.subjectPublicKeyInfo; result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header); if(result) { @@ -913,6 +1174,11 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, result = gskit_connect_step1(conn, sockindex); } + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + /* Step 2: check if handshake is over. */ if(!result && connssl->connecting_state == ssl_connect_2) { /* check allowed time left */ @@ -927,12 +1193,17 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, result = gskit_connect_step2(conn, sockindex, nonblocking); } + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + /* Step 3: gather certificate info, verify host. */ if(!result && connssl->connecting_state == ssl_connect_3) result = gskit_connect_step3(conn, sockindex); if(result) - close_one(connssl, data); + close_one(connssl, conn, sockindex); else if(connssl->connecting_state == ssl_connect_done) { connssl->state = ssl_connection_complete; connssl->connecting_state = ssl_connect_1; @@ -976,11 +1247,8 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) void Curl_gskit_close(struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - if(connssl->use) - close_one(connssl, data); + close_one(&conn->ssl[sockindex], conn, sockindex); + close_one(&conn->proxy_ssl[sockindex], conn, sockindex); } @@ -999,7 +1267,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) return 0; - close_one(connssl, data); + close_one(connssl, conn, sockindex); rc = 0; what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h index 41483cba6..229759217 100644 --- a/Utilities/cmcurl/lib/vtls/gskit.h +++ b/Utilities/cmcurl/lib/vtls/gskit.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,6 +41,9 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex); size_t Curl_gskit_version(char *buffer, size_t size); int Curl_gskit_check_cxn(struct connectdata *cxn); +/* Support HTTPS-proxy */ +/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */ + /* Set the API backend definition to GSKit */ #define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT @@ -64,7 +67,7 @@ int Curl_gskit_check_cxn(struct connectdata *cxn); #define curlssl_version Curl_gskit_version #define curlssl_check_cxn(x) Curl_gskit_check_cxn(x) #define curlssl_data_pending(x,y) 0 -#define curlssl_random(x,y,z) -1 +#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN) #endif /* USE_GSKIT */ diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c index 5c87c7fe3..844be2de1 100644 --- a/Utilities/cmcurl/lib/vtls/gtls.c +++ b/Utilities/cmcurl/lib/vtls/gtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -68,7 +68,7 @@ #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p)) #endif #ifndef GNUTLS_INT_TO_POINTER_CAST -#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i)) +#define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i)) #endif /* Enable GnuTLS debugging by defining GTLSDEBUG */ @@ -92,11 +92,11 @@ static bool gtls_inited = FALSE; # define GNUTLS_MAPS_WINSOCK_ERRORS 1 # endif -# if (GNUTLS_VERSION_NUMBER >= 0x030200) +# if HAVE_GNUTLS_ALPN_SET_PROTOCOLS # define HAS_ALPN # endif -# if (GNUTLS_VERSION_NUMBER >= 0x03020d) +# if HAVE_GNUTLS_OCSP_REQ_INIT # define HAS_OCSP # endif @@ -171,6 +171,16 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) return ret; } +static ssize_t Curl_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) +{ + return gnutls_record_recv((gnutls_session_t) s, buf, len); +} + /* Curl_gtls_init() * * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that @@ -201,18 +211,20 @@ int Curl_gtls_cleanup(void) return 1; } +#ifndef CURL_DISABLE_VERBOSE_STRINGS static void showtime(struct Curl_easy *data, const char *text, time_t stamp) { struct tm buffer; const struct tm *tm = &buffer; + char str[96]; CURLcode result = Curl_gmtime(stamp, &buffer); if(result) return; - snprintf(data->state.buffer, - BUFSIZE, + snprintf(str, + sizeof(str), "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT", text, Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], @@ -222,17 +234,19 @@ static void showtime(struct Curl_easy *data, tm->tm_hour, tm->tm_min, tm->tm_sec); - infof(data, "%s\n", data->state.buffer); + infof(data, "%s\n", str); } +#endif -static gnutls_datum_t load_file (const char *file) +static gnutls_datum_t load_file(const char *file) { FILE *f; gnutls_datum_t loaded_file = { NULL, 0 }; long filelen; void *ptr; - if(!(f = fopen(file, "rb"))) + f = fopen(file, "rb"); + if(!f) return loaded_file; if(fseek(f, 0, SEEK_END) != 0 || (filelen = ftell(f)) < 0 @@ -251,7 +265,8 @@ out: return loaded_file; } -static void unload_file(gnutls_datum_t data) { +static void unload_file(gnutls_datum_t data) +{ free(data.data); } @@ -266,7 +281,7 @@ static CURLcode handshake(struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; gnutls_session_t session = conn->ssl[sockindex].session; curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; + time_t timeout_ms; int rc; int what; @@ -302,7 +317,7 @@ static CURLcode handshake(struct connectdata *conn, return CURLE_OK; else if(timeout_ms) { /* timeout */ - failf(data, "SSL connection timeout at %ld", timeout_ms); + failf(data, "SSL connection timeout at %ld", (long)timeout_ms); return CURLE_OPERATION_TIMEDOUT; } } @@ -363,14 +378,112 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type) return -1; } +#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT +static CURLcode +set_ssl_version_min_max(int *list, size_t list_size, 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; + long protocol_priority_idx = 0; + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version << 16; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + for(; i <= (ssl_version_max >> 16) && + protocol_priority_idx < list_size; ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0; + break; + case CURL_SSLVERSION_TLSv1_1: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1; + break; + case CURL_SSLVERSION_TLSv1_2: + protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +} +#else +#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" +/* If GnuTLS was compiled without support for SRP it will error out if SRP is + requested in the priority string, so treat it specially + */ +#define GNUTLS_SRP "+SRP" + +static CURLcode +set_ssl_version_min_max(const char **prioritylist, 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); + if(ssl_version == CURL_SSLVERSION_TLSv1_3 || + ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) { + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) { + ssl_version_max = ssl_version << 16; + } + switch(ssl_version | ssl_version_max) { + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2: + case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2: + case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2: + case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT: + *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" + "+VERS-TLS1.2:" GNUTLS_SRP; + return CURLE_OK; + } + + failf(data, "GnuTLS: cannot set ssl protocol"); + return CURLE_SSL_CONNECT_ERROR; +} +#endif + static CURLcode gtls_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; + unsigned int init_flags; gnutls_session_t session; int rc; bool sni = TRUE; /* default is SNI enabled */ + void *transport_ptr = NULL; + gnutls_push_func gnutls_transport_push = NULL; + gnutls_pull_func gnutls_transport_pull = NULL; #ifdef ENABLE_IPV6 struct in6_addr addr; #else @@ -390,17 +503,15 @@ gtls_connect_step1(struct connectdata *conn, GNUTLS_CIPHER_3DES_CBC, }; static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; - static int protocol_priority[] = { 0, 0, 0, 0 }; + int protocol_priority[] = { 0, 0, 0, 0 }; #else -#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" -/* If GnuTLS was compiled without support for SRP it will error out if SRP is - requested in the priority string, so treat it specially - */ -#define GNUTLS_SRP "+SRP" - const char* prioritylist; + const char *prioritylist; const char *err = NULL; #endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the same connection */ @@ -409,12 +520,11 @@ gtls_connect_step1(struct connectdata *conn, if(!gtls_inited) Curl_gtls_init(); - /* GnuTLS only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } - else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) + else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ /* allocate a cred struct */ @@ -425,8 +535,8 @@ gtls_connect_step1(struct connectdata *conn, } #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); rc = gnutls_srp_allocate_client_credentials( &conn->ssl[sockindex].srp_client_cred); @@ -438,8 +548,8 @@ gtls_connect_step1(struct connectdata *conn, rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. srp_client_cred, - data->set.ssl.username, - data->set.ssl.password); + SSL_SET_OPTION(username), + SSL_SET_OPTION(password)); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_set_client_cred() failed: %s", gnutls_strerror(rc)); @@ -448,68 +558,75 @@ gtls_connect_step1(struct connectdata *conn, } #endif - if(data->set.ssl.CAfile) { + if(SSL_CONN_CONFIG(CAfile)) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, - data->set.ssl.CAfile, + SSL_CONN_CONFIG(CAfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", - data->set.ssl.CAfile, gnutls_strerror(rc)); - if(data->set.ssl.verifypeer) + SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } else - infof(data, "found %d certificates in %s\n", - rc, data->set.ssl.CAfile); + infof(data, "found %d certificates in %s\n", rc, + SSL_CONN_CONFIG(CAfile)); } #ifdef HAS_CAPATH - if(data->set.ssl.CApath) { + if(SSL_CONN_CONFIG(CApath)) { /* set the trusted CA cert directory */ rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred, - data->set.ssl.CApath, - GNUTLS_X509_FMT_PEM); + SSL_CONN_CONFIG(CApath), + GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", - data->set.ssl.CAfile, gnutls_strerror(rc)); - if(data->set.ssl.verifypeer) + SSL_CONN_CONFIG(CApath), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", - rc, data->set.ssl.CApath); + rc, SSL_CONN_CONFIG(CApath)); } #endif #ifdef CURL_CA_FALLBACK /* use system ca certificate store as fallback */ - if(data->set.ssl.verifypeer && - !(data->set.ssl.CAfile || data->set.ssl.CApath)) { + if(SSL_CONN_CONFIG(verifypeer) && + !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) { gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred); } #endif - if(data->set.ssl.CRLfile) { + if(SSL_SET_OPTION(CRLfile)) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, - data->set.ssl.CRLfile, + SSL_SET_OPTION(CRLfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { failf(data, "error reading crl file %s (%s)", - data->set.ssl.CRLfile, gnutls_strerror(rc)); + SSL_SET_OPTION(CRLfile), gnutls_strerror(rc)); return CURLE_SSL_CRL_BADFILE; } else infof(data, "found %d CRL in %s\n", - rc, data->set.ssl.CRLfile); + rc, SSL_SET_OPTION(CRLfile)); } /* Initialize TLS session as a client */ - rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); + init_flags = GNUTLS_CLIENT; + +#if defined(GNUTLS_NO_TICKETS) + /* Disable TLS session tickets */ + init_flags |= GNUTLS_NO_TICKETS; +#endif + + rc = gnutls_init(&conn->ssl[sockindex].session, init_flags); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_init() failed: %d", rc); return CURLE_SSL_CONNECT_ERROR; @@ -518,13 +635,13 @@ gtls_connect_step1(struct connectdata *conn, /* convenient assign */ session = conn->ssl[sockindex].session; - if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif sni && - (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, - strlen(conn->host.name)) < 0)) + (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, + strlen(hostname)) < 0)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); @@ -545,13 +662,13 @@ gtls_connect_step1(struct connectdata *conn, if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; - if(data->set.ssl.cipher_list != NULL) { + if(SSL_CONN_CONFIG(cipher_list) != NULL) { failf(data, "can't pass a custom cipher list to older GnuTLS" " versions"); return CURLE_SSL_CONNECT_ERROR; } - switch (data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_SSLv3: protocol_priority[0] = GNUTLS_SSL3; break; @@ -562,19 +679,22 @@ gtls_connect_step1(struct connectdata *conn, protocol_priority[2] = GNUTLS_TLS1_2; break; case CURL_SSLVERSION_TLSv1_0: - protocol_priority[0] = GNUTLS_TLS1_0; - break; case CURL_SSLVERSION_TLSv1_1: - protocol_priority[0] = GNUTLS_TLS1_1; - break; case CURL_SSLVERSION_TLSv1_2: - protocol_priority[0] = GNUTLS_TLS1_2; - break; - case CURL_SSLVERSION_SSLv2: - default: + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(protocol_priority, + sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn); + if(result != CURLE_OK) + return result; + break; + } + case CURL_SSLVERSION_SSLv2: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; - break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } rc = gnutls_protocol_set_priority(session, protocol_priority); if(rc != GNUTLS_E_SUCCESS) { @@ -586,7 +706,7 @@ gtls_connect_step1(struct connectdata *conn, /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ - switch (data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_SSLv3: prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; sni = false; @@ -596,22 +716,21 @@ gtls_connect_step1(struct connectdata *conn, prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP; break; case CURL_SSLVERSION_TLSv1_0: - prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.0:" GNUTLS_SRP; - break; case CURL_SSLVERSION_TLSv1_1: - prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.1:" GNUTLS_SRP; - break; case CURL_SSLVERSION_TLSv1_2: - prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" - "+VERS-TLS1.2:" GNUTLS_SRP; - break; + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(&prioritylist, conn); + if(result != CURLE_OK) + return result; + break; + } case CURL_SSLVERSION_SSLv2: - default: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; - break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } rc = gnutls_priority_set_direct(session, prioritylist, &err); if((rc == GNUTLS_E_INVALID_REQUEST) && err) { @@ -661,8 +780,8 @@ gtls_connect_step1(struct connectdata *conn, } #endif - if(data->set.str[STRING_CERT]) { - if(data->set.str[STRING_KEY_PASSWD]) { + if(SSL_SET_OPTION(cert)) { + if(SSL_SET_OPTION(key_passwd)) { #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 const unsigned int supported_key_encryption_algorithms = GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | @@ -671,11 +790,11 @@ gtls_connect_step1(struct connectdata *conn, GNUTLS_PKCS_USE_PBES2_AES_256; rc = gnutls_certificate_set_x509_key_file2( conn->ssl[sockindex].cred, - data->set.str[STRING_CERT], - data->set.str[STRING_KEY] ? - data->set.str[STRING_KEY] : data->set.str[STRING_CERT], - do_file_type(data->set.str[STRING_CERT_TYPE]), - data->set.str[STRING_KEY_PASSWD], + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)), + SSL_SET_OPTION(key_passwd), supported_key_encryption_algorithms); if(rc != GNUTLS_E_SUCCESS) { failf(data, @@ -689,15 +808,14 @@ gtls_connect_step1(struct connectdata *conn, #endif } else { - rc = gnutls_certificate_set_x509_key_file( + if(gnutls_certificate_set_x509_key_file( conn->ssl[sockindex].cred, - data->set.str[STRING_CERT], - data->set.str[STRING_KEY] ? - data->set.str[STRING_KEY] : data->set.str[STRING_CERT], - do_file_type(data->set.str[STRING_CERT_TYPE]) ); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "error reading X.509 key or certificate file: %s", - gnutls_strerror(rc)); + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)) ) != + GNUTLS_E_SUCCESS) { + failf(data, "error reading X.509 key or certificate file"); return CURLE_SSL_CONNECT_ERROR; } } @@ -705,7 +823,7 @@ gtls_connect_step1(struct connectdata *conn, #ifdef USE_TLS_SRP /* put the credentials to the current session */ - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { @@ -724,19 +842,30 @@ gtls_connect_step1(struct connectdata *conn, } } - /* set the connection handle (file descriptor for the socket) */ - gnutls_transport_set_ptr(session, - GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); + if(conn->proxy_ssl[sockindex].use) { + transport_ptr = conn->proxy_ssl[sockindex].session; + gnutls_transport_push = Curl_gtls_push_ssl; + gnutls_transport_pull = Curl_gtls_pull_ssl; + } + else { + /* file descriptor for the socket */ + transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]); + gnutls_transport_push = Curl_gtls_push; + gnutls_transport_pull = Curl_gtls_pull; + } + + /* set the connection handle */ + gnutls_transport_set_ptr(session, transport_ptr); /* register callback functions to send and receive data. */ - gnutls_transport_set_push_function(session, Curl_gtls_push); - gnutls_transport_set_pull_function(session, Curl_gtls_pull); + gnutls_transport_set_push_function(session, gnutls_transport_push); + gnutls_transport_set_pull_function(session, gnutls_transport_pull); /* lowat must be set to zero when using custom push and pull functions. */ gnutls_transport_set_lowat(session, 0); #ifdef HAS_OCSP - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); @@ -747,17 +876,17 @@ gtls_connect_step1(struct connectdata *conn, /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid; size_t ssl_idsize; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { + if(!Curl_ssl_getsessionid(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"); + infof(data, "SSL re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); } @@ -836,8 +965,6 @@ gtls_connect_step3(struct connectdata *conn, gnutls_datum_t issuerp; char certbuf[256] = ""; /* big enough? */ size_t size; - unsigned int algo; - unsigned int bits; time_t certclock; const char *ptr; struct Curl_easy *data = conn->data; @@ -847,8 +974,13 @@ gtls_connect_step3(struct connectdata *conn, gnutls_datum_t proto; #endif CURLcode result = CURLE_OK; - +#ifndef CURL_DISABLE_VERBOSE_STRINGS + unsigned int algo; + unsigned int bits; gnutls_protocol_t version = gnutls_protocol_get_version(session); +#endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; /* 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), @@ -866,13 +998,13 @@ gtls_connect_step3(struct connectdata *conn, chainp = gnutls_certificate_get_peers(session, &cert_list_size); if(!chainp) { - if(data->set.ssl.verifypeer || - data->set.ssl.verifyhost || - data->set.ssl.issuercert) { + if(SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost) || + SSL_SET_OPTION(issuercert)) { #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP - && data->set.ssl.username != NULL - && !data->set.ssl.verifypeer + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL + && !SSL_CONN_CONFIG(verifypeer) && gnutls_cipher_get(session)) { /* no peer cert, but auth is ok if we have SRP user and cipher and no peer verify */ @@ -905,7 +1037,7 @@ gtls_connect_step3(struct connectdata *conn, } } - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { /* This function will try to verify the peer's certificate and return its status (trusted, invalid etc.). The value of status should be one or more of the gnutls_certificate_status_t enumerated elements bitwise @@ -921,10 +1053,11 @@ gtls_connect_step3(struct connectdata *conn, /* verify_status is a bitmask of gnutls_certificate_status bits */ if(verify_status & GNUTLS_CERT_INVALID) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server certificate verification failed. CAfile: %s " - "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none", - data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none"); + "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): + "none", + SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none"); return CURLE_SSL_CACERT; } else @@ -937,7 +1070,7 @@ gtls_connect_step3(struct connectdata *conn, infof(data, "\t server certificate verification SKIPPED\n"); #ifdef HAS_OCSP - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { gnutls_datum_t status_request; gnutls_ocsp_resp_t ocsp_resp; @@ -1049,21 +1182,21 @@ gtls_connect_step3(struct connectdata *conn, gnutls_x509_crt_t format */ gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); - if(data->set.ssl.issuercert) { + if(SSL_SET_OPTION(issuercert)) { gnutls_x509_crt_init(&x509_issuer); - issuerp = load_file(data->set.ssl.issuercert); + issuerp = load_file(SSL_SET_OPTION(issuercert)); gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer); gnutls_x509_crt_deinit(x509_issuer); unload_file(issuerp); if(rc <= 0) { failf(data, "server certificate issuer check failed (IssuerCert: %s)", - data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_ISSUER_ERROR; } infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n", - data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); } size=sizeof(certbuf); @@ -1082,7 +1215,7 @@ gtls_connect_step3(struct connectdata *conn, in RFC2818 (HTTPS), which takes into account wildcards, and the subject alternative name PKIX extension. Returns non zero on success, and zero on failure. */ - rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); + rc = gnutls_x509_crt_check_hostname(x509_cert, hostname); #if GNUTLS_VERSION_NUMBER < 0x030306 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP addresses. */ @@ -1098,10 +1231,10 @@ gtls_connect_step3(struct connectdata *conn, int i; int ret = 0; - if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0) + if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0) addrlen = 4; #ifdef ENABLE_IPV6 - else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0) + else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0) addrlen = 16; #endif @@ -1126,15 +1259,18 @@ gtls_connect_step3(struct connectdata *conn, } #endif if(!rc) { - if(data->set.ssl.verifyhost) { + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + + if(SSL_CONN_CONFIG(verifyhost)) { failf(data, "SSL: certificate subject name (%s) does not match " - "target host name '%s'", certbuf, conn->host.dispname); + "target host name '%s'", certbuf, dispname); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\t common name: %s (does not match '%s')\n", - certbuf, conn->host.dispname); + certbuf, dispname); } else infof(data, "\t common name: %s (matched)\n", certbuf); @@ -1143,7 +1279,7 @@ gtls_connect_step3(struct connectdata *conn, certclock = gnutls_x509_crt_get_expiration_time(x509_cert); if(certclock == (time_t)-1) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server cert expiration date verify failed"); gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_CONNECT_ERROR; @@ -1153,7 +1289,7 @@ gtls_connect_step3(struct connectdata *conn, } else { if(certclock < time(NULL)) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server certificate expiration date has passed."); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; @@ -1168,7 +1304,7 @@ gtls_connect_step3(struct connectdata *conn, certclock = gnutls_x509_crt_get_activation_time(x509_cert); if(certclock == (time_t)-1) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server cert activation date verify failed"); gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_CONNECT_ERROR; @@ -1178,7 +1314,7 @@ gtls_connect_step3(struct connectdata *conn, } else { if(certclock > time(NULL)) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server certificate not activated yet."); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; @@ -1190,7 +1326,8 @@ gtls_connect_step3(struct connectdata *conn, infof(data, "\t server certificate activation date OK\n"); } - ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(ptr) { result = pkp_pin_peer_pubkey(data, x509_cert, ptr); if(result != CURLE_OK) { @@ -1210,6 +1347,7 @@ gtls_connect_step3(struct connectdata *conn, */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS /* public key algorithm's parameters */ algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); infof(data, "\t certificate public key: %s\n", @@ -1234,12 +1372,13 @@ gtls_connect_step3(struct connectdata *conn, gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); infof(data, "\t issuer: %s\n", certbuf); - gnutls_x509_crt_deinit(x509_cert); - /* compression algorithm (if any) */ ptr = gnutls_compression_get_name(gnutls_compression_get(session)); /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ infof(data, "\t compression: %s\n", ptr); +#endif + + gnutls_x509_crt_deinit(x509_cert); #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { @@ -1270,7 +1409,7 @@ gtls_connect_step3(struct connectdata *conn, conn->recv[sockindex] = gtls_recv; conn->send[sockindex] = gtls_send; - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { /* we always unconditionally get the session id here, as even if we already got it from the cache and asked to use it in the connection, it might've been rejected and then a new one is in use now and we need to @@ -1289,7 +1428,8 @@ gtls_connect_step3(struct connectdata *conn, gnutls_session_get_data(session, connect_sessionid, &connect_idsize); Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)); + incache = !(Curl_ssl_getsessionid(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 */ @@ -1297,7 +1437,8 @@ gtls_connect_step3(struct connectdata *conn, } /* store this session id */ - result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize); + result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize, + sockindex); Curl_ssl_sessionid_unlock(conn); if(result) { free(connect_sessionid); @@ -1332,7 +1473,7 @@ 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(conn, sockindex); if(rc) return rc; } @@ -1379,6 +1520,20 @@ Curl_gtls_connect(struct connectdata *conn, return CURLE_OK; } +bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex) +{ + bool res = FALSE; + if(conn->ssl[connindex].session && + 0 != gnutls_record_check_pending(conn->ssl[connindex].session)) + res = TRUE; + + if(conn->proxy_ssl[connindex].session && + 0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session)) + res = TRUE; + + return res; +} + static ssize_t gtls_send(struct connectdata *conn, int sockindex, const void *mem, @@ -1398,29 +1553,29 @@ static ssize_t gtls_send(struct connectdata *conn, return rc; } -static void close_one(struct connectdata *conn, - int idx) +static void close_one(struct ssl_connect_data *ssl) { - if(conn->ssl[idx].session) { - gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR); - gnutls_deinit(conn->ssl[idx].session); - conn->ssl[idx].session = NULL; + if(ssl->session) { + gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR); + gnutls_deinit(ssl->session); + ssl->session = NULL; } - if(conn->ssl[idx].cred) { - gnutls_certificate_free_credentials(conn->ssl[idx].cred); - conn->ssl[idx].cred = NULL; + if(ssl->cred) { + gnutls_certificate_free_credentials(ssl->cred); + ssl->cred = NULL; } #ifdef USE_TLS_SRP - if(conn->ssl[idx].srp_client_cred) { - gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred); - conn->ssl[idx].srp_client_cred = NULL; + if(ssl->srp_client_cred) { + gnutls_srp_free_client_credentials(ssl->srp_client_cred); + ssl->srp_client_cred = NULL; } #endif } void Curl_gtls_close(struct connectdata *conn, int sockindex) { - close_one(conn, sockindex); + close_one(&conn->ssl[sockindex]); + close_one(&conn->proxy_ssl[sockindex]); } /* @@ -1486,8 +1641,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) gnutls_certificate_free_credentials(conn->ssl[sockindex].cred); #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP - && data->set.ssl.username != NULL) + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL) gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred); #endif @@ -1568,19 +1723,21 @@ static int Curl_gtls_seed(struct Curl_easy *data) #endif /* data might be NULL! */ -int Curl_gtls_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +CURLcode Curl_gtls_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { #if defined(USE_GNUTLS_NETTLE) + int rc; (void)data; - gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length); + rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length); + return rc?CURLE_FAILED_INIT:CURLE_OK; #elif defined(USE_GNUTLS) if(data) Curl_gtls_seed(data); /* Initiate the seed if not already done */ gcry_randomize(entropy, length, GCRY_STRONG_RANDOM); #endif - return 0; + return CURLE_OK; } void Curl_gtls_md5sum(unsigned char *tmp, /* input */ @@ -1597,7 +1754,7 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */ 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); + memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len); gcry_md_close(MD5pw); #endif } @@ -1616,7 +1773,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ gcry_md_hd_t SHA256pw; gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0); gcry_md_write(SHA256pw, tmp, tmplen); - memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len); + memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len); gcry_md_close(SHA256pw); #endif } diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h index e0a95a7cc..462c04853 100644 --- a/Utilities/cmcurl/lib/vtls/gtls.h +++ b/Utilities/cmcurl/lib/vtls/gtls.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,6 +34,8 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex); CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done); +bool Curl_gtls_data_pending(const struct connectdata *conn, + int connindex); /* close a SSL connection */ void Curl_gtls_close(struct connectdata *conn, int sockindex); @@ -41,9 +43,9 @@ void Curl_gtls_close(struct connectdata *conn, int sockindex); void Curl_gtls_session_free(void *ptr); size_t Curl_gtls_version(char *buffer, size_t size); int Curl_gtls_shutdown(struct connectdata *conn, int sockindex); -int Curl_gtls_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length); +CURLcode Curl_gtls_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length); void Curl_gtls_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ @@ -55,6 +57,9 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ bool Curl_gtls_cert_status_request(void); +/* Support HTTPS-proxy */ +#define HTTPS_PROXY_SUPPORT 1 + /* Set the API backend definition to GnuTLS */ #define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS @@ -81,7 +86,7 @@ bool Curl_gtls_cert_status_request(void); #define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) #define curlssl_version Curl_gtls_version #define curlssl_check_cxn(x) ((void)x, -1) -#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y) #define curlssl_random(x,y,z) Curl_gtls_random(x,y,z) #define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d) #define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d) diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c index 24249dd65..037babe38 100644 --- a/Utilities/cmcurl/lib/vtls/mbedtls.c +++ b/Utilities/cmcurl/lib/vtls/mbedtls.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010 - 2011, Hoi-Ho Chan, - * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,11 +31,15 @@ #ifdef USE_MBEDTLS +#include +#if MBEDTLS_VERSION_NUMBER >= 0x02040000 #include +#else +#include +#endif #include #include #include -#include #include #include @@ -63,7 +67,7 @@ #endif #if defined(THREADING_SUPPORT) -static mbedtls_entropy_context entropy; +static mbedtls_entropy_context ts_entropy; static int entropy_init_initialized = 0; @@ -127,7 +131,7 @@ static void mbed_debug(void *context, int level, const char *f_name, /* * profile */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = +static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = { /* Hashes from SHA-1 and above */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | @@ -153,29 +157,101 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = static Curl_recv mbed_recv; static Curl_send mbed_send; +static CURLcode mbedtls_version_from_curl(int *mbedver, long version) +{ + switch(version) { + case CURL_SSLVERSION_TLSv1_0: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_2; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2: + *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + +static CURLcode +set_ssl_version_min_max(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; + int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + CURLcode result = CURLE_OK; + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version << 16; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ver_min); + mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, + mbedtls_ver_max); + + return result; +} + static CURLcode mbed_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; - + 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); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + 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; int ret = -1; char errorbuf[128]; errorbuf[0]=0; /* mbedTLS only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } #ifdef THREADING_SUPPORT - entropy_init_mutex(&entropy); + entropy_init_mutex(&ts_entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex, - &entropy, NULL, 0); + &ts_entropy, NULL, 0); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); @@ -201,34 +277,32 @@ mbed_connect_step1(struct connectdata *conn, /* Load the trusted CA */ mbedtls_x509_crt_init(&connssl->cacert); - if(data->set.str[STRING_SSL_CAFILE]) { - ret = mbedtls_x509_crt_parse_file(&connssl->cacert, - data->set.str[STRING_SSL_CAFILE]); + if(ssl_cafile) { + ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); + ssl_cafile, -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } - if(data->set.str[STRING_SSL_CAPATH]) { - ret = mbedtls_x509_crt_parse_path(&connssl->cacert, - data->set.str[STRING_SSL_CAPATH]); + if(ssl_capath) { + ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); + ssl_capath, -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } @@ -236,16 +310,15 @@ mbed_connect_step1(struct connectdata *conn, /* Load the client certificate */ mbedtls_x509_crt_init(&connssl->clicert); - if(data->set.str[STRING_CERT]) { - ret = mbedtls_x509_crt_parse_file(&connssl->clicert, - data->set.str[STRING_CERT]); + if(ssl_cert) { + ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_CERT], -ret, errorbuf); + ssl_cert, -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -254,9 +327,9 @@ mbed_connect_step1(struct connectdata *conn, /* Load the client private key */ mbedtls_pk_init(&connssl->pk); - if(data->set.str[STRING_KEY]) { - ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY], - data->set.str[STRING_KEY_PASSWD]); + if(SSL_SET_OPTION(key)) { + ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; @@ -265,7 +338,7 @@ mbed_connect_step1(struct connectdata *conn, mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_KEY], -ret, errorbuf); + SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -274,23 +347,21 @@ mbed_connect_step1(struct connectdata *conn, /* Load the CRL */ mbedtls_x509_crl_init(&connssl->crl); - if(data->set.str[STRING_SSL_CRLFILE]) { - ret = mbedtls_x509_crl_parse_file(&connssl->crl, - data->set.str[STRING_SSL_CRLFILE]); + if(ssl_crlfile) { + ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); + ssl_crlfile, -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } - infof(data, "mbedTLS: Connecting to %s:%d\n", - conn->host.name, conn->remote_port); + infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port); mbedtls_ssl_config_init(&connssl->config); @@ -312,7 +383,7 @@ mbed_connect_step1(struct connectdata *conn, mbedtls_ssl_conf_cert_profile(&connssl->config, &mbedtls_x509_crt_profile_fr); - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, @@ -327,28 +398,17 @@ mbed_connect_step1(struct connectdata *conn, infof(data, "mbedTLS: Set SSL version to SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: - mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_1); - mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_1); - infof(data, "mbedTLS: Set SSL version to TLS 1.0\n"); - break; case CURL_SSLVERSION_TLSv1_1: - mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_2); - mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_2); - infof(data, "mbedTLS: Set SSL version to TLS 1.1\n"); - break; case CURL_SSLVERSION_TLSv1_2: - mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_3); - mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_3); - infof(data, "mbedTLS: Set SSL version to TLS 1.2\n"); - break; + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } default: - failf(data, "mbedTLS: Unsupported SSL protocol version"); + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } @@ -364,12 +424,22 @@ mbed_connect_step1(struct connectdata *conn, mbedtls_ssl_conf_ciphersuites(&connssl->config, mbedtls_ssl_list_ciphersuites()); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation(&connssl->config, + MBEDTLS_SSL_RENEGOTIATION_ENABLED); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_session_tickets(&connssl->config, + MBEDTLS_SSL_SESSION_TICKETS_DISABLED); +#endif + /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = mbedtls_ssl_set_session(&connssl->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); @@ -385,11 +455,11 @@ mbed_connect_step1(struct connectdata *conn, &connssl->cacert, &connssl->crl); - if(data->set.str[STRING_KEY]) { + if(SSL_SET_OPTION(key)) { mbedtls_ssl_conf_own_cert(&connssl->config, &connssl->clicert, &connssl->pk); } - if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) { + if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) { /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ @@ -430,6 +500,16 @@ mbed_connect_step1(struct connectdata *conn, mbedtls_debug_set_threshold(4); #endif + /* give application a chance to interfere with mbedTLS set up. */ + if(data->set.ssl.fsslctx) { + ret = (*data->set.ssl.fsslctx)(data, &connssl->config, + data->set.ssl.fsslctxp); + if(ret) { + failf(data, "error signaled by ssl ctx callback"); + return ret; + } + } + connssl->connecting_state = ssl_connect_2; return CURLE_OK; @@ -443,9 +523,12 @@ mbed_connect_step2(struct connectdata *conn, struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; const mbedtls_x509_crt *peercert; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; #ifdef HAS_ALPN - const char* next_protocol; + const char *next_protocol; #endif char errorbuf[128]; @@ -479,7 +562,7 @@ mbed_connect_step2(struct connectdata *conn, ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl); - if(ret && data->set.ssl.verifypeer) { + if(ret && SSL_CONN_CONFIG(verifypeer)) { if(ret & MBEDTLS_X509_BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); @@ -514,7 +597,7 @@ mbed_connect_step2(struct connectdata *conn, free(buffer); } - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + if(pinnedpubkey) { int size; CURLcode result; mbedtls_x509_crt *p; @@ -553,7 +636,7 @@ mbed_connect_step2(struct connectdata *conn, /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, - data->set.str[STRING_SSL_PINNEDPUBLICKEY], + pinnedpubkey, &pubkey[PUB_DER_MAX_BYTES - size], size); if(result) { mbedtls_x509_crt_free(p); @@ -606,7 +689,7 @@ mbed_connect_step3(struct connectdata *conn, DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { int ret; mbedtls_ssl_session *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -619,16 +702,17 @@ mbed_connect_step3(struct connectdata *conn, ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid); if(ret) { + free(our_ssl_sessionid); failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } /* 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)) + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) Curl_ssl_delsessionid(conn, old_ssl_sessionid); - retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0); + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); Curl_ssl_sessionid_unlock(conn); if(retcode) { free(our_ssl_sessionid); @@ -717,6 +801,55 @@ size_t Curl_mbedtls_version(char *buffer, size_t size) (version>>16)&0xff, (version>>8)&0xff); } +CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy, + size_t length) +{ +#if defined(MBEDTLS_CTR_DRBG_C) + int ret = -1; + char errorbuf[128]; + mbedtls_entropy_context ctr_entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_init(&ctr_entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + errorbuf[0]=0; + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, + &ctr_entropy, NULL, 0); + + if(ret) { +#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", + -ret, errorbuf); + } + else { + ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); + + if(ret) { +#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", + -ret, errorbuf); + } + } + + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&ctr_entropy); + + return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; +#elif defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state hs; + mbedtls_havege_init(&hs); + mbedtls_havege_random(&hs, entropy, length); + mbedtls_havege_free(&hs); + return CURLE_OK; +#else + return CURLE_NOT_BUILT_IN; +#endif +} + static CURLcode mbed_connect_common(struct connectdata *conn, int sockindex, @@ -871,9 +1004,7 @@ void Curl_mbedtls_cleanup(void) int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex) { - mbedtls_ssl_context *ssl = - (mbedtls_ssl_context *)&conn->ssl[sockindex].ssl; - return ssl->in_msglen != 0; + return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0; } #endif /* USE_MBEDTLS */ diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h index 1021d5461..71d17a491 100644 --- a/Utilities/cmcurl/lib/vtls/mbedtls.h +++ b/Utilities/cmcurl/lib/vtls/mbedtls.h @@ -50,9 +50,15 @@ void Curl_mbedtls_session_free(void *ptr); size_t Curl_mbedtls_version(char *buffer, size_t size); int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex); +CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy, + size_t length); + /* this backends supports CURLOPT_PINNEDPUBLICKEY */ #define have_curlssl_pinnedpubkey 1 +/* this backend supports CURLOPT_SSL_CTX_* */ +#define have_curlssl_ssl_ctx 1 + /* API setup for mbedTLS */ #define curlssl_init() Curl_mbedtls_init() #define curlssl_cleanup() Curl_mbedtls_cleanup() @@ -70,11 +76,7 @@ int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex); #define curlssl_data_pending(x,y) Curl_mbedtls_data_pending(x, y) #define CURL_SSL_BACKEND CURLSSLBACKEND_MBEDTLS #define curlssl_sha256sum(a,b,c,d) mbedtls_sha256(a,b,c,0) - -/* This might cause libcurl to use a weeker random! - TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that -*/ -#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN) +#define curlssl_random(x,y,z) Curl_mbedtls_random(x, y, z) #endif /* USE_MBEDTLS */ #endif /* HEADER_CURL_MBEDTLS_H */ diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c index dff15758f..cd0138930 100644 --- a/Utilities/cmcurl/lib/vtls/nss.c +++ b/Utilities/cmcurl/lib/vtls/nss.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -56,7 +56,8 @@ #include #include #include -#include /* for SECKEY_DestroyPublicKey() */ +#include /* for SECKEY_DestroyPublicKey() */ +#include /* for PR_ImportTCPSocket */ #define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) @@ -77,14 +78,20 @@ /* enough to fit the string "PEM Token #[0|1]" */ #define SLOTSIZE 13 -PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd); static PRLock *nss_initlock = NULL; static PRLock *nss_crllock = NULL; static PRLock *nss_findslot_lock = NULL; -static struct curl_llist *nss_crl_list = NULL; +static PRLock *nss_trustload_lock = NULL; +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; +}; + typedef struct { const char *name; int num; @@ -200,14 +207,17 @@ static const cipher_s cipherlist[] = { #endif }; -static const char* pem_library = "libnsspem.so"; -static SECMODModule* mod = NULL; +static const char *pem_library = "libnsspem.so"; +static SECMODModule *pem_module = NULL; + +static const char *trust_library = "libnssckbi.so"; +static SECMODModule *trust_module = NULL; /* NSPR I/O layer we use to detect blocking direction during SSL handshake */ static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER; static PRIOMethods nspr_io_methods; -static const char* nss_error_to_name(PRErrorCode code) +static const char *nss_error_to_name(PRErrorCode code) { const char *name = PR_ErrorToName(code); if(name) @@ -254,7 +264,8 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, while((*cipher) && (ISSPACE(*cipher))) ++cipher; - if((cipher_list = strchr(cipher, ','))) { + cipher_list = strchr(cipher, ','); + if(cipher_list) { *cipher_list++ = '\0'; } @@ -337,9 +348,8 @@ static int is_file(const char *filename) * should be later deallocated using free(). If the OOM failure occurs, we * return NULL, too. */ -static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind) +static char *dup_nickname(struct Curl_easy *data, const char *str) { - const char *str = data->set.str[cert_kind]; const char *n; if(!is_file(str)) @@ -365,12 +375,24 @@ static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind) static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name) { PK11SlotInfo *slot; - PR_Lock(nss_initlock); + PR_Lock(nss_findslot_lock); slot = PK11_FindSlotByName(slot_name); - PR_Unlock(nss_initlock); + PR_Unlock(nss_findslot_lock); return slot; } +/* wrap 'ptr' as list node and tail-insert into 'list' */ +static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr) +{ + struct ptr_list_wrap *wrap = malloc(sizeof *wrap); + if(!wrap) + return CURLE_OUT_OF_MEMORY; + + wrap->ptr = ptr; + Curl_llist_insert_next(list, list->tail, wrap, &wrap->node); + return CURLE_OK; +} + /* 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(). */ @@ -401,7 +423,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename, - strlen(filename) + 1); + (CK_ULONG)strlen(filename) + 1); if(CKO_CERTIFICATE == obj_class) { CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse); @@ -413,7 +435,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, if(!obj) return result; - if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) { + if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) { PK11_DestroyGenericObject(obj); return CURLE_OUT_OF_MEMORY; } @@ -430,17 +452,21 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, * NSS objects in Curl_nss_close() */ static void nss_destroy_object(void *user, void *ptr) { - PK11GenericObject *obj = (PK11GenericObject *)ptr; + struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr; + PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr; (void) user; PK11_DestroyGenericObject(obj); + free(wrap); } /* same as nss_destroy_object() but for CRL items */ static void nss_destroy_crl_item(void *user, void *ptr) { - SECItem *crl_der = (SECItem *)ptr; + struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr; + SECItem *crl_der = (SECItem *) wrap->ptr; (void) user; SECITEM_FreeItem(crl_der, PR_TRUE); + free(wrap); } static CURLcode nss_load_cert(struct ssl_connect_data *ssl, @@ -496,7 +522,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der) PR_Lock(nss_crllock); /* store the CRL item so that we can free it in Curl_nss_cleanup() */ - if(!Curl_llist_insert_next(nss_crl_list, nss_crl_list->tail, crl_der)) { + if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) { SECITEM_FreeItem(crl_der, PR_TRUE); PR_Unlock(nss_crllock); return CURLE_OUT_OF_MEMORY; @@ -514,7 +540,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der) return CURLE_OK; } -static CURLcode nss_load_crl(const char* crlfilename) +static CURLcode nss_load_crl(const char *crlfilename) { PRFileDesc *infile; PRFileInfo info; @@ -540,7 +566,7 @@ static CURLcode nss_load_crl(const char* crlfilename) goto fail; /* place a trailing zero right after the visible data */ - body = (char*)filedata.data; + body = (char *)filedata.data; body[--filedata.len] = '\0'; body = strstr(body, "-----BEGIN"); @@ -581,10 +607,11 @@ fail: static CURLcode nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { - PK11SlotInfo *slot; + PK11SlotInfo *slot, *tmp; SECStatus status; CURLcode result; struct ssl_connect_data *ssl = conn->ssl; + struct Curl_easy *data = conn->data; (void)sockindex; /* unused */ @@ -599,11 +626,12 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex, return CURLE_SSL_CERTPROBLEM; /* This will force the token to be seen as re-inserted */ - SECMOD_WaitForAnyTokenEvent(mod, 0, 0); + tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0); + if(tmp) + PK11_FreeSlot(tmp); PK11_IsPresent(slot); - status = PK11_Authenticate(slot, PR_TRUE, - conn->data->set.str[STRING_KEY_PASSWD]); + status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd)); PK11_FreeSlot(slot); return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; @@ -664,7 +692,7 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex, return CURLE_OK; } -static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg) +static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg) { (void)slot; /* unused */ @@ -682,7 +710,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, struct connectdata *conn = (struct connectdata *)arg; #ifdef SSL_ENABLE_OCSP_STAPLING - if(conn->data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { SECStatus cacheResult; const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); @@ -708,7 +736,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, } #endif - if(!conn->data->set.ssl.verifypeer) { + if(!SSL_CONN_CONFIG(verifypeer)) { infof(conn->data, "skipping SSL peer certificate verification\n"); return SECSuccess; } @@ -734,6 +762,11 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { switch(state) { +#if NSSVERNUM >= 0x031a00 /* 3.26.0 */ + /* used by NSS internally to implement 0-RTT */ + case SSL_NEXT_PROTO_EARLY_VALUE: + /* fall through! */ +#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"); @@ -928,9 +961,12 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) CERTCertificate *cert; /* remember the cert verification result */ - data->set.ssl.certverifyresult = err; + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = err; + else + data->set.ssl.certverifyresult = err; - if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost) + if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost)) /* we are asked not to verify the host name */ return SECSuccess; @@ -1170,6 +1206,50 @@ static PRStatus nspr_io_close(PRFileDesc *fd) return close_fn(fd); } +/* load a PKCS #11 module */ +static CURLcode nss_load_module(SECMODModule **pmod, const char *library, + const char *name) +{ + char *config_string; + SECMODModule *module = *pmod; + if(module) + /* already loaded */ + return CURLE_OK; + + config_string = aprintf("library=%s name=%s", library, name); + if(!config_string) + return CURLE_OUT_OF_MEMORY; + + module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE); + free(config_string); + + if(module && module->loaded) { + /* loaded successfully */ + *pmod = module; + return CURLE_OK; + } + + if(module) + SECMOD_DestroyModule(module); + return CURLE_FAILED_INIT; +} + +/* unload a PKCS #11 module */ +static void nss_unload_module(SECMODModule **pmod) +{ + SECMODModule *module = *pmod; + if(!module) + /* not loaded */ + return; + + if(SECMOD_UnloadUserModule(module) != SECSuccess) + /* unload failed */ + return; + + SECMOD_DestroyModule(module); + *pmod = NULL; +} + /* data might be NULL */ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir) { @@ -1219,9 +1299,7 @@ static CURLcode nss_init(struct Curl_easy *data) return CURLE_OK; /* list of all CRL items we need to destroy in Curl_nss_cleanup() */ - nss_crl_list = Curl_llist_alloc(nss_destroy_crl_item); - if(!nss_crl_list) - return CURLE_OUT_OF_MEMORY; + Curl_llist_init(&nss_crl_list, nss_destroy_crl_item); /* First we check if $SSL_DIR points to a valid dir */ cert_dir = getenv("SSL_DIR"); @@ -1281,6 +1359,7 @@ int Curl_nss_init(void) nss_initlock = PR_NewLock(); nss_crllock = PR_NewLock(); nss_findslot_lock = PR_NewLock(); + nss_trustload_lock = PR_NewLock(); } /* We will actually initialize NSS later */ @@ -1319,23 +1398,21 @@ void Curl_nss_cleanup(void) * the certificates. */ SSL_ClearSessionCache(); - if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) { - SECMOD_DestroyModule(mod); - mod = NULL; - } + nss_unload_module(&pem_module); + nss_unload_module(&trust_module); NSS_ShutdownContext(nss_context); nss_context = NULL; } /* destroy all CRL items */ - Curl_llist_destroy(nss_crl_list, NULL); - nss_crl_list = NULL; + Curl_llist_destroy(&nss_crl_list, NULL); PR_Unlock(nss_initlock); PR_DestroyLock(nss_initlock); PR_DestroyLock(nss_crllock); PR_DestroyLock(nss_findslot_lock); + PR_DestroyLock(nss_trustload_lock); nss_initlock = NULL; initialized = 0; @@ -1367,36 +1444,54 @@ Curl_nss_check_cxn(struct connectdata *conn) return -1; /* connection status unknown */ } +static void nss_close(struct ssl_connect_data *connssl) +{ + /* before the cleanup, check whether we are using a client certificate */ + const bool client_cert = (connssl->client_nickname != NULL) + || (connssl->obj_clicert != NULL); + + free(connssl->client_nickname); + connssl->client_nickname = NULL; + + /* destroy all NSS objects in order to avoid failure of NSS shutdown */ + Curl_llist_destroy(&connssl->obj_list, NULL); + connssl->obj_clicert = NULL; + + if(connssl->handle) { + if(client_cert) + /* A server might require different authentication based on the + * particular path being requested by the client. To support this + * scenario, we must ensure that a connection will never reuse the + * authentication data from a previous connection. */ + SSL_InvalidateSession(connssl->handle); + + PR_Close(connssl->handle); + connssl->handle = NULL; + } +} + /* * This function is called when an SSL connection is closed. */ void Curl_nss_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; - if(connssl->handle) { + if(connssl->handle || connssl_proxy->handle) { /* NSS closes the socket we previously handed to it, so we must mark it as closed to avoid double close */ fake_sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; + } - if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL)) - /* A server might require different authentication based on the - * particular path being requested by the client. To support this - * scenario, we must ensure that a connection will never reuse the - * authentication data from a previous connection. */ - SSL_InvalidateSession(connssl->handle); - - free(connssl->client_nickname); - connssl->client_nickname = NULL; - /* destroy all NSS objects in order to avoid failure of NSS shutdown */ - Curl_llist_destroy(connssl->obj_list, NULL); - connssl->obj_list = NULL; - connssl->obj_clicert = NULL; + if(connssl->handle) + /* nss_close(connssl) will transitively close also connssl_proxy->handle + if both are used. Clear it to avoid a double close leading to crash. */ + connssl_proxy->handle = NULL; - PR_Close(connssl->handle); - connssl->handle = NULL; - } + nss_close(connssl); + nss_close(connssl_proxy); } /* return true if NSS can provide error code (and possibly msg) for the @@ -1437,14 +1532,46 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; - const char *cafile = data->set.ssl.CAfile; - const char *capath = data->set.ssl.CApath; + const char *cafile = SSL_CONN_CONFIG(CAfile); + const char *capath = SSL_CONN_CONFIG(CApath); + bool use_trust_module; + CURLcode result = CURLE_OK; - if(cafile) { - CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); - if(result) - return result; + /* treat empty string as unset */ + if(cafile && !cafile[0]) + cafile = NULL; + if(capath && !capath[0]) + capath = NULL; + + infof(data, " CAfile: %s\n CApath: %s\n", + cafile ? cafile : "none", + capath ? capath : "none"); + + /* load libnssckbi.so if no other trust roots were specified */ + use_trust_module = !cafile && !capath; + + PR_Lock(nss_trustload_lock); + if(use_trust_module && !trust_module) { + /* libnssckbi.so needed but not yet loaded --> load it! */ + result = nss_load_module(&trust_module, trust_library, "trust"); + infof(data, "%s %s\n", (result) ? "failed to load" : "loaded", + trust_library); + if(result == CURLE_FAILED_INIT) + /* make the error non-fatal if we are not going to verify peer */ + result = CURLE_SSL_CACERT_BADFILE; } + else if(!use_trust_module && trust_module) { + /* libnssckbi.so not needed but already loaded --> unload it! */ + infof(data, "unloading %s\n", trust_library); + nss_unload_module(&trust_module); + } + PR_Unlock(nss_trustload_lock); + + if(cafile) + result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); + + if(result) + return result; if(capath) { struct_stat st; @@ -1478,64 +1605,111 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath); } - infof(data, " CAfile: %s\n CApath: %s\n", - cafile ? cafile : "none", - capath ? capath : "none"); - return CURLE_OK; } -static CURLcode nss_init_sslver(SSLVersionRange *sslver, - struct Curl_easy *data) +static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version) { - switch(data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: + switch(version) { case CURL_SSLVERSION_TLSv1: - sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */ #ifdef SSL_LIBRARY_VERSION_TLS_1_2 - sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; + *nssver = SSL_LIBRARY_VERSION_TLS_1_2; #elif defined SSL_LIBRARY_VERSION_TLS_1_1 - sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; + *nssver = SSL_LIBRARY_VERSION_TLS_1_1; #else - sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; + *nssver = SSL_LIBRARY_VERSION_TLS_1_0; #endif return CURLE_OK; case CURL_SSLVERSION_SSLv2: - sslver->min = SSL_LIBRARY_VERSION_2; - sslver->max = SSL_LIBRARY_VERSION_2; + *nssver = SSL_LIBRARY_VERSION_2; return CURLE_OK; case CURL_SSLVERSION_SSLv3: - sslver->min = SSL_LIBRARY_VERSION_3_0; - sslver->max = SSL_LIBRARY_VERSION_3_0; + *nssver = SSL_LIBRARY_VERSION_3_0; return CURLE_OK; case CURL_SSLVERSION_TLSv1_0: - sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; - sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; + *nssver = SSL_LIBRARY_VERSION_TLS_1_0; return CURLE_OK; case CURL_SSLVERSION_TLSv1_1: #ifdef SSL_LIBRARY_VERSION_TLS_1_1 - sslver->min = SSL_LIBRARY_VERSION_TLS_1_1; - sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; + *nssver = SSL_LIBRARY_VERSION_TLS_1_1; return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; #endif - break; case CURL_SSLVERSION_TLSv1_2: #ifdef SSL_LIBRARY_VERSION_TLS_1_2 - sslver->min = SSL_LIBRARY_VERSION_TLS_1_2; - sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; + *nssver = SSL_LIBRARY_VERSION_TLS_1_2; + return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; +#endif + + case CURL_SSLVERSION_TLSv1_3: +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + *nssver = SSL_LIBRARY_VERSION_TLS_1_3; return CURLE_OK; +#else + return CURLE_SSL_CONNECT_ERROR; #endif + + default: + return CURLE_SSL_CONNECT_ERROR; + } +} + +static CURLcode nss_init_sslver(SSLVersionRange *sslver, + struct Curl_easy *data, + struct connectdata *conn) +{ + CURLcode result; + const long min = SSL_CONN_CONFIG(version); + const long max = SSL_CONN_CONFIG(version_max); + + /* map CURL_SSLVERSION_DEFAULT to NSS default */ + if(min == CURL_SSLVERSION_DEFAULT || max == CURL_SSLVERSION_MAX_DEFAULT) { + /* map CURL_SSLVERSION_DEFAULT to NSS default */ + if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess) + return CURLE_SSL_CONNECT_ERROR; + /* ... but make sure we use at least TLSv1.0 according to libcurl API */ + if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0) + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + } + + switch(min) { + case CURL_SSLVERSION_DEFAULT: break; + case CURL_SSLVERSION_TLSv1: + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + break; + default: + result = nss_sslver_from_curl(&sslver->min, min); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + if(max == CURL_SSLVERSION_MAX_NONE) + sslver->max = sslver->min; } - failf(data, "TLS minor version cannot be set"); - return CURLE_SSL_CONNECT_ERROR; + switch(max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + break; + default: + result = nss_sslver_from_curl(&sslver->max, max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + } + + return CURLE_OK; } static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, @@ -1558,19 +1732,19 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, } /* cleanup on connection failure */ - Curl_llist_destroy(connssl->obj_list, NULL); - connssl->obj_list = NULL; + Curl_llist_destroy(&connssl->obj_list, NULL); return curlerr; } -/* Switch the SSL socket into non-blocking mode. */ -static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl, - struct Curl_easy *data) +/* Switch the SSL socket into blocking or non-blocking mode. */ +static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, + struct Curl_easy *data, + bool blocking) { static PRSocketOptionData sock_opt; sock_opt.option = PR_SockOpt_Nonblocking; - sock_opt.value.non_blocking = PR_TRUE; + sock_opt.value.non_blocking = !blocking; if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS) return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); @@ -1589,6 +1763,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result; + bool second_layer = FALSE; SSLVersionRange sslver = { SSL_LIBRARY_VERSION_TLS_1_0, /* min */ @@ -1598,9 +1773,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) connssl->data = data; /* list of all NSS objects we need to destroy in Curl_nss_close() */ - connssl->obj_list = Curl_llist_alloc(nss_destroy_object); - if(!connssl->obj_list) - return CURLE_OUT_OF_MEMORY; + Curl_llist_init(&connssl->obj_list, nss_destroy_object); /* FIXME. NSS doesn't support multiple databases open at the same time. */ PR_Lock(nss_initlock); @@ -1610,29 +1783,17 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; } - result = CURLE_SSL_CONNECT_ERROR; - - if(!mod) { - char *configstring = aprintf("library=%s name=PEM", pem_library); - if(!configstring) { - PR_Unlock(nss_initlock); - goto error; - } - mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE); - free(configstring); - - if(!mod || !mod->loaded) { - if(mod) { - SECMOD_DestroyModule(mod); - mod = NULL; - } - infof(data, "WARNING: failed to load NSS PEM library %s. Using " - "OpenSSL PEM certificates will not work.\n", pem_library); - } - } - PK11_SetPasswordFunc(nss_get_password); + + result = nss_load_module(&pem_module, pem_library, "PEM"); PR_Unlock(nss_initlock); + if(result == CURLE_FAILED_INIT) + infof(data, "WARNING: failed to load NSS PEM library %s. Using " + "OpenSSL PEM certificates will not work.\n", pem_library); + else if(result) + goto error; + + result = CURLE_SSL_CONNECT_ERROR; model = PR_NewTCPSocket(); if(!model) @@ -1647,18 +1808,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; /* do not use SSL cache if disabled or we are not going to verify peer */ - ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ? - PR_FALSE : PR_TRUE; + ssl_no_cache = (SSL_SET_OPTION(primary.sessionid) + && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE; if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) goto error; /* enable/disable the requested SSL version(s) */ - if(nss_init_sslver(&sslver, data) != CURLE_OK) + if(nss_init_sslver(&sslver, data, conn) != CURLE_OK) goto error; if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) goto error; - ssl_cbc_random_iv = !data->set.ssl_enable_beast; + ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast); #ifdef SSL_CBC_RANDOM_IV /* unless the user explicitly asks to allow the protocol vulnerability, we use the work-around */ @@ -1670,14 +1831,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); #endif - if(data->set.ssl.cipher_list) { - if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { + if(SSL_CONN_CONFIG(cipher_list)) { + if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) { result = CURLE_SSL_CIPHER; goto error; } } - if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost) + if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost)) infof(data, "warning: ignoring value of ssl.verifyhost\n"); /* bypass the default SSL_AuthCertificate() hook in case we do not want to @@ -1685,39 +1846,47 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) goto error; - data->set.ssl.certverifyresult=0; /* not checked yet */ + /* not checked yet */ + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = 0; + else + data->set.ssl.certverifyresult = 0; + if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) goto error; if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess) goto error; - if(data->set.ssl.verifypeer) { + { const CURLcode rv = nss_load_ca_certificates(conn, sockindex); - if(rv) { + 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"); + else if(rv) { result = rv; goto error; } } - if(data->set.ssl.CRLfile) { - const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile); + if(SSL_SET_OPTION(CRLfile)) { + const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile)); if(rv) { result = rv; goto error; } - infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile); + infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile)); } - if(data->set.str[STRING_CERT]) { - char *nickname = dup_nickname(data, STRING_CERT); + if(SSL_SET_OPTION(cert)) { + char *nickname = dup_nickname(data, SSL_SET_OPTION(cert)); if(nickname) { /* we are not going to use libnsspem.so to read the client cert */ connssl->obj_clicert = NULL; } else { - CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT], - data->set.str[STRING_KEY]); + CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert), + SSL_SET_OPTION(key)); if(rv) { /* failf() is already done in cert_stuff() */ result = rv; @@ -1737,15 +1906,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; } - /* wrap OS file descriptor by NSPR's file descriptor abstraction */ - nspr_io = PR_ImportTCPSocket(sockfd); - if(!nspr_io) - goto error; + if(conn->proxy_ssl[sockindex].use) { + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); + nspr_io = conn->proxy_ssl[sockindex].handle; + second_layer = TRUE; + } + else { + /* wrap OS file descriptor by NSPR's file descriptor abstraction */ + nspr_io = PR_ImportTCPSocket(sockfd); + if(!nspr_io) + goto error; + } /* create our own NSPR I/O layer */ nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods); if(!nspr_io_stub) { - PR_Close(nspr_io); + if(!second_layer) + PR_Close(nspr_io); goto error; } @@ -1754,7 +1932,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* push our new layer to the NSPR I/O stack */ if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) { - PR_Close(nspr_io); + if(!second_layer) + PR_Close(nspr_io); PR_Close(nspr_io_stub); goto error; } @@ -1762,7 +1941,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* import our model socket onto the current I/O stack */ connssl->handle = SSL_ImportFD(model, nspr_io); if(!connssl->handle) { - PR_Close(nspr_io); + if(!second_layer) + PR_Close(nspr_io); goto error; } @@ -1770,12 +1950,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) model = NULL; /* This is the password associated with the cert that we're using */ - if(data->set.str[STRING_KEY_PASSWD]) { - SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); + if(SSL_SET_OPTION(key_passwd)) { + SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd)); } #ifdef SSL_ENABLE_OCSP_STAPLING - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) != SECSuccess) goto error; @@ -1835,11 +2015,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; /* propagate hostname to the TLS layer */ - if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess) + if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name) != SECSuccess) goto error; /* prevent NSS from re-using the session for a different hostname */ - if(SSL_SetSockPeerID(connssl->handle, conn->host.name) != SECSuccess) + if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name) + != SECSuccess) goto error; return CURLE_OK; @@ -1857,10 +2040,16 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) struct Curl_easy *data = conn->data; CURLcode result = CURLE_SSL_CONNECT_ERROR; PRUint32 timeout; + 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]; + /* check timeout situation */ - const long time_left = Curl_timeleft(data, NULL, TRUE); - if(time_left < 0L) { + const time_t time_left = Curl_timeleft(data, NULL, TRUE); + if(time_left < 0) { failf(data, "timed out before SSL handshake"); result = CURLE_OPERATION_TIMEDOUT; goto error; @@ -1872,9 +2061,9 @@ 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(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) result = CURLE_PEER_FAILED_VERIFICATION; - else if(conn->data->set.ssl.certverifyresult!=0) + else if(*certverifyresult != 0) result = CURLE_SSL_CACERT; goto error; } @@ -1883,11 +2072,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) if(result) goto error; - if(data->set.str[STRING_SSL_ISSUERCERT]) { + if(SSL_SET_OPTION(issuercert)) { SECStatus ret = SECFailure; - char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT); + char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); if(nickname) { - /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */ + /* we support only nicknames in case of issuercert for now */ ret = check_issuer_cert(connssl->handle, nickname); free(nickname); } @@ -1902,7 +2091,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } } - result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); + result = cmp_peer_pubkey(connssl, pinnedpubkey); if(result) /* status already printed */ goto error; @@ -1933,16 +2122,14 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, /* we do not expect CURLE_AGAIN from nss_setup_connect() */ return result; - if(!blocking) { - /* in non-blocking mode, set NSS non-blocking mode before handshake */ - result = nss_set_nonblock(connssl, data); - if(result) - return result; - } - connssl->connecting_state = ssl_connect_2; } + /* enable/disable blocking mode before handshake */ + result = nss_set_blocking(connssl, data, blocking); + if(result) + return result; + result = nss_do_connect(conn, sockindex); switch(result) { case CURLE_OK: @@ -1958,7 +2145,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, if(blocking) { /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */ - result = nss_set_nonblock(connssl, data); + result = nss_set_blocking(connssl, data, /* blocking */ FALSE); if(result) return result; } @@ -2064,17 +2251,17 @@ int Curl_nss_seed(struct Curl_easy *data) } /* data might be NULL */ -int Curl_nss_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +CURLcode Curl_nss_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { Curl_nss_seed(data); /* Initiate the seed if not already done */ if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) /* signal a failure */ - return -1; + return CURLE_FAILED_INIT; - return 0; + return CURLE_OK; } void Curl_nss_md5sum(unsigned char *tmp, /* input */ @@ -2112,7 +2299,8 @@ bool Curl_nss_cert_status_request(void) #endif } -bool Curl_nss_false_start(void) { +bool Curl_nss_false_start(void) +{ #if NSSVERNUM >= 0x030f04 /* 3.15.4 */ return TRUE; #else diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h index ac67e6ab7..8c46929ff 100644 --- a/Utilities/cmcurl/lib/vtls/nssg.h +++ b/Utilities/cmcurl/lib/vtls/nssg.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -47,9 +47,9 @@ int Curl_nss_seed(struct Curl_easy *data); /* initialize NSS library if not already */ CURLcode Curl_nss_force_init(struct Curl_easy *data); -int Curl_nss_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length); +CURLcode Curl_nss_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length); void Curl_nss_md5sum(unsigned char *tmp, /* input */ size_t tmplen, @@ -65,6 +65,9 @@ bool Curl_nss_cert_status_request(void); bool Curl_nss_false_start(void); +/* Support HTTPS-proxy */ +#define HTTPS_PROXY_SUPPORT 1 + /* Set the API backend definition to NSS */ #define CURL_SSL_BACKEND CURLSSLBACKEND_NSS diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c index c040928a1..dbee36929 100644 --- a/Utilities/cmcurl/lib/vtls/openssl.c +++ b/Utilities/cmcurl/lib/vtls/openssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -55,7 +55,9 @@ #include #include #include +#ifndef OPENSSL_NO_DSA #include +#endif #include #include #include @@ -156,10 +158,56 @@ static unsigned long OpenSSL_version_num(void) * Number of bytes to read from the random number seed file. This must be * a finite value (because some entropy "files" like /dev/urandom have * an infinite length), but must be large enough to provide enough - * entopy to properly seed OpenSSL's PRNG. + * entropy to properly seed OpenSSL's PRNG. */ #define RAND_LOAD_LENGTH 1024 +static const char *SSL_ERROR_to_str(int err) +{ + switch(err) { + case SSL_ERROR_NONE: + return "SSL_ERROR_NONE"; + case SSL_ERROR_SSL: + return "SSL_ERROR_SSL"; + case SSL_ERROR_WANT_READ: + return "SSL_ERROR_WANT_READ"; + case SSL_ERROR_WANT_WRITE: + return "SSL_ERROR_WANT_WRITE"; + case SSL_ERROR_WANT_X509_LOOKUP: + return "SSL_ERROR_WANT_X509_LOOKUP"; + case SSL_ERROR_SYSCALL: + return "SSL_ERROR_SYSCALL"; + case SSL_ERROR_ZERO_RETURN: + return "SSL_ERROR_ZERO_RETURN"; + case SSL_ERROR_WANT_CONNECT: + return "SSL_ERROR_WANT_CONNECT"; + case SSL_ERROR_WANT_ACCEPT: + return "SSL_ERROR_WANT_ACCEPT"; +#if defined(SSL_ERROR_WANT_ASYNC) + case SSL_ERROR_WANT_ASYNC: + return "SSL_ERROR_WANT_ASYNC"; +#endif +#if defined(SSL_ERROR_WANT_ASYNC_JOB) + case SSL_ERROR_WANT_ASYNC_JOB: + return "SSL_ERROR_WANT_ASYNC_JOB"; +#endif +#if defined(SSL_ERROR_WANT_EARLY) + case SSL_ERROR_WANT_EARLY: + return "SSL_ERROR_WANT_EARLY"; +#endif + default: + return "SSL_ERROR unknown"; + } +} + +/* Return error string for last OpenSSL error + */ +static char *ossl_strerror(unsigned long error, char *buf, size_t size) +{ + ERR_error_string_n(error, buf, size); + return buf; +} + static int passwd_callback(char *buf, int num, int encrypting, void *global_passwd) { @@ -176,39 +224,34 @@ static int passwd_callback(char *buf, int num, int encrypting, } /* - * rand_enough() is a function that returns TRUE if we have seeded the random - * engine properly. We use some preprocessor magic to provide a seed_enough() - * macro to use, just to prevent a compiler warning on this function if we - * pass in an argument that is never used. + * rand_enough() returns TRUE if we have seeded the random engine properly. */ - -#ifdef HAVE_RAND_STATUS -#define seed_enough(x) rand_enough() static bool rand_enough(void) { return (0 != RAND_status()) ? TRUE : FALSE; } -#else -#define seed_enough(x) rand_enough(x) -static bool rand_enough(int nread) -{ - /* this is a very silly decision to make */ - return (nread > 500) ? TRUE : FALSE; -} -#endif -static int ossl_seed(struct Curl_easy *data) +static CURLcode Curl_ossl_seed(struct Curl_easy *data) { - char *buf = data->state.buffer; /* point to the big buffer */ + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; int nread=0; + char fname[256]; - /* Q: should we add support for a random file name as a libcurl option? - A: Yes, it is here */ + if(ssl_seeded) + return CURLE_OK; + + if(rand_enough()) { + /* OpenSSL 1.1.0+ will return here */ + ssl_seeded = TRUE; + return CURLE_OK; + } #ifndef RANDOM_FILE /* if RANDOM_FILE isn't defined, we only perform this if an option tells us to! */ - if(data->set.ssl.random_file) + if(data->set.str[STRING_SSL_RANDOM_FILE]) #define RANDOM_FILE "" /* doesn't matter won't be used */ #endif { @@ -217,7 +260,7 @@ static int ossl_seed(struct Curl_easy *data) data->set.str[STRING_SSL_RANDOM_FILE]: RANDOM_FILE), RAND_LOAD_LENGTH); - if(seed_enough(nread)) + if(rand_enough()) return nread; } @@ -237,7 +280,7 @@ static int ossl_seed(struct Curl_easy *data) data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET); if(-1 != ret) { nread += ret; - if(seed_enough(nread)) + if(rand_enough()) return nread; } } @@ -248,35 +291,23 @@ static int ossl_seed(struct Curl_easy *data) do { unsigned char randb[64]; int len = sizeof(randb); - RAND_bytes(randb, len); + if(!RAND_bytes(randb, len)) + break; RAND_add(randb, len, (len >> 1)); - } while(!RAND_status()); + } while(!rand_enough()); /* generates a default path for the random seed file */ - buf[0]=0; /* blank it first */ - RAND_file_name(buf, BUFSIZE); - if(buf[0]) { + fname[0]=0; /* blank it first */ + RAND_file_name(fname, sizeof(fname)); + if(fname[0]) { /* we got a file name to try */ - nread += RAND_load_file(buf, RAND_LOAD_LENGTH); - if(seed_enough(nread)) + nread += RAND_load_file(fname, RAND_LOAD_LENGTH); + if(rand_enough()) return nread; } infof(data, "libcurl is now using a weak random seed!\n"); - return nread; -} - -static void Curl_ossl_seed(struct Curl_easy *data) -{ - /* we have the "SSL is seeded" boolean static to prevent multiple - time-consuming seedings in vain */ - static bool ssl_seeded = FALSE; - - if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || - data->set.str[STRING_SSL_EGDSOCKET]) { - ossl_seed(data); - ssl_seeded = TRUE; - } + return CURLE_SSL_CONNECT_ERROR; /* confusing error code */ } #ifndef SSL_FILETYPE_ENGINE @@ -312,7 +343,7 @@ static int ssl_ui_reader(UI *ui, UI_STRING *uis) switch(UI_get_string_type(uis)) { case UIT_PROMPT: case UIT_VERIFY: - password = (const char*)UI_get0_user_data(ui); + password = (const char *)UI_get0_user_data(ui); if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { UI_set_result(ui, uis, password); return 1; @@ -348,9 +379,11 @@ int cert_stuff(struct connectdata *conn, char *cert_file, const char *cert_type, char *key_file, - const char *key_type) + const char *key_type, + char *key_passwd) { struct Curl_easy *data = conn->data; + char error_buffer[256]; int file_type = do_file_type(cert_type); @@ -359,10 +392,9 @@ int cert_stuff(struct connectdata *conn, X509 *x509; int cert_done = 0; - if(data->set.str[STRING_KEY_PASSWD]) { + if(key_passwd) { /* set the password in the callback userdata */ - SSL_CTX_set_default_passwd_cb_userdata(ctx, - data->set.str[STRING_KEY_PASSWD]); + SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd); /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } @@ -377,7 +409,8 @@ int cert_stuff(struct connectdata *conn, "could not load PEM client certificate, " OSSL_PACKAGE " error %s, " "(no key found, wrong pass phrase, or wrong file format?)", - ERR_error_string(ERR_get_error(), NULL) ); + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); return 0; } break; @@ -393,7 +426,8 @@ int cert_stuff(struct connectdata *conn, "could not load ASN1 client certificate, " OSSL_PACKAGE " error %s, " "(no key found, wrong pass phrase, or wrong file format?)", - ERR_error_string(ERR_get_error(), NULL) ); + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); return 0; } break; @@ -422,7 +456,8 @@ int cert_stuff(struct connectdata *conn, 0, ¶ms, NULL, 1)) { failf(data, "ssl engine cannot load client cert with id" " '%s' [%s]", cert_file, - ERR_error_string(ERR_get_error(), NULL)); + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); return 0; } @@ -473,12 +508,13 @@ int cert_stuff(struct connectdata *conn, PKCS12_PBE_add(); - if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509, + if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) { failf(data, "could not parse PKCS12 file, check password, " OSSL_PACKAGE " error %s", - ERR_error_string(ERR_get_error(), NULL) ); + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); PKCS12_free(p12); return 0; } @@ -489,7 +525,8 @@ int cert_stuff(struct connectdata *conn, failf(data, "could not load PKCS12 client certificate, " OSSL_PACKAGE " error %s", - ERR_error_string(ERR_get_error(), NULL) ); + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer)) ); goto fail; } @@ -510,21 +547,19 @@ int cert_stuff(struct connectdata *conn, /* * Note that sk_X509_pop() is used below to make sure the cert is * removed from the stack properly before getting passed to - * SSL_CTX_add_extra_chain_cert(). Previously we used - * sk_X509_value() instead, but then we'd clean it in the subsequent - * sk_X509_pop_free() call. + * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously + * we used sk_X509_value() instead, but then we'd clean it in the + * subsequent sk_X509_pop_free() call. */ X509 *x = sk_X509_pop(ca); - if(!SSL_CTX_add_extra_chain_cert(ctx, x)) { + if(!SSL_CTX_add_client_CA(ctx, x)) { X509_free(x); - failf(data, "cannot add certificate to certificate chain"); + failf(data, "cannot add certificate to client CA list"); goto fail; } - /* SSL_CTX_add_client_CA() seems to work with either sk_* function, - * presumably because it duplicates what we pass to it. - */ - if(!SSL_CTX_add_client_CA(ctx, x)) { - failf(data, "cannot add certificate to client CA list"); + if(!SSL_CTX_add_extra_chain_cert(ctx, x)) { + X509_free(x); + failf(data, "cannot add certificate to certificate chain"); goto fail; } } @@ -558,6 +593,7 @@ int cert_stuff(struct connectdata *conn, if(!key_file) /* cert & key can only be in PEM case in the same file */ key_file=cert_file; + /* FALLTHROUGH */ case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { failf(data, "unable to set private key file: '%s' type %s", @@ -571,7 +607,7 @@ int cert_stuff(struct connectdata *conn, EVP_PKEY *priv_key = NULL; if(data->state.engine) { UI_METHOD *ui_method = - UI_create_method((char *)"cURL user interface"); + UI_create_method((char *)"curl user interface"); if(!ui_method) { failf(data, "unable do create " OSSL_PACKAGE " user-interface method"); @@ -585,7 +621,7 @@ int cert_stuff(struct connectdata *conn, priv_key = (EVP_PKEY *) ENGINE_load_private_key(data->state.engine, key_file, ui_method, - data->set.str[STRING_KEY_PASSWD]); + key_passwd); UI_destroy_method(ui_method); if(!priv_key) { failf(data, "failed to load private key from crypto engine"); @@ -681,17 +717,6 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) #endif } -/* Return error string for last OpenSSL error - */ -static char *ossl_strerror(unsigned long error, char *buf, size_t size) -{ - /* OpenSSL 0.9.6 and later has a function named - ERR_error_string_n() that takes the size of the buffer as a - third argument */ - ERR_error_string_n(error, buf, size); - return buf; -} - /** * Global SSL init * @@ -793,7 +818,7 @@ int Curl_ossl_check_cxn(struct connectdata *conn) (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK); if(nread == 0) return 0; /* connection has been closed */ - else if(nread == 1) + if(nread == 1) return 1; /* connection still in place */ else if(nread == -1) { int err = SOCKERRNO; @@ -916,26 +941,30 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) } -/* - * This function is called when an SSL connection is closed. - */ -void Curl_ossl_close(struct connectdata *conn, int sockindex) +static void ossl_close(struct ssl_connect_data *connssl) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - if(connssl->handle) { (void)SSL_shutdown(connssl->handle); SSL_set_connect_state(connssl->handle); - SSL_free (connssl->handle); + SSL_free(connssl->handle); connssl->handle = NULL; } if(connssl->ctx) { - SSL_CTX_free (connssl->ctx); + SSL_CTX_free(connssl->ctx); connssl->ctx = NULL; } } +/* + * This function is called when an SSL connection is closed. + */ +void Curl_ossl_close(struct connectdata *conn, int sockindex) +{ + ossl_close(&conn->ssl[sockindex]); + ossl_close(&conn->proxy_ssl[sockindex]); +} + /* * This function is called to shut down the SSL layer but keep the * socket open (CCC - Clear Command Channel) @@ -994,8 +1023,10 @@ 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: %s, errno %d", - ossl_strerror(sslerror, buf, sizeof(buf)), + failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d", + (sslerror ? + ossl_strerror(sslerror, buf, sizeof(buf)) : + SSL_ERROR_to_str(err)), SOCKERRNO); done = 1; break; @@ -1031,7 +1062,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) #endif } - SSL_free (connssl->handle); + SSL_free(connssl->handle); connssl->handle = NULL; } return retval; @@ -1107,16 +1138,20 @@ 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 */ + 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; #ifdef ENABLE_IPV6 if(conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, conn->host.name, &addr)) { + Curl_inet_pton(AF_INET6, hostname, &addr)) { target = GEN_IPADD; addrlen = sizeof(struct in6_addr); } else #endif - if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) { + if(Curl_inet_pton(AF_INET, hostname, &addr)) { target = GEN_IPADD; addrlen = sizeof(struct in_addr); } @@ -1165,11 +1200,11 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) if((altlen == strlen(altptr)) && /* if this isn't true, there was an embedded zero in the name string and we cannot match it. */ - Curl_cert_hostcheck(altptr, conn->host.name)) { + Curl_cert_hostcheck(altptr, hostname)) { dnsmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n", - conn->host.dispname, altptr); + dispname, altptr); } break; @@ -1180,7 +1215,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) ipmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's IP address!\n", - conn->host.dispname); + dispname); } break; } @@ -1196,9 +1231,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) /* an alternative name matched */ ; else if(dNSName || iPAddress) { - infof(data, " subjectAltName does not match %s\n", conn->host.dispname); + infof(data, " subjectAltName does not match %s\n", dispname); failf(data, "SSL: no alternative certificate subject name matches " - "target host name '%s'", conn->host.dispname); + "target host name '%s'", dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -1272,9 +1307,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) "SSL: unable to obtain common name from peer certificate"); result = CURLE_PEER_FAILED_VERIFICATION; } - else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { + else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", peer_CN, conn->host.dispname); + "target host name '%s'", peer_CN, dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -1336,7 +1371,8 @@ static CURLcode verifystatus(struct connectdata *conn, st = SSL_CTX_get_cert_store(connssl->ctx); #if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ - defined(LIBRESSL_VERSION_NUMBER)) + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER <= 0x2040200fL)) /* The authorized responder cert in the OCSP response MUST be signed by the peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert, no problem, but if it's an intermediate cert OpenSSL has a bug where it @@ -1425,7 +1461,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg) { #ifdef SSL2_VERSION_MAJOR if(ssl_ver == SSL2_VERSION_MAJOR) { - switch (msg) { + switch(msg) { case SSL2_MT_ERROR: return "Error"; case SSL2_MT_CLIENT_HELLO: @@ -1449,7 +1485,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg) else #endif if(ssl_ver == SSL3_VERSION_MAJOR) { - switch (msg) { + switch(msg) { case SSL3_MT_HELLO_REQUEST: return "Hello request"; case SSL3_MT_CLIENT_HELLO: @@ -1548,6 +1584,11 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, case TLS1_2_VERSION: verstr = "TLSv1.2"; break; +#endif +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + verstr = "TLSv1.3"; + break; #endif case 0: break; @@ -1571,7 +1612,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, else tls_rt_name = ""; - msg_type = *(char*)buf; + msg_type = *(char *)buf; msg_name = ssl_msg_type(ssl_ver, msg_type); txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n", @@ -1613,7 +1654,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, #ifdef HAS_NPN /* - * in is a list of lenght prefixed strings. this function has to select + * in is a list of length prefixed strings. this function has to select * the protocol we want to use from the list and write its string into out. */ @@ -1677,6 +1718,10 @@ get_ssl_version_txt(SSL *ssl) return ""; switch(SSL_version(ssl)) { +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + return "TLSv1.3"; +#endif #if OPENSSL_VERSION_NUMBER >= 0x1000100FL case TLS1_2_VERSION: return "TLSv1.2"; @@ -1693,6 +1738,85 @@ get_ssl_version_txt(SSL *ssl) return "unknown"; } +static CURLcode +set_ssl_version_min_max(long *ctx_options, 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); + + if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) { + ssl_version_max = ssl_version << 16; + } + + switch(ssl_version) { + case CURL_SSLVERSION_TLSv1_3: +#ifdef TLS1_3_VERSION + { + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION); + *ctx_options |= SSL_OP_NO_TLSv1_2; + } +#else + (void)sockindex; + failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); + return CURLE_NOT_BUILT_IN; +#endif + case CURL_SSLVERSION_TLSv1_2: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_1; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.2 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_1: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.1 support"); + return CURLE_NOT_BUILT_IN; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_TLSv1_0: + *ctx_options |= SSL_OP_NO_SSLv2; + *ctx_options |= SSL_OP_NO_SSLv3; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_TLSv1_0: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_1; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_MAX_TLSv1_1: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL + *ctx_options |= SSL_OP_NO_TLSv1_2; +#endif + /* FALLTHROUGH */ + case CURL_SSLVERSION_MAX_TLSv1_2: + case CURL_SSLVERSION_MAX_DEFAULT: +#ifdef TLS1_3_VERSION + *ctx_options |= SSL_OP_NO_TLSv1_3; +#endif + break; + case CURL_SSLVERSION_MAX_TLSv1_3: +#ifdef TLS1_3_VERSION + break; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); + return CURLE_NOT_BUILT_IN; +#endif + } + return CURLE_OK; +} + static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) { CURLcode result = CURLE_OK; @@ -1702,32 +1826,49 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) X509_LOOKUP *lookup = NULL; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - long ctx_options; + long ctx_options = 0; #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME bool sni; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif #endif + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const long int ssl_version = SSL_CONN_CONFIG(version); +#ifdef USE_TLS_SRP + const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); +#endif + char * const ssl_cert = SSL_SET_OPTION(cert); + 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); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + char error_buffer[256]; DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); /* Make funny stuff to get random input */ - Curl_ossl_seed(data); + result = Curl_ossl_seed(data); + if(result) + return result; - data->set.ssl.certverifyresult = !X509_V_OK; + *certverifyresult = !X509_V_OK; /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { - default: + switch(ssl_version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: /* it will be handled later with the context options */ #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) @@ -1743,7 +1884,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_NOT_BUILT_IN; #else #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + if(ssl_authtype == CURL_TLSAUTH_SRP) return CURLE_SSL_CONNECT_ERROR; #endif req_method = SSLv2_client_method(); @@ -1756,13 +1897,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_NOT_BUILT_IN; #else #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + if(ssl_authtype == CURL_TLSAUTH_SRP) return CURLE_SSL_CONNECT_ERROR; #endif req_method = SSLv3_client_method(); use_sni(FALSE); break; #endif + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } if(connssl->ctx) @@ -1771,7 +1915,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) if(!connssl->ctx) { failf(data, "SSL: couldn't create a context: %s", - ERR_error_string(ERR_peek_error(), NULL)); + ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); return CURLE_OUT_OF_MEMORY; } @@ -1841,14 +1985,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS /* unless the user explicitly ask to allow the protocol vulnerability we use the work-around */ - if(!conn->data->set.ssl_enable_beast) + if(!SSL_SET_OPTION(enable_beast)) ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #endif - switch(data->set.ssl.version) { + switch(ssl_version) { case CURL_SSLVERSION_SSLv3: #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + if(ssl_authtype == CURL_TLSAUTH_SRP) { infof(data, "Set version TLSv1.x for SRP authorisation\n"); } #endif @@ -1857,6 +2001,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if OPENSSL_VERSION_NUMBER >= 0x1000100FL ctx_options |= SSL_OP_NO_TLSv1_1; ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif #endif break; @@ -1867,43 +2014,33 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) break; case CURL_SSLVERSION_TLSv1_0: - ctx_options |= SSL_OP_NO_SSLv2; - ctx_options |= SSL_OP_NO_SSLv3; -#if OPENSSL_VERSION_NUMBER >= 0x1000100FL - ctx_options |= SSL_OP_NO_TLSv1_1; - ctx_options |= SSL_OP_NO_TLSv1_2; -#endif - break; - -#if OPENSSL_VERSION_NUMBER >= 0x1000100FL case CURL_SSLVERSION_TLSv1_1: - ctx_options |= SSL_OP_NO_SSLv2; - ctx_options |= SSL_OP_NO_SSLv3; - ctx_options |= SSL_OP_NO_TLSv1; - ctx_options |= SSL_OP_NO_TLSv1_2; - break; - case CURL_SSLVERSION_TLSv1_2: - ctx_options |= SSL_OP_NO_SSLv2; - ctx_options |= SSL_OP_NO_SSLv3; - ctx_options |= SSL_OP_NO_TLSv1; - ctx_options |= SSL_OP_NO_TLSv1_1; + case CURL_SSLVERSION_TLSv1_3: + result = set_ssl_version_min_max(&ctx_options, conn, sockindex); + if(result != CURLE_OK) + return result; break; -#endif -#ifndef OPENSSL_NO_SSL2 case CURL_SSLVERSION_SSLv2: +#ifndef OPENSSL_NO_SSL2 ctx_options |= SSL_OP_NO_SSLv3; ctx_options |= SSL_OP_NO_TLSv1; #if OPENSSL_VERSION_NUMBER >= 0x1000100FL ctx_options |= SSL_OP_NO_TLSv1_1; ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif #endif break; +#else + failf(data, OSSL_PACKAGE " was built without SSLv2 support"); + return CURLE_NOT_BUILT_IN; #endif default: - failf(data, "Unsupported SSL protocol version"); + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } @@ -1942,19 +2079,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } #endif - if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) { - if(!cert_stuff(conn, - connssl->ctx, - data->set.str[STRING_CERT], - data->set.str[STRING_CERT_TYPE], - data->set.str[STRING_KEY], - data->set.str[STRING_KEY_TYPE])) { + if(ssl_cert || ssl_cert_type) { + if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type, + SSL_SET_OPTION(key), SSL_SET_OPTION(key_type), + SSL_SET_OPTION(key_passwd))) { /* failf() is already done in cert_stuff() */ return CURLE_SSL_CERTPROBLEM; } } - ciphers = data->set.str[STRING_SSL_CIPHER_LIST]; + ciphers = SSL_CONN_CONFIG(cipher_list); if(!ciphers) ciphers = (char *)DEFAULT_CIPHER_SELECTION; if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) { @@ -1964,18 +2098,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, "Cipher selection: %s\n", ciphers); #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + if(ssl_authtype == CURL_TLSAUTH_SRP) { + char * const ssl_username = SSL_SET_OPTION(username); - if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) { + infof(data, "Using TLS-SRP username: %s\n", ssl_username); + + if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) { failf(data, "Unable to set SRP user name"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) { + if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) { failf(data, "failed setting SRP password"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!data->set.str[STRING_SSL_CIPHER_LIST]) { + if(!SSL_CONN_CONFIG(cipher_list)) { infof(data, "Setting cipher list SRP\n"); if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) { @@ -1985,28 +2121,23 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } } #endif - if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) { + + if(ssl_cafile || ssl_capath) { /* tell SSL where to find CA certificates that are used to verify the servers certificate. */ - if(!SSL_CTX_load_verify_locations(connssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { - if(data->set.ssl.verifypeer) { + if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) { + if(verifypeer) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:\n" " CAfile: %s\n CApath: %s", - data->set.str[STRING_SSL_CAFILE]? - data->set.str[STRING_SSL_CAFILE]: "none", - data->set.str[STRING_SSL_CAPATH]? - data->set.str[STRING_SSL_CAPATH] : "none"); + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); return CURLE_SSL_CACERT_BADFILE; } - else { - /* Just continue with a warning if no strict certificate verification - is required. */ - infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); - } + /* Just continue with a warning if no strict certificate verification + is required. */ + infof(data, "error setting certificate verify locations," + " continuing anyway:\n"); } else { /* Everything is fine. */ @@ -2015,40 +2146,33 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, " CAfile: %s\n" " CApath: %s\n", - data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: - "none", - data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: - "none"); + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); } #ifdef CURL_CA_FALLBACK - else if(data->set.ssl.verifypeer) { + else if(verifypeer) { /* verfying the peer without any CA certificates won't work so use openssl's built in default as fallback */ SSL_CTX_set_default_verify_paths(connssl->ctx); } #endif - if(data->set.str[STRING_SSL_CRLFILE]) { + if(ssl_crlfile) { /* tell SSL where to find CRL file that is used to check certificate * revocation */ lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx), X509_LOOKUP_file()); if(!lookup || - (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE], - X509_FILETYPE_PEM)) ) { - failf(data, "error loading CRL file: %s", - data->set.str[STRING_SSL_CRLFILE]); + (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { + failf(data, "error loading CRL file: %s", ssl_crlfile); return CURLE_SSL_CRL_BADFILE; } - else { - /* Everything is fine. */ - infof(data, "successfully load CRL file:\n"); - X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), - X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); - } - infof(data, - " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ? - data->set.str[STRING_SSL_CRLFILE]: "none"); + /* Everything is fine. */ + infof(data, "successfully load CRL file:\n"); + X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), + X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); + + infof(data, " CRLfile: %s\n", ssl_crlfile); } /* Try building a chain using issuers in the trusted store first to avoid @@ -2059,7 +2183,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest */ #if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS) - if(data->set.ssl.verifypeer) { + if(verifypeer) { X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), X509_V_FLAG_TRUSTED_FIRST); } @@ -2070,8 +2194,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ SSL_CTX_set_verify(connssl->ctx, - data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, - NULL); + verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { @@ -2094,48 +2217,56 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(data->set.ssl.verifystatus) + if(SSL_CONN_CONFIG(verifystatus)) SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp); #endif SSL_set_connect_state(connssl->handle); connssl->server_cert = 0x0; - #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif sni && - !SSL_set_tlsext_host_name(connssl->handle, conn->host.name)) + !SSL_set_tlsext_host_name(connssl->handle, hostname)) 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(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(connssl->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); failf(data, "SSL: SSL_set_session failed: %s", - ERR_error_string(ERR_get_error(), NULL)); + ossl_strerror(ERR_get_error(), error_buffer, + sizeof(error_buffer))); return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ - infof (data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); } - /* pass the raw socket into the SSL layers */ - if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + if(conn->proxy_ssl[sockindex].use) { + BIO *const bio = BIO_new(BIO_f_ssl()); + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); + DEBUGASSERT(bio != NULL); + BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE); + SSL_set_bio(connssl->handle, bio, bio); + } + else if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + /* pass the raw socket into the SSL layers */ failf(data, "SSL: SSL_set_fd failed: %s", - ERR_error_string(ERR_get_error(), NULL)); + ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); return CURLE_SSL_CONNECT_ERROR; } @@ -2149,9 +2280,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) struct Curl_easy *data = conn->data; int err; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; DEBUGASSERT(ssl_connect_2 == connssl->connecting_state - || ssl_connect_2_reading == connssl->connecting_state - || ssl_connect_2_writing == connssl->connecting_state); + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); ERR_clear_error(); @@ -2167,15 +2300,14 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) connssl->connecting_state = ssl_connect_2_reading; return CURLE_OK; } - else if(SSL_ERROR_WANT_WRITE == detail) { + if(SSL_ERROR_WANT_WRITE == detail) { connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; } else { /* untreated error */ unsigned long errdetail; - char error_buffer[256]=""; /* OpenSSL documents that this must be at - least 256 bytes long. */ + char error_buffer[256]=""; CURLcode result; long lerr; int lib; @@ -2198,7 +2330,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) lerr = SSL_get_verify_result(connssl->handle); if(lerr != X509_V_OK) { - data->set.ssl.certverifyresult = lerr; + *certverifyresult = lerr; snprintf(error_buffer, sizeof(error_buffer), "SSL certificate problem: %s", X509_verify_cert_error_string(lerr)); @@ -2220,8 +2352,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) * the SO_ERROR is also lost. */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { - failf(data, "Unknown SSL protocol error in connection to %s:%ld ", - conn->host.name, conn->remote_port); + 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; + failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ", + SSL_ERROR_to_str(detail), hostname, port); return result; } @@ -2245,7 +2380,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) * negotiated */ if(conn->bits.tls_enable_alpn) { - const unsigned char* neg_protocol; + const unsigned char *neg_protocol; unsigned int len; SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len); if(len != 0) { @@ -2276,7 +2411,8 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) { int i, ilen; - if((ilen = (int)len) < 0) + ilen = (int)len; + if(ilen < 0) return 1; /* buffer too big */ i = i2t_ASN1_OBJECT(buf, ilen, a); @@ -2493,44 +2629,25 @@ static CURLcode get_cert_chain(struct connectdata *conn, { const BIGNUM *n; const BIGNUM *e; - const BIGNUM *d; - const BIGNUM *p; - const BIGNUM *q; - const BIGNUM *dmp1; - const BIGNUM *dmq1; - const BIGNUM *iqmp; - RSA_get0_key(rsa, &n, &e, &d); - RSA_get0_factors(rsa, &p, &q); - RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); + RSA_get0_key(rsa, &n, &e, NULL); BN_print(mem, n); push_certinfo("RSA Public Key", i); print_pubkey_BN(rsa, n, i); print_pubkey_BN(rsa, e, i); - print_pubkey_BN(rsa, d, i); - print_pubkey_BN(rsa, p, i); - print_pubkey_BN(rsa, q, i); - print_pubkey_BN(rsa, dmp1, i); - print_pubkey_BN(rsa, dmq1, i); - print_pubkey_BN(rsa, iqmp, i); } #else BIO_printf(mem, "%d", BN_num_bits(rsa->n)); push_certinfo("RSA Public Key", i); print_pubkey_BN(rsa, n, i); print_pubkey_BN(rsa, e, i); - print_pubkey_BN(rsa, d, i); - print_pubkey_BN(rsa, p, i); - print_pubkey_BN(rsa, q, i); - print_pubkey_BN(rsa, dmp1, i); - print_pubkey_BN(rsa, dmq1, i); - print_pubkey_BN(rsa, iqmp, i); #endif break; } case EVP_PKEY_DSA: { +#ifndef OPENSSL_NO_DSA DSA *dsa; #ifdef HAVE_OPAQUE_EVP_PKEY dsa = EVP_PKEY_get0_DSA(pubkey); @@ -2542,25 +2659,23 @@ static CURLcode get_cert_chain(struct connectdata *conn, const BIGNUM *p; const BIGNUM *q; const BIGNUM *g; - const BIGNUM *priv_key; const BIGNUM *pub_key; DSA_get0_pqg(dsa, &p, &q, &g); - DSA_get0_key(dsa, &pub_key, &priv_key); + DSA_get0_key(dsa, &pub_key, NULL); print_pubkey_BN(dsa, p, i); print_pubkey_BN(dsa, q, i); print_pubkey_BN(dsa, g, i); - print_pubkey_BN(dsa, priv_key, i); print_pubkey_BN(dsa, pub_key, i); } #else print_pubkey_BN(dsa, p, i); print_pubkey_BN(dsa, q, i); print_pubkey_BN(dsa, g, i); - print_pubkey_BN(dsa, priv_key, i); print_pubkey_BN(dsa, pub_key, i); #endif +#endif /* !OPENSSL_NO_DSA */ break; } case EVP_PKEY_DH: @@ -2576,20 +2691,17 @@ static CURLcode get_cert_chain(struct connectdata *conn, const BIGNUM *p; const BIGNUM *q; const BIGNUM *g; - const BIGNUM *priv_key; const BIGNUM *pub_key; DH_get0_pqg(dh, &p, &q, &g); - DH_get0_key(dh, &pub_key, &priv_key); + DH_get0_key(dh, &pub_key, NULL); print_pubkey_BN(dh, p, i); print_pubkey_BN(dh, q, i); print_pubkey_BN(dh, g, i); - print_pubkey_BN(dh, priv_key, i); print_pubkey_BN(dh, pub_key, i); } #else print_pubkey_BN(dh, p, i); print_pubkey_BN(dh, g, i); - print_pubkey_BN(dh, priv_key, i); print_pubkey_BN(dh, pub_key, i); #endif break; @@ -2696,8 +2808,10 @@ static CURLcode servercert(struct connectdata *conn, struct Curl_easy *data = conn->data; X509 *issuer; FILE *fp; - char *buffer = data->state.buffer; + char buffer[2048]; const char *ptr; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; BIO *mem = BIO_new(BIO_s_mem()); if(data->set.ssl.certinfo) @@ -2706,6 +2820,7 @@ static CURLcode servercert(struct connectdata *conn, connssl->server_cert = SSL_get_peer_certificate(connssl->handle); if(!connssl->server_cert) { + BIO_free(mem); if(!strict) return CURLE_OK; @@ -2713,10 +2828,10 @@ static CURLcode servercert(struct connectdata *conn, return CURLE_PEER_FAILED_VERIFICATION; } - infof(data, "Server certificate:\n"); + infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert), - buffer, BUFSIZE); + buffer, sizeof(buffer)); infof(data, " subject: %s\n", rc?"[NONE]":buffer); ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert)); @@ -2731,7 +2846,7 @@ static CURLcode servercert(struct connectdata *conn, BIO_free(mem); - if(data->set.ssl.verifyhost) { + if(SSL_CONN_CONFIG(verifyhost)) { result = verifyhost(conn, connssl->server_cert); if(result) { X509_free(connssl->server_cert); @@ -2741,7 +2856,7 @@ static CURLcode servercert(struct connectdata *conn, } rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert), - buffer, BUFSIZE); + buffer, sizeof(buffer)); if(rc) { if(strict) failf(data, "SSL: couldn't get X509-issuer name!"); @@ -2754,12 +2869,12 @@ static CURLcode servercert(struct connectdata *conn, deallocating the certificate. */ /* e.g. match issuer name with provided issuer certificate */ - if(data->set.str[STRING_SSL_ISSUERCERT]) { - fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT); + if(SSL_SET_OPTION(issuercert)) { + fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT); if(!fp) { if(strict) failf(data, "SSL: Unable to open issuer cert (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); connssl->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; @@ -2769,7 +2884,7 @@ static CURLcode servercert(struct connectdata *conn, if(!issuer) { if(strict) failf(data, "SSL: Unable to read issuer cert (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); X509_free(issuer); fclose(fp); @@ -2781,7 +2896,7 @@ static CURLcode servercert(struct connectdata *conn, if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) { if(strict) failf(data, "SSL: Certificate issuer check failed (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); X509_free(issuer); connssl->server_cert = NULL; @@ -2789,15 +2904,14 @@ static CURLcode servercert(struct connectdata *conn, } infof(data, " SSL certificate issuer check ok (%s)\n", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(issuer); } - lerr = data->set.ssl.certverifyresult = - SSL_get_verify_result(connssl->handle); + lerr = *certverifyresult = SSL_get_verify_result(connssl->handle); - if(data->set.ssl.certverifyresult != X509_V_OK) { - if(data->set.ssl.verifypeer) { + if(*certverifyresult != 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? */ if(strict) @@ -2816,7 +2930,7 @@ static CURLcode servercert(struct connectdata *conn, #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { result = verifystatus(conn, connssl); if(result) { X509_free(connssl->server_cert); @@ -2830,7 +2944,8 @@ static CURLcode servercert(struct connectdata *conn, /* when not strict, we don't bother about the verify cert problems */ result = CURLE_OK; - ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(!result && ptr) { result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr); if(result) @@ -2852,7 +2967,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { bool incache; SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -2864,7 +2979,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) regardless of its state. */ Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + incache = !(Curl_ssl_getsessionid(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"); @@ -2875,7 +2991,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) if(!incache) { result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */); + 0 /* unknown size */, sockindex); if(result) { Curl_ssl_sessionid_unlock(conn); failf(data, "failed to store ssl session"); @@ -2899,8 +3015,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) * operations. */ - result = servercert(conn, connssl, - (data->set.ssl.verifypeer || data->set.ssl.verifyhost)); + result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost))); if(!result) connssl->connecting_state = ssl_connect_done; @@ -2920,7 +3036,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn, struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; + time_t timeout_ms; int what; /* check if the connection has already been established */ @@ -2973,16 +3089,14 @@ static CURLcode ossl_connect_common(struct connectdata *conn, failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); return CURLE_SSL_CONNECT_ERROR; } - else if(0 == what) { + if(0 == what) { if(nonblocking) { *done = FALSE; return CURLE_OK; } - else { - /* timeout */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEDOUT; } /* socket is readable or writable */ } @@ -3048,9 +3162,11 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex) { if(conn->ssl[connindex].handle) /* SSL is in use */ - return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE; - else - return FALSE; + return (0 != SSL_pending(conn->ssl[connindex].handle) || + (conn->proxy_ssl[connindex].handle && + 0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ? + TRUE : FALSE; + return FALSE; } static ssize_t ossl_send(struct connectdata *conn, @@ -3062,8 +3178,7 @@ static ssize_t ossl_send(struct connectdata *conn, /* SSL_write() is said to return 'int' while write() and send() returns 'size_t' */ int err; - char error_buffer[256]; /* OpenSSL documents that this must be at least 256 - bytes long. */ + char error_buffer[256]; unsigned long sslerror; int memlen; int rc; @@ -3093,13 +3208,24 @@ static ssize_t ossl_send(struct connectdata *conn, /* A failure in the SSL library occurred, usually a protocol error. The OpenSSL error queue contains more information on the error. */ sslerror = ERR_get_error(); - failf(conn->data, "SSL_write() error: %s", - ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); + if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL && + ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET && + conn->ssl[sockindex].state == ssl_connection_complete && + conn->proxy_ssl[sockindex].state == ssl_connection_complete) { + char ver[120]; + Curl_ossl_version(ver, 120); + failf(conn->data, "Error: %s does not support double SSL tunneling.", + ver); + } + else + failf(conn->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, "SSL_write() return error %d", err); + failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d", + SSL_ERROR_to_str(err), SOCKERRNO); *curlcode = CURLE_SEND_ERROR; return -1; } @@ -3113,8 +3239,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ size_t buffersize, /* max amount to read */ CURLcode *curlcode) { - char error_buffer[256]; /* OpenSSL documents that this must be at - least 256 bytes long. */ + char error_buffer[256]; unsigned long sslerror; ssize_t nread; int buffsize; @@ -3144,8 +3269,10 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ if((nread < 0) || sslerror) { /* If the return code was negative or there actually is an error in the queue */ - failf(conn->data, "SSL read: %s, errno %d", - ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)), + failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d", + (sslerror ? + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)) : + SSL_ERROR_to_str(err)), SOCKERRNO); *curlcode = CURLE_RECV_ERROR; return -1; @@ -3178,7 +3305,7 @@ size_t Curl_ossl_version(char *buffer, size_t size) sub[0] = 'z'; } else { - sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1); + sub[0] = (char) (minor_ver + 'a' - 1); } } else @@ -3195,14 +3322,21 @@ size_t Curl_ossl_version(char *buffer, size_t size) } /* can be called with data == NULL */ -int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy, - size_t length) +CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy, + size_t length) { + int rc; if(data) { - Curl_ossl_seed(data); /* Initiate the seed if not already done */ + if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */ + return CURLE_FAILED_INIT; /* couldn't seed for some reason */ + } + else { + if(!rand_enough()) + return CURLE_FAILED_INIT; } - RAND_bytes(entropy, curlx_uztosi(length)); - return 0; /* 0 as in no problem */ + /* RAND_bytes() returns 1 on success, 0 otherwise. */ + rc = RAND_bytes(entropy, curlx_uztosi(length)); + return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT); } void Curl_ossl_md5sum(unsigned char *tmp, /* input */ diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h index ee18e710f..b9648d514 100644 --- a/Utilities/cmcurl/lib/vtls/openssl.h +++ b/Utilities/cmcurl/lib/vtls/openssl.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -66,8 +66,8 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex); /* return 0 if a find random is filled in */ -int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy, - size_t length); +CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy, + size_t length); void Curl_ossl_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum /* output */, @@ -79,6 +79,9 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ bool Curl_ossl_cert_status_request(void); +/* Support HTTPS-proxy */ +#define HTTPS_PROXY_SUPPORT 1 + /* Set the API backend definition to OpenSSL */ #define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c index 18b564e02..669091cb5 100644 --- a/Utilities/cmcurl/lib/vtls/polarssl.c +++ b/Utilities/cmcurl/lib/vtls/polarssl.c @@ -140,6 +140,68 @@ static void polarssl_debug(void *context, int level, const char *line) static Curl_recv polarssl_recv; static Curl_send polarssl_send; +static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version) +{ + switch(ssl_version) { + case CURL_SSLVERSION_TLSv1_0: + *polarver = SSL_MINOR_VERSION_1; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_1: + *polarver = SSL_MINOR_VERSION_2; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_2: + *polarver = SSL_MINOR_VERSION_3; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1_3: + break; + } + return CURLE_SSL_CONNECT_ERROR; +} + +static CURLcode +set_ssl_version_min_max(struct connectdata *conn, int sockindex) +{ + struct Curl_easy *data = conn->data; + struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + long ssl_version = SSL_CONN_CONFIG(version); + long ssl_version_max = SSL_CONN_CONFIG(version_max); + int ssl_min_ver = SSL_MINOR_VERSION_1; + int ssl_max_ver = SSL_MINOR_VERSION_1; + CURLcode result = CURLE_OK; + + switch(ssl_version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + ssl_version = CURL_SSLVERSION_TLSv1_0; + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version << 16; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + + result = polarssl_version_from_curl(&ssl_min_ver, ssl_version); + if(result) { + failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); + return result; + } + result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16); + if(result) { + failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); + return result; + } + + ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver); + ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver); + + return result; +} static CURLcode polarssl_connect_step1(struct connectdata *conn, @@ -147,12 +209,16 @@ polarssl_connect_step1(struct connectdata *conn, { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char *capath = SSL_CONN_CONFIG(CApath); + 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; int ret = -1; char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } @@ -180,30 +246,29 @@ polarssl_connect_step1(struct connectdata *conn, /* Load the trusted CA */ memset(&connssl->cacert, 0, sizeof(x509_crt)); - if(data->set.str[STRING_SSL_CAFILE]) { + if(SSL_CONN_CONFIG(CAfile)) { ret = x509_crt_parse_file(&connssl->cacert, - data->set.str[STRING_SSL_CAFILE]); + SSL_CONN_CONFIG(CAfile)); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); + SSL_CONN_CONFIG(CAfile), -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } - if(data->set.str[STRING_SSL_CAPATH]) { - ret = x509_crt_parse_path(&connssl->cacert, - data->set.str[STRING_SSL_CAPATH]); + if(capath) { + ret = x509_crt_parse_path(&connssl->cacert, capath); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); + capath, -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } @@ -211,25 +276,25 @@ polarssl_connect_step1(struct connectdata *conn, /* Load the client certificate */ memset(&connssl->clicert, 0, sizeof(x509_crt)); - if(data->set.str[STRING_CERT]) { + if(SSL_SET_OPTION(cert)) { ret = x509_crt_parse_file(&connssl->clicert, - data->set.str[STRING_CERT]); + SSL_SET_OPTION(cert)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_CERT], -ret, errorbuf); + SSL_SET_OPTION(cert), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ - if(data->set.str[STRING_KEY]) { + if(SSL_SET_OPTION(key)) { pk_context pk; pk_init(&pk); - ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], - data->set.str[STRING_KEY_PASSWD]); + ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) @@ -241,7 +306,7 @@ polarssl_connect_step1(struct connectdata *conn, if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_KEY], -ret, errorbuf); + SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -250,29 +315,27 @@ polarssl_connect_step1(struct connectdata *conn, /* Load the CRL */ memset(&connssl->crl, 0, sizeof(x509_crl)); - if(data->set.str[STRING_SSL_CRLFILE]) { + if(SSL_SET_OPTION(CRLfile)) { ret = x509_crl_parse_file(&connssl->crl, - data->set.str[STRING_SSL_CRLFILE]); + SSL_SET_OPTION(CRLfile)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); + SSL_SET_OPTION(CRLfile), -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } - infof(data, "PolarSSL: Connecting to %s:%d\n", - conn->host.name, conn->remote_port); + infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port); if(ssl_init(&connssl->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } - switch(data->set.ssl.version) { - default: + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, @@ -286,26 +349,18 @@ polarssl_connect_step1(struct connectdata *conn, infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: - ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_1); - ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_1); - infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n"); - break; case CURL_SSLVERSION_TLSv1_1: - ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_2); - ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_2); - infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n"); - break; case CURL_SSLVERSION_TLSv1_2: - ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_3); - ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, - SSL_MINOR_VERSION_3); - infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); - break; + case CURL_SSLVERSION_TLSv1_3: + { + CURLcode result = set_ssl_version_min_max(conn, sockindex); + if(result != CURLE_OK) + return result; + break; + } + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); @@ -320,11 +375,11 @@ polarssl_connect_step1(struct connectdata *conn, ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = ssl_set_session(&connssl->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); @@ -339,12 +394,12 @@ polarssl_connect_step1(struct connectdata *conn, ssl_set_ca_chain(&connssl->ssl, &connssl->cacert, &connssl->crl, - conn->host.name); + hostname); ssl_set_own_cert_rsa(&connssl->ssl, &connssl->clicert, &connssl->rsa); - if(ssl_set_hostname(&connssl->ssl, conn->host.name)) { + if(ssl_set_hostname(&connssl->ssl, hostname)) { /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ @@ -354,7 +409,7 @@ polarssl_connect_step1(struct connectdata *conn, #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { - static const char* protocols[3]; + static const char *protocols[3]; int cur = 0; #ifdef USE_NGHTTP2 @@ -390,6 +445,10 @@ polarssl_connect_step2(struct connectdata *conn, struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; char buffer[1024]; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + char errorbuf[128]; errorbuf[0] = 0; @@ -423,7 +482,7 @@ polarssl_connect_step2(struct connectdata *conn, ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); - if(ret && data->set.ssl.verifypeer) { + if(ret && SSL_CONN_CONFIG(verifypeer)) { if(ret & BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); @@ -451,7 +510,7 @@ polarssl_connect_step2(struct connectdata *conn, } /* adapted from mbedtls.c */ - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + if(pinnedpubkey) { int size; CURLcode result; x509_crt *p; @@ -493,7 +552,7 @@ polarssl_connect_step2(struct connectdata *conn, /* pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, - data->set.str[STRING_SSL_PINNEDPUBLICKEY], + pinnedpubkey, &pubkey[PUB_DER_MAX_BYTES - size], size); if(result) { x509_crt_free(p); @@ -544,7 +603,7 @@ polarssl_connect_step3(struct connectdata *conn, DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { int ret; ssl_session *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -553,7 +612,7 @@ polarssl_connect_step3(struct connectdata *conn, if(!our_ssl_sessionid) return CURLE_OUT_OF_MEMORY; - ssl_session_init(our_ssl_sessionid); + memset(our_ssl_sessionid, 0, sizeof(ssl_session)); ret = ssl_get_session(&connssl->ssl, our_ssl_sessionid); if(ret) { @@ -563,10 +622,10 @@ polarssl_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)) + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) Curl_ssl_delsessionid(conn, old_ssl_sessionid); - retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0); + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); Curl_ssl_sessionid_unlock(conn); if(retcode) { free(our_ssl_sessionid); @@ -805,4 +864,10 @@ void Curl_polarssl_cleanup(void) (void)Curl_polarsslthreadlock_thread_cleanup(); } + +int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex) +{ + return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0; +} + #endif /* USE_POLARSSL */ diff --git a/Utilities/cmcurl/lib/vtls/polarssl.h b/Utilities/cmcurl/lib/vtls/polarssl.h index 7098b24a4..47af7b417 100644 --- a/Utilities/cmcurl/lib/vtls/polarssl.h +++ b/Utilities/cmcurl/lib/vtls/polarssl.h @@ -31,6 +31,7 @@ /* Called on first use PolarSSL, setup threading if supported */ int Curl_polarssl_init(void); void Curl_polarssl_cleanup(void); +int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex); CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex); @@ -69,7 +70,7 @@ int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex); #define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) #define curlssl_version Curl_polarssl_version #define curlssl_check_cxn(x) ((void)x, -1) -#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define curlssl_data_pending(x,y) Curl_polarssl_data_pending(x, y) #define curlssl_sha256sum(a,b,c,d) sha256(a,b,c,0) /* This might cause libcurl to use a weeker random! diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c index f731eebdc..94603018b 100644 --- a/Utilities/cmcurl/lib/vtls/schannel.c +++ b/Utilities/cmcurl/lib/vtls/schannel.c @@ -7,7 +7,7 @@ * * Copyright (C) 2012 - 2016, Marc Hoersken, * Copyright (C) 2012, Mark Salisbury, - * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -59,6 +59,7 @@ #include "x509asn1.h" #include "curl_printf.h" #include "system_win32.h" +#include "hostcheck.h" /* The last #include file should be: */ #include "curl_memory.h" @@ -101,6 +102,41 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, desc->cBuffers = NumArrElem; } +static CURLcode +set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, 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; + + switch(ssl_version_max) { + case CURL_SSLVERSION_MAX_NONE: + ssl_version_max = ssl_version << 16; + break; + case CURL_SSLVERSION_MAX_DEFAULT: + ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; + break; + } + for(; i <= (ssl_version_max >> 16); ++i) { + switch(i) { + case CURL_SSLVERSION_TLSv1_0: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_1: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_2: + schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT; + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Schannel: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + } + } + return CURLE_OK; +} + static CURLcode schannel_connect_step1(struct connectdata *conn, int sockindex) { @@ -123,9 +159,19 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) #endif TCHAR *host_name; CURLcode result; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); + + if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, + VERSION_LESS_THAN_EQUAL)) { + /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and + algorithms that may not be supported by all servers. */ + infof(data, "schannel: WinSSL version is old and may not be able to " + "connect to some servers due to lack of SNI, algorithms, etc.\n"); + } #ifdef HAS_ALPN /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. @@ -142,9 +188,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) connssl->cred = NULL; /* check for an existing re-usable credential handle */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) { + if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { connssl->cred = old_cred; infof(data, "schannel: re-using existing credential handle\n"); @@ -161,7 +207,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) memset(&schannel_cred, 0, sizeof(schannel_cred)); schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; - if(data->set.ssl.verifypeer) { + if(conn->ssl_config.verifypeer) { #ifdef _WIN32_WCE /* certificate validation on CE doesn't seem to work right; we'll do it following a more manual process. */ @@ -170,13 +216,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) SCH_CRED_IGNORE_REVOCATION_OFFLINE; #else schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; - if(data->set.ssl_no_revoke) + /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */ + if(data->set.ssl.no_revoke) schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; else schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; #endif - if(data->set.ssl_no_revoke) + if(data->set.ssl.no_revoke) infof(data, "schannel: disabled server certificate revocation " "checks\n"); else @@ -189,15 +236,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) infof(data, "schannel: disabled server certificate revocation checks\n"); } - if(!data->set.ssl.verifyhost) { + if(!conn->ssl_config.verifyhost) { schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; infof(data, "schannel: verifyhost setting prevents Schannel from " "comparing the supplied target name with the subject " - "names in server certificates. Also disables SNI.\n"); + "names in server certificates.\n"); } - switch(data->set.ssl.version) { - default: + switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | @@ -205,20 +251,24 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) SP_PROT_TLS1_2_CLIENT; break; case CURL_SSLVERSION_TLSv1_0: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT; - break; case CURL_SSLVERSION_TLSv1_1: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT; - break; case CURL_SSLVERSION_TLSv1_2: - schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; - break; + case CURL_SSLVERSION_TLSv1_3: + { + result = set_ssl_version_min_max(&schannel_cred, conn); + if(result != CURLE_OK) + return result; + break; + } case CURL_SSLVERSION_SSLv3: schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; break; case CURL_SSLVERSION_SSLv2: schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } /* allocate memory for the re-usable credential handle */ @@ -253,9 +303,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) } /* Warn if SNI is disabled due to use of an IP address */ - if(Curl_inet_pton(AF_INET, conn->host.name, &addr) + if(Curl_inet_pton(AF_INET, hostname, &addr) #ifdef ENABLE_IPV6 - || Curl_inet_pton(AF_INET6, conn->host.name, &addr6) + || Curl_inet_pton(AF_INET6, hostname, &addr6) #endif ) { infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); @@ -265,17 +315,17 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) if(connssl->use_alpn) { int cur = 0; int list_start_index = 0; - unsigned int* extension_len = NULL; + unsigned int *extension_len = NULL; unsigned short* list_len = NULL; /* The first four bytes will be an unsigned int indicating number of bytes of data in the rest of the the buffer. */ - extension_len = (unsigned int*)(&alpn_buffer[cur]); + extension_len = (unsigned int *)(&alpn_buffer[cur]); cur += sizeof(unsigned int); /* The next four bytes are an indicator that this buffer will contain ALPN data, as opposed to NPN, for example. */ - *(unsigned int*)&alpn_buffer[cur] = + *(unsigned int *)&alpn_buffer[cur] = SecApplicationProtocolNegotiationExt_ALPN; cur += sizeof(unsigned int); @@ -333,7 +383,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) } memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt)); - host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) return CURLE_OUT_OF_MEMORY; @@ -382,6 +432,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) connssl->recv_unrecoverable_err = CURLE_OK; connssl->recv_sspi_close_notify = false; connssl->recv_connection_closed = false; + connssl->encdata_is_incomplete = false; /* continue to second handshake step */ connssl->connecting_state = ssl_connect_2; @@ -406,11 +457,13 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) TCHAR *host_name; CURLcode result; bool doread; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); if(!connssl->cred || !connssl->ctxt) return CURLE_SSL_CONNECT_ERROR; @@ -428,6 +481,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* buffer to store previously received and encrypted data */ if(connssl->encdata_buffer == NULL) { + connssl->encdata_is_incomplete = false; connssl->encdata_offset = 0; connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; connssl->encdata_buffer = malloc(connssl->encdata_length); @@ -480,6 +534,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* increase encrypted data buffer offset */ connssl->encdata_offset += nread; + connssl->encdata_is_incomplete = false; + infof(data, "schannel: encrypted data got %zd\n", nread); } infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", @@ -506,7 +562,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer, connssl->encdata_offset); - host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) return CURLE_OUT_OF_MEMORY; @@ -524,6 +580,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* check if the handshake was incomplete */ if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + connssl->encdata_is_incomplete = true; connssl->connecting_state = ssl_connect_2_reading; infof(data, "schannel: received incomplete message, need more data\n"); return CURLE_OK; @@ -573,7 +630,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) else failf(data, "schannel: next InitializeSecurityContext failed: %s", Curl_sspi_strerror(conn, sspi_status)); - return CURLE_SSL_CONNECT_ERROR; + return sspi_status == SEC_E_UNTRUSTED_ROOT ? + CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CONNECT_ERROR; } /* check if there was additional remaining encrypted data */ @@ -623,7 +681,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) #ifdef _WIN32_WCE /* Windows CE doesn't do any server certificate validation. We have to do it manually. */ - if(data->set.ssl.verifypeer) + if(conn->ssl_config.verifypeer) return verify_certificate(conn, sockindex); #endif @@ -638,6 +696,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; +#endif #ifdef HAS_ALPN SecPkgContext_ApplicationProtocol alpn_result; #endif @@ -645,7 +707,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); if(!connssl->cred) return CURLE_SSL_CONNECT_ERROR; @@ -701,12 +763,13 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) #endif /* save the current session data for possible re-use */ - if(conn->ssl_config.sessionid) { + if(SSL_SET_OPTION(primary.sessionid)) { bool incache; struct curl_schannel_cred *old_cred = NULL; Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)); + incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, + sockindex)); if(incache) { if(old_cred != connssl->cred) { infof(data, "schannel: old credential handle is stale, removing\n"); @@ -717,7 +780,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) } if(!incache) { result = Curl_ssl_addsessionid(conn, (void *)connssl->cred, - sizeof(struct curl_schannel_cred)); + sizeof(struct curl_schannel_cred), + sockindex); if(result) { Curl_ssl_sessionid_unlock(conn); failf(data, "schannel: failed to store credential handle"); @@ -769,7 +833,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex, struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; + time_t timeout_ms; int what; /* check if the connection has already been established */ @@ -957,7 +1021,7 @@ schannel_send(struct connectdata *conn, int sockindex, /* send entire message or fail */ while(len > (size_t)written) { ssize_t this_write; - long timeleft; + time_t timeleft; int what; this_write = 0; @@ -1119,6 +1183,7 @@ schannel_recv(struct connectdata *conn, int sockindex, } else if(nread > 0) { connssl->encdata_offset += (size_t)nread; + connssl->encdata_is_incomplete = false; infof(data, "schannel: encrypted data got %zd\n", nread); } } @@ -1255,6 +1320,7 @@ schannel_recv(struct connectdata *conn, int sockindex, } } else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + connssl->encdata_is_incomplete = true; if(!*err) *err = CURLE_AGAIN; infof(data, "schannel: failed to decrypt data, need more data\n"); @@ -1356,8 +1422,8 @@ bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex) const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; if(connssl->use) /* SSL/TLS is in use */ - return (connssl->encdata_offset > 0 || - connssl->decdata_offset > 0) ? TRUE : FALSE; + return (connssl->decdata_offset > 0 || + (connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete)); else return FALSE; } @@ -1376,9 +1442,11 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) */ struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); if(connssl->cred && connssl->ctxt) { SecBufferDesc BuffDesc; @@ -1400,7 +1468,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) failf(data, "schannel: ApplyControlToken failure: %s", Curl_sspi_strerror(conn, sspi_status)); - host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) return CURLE_OUT_OF_MEMORY; @@ -1458,6 +1526,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) Curl_safefree(connssl->encdata_buffer); connssl->encdata_length = 0; connssl->encdata_offset = 0; + connssl->encdata_is_incomplete = false; } /* free internal buffer for received decrypted data */ @@ -1499,21 +1568,21 @@ size_t Curl_schannel_version(char *buffer, size_t size) return size; } -int Curl_schannel_random(unsigned char *entropy, size_t length) +CURLcode Curl_schannel_random(unsigned char *entropy, size_t length) { HCRYPTPROV hCryptProv = 0; if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) - return 1; + return CURLE_FAILED_INIT; if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) { CryptReleaseContext(hCryptProv, 0UL); - return 1; + return CURLE_FAILED_INIT; } CryptReleaseContext(hCryptProv, 0UL); - return 0; + return CURLE_OK; } #ifdef _WIN32_WCE @@ -1525,6 +1594,9 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) CURLcode result = CURLE_OK; CERT_CONTEXT *pCertContextServer = NULL; const CERT_CHAIN_CONTEXT *pChainContext = NULL; + const char * const conn_hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : + conn->host.name; status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, @@ -1546,7 +1618,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) NULL, pCertContextServer->hCertStore, &ChainPara, - (data->set.ssl_no_revoke ? 0 : + (data->set.ssl.no_revoke ? 0 : CERT_CHAIN_REVOCATION_CHECK_CHAIN), NULL, &pChainContext)) { @@ -1582,15 +1654,10 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) } if(result == CURLE_OK) { - if(data->set.ssl.verifyhost) { - TCHAR cert_hostname_buff[128]; - xcharp_u hostname; - xcharp_u cert_hostname; + if(conn->ssl_config.verifyhost) { + TCHAR cert_hostname_buff[256]; DWORD len; - cert_hostname.const_tchar_ptr = cert_hostname_buff; - hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name); - /* TODO: Fix this for certificates with multiple alternative names. Right now we're only asking for the first preferred alternative name. Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG @@ -1601,31 +1668,50 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) */ len = CertGetNameString(pCertContextServer, CERT_NAME_DNS_TYPE, - 0, + CERT_NAME_DISABLE_IE4_UTF8_FLAG, NULL, - cert_hostname.tchar_ptr, - 128); - if(len > 0 && *cert_hostname.tchar_ptr == '*') { - /* this is a wildcard cert. try matching the last len - 1 chars */ - int hostname_len = strlen(conn->host.name); - cert_hostname.tchar_ptr++; - if(_tcsicmp(cert_hostname.const_tchar_ptr, - hostname.const_tchar_ptr + hostname_len - len + 2) != 0) - result = CURLE_PEER_FAILED_VERIFICATION; + cert_hostname_buff, + 256); + if(len > 0) { + const char *cert_hostname; + + /* Comparing the cert name and the connection hostname encoded as UTF-8 + * is acceptable since both values are assumed to use ASCII + * (or some equivalent) encoding + */ + cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff); + if(!cert_hostname) { + result = CURLE_OUT_OF_MEMORY; + } + else{ + int match_result; + + match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name); + if(match_result == CURL_HOST_MATCH) { + infof(data, + "schannel: connection hostname (%s) validated " + "against certificate name (%s)\n", + conn->host.name, + cert_hostname); + result = CURLE_OK; + } + else{ + failf(data, + "schannel: connection hostname (%s) " + "does not match certificate name (%s)", + conn->host.name, + cert_hostname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + Curl_unicodefree(cert_hostname); + } } - else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr, - cert_hostname.const_tchar_ptr) != 0) { + else { + failf(data, + "schannel: CertGetNameString did not provide any " + "certificate name information"); result = CURLE_PEER_FAILED_VERIFICATION; } - if(result == CURLE_PEER_FAILED_VERIFICATION) { - char *_cert_hostname; - _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr); - failf(data, "schannel: CertGetNameString() certificate hostname " - "(%s) did not match connection (%s)", - _cert_hostname, conn->host.name); - Curl_unicodefree(_cert_hostname); - } - Curl_unicodefree(hostname.tchar_ptr); } } diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h index 8a4991ec8..8627c63c9 100644 --- a/Utilities/cmcurl/lib/vtls/schannel.h +++ b/Utilities/cmcurl/lib/vtls/schannel.h @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012, Marc Hoersken, , et al. - * Copyright (C) 2012 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -92,7 +92,7 @@ int Curl_schannel_init(void); void Curl_schannel_cleanup(void); size_t Curl_schannel_version(char *buffer, size_t size); -int Curl_schannel_random(unsigned char *entropy, size_t length); +CURLcode Curl_schannel_random(unsigned char *entropy, size_t length); /* Set the API backend definition to Schannel */ #define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c index 56a882341..d5d0971c4 100644 --- a/Utilities/cmcurl/lib/vtls/vtls.c +++ b/Utilities/cmcurl/lib/vtls/vtls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -65,6 +65,7 @@ #include "url.h" #include "progress.h" #include "share.h" +#include "multiif.h" #include "timeval.h" #include "curl_md5.h" #include "warnless.h" @@ -80,94 +81,54 @@ (data->share->specifier & \ (1<var) { \ + dest->var = strdup(source->var); \ + if(!dest->var) \ + return FALSE; \ + } \ + else \ + dest->var = NULL; bool -Curl_ssl_config_matches(struct ssl_config_data* data, - struct ssl_config_data* needle) +Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle) { if((data->version == needle->version) && + (data->version_max == needle->version_max) && (data->verifypeer == needle->verifypeer) && (data->verifyhost == needle->verifyhost) && - safe_strequal(data->CApath, needle->CApath) && - safe_strequal(data->CAfile, needle->CAfile) && - safe_strequal(data->clientcert, needle->clientcert) && - safe_strequal(data->cipher_list, needle->cipher_list)) + Curl_safe_strcasecompare(data->CApath, needle->CApath) && + Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && + Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list)) return TRUE; return FALSE; } bool -Curl_clone_ssl_config(struct ssl_config_data *source, - struct ssl_config_data *dest) +Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest) { - dest->sessionid = source->sessionid; dest->verifyhost = source->verifyhost; dest->verifypeer = source->verifypeer; dest->version = source->version; + dest->version_max = source->version_max; - if(source->CAfile) { - dest->CAfile = strdup(source->CAfile); - if(!dest->CAfile) - return FALSE; - } - else - dest->CAfile = NULL; - - if(source->CApath) { - dest->CApath = strdup(source->CApath); - if(!dest->CApath) - return FALSE; - } - else - dest->CApath = NULL; - - if(source->cipher_list) { - dest->cipher_list = strdup(source->cipher_list); - if(!dest->cipher_list) - return FALSE; - } - else - dest->cipher_list = NULL; - - if(source->egdsocket) { - dest->egdsocket = strdup(source->egdsocket); - if(!dest->egdsocket) - return FALSE; - } - else - dest->egdsocket = NULL; - - if(source->random_file) { - dest->random_file = strdup(source->random_file); - if(!dest->random_file) - return FALSE; - } - else - dest->random_file = NULL; - - if(source->clientcert) { - dest->clientcert = strdup(source->clientcert); - if(!dest->clientcert) - return FALSE; - dest->sessionid = FALSE; - } - else - dest->clientcert = NULL; + CLONE_STRING(CAfile); + CLONE_STRING(CApath); + CLONE_STRING(cipher_list); + CLONE_STRING(egdsocket); + CLONE_STRING(random_file); + CLONE_STRING(clientcert); + /* Disable dest sessionid cache if a client cert is used, CVE-2016-5419. */ + dest->sessionid = (dest->clientcert ? false : source->sessionid); return TRUE; } -void Curl_free_ssl_config(struct ssl_config_data* sslc) +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc) { Curl_safefree(sslc->CAfile); Curl_safefree(sslc->CApath); @@ -177,77 +138,6 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc) Curl_safefree(sslc->clientcert); } - -/* - * Curl_rand() returns a random unsigned integer, 32bit. - * - * This non-SSL function is put here only because this file is the only one - * with knowledge of what the underlying SSL libraries provide in terms of - * randomizers. - * - * NOTE: 'data' may be passed in as NULL when coming from external API without - * easy handle! - * - */ - -unsigned int Curl_rand(struct Curl_easy *data) -{ - unsigned int r = 0; - static unsigned int randseed; - static bool seeded = FALSE; - -#ifdef CURLDEBUG - char *force_entropy = getenv("CURL_ENTROPY"); - if(force_entropy) { - if(!seeded) { - size_t elen = strlen(force_entropy); - size_t clen = sizeof(randseed); - size_t min = elen < clen ? elen : clen; - memcpy((char *)&randseed, force_entropy, min); - seeded = TRUE; - } - else - randseed++; - return randseed; - } -#endif - - /* data may be NULL! */ - if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r))) - return r; - - /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we - instead perform a "best effort" */ - -#ifdef RANDOM_FILE - if(!seeded) { - /* if there's a random file to read a seed from, use it */ - int fd = open(RANDOM_FILE, O_RDONLY); - if(fd > -1) { - /* read random data into the randseed variable */ - ssize_t nread = read(fd, &randseed, sizeof(randseed)); - if(nread == sizeof(randseed)) - seeded = TRUE; - close(fd); - } - } -#endif - - if(!seeded) { - struct timeval now = curlx_tvnow(); - infof(data, "WARNING: Using weak random seed\n"); - randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - seeded = TRUE; - } - - /* Return an unsigned 32-bit pseudo-random number. */ - r = randseed = randseed * 1103515245 + 12345; - return (r << 16) | ((r >> 16) & 0xFFFF); -} - int Curl_ssl_backend(void) { return (int)CURL_SSL_BACKEND; @@ -288,19 +178,54 @@ void Curl_ssl_cleanup(void) static bool ssl_prefs_check(struct Curl_easy *data) { /* check for CURLOPT_SSLVERSION invalid parameter value */ - if((data->set.ssl.version < 0) - || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) { + const long sslver = data->set.ssl.primary.version; + if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) { failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION"); return FALSE; } + + switch(data->set.ssl.primary.version_max) { + case CURL_SSLVERSION_MAX_NONE: + case CURL_SSLVERSION_MAX_DEFAULT: + break; + + default: + if((data->set.ssl.primary.version_max >> 16) < sslver) { + failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION"); + return FALSE; + } + } + return TRUE; } +static CURLcode +ssl_connect_init_proxy(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]); + if(ssl_connection_complete == conn->ssl[sockindex].state && + !conn->proxy_ssl[sockindex].use) { +#if defined(HTTPS_PROXY_SUPPORT) + conn->proxy_ssl[sockindex] = conn->ssl[sockindex]; + memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex])); +#else + return CURLE_NOT_BUILT_IN; +#endif + } + return CURLE_OK; +} + CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex) { CURLcode result; + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } + if(!ssl_prefs_check(conn->data)) return CURLE_SSL_CONNECT_ERROR; @@ -321,6 +246,11 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done) { CURLcode result; + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } if(!ssl_prefs_check(conn->data)) return CURLE_SSL_CONNECT_ERROR; @@ -363,7 +293,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn) */ bool Curl_ssl_getsessionid(struct connectdata *conn, void **ssl_sessionid, - size_t *idsize) /* set 0 if unknown */ + size_t *idsize, /* set 0 if unknown */ + int sockindex) { struct curl_ssl_session *check; struct Curl_easy *data = conn->data; @@ -371,11 +302,18 @@ bool Curl_ssl_getsessionid(struct connectdata *conn, long *general_age; bool no_match = TRUE; + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; + const char * const name = isProxy ? conn->http_proxy.host.name : + conn->host.name; + int port = isProxy ? (int)conn->port : conn->remote_port; *ssl_sessionid = NULL; - DEBUGASSERT(conn->ssl_config.sessionid); + DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); - if(!conn->ssl_config.sessionid) + if(!SSL_SET_OPTION(primary.sessionid)) /* session ID re-use is disabled */ return TRUE; @@ -385,21 +323,21 @@ bool Curl_ssl_getsessionid(struct connectdata *conn, else general_age = &data->state.sessionage; - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { check = &data->state.session[i]; if(!check->sessionid) /* not session ID means blank entry */ continue; - if(strcasecompare(conn->host.name, check->name) && + if(strcasecompare(name, check->name) && ((!conn->bits.conn_to_host && !check->conn_to_host) || (conn->bits.conn_to_host && check->conn_to_host && strcasecompare(conn->conn_to_host.name, check->conn_to_host))) && ((!conn->bits.conn_to_port && check->conn_to_port == -1) || (conn->bits.conn_to_port && check->conn_to_port != -1 && conn->conn_to_port == check->conn_to_port)) && - (conn->remote_port == check->remote_port) && + (port == check->remote_port) && strcasecompare(conn->handler->scheme, check->scheme) && - Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { + Curl_ssl_config_matches(ssl_config, &check->ssl_config)) { /* yes, we have a session ID! */ (*general_age)++; /* increase general age */ check->age = *general_age; /* set this as used in this age */ @@ -428,7 +366,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session) session->sessionid = NULL; session->age = 0; /* fresh */ - Curl_free_ssl_config(&session->ssl_config); + Curl_free_primary_ssl_config(&session->ssl_config); Curl_safefree(session->name); Curl_safefree(session->conn_to_host); @@ -443,7 +381,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) size_t i; struct Curl_easy *data=conn->data; - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { struct curl_ssl_session *check = &data->state.session[i]; if(check->sessionid == ssl_sessionid) { @@ -461,7 +399,8 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) */ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, void *ssl_sessionid, - size_t idsize) + size_t idsize, + int sockindex) { size_t i; struct Curl_easy *data=conn->data; /* the mother of all structs */ @@ -471,10 +410,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, char *clone_conn_to_host; int conn_to_port; long *general_age; + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; - DEBUGASSERT(conn->ssl_config.sessionid); + DEBUGASSERT(SSL_SET_OPTION(primary.sessionid)); - clone_host = strdup(conn->host.name); + clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name); if(!clone_host) return CURLE_OUT_OF_MEMORY; /* bail out */ @@ -505,14 +448,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, } /* find an empty slot for us, or find the oldest */ - for(i = 1; (i < data->set.ssl.max_ssl_sessions) && + for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) && data->state.session[i].sessionid; i++) { if(data->state.session[i].age < oldest_age) { oldest_age = data->state.session[i].age; store = &data->state.session[i]; } } - if(i == data->set.ssl.max_ssl_sessions) + if(i == data->set.general_ssl.max_ssl_sessions) /* cache is full, we must "kill" the oldest entry! */ Curl_ssl_kill_session(store); else @@ -522,16 +465,17 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, store->sessionid = ssl_sessionid; store->idsize = idsize; store->age = *general_age; /* set current age */ - /* free it if there's one already present */ + /* free it if there's one already present */ free(store->name); free(store->conn_to_host); store->name = clone_host; /* clone host name */ store->conn_to_host = clone_conn_to_host; /* clone connect to host name */ store->conn_to_port = conn_to_port; /* connect to port number */ - store->remote_port = conn->remote_port; /* port number */ + /* port number */ + store->remote_port = isProxy ? (int)conn->port : conn->remote_port; store->scheme = conn->handler->scheme; - if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { + if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) { store->sessionid = NULL; /* let caller free sessionid */ free(clone_host); free(clone_conn_to_host); @@ -547,7 +491,7 @@ void Curl_ssl_close_all(struct Curl_easy *data) size_t i; /* kill the session ID cache if not shared */ if(data->state.session && !SSLSESSION_SHARED(data)) { - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) /* the single-killer function handles empty table slots */ Curl_ssl_kill_session(&data->state.session[i]); @@ -558,6 +502,43 @@ void Curl_ssl_close_all(struct Curl_easy *data) curlssl_close_all(data); } +#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_MBEDTLS) +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + + if(!numsocks) + return GETSOCK_BLANK; + + if(connssl->connecting_state == ssl_connect_2_writing) { + /* write mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); + } + if(connssl->connecting_state == ssl_connect_2_reading) { + /* read mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0); + } + + return GETSOCK_BLANK; +} +#else +int Curl_ssl_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */ +#endif + void Curl_ssl_close(struct connectdata *conn, int sockindex) { DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); @@ -615,7 +596,7 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount) return CURLE_OUT_OF_MEMORY; /* store the info in the SSL section */ - data->set.ssl.max_ssl_sessions = amount; + data->set.general_ssl.max_ssl_sessions = amount; data->state.session = session; data->state.sessionage = 1; /* this is brand new */ return CURLE_OK; @@ -691,9 +672,9 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, const char *value, size_t valuelen) { - struct curl_certinfo * ci = &data->info.certs; - char * output; - struct curl_slist * nl; + struct curl_certinfo *ci = &data->info.certs; + char *output; + struct curl_slist *nl; CURLcode result = CURLE_OK; size_t labellen = strlen(label); size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ @@ -736,9 +717,9 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); } -int Curl_ssl_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +CURLcode Curl_ssl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { return curlssl_random(data, entropy, length); } diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h index a41ecc325..2aabeda20 100644 --- a/Utilities/cmcurl/lib/vtls/vtls.h +++ b/Utilities/cmcurl/lib/vtls/vtls.h @@ -50,13 +50,24 @@ #define ALPN_HTTP_1_1_LENGTH 8 #define ALPN_HTTP_1_1 "http/1.1" -bool Curl_ssl_config_matches(struct ssl_config_data* data, - struct ssl_config_data* needle); -bool Curl_clone_ssl_config(struct ssl_config_data* source, - struct ssl_config_data* dest); -void Curl_free_ssl_config(struct ssl_config_data* sslc); - -unsigned int Curl_rand(struct Curl_easy *); +/* set of helper macros for the backends to access the correct fields. For the + proxy or for the remote host - to properly support HTTPS proxy */ + +#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \ + ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \ + 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_CONN_CONFIG(var) (SSL_IS_PROXY() ? \ + conn->proxy_ssl_config.var : conn->ssl_config.var) + +bool Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle); +bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest); +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc); +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); int Curl_ssl_backend(void); @@ -87,12 +98,12 @@ int Curl_ssl_check_cxn(struct connectdata *conn); /* Certificate information list handling. */ void Curl_ssl_free_certinfo(struct Curl_easy *data); -CURLcode Curl_ssl_init_certinfo(struct Curl_easy * data, int num); -CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy * data, int certnum, - const char * label, const char * value, +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum, + const char *label, const char *value, size_t valuelen); -CURLcode Curl_ssl_push_certinfo(struct Curl_easy * data, int certnum, - const char * label, const char * value); +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, + const char *label, const char *value); /* Functions to be used by SSL library adaptation functions */ @@ -116,7 +127,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn); */ bool Curl_ssl_getsessionid(struct connectdata *conn, void **ssl_sessionid, - size_t *idsize); /* set 0 if unknown */ + size_t *idsize, /* set 0 if unknown */ + int sockindex); /* add a new session ID * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). * Caller must ensure that it has properly shared ownership of this sessionid @@ -124,7 +136,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn, */ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, void *ssl_sessionid, - size_t idsize); + size_t idsize, + int sockindex); /* Kill a single session ID entry in the cache * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). * This will call engine-specific curlssl_session_free function, which must @@ -140,10 +153,9 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session); */ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); -/* get N random bytes into the buffer, return 0 if a find random is filled - in */ -int Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, - size_t length); +/* 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 */ diff --git a/Utilities/cmcurl/lib/warnless.c b/Utilities/cmcurl/lib/warnless.c index 0c4472e4a..fb085c86d 100644 --- a/Utilities/cmcurl/lib/warnless.c +++ b/Utilities/cmcurl/lib/warnless.c @@ -183,12 +183,15 @@ curl_off_t curlx_uztoso(size_t uznum) #ifdef __INTEL_COMPILER # pragma warning(push) # pragma warning(disable:810) /* conversion may lose significant bits */ +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4310) /* cast truncates constant value */ #endif DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT); return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT); -#ifdef __INTEL_COMPILER +#if defined(__INTEL_COMPILER) || defined(_MSC_VER) # pragma warning(pop) #endif } diff --git a/Utilities/cmcurl/lib/wildcard.c b/Utilities/cmcurl/lib/wildcard.c index dbbe45f6f..af45c79bd 100644 --- a/Utilities/cmcurl/lib/wildcard.c +++ b/Utilities/cmcurl/lib/wildcard.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,13 +32,9 @@ CURLcode Curl_wildcard_init(struct WildcardData *wc) { - DEBUGASSERT(wc->filelist == NULL); - /* now allocate only wc->filelist, everything else - will be allocated if it is needed. */ - wc->filelist = Curl_llist_alloc(Curl_fileinfo_dtor); - if(!wc->filelist) {; - return CURLE_OUT_OF_MEMORY; - } + Curl_llist_init(&wc->filelist, Curl_fileinfo_dtor); + wc->state = CURLWC_INIT; + return CURLE_OK; } @@ -54,10 +50,8 @@ void Curl_wildcard_dtor(struct WildcardData *wc) } DEBUGASSERT(wc->tmp == NULL); - if(wc->filelist) { - Curl_llist_destroy(wc->filelist, NULL); - wc->filelist = NULL; - } + Curl_llist_destroy(&wc->filelist, NULL); + free(wc->path); wc->path = NULL; diff --git a/Utilities/cmcurl/lib/wildcard.h b/Utilities/cmcurl/lib/wildcard.h index 7f61cd173..8a5e4b769 100644 --- a/Utilities/cmcurl/lib/wildcard.h +++ b/Utilities/cmcurl/lib/wildcard.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010 - 2013, Daniel Stenberg, , et al. + * Copyright (C) 2010 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,9 +24,12 @@ #include +#include "llist.h" + /* list of wildcard process states */ typedef enum { - CURLWC_INIT = 0, + CURLWC_CLEAR = 0, + CURLWC_INIT = 1, CURLWC_MATCHING, /* library is trying to get list of addresses for downloading */ CURLWC_DOWNLOADING, @@ -44,7 +47,7 @@ struct WildcardData { curl_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 *tmp; /* pointer to protocol specific temporary data */ curl_wildcard_tmp_dtor tmp_dtor; void *customptr; /* for CURLOPT_CHUNK_DATA pointer */ diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c index 74a511b2d..bba20233f 100644 --- a/Utilities/cmcurl/lib/x509asn1.c +++ b/Utilities/cmcurl/lib/x509asn1.c @@ -40,6 +40,9 @@ #include "curl_memory.h" #include "memdebug.h" +/* For overflow checks. */ +#define CURL_SIZE_T_MAX ((size_t)-1) + /* ASN.1 OIDs. */ static const char cnOID[] = "2.5.4.3"; /* Common name. */ @@ -105,8 +108,8 @@ static const curl_OID OIDtable[] = { */ -const char * Curl_getASN1Element(curl_asn1Element * elem, - const char * beg, const char * end) +const char *Curl_getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end) { unsigned char b; unsigned long len; @@ -116,8 +119,8 @@ const char * Curl_getASN1Element(curl_asn1Element * elem, ending at `end'. Returns a pointer in source string after the parsed element, or NULL if an error occurs. */ - - if(beg >= end || !*beg) + if(!beg || !end || beg >= end || !*beg || + (size_t)(end - beg) > CURL_ASN1_MAX) return (const char *) NULL; /* Process header byte. */ @@ -152,7 +155,7 @@ const char * Curl_getASN1Element(curl_asn1Element * elem, elem->end = beg; return beg + 1; } - else if(beg + b > end) + else if((unsigned)b > (size_t)(end - beg)) return (const char *) NULL; /* Does not fit in source. */ else { /* Get long length. */ @@ -163,16 +166,16 @@ const char * Curl_getASN1Element(curl_asn1Element * elem, len = (len << 8) | (unsigned char) *beg++; } while(--b); } - if((unsigned long) (end - beg) < len) + if(len > (size_t)(end - beg)) return (const char *) NULL; /* Element data does not fit in source. */ elem->beg = beg; elem->end = beg + len; return elem->end; } -static const curl_OID * searchOID(const char * oid) +static const curl_OID * searchOID(const char *oid) { - const curl_OID * op; + const curl_OID *op; /* Search the null terminated OID or OID identifier in local table. Return the table entry pointer or NULL if not found. */ @@ -184,7 +187,7 @@ static const curl_OID * searchOID(const char * oid) return (const curl_OID *) NULL; } -static const char * bool2str(const char * beg, const char * end) +static const char *bool2str(const char *beg, const char *end) { /* Convert an ASN.1 Boolean value into its string representation. Return the dynamically allocated string, or NULL if source is not an @@ -195,22 +198,24 @@ static const char * bool2str(const char * beg, const char * end) return strdup(*beg? "TRUE": "FALSE"); } -static const char * octet2str(const char * beg, const char * end) +static const char *octet2str(const char *beg, const char *end) { size_t n = end - beg; - char * buf; + char *buf = NULL; /* Convert an ASN.1 octet string to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ - buf = malloc(3 * n + 1); - if(buf) - for(n = 0; beg < end; n += 3) - snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); + if(n <= (CURL_SIZE_T_MAX - 1) / 3) { + buf = malloc(3 * n + 1); + if(buf) + for(n = 0; beg < end; n += 3) + snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); + } return buf; } -static const char * bit2str(const char * beg, const char * end) +static const char *bit2str(const char *beg, const char *end) { /* Convert an ASN.1 bit string to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -220,7 +225,7 @@ static const char * bit2str(const char * beg, const char * end) return octet2str(beg, end); } -static const char * int2str(const char * beg, const char * end) +static const char *int2str(const char *beg, const char *end) { long val = 0; size_t n = end - beg; @@ -246,14 +251,14 @@ static const char * int2str(const char * beg, const char * end) } static ssize_t -utf8asn1str(char * * to, int type, const char * from, const char * end) +utf8asn1str(char **to, int type, const char *from, const char *end) { size_t inlength = end - from; int size = 1; size_t outlength; int charsize; unsigned int wc; - char * buf; + char *buf; /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the destination buffer dynamically. The allocation size will normally be too @@ -262,7 +267,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) string length. */ *to = (char *) NULL; - switch (type) { + switch(type) { case CURL_ASN1_BMP_STRING: size = 2; break; @@ -282,6 +287,8 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) if(inlength % size) return -1; /* Length inconsistent with character size. */ + if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4) + return -1; /* Too big. */ buf = malloc(4 * (inlength / size) + 1); if(!buf) return -1; /* Not enough memory. */ @@ -295,7 +302,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) else { for(outlength = 0; from < end;) { wc = 0; - switch (size) { + switch(size) { case 4: wc = (wc << 8) | *(const unsigned char *) from++; wc = (wc << 8) | *(const unsigned char *) from++; @@ -335,9 +342,9 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) return outlength; } -static const char * string2str(int type, const char * beg, const char * end) +static const char *string2str(int type, const char *beg, const char *end) { - char * buf; + char *buf; /* Convert an ASN.1 String into its UTF-8 string representation. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -347,7 +354,7 @@ static const char * string2str(int type, const char * beg, const char * end) return buf; } -static int encodeUint(char * buf, int n, unsigned int x) +static int encodeUint(char *buf, int n, unsigned int x) { int i = 0; unsigned int y = x / 10; @@ -367,7 +374,7 @@ static int encodeUint(char * buf, int n, unsigned int x) return i; } -static int encodeOID(char * buf, int n, const char * beg, const char * end) +static int encodeOID(char *buf, int n, const char *beg, const char *end) { int i = 0; unsigned int x; @@ -406,9 +413,9 @@ static int encodeOID(char * buf, int n, const char * beg, const char * end) return i; } -static const char * OID2str(const char * beg, const char * end, bool symbolic) +static const char *OID2str(const char *beg, const char *end, bool symbolic) { - char * buf = (char *) NULL; + char *buf = (char *) NULL; const curl_OID * op; int n; @@ -436,14 +443,14 @@ static const char * OID2str(const char * beg, const char * end, bool symbolic) return buf; } -static const char * GTime2str(const char * beg, const char * end) +static const char *GTime2str(const char *beg, const char *end) { - const char * tzp; - const char * fracp; + const char *tzp; + const char *fracp; char sec1, sec2; size_t fracl; size_t tzl; - const char * sep = ""; + const char *sep = ""; /* Convert an ASN.1 Generalized time to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -453,12 +460,13 @@ static const char * GTime2str(const char * beg, const char * end) /* Get seconds digits. */ sec1 = '0'; - switch (fracp - beg - 12) { + switch(fracp - beg - 12) { case 0: sec2 = '0'; break; case 2: sec1 = fracp[-2]; + /* FALLTHROUGH */ case 1: sec2 = fracp[-1]; break; @@ -499,11 +507,11 @@ static const char * GTime2str(const char * beg, const char * end) sep, tzl, tzp); } -static const char * UTime2str(const char * beg, const char * end) +static const char *UTime2str(const char *beg, const char *end) { - const char * tzp; + const char *tzp; size_t tzl; - const char * sec; + const char *sec; /* Convert an ASN.1 UTC time to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -512,7 +520,7 @@ static const char * UTime2str(const char * beg, const char * end) ; /* Get the seconds. */ sec = beg + 10; - switch (tzp - sec) { + switch(tzp - sec) { case 0: sec = "00"; case 2: @@ -538,7 +546,7 @@ static const char * UTime2str(const char * beg, const char * end) tzl, tzp); } -const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) +const char *Curl_ASN1tostr(curl_asn1Element *elem, int type) { /* Convert an ASN.1 element to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -549,7 +557,7 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) if(!type) type = elem->tag; /* Type not forced: use element tag as type. */ - switch (type) { + switch(type) { case CURL_ASN1_BOOLEAN: return bool2str(elem->beg, elem->end); case CURL_ASN1_INTEGER: @@ -581,17 +589,17 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) return (const char *) NULL; /* Unsupported. */ } -static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn) +static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) { curl_asn1Element rdn; curl_asn1Element atv; curl_asn1Element oid; curl_asn1Element value; size_t l = 0; - const char * p1; - const char * p2; - const char * p3; - const char * str; + const char *p1; + const char *p2; + const char *p3; + const char *str; /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'. Return the total string length, even if larger than `n'. */ @@ -647,9 +655,9 @@ static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn) return l; } -const char * Curl_DNtostr(curl_asn1Element * dn) +const char *Curl_DNtostr(curl_asn1Element *dn) { - char * buf = (char *) NULL; + char *buf = (char *) NULL; ssize_t n = encodeDN(buf, 0, dn); /* Convert an ASN.1 distinguished name into a printable string. @@ -669,12 +677,12 @@ const char * Curl_DNtostr(curl_asn1Element * dn) * X509 parser. */ -void Curl_parseX509(curl_X509certificate * cert, - const char * beg, const char * end) +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end) { curl_asn1Element elem; curl_asn1Element tbsCertificate; - const char * ccp; + const char *ccp; static const char defaultVersion = 0; /* v1. */ /* ASN.1 parse an X509 certificate into structure subfields. @@ -686,7 +694,8 @@ void Curl_parseX509(curl_X509certificate * cert, cert->certificate.end = end; /* Get the sequence content. */ - Curl_getASN1Element(&elem, beg, end); + if(!Curl_getASN1Element(&elem, beg, end)) + return -1; /* Invalid bounds/size. */ beg = elem.beg; end = elem.end; @@ -749,9 +758,10 @@ void Curl_parseX509(curl_X509certificate * cert, } if(elem.tag == 3) Curl_getASN1Element(&cert->extensions, elem.beg, elem.end); + return 0; } -static size_t copySubstring(char * to, const char * from) +static size_t copySubstring(char *to, const char *from) { size_t i; @@ -768,8 +778,8 @@ static size_t copySubstring(char * to, const char * from) return i; } -static const char * dumpAlgo(curl_asn1Element * param, - const char * beg, const char * end) +static const char *dumpAlgo(curl_asn1Element *param, + const char *beg, const char *end) { curl_asn1Element oid; @@ -784,10 +794,10 @@ static const char * dumpAlgo(curl_asn1Element * param, return OID2str(oid.beg, oid.end, TRUE); } -static void do_pubkey_field(struct Curl_easy * data, int certnum, - const char * label, curl_asn1Element * elem) +static void do_pubkey_field(struct Curl_easy *data, int certnum, + const char *label, curl_asn1Element *elem) { - const char * output; + const char *output; /* Generate a certificate information record for the public key. */ @@ -801,14 +811,14 @@ static void do_pubkey_field(struct Curl_easy * data, int certnum, } } -static void do_pubkey(struct Curl_easy * data, int certnum, - const char * algo, curl_asn1Element * param, - curl_asn1Element * pubkey) +static void do_pubkey(struct Curl_easy *data, int certnum, + const char *algo, curl_asn1Element *param, + curl_asn1Element *pubkey) { curl_asn1Element elem; curl_asn1Element pk; - const char * p; - const char * q; + const char *p; + const char *q; unsigned long len; unsigned int i; @@ -865,18 +875,18 @@ static void do_pubkey(struct Curl_easy * data, int certnum, #endif } -CURLcode Curl_extract_certinfo(struct connectdata * conn, +CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, - const char * beg, - const char * end) + const char *beg, + const char *end) { curl_X509certificate cert; - struct Curl_easy * data = conn->data; + struct Curl_easy *data = conn->data; curl_asn1Element param; - const char * ccp; - char * cp1; + const char *ccp; + char *cp1; size_t cl1; - char * cp2; + char *cp2; CURLcode result; unsigned long version; size_t i; @@ -889,7 +899,8 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, /* Prepare the certificate information for curl_easy_getinfo(). */ /* Extract the certificate ASN.1 elements. */ - Curl_parseX509(&cert, beg, end); + if(Curl_parseX509(&cert, beg, end)) + return CURLE_OUT_OF_MEMORY; /* Subject. */ ccp = Curl_DNtostr(&cert.subject); @@ -1029,12 +1040,12 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, #if defined(USE_GSKIT) -static const char * checkOID(const char * beg, const char * end, - const char * oid) +static const char *checkOID(const char *beg, const char *end, + const char *oid) { curl_asn1Element e; - const char * ccp; - const char * p; + const char *ccp; + const char *p; bool matched; /* Check if first ASN.1 element at `beg' is the given OID. @@ -1053,21 +1064,26 @@ static const char * checkOID(const char * beg, const char * end, return matched? ccp: (const char *) NULL; } -CURLcode Curl_verifyhost(struct connectdata * conn, - const char * beg, const char * end) +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end) { - struct Curl_easy * data = conn->data; + struct Curl_easy *data = conn->data; curl_X509certificate cert; curl_asn1Element dn; curl_asn1Element elem; curl_asn1Element ext; curl_asn1Element name; - const char * p; - const char * q; - char * dnsname; + const char *p; + const char *q; + char *dnsname; int matched = -1; size_t addrlen = (size_t) -1; ssize_t len; + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char * const dispname = SSL_IS_PROXY()? + conn->http_proxy.host.dispname: + conn->host.dispname; #ifdef ENABLE_IPV6 struct in6_addr addr; #else @@ -1077,20 +1093,19 @@ CURLcode Curl_verifyhost(struct connectdata * conn, /* Verify that connection server matches info in X509 certificate at `beg'..`end'. */ - if(!data->set.ssl.verifyhost) + if(!SSL_CONN_CONFIG(verifyhost)) return CURLE_OK; - if(!beg) + if(Curl_parseX509(&cert, beg, end)) return CURLE_PEER_FAILED_VERIFICATION; - Curl_parseX509(&cert, beg, end); /* Get the server IP address. */ #ifdef ENABLE_IPV6 - if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr)) + if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr)) addrlen = sizeof(struct in6_addr); else #endif - if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) + if(Curl_inet_pton(AF_INET, hostname, &addr)) addrlen = sizeof(struct in_addr); /* Process extensions. */ @@ -1108,12 +1123,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn, /* Check all GeneralNames. */ for(q = elem.beg; matched != 1 && q < elem.end;) { q = Curl_getASN1Element(&name, q, elem.end); - switch (name.tag) { + switch(name.tag) { case 2: /* DNS name. */ len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING, name.beg, name.end); if(len > 0 && (size_t)len == strlen(dnsname)) - matched = Curl_cert_hostcheck(dnsname, conn->host.name); + matched = Curl_cert_hostcheck(dnsname, hostname); else matched = 0; free(dnsname); @@ -1128,15 +1143,15 @@ CURLcode Curl_verifyhost(struct connectdata * conn, } } - switch (matched) { + switch(matched) { case 1: /* an alternative name matched the server hostname */ - infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname); + infof(data, "\t subjectAltName: %s matched\n", dispname); return CURLE_OK; case 0: /* an alternative name field existed, but didn't match and then we MUST fail */ - infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname); + infof(data, "\t subjectAltName does not match %s\n", dispname); return CURLE_PEER_FAILED_VERIFICATION; } @@ -1168,14 +1183,14 @@ CURLcode Curl_verifyhost(struct connectdata * conn, } if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ failf(data, "SSL: illegal cert name field"); - else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) { + else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) { infof(data, "\t common name: %s (matched)\n", dnsname); free(dnsname); return CURLE_OK; } else failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", dnsname, conn->host.dispname); + "target host name '%s'", dnsname, dispname); free(dnsname); } diff --git a/Utilities/cmcurl/lib/x509asn1.h b/Utilities/cmcurl/lib/x509asn1.h index 0f2b9304f..ce4029792 100644 --- a/Utilities/cmcurl/lib/x509asn1.h +++ b/Utilities/cmcurl/lib/x509asn1.h @@ -8,7 +8,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,6 +34,9 @@ * Constants. */ +/* Largest supported ASN.1 structure. */ +#define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */ + /* ASN.1 classes. */ #define CURL_ASN1_UNIVERSAL 0 #define CURL_ASN1_APPLICATION 1 @@ -117,16 +120,15 @@ typedef struct { * Prototypes. */ -const char * Curl_getASN1Element(curl_asn1Element * elem, - const char * beg, const char * end); -const char * Curl_ASN1tostr(curl_asn1Element * elem, int type); -const char * Curl_DNtostr(curl_asn1Element * dn); -void Curl_parseX509(curl_X509certificate * cert, - const char * beg, const char * end); -CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum, - const char * beg, const char * end); -CURLcode Curl_verifyhost(struct connectdata * conn, - const char * beg, const char * end); - +const char *Curl_getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end); +const char *Curl_ASN1tostr(curl_asn1Element *elem, int type); +const char *Curl_DNtostr(curl_asn1Element *dn); +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end); +CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, + const char *beg, const char *end); +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end); #endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */ #endif /* HEADER_CURL_X509ASN1_H */ diff --git a/Utilities/cmexpat/COPYING b/Utilities/cmexpat/COPYING index dcb450642..8d288f0f2 100644 --- a/Utilities/cmexpat/COPYING +++ b/Utilities/cmexpat/COPYING @@ -1,6 +1,5 @@ -Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd - and Clark Cooper -Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers. +Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper +Copyright (c) 2001-2017 Expat maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/Utilities/cmexpat/README b/Utilities/cmexpat/README index 9ec8d0c6a..cd11a226c 100644 --- a/Utilities/cmexpat/README +++ b/Utilities/cmexpat/README @@ -1,5 +1,5 @@ - Expat, Release 2.1.1 + Expat, Release 2.2.1 This is Expat, a C library for parsing XML, written by James Clark. Expat is a stream-oriented XML parser. This means that you register @@ -114,7 +114,7 @@ Note for Solaris users: The "ar" command is usually located in "/usr/ccs/bin", which is not in the default PATH. You will need to add this to your path for the "make" command, and probably also switch to GNU make (the "make" found in /usr/ccs/bin does not seem to work -properly -- appearantly it does not understand .PHONY directives). If +properly -- apparently it does not understand .PHONY directives). If you're using ksh or bash, use this command to build: PATH=/usr/ccs/bin:$PATH make diff --git a/Utilities/cmexpat/lib/expat.h b/Utilities/cmexpat/lib/expat.h index 5abcefdfa..28b0f954d 100644 --- a/Utilities/cmexpat/lib/expat.h +++ b/Utilities/cmexpat/lib/expat.h @@ -95,7 +95,9 @@ enum XML_Error { /* Added in 2.0. */ XML_ERROR_RESERVED_PREFIX_XML, XML_ERROR_RESERVED_PREFIX_XMLNS, - XML_ERROR_RESERVED_NAMESPACE_URI + XML_ERROR_RESERVED_NAMESPACE_URI, + /* Added in 2.2.1. */ + XML_ERROR_INVALID_ARGUMENT }; enum XML_Content_Type { @@ -342,7 +344,7 @@ XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler); /* OBSOLETE -- OBSOLETE -- OBSOLETE - This handler has been superceded by the EntityDeclHandler above. + This handler has been superseded by the EntityDeclHandler above. It is provided here for backward compatibility. This is called for a declaration of an unparsed (NDATA) entity. @@ -706,6 +708,7 @@ XML_UseParserAsHandlerArg(XML_Parser parser); be called, despite an external subset being parsed. Note: If XML_DTD is not defined when Expat is compiled, returns XML_ERROR_FEATURE_REQUIRES_XML_DTD. + Note: If parser == NULL, returns XML_ERROR_INVALID_ARGUMENT. */ XMLPARSEAPI(enum XML_Error) XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); @@ -729,15 +732,16 @@ XML_GetBase(XML_Parser parser); to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the - XML_StartElementHandler. + XML_StartElementHandler. Returns -1 if parser == NULL. */ XMLPARSEAPI(int) XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to - XML_StartElementHandler, or -1 if there is no ID attribute. Each - attribute/value pair counts as 2; thus this correspondds to an - index into the atts array passed to the XML_StartElementHandler. + XML_StartElementHandler, or -1 if there is no ID attribute or + parser == NULL. Each attribute/value pair counts as 2; thus this + correspondds to an index into the atts array passed to the + XML_StartElementHandler. */ XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); @@ -901,6 +905,7 @@ enum XML_ParamEntityParsing { entities is requested; otherwise it will return non-zero. Note: If XML_SetParamEntityParsing is called after XML_Parse or XML_ParseBuffer, then it has no effect and will always return 0. + Note: If parser == NULL, the function will do nothing and return 0. */ XMLPARSEAPI(int) XML_SetParamEntityParsing(XML_Parser parser, @@ -910,6 +915,7 @@ XML_SetParamEntityParsing(XML_Parser parser, Helps in preventing DoS attacks based on predicting hash function behavior. This must be called before parsing is started. Returns 1 if successful, 0 when called after parsing has started. + Note: If parser == NULL, the function will do nothing and return 0. */ XMLPARSEAPI(int) XML_SetHashSalt(XML_Parser parser, @@ -936,6 +942,10 @@ XML_GetErrorCode(XML_Parser parser); the location is the location of the character at which the error was detected; otherwise the location is the location of the last parse event, as described above. + + Note: XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber + return 0 to indicate an error. + Note: XML_GetCurrentByteIndex returns -1 to indicate an error. */ XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser); XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser); @@ -1034,13 +1044,11 @@ XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); -/* Expat follows the GNU/Linux convention of odd number minor version for - beta/development releases and even number minor version for stable - releases. Micro is bumped with each release, and set to 0 with each - change to major or minor version. +/* Expat follows the semantic versioning convention. + See http://semver.org. */ #define XML_MAJOR_VERSION 2 -#define XML_MINOR_VERSION 1 +#define XML_MINOR_VERSION 2 #define XML_MICRO_VERSION 1 #ifdef __cplusplus diff --git a/Utilities/cmexpat/lib/expat_external.h b/Utilities/cmexpat/lib/expat_external.h index 07a3c5c8e..d60eeccfb 100644 --- a/Utilities/cmexpat/lib/expat_external.h +++ b/Utilities/cmexpat/lib/expat_external.h @@ -95,7 +95,10 @@ extern "C" { #endif #ifdef XML_UNICODE_WCHAR_T -#define XML_UNICODE +# define XML_UNICODE +# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2) +# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc" +# endif #endif #ifdef XML_UNICODE /* Information is UTF-16 encoded. */ diff --git a/Utilities/cmexpat/lib/siphash.h b/Utilities/cmexpat/lib/siphash.h new file mode 100644 index 000000000..db1745808 --- /dev/null +++ b/Utilities/cmexpat/lib/siphash.h @@ -0,0 +1,354 @@ +/* ========================================================================== + * siphash.h - SipHash-2-4 in a single header file + * -------------------------------------------------------------------------- + * Derived by William Ahern from the reference implementation[1] published[2] + * by Jean-Philippe Aumasson and Daniel J. Berstein. Licensed in kind. + * by Jean-Philippe Aumasson and Daniel J. Berstein. + * Minimal changes by Sebastian Pipping on top, details below. + * Licensed under the CC0 Public Domain Dedication license. + * + * 1. https://www.131002.net/siphash/siphash24.c + * 2. https://www.131002.net/siphash/ + * -------------------------------------------------------------------------- + * HISTORY: + * + * 2017-06-10 (Sebastian Pipping) + * - Clarify license note in the header + * - Address C89 issues: + * - Stop using inline keyword (and let compiler decide) + * - Turn integer suffix ULL to UL + * - Replace _Bool by int + * - Turn macro siphash24 into a function + * - Address invalid conversion (void pointer) by explicit cast + * - Always expose sip24_valid (for self-tests) + * + * 2012-11-04 - Born. (William Ahern) + * -------------------------------------------------------------------------- + * USAGE: + * + * SipHash-2-4 takes as input two 64-bit words as the key, some number of + * message bytes, and outputs a 64-bit word as the message digest. This + * implementation employs two data structures: a struct sipkey for + * representing the key, and a struct siphash for representing the hash + * state. + * + * For converting a 16-byte unsigned char array to a key, use either the + * macro sip_keyof or the routine sip_tokey. The former instantiates a + * compound literal key, while the latter requires a key object as a + * parameter. + * + * unsigned char secret[16]; + * arc4random_buf(secret, sizeof secret); + * struct sipkey *key = sip_keyof(secret); + * + * For hashing a message, use either the convenience macro siphash24 or the + * routines sip24_init, sip24_update, and sip24_final. + * + * struct siphash state; + * void *msg; + * size_t len; + * uint64_t hash; + * + * sip24_init(&state, key); + * sip24_update(&state, msg, len); + * hash = sip24_final(&state); + * + * or + * + * hash = siphash24(msg, len, key); + * + * To convert the 64-bit hash value to a canonical 8-byte little-endian + * binary representation, use either the macro sip_binof or the routine + * sip_tobin. The former instantiates and returns a compound literal array, + * while the latter requires an array object as a parameter. + * -------------------------------------------------------------------------- + * NOTES: + * + * o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers + * lacking compound literal support. Instead, you must use the lower-level + * interfaces which take as parameters the temporary state objects. + * + * o Uppercase macros may evaluate parameters more than once. Lowercase + * macros should not exhibit any such side effects. + * ========================================================================== + */ +#ifndef SIPHASH_H +#define SIPHASH_H + +#include /* size_t */ + +#include + +#ifndef KWIML_INT_HAVE_UINT64_T +# define uint64_t KWIML_INT_uint64_t +#endif +#ifndef KWIML_INT_HAVE_UINT32_T +# define uint32_t KWIML_INT_uint32_t +#endif +#ifndef KWIML_INT_HAVE_UINT8_T +# define uint8_t KWIML_INT_uint8_t +#endif + +#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b)))) + +#define SIP_U32TO8_LE(p, v) \ + (p)[0] = (uint8_t)((v) >> 0); (p)[1] = (uint8_t)((v) >> 8); \ + (p)[2] = (uint8_t)((v) >> 16); (p)[3] = (uint8_t)((v) >> 24); + +#define SIP_U64TO8_LE(p, v) \ + SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \ + SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); + +#define SIP_U8TO64_LE(p) \ + (((uint64_t)((p)[0]) << 0) | \ + ((uint64_t)((p)[1]) << 8) | \ + ((uint64_t)((p)[2]) << 16) | \ + ((uint64_t)((p)[3]) << 24) | \ + ((uint64_t)((p)[4]) << 32) | \ + ((uint64_t)((p)[5]) << 40) | \ + ((uint64_t)((p)[6]) << 48) | \ + ((uint64_t)((p)[7]) << 56)) + + +#define SIPHASH_INITIALIZER { 0, 0, 0, 0, { 0 }, 0, 0 } + +struct siphash { + uint64_t v0, v1, v2, v3; + + unsigned char buf[8], *p; + uint64_t c; +}; /* struct siphash */ + + +#define SIP_KEYLEN 16 + +struct sipkey { + uint64_t k[2]; +}; /* struct sipkey */ + +#define sip_keyof(k) sip_tokey(&(struct sipkey){ { 0 } }, (k)) + +static struct sipkey *sip_tokey(struct sipkey *key, const void *src) { + key->k[0] = SIP_U8TO64_LE((const unsigned char *)src); + key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8); + return key; +} /* sip_tokey() */ + + +#define sip_binof(v) sip_tobin((unsigned char[8]){ 0 }, (v)) + +static void *sip_tobin(void *dst, uint64_t u64) { + SIP_U64TO8_LE((unsigned char *)dst, u64); + return dst; +} /* sip_tobin() */ + + +static void sip_round(struct siphash *H, const int rounds) { + int i; + + for (i = 0; i < rounds; i++) { + H->v0 += H->v1; + H->v1 = SIP_ROTL(H->v1, 13); + H->v1 ^= H->v0; + H->v0 = SIP_ROTL(H->v0, 32); + + H->v2 += H->v3; + H->v3 = SIP_ROTL(H->v3, 16); + H->v3 ^= H->v2; + + H->v0 += H->v3; + H->v3 = SIP_ROTL(H->v3, 21); + H->v3 ^= H->v0; + + H->v2 += H->v1; + H->v1 = SIP_ROTL(H->v1, 17); + H->v1 ^= H->v2; + H->v2 = SIP_ROTL(H->v2, 32); + } +} /* sip_round() */ + + +static struct siphash *sip24_init(struct siphash *H, const struct sipkey *key) { + H->v0 = 0x736f6d6570736575UL ^ key->k[0]; + H->v1 = 0x646f72616e646f6dUL ^ key->k[1]; + H->v2 = 0x6c7967656e657261UL ^ key->k[0]; + H->v3 = 0x7465646279746573UL ^ key->k[1]; + + H->p = H->buf; + H->c = 0; + + return H; +} /* sip24_init() */ + + +#define sip_endof(a) (&(a)[sizeof (a) / sizeof *(a)]) + +static struct siphash *sip24_update(struct siphash *H, const void *src, size_t len) { + const unsigned char *p = (const unsigned char *)src, *pe = p + len; + uint64_t m; + + do { + while (p < pe && H->p < sip_endof(H->buf)) + *H->p++ = *p++; + + if (H->p < sip_endof(H->buf)) + break; + + m = SIP_U8TO64_LE(H->buf); + H->v3 ^= m; + sip_round(H, 2); + H->v0 ^= m; + + H->p = H->buf; + H->c += 8; + } while (p < pe); + + return H; +} /* sip24_update() */ + + +static uint64_t sip24_final(struct siphash *H) { + char left = H->p - H->buf; + uint64_t b = (H->c + left) << 56; + + switch (left) { + case 7: b |= (uint64_t)H->buf[6] << 48; + case 6: b |= (uint64_t)H->buf[5] << 40; + case 5: b |= (uint64_t)H->buf[4] << 32; + case 4: b |= (uint64_t)H->buf[3] << 24; + case 3: b |= (uint64_t)H->buf[2] << 16; + case 2: b |= (uint64_t)H->buf[1] << 8; + case 1: b |= (uint64_t)H->buf[0] << 0; + case 0: break; + } + + H->v3 ^= b; + sip_round(H, 2); + H->v0 ^= b; + H->v2 ^= 0xff; + sip_round(H, 4); + + return H->v0 ^ H->v1 ^ H->v2 ^ H->v3; +} /* sip24_final() */ + + +static uint64_t siphash24(const void *src, size_t len, const struct sipkey *key) { + struct siphash state = SIPHASH_INITIALIZER; + return sip24_final(sip24_update(sip24_init(&state, key), src, len)); +} /* siphash24() */ + + +/* + * SipHash-2-4 output with + * k = 00 01 02 ... + * and + * in = (empty string) + * in = 00 (1 byte) + * in = 00 01 (2 bytes) + * in = 00 01 02 (3 bytes) + * ... + * in = 00 01 02 ... 3e (63 bytes) + */ +static int sip24_valid(void) { + static const unsigned char vectors[64][8] = { + { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, }, + { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, }, + { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, }, + { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, }, + { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, }, + { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, }, + { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, }, + { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, }, + { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, }, + { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, }, + { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, }, + { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, }, + { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, }, + { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, }, + { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, }, + { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, }, + { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, }, + { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, }, + { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, }, + { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, }, + { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, }, + { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, }, + { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, }, + { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, }, + { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, }, + { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, }, + { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, }, + { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, }, + { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, }, + { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, }, + { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, }, + { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, }, + { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, }, + { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, }, + { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, }, + { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, }, + { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, }, + { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, }, + { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, }, + { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, }, + { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, }, + { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, }, + { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, }, + { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, }, + { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, }, + { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, }, + { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, }, + { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, }, + { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, }, + { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, }, + { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, }, + { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, }, + { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, }, + { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, }, + { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, }, + { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, }, + { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, }, + { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, }, + { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, }, + { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, }, + { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, }, + { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, }, + { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, }, + { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, } + }; + unsigned char in[64]; + struct sipkey k; + size_t i; + + sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"); + + for (i = 0; i < sizeof in; ++i) { + in[i] = i; + + if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i])) + return 0; + } + + return 1; +} /* sip24_valid() */ + + +#if SIPHASH_MAIN + +#include + +int main(void) { + int ok = sip24_valid(); + + if (ok) + puts("OK"); + else + puts("FAIL"); + + return !ok; +} /* main() */ + +#endif /* SIPHASH_MAIN */ + + +#endif /* SIPHASH_H */ diff --git a/Utilities/cmexpat/lib/winconfig.h b/Utilities/cmexpat/lib/winconfig.h index d7dad38f7..c9dbfea85 100644 --- a/Utilities/cmexpat/lib/winconfig.h +++ b/Utilities/cmexpat/lib/winconfig.h @@ -17,7 +17,24 @@ #include #include -#include "expat_config.h" + +#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */ +# include +#else /* !defined(HAVE_EXPAT_CONFIG_H) */ + + +#define XML_NS 1 +#define XML_DTD 1 +#define XML_CONTEXT_BYTES 1024 + +/* we will assume all Windows platforms are little endian */ +#define BYTEORDER 1234 + +/* Windows has memmove() available. */ +#define HAVE_MEMMOVE + + +#endif /* !defined(HAVE_EXPAT_CONFIG_H) */ #if defined(_MSC_VER) # pragma warning(push,1) diff --git a/Utilities/cmexpat/lib/xmlparse.c b/Utilities/cmexpat/lib/xmlparse.c index b56b66afc..76f078e25 100644 --- a/Utilities/cmexpat/lib/xmlparse.c +++ b/Utilities/cmexpat/lib/xmlparse.c @@ -1,13 +1,19 @@ /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd See the file COPYING for copying permission. + + 77fea421d361dca90041d0040ecf1dca651167fadf2af79e990e35168d70d933 (2.2.1+) */ +#define _GNU_SOURCE /* syscall prototype */ + #include #include /* memset(), memcpy() */ #include #include /* UINT_MAX */ +#include /* fprintf */ +#include /* getenv */ -#ifdef COMPILING_FOR_WINDOWS +#ifdef _WIN32 #define getpid GetCurrentProcessId #else #include /* gettimeofday() */ @@ -17,20 +23,15 @@ #define XML_BUILDING_EXPAT 1 -#ifdef COMPILING_FOR_WINDOWS +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #elif defined(HAVE_EXPAT_CONFIG_H) #include -#endif /* ndef COMPILING_FOR_WINDOWS */ +#endif /* ndef _WIN32 */ #include "ascii.h" #include "expat.h" +#include "siphash.h" #ifdef XML_UNICODE #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX @@ -109,17 +110,11 @@ typedef struct { const XML_Memory_Handling_Suite *mem; } HASH_TABLE; -/* Basic character hash algorithm, taken from Python's string hash: - h = h * 1000003 ^ character, the constant being a prime number. +static size_t +keylen(KEY s); -*/ -#ifdef XML_UNICODE -#define CHAR_HASH(h, c) \ - (((h) * 0xF4243) ^ (unsigned short)(c)) -#else -#define CHAR_HASH(h, c) \ - (((h) * 0xF4243) ^ (unsigned char)(c)) -#endif +static void +copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key); /* For probing (after a collision) we need a step size relative prime to the hash table size, which is a power of 2. We use double-hashing, @@ -355,6 +350,8 @@ doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr, XML_Bool haveMore); #endif /* XML_DTD */ +static void +freeBindings(XML_Parser parser, BINDING *bindings); static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, TAG_NAME *tagNamePtr, BINDING **bindingsPtr); @@ -697,10 +694,84 @@ static const XML_Char implicitContext[] = { ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0' }; + +#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) +# include + +# if defined(HAVE_GETRANDOM) +# include /* getrandom */ +# else +# include /* syscall */ +# include /* SYS_getrandom */ +# endif + +/* Obtain entropy on Linux 3.17+ */ +static int +writeRandomBytes_getrandom(void * target, size_t count) { + int success = 0; /* full count bytes written? */ + size_t bytesWrittenTotal = 0; + const unsigned int getrandomFlags = 0; + + do { + void * const currentTarget = (void*)((char*)target + bytesWrittenTotal); + const size_t bytesToWrite = count - bytesWrittenTotal; + + const int bytesWrittenMore = +#if defined(HAVE_GETRANDOM) + getrandom(currentTarget, bytesToWrite, getrandomFlags); +#else + syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags); +#endif + + if (bytesWrittenMore > 0) { + bytesWrittenTotal += bytesWrittenMore; + if (bytesWrittenTotal >= count) + success = 1; + } + } while (! success && (errno == EINTR || errno == EAGAIN)); + + return success; +} + +#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ + + +#ifdef _WIN32 + +typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG); + +/* Obtain entropy on Windows XP / Windows Server 2003 and later. + * Hint on RtlGenRandom and the following article from libsodioum. + * + * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI + * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/ + */ +static int +writeRandomBytes_RtlGenRandom(void * target, size_t count) { + int success = 0; /* full count bytes written? */ + const HMODULE advapi32 = LoadLibrary("ADVAPI32.DLL"); + + if (advapi32) { + const RTLGENRANDOM_FUNC RtlGenRandom + = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036"); + if (RtlGenRandom) { + if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) { + success = 1; + } + } + FreeLibrary(advapi32); + } + + return success; +} + +#endif /* _WIN32 */ + + static unsigned long gather_time_entropy(void) { -#ifdef COMPILING_FOR_WINDOWS +#ifdef _WIN32 FILETIME ft; GetSystemTimeAsFileTime(&ft); /* never fails */ return ft.dwHighDateTime ^ ft.dwLowDateTime; @@ -716,20 +787,62 @@ gather_time_entropy(void) #endif } +#if defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_LIBBSD) +# include +#endif + +static unsigned long +ENTROPY_DEBUG(const char * label, unsigned long entropy) { + const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG"); + if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) { + fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", + label, + (int)sizeof(entropy) * 2, entropy, + (unsigned long)sizeof(entropy)); + } + return entropy; +} + static unsigned long generate_hash_secret_salt(XML_Parser parser) { - /* Process ID is 0 bits entropy if attacker has local access - * XML_Parser address is few bits of entropy if attacker has local access */ - const unsigned long entropy = - gather_time_entropy() ^ getpid() ^ (unsigned long)parser; + unsigned long entropy; + (void)parser; +#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__) + (void)gather_time_entropy; + arc4random_buf(&entropy, sizeof(entropy)); + return ENTROPY_DEBUG("arc4random_buf", entropy); +#else + /* Try high quality providers first .. */ +#ifdef _WIN32 + if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) { + return ENTROPY_DEBUG("RtlGenRandom", entropy); + } +#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) + if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) { + return ENTROPY_DEBUG("getrandom", entropy); + } +#endif + /* .. and self-made low quality for backup: */ + + /* Process ID is 0 bits entropy if attacker has local access */ + entropy = gather_time_entropy() ^ getpid(); /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */ if (sizeof(unsigned long) == 4) { - return entropy * 2147483647; + return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647); } else { - return entropy * 2305843009213693951; + return ENTROPY_DEBUG("fallback(8)", + entropy * (unsigned long)2305843009213693951); } +#endif +} + +static unsigned long +get_hash_secret_salt(XML_Parser parser) { + if (parser->m_parentParser != NULL) + return get_hash_secret_salt(parser->m_parentParser); + return parser->m_hash_secret_salt; } static XML_Bool /* only valid for root parser */ @@ -960,6 +1073,10 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { TAG *tStk; OPEN_INTERNAL_ENTITY *openEntityList; + + if (parser == NULL) + return XML_FALSE; + if (parentParser) return XML_FALSE; /* move tagStack to freeTagList */ @@ -994,6 +1111,8 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) enum XML_Status XMLCALL XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { + if (parser == NULL) + return XML_STATUS_ERROR; /* Block after XML_Parse()/XML_ParseBuffer() has been called. XXX There's no way for the caller to determine which of the XXX possible error cases caused the XML_STATUS_ERROR return. @@ -1017,52 +1136,88 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, { XML_Parser parser = oldParser; DTD *newDtd = NULL; - DTD *oldDtd = _dtd; - XML_StartElementHandler oldStartElementHandler = startElementHandler; - XML_EndElementHandler oldEndElementHandler = endElementHandler; - XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; - XML_ProcessingInstructionHandler oldProcessingInstructionHandler - = processingInstructionHandler; - XML_CommentHandler oldCommentHandler = commentHandler; - XML_StartCdataSectionHandler oldStartCdataSectionHandler - = startCdataSectionHandler; - XML_EndCdataSectionHandler oldEndCdataSectionHandler - = endCdataSectionHandler; - XML_DefaultHandler oldDefaultHandler = defaultHandler; - XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler - = unparsedEntityDeclHandler; - XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; - XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler - = startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler - = endNamespaceDeclHandler; - XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; - XML_ExternalEntityRefHandler oldExternalEntityRefHandler - = externalEntityRefHandler; - XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; - XML_UnknownEncodingHandler oldUnknownEncodingHandler - = unknownEncodingHandler; - XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; - XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; - XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; - XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; - ELEMENT_TYPE * oldDeclElementType = declElementType; - - void *oldUserData = userData; - void *oldHandlerArg = handlerArg; - XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; - XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; + DTD *oldDtd; + XML_StartElementHandler oldStartElementHandler; + XML_EndElementHandler oldEndElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler; + XML_CommentHandler oldCommentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler; + XML_SkippedEntityHandler oldSkippedEntityHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler; + XML_ElementDeclHandler oldElementDeclHandler; + XML_AttlistDeclHandler oldAttlistDeclHandler; + XML_EntityDeclHandler oldEntityDeclHandler; + XML_XmlDeclHandler oldXmlDeclHandler; + ELEMENT_TYPE * oldDeclElementType; + + void *oldUserData; + void *oldHandlerArg; + XML_Bool oldDefaultExpandInternalEntities; + XML_Parser oldExternalEntityRefHandlerArg; #ifdef XML_DTD - enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; - int oldInEntityValue = prologState.inEntityValue; + enum XML_ParamEntityParsing oldParamEntityParsing; + int oldInEntityValue; #endif - XML_Bool oldns_triplets = ns_triplets; + XML_Bool oldns_triplets; /* Note that the new parser shares the same hash secret as the old parser, so that dtdCopy and copyEntityTable can lookup values from hash tables associated with either parser without us having to worry which hash secrets each table has. */ - unsigned long oldhash_secret_salt = hash_secret_salt; + unsigned long oldhash_secret_salt; + + /* Validate the oldParser parameter before we pull everything out of it */ + if (oldParser == NULL) + return NULL; + + /* Stash the original parser contents on the stack */ + oldDtd = _dtd; + oldStartElementHandler = startElementHandler; + oldEndElementHandler = endElementHandler; + oldCharacterDataHandler = characterDataHandler; + oldProcessingInstructionHandler = processingInstructionHandler; + oldCommentHandler = commentHandler; + oldStartCdataSectionHandler = startCdataSectionHandler; + oldEndCdataSectionHandler = endCdataSectionHandler; + oldDefaultHandler = defaultHandler; + oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler; + oldNotationDeclHandler = notationDeclHandler; + oldStartNamespaceDeclHandler = startNamespaceDeclHandler; + oldEndNamespaceDeclHandler = endNamespaceDeclHandler; + oldNotStandaloneHandler = notStandaloneHandler; + oldExternalEntityRefHandler = externalEntityRefHandler; + oldSkippedEntityHandler = skippedEntityHandler; + oldUnknownEncodingHandler = unknownEncodingHandler; + oldElementDeclHandler = elementDeclHandler; + oldAttlistDeclHandler = attlistDeclHandler; + oldEntityDeclHandler = entityDeclHandler; + oldXmlDeclHandler = xmlDeclHandler; + oldDeclElementType = declElementType; + + oldUserData = userData; + oldHandlerArg = handlerArg; + oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; +#ifdef XML_DTD + oldParamEntityParsing = paramEntityParsing; + oldInEntityValue = prologState.inEntityValue; +#endif + oldns_triplets = ns_triplets; + /* Note that the new parser shares the same hash secret as the old + parser, so that dtdCopy and copyEntityTable can lookup values + from hash tables associated with either parser without us having + to worry which hash secrets each table has. + */ + oldhash_secret_salt = hash_secret_salt; #ifdef XML_DTD if (!context) @@ -1228,12 +1383,15 @@ XML_ParserFree(XML_Parser parser) void XMLCALL XML_UseParserAsHandlerArg(XML_Parser parser) { - handlerArg = parser; + if (parser != NULL) + handlerArg = parser; } enum XML_Error XMLCALL XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { + if (parser == NULL) + return XML_ERROR_INVALID_ARGUMENT; #ifdef XML_DTD /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) @@ -1248,6 +1406,8 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) void XMLCALL XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { + if (parser == NULL) + return; /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) return; @@ -1257,6 +1417,8 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) void XMLCALL XML_SetUserData(XML_Parser parser, void *p) { + if (parser == NULL) + return; if (handlerArg == userData) handlerArg = userData = p; else @@ -1266,6 +1428,8 @@ XML_SetUserData(XML_Parser parser, void *p) enum XML_Status XMLCALL XML_SetBase(XML_Parser parser, const XML_Char *p) { + if (parser == NULL) + return XML_STATUS_ERROR; if (p) { p = poolCopyString(&_dtd->pool, p); if (!p) @@ -1280,18 +1444,24 @@ XML_SetBase(XML_Parser parser, const XML_Char *p) const XML_Char * XMLCALL XML_GetBase(XML_Parser parser) { + if (parser == NULL) + return NULL; return curBase; } int XMLCALL XML_GetSpecifiedAttributeCount(XML_Parser parser) { + if (parser == NULL) + return -1; return nSpecifiedAtts; } int XMLCALL XML_GetIdAttributeIndex(XML_Parser parser) { + if (parser == NULL) + return -1; return idAttIndex; } @@ -1299,6 +1469,8 @@ XML_GetIdAttributeIndex(XML_Parser parser) const XML_AttrInfo * XMLCALL XML_GetAttributeInfo(XML_Parser parser) { + if (parser == NULL) + return NULL; return attInfo; } #endif @@ -1308,6 +1480,8 @@ XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) { + if (parser == NULL) + return; startElementHandler = start; endElementHandler = end; } @@ -1315,34 +1489,39 @@ XML_SetElementHandler(XML_Parser parser, void XMLCALL XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) { - startElementHandler = start; + if (parser != NULL) + startElementHandler = start; } void XMLCALL XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) { - endElementHandler = end; + if (parser != NULL) + endElementHandler = end; } void XMLCALL XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler) { - characterDataHandler = handler; + if (parser != NULL) + characterDataHandler = handler; } void XMLCALL XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler) { - processingInstructionHandler = handler; + if (parser != NULL) + processingInstructionHandler = handler; } void XMLCALL XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) { - commentHandler = handler; + if (parser != NULL) + commentHandler = handler; } void XMLCALL @@ -1350,6 +1529,8 @@ XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end) { + if (parser == NULL) + return; startCdataSectionHandler = start; endCdataSectionHandler = end; } @@ -1357,19 +1538,23 @@ XML_SetCdataSectionHandler(XML_Parser parser, void XMLCALL XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start) { - startCdataSectionHandler = start; + if (parser != NULL) + startCdataSectionHandler = start; } void XMLCALL XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end) { - endCdataSectionHandler = end; + if (parser != NULL) + endCdataSectionHandler = end; } void XMLCALL XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) { + if (parser == NULL) + return; defaultHandler = handler; defaultExpandInternalEntities = XML_FALSE; } @@ -1378,6 +1563,8 @@ void XMLCALL XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) { + if (parser == NULL) + return; defaultHandler = handler; defaultExpandInternalEntities = XML_TRUE; } @@ -1387,6 +1574,8 @@ XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end) { + if (parser == NULL) + return; startDoctypeDeclHandler = start; endDoctypeDeclHandler = end; } @@ -1394,27 +1583,31 @@ XML_SetDoctypeDeclHandler(XML_Parser parser, void XMLCALL XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start) { - startDoctypeDeclHandler = start; + if (parser != NULL) + startDoctypeDeclHandler = start; } void XMLCALL XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) { - endDoctypeDeclHandler = end; + if (parser != NULL) + endDoctypeDeclHandler = end; } void XMLCALL XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler) { - unparsedEntityDeclHandler = handler; + if (parser != NULL) + unparsedEntityDeclHandler = handler; } void XMLCALL XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) { - notationDeclHandler = handler; + if (parser != NULL) + notationDeclHandler = handler; } void XMLCALL @@ -1422,6 +1615,8 @@ XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end) { + if (parser == NULL) + return; startNamespaceDeclHandler = start; endNamespaceDeclHandler = end; } @@ -1429,32 +1624,38 @@ XML_SetNamespaceDeclHandler(XML_Parser parser, void XMLCALL XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start) { - startNamespaceDeclHandler = start; + if (parser != NULL) + startNamespaceDeclHandler = start; } void XMLCALL XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end) { - endNamespaceDeclHandler = end; + if (parser != NULL) + endNamespaceDeclHandler = end; } void XMLCALL XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler) { - notStandaloneHandler = handler; + if (parser != NULL) + notStandaloneHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler) { - externalEntityRefHandler = handler; + if (parser != NULL) + externalEntityRefHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) { + if (parser == NULL) + return; if (arg) externalEntityRefHandlerArg = (XML_Parser)arg; else @@ -1465,7 +1666,8 @@ void XMLCALL XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler) { - skippedEntityHandler = handler; + if (parser != NULL) + skippedEntityHandler = handler; } void XMLCALL @@ -1473,6 +1675,8 @@ XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *data) { + if (parser == NULL) + return; unknownEncodingHandler = handler; unknownEncodingHandlerData = data; } @@ -1481,33 +1685,39 @@ void XMLCALL XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) { - elementDeclHandler = eldecl; + if (parser != NULL) + elementDeclHandler = eldecl; } void XMLCALL XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) { - attlistDeclHandler = attdecl; + if (parser != NULL) + attlistDeclHandler = attdecl; } void XMLCALL XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) { - entityDeclHandler = handler; + if (parser != NULL) + entityDeclHandler = handler; } void XMLCALL XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) { - xmlDeclHandler = handler; + if (parser != NULL) + xmlDeclHandler = handler; } int XMLCALL XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing peParsing) { + if (parser == NULL) + return 0; /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) return 0; @@ -1523,6 +1733,10 @@ int XMLCALL XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) { + if (parser == NULL) + return 0; + if (parser->m_parentParser) + return XML_SetHashSalt(parser->m_parentParser, hash_salt); /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) return 0; @@ -1533,6 +1747,10 @@ XML_SetHashSalt(XML_Parser parser, enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { + if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) { + errorCode = XML_ERROR_INVALID_ARGUMENT; + return XML_STATUS_ERROR; + } switch (ps_parsing) { case XML_SUSPENDED: errorCode = XML_ERROR_SUSPENDED; @@ -1585,6 +1803,13 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) const char *end; int nLeftOver; enum XML_Status result; + /* Detect overflow (a+b > MAX <==> b > MAX-a) */ + if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = NULL; + processor = errorProcessor; + return XML_STATUS_ERROR; + } parseEndByteIndex += len; positionPtr = s; ps_finalBuffer = (XML_Bool)isFinal; @@ -1617,11 +1842,14 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) nLeftOver = s + len - end; if (nLeftOver) { if (buffer == NULL || nLeftOver > bufferLim - buffer) { - /* FIXME avoid integer overflow */ - char *temp; - temp = (buffer == NULL - ? (char *)MALLOC(len * 2) - : (char *)REALLOC(buffer, len * 2)); + /* avoid _signed_ integer overflow */ + char *temp = NULL; + const int bytesToAllocate = (int)((unsigned)len * 2U); + if (bytesToAllocate > 0) { + temp = (buffer == NULL + ? (char *)MALLOC(bytesToAllocate) + : (char *)REALLOC(buffer, bytesToAllocate)); + } if (temp == NULL) { errorCode = XML_ERROR_NO_MEMORY; eventPtr = eventEndPtr = NULL; @@ -1629,7 +1857,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) return XML_STATUS_ERROR; } buffer = temp; - bufferLim = buffer + len * 2; + bufferLim = buffer + bytesToAllocate; } memcpy(buffer, end, nLeftOver); } @@ -1659,6 +1887,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) const char *start; enum XML_Status result = XML_STATUS_OK; + if (parser == NULL) + return XML_STATUS_ERROR; switch (ps_parsing) { case XML_SUSPENDED: errorCode = XML_ERROR_SUSPENDED; @@ -1712,6 +1942,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) void * XMLCALL XML_GetBuffer(XML_Parser parser, int len) { + if (parser == NULL) + return NULL; if (len < 0) { errorCode = XML_ERROR_NO_MEMORY; return NULL; @@ -1808,6 +2040,8 @@ XML_GetBuffer(XML_Parser parser, int len) enum XML_Status XMLCALL XML_StopParser(XML_Parser parser, XML_Bool resumable) { + if (parser == NULL) + return XML_STATUS_ERROR; switch (ps_parsing) { case XML_SUSPENDED: if (resumable) { @@ -1840,6 +2074,8 @@ XML_ResumeParser(XML_Parser parser) { enum XML_Status result = XML_STATUS_OK; + if (parser == NULL) + return XML_STATUS_ERROR; if (ps_parsing != XML_SUSPENDED) { errorCode = XML_ERROR_NOT_SUSPENDED; return XML_STATUS_ERROR; @@ -1876,6 +2112,8 @@ XML_ResumeParser(XML_Parser parser) void XMLCALL XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) { + if (parser == NULL) + return; assert(status != NULL); *status = parser->m_parsingStatus; } @@ -1883,20 +2121,26 @@ XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) enum XML_Error XMLCALL XML_GetErrorCode(XML_Parser parser) { + if (parser == NULL) + return XML_ERROR_INVALID_ARGUMENT; return errorCode; } XML_Index XMLCALL XML_GetCurrentByteIndex(XML_Parser parser) { + if (parser == NULL) + return -1; if (eventPtr) - return parseEndByteIndex - (parseEndPtr - eventPtr); + return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr)); return -1; } int XMLCALL XML_GetCurrentByteCount(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventEndPtr && eventPtr) return (int)(eventEndPtr - eventPtr); return 0; @@ -1906,11 +2150,19 @@ const char * XMLCALL XML_GetInputContext(XML_Parser parser, int *offset, int *size) { #ifdef XML_CONTEXT_BYTES + if (parser == NULL) + return NULL; if (eventPtr && buffer) { - *offset = (int)(eventPtr - buffer); - *size = (int)(bufferEnd - buffer); + if (offset != NULL) + *offset = (int)(eventPtr - buffer); + if (size != NULL) + *size = (int)(bufferEnd - buffer); return buffer; } +#else + (void)parser; + (void)offset; + (void)size; #endif /* defined XML_CONTEXT_BYTES */ return (char *) 0; } @@ -1918,6 +2170,8 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size) XML_Size XMLCALL XML_GetCurrentLineNumber(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventPtr && eventPtr >= positionPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; @@ -1928,6 +2182,8 @@ XML_GetCurrentLineNumber(XML_Parser parser) XML_Size XMLCALL XML_GetCurrentColumnNumber(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventPtr && eventPtr >= positionPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; @@ -1938,30 +2194,38 @@ XML_GetCurrentColumnNumber(XML_Parser parser) void XMLCALL XML_FreeContentModel(XML_Parser parser, XML_Content *model) { - FREE(model); + if (parser != NULL) + FREE(model); } void * XMLCALL XML_MemMalloc(XML_Parser parser, size_t size) { + if (parser == NULL) + return NULL; return MALLOC(size); } void * XMLCALL XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { + if (parser == NULL) + return NULL; return REALLOC(ptr, size); } void XMLCALL XML_MemFree(XML_Parser parser, void *ptr) { - FREE(ptr); + if (parser != NULL) + FREE(ptr); } void XMLCALL XML_DefaultCurrent(XML_Parser parser) { + if (parser == NULL) + return; if (defaultHandler) { if (openInternalEntities) reportDefault(parser, @@ -2468,7 +2732,7 @@ doContent(XML_Parser parser, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); convLen = (int)(toPtr - (XML_Char *)tag->buf); - if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { + if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { tag->name.strLen = convLen; break; } @@ -2511,8 +2775,10 @@ doContent(XML_Parser parser, return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); result = storeAtts(parser, enc, s, &name, &bindings); - if (result) + if (result != XML_ERROR_NONE) { + freeBindings(parser, bindings); return result; + } poolFinish(&tempPool); if (startElementHandler) { startElementHandler(handlerArg, name.str, (const XML_Char **)atts); @@ -2527,15 +2793,7 @@ doContent(XML_Parser parser, if (noElmHandlers && defaultHandler) reportDefault(parser, enc, s, next); poolClear(&tempPool); - while (bindings) { - BINDING *b = bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } + freeBindings(parser, bindings); } if (tagLevel == 0) return epilogProcessor(parser, next, end, nextPtr); @@ -2733,6 +2991,29 @@ doContent(XML_Parser parser, /* not reached */ } +/* This function does not call free() on the allocated memory, merely + * moving it to the parser's freeBindingList where it can be freed or + * reused as appropriate. + */ +static void +freeBindings(XML_Parser parser, BINDING *bindings) +{ + while (bindings) { + BINDING *b = bindings; + + /* startNamespaceDeclHandler will have been called for this + * binding in addBindings(), so call the end handler now. + */ + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } +} + /* Precondition: all arguments must be non-NULL; Purpose: - normalize attributes @@ -2957,7 +3238,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, if (s[-1] == 2) { /* prefixed */ ATTRIBUTE_ID *id; const BINDING *b; - unsigned long uriHash = hash_secret_salt; + unsigned long uriHash; + struct siphash sip_state; + struct sipkey sip_key; + + copy_salt_to_sipkey(parser, &sip_key); + sip24_init(&sip_state, &sip_key); + ((XML_Char *)s)[-1] = 0; /* clear flag */ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); if (!id || !id->prefix) @@ -2966,22 +3253,26 @@ storeAtts(XML_Parser parser, const ENCODING *enc, if (!b) return XML_ERROR_UNBOUND_PREFIX; - /* as we expand the name we also calculate its hash value */ for (j = 0; j < b->uriLen; j++) { const XML_Char c = b->uri[j]; if (!poolAppendChar(&tempPool, c)) return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); } + + sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char)); + while (*s++ != XML_T(ASCII_COLON)) ; + + sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char)); + do { /* copies null terminator */ - const XML_Char c = *s; if (!poolAppendChar(&tempPool, *s)) return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); } while (*s++); + uriHash = (unsigned long)sip24_final(&sip_state); + { /* Check hash table for duplicate of expanded name (uriName). Derived from code in lookup(parser, HASH_TABLE *table, ...). */ @@ -3695,6 +3986,14 @@ entityValueInitProcessor(XML_Parser parser, *nextPtr = next; return XML_ERROR_NONE; } + /* If we get this token, we have the start of what might be a + normal tag, but not a declaration (i.e. it doesn't begin with + "internalEventEndPtr = NULL; textStart = (char *)entity->textPtr; textEnd = (char *)(entity->textPtr + entity->textLen); + /* Set a safe default value in case 'next' does not get set */ + next = textStart; #ifdef XML_DTD if (entity->is_param) { @@ -4916,6 +5217,8 @@ internalEntityProcessor(XML_Parser parser, entity = openEntity->entity; textStart = ((char *)entity->textPtr) + entity->processed; textEnd = (char *)(entity->textPtr + entity->textLen); + /* Set a safe default value in case 'next' does not get set */ + next = textStart; #ifdef XML_DTD if (entity->is_param) { @@ -5876,7 +6179,6 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_H newE->defaultAtts = (DEFAULT_ATTRIBUTE *) ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (!newE->defaultAtts) { - ms->free_fcn(newE); return 0; } } @@ -6011,13 +6313,32 @@ keyeq(KEY s1, KEY s2) return XML_FALSE; } +static size_t +keylen(KEY s) +{ + size_t len = 0; + for (; *s; s++, len++); + return len; +} + +static void +copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key) +{ + key->k[0] = 0; + key->k[1] = get_hash_secret_salt(parser); +} + static unsigned long FASTCALL hash(XML_Parser parser, KEY s) { - unsigned long h = hash_secret_salt; - while (*s) - h = CHAR_HASH(h, *s++); - return h; + struct siphash state; + struct sipkey key; + (void)sip_tobin; + (void)sip24_valid; + copy_salt_to_sipkey(parser, &key); + sip24_init(&state, &key); + sip24_update(&state, s, keylen(s) * sizeof(XML_Char)); + return (unsigned long)sip24_final(&state); } static NAMED * @@ -6260,6 +6581,35 @@ poolStoreString(STRING_POOL *pool, const ENCODING *enc, return pool->start; } +static size_t +poolBytesToAllocateFor(int blockSize) +{ + /* Unprotected math would be: + ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char); + ** + ** Detect overflow, avoiding _signed_ overflow undefined behavior + ** For a + b * c we check b * c in isolation first, so that addition of a + ** on top has no chance of making us accept a small non-negative number + */ + const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */ + + if (blockSize <= 0) + return 0; + + if (blockSize > (int)(INT_MAX / stretch)) + return 0; + + { + const int stretchedBlockSize = blockSize * (int)stretch; + const int bytesToAllocate = (int)( + offsetof(BLOCK, s) + (unsigned)stretchedBlockSize); + if (bytesToAllocate < 0) + return 0; + + return (size_t)bytesToAllocate; + } +} + static XML_Bool FASTCALL poolGrow(STRING_POOL *pool) { @@ -6289,14 +6639,17 @@ poolGrow(STRING_POOL *pool) if (pool->blocks && pool->start == pool->blocks->s) { BLOCK *temp; int blockSize = (int)((unsigned)(pool->end - pool->start)*2U); + size_t bytesToAllocate; if (blockSize < 0) return XML_FALSE; + bytesToAllocate = poolBytesToAllocateFor(blockSize); + if (bytesToAllocate == 0) + return XML_FALSE; + temp = (BLOCK *) - pool->mem->realloc_fcn(pool->blocks, - (offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char))); + pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate); if (temp == NULL) return XML_FALSE; pool->blocks = temp; @@ -6308,16 +6661,26 @@ poolGrow(STRING_POOL *pool) else { BLOCK *tem; int blockSize = (int)(pool->end - pool->start); + size_t bytesToAllocate; if (blockSize < 0) return XML_FALSE; if (blockSize < INIT_BLOCK_SIZE) blockSize = INIT_BLOCK_SIZE; - else + else { + /* Detect overflow, avoiding _signed_ overflow undefined behavior */ + if ((int)((unsigned)blockSize * 2U) < 0) { + return XML_FALSE; + } blockSize *= 2; - tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char)); + } + + bytesToAllocate = poolBytesToAllocateFor(blockSize); + if (bytesToAllocate == 0) + return XML_FALSE; + + tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate); if (!tem) return XML_FALSE; tem->size = blockSize; diff --git a/Utilities/cmexpat/lib/xmlrole.c b/Utilities/cmexpat/lib/xmlrole.c index 4e79ffdfb..a7c563027 100644 --- a/Utilities/cmexpat/lib/xmlrole.c +++ b/Utilities/cmexpat/lib/xmlrole.c @@ -4,19 +4,13 @@ #include -#ifdef COMPILING_FOR_WINDOWS +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #else #ifdef HAVE_EXPAT_CONFIG_H #include #endif -#endif /* ndef COMPILING_FOR_WINDOWS */ +#endif /* ndef _WIN32 */ #include "expat_external.h" #include "internal.h" diff --git a/Utilities/cmexpat/lib/xmltok.c b/Utilities/cmexpat/lib/xmltok.c index 419527953..cdf0720dd 100644 --- a/Utilities/cmexpat/lib/xmltok.c +++ b/Utilities/cmexpat/lib/xmltok.c @@ -4,19 +4,13 @@ #include -#ifdef COMPILING_FOR_WINDOWS +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #else #ifdef HAVE_EXPAT_CONFIG_H #include #endif -#endif /* ndef COMPILING_FOR_WINDOWS */ +#endif /* ndef _WIN32 */ #include "expat_external.h" #include "internal.h" @@ -369,24 +363,24 @@ utf8_toUtf8(const ENCODING *UNUSED_P(enc), const char **fromP, const char *fromLim, char **toP, const char *toLim) { - enum XML_Convert_Result res = XML_CONVERT_COMPLETED; char *to; const char *from; - if (fromLim - *fromP > toLim - *toP) { - /* Avoid copying partial characters. */ - res = XML_CONVERT_OUTPUT_EXHAUSTED; - fromLim = *fromP + (toLim - *toP); - align_limit_to_full_utf8_characters(*fromP, &fromLim); - } + const char *fromLimInitial = fromLim; + + /* Avoid copying partial characters. */ + align_limit_to_full_utf8_characters(*fromP, &fromLim); + for (to = *toP, from = *fromP; (from < fromLim) && (to < toLim); from++, to++) *to = *from; *fromP = from; *toP = to; - if ((to == toLim) && (from < fromLim)) + if (fromLim < fromLimInitial) + return XML_CONVERT_INPUT_INCOMPLETE; + else if ((to == toLim) && (from < fromLim)) return XML_CONVERT_OUTPUT_EXHAUSTED; else - return res; + return XML_CONVERT_COMPLETED; } static enum XML_Convert_Result PTRCALL @@ -402,7 +396,7 @@ utf8_toUtf16(const ENCODING *enc, case BT_LEAD2: if (fromLim - from < 2) { res = XML_CONVERT_INPUT_INCOMPLETE; - break; + goto after; } *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f)); from += 2; @@ -410,7 +404,7 @@ utf8_toUtf16(const ENCODING *enc, case BT_LEAD3: if (fromLim - from < 3) { res = XML_CONVERT_INPUT_INCOMPLETE; - break; + goto after; } *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f)); @@ -441,6 +435,8 @@ utf8_toUtf16(const ENCODING *enc, break; } } + if (from < fromLim) + res = XML_CONVERT_OUTPUT_EXHAUSTED; after: *fromP = from; *toP = to; diff --git a/Utilities/cmexpat/lib/xmltok_impl.c b/Utilities/cmexpat/lib/xmltok_impl.c index fd0ee222b..5f779c057 100644 --- a/Utilities/cmexpat/lib/xmltok_impl.c +++ b/Utilities/cmexpat/lib/xmltok_impl.c @@ -1198,6 +1198,8 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *start; if (ptr >= end) return XML_TOK_NONE; + else if (! HAS_CHAR(enc, ptr, end)) + return XML_TOK_PARTIAL; start = ptr; while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { @@ -1256,6 +1258,8 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *start; if (ptr >= end) return XML_TOK_NONE; + else if (! HAS_CHAR(enc, ptr, end)) + return XML_TOK_PARTIAL; start = ptr; while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt index d0114e711..bc9076e8e 100644 --- a/Utilities/cmjsoncpp/CMakeLists.txt +++ b/Utilities/cmjsoncpp/CMakeLists.txt @@ -24,3 +24,4 @@ include_directories( add_library(cmjsoncpp ${JSONCPP_SOURCES}) target_link_libraries(cmjsoncpp ${CMake_KWIML_LIBRARIES}) +set_property(TARGET cmjsoncpp PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index 09bef5192..bfe6b131e 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -17,13 +17,13 @@ SET(CMAKE_MACOSX_RPATH ON) # FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version) STRING(REGEX REPLACE - "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version}) + "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version}) STRING(REGEX REPLACE - "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version}) + "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version}) STRING(REGEX REPLACE - "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version}) + "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version}) STRING(REGEX REPLACE - "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version}) + "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version}) SET(_version_number ${_major}${_minor}${_revision}) STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor}) STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision}) @@ -71,13 +71,15 @@ include(CTest) OPTION(ENABLE_NETTLE "Enable use of Nettle" ON) OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON) -OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON) -OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON) -OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON) -OPTION(ENABLE_LIBXML2 "Enable the use of the system found libxml2 library if found" ON) -OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON) -OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON) -OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON) +OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF) +OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON) + +OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON) +OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON) +OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON) +OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON) +OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON) +OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON) # CNG is used for encrypt/decrypt Zip archives on Windows. OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON) @@ -107,7 +109,7 @@ INCLUDE(CheckHeaderDirent) INCLUDE(CheckIncludeFile) INCLUDE(CheckIncludeFiles) INCLUDE(CheckLibraryExists) -INCLUDE(CheckStructMember) +INCLUDE(CheckStructHasMember) INCLUDE(CheckSymbolExists) INCLUDE(CheckTypeExists) INCLUDE(CheckTypeSize) @@ -285,21 +287,20 @@ MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) # Find LZMA # IF(ENABLE_LZMA) - FIND_PACKAGE(LZMA) + FIND_PACKAGE(LibLZMA) ELSE() - SET(LZMA_FOUND FALSE) # Override cached value - SET(LZMADEC_FOUND FALSE) # Override cached value + SET(LIBZMA_FOUND FALSE) # Override cached value ENDIF() -IF(LZMA_FOUND) +IF(LIBLZMA_FOUND) SET(HAVE_LIBLZMA 1) SET(HAVE_LZMA_H 1) - INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR}) - LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES}) + INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS}) + LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES}) IF(CMAKE_USE_SYSTEM_LIBLZMA) # Test if a macro is needed for the library. TRY_MACRO_FOR_LIBRARY( - "${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}" + "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}" COMPILES "#include \nint main() {return (int)lzma_version_number(); }" "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC") @@ -309,27 +310,26 @@ IF(LZMA_FOUND) ELSE() ADD_DEFINITIONS(-DLZMA_API_STATIC) ENDIF() -ELSEIF(LZMADEC_FOUND) - SET(HAVE_LIBLZMADEC 1) - SET(HAVE_LZMADEC_H 1) - INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR}) - LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES}) -ELSE(LZMA_FOUND) +ELSE(LIBLZMA_FOUND) # LZMA not found and will not be used. -ENDIF(LZMA_FOUND) +ENDIF(LIBLZMA_FOUND) IF(0) # CMake does not need LZO2 support in libarchive # # Find LZO2 # -IF (LZO2_INCLUDE_DIR) - # Already in cache, be silent - SET(LZO2_FIND_QUIETLY TRUE) -ENDIF (LZO2_INCLUDE_DIR) - -FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) -FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +IF(ENABLE_LZO) + IF (LZO2_INCLUDE_DIR) + # Already in cache, be silent + SET(LZO2_FIND_QUIETLY TRUE) + ENDIF (LZO2_INCLUDE_DIR) + + FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) + FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +ELSE(ENABLE_LZO) + SET(LIBZMA_FOUND FALSE) # Override cached value +ENDIF(ENABLE_LZO) IF(LZO2_FOUND) SET(HAVE_LIBLZO2 1) SET(HAVE_LZO_LZOCONF_H 1) @@ -415,6 +415,11 @@ LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H) LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H) LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H) LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H) + +CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS) + LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H) LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H) LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H) @@ -459,7 +464,7 @@ IF(ENABLE_CNG) ELSE(ENABLE_CNG) UNSET(HAVE_BCRYPT_H CACHE) ENDIF(ENABLE_CNG) -# Following files need windwos.h, so we should test it after windows.h test. +# Following files need windows.h, so we should test it after windows.h test. LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H) LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H) @@ -1005,6 +1010,14 @@ CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE) CMAKE_POP_CHECK_STATE() # Restore the state of the variables +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct vfsconf v; return sizeof(v);}" + HAVE_STRUCT_VFSCONF) + +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct xvfsconf v; return sizeof(v);}" + HAVE_STRUCT_XVFSCONF) + # Make sure we have the POSIX version of readdir_r, not the # older 2-argument version. CHECK_C_SOURCE_COMPILES( @@ -1030,6 +1043,10 @@ CHECK_C_SOURCE_COMPILES( "#include \nint main() { return major(256); }" MAJOR_IN_SYSMACROS) +CHECK_C_SOURCE_COMPILES( + "#include \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) + IF(HAVE_STRERROR_R) SET(HAVE_DECL_STRERROR_R 1) ENDIF(HAVE_STRERROR_R) @@ -1063,47 +1080,47 @@ CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX) # Check struct members # # Check for tm_gmtoff in struct tm -CHECK_STRUCT_MEMBER("struct tm" tm_gmtoff +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff "time.h" HAVE_STRUCT_TM_TM_GMTOFF) -CHECK_STRUCT_MEMBER("struct tm" __tm_gmtoff +CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff "time.h" HAVE_STRUCT_TM___TM_GMTOFF) # Check for f_namemax in struct statfs -CHECK_STRUCT_MEMBER("struct statfs" f_namemax +CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax "sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX) # Check for birthtime in struct stat -CHECK_STRUCT_MEMBER("struct stat" st_birthtime +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME) # Check for high-resolution timestamps in struct stat -CHECK_STRUCT_MEMBER("struct stat" st_birthtimespec.tv_nsec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC) -CHECK_STRUCT_MEMBER("struct stat" st_mtimespec.tv_nsec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) -CHECK_STRUCT_MEMBER("struct stat" st_mtim.tv_nsec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) -CHECK_STRUCT_MEMBER("struct stat" st_mtime_n +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N) -CHECK_STRUCT_MEMBER("struct stat" st_umtime +CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME) -CHECK_STRUCT_MEMBER("struct stat" st_mtime_usec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC) # Check for block size support in struct stat -CHECK_STRUCT_MEMBER("struct stat" st_blksize +CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE) # Check for st_flags in struct stat (BSD fflags) -CHECK_STRUCT_MEMBER("struct stat" st_flags +CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS) IF(HAVE_SYS_STATVFS_H) - CHECK_STRUCT_MEMBER("struct statvfs" f_iosize + CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize "sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE) ENDIF() # # -CHECK_STRUCT_MEMBER("struct tm" tm_sec +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME) # @@ -1323,16 +1340,36 @@ IF(ENABLE_ACL) # test for specific permissions in a permset.) Linux uses the obvious # name, FreeBSD adds _np to mark it as "non-Posix extension." # Test for both as a double-check that we really have POSIX-style ACL support. + CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP) CHECK_FUNCTION_EXISTS(acl_get_perm HAVE_ACL_GET_PERM) CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP) CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK) CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP) CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP) CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP) + CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4) # MacOS has an acl.h that isn't POSIX. It can be detected by # checking for ACL_USER CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER) + CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED) + + # Solaris and derivates ACLs + CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC) + IF(HAVE_LIBSEC) + SET(CMAKE_REQUIRED_LIBRARIES "sec") + FIND_LIBRARY(SEC_LIBRARY NAMES sec) + LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY}) + ENDIF(HAVE_LIBSEC) + # + CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T) + CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T) + CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET) + CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET) + CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET) + CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET) ELSE(ENABLE_ACL) # If someone runs cmake, then disables ACL support, we need # to forcibly override the cached values for these. @@ -1347,7 +1384,15 @@ ELSE(ENABLE_ACL) SET(HAVE_ACL_SET_FD FALSE) SET(HAVE_ACL_SET_FD_NP FALSE) SET(HAVE_ACL_SET_FILE FALSE) + SET(HAVE_ACL_TYPE_NFS4 FALSE) SET(HAVE_ACL_USER FALSE) + SET(HAVE_ACL_TYPE_EXTENDED FALSE) + SET(HAVE_ACL_GET FALSE) + SET(HAVE_ACLENT_T FALSE) + SET(HAVE_ACE_T FALSE) + SET(HAVE_FACL_GET FALSE) + SET(HAVE_ACL_SET FALSE) + SET(HAVE_FACL_SET FALSE) ENDIF(ENABLE_ACL) # diff --git a/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake b/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake deleted file mode 100644 index 05ddb3a11..000000000 --- a/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake +++ /dev/null @@ -1,43 +0,0 @@ -# - Check if the given struct or class has the specified member variable -# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE) -# -# STRUCT - the name of the struct or class you are interested in -# MEMBER - the member which existence you want to check -# HEADER - the header(s) where the prototype should be declared -# VARIABLE - variable to store the result -# -# 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 - -# Copyright (c) 2006, Alexander Neundorf, -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - - -INCLUDE(CheckCSourceCompiles) - -MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT) - SET(_INCLUDE_FILES) - FOREACH (it ${_HEADER}) - SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") - ENDFOREACH (it) - - SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE " -${_INCLUDE_FILES} -int main() -{ - static ${_STRUCT} tmp; - if (sizeof(tmp.${_MEMBER})) - return 0; - return 0; -} -") - CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) - -ENDMACRO (CHECK_STRUCT_MEMBER) - diff --git a/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake b/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake deleted file mode 100644 index 0b46b2cdd..000000000 --- a/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# - Find lzma and lzmadec -# Find the native LZMA includes and library -# -# LZMA_INCLUDE_DIR - where to find lzma.h, etc. -# LZMA_LIBRARIES - List of libraries when using liblzma. -# LZMA_FOUND - True if liblzma found. -# LZMADEC_INCLUDE_DIR - where to find lzmadec.h, etc. -# LZMADEC_LIBRARIES - List of libraries when using liblzmadec. -# LZMADEC_FOUND - True if liblzmadec found. - -IF (LZMA_INCLUDE_DIR) - # Already in cache, be silent - SET(LZMA_FIND_QUIETLY TRUE) -ENDIF (LZMA_INCLUDE_DIR) - -FIND_PATH(LZMA_INCLUDE_DIR lzma.h) -FIND_LIBRARY(LZMA_LIBRARY NAMES lzma liblzma) - -# handle the QUIETLY and REQUIRED arguments and set LZMA_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMA DEFAULT_MSG LZMA_LIBRARY LZMA_INCLUDE_DIR) - -IF(LZMA_FOUND) - SET( LZMA_LIBRARIES ${LZMA_LIBRARY} ) -ELSE(LZMA_FOUND) - SET( LZMA_LIBRARIES ) - - IF (LZMADEC_INCLUDE_DIR) - # Already in cache, be silent - SET(LZMADEC_FIND_QUIETLY TRUE) - ENDIF (LZMADEC_INCLUDE_DIR) - - FIND_PATH(LZMADEC_INCLUDE_DIR lzmadec.h) - FIND_LIBRARY(LZMADEC_LIBRARY NAMES lzmadec ) - - # handle the QUIETLY and REQUIRED arguments and set LZMADEC_FOUND to TRUE if - # all listed variables are TRUE - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMADEC DEFAULT_MSG LZMADEC_LIBRARY - LZMADEC_INCLUDE_DIR) - - IF(LZMADEC_FOUND) - SET( LZMADEC_LIBRARIES ${LZMADEC_LIBRARY} ) - ELSE(LZMADEC_FOUND) - SET( LZMADEC_LIBRARIES ) - ENDIF(LZMADEC_FOUND) -ENDIF(LZMA_FOUND) diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in index 9843875d7..55e04b9af 100644 --- a/Utilities/cmlibarchive/build/cmake/config.h.in +++ b/Utilities/cmlibarchive/build/cmake/config.h.in @@ -296,6 +296,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `acl_create_entry' function. */ #cmakedefine HAVE_ACL_CREATE_ENTRY 1 +/* Define to 1 if you have the `acl_get_fd_np' function. */ +#cmakedefine HAVE_ACL_GET_FD_NP 1 + /* Define to 1 if you have the `acl_get_link' function. */ #cmakedefine HAVE_ACL_GET_LINK 1 @@ -326,6 +329,12 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `acl_set_file' function. */ #cmakedefine HAVE_ACL_SET_FILE 1 +/* True for FreeBSD with NFSv4 ACL support */ +#cmakedefine HAVE_ACL_TYPE_NFS4 1 + +/* True for MacOS ACL support */ +#cmakedefine HAVE_ACL_TYPE_EXTENDED 1 + /* True for systems with POSIX ACL support */ #cmakedefine HAVE_ACL_USER 1 @@ -727,6 +736,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LZMA_H 1 +/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */ +#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LZO_LZO1X_H 1 @@ -929,6 +941,12 @@ typedef uint64_t uintmax_t; /* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ #cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1 +/* Define to 1 if you have `struct vfsconf'. */ +#cmakedefine HAVE_STRUCT_VFSCONF 1 + +/* Define to 1 if you have `struct xvfsconf'. */ +#cmakedefine HAVE_STRUCT_XVFSCONF 1 + /* Define to 1 if you have the `symlink' function. */ #cmakedefine HAVE_SYMLINK 1 @@ -1087,6 +1105,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have a working EXT2_IOC_GETFLAGS */ #cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1 +/* Define to 1 if you have a working FS_IOC_GETFLAGS */ +#cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ZLIB_H 1 diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version index f29315637..ef8345726 100644 --- a/Utilities/cmlibarchive/build/version +++ b/Utilities/cmlibarchive/build/version @@ -1 +1 @@ -3002001 +3003001 diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt index eaa7b2012..d412c80dc 100644 --- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt @@ -168,15 +168,33 @@ SET(libarchive_MANS archive_entry_time.3 archive_read.3 archive_read_add_passphrase.3 + archive_read_data.3 archive_read_disk.3 + archive_read_extract.3 + archive_read_filter.3 + archive_read_format.3 + archive_read_free.3 + archive_read_header.3 + archive_read_new.3 + archive_read_open.3 archive_read_set_options.3 archive_util.3 archive_write.3 + archive_write_blocksize.3 + archive_write_data.3 archive_write_disk.3 + archive_write_filter.3 + archive_write_finish_entry.3 + archive_write_format.3 + archive_write_free.3 + archive_write_header.3 + archive_write_new.3 + archive_write_open.3 archive_write_set_options.3 archive_write_set_passphrase.3 cpio.5 libarchive.3 + libarchive_changes.3 libarchive_internals.3 libarchive-formats.5 mtree.5 diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h index 3b5104b37..cfb5c48b2 100644 --- a/Utilities/cmlibarchive/libarchive/archive.h +++ b/Utilities/cmlibarchive/libarchive/archive.h @@ -36,7 +36,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3002001 +#define ARCHIVE_VERSION_NUMBER 3003001 #include #include /* for wchar_t */ @@ -152,7 +152,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.2.1" +#define ARCHIVE_VERSION_ONLY_STRING "3.3.1" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -370,7 +370,7 @@ typedef const char *archive_passphrase_callback(struct archive *, * 4) Repeatedly call archive_read_next_header to get information about * successive archive entries. Call archive_read_data to extract * data for entries of interest. - * 5) Call archive_read_finish to end processing. + * 5) Call archive_read_free to end processing. */ __LA_DECL struct archive *archive_read_new(void); @@ -559,7 +559,7 @@ __LA_DECL la_int64_t archive_read_header_position(struct archive *); * we cannot say whether there are encrypted entries, then * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. * In general, this function will return values below zero when the - * reader is uncertain or totally uncapable of encryption support. + * reader is uncertain or totally incapable of encryption support. * When this function returns 0 you can be sure that the reader * supports encryption detection but no encrypted entries have * been found yet. @@ -981,12 +981,12 @@ __LA_DECL int archive_read_disk_can_descend(struct archive *); __LA_DECL int archive_read_disk_current_filesystem(struct archive *); __LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); __LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); -/* Request that the access time of the entry visited by travesal be restored. */ +/* Request that the access time of the entry visited by traversal be restored. */ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *); /* * Set behavior. The "flags" argument selects optional behavior. */ -/* Request that the access time of the entry visited by travesal be restored. +/* Request that the access time of the entry visited by traversal be restored. * This is the same as archive_read_disk_set_atime_restored. */ #define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) /* Default: Do not skip an entry which has nodump flags. */ @@ -998,6 +998,10 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *); #define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) /* Default: Xattrs are read from disk. */ #define ARCHIVE_READDISK_NO_XATTR (0x0010) +/* Default: ACLs are read from disk. */ +#define ARCHIVE_READDISK_NO_ACL (0x0020) +/* Default: File flags are read from disk. */ +#define ARCHIVE_READDISK_NO_FFLAGS (0x0040) __LA_DECL int archive_read_disk_set_behavior(struct archive *, int flags); @@ -1121,7 +1125,7 @@ __LA_DECL int archive_match_time_excluded(struct archive *, /* * Flags to tell a matching type of time stamps. These are used for - * following functinos. + * following functions. */ /* Time flag: mtime to be tested. */ #define ARCHIVE_MATCH_MTIME (0x0100) @@ -1141,7 +1145,7 @@ __LA_DECL int archive_match_include_date(struct archive *, int _flag, const char *_datestr); __LA_DECL int archive_match_include_date_w(struct archive *, int _flag, const wchar_t *_datestr); -/* Set inclusion time by a particluar file. */ +/* Set inclusion time by a particular file. */ __LA_DECL int archive_match_include_file_time(struct archive *, int _flag, const char *_pathname); __LA_DECL int archive_match_include_file_time_w(struct archive *, diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c index bf4b61040..b8b6b6364 100644 --- a/Utilities/cmlibarchive/libarchive/archive_acl.c +++ b/Utilities/cmlibarchive/libarchive/archive_acl.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,25 +56,77 @@ static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl, static int archive_acl_add_entry_len_l(struct archive_acl *acl, int type, int permset, int tag, int id, const char *name, size_t len, struct archive_string_conv *sc); +static int archive_acl_text_want_type(struct archive_acl *acl, int flags); +static ssize_t archive_acl_text_len(struct archive_acl *acl, int want_type, + int flags, int wide, struct archive *a, + struct archive_string_conv *sc); static int isint_w(const wchar_t *start, const wchar_t *end, int *result); static int ismode_w(const wchar_t *start, const wchar_t *end, int *result); +static int is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, + int *result); +static int is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, + int *result); static void next_field_w(const wchar_t **wp, const wchar_t **start, const wchar_t **end, wchar_t *sep); -static int prefix_w(const wchar_t *start, const wchar_t *end, - const wchar_t *test); -static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, - const wchar_t *wname, int perm, int id); +static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, + int tag, int flags, const wchar_t *wname, int perm, int id); static void append_id_w(wchar_t **wp, int id); static int isint(const char *start, const char *end, int *result); static int ismode(const char *start, const char *end, int *result); +static int is_nfs4_flags(const char *start, const char *end, + int *result); +static int is_nfs4_perms(const char *start, const char *end, + int *result); static void next_field(const char **p, const char **start, const char **end, char *sep); -static int prefix_c(const char *start, const char *end, - const char *test); -static void append_entry(char **p, const char *prefix, int tag, - const char *name, int perm, int id); +static void append_entry(char **p, const char *prefix, int type, + int tag, int flags, const char *name, int perm, int id); static void append_id(char **p, int id); +static const struct { + const int perm; + const char c; + const wchar_t wc; +} nfsv4_acl_perm_map[] = { + { ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r', + L'r' }, + { ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w', + L'w' }, + { ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' }, + { ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, + 'p', L'p' }, + { ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' }, + { ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' }, + { ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' }, + { ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' }, + { ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' }, + { ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' }, + { ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' }, + { ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' }, + { ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' }, + { ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' } +}; + +static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) / + sizeof(nfsv4_acl_perm_map[0])); + +static const struct { + const int perm; + const char c; + const wchar_t wc; +} nfsv4_acl_flag_map[] = { + { ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' }, + { ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' }, + { ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' }, + { ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' }, + { ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' }, + { ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' }, + { ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' } +}; + +static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) / + sizeof(nfsv4_acl_flag_map[0])); + void archive_acl_clear(struct archive_acl *acl) { @@ -94,6 +147,7 @@ archive_acl_clear(struct archive_acl *acl) acl->acl_text = NULL; } acl->acl_p = NULL; + acl->acl_types = 0; acl->acl_state = 0; /* Not counting. */ } @@ -279,23 +333,31 @@ acl_new_entry(struct archive_acl *acl, acl->acl_text = NULL; } - /* If there's a matching entry already in the list, overwrite it. */ + /* + * If there's a matching entry already in the list, overwrite it. + * NFSv4 entries may be repeated and are not overwritten. + * + * TODO: compare names of no id is provided (needs more rework) + */ ap = acl->acl_head; aq = NULL; while (ap != NULL) { - if (ap->type == type && ap->tag == tag && ap->id == id) { - ap->permset = permset; - return (ap); + if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) && + ap->type == type && ap->tag == tag && ap->id == id) { + if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER && + tag != ARCHIVE_ENTRY_ACL_GROUP)) { + ap->permset = permset; + return (ap); + } } aq = ap; ap = ap->next; } /* Add a new entry to the end of the list. */ - ap = (struct archive_acl_entry *)malloc(sizeof(*ap)); + ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap)); if (ap == NULL) return (NULL); - memset(ap, 0, sizeof(*ap)); if (aq == NULL) acl->acl_head = ap; else @@ -330,6 +392,15 @@ archive_acl_count(struct archive_acl *acl, int want_type) return (count); } +/* + * Return a bitmask of stored ACL types in an ACL list + */ +int +archive_acl_types(struct archive_acl *acl) +{ + return (acl->acl_types); +} + /* * Prepare for reading entries from the ACL data. Returns a count * of entries matching "want_type", or zero if there are no @@ -366,8 +437,8 @@ archive_acl_reset(struct archive_acl *acl, int want_type) * standard permissions and include them in the returned list. */ int -archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int *type, - int *permset, int *tag, int *id, const char **name) +archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, + int *type, int *permset, int *tag, int *id, const char **name) { *name = NULL; *id = -1; @@ -432,130 +503,273 @@ archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int } /* - * Generate a text version of the ACL. The flags parameter controls - * the style of the generated ACL. + * Determine what type of ACL do we want */ -const wchar_t * -archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) +static int +archive_acl_text_want_type(struct archive_acl *acl, int flags) { - int count; - size_t length; - const wchar_t *wname; - const wchar_t *prefix; - wchar_t separator; - struct archive_acl_entry *ap; - int id, r; - wchar_t *wp; + int want_type; - if (acl->acl_text_w != NULL) { - free (acl->acl_text_w); - acl->acl_text_w = NULL; + /* Check if ACL is NFSv4 */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + /* NFSv4 should never mix with POSIX.1e */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + return (0); + else + return (ARCHIVE_ENTRY_ACL_TYPE_NFS4); } - separator = L','; + /* Now deal with POSIX.1e ACLs */ + + want_type = 0; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + + /* By default we want both access and default ACLs */ + if (want_type == 0) + return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E); + + return (want_type); +} + +/* + * Calculate ACL text string length + */ +static ssize_t +archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, + int wide, struct archive *a, struct archive_string_conv *sc) { + struct archive_acl_entry *ap; + const char *name; + const wchar_t *wname; + int count, idlen, tmp, r; + ssize_t length; + size_t len; + count = 0; length = 0; - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & flags) != 0) { - count++; - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && - (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) - length += 8; /* "default:" */ - length += 5; /* tag name */ - length += 1; /* colon */ - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0 && wname != NULL) - length += wcslen(wname); - else if (r < 0 && errno == ENOMEM) - return (NULL); - else - length += sizeof(uid_t) * 3 + 1; - length ++; /* colon */ + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + count++; + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 + && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + length += 8; /* "default:" */ + switch (ap->tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + length += 6; /* "owner@" */ + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_USER: + case ARCHIVE_ENTRY_ACL_MASK: + length += 4; /* "user", "mask" */ + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + length += 6; /* "group@" */ + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_GROUP: + case ARCHIVE_ENTRY_ACL_OTHER: + length += 5; /* "group", "other" */ + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + length += 9; /* "everyone@" */ + break; + } + length += 1; /* colon after tag */ + if (ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (wide) { + r = archive_mstring_get_wcs(a, &ap->name, + &wname); + if (r == 0 && wname != NULL) + length += wcslen(wname); + else if (r < 0 && errno == ENOMEM) + return (0); + else + length += sizeof(uid_t) * 3 + 1; + } else { + r = archive_mstring_get_mbs_l(&ap->name, &name, + &len, sc); + if (r != 0) + return (0); + if (len > 0 && name != NULL) + length += len; + else + length += sizeof(uid_t) * 3 + 1; + } + length += 1; /* colon after user or group name */ + } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) + length += 1; /* 2nd colon empty user,group or other */ + + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) + && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER + || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) { + /* Solaris has no colon after other: and mask: */ + length = length - 1; + } + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* rwxpdDaARWcCos:fdinSFI:deny */ + length += 27; + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0) + length += 1; /* allow, alarm, audit */ + } else length += 3; /* rwx */ + + if ((ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) && + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) { length += 1; /* colon */ - length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; - length ++; /* newline */ + /* ID digit count */ + idlen = 1; + tmp = ap->id; + while (tmp > 9) { + tmp = tmp / 10; + idlen++; + } + length += idlen; } - ap = ap->next; + length ++; /* entry separator */ } - if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { - length += 10; /* "user::rwx\n" */ - length += 11; /* "group::rwx\n" */ - length += 11; /* "other::rwx\n" */ - } + /* Add filemode-mapping access entries to the length */ + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) { + /* "user::rwx\ngroup::rwx\nother:rwx\n" */ + length += 31; + } else { + /* "user::rwx\ngroup::rwx\nother::rwx\n" */ + length += 32; + } + } else if (count == 0) + return (0); + + /* The terminating character is included in count */ + return (length); +} + +/* + * Generate a wide text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +wchar_t * +archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, + struct archive *a) +{ + int count; + ssize_t length; + size_t len; + const wchar_t *wname; + const wchar_t *prefix; + wchar_t separator; + struct archive_acl_entry *ap; + int id, r, want_type; + wchar_t *wp, *ws; + + want_type = archive_acl_text_want_type(acl, flags); + + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL); - if (count == 0) + if (length == 0) return (NULL); + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = L','; + else + separator = L'\n'; + /* Now, allocate the string and actually populate it. */ - wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t)); - if (wp == NULL) + wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t)); + if (wp == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); + } count = 0; - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); count += 3; - - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0) { - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, NULL, ap->tag, wname, - ap->permset, id); - count++; - } else if (r < 0 && errno == ENOMEM) - return (NULL); - } - ap = ap->next; - } } - - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) prefix = L"default:"; else prefix = NULL; - ap = acl->acl_head; - count = 0; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0) { - if (count > 0) - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, prefix, ap->tag, - wname, ap->permset, id); - count ++; - } else if (r < 0 && errno == ENOMEM) - return (NULL); - } - ap = ap->next; - } + r = archive_mstring_get_wcs(a, &ap->name, &wname); + if (r == 0) { + if (count > 0) + *wp++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry_w(&wp, prefix, ap->type, ap->tag, flags, + wname, ap->permset, id); + count++; + } else if (r < 0 && errno == ENOMEM) + return (NULL); } - return (acl->acl_text_w); -} + /* Add terminating character */ + *wp++ = L'\0'; + + len = wcslen(ws); + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (ws); +} static void append_id_w(wchar_t **wp, int id) @@ -568,9 +782,11 @@ append_id_w(wchar_t **wp, int id) } static void -append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, - const wchar_t *wname, int perm, int id) +append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, + int tag, int flags, const wchar_t *wname, int perm, int id) { + int i; + if (prefix != NULL) { wcscpy(*wp, prefix); *wp += wcslen(*wp); @@ -579,6 +795,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, case ARCHIVE_ENTRY_ACL_USER_OBJ: wname = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + wcscpy(*wp, L"owner@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: wcscpy(*wp, L"user"); @@ -586,6 +806,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, case ARCHIVE_ENTRY_ACL_GROUP_OBJ: wname = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + wcscpy(*wp, L"group@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: wcscpy(*wp, L"group"); @@ -600,153 +824,184 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, wname = NULL; id = -1; break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + wcscpy(*wp, L"everyone@"); + wname = NULL; + id = -1; + break; } *wp += wcslen(*wp); *(*wp)++ = L':'; - if (wname != NULL) { - wcscpy(*wp, wname); + if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || + tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (wname != NULL) { + wcscpy(*wp, wname); + *wp += wcslen(*wp); + } else if (tag == ARCHIVE_ENTRY_ACL_USER + || tag == ARCHIVE_ENTRY_ACL_GROUP) { + append_id_w(wp, id); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*wp)++ = L':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*wp)++ = (perm & 0444) ? L'r' : L'-'; + *(*wp)++ = (perm & 0222) ? L'w' : L'-'; + *(*wp)++ = (perm & 0111) ? L'x' : L'-'; + } else { + /* NFSv4 ACL perms */ + for (i = 0; i < nfsv4_acl_perm_map_size; i++) { + if (perm & nfsv4_acl_perm_map[i].perm) + *(*wp)++ = nfsv4_acl_perm_map[i].wc; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*wp)++ = L'-'; + } + *(*wp)++ = L':'; + for (i = 0; i < nfsv4_acl_flag_map_size; i++) { + if (perm & nfsv4_acl_flag_map[i].perm) + *(*wp)++ = nfsv4_acl_flag_map[i].wc; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*wp)++ = L'-'; + } + *(*wp)++ = L':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + wcscpy(*wp, L"allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + wcscpy(*wp, L"deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + wcscpy(*wp, L"audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + wcscpy(*wp, L"alarm"); + break; + default: + break; + } *wp += wcslen(*wp); - } else if (tag == ARCHIVE_ENTRY_ACL_USER - || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id_w(wp, id); - id = -1; } - *(*wp)++ = L':'; - *(*wp)++ = (perm & 0444) ? L'r' : L'-'; - *(*wp)++ = (perm & 0222) ? L'w' : L'-'; - *(*wp)++ = (perm & 0111) ? L'x' : L'-'; if (id != -1) { *(*wp)++ = L':'; append_id_w(wp, id); } - **wp = L'\0'; } -int -archive_acl_text_l(struct archive_acl *acl, int flags, - const char **acl_text, size_t *acl_text_len, +/* + * Generate a text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +char * +archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, struct archive_string_conv *sc) { int count; - size_t length; + ssize_t length; + size_t len; const char *name; const char *prefix; char separator; struct archive_acl_entry *ap; - size_t len; - int id, r; - char *p; + int id, r, want_type; + char *p, *s; - if (acl->acl_text != NULL) { - free (acl->acl_text); - acl->acl_text = NULL; - } + want_type = archive_acl_text_want_type(acl, flags); - *acl_text = NULL; - if (acl_text_len != NULL) - *acl_text_len = 0; - separator = ','; - count = 0; - length = 0; - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & flags) != 0) { - count++; - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && - (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) - length += 8; /* "default:" */ - length += 5; /* tag name */ - length += 1; /* colon */ - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - if (len > 0 && name != NULL) - length += len; - else - length += sizeof(uid_t) * 3 + 1; - length ++; /* colon */ - length += 3; /* rwx */ - length += 1; /* colon */ - length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; - length ++; /* newline */ - } - ap = ap->next; - } + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); - if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { - length += 10; /* "user::rwx\n" */ - length += 11; /* "group::rwx\n" */ - length += 11; /* "other::rwx\n" */ - } + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; - if (count == 0) - return (0); + length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc); + + if (length == 0) + return (NULL); + + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = ','; + else + separator = '\n'; /* Now, allocate the string and actually populate it. */ - p = acl->acl_text = (char *)malloc(length); - if (p == NULL) - return (-1); + p = s = (char *)malloc(length * sizeof(char)); + if (p == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); + } count = 0; - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *p++ = ','; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *p++ = ','; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); count += 3; - - for (ap = acl->acl_head; ap != NULL; ap = ap->next) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) == 0) - continue; - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - *p++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry(&p, NULL, ap->tag, name, - ap->permset, id); - count++; - } } - - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) prefix = "default:"; else prefix = NULL; - count = 0; - for (ap = acl->acl_head; ap != NULL; ap = ap->next) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) == 0) - continue; - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - if (count > 0) - *p++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry(&p, prefix, ap->tag, - name, ap->permset, id); - count ++; + r = archive_mstring_get_mbs_l( + &ap->name, &name, &len, sc); + if (r != 0) + return (NULL); + if (count > 0) + *p++ = separator; + if (name == NULL || + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) { + id = ap->id; + } else { + id = -1; } + append_entry(&p, prefix, ap->type, ap->tag, flags, name, + ap->permset, id); + count++; } - *acl_text = acl->acl_text; - if (acl_text_len != NULL) - *acl_text_len = strlen(acl->acl_text); - return (0); + /* Add terminating character */ + *p++ = '\0'; + + len = strlen(s); + + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (s); } static void @@ -760,9 +1015,11 @@ append_id(char **p, int id) } static void -append_entry(char **p, const char *prefix, int tag, - const char *name, int perm, int id) +append_entry(char **p, const char *prefix, int type, + int tag, int flags, const char *name, int perm, int id) { + int i; + if (prefix != NULL) { strcpy(*p, prefix); *p += strlen(*p); @@ -771,6 +1028,10 @@ append_entry(char **p, const char *prefix, int tag, case ARCHIVE_ENTRY_ACL_USER_OBJ: name = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + strcpy(*p, "owner@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: strcpy(*p, "user"); @@ -778,6 +1039,10 @@ append_entry(char **p, const char *prefix, int tag, case ARCHIVE_ENTRY_ACL_GROUP_OBJ: name = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + strcpy(*p, "group@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: strcpy(*p, "group"); @@ -792,48 +1057,120 @@ append_entry(char **p, const char *prefix, int tag, name = NULL; id = -1; break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + strcpy(*p, "everyone@"); + name = NULL; + id = -1; + break; } *p += strlen(*p); *(*p)++ = ':'; - if (name != NULL) { - strcpy(*p, name); + if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || + tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (name != NULL) { + strcpy(*p, name); + *p += strlen(*p); + } else if (tag == ARCHIVE_ENTRY_ACL_USER + || tag == ARCHIVE_ENTRY_ACL_GROUP) { + append_id(p, id); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*p)++ = ':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*p)++ = (perm & 0444) ? 'r' : '-'; + *(*p)++ = (perm & 0222) ? 'w' : '-'; + *(*p)++ = (perm & 0111) ? 'x' : '-'; + } else { + /* NFSv4 ACL perms */ + for (i = 0; i < nfsv4_acl_perm_map_size; i++) { + if (perm & nfsv4_acl_perm_map[i].perm) + *(*p)++ = nfsv4_acl_perm_map[i].c; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*p)++ = '-'; + } + *(*p)++ = ':'; + for (i = 0; i < nfsv4_acl_flag_map_size; i++) { + if (perm & nfsv4_acl_flag_map[i].perm) + *(*p)++ = nfsv4_acl_flag_map[i].c; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*p)++ = '-'; + } + *(*p)++ = ':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + strcpy(*p, "allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + strcpy(*p, "deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + strcpy(*p, "audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + strcpy(*p, "alarm"); + break; + } *p += strlen(*p); - } else if (tag == ARCHIVE_ENTRY_ACL_USER - || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id(p, id); - id = -1; } - *(*p)++ = ':'; - *(*p)++ = (perm & 0444) ? 'r' : '-'; - *(*p)++ = (perm & 0222) ? 'w' : '-'; - *(*p)++ = (perm & 0111) ? 'x' : '-'; if (id != -1) { *(*p)++ = ':'; append_id(p, id); } - **p = '\0'; } /* - * Parse a textual ACL. This automatically recognizes and supports - * extensions described above. The 'type' argument is used to - * indicate the type that should be used for any entries not - * explicitly marked as "default:". + * Parse a wide ACL text string. + * + * The want_type argument may be one of the following: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT + * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL + * + * POSIX.1e ACL entries prefixed with "default:" are treated as + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ int -archive_acl_parse_w(struct archive_acl *acl, - const wchar_t *text, int default_type) +archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, + int want_type) { struct { const wchar_t *start; const wchar_t *end; - } field[4], name; + } field[6], name; + + const wchar_t *s, *st; - int fields, n; - int type, tag, permset, id; + int numfields, fields, n, r, sol, ret; + int type, types, tag, permset, id; + size_t len; wchar_t sep; - while (text != NULL && *text != L'\0') { + ret = ARCHIVE_OK; + types = 0; + + switch (want_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + numfields = 5; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + numfields = 6; + break; + default: + return (ARCHIVE_FATAL); + } + + while (text != NULL && *text != L'\0') { /* * Parse the fields out of the next entry, * advance 'text' to start of next entry. @@ -842,7 +1179,7 @@ archive_acl_parse_w(struct archive_acl *acl, do { const wchar_t *start, *end; next_field_w(&text, &start, &end, &sep); - if (fields < 4) { + if (fields < numfields) { field[fields].start = start; field[fields].end = end; } @@ -850,78 +1187,210 @@ archive_acl_parse_w(struct archive_acl *acl, } while (sep == L':'); /* Set remaining fields to blank. */ - for (n = fields; n < 4; ++n) + for (n = fields; n < numfields; ++n) field[n].start = field[n].end = NULL; - /* Check for a numeric ID in field 1 or 3. */ - id = -1; - isint_w(field[1].start, field[1].end, &id); - /* Field 3 is optional. */ - if (id == -1 && fields > 3) - isint_w(field[3].start, field[3].end, &id); - - /* - * Solaris extension: "defaultuser::rwx" is the - * default ACL corresponding to "user::rwx", etc. - */ - if (field[0].end - field[0].start > 7 - && wmemcmp(field[0].start, L"default", 7) == 0) { - type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; - field[0].start += 7; - } else - type = default_type; + if (field[0].start != NULL && *(field[0].start) == L'#') { + /* Comment, skip entry */ + continue; + } + n = 0; + sol = 0; + id = -1; + permset = 0; name.start = name.end = NULL; - if (prefix_w(field[0].start, field[0].end, L"user")) { - if (!ismode_w(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_USER; - name = field[1]; + + if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* POSIX.1e ACLs */ + /* + * Default keyword "default:user::rwx" + * if found, we have one more field + * + * We also support old Solaris extension: + * "defaultuser::rwx" is the default ACL corresponding + * to "user::rwx", etc. valid only for first field + */ + s = field[0].start; + len = field[0].end - field[0].start; + if (*s == L'd' && (len == 1 || (len >= 7 + && wmemcmp((s + 1), L"efault", 6) == 0))) { + type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + if (len > 7) + field[0].start += 7; + else + n = 1; } else - tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (prefix_w(field[0].start, field[0].end, L"group")) { - if (!ismode_w(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_GROUP; + type = want_type; + + /* Check for a numeric ID in field n+1 or n+3. */ + isint_w(field[n + 1].start, field[n + 1].end, &id); + /* Field n+3 is optional. */ + if (id == -1 && fields > n+3) + isint_w(field[n + 3].start, field[n + 3].end, + &id); + + tag = 0; + s = field[n].start; + st = field[n].start + 1; + len = field[n].end - field[n].start; + + switch (*s) { + case L'u': + if (len == 1 || (len == 4 + && wmemcmp(st, L"ser", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case L'g': + if (len == 1 || (len == 5 + && wmemcmp(st, L"roup", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case L'o': + if (len == 1 || (len == 5 + && wmemcmp(st, L"ther", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + case L'm': + if (len == 1 || (len == 4 + && wmemcmp(st, L"ask", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_MASK; + break; + default: + break; + } + + switch (tag) { + case ARCHIVE_ENTRY_ACL_OTHER: + case ARCHIVE_ENTRY_ACL_MASK: + if (fields == (n + 2) + && field[n + 1].start < field[n + 1].end + && ismode_w(field[n + 1].start, + field[n + 1].end, &permset)) { + /* This is Solaris-style "other:rwx" */ + sol = 1; + } else if (fields == (n + 3) && + field[n + 1].start < field[n + 1].end) { + /* Invalid mask or other field */ + ret = ARCHIVE_WARN; + continue; + } + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (id != -1 || + field[n + 1].start < field[n + 1].end) { + name = field[n + 1]; + if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) + tag = ARCHIVE_ENTRY_ACL_USER; + else + tag = ARCHIVE_ENTRY_ACL_GROUP; + } + break; + default: + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + + /* + * Without "default:" we expect mode in field 2 + * Exception: Solaris other and mask fields + */ + if (permset == 0 && !ismode_w(field[n + 2 - sol].start, + field[n + 2 - sol].end, &permset)) { + /* Invalid mode, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + } else { + /* NFS4 ACLs */ + s = field[0].start; + len = field[0].end - field[0].start; + tag = 0; + + switch (len) { + case 4: + if (wmemcmp(s, L"user", 4) == 0) + tag = ARCHIVE_ENTRY_ACL_USER; + break; + case 5: + if (wmemcmp(s, L"group", 5) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case 6: + if (wmemcmp(s, L"owner@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if (wmemcmp(s, L"group@", len) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 9: + if (wmemcmp(s, L"everyone@", 9) == 0) + tag = ARCHIVE_ENTRY_ACL_EVERYONE; + default: + break; + } + + if (tag == 0) { + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } else if (tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + n = 1; name = field[1]; + isint_w(name.start, name.end, &id); } else - tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (prefix_w(field[0].start, field[0].end, L"other")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode_w(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "other:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode_w(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "other::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_OTHER; - } else if (prefix_w(field[0].start, field[0].end, L"mask")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode_w(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "mask:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode_w(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "mask::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_MASK; - } else - return (ARCHIVE_WARN); + n = 0; + + if (!is_nfs4_perms_w(field[1 + n].start, + field[1 + n].end, &permset)) { + /* Invalid NFSv4 perms, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + if (!is_nfs4_flags_w(field[2 + n].start, + field[2 + n].end, &permset)) { + /* Invalid NFSv4 flags, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + s = field[3 + n].start; + len = field[3 + n].end - field[3 + n].start; + type = 0; + if (len == 4) { + if (wmemcmp(s, L"deny", 4) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + } else if (len == 5) { + if (wmemcmp(s, L"allow", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + else if (wmemcmp(s, L"audit", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + else if (wmemcmp(s, L"alarm", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + } + if (type == 0) { + /* Invalid entry type, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + isint_w(field[4 + n].start, field[4 + n].end, &id); + } /* Add entry to the internal list. */ - archive_acl_add_entry_w_len(acl, type, permset, + r = archive_acl_add_entry_w_len(acl, type, permset, tag, id, name.start, name.end - name.start); + if (r < ARCHIVE_WARN) + return (r); + if (r != ARCHIVE_OK) + ret = ARCHIVE_WARN; + types |= type; } - return (ARCHIVE_OK); + + /* Reset ACL */ + archive_acl_reset(acl, types); + + return (ret); } /* @@ -967,16 +1436,122 @@ ismode_w(const wchar_t *start, const wchar_t *end, int *permset) *permset = 0; while (p < end) { switch (*p++) { - case 'r': case 'R': + case L'r': case L'R': *permset |= ARCHIVE_ENTRY_ACL_READ; break; - case 'w': case 'W': + case L'w': case L'W': *permset |= ARCHIVE_ENTRY_ACL_WRITE; break; - case 'x': case 'X': + case L'x': case L'X': *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; break; - case '-': + case L'-': + break; + default: + return (0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL permission field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * permission characters, false otherwise + */ +static int +is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset) +{ + const wchar_t *p = start; + + while (p < end) { + switch (*p++) { + case L'r': + *permset |= ARCHIVE_ENTRY_ACL_READ_DATA; + break; + case L'w': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA; + break; + case L'x': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case L'p': + *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA; + break; + case L'D': + *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD; + break; + case L'd': + *permset |= ARCHIVE_ENTRY_ACL_DELETE; + break; + case L'a': + *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES; + break; + case L'A': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES; + break; + case L'R': + *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS; + break; + case L'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS; + break; + case L'c': + *permset |= ARCHIVE_ENTRY_ACL_READ_ACL; + break; + case L'C': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL; + break; + case L'o': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER; + break; + case L's': + *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + break; + case L'-': + break; + default: + return(0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL flags field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * flag characters, false otherwise + */ +static int +is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset) +{ + const wchar_t *p = start; + + while (p < end) { + switch(*p++) { + case L'f': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT; + break; + case L'd': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT; + break; + case L'i': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY; + break; + case L'n': + *permset |= + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT; + break; + case L'S': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS; + break; + case L'F': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS; + break; + case L'I': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED; + break; + case L'-': break; default: return (0); @@ -1023,46 +1598,48 @@ next_field_w(const wchar_t **wp, const wchar_t **start, } /* - * Return true if the characters [start...end) are a prefix of 'test'. - * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc. - */ -static int -prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test) -{ - if (start == end) - return (0); - - if (*start++ != *test++) - return (0); - - while (start < end && *start++ == *test++) - ; - - if (start < end) - return (0); - - return (1); -} - -/* - * Parse a textual ACL. This automatically recognizes and supports - * extensions described above. The 'type' argument is used to - * indicate the type that should be used for any entries not - * explicitly marked as "default:". + * Parse an ACL text string. + * + * The want_type argument may be one of the following: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT + * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL + * + * POSIX.1e ACL entries prefixed with "default:" are treated as + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ int -archive_acl_parse_l(struct archive_acl *acl, - const char *text, int default_type, struct archive_string_conv *sc) +archive_acl_from_text_l(struct archive_acl *acl, const char *text, + int want_type, struct archive_string_conv *sc) { struct { const char *start; const char *end; - } field[4], name; + } field[6], name; - int fields, n, r, ret = ARCHIVE_OK; - int type, tag, permset, id; + const char *s, *st; + int numfields, fields, n, r, sol, ret; + int type, types, tag, permset, id; + size_t len; char sep; + switch (want_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + numfields = 5; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + numfields = 6; + break; + default: + return (ARCHIVE_FATAL); + } + + ret = ARCHIVE_OK; + types = 0; + while (text != NULL && *text != '\0') { /* * Parse the fields out of the next entry, @@ -1072,7 +1649,7 @@ archive_acl_parse_l(struct archive_acl *acl, do { const char *start, *end; next_field(&text, &start, &end, &sep); - if (fields < 4) { + if (fields < numfields) { field[fields].start = start; field[fields].end = end; } @@ -1080,72 +1657,197 @@ archive_acl_parse_l(struct archive_acl *acl, } while (sep == ':'); /* Set remaining fields to blank. */ - for (n = fields; n < 4; ++n) + for (n = fields; n < numfields; ++n) field[n].start = field[n].end = NULL; - /* Check for a numeric ID in field 1 or 3. */ - id = -1; - isint(field[1].start, field[1].end, &id); - /* Field 3 is optional. */ - if (id == -1 && fields > 3) - isint(field[3].start, field[3].end, &id); - - /* - * Solaris extension: "defaultuser::rwx" is the - * default ACL corresponding to "user::rwx", etc. - */ - if (field[0].end - field[0].start > 7 - && memcmp(field[0].start, "default", 7) == 0) { - type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; - field[0].start += 7; - } else - type = default_type; + if (field[0].start != NULL && *(field[0].start) == '#') { + /* Comment, skip entry */ + continue; + } + n = 0; + sol = 0; + id = -1; + permset = 0; name.start = name.end = NULL; - if (prefix_c(field[0].start, field[0].end, "user")) { - if (!ismode(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_USER; - name = field[1]; + + if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* POSIX.1e ACLs */ + /* + * Default keyword "default:user::rwx" + * if found, we have one more field + * + * We also support old Solaris extension: + * "defaultuser::rwx" is the default ACL corresponding + * to "user::rwx", etc. valid only for first field + */ + s = field[0].start; + len = field[0].end - field[0].start; + if (*s == 'd' && (len == 1 || (len >= 7 + && memcmp((s + 1), "efault", 6) == 0))) { + type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + if (len > 7) + field[0].start += 7; + else + n = 1; } else - tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (prefix_c(field[0].start, field[0].end, "group")) { - if (!ismode(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_GROUP; + type = want_type; + + /* Check for a numeric ID in field n+1 or n+3. */ + isint(field[n + 1].start, field[n + 1].end, &id); + /* Field n+3 is optional. */ + if (id == -1 && fields > (n + 3)) + isint(field[n + 3].start, field[n + 3].end, + &id); + + tag = 0; + s = field[n].start; + st = field[n].start + 1; + len = field[n].end - field[n].start; + + switch (*s) { + case 'u': + if (len == 1 || (len == 4 + && memcmp(st, "ser", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case 'g': + if (len == 1 || (len == 5 + && memcmp(st, "roup", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 'o': + if (len == 1 || (len == 5 + && memcmp(st, "ther", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + case 'm': + if (len == 1 || (len == 4 + && memcmp(st, "ask", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_MASK; + break; + default: + break; + } + + switch (tag) { + case ARCHIVE_ENTRY_ACL_OTHER: + case ARCHIVE_ENTRY_ACL_MASK: + if (fields == (n + 2) + && field[n + 1].start < field[n + 1].end + && ismode(field[n + 1].start, + field[n + 1].end, &permset)) { + /* This is Solaris-style "other:rwx" */ + sol = 1; + } else if (fields == (n + 3) && + field[n + 1].start < field[n + 1].end) { + /* Invalid mask or other field */ + ret = ARCHIVE_WARN; + continue; + } + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (id != -1 || + field[n + 1].start < field[n + 1].end) { + name = field[n + 1]; + if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) + tag = ARCHIVE_ENTRY_ACL_USER; + else + tag = ARCHIVE_ENTRY_ACL_GROUP; + } + break; + default: + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + + /* + * Without "default:" we expect mode in field 3 + * Exception: Solaris other and mask fields + */ + if (permset == 0 && !ismode(field[n + 2 - sol].start, + field[n + 2 - sol].end, &permset)) { + /* Invalid mode, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + } else { + /* NFS4 ACLs */ + s = field[0].start; + len = field[0].end - field[0].start; + tag = 0; + + switch (len) { + case 4: + if (memcmp(s, "user", 4) == 0) + tag = ARCHIVE_ENTRY_ACL_USER; + break; + case 5: + if (memcmp(s, "group", 5) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case 6: + if (memcmp(s, "owner@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if (memcmp(s, "group@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 9: + if (memcmp(s, "everyone@", 9) == 0) + tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; + default: + break; + } + + if (tag == 0) { + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } else if (tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + n = 1; name = field[1]; + isint(name.start, name.end, &id); } else - tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (prefix_c(field[0].start, field[0].end, "other")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "other:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "other::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_OTHER; - } else if (prefix_c(field[0].start, field[0].end, "mask")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "mask:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "mask::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_MASK; - } else - return (ARCHIVE_WARN); + n = 0; + + if (!is_nfs4_perms(field[1 + n].start, + field[1 + n].end, &permset)) { + /* Invalid NFSv4 perms, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + if (!is_nfs4_flags(field[2 + n].start, + field[2 + n].end, &permset)) { + /* Invalid NFSv4 flags, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + s = field[3 + n].start; + len = field[3 + n].end - field[3 + n].start; + type = 0; + if (len == 4) { + if (memcmp(s, "deny", 4) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + } else if (len == 5) { + if (memcmp(s, "allow", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + else if (memcmp(s, "audit", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + else if (memcmp(s, "alarm", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + } + if (type == 0) { + /* Invalid entry type, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + isint(field[4 + n].start, field[4 + n].end, + &id); + } /* Add entry to the internal list. */ r = archive_acl_add_entry_len_l(acl, type, permset, @@ -1154,7 +1856,12 @@ archive_acl_parse_l(struct archive_acl *acl, return (r); if (r != ARCHIVE_OK) ret = ARCHIVE_WARN; + types |= type; } + + /* Reset ACL */ + archive_acl_reset(acl, types); + return (ret); } @@ -1219,6 +1926,112 @@ ismode(const char *start, const char *end, int *permset) return (1); } +/* + * Parse a string as a NFS4 ACL permission field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * permission characters, false otherwise + */ +static int +is_nfs4_perms(const char *start, const char *end, int *permset) +{ + const char *p = start; + + while (p < end) { + switch (*p++) { + case 'r': + *permset |= ARCHIVE_ENTRY_ACL_READ_DATA; + break; + case 'w': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA; + break; + case 'x': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case 'p': + *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA; + break; + case 'D': + *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD; + break; + case 'd': + *permset |= ARCHIVE_ENTRY_ACL_DELETE; + break; + case 'a': + *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES; + break; + case 'A': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES; + break; + case 'R': + *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS; + break; + case 'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS; + break; + case 'c': + *permset |= ARCHIVE_ENTRY_ACL_READ_ACL; + break; + case 'C': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL; + break; + case 'o': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER; + break; + case 's': + *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + break; + case '-': + break; + default: + return(0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL flags field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * flag characters, false otherwise + */ +static int +is_nfs4_flags(const char *start, const char *end, int *permset) +{ + const char *p = start; + + while (p < end) { + switch(*p++) { + case 'f': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT; + break; + case 'd': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT; + break; + case 'i': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY; + break; + case 'n': + *permset |= + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT; + break; + case 'S': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS; + break; + case 'F': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS; + break; + case 'I': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED; + break; + case '-': + break; + default: + return (0); + } + } + return (1); +} + /* * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated * to point to just after the separator. *start points to the first @@ -1254,25 +2067,3 @@ next_field(const char **p, const char **start, if (**p != '\0') (*p)++; } - -/* - * Return true if the characters [start...end) are a prefix of 'test'. - * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc. - */ -static int -prefix_c(const char *start, const char *end, const char *test) -{ - if (start == end) - return (0); - - if (*start++ != *test++) - return (0); - - while (start < end && *start++ == *test++) - ; - - if (start < end) - return (0); - - return (1); -} diff --git a/Utilities/cmlibarchive/libarchive/archive_acl_private.h b/Utilities/cmlibarchive/libarchive/archive_acl_private.h index 1421adbf8..ef0b0234c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_acl_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_acl_private.h @@ -56,6 +56,7 @@ struct archive_acl { void archive_acl_clear(struct archive_acl *); void archive_acl_copy(struct archive_acl *, struct archive_acl *); int archive_acl_count(struct archive_acl *, int); +int archive_acl_types(struct archive_acl *); int archive_acl_reset(struct archive_acl *, int); int archive_acl_next(struct archive *, struct archive_acl *, int, int *, int *, int *, int *, const char **); @@ -66,22 +67,17 @@ int archive_acl_add_entry_w_len(struct archive_acl *, int archive_acl_add_entry_len(struct archive_acl *, int, int, int, int, const char *, size_t); -const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int); -int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *, +wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int, + struct archive *); +char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int, struct archive_string_conv *); /* - * Private ACL parser. This is private because it handles some - * very weird formats that clients should not be messing with. - * Clients should only deal with their platform-native formats. - * Because of the need to support many formats cleanly, new arguments - * are likely to get added on a regular basis. Clients who try to use - * this interface are likely to be surprised when it changes. + * ACL text parser. */ -int archive_acl_parse_w(struct archive_acl *, - const wchar_t *, int /* type */); -int archive_acl_parse_l(struct archive_acl *, - const char *, int /* type */, - struct archive_string_conv *); +int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */, + int /* type */); +int archive_acl_from_text_l(struct archive_acl *, const char * /* text */, + int /* type */, struct archive_string_conv *); #endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */ diff --git a/Utilities/cmlibarchive/libarchive/archive_cryptor.c b/Utilities/cmlibarchive/libarchive/archive_cryptor.c index 2a51dfe1d..ced52fd70 100644 --- a/Utilities/cmlibarchive/libarchive/archive_cryptor.c +++ b/Utilities/cmlibarchive/libarchive/archive_cryptor.c @@ -302,7 +302,8 @@ aes_ctr_release(archive_crypto_ctx *ctx) static int aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) { - ctx->ctx = EVP_CIPHER_CTX_new(); + if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL) + return -1; switch (key_len) { case 16: ctx->type = EVP_aes_128_ecb(); break; diff --git a/Utilities/cmlibarchive/libarchive/archive_digest_private.h b/Utilities/cmlibarchive/libarchive/archive_digest_private.h index b58ffb348..b4fd6ca22 100644 --- a/Utilities/cmlibarchive/libarchive/archive_digest_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_digest_private.h @@ -143,6 +143,7 @@ defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA512_WIN) +#include #include typedef struct { int valid; diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c index 4ac196608..10eff11b2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -248,10 +249,9 @@ archive_entry_new2(struct archive *a) { struct archive_entry *entry; - entry = (struct archive_entry *)malloc(sizeof(*entry)); + entry = (struct archive_entry *)calloc(1, sizeof(*entry)); if (entry == NULL) return (NULL); - memset(entry, 0, sizeof(*entry)); entry->archive = a; return (entry); } @@ -1441,6 +1441,15 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry, type, permset, tag, id, name, wcslen(name)); } +/* + * Return a bitmask of ACL types in an archive entry ACL list + */ +int +archive_entry_acl_types(struct archive_entry *entry) +{ + return (archive_acl_types(&entry->acl)); +} + /* * Return a count of entries matching "want_type". */ @@ -1478,34 +1487,121 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, } /* - * Generate a text version of the ACL. The flags parameter controls + * Generate a text version of the ACL. The flags parameter controls * the style of the generated ACL. */ +wchar_t * +archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len, + int flags) +{ + return (archive_acl_to_text_w(&entry->acl, len, flags, + entry->archive)); +} + +char * +archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len, + int flags) +{ + return (archive_acl_to_text_l(&entry->acl, len, flags, NULL)); +} + +char * +_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len, + int flags, struct archive_string_conv *sc) +{ + return (archive_acl_to_text_l(&entry->acl, len, flags, sc)); +} + +/* + * ACL text parser. + */ +int +archive_entry_acl_from_text_w(struct archive_entry *entry, + const wchar_t *wtext, int type) +{ + return (archive_acl_from_text_w(&entry->acl, wtext, type)); +} + +int +archive_entry_acl_from_text(struct archive_entry *entry, + const char *text, int type) +{ + return (archive_acl_from_text_l(&entry->acl, text, type, NULL)); +} + +int +_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text, + int type, struct archive_string_conv *sc) +{ + return (archive_acl_from_text_l(&entry->acl, text, type, sc)); +} + +/* Deprecated */ +static int +archive_entry_acl_text_compat(int *flags) +{ + if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0) + return (1); + + /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */ + if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) + *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID; + + /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */ + if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) + *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA; + + return (0); +} + +/* Deprecated */ const wchar_t * archive_entry_acl_text_w(struct archive_entry *entry, int flags) { - const wchar_t *r; - r = archive_acl_text_w(entry->archive, &entry->acl, flags); - if (r == NULL && errno == ENOMEM) - __archive_errx(1, "No memory"); - return (r); + if (entry->acl.acl_text_w != NULL) { + free(entry->acl.acl_text_w); + entry->acl.acl_text_w = NULL; + } + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl, + NULL, flags, entry->archive); + return (entry->acl.acl_text_w); } +/* Deprecated */ const char * archive_entry_acl_text(struct archive_entry *entry, int flags) { - const char *p; - if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0 - && errno == ENOMEM) - __archive_errx(1, "No memory"); - return (p); + if (entry->acl.acl_text != NULL) { + free(entry->acl.acl_text); + entry->acl.acl_text = NULL; + } + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL, + flags, NULL); + + return (entry->acl.acl_text); } +/* Deprecated */ int _archive_entry_acl_text_l(struct archive_entry *entry, int flags, const char **acl_text, size_t *len, struct archive_string_conv *sc) { - return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc)); + if (entry->acl.acl_text != NULL) { + free(entry->acl.acl_text); + entry->acl.acl_text = NULL; + } + + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, + (ssize_t *)len, flags, sc); + + *acl_text = entry->acl.acl_text; + + return (0); } /* @@ -1553,7 +1649,10 @@ static struct flag { { "nosappnd", L"nosappnd", SF_APPEND, 0 }, { "nosappend", L"nosappend", SF_APPEND, 0 }, #endif -#ifdef EXT2_APPEND_FL /* 'a' */ +#if defined(FS_APPEND_FL) /* 'a' */ + { "nosappnd", L"nosappnd", FS_APPEND_FL, 0 }, + { "nosappend", L"nosappend", FS_APPEND_FL, 0 }, +#elif defined(EXT2_APPEND_FL) /* 'a' */ { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 }, { "nosappend", L"nosappend", EXT2_APPEND_FL, 0 }, #endif @@ -1566,7 +1665,11 @@ static struct flag { { "noschange", L"noschange", SF_IMMUTABLE, 0 }, { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 }, #endif -#ifdef EXT2_IMMUTABLE_FL /* 'i' */ +#if defined(FS_IMMUTABLE_FL) /* 'i' */ + { "noschg", L"noschg", FS_IMMUTABLE_FL, 0 }, + { "noschange", L"noschange", FS_IMMUTABLE_FL, 0 }, + { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0 }, +#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */ { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 }, { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 }, { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 }, @@ -1590,7 +1693,9 @@ static struct flag { #ifdef UF_NODUMP { "nodump", L"nodump", 0, UF_NODUMP}, #endif -#ifdef EXT2_NODUMP_FL /* 'd' */ +#if defined(FS_NODUMP_FL) /* 'd' */ + { "nodump", L"nodump", 0, FS_NODUMP_FL}, +#elif defined(EXT2_NODUMP_FL) /* 'd' */ { "nodump", L"nodump", 0, EXT2_NODUMP_FL}, #endif #ifdef UF_OPAQUE @@ -1603,65 +1708,124 @@ static struct flag { #ifdef UF_COMPRESSED { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 }, #endif -#ifdef EXT2_UNRM_FL +#if defined(FS_UNRM_FL) + { "nouunlink", L"nouunlink", FS_UNRM_FL, 0}, +#elif defined(EXT2_UNRM_FL) { "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0}, #endif -#ifdef EXT2_BTREE_FL +#if defined(FS_BTREE_FL) + { "nobtree", L"nobtree", FS_BTREE_FL, 0 }, +#elif defined(EXT2_BTREE_FL) { "nobtree", L"nobtree", EXT2_BTREE_FL, 0 }, #endif -#ifdef EXT2_ECOMPR_FL +#if defined(FS_ECOMPR_FL) + { "nocomperr", L"nocomperr", FS_ECOMPR_FL, 0 }, +#elif defined(EXT2_ECOMPR_FL) { "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 }, #endif -#ifdef EXT2_COMPR_FL /* 'c' */ +#if defined(FS_COMPR_FL) /* 'c' */ + { "nocompress", L"nocompress", FS_COMPR_FL, 0 }, +#elif defined(EXT2_COMPR_FL) /* 'c' */ { "nocompress", L"nocompress", EXT2_COMPR_FL, 0 }, #endif -#ifdef EXT2_NOATIME_FL /* 'A' */ +#if defined(FS_NOATIME_FL) /* 'A' */ + { "noatime", L"noatime", 0, FS_NOATIME_FL}, +#elif defined(EXT2_NOATIME_FL) /* 'A' */ { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, #endif -#ifdef EXT2_DIRTY_FL +#if defined(FS_DIRTY_FL) + { "nocompdirty",L"nocompdirty", FS_DIRTY_FL, 0}, +#elif defined(EXT2_DIRTY_FL) { "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0}, #endif -#ifdef EXT2_COMPRBLK_FL -#ifdef EXT2_NOCOMPR_FL +#if defined(FS_COMPRBLK_FL) +#if defined(FS_NOCOMPR_FL) + { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, FS_NOCOMPR_FL}, +#else + { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, 0}, +#endif +#elif defined(EXT2_COMPRBLK_FL) +#if defined(EXT2_NOCOMPR_FL) { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL}, #else { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0}, #endif #endif -#ifdef EXT2_DIRSYNC_FL +#if defined(FS_DIRSYNC_FL) + { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0}, +#elif defined(EXT2_DIRSYNC_FL) { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0}, #endif -#ifdef EXT2_INDEX_FL +#if defined(FS_INDEX_FL) + { "nohashidx", L"nohashidx", FS_INDEX_FL, 0}, +#elif defined(EXT2_INDEX_FL) { "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0}, #endif -#ifdef EXT2_IMAGIC_FL +#if defined(FS_IMAGIC_FL) + { "noimagic", L"noimagic", FS_IMAGIC_FL, 0}, +#elif defined(EXT2_IMAGIC_FL) { "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0}, #endif -#ifdef EXT3_JOURNAL_DATA_FL +#if defined(FS_JOURNAL_DATA_FL) + { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0}, +#elif defined(EXT3_JOURNAL_DATA_FL) { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0}, #endif -#ifdef EXT2_SECRM_FL +#if defined(FS_SECRM_FL) + { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0}, +#elif defined(EXT2_SECRM_FL) { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0}, #endif -#ifdef EXT2_SYNC_FL +#if defined(FS_SYNC_FL) + { "nosync", L"nosync", FS_SYNC_FL, 0}, +#elif defined(EXT2_SYNC_FL) { "nosync", L"nosync", EXT2_SYNC_FL, 0}, #endif -#ifdef EXT2_NOTAIL_FL +#if defined(FS_NOTAIL_FL) + { "notail", L"notail", 0, FS_NOTAIL_FL}, +#elif defined(EXT2_NOTAIL_FL) { "notail", L"notail", 0, EXT2_NOTAIL_FL}, #endif -#ifdef EXT2_TOPDIR_FL +#if defined(FS_TOPDIR_FL) + { "notopdir", L"notopdir", FS_TOPDIR_FL, 0}, +#elif defined(EXT2_TOPDIR_FL) { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0}, #endif -#ifdef EXT2_RESERVED_FL +#ifdef FS_ENCRYPT_FL + { "noencrypt", L"noencrypt", FS_ENCRYPT_FL, 0}, +#endif +#ifdef FS_HUGE_FILE_FL + { "nohugefile", L"nohugefile", FS_HUGE_FILE_FL, 0}, +#endif +#ifdef FS_EXTENT_FL + { "noextent", L"noextent", FS_EXTENT_FL, 0}, +#endif +#ifdef FS_EA_INODE_FL + { "noeainode", L"noeainode", FS_EA_INODE_FL, 0}, +#endif +#ifdef FS_EOFBLOCKS_FL + { "noeofblocks",L"noeofblocks", FS_EOFBLOCKS_FL, 0}, +#endif +#ifdef FS_NOCOW_FL + { "nocow", L"nocow", FS_NOCOW_FL, 0}, +#endif +#ifdef FS_INLINE_DATA_FL + { "noinlinedata",L"noinlinedata", FS_INLINE_DATA_FL, 0}, +#endif +#ifdef FS_PROJINHERIT_FL + { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0}, +#endif +#if defined(FS_RESERVED_FL) + { "noreserved", L"noreserved", FS_RESERVED_FL, 0}, +#elif defined(EXT2_RESERVED_FL) { "noreserved", L"noreserved", EXT2_RESERVED_FL, 0}, #endif - { NULL, NULL, 0, 0 } }; diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index 81cd425e4..6e0225b04 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3002001 +#define ARCHIVE_VERSION_NUMBER 3003001 /* * Note: archive_entry.h is for use outside of libarchive; the @@ -65,6 +66,27 @@ typedef int64_t la_int64_t; # endif #endif +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + /* Get a suitable definition for mode_t */ #if ARCHIVE_VERSION_NUMBER >= 3999000 /* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ @@ -104,6 +126,9 @@ typedef int64_t la_int64_t; # define __LA_DECL #endif +/* CMake uses some deprecated APIs to build with old libarchive versions. */ +#define __LA_DEPRECATED + #ifdef __cplusplus extern "C" { #endif @@ -420,6 +445,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi /* * Inheritance values (NFS4 ACLs only); included in permset. */ +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000 #define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 #define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 #define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 @@ -433,15 +459,16 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ - | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS) + | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) /* We need to be able to specify combinations of these. */ -#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */ -#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */ -#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */ -#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */ -#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */ -#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */ #define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) #define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ @@ -492,21 +519,51 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type * Construct a text-format ACL. The flags argument is a bitmask that * can include any of the following: * + * Flags only for archive entries with POSIX.1e ACL: * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. - * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries. - * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in - * each ACL entry. ('star' introduced this for POSIX.1e, this flag - * also applies to NFS4.) * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each - * default ACL entry, as used in old Solaris ACLs. + * default ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and + * "mask" entries. + * + * Flags only for archive entries with NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for + * unset permissions and flags in NFSv4 ACL permission and flag fields + * + * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in + * each ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma + * instead of newline. */ -#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 -#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 +#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001 +#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002 +#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004 +#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008 +#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 + +__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, + const wchar_t * /* wtext */, int /* type */); +__LA_DECL int archive_entry_acl_from_text(struct archive_entry *, + const char * /* text */, int /* type */); + +/* Deprecated constants */ +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 + +/* Deprecated functions */ __LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, - int /* flags */); + int /* flags */) __LA_DEPRECATED; __LA_DECL const char *archive_entry_acl_text(struct archive_entry *, - int /* flags */); + int /* flags */) __LA_DEPRECATED; + +/* Return bitmask of ACL types in an archive entry */ +__LA_DECL int archive_entry_acl_types(struct archive_entry *); /* Return a count of entries matching 'want_type' */ __LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 index 5aff99682..c5115f727 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 @@ -1,4 +1,5 @@ .\" Copyright (c) 2010 Joerg Sonnenberger +.\" Copyright (c) 2016 Martin Matuska .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -22,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 2, 2012 +.Dd February 15, 2017 .Dt ARCHIVE_ENTRY_ACL 3 .Os .Sh NAME @@ -30,10 +31,14 @@ .Nm archive_entry_acl_add_entry_w , .Nm archive_entry_acl_clear , .Nm archive_entry_acl_count , +.Nm archive_entry_acl_from_text , +.Nm archive_entry_acl_from_text_w, .Nm archive_entry_acl_next , .Nm archive_entry_acl_next_w , .Nm archive_entry_acl_reset , -.Nm archive_entry_acl_text_w +.Nm archive_entry_acl_to_text , +.Nm archive_entry_acl_to_text_w , +.Nm archive_entry_acl_types .Nd functions for manipulating Access Control Lists in archive entry descriptions .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -62,6 +67,18 @@ Streaming Archive Library (libarchive, -larchive) .Ft int .Fn archive_entry_acl_count "struct archive_entry *a" "int type" .Ft int +.Fo archive_entry_acl_from_text +.Fa "struct archive_entry *a" +.Fa "const char *text" +.Fa "int type" +.Fc +.Ft int +.Fo archive_entry_acl_from_text_w +.Fa "struct archive_entry *a" +.Fa "const wchar_t *text" +.Fa "int type" +.Fc +.Ft int .Fo archive_entry_acl_next .Fa "struct archive_entry *a" .Fa "int type" @@ -83,31 +100,48 @@ Streaming Archive Library (libarchive, -larchive) .Fc .Ft int .Fn archive_entry_acl_reset "struct archive_entry *a" "int type" -.Ft const wchar_t * -.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags" +.Ft char * +.Fo archive_entry_acl_to_text +.Fa "struct archive_entry *a" +.Fa "ssize_t *len_p" +.Fa "int flags" +.Fc +.Ft wchar_t * +.Fo archive_entry_acl_to_text_w +.Fa "struct archive_entry *a" +.Fa "ssize_t *len_p" +.Fa "int flags" +.Fc +.Ft int +.Fn archive_entry_acl_types "struct archive_entry *a" .\" enum? .Sh DESCRIPTION -An -.Dq Access Control List -is a generalisation of the classic Unix permission system. +The +.Dq Access Control Lists (ACLs) +extend the standard Unix perssion model. The ACL interface of .Nm libarchive -is derived from the POSIX.1e draft, but restricted to simplify dealing -with practical implementations in various Operating Systems and archive formats. -.Pp -An ACL consists of a number of independent entries. +supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is restricted by +various levels of ACL support in operating systems, file systems and archive +formats. +.Ss POSIX.1e Access Control Lists +A POSIX.1e ACL consists of a number of independent entries. Each entry specifies the permission set as bitmask of basic permissions. -Valid permissions are: +Valid permissions in the +.Fa permset +are: .Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE" -.It Dv ARCHIVE_ENTRY_ACL_EXECUTE -.It Dv ARCHIVE_ENTRY_ACL_WRITE -.It Dv ARCHIVE_ENTRY_ACL_READ +.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r ) +.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w ) +.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x ) .El The permissions correspond to the normal Unix permissions. .Pp -The tag specifies the principal to which the permission applies. +The +.Fa tag +specifies the principal to which the permission applies. Valid values are: -.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" .It Dv ARCHIVE_ENTRY_ACL_USER The user specified by the name field. .It Dv ARCHIVE_ENTRY_ACL_USER_OBJ @@ -119,8 +153,9 @@ The group who owns the file. .It Dv ARCHIVE_ENTRY_ACL_MASK The maximum permissions to be obtained via group permissions. .It Dv ARCHIVE_ENTRY_ACL_OTHER -Any principal who doesn't have a user or group entry. +Any principal who is not file owner or a member of the owning group. .El +.Pp The principals .Dv ARCHIVE_ENTRY_ACL_USER_OBJ , .Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ @@ -129,19 +164,123 @@ and are equivalent to user, group and other in the classic Unix permission model and specify non-extended ACL entries. .Pp -All files have an access ACL +All files with have an access ACL .Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS . This specifies the permissions required for access to the file itself. Directories have an additional ACL .Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT , which controls the initial access ACL for newly created directory entries. +.Ss NFSv4 Access Control Lists +A NFSv4 ACL consists of multiple individual entries called Access Control +Entries (ACEs). +.Pp +There are four possible types of a NFSv4 ACE: +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW +Allow principal to perform actions requiring given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY +Prevent principal from performing actions requiring given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT +Log access attempts by principal which require given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM +Trigger a system alarm on access attempts by principal which require given +permissions. +.El +.Pp +The +.Fa tag +specifies the principal to which the permission applies. +Valid values are: +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" +.It Dv ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +.It Dv ARCHIVE_ENTRY_ACL_GROUP +The group specied by the name field. +.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group who owns the file. +.It Dv ARCHIVE_ENTRY_ACL_EVERYONE +Any principal who is not file owner or a member of the owning group. +.El +.Pp +Entries with the +.Dv ARCHIVE_ENTRY_ACL_USER +or +.Dv ARCHIVE_ENTRY_ACL_GROUP +tag store the user and group name in the +.Fa name +string and optionally the user or group ID in the +.Fa qualifier +integer. +.Pp +NFSv4 ACE permissions and flags are stored in the same +.Fa permset +bitfield. Some permissions share the same constant and permission character but +have different effect on directories than on files. The following ACE +permissions are supported: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r ) +Read data (file). +.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r ) +List entries (directory). +.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w ) +Write data (file). +.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w ) +Create files (directory). +.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x ) +Execute file or change into a directory. +.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p ) +Append data (file). +.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p ) +Create subdirectories (directory). +.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D ) +Remove files and subdirectories inside a directory. +.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d ) +Remove file or directory. +.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a ) +Read file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A ) +Write file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R ) +Read named file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W ) +Write named file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c ) +Read file or directory ACL. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C ) +Write file or directory ACL. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o ) +Change owner of a file or directory. +.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s ) +Use synchronous I/O. +.El .Pp +The following NFSv4 ACL inheritance flags are supported: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f ) +Inherit parent directory ACE to files. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d ) +Inherit parent directory ACE to subdirectories. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i ) +Only inherit, do not apply the permission on the directory itself. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n ) +Do not propagate inherit flags. Only first-level entries inherit ACLs. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S ) +Trigger alarm or audit on succesful access. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F ) +Trigger alarm or audit on failed access. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I ) +Mark that ACE was inherited. +.El +.Ss Functions .Fn archive_entry_acl_add_entry and .Fn archive_entry_acl_add_entry_w add a single ACL entry. For the access ACL and non-extended principals, the classic Unix permissions -are updated. +are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL +entries. .Pp .Fn archive_entry_acl_clear removes all ACL entries and resets the enumeration pointer. @@ -150,14 +289,58 @@ removes all ACL entries and resets the enumeration pointer. counts the ACL entries that have the given type mask. .Fa type can be the bitwise-or of -.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS -and -.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT . -If +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.El +for POSIX.1e ACLs and +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY +.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM +.El +for NFSv4 ACLs. For POSIX.1e ACLs if .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS is included and at least one extended ACL entry is found, the three non-extened ACLs are added. .Pp +.Fn archive_entry_acl_from_text +and +.Fn archive_entry_acl_from_text_w +add new +.Pq or merge with existing +ACL entries from +.Pq wide +text. The argument +.Fa type +may take one of the following values: +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 +.El +Supports all formats that can be created with +.Fn archive_entry_acl_to_text +or respective +.Fn archive_entry_acl_to_text_w . +Existing ACL entries are preserved. To get a clean new ACL from text +.Fn archive_entry_acl_clear +must be called first. Entries prefixed with +.Dq default: +are treated as +.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +unless +.Fa type +is +.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 . +Invalid entries, non-parseable ACL entries and entries beginning with +the +.Sq # +character +.Pq comments +are skipped. +.Pp .Fn archive_entry_acl_next and .Fn archive_entry_acl_next_w @@ -179,29 +362,81 @@ or set using Otherwise, the function returns the same value as .Fn archive_entry_acl_count . .Pp -.Fn archive_entry_acl_text_w -converts the ACL entries for the given type mask into a wide string. -In addition to the normal type flags, -.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID +.Fn archive_entry_acl_to_text and -.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT -can be specified to further customize the result. -The returned long string is valid until the next call to -.Fn archive_entry_acl_clear , -.Fn archive_entry_acl_add_entry , -.Fn archive_entry_acl_add_entry_w +.Fn archive_entry_acl_to_text_w +convert the ACL entries for the given type into a +.Pq wide +string of ACL entries separated by newline. If the the pointer +.Fa len_p +is not NULL, then the function shall return the length of the string +.Pq not including the NULL terminator +in the location pointed to by +.Fa len_p . +The +.Fa flag +argument is a bitwise-or. +.Pp +The following flags are effective only on POSIX.1e ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +Output access ACLs. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +Output POSIX.1e default ACLs. +.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT +Prefix each default ACL entry with the word +.Dq default: . +.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS +The mask and other ACLs don not contain a double colon. +.El +.Pp +The following flags are effecive only on NFSv4 ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT +Do not output minus characters for unset permissions and flags in NFSv4 ACL +permission and flag fields. +.El +.Pp +The following flags are effective on both POSIX.1e and NFSv4 ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID +Add an additional colon-separated field containing the user or group id. +.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA +Separate ACL entries with comma instead of newline. +.El +.Pp +If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned. +It the entry contains POSIX.1e ACLs and none of the flags +.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS or -.Fn archive_entry_acl_text_w . +.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +are specified, both access and default entries are returned and default entries +are prefixed with +.Dq default: . +.Pp +.Fn archive_entry_acl_types +get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4 +ACL entries cannot be mixed, this function is a very efficient way to detect if +an ACL already contains POSIX.1e or NFSv4 ACL entries. .Sh RETURN VALUES .Fn archive_entry_acl_count and .Fn archive_entry_acl_reset returns the number of ACL entries that match the given type mask. -If the type mask includes +For POSIX.1e ACLS if the type mask includes .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS and at least one extended ACL entry exists, the three classic Unix permissions are counted. .Pp +.Fn archive_entry_acl_from_text +and +.Fn archive_entry_acl_from_text_w +return +.Dv ARCHIVE_OK +if all entries were successfully parsed and +.Dv ARCHIVE_WARN +if one or more entries were invalid or non-parseable. +.Pp .Fn archive_entry_acl_next and .Fn archive_entry_acl_next_w @@ -216,20 +451,16 @@ if .Fn archive_entry_acl_reset has not been called first. .Pp -.Fn archive_entry_text_w -returns a wide string representation of the ACL entrise matching the -given type mask. -The returned long string is valid until the next call to -.Fn archive_entry_acl_clear , -.Fn archive_entry_acl_add_entry , -.Fn archive_entry_acl_add_entry_w -or -.Fn archive_entry_acl_text_w . +.Fn archive_entry_acl_to_text +returns a string representing the ACL entries matching the given type and +flags on success or NULL on error. +.Pp +.Fn archive_entry_acl_to_text_w +returns a wide string representing the ACL entries matching the given type +and flags on success or NULL on error. +.Pp +.Fn archive_entry_acl_types +returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries. .Sh SEE ALSO -.Xr archive_entry 3 -.Xr libarchive 3 , -.Sh BUGS -.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID -and -.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT -are not documented. +.Xr archive_entry 3 , +.Xr libarchive 3 diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_locale.h b/Utilities/cmlibarchive/libarchive/archive_entry_locale.h index 02e024ae2..44550c51e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_locale.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry_locale.h @@ -63,9 +63,13 @@ int _archive_entry_uname_l(struct archive_entry *, const char **, size_t *, struct archive_string_conv *); #define archive_entry_acl_text_l _archive_entry_acl_text_l int _archive_entry_acl_text_l(struct archive_entry *, int, - const char **, size_t *, struct archive_string_conv *); - - +const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED; +#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l +char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int, + struct archive_string_conv *); +#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l +int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text, + int type, struct archive_string_conv *); #define archive_entry_copy_gname_l _archive_entry_copy_gname_l int _archive_entry_copy_gname_l(struct archive_entry *, const char *, size_t, struct archive_string_conv *); diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c b/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c index 16cb3f7bb..af2517a32 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c @@ -80,7 +80,7 @@ archive_entry_strmode(struct archive_entry *entry) if (mode & 0001) bp[9] = 't'; else bp[9] = 'T'; } - if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)) + if (archive_entry_acl_types(entry) != 0) bp[10] = '+'; return (bp); diff --git a/Utilities/cmlibarchive/libarchive/archive_hmac.c b/Utilities/cmlibarchive/libarchive/archive_hmac.c index 1e0ae283b..f29965577 100644 --- a/Utilities/cmlibarchive/libarchive/archive_hmac.c +++ b/Utilities/cmlibarchive/libarchive/archive_hmac.c @@ -76,6 +76,10 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) +#ifndef BCRYPT_HASH_REUSABLE_FLAG +# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 +#endif + static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) { diff --git a/Utilities/cmlibarchive/libarchive/archive_match.c b/Utilities/cmlibarchive/libarchive/archive_match.c index 4c41badf1..be72066ea 100644 --- a/Utilities/cmlibarchive/libarchive/archive_match.c +++ b/Utilities/cmlibarchive/libarchive/archive_match.c @@ -471,7 +471,7 @@ archive_match_path_excluded(struct archive *_a, } /* - * Utilty functions to get statistic information for inclusion patterns. + * Utility functions to get statistic information for inclusion patterns. */ int archive_match_path_unmatched_inclusions(struct archive *_a) @@ -655,7 +655,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist, } } - /* If something error happend, report it immediately. */ + /* If an error occurred, report it immediately. */ if (r < ARCHIVE_OK) { archive_copy_error(&(a->archive), ar); archive_read_free(ar); @@ -1270,7 +1270,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype, #endif /* _WIN32 && !__CYGWIN__ */ /* - * Call back funtions for archive_rb. + * Call back functions for archive_rb. */ static int cmp_node_mbs(const struct archive_rb_node *n1, @@ -1405,7 +1405,7 @@ add_entry(struct archive_match *a, int flag, &(a->exclusion_tree), pathname); /* - * We always overwrite comparison condision. + * We always overwrite comparison condition. * If you do not want to overwrite it, you should not * call archive_match_exclude_entry(). We cannot know * what behavior you really expect since overwriting @@ -1481,7 +1481,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry) if (nsec == a->older_ctime_nsec && (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL) == 0) - return (1); /* Eeual, skip it. */ + return (1); /* Equal, skip it. */ } } if (a->newer_mtime_filter) { @@ -1513,7 +1513,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry) } } - /* If there is no excluson list, include the file. */ + /* If there is no exclusion list, include the file. */ if (a->exclusion_entry_list.count == 0) return (0); @@ -1700,7 +1700,7 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) break; } - /* Add oowner id. */ + /* Add owner id. */ if (i == ids->count) ids->ids[ids->count++] = id; else if (ids->ids[i] != id) { diff --git a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h index 0e97e2766..43a3ccc52 100644 --- a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h @@ -33,10 +33,7 @@ #include /* memset */ static inline EVP_MD_CTX *EVP_MD_CTX_new(void) { - EVP_MD_CTX *ctx = (EVP_MD_CTX *)malloc(sizeof(EVP_MD_CTX)); - if (ctx != NULL) { - memset(ctx, 0, sizeof(*ctx)); - } + EVP_MD_CTX *ctx = (EVP_MD_CTX *)calloc(1, sizeof(EVP_MD_CTX)); return ctx; } diff --git a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h index d4ae0d174..2deeb5f55 100644 --- a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h @@ -33,11 +33,7 @@ #include /* memset */ static inline HMAC_CTX *HMAC_CTX_new(void) { - HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof(HMAC_CTX)); - if (ctx != NULL) { - memset(ctx, 0, sizeof(*ctx)); - HMAC_CTX_init(ctx); - } + HMAC_CTX *ctx = (HMAC_CTX *)calloc(1, sizeof(HMAC_CTX)); return ctx; } diff --git a/Utilities/cmlibarchive/libarchive/archive_options.c b/Utilities/cmlibarchive/libarchive/archive_options.c index dbf3e80e9..6496025a5 100644 --- a/Utilities/cmlibarchive/libarchive/archive_options.c +++ b/Utilities/cmlibarchive/libarchive/archive_options.c @@ -26,6 +26,10 @@ #include "archive_platform.h" __FBSDID("$FreeBSD$"); +#ifdef HAVE_ERRNO_H +#include +#endif + #include "archive_options_private.h" static const char * @@ -105,8 +109,11 @@ _archive_set_options(struct archive *a, const char *options, if (options == NULL || options[0] == '\0') return ARCHIVE_OK; - data = (char *)malloc(strlen(options) + 1); - strcpy(data, options); + if ((data = strdup(options)) == NULL) { + archive_set_error(a, + ENOMEM, "Out of memory adding file to list"); + return (ARCHIVE_FATAL); + } s = (const char *)data; do { diff --git a/Utilities/cmlibarchive/libarchive/archive_platform.h b/Utilities/cmlibarchive/libarchive/archive_platform.h index 08a384c0b..47d144b05 100644 --- a/Utilities/cmlibarchive/libarchive/archive_platform.h +++ b/Utilities/cmlibarchive/libarchive/archive_platform.h @@ -152,8 +152,25 @@ * acl_set_file(), and ACL_USER, we assume it has the rest of the * POSIX.1e draft functions used in archive_read_extract.c. */ -#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER +#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE +#if HAVE_ACL_USER #define HAVE_POSIX_ACL 1 +#elif HAVE_ACL_TYPE_EXTENDED +#define HAVE_DARWIN_ACL 1 +#endif +#endif + +/* + * If this platform has , acl_get(), facl_get(), acl_set(), + * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions + */ +#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T +#define HAVE_SUN_ACL 1 +#endif + +/* Define if platform supports NFSv4 ACLs */ +#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL +#define HAVE_NFS4_ACL 1 #endif /* @@ -164,6 +181,15 @@ #define CAN_RESTORE_METADATA_FD #endif +/* + * glibc 2.24 deprecates readdir_r + */ +#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) +#define USE_READDIR_R 1 +#else +#undef USE_READDIR_R +#endif + /* Set up defaults for internal error codes. */ #ifndef ARCHIVE_ERRNO_FILE_FORMAT #if HAVE_EFTYPE diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h index 3a6b9eb41..06c99e828 100644 --- a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h @@ -19,7 +19,7 @@ If you need the compatibility with original PPMd var.H, you can use external Ran #define PPMD7_MAX_ORDER 64 #define PPMD7_MIN_MEM_SIZE (1 << 11) -#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) +#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3) struct CPpmd7_Context_; diff --git a/Utilities/cmlibarchive/libarchive/archive_random.c b/Utilities/cmlibarchive/libarchive/archive_random.c index fcea6c6d0..90ee7c626 100644 --- a/Utilities/cmlibarchive/libarchive/archive_random.c +++ b/Utilities/cmlibarchive/libarchive/archive_random.c @@ -80,7 +80,7 @@ archive_random(void *buf, size_t nbytes) success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - if (!success && GetLastError() == NTE_BAD_KEYSET) { + if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) { success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET); } diff --git a/Utilities/cmlibarchive/libarchive/archive_rb.c b/Utilities/cmlibarchive/libarchive/archive_rb.c index 5b5da2034..cf58ac335 100644 --- a/Utilities/cmlibarchive/libarchive/archive_rb.c +++ b/Utilities/cmlibarchive/libarchive/archive_rb.c @@ -312,7 +312,7 @@ __archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt, father = RB_FATHER(self); if (RB_BLACK_P(father)) { /* - * If our greatgrandpa is black, we're done. + * If our great-grandpa is black, we're done. */ return; } diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c index 0bbacc8f1..d1fecebfd 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read.c +++ b/Utilities/cmlibarchive/libarchive/archive_read.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2 static int choose_filters(struct archive_read *); static int choose_format(struct archive_read *); +static int close_filters(struct archive_read *); static struct archive_vtable *archive_read_vtable(void); static int64_t _archive_filter_bytes(struct archive *, int); static int _archive_filter_code(struct archive *, int); @@ -528,7 +529,7 @@ archive_read_open1(struct archive *_a) { slot = choose_format(a); if (slot < 0) { - __archive_read_close_filters(a); + close_filters(a); a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } @@ -582,7 +583,6 @@ choose_filters(struct archive_read *a) /* Verify the filter by asking it for some data. */ __archive_read_filter_ahead(a->filter, 1, &avail); if (avail < 0) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } @@ -601,7 +601,6 @@ choose_filters(struct archive_read *a) a->filter = filter; r = (best_bidder->init)(a->filter); if (r != ARCHIVE_OK) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } @@ -765,7 +764,7 @@ archive_read_header_position(struct archive *_a) * we cannot say whether there are encrypted entries, then * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. * In general, this function will return values below zero when the - * reader is uncertain or totally uncapable of encryption support. + * reader is uncertain or totally incapable of encryption support. * When this function returns 0 you can be sure that the reader * supports encryption detection but no encrypted entries have * been found yet. @@ -986,8 +985,8 @@ _archive_read_data_block(struct archive *_a, return (a->format->read_data)(a, buff, size, offset); } -int -__archive_read_close_filters(struct archive_read *a) +static int +close_filters(struct archive_read *a) { struct archive_read_filter *f = a->filter; int r = ARCHIVE_OK; @@ -1010,6 +1009,9 @@ __archive_read_close_filters(struct archive_read *a) void __archive_read_free_filters(struct archive_read *a) { + /* Make sure filters are closed and their buffers are freed */ + close_filters(a); + while (a->filter != NULL) { struct archive_read_filter *t = a->filter->upstream; free(a->filter); @@ -1052,7 +1054,7 @@ _archive_read_close(struct archive *_a) /* TODO: Clean up the formatters. */ /* Release the filter objects. */ - r1 = __archive_read_close_filters(a); + r1 = close_filters(a); if (r1 < r) r = r1; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c index f67f1ebc6..cf821b5d4 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c @@ -125,7 +125,7 @@ void __archive_read_reset_passphrase(struct archive_read *a) { - a->passphrases.candiate = -1; + a->passphrases.candidate = -1; } /* @@ -137,31 +137,31 @@ __archive_read_next_passphrase(struct archive_read *a) struct archive_read_passphrase *p; const char *passphrase; - if (a->passphrases.candiate < 0) { + if (a->passphrases.candidate < 0) { /* Count out how many passphrases we have. */ int cnt = 0; for (p = a->passphrases.first; p != NULL; p = p->next) cnt++; - a->passphrases.candiate = cnt; + a->passphrases.candidate = cnt; p = a->passphrases.first; - } else if (a->passphrases.candiate > 1) { + } else if (a->passphrases.candidate > 1) { /* Rotate a passphrase list. */ - a->passphrases.candiate--; + a->passphrases.candidate--; p = remove_passphrases_from_head(a); add_passphrase_to_tail(a, p); - /* Pick a new passphrase candiate up. */ + /* Pick a new passphrase candidate up. */ p = a->passphrases.first; - } else if (a->passphrases.candiate == 1) { - /* This case is that all cadiates failed to decryption. */ - a->passphrases.candiate = 0; + } else if (a->passphrases.candidate == 1) { + /* This case is that all candidates failed to decrypt. */ + a->passphrases.candidate = 0; if (a->passphrases.first->next != NULL) { /* Rotate a passphrase list. */ p = remove_passphrases_from_head(a); add_passphrase_to_tail(a, p); } p = NULL; - } else /* There is no passphrase candaite. */ + } else /* There is no passphrase candidate. */ p = NULL; if (p != NULL) @@ -177,7 +177,7 @@ __archive_read_next_passphrase(struct archive_read *a) if (p == NULL) return (NULL); insert_passphrase_to_head(a, p); - a->passphrases.candiate = 1; + a->passphrases.candidate = 1; } } else passphrase = NULL; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c index 3a0d4d68d..5e4d16307 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c @@ -133,7 +133,6 @@ archive_read_append_filter(struct archive *_a, int code) a->filter = filter; r2 = (bidder->init)(a->filter); if (r2 != ARCHIVE_OK) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } @@ -191,7 +190,6 @@ archive_read_append_filter_program_signature(struct archive *_a, a->filter = filter; r = (bidder->init)(a->filter); if (r != ARCHIVE_OK) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 b/Utilities/cmlibarchive/libarchive/archive_read_disk.3 index 525dc59cb..2a5c1305e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd December 30, 2016 .Dt ARCHIVE_READ_DISK 3 .Os .Sh NAME @@ -54,9 +54,9 @@ Streaming Archive Library (libarchive, -larchive) .Fn archive_read_disk_set_symlink_physical "struct archive *" .Ft int .Fn archive_read_disk_set_symlink_hybrid "struct archive *" -.Ft int +.Ft const char * .Fn archive_read_disk_gname "struct archive *" "gid_t" -.Ft int +.Ft const char * .Fn archive_read_disk_uname "struct archive *" "uid_t" .Ft int .Fo archive_read_disk_set_gname_lookup diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c index 74fe353d9..b2f1d17d9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2009 Tim Kientzle * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +38,11 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #ifdef HAVE_SYS_ACL_H #include #endif +#ifdef HAVE_DARWIN_ACL +#include +#include +#include +#endif #ifdef HAVE_SYS_EXTATTR_H #include #endif @@ -117,6 +123,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #define ACL_GET_PERM acl_get_perm_np #endif +/* NFSv4 platform ACL type */ +#if HAVE_SUN_ACL +#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T +#elif HAVE_DARWIN_ACL +#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED +#elif HAVE_ACL_TYPE_NFS4 +#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4 +#endif + static int setup_acls(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_mac_metadata(struct archive_read_disk *, @@ -125,6 +140,10 @@ static int setup_xattrs(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_sparse(struct archive_read_disk *, struct archive_entry *, int *fd); +#if defined(HAVE_LINUX_FIEMAP_H) +static int setup_sparse_fiemap(struct archive_read_disk *, + struct archive_entry *, int *fd); +#endif int archive_read_disk_entry_from_file(struct archive *_a, @@ -184,15 +203,17 @@ archive_read_disk_entry_from_file(struct archive *_a, #ifdef HAVE_STRUCT_STAT_ST_FLAGS /* On FreeBSD, we get flags for free with the stat. */ /* TODO: Does this belong in copy_stat()? */ - if (st->st_flags != 0) + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0) archive_entry_set_fflags(entry, st->st_flags, 0); #endif -#if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) +#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) /* Linux requires an extra ioctl to pull the flags. Although * this is an extra step, it has a nice side-effect: We get an * open file descriptor which we can use in the subsequent lookups. */ - if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && + (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { if (fd < 0) { if (a->tree != NULL) fd = a->open_on_current_dir(a->tree, path, @@ -204,7 +225,13 @@ archive_read_disk_entry_from_file(struct archive *_a, } if (fd >= 0) { int stflags; - r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags); + r = ioctl(fd, +#if defined(FS_IOC_GETFLAGS) + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &stflags); if (r == 0 && stflags != 0) archive_entry_set_fflags(entry, stflags, 0); } @@ -250,13 +277,15 @@ archive_read_disk_entry_from_file(struct archive *_a, } #endif /* HAVE_READLINK || HAVE_READLINKAT */ - r = setup_acls(a, entry, &fd); - if (!a->suppress_xattr) { + r = 0; + if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0) + r = setup_acls(a, entry, &fd); + if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) { r1 = setup_xattrs(a, entry, &fd); if (r1 < r) r = r1; } - if (a->enable_copyfile) { + if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { r1 = setup_mac_metadata(a, entry, &fd); if (r1 < r) r = r1; @@ -302,20 +331,17 @@ setup_mac_metadata(struct archive_read_disk *a, name = archive_entry_sourcepath(entry); if (name == NULL) name = archive_entry_pathname(entry); + else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) { + archive_set_error(&a->archive, errno, + "Can't change dir to read extended attributes"); + return (ARCHIVE_FAILED); + } if (name == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't open file to read extended attributes: No name"); return (ARCHIVE_WARN); } - if (a->tree != NULL) { - if (a->tree_enter_working_dir(a->tree) != 0) { - archive_set_error(&a->archive, errno, - "Couldn't change dir"); - return (ARCHIVE_FAILED); - } - } - /* Short-circuit if there's nothing to do. */ have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK); if (have_attrs == -1) { @@ -400,34 +426,87 @@ setup_mac_metadata(struct archive_read_disk *a, } #endif +#if HAVE_DARWIN_ACL +static int translate_guid(struct archive *, acl_entry_t, + int *, int *, const char **); -#ifdef HAVE_POSIX_ACL +static void add_trivial_nfs4_acl(struct archive_entry *); +#endif + +#if HAVE_SUN_ACL +static int +sun_acl_is_trivial(acl_t *, mode_t, int *trivialp); +#endif + +#if HAVE_POSIX_ACL || HAVE_NFS4_ACL static int translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, acl_t acl, int archive_entry_acl_type); + struct archive_entry *entry, +#if HAVE_SUN_ACL + acl_t *acl, +#else + acl_t acl, +#endif + int archive_entry_acl_type); static int setup_acls(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { const char *accpath; - acl_t acl; -#if HAVE_ACL_IS_TRIVIAL_NP - int r; +#if HAVE_SUN_ACL + acl_t *acl; +#else + acl_t acl; #endif + int r; - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL) - accpath = archive_entry_pathname(entry); + accpath = NULL; + +#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP + if (*fd < 0) +#else + /* For default ACLs on Linux we need reachable accpath */ + if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) +#endif + { + accpath = archive_entry_sourcepath(entry); + if (accpath == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + accpath = archive_entry_pathname(entry); + if (accpath == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine file path to read ACLs"); + return (ARCHIVE_WARN); + } + if (a->tree != NULL && +#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP + *fd < 0 && +#endif + (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, + accpath, O_RDONLY | O_NONBLOCK); + } + } archive_entry_acl_clear(entry); -#ifdef ACL_TYPE_NFS4 - /* Try NFS4 ACL first. */ + acl = NULL; + +#if HAVE_NFS4_ACL + /* Try NFSv4 ACL first. */ if (*fd >= 0) +#if HAVE_SUN_ACL + /* Solaris reads both POSIX.1e and NFSv4 ACL here */ + facl_get(*fd, 0, &acl); +#elif HAVE_ACL_GET_FD_NP + acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); +#else acl = acl_get_fd(*fd); +#endif #if HAVE_ACL_GET_LINK_NP else if (!a->follow_symlinks) - acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); + acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); #else else if ((!a->follow_symlinks) && (archive_entry_filetype(entry) == AE_IFLNK)) @@ -436,21 +515,62 @@ setup_acls(struct archive_read_disk *a, acl = NULL; #endif else - acl = acl_get_file(accpath, ACL_TYPE_NFS4); -#if HAVE_ACL_IS_TRIVIAL_NP +#if HAVE_SUN_ACL + /* Solaris reads both POSIX.1e and NFSv4 ACLs here */ + acl_get(accpath, 0, &acl); +#else + acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); +#endif + + +#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL /* Ignore "trivial" ACLs that just mirror the file mode. */ - acl_is_trivial_np(acl, &r); - if (r) { - acl_free(acl); - acl = NULL; - } + if (acl != NULL) { +#if HAVE_SUN_ACL + if (sun_acl_is_trivial(acl, archive_entry_mode(entry), + &r) == 0 && r == 1) +#elif HAVE_ACL_IS_TRIVIAL_NP + if (acl_is_trivial_np(acl, &r) == 0 && r == 1) #endif + { + acl_free(acl); + acl = NULL; + /* + * Simultaneous NFSv4 and POSIX.1e ACLs for the same + * entry are not allowed, so we should return here + */ + return (ARCHIVE_OK); + } + } +#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */ if (acl != NULL) { - translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); acl_free(acl); - return (ARCHIVE_OK); - } + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate " +#if !HAVE_SUN_ACL + "NFSv4 " +#endif + "ACLs"); + } +#if HAVE_DARWIN_ACL + /* + * Because Mac OS doesn't support owner@, group@ and everyone@ + * ACLs we need to add NFSv4 ACLs mirroring the file mode to + * the archive entry. Otherwise extraction on non-Mac platforms + * would lead to an invalid file mode. + */ + if ((archive_entry_acl_types(entry) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) + add_trivial_nfs4_acl(entry); #endif + return (r); + } +#endif /* HAVE_NFS4_ACL */ + +#if HAVE_POSIX_ACL + /* This code path is skipped on MacOS and Solaris */ /* Retrieve access ACL from file. */ if (*fd >= 0) @@ -467,88 +587,609 @@ setup_acls(struct archive_read_disk *a, #endif else acl = acl_get_file(accpath, ACL_TYPE_ACCESS); + +#if HAVE_ACL_IS_TRIVIAL_NP + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) { + if (r) { + acl_free(acl); + acl = NULL; + } + } +#endif + if (acl != NULL) { - translate_acl(a, entry, acl, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); acl_free(acl); + acl = NULL; + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } } /* Only directories can have default ACLs. */ if (S_ISDIR(archive_entry_mode(entry))) { +#if HAVE_ACL_GET_FD_NP + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); + else +#endif acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); if (acl != NULL) { - translate_acl(a, entry, acl, + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); acl_free(acl); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate default ACLs"); + return (r); + } } } +#endif /* HAVE_POSIX_ACL */ return (ARCHIVE_OK); } /* - * Translate system ACL into libarchive internal structure. + * Translate system ACL permissions into libarchive internal structure */ - -static struct { - int archive_perm; - int platform_perm; +static const struct { + const int archive_perm; + const int platform_perm; } acl_perm_map[] = { - {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, - {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, - {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, -#ifdef ACL_TYPE_NFS4 - {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, - {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, - {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, - {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, - {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, - {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */ + {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} +#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */ + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +#else /* POSIX.1e ACL permissions */ + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, + {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, +#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */ + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} #endif +#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ }; -#ifdef ACL_TYPE_NFS4 -static struct { - int archive_inherit; - int platform_inherit; +#if HAVE_NFS4_ACL +/* + * Translate system NFSv4 inheritance flags into libarchive internal structure + */ +static const struct { + const int archive_inherit; + const int platform_inherit; } acl_inherit_map[] = { - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, +#if HAVE_SUN_ACL /* Solaris ACL inheritance flags */ + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} +#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */ + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} +#else /* FreeBSD NFSv4 ACL inheritance flags */ + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} +#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ }; -#endif +#endif /* HAVE_NFS4_ACL */ + +#if HAVE_DARWIN_ACL +static int translate_guid(struct archive *a, acl_entry_t acl_entry, + int *ae_id, int *ae_tag, const char **ae_name) +{ + void *q; + uid_t ugid; + int r, idtype; + struct passwd *pwd; + struct group *grp; + + q = acl_get_qualifier(acl_entry); + if (q == NULL) + return (1); + r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); + if (r != 0) { + acl_free(q); + return (1); + } + if (idtype == ID_TYPE_UID) { + *ae_tag = ARCHIVE_ENTRY_ACL_USER; + pwd = getpwuuid(q); + if (pwd == NULL) { + *ae_id = ugid; + *ae_name = NULL; + } else { + *ae_id = pwd->pw_uid; + *ae_name = archive_read_disk_uname(a, *ae_id); + } + } else if (idtype == ID_TYPE_GID) { + *ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + grp = getgruuid(q); + if (grp == NULL) { + *ae_id = ugid; + *ae_name = NULL; + } else { + *ae_id = grp->gr_gid; + *ae_name = archive_read_disk_gname(a, *ae_id); + } + } else + r = 1; + + acl_free(q); + return (r); +} + +/* + * Add trivial NFSv4 ACL entries from mode + */ +static void +add_trivial_nfs4_acl(struct archive_entry *entry) +{ + mode_t mode; + int i; + const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; + const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA; + const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE; + const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER; + + struct { + const int type; + const int tag; + int permset; + } tacl_entry[] = { + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset} + }; + + mode = archive_entry_mode(entry); + + /* Permissions for everyone@ */ + if (mode & 0004) + tacl_entry[5].permset |= rperm; + if (mode & 0002) + tacl_entry[5].permset |= wperm; + if (mode & 0001) + tacl_entry[5].permset |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tacl_entry[4].permset |= rperm; + else if (mode & 0004) + tacl_entry[2].permset |= rperm; + if (mode & 0020) + tacl_entry[4].permset |= wperm; + else if (mode & 0002) + tacl_entry[2].permset |= wperm; + if (mode & 0010) + tacl_entry[4].permset |= eperm; + else if (mode & 0001) + tacl_entry[2].permset |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tacl_entry[3].permset |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tacl_entry[0].permset |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tacl_entry[1].permset |= rperm; + if (mode & 0200) { + tacl_entry[3].permset |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tacl_entry[0].permset |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tacl_entry[1].permset |= wperm; + if (mode & 0100) { + tacl_entry[3].permset |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tacl_entry[0].permset |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tacl_entry[1].permset |= eperm; + + for (i = 0; i < 6; i++) { + if (tacl_entry[i].permset != 0) { + archive_entry_acl_add_entry(entry, + tacl_entry[i].type, tacl_entry[i].permset, + tacl_entry[i].tag, -1, NULL); + } + } + + return; +} +#elif HAVE_SUN_ACL +/* + * Check if acl is trivial + * This is a FreeBSD acl_is_trivial_np() implementation for Solaris + */ +static int +sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) +{ + int i, p; + const uint32_t rperm = ACE_READ_DATA; + const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA; + const uint32_t eperm = ACE_EXECUTE; + const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | + ACE_READ_ACL | ACE_SYNCHRONIZE; + const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES | + ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER; + + ace_t *ace; + ace_t tace[6]; + + if (acl == NULL || trivialp == NULL) + return (-1); + + *trivialp = 0; + + /* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */ + if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0) + return (0); + + /* + * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with + * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries, + * including mask. + */ + if (acl->acl_type == ACLENT_T) { + if (acl->acl_cnt == 4) + *trivialp = 1; + return (0); + } + + if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t)) + return (-1); + + /* + * Continue with checking NFSv4 ACLs + * + * Create list of trivial ace's to be compared + */ + + /* owner@ allow pre */ + tace[0].a_flags = ACE_OWNER; + tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[0].a_access_mask = 0; + + /* owner@ deny */ + tace[1].a_flags = ACE_OWNER; + tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[1].a_access_mask = 0; + + /* group@ deny */ + tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[2].a_access_mask = 0; + + /* owner@ allow */ + tace[3].a_flags = ACE_OWNER; + tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[3].a_access_mask = ownset; + + /* group@ allow */ + tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[4].a_access_mask = pubset; + + /* everyone@ allow */ + tace[5].a_flags = ACE_EVERYONE; + tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[5].a_access_mask = pubset; + + /* Permissions for everyone@ */ + if (mode & 0004) + tace[5].a_access_mask |= rperm; + if (mode & 0002) + tace[5].a_access_mask |= wperm; + if (mode & 0001) + tace[5].a_access_mask |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tace[4].a_access_mask |= rperm; + else if (mode & 0004) + tace[2].a_access_mask |= rperm; + if (mode & 0020) + tace[4].a_access_mask |= wperm; + else if (mode & 0002) + tace[2].a_access_mask |= wperm; + if (mode & 0010) + tace[4].a_access_mask |= eperm; + else if (mode & 0001) + tace[2].a_access_mask |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tace[3].a_access_mask |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tace[0].a_access_mask |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tace[1].a_access_mask |= rperm; + if (mode & 0200) { + tace[3].a_access_mask |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tace[0].a_access_mask |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tace[1].a_access_mask |= wperm; + if (mode & 0100) { + tace[3].a_access_mask |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tace[0].a_access_mask |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tace[1].a_access_mask |= eperm; + + /* Check if the acl count matches */ + p = 3; + for (i = 0; i < 3; i++) { + if (tace[i].a_access_mask != 0) + p++; + } + if (acl->acl_cnt != p) + return (0); + + p = 0; + for (i = 0; i < 6; i++) { + if (tace[i].a_access_mask != 0) { + ace = &((ace_t *)acl->acl_aclp)[p]; + /* + * Illumos added ACE_DELETE_CHILD to write perms for + * directories. We have to check against that, too. + */ + if (ace->a_flags != tace[i].a_flags || + ace->a_type != tace[i].a_type || + (ace->a_access_mask != tace[i].a_access_mask && + ((acl->acl_flags & ACL_IS_DIR) == 0 || + (tace[i].a_access_mask & wperm) == 0 || + ace->a_access_mask != + (tace[i].a_access_mask | ACE_DELETE_CHILD)))) + return (0); + p++; + } + } + + *trivialp = 1; + return (0); +} +#endif /* HAVE_SUN_ACL */ + +#if HAVE_SUN_ACL +/* + * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL + */ +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t *acl, int default_entry_acl_type) +{ + int e, i; + int ae_id, ae_tag, ae_perm; + int entry_acl_type; + const char *ae_name; + aclent_t *aclent; + ace_t *ace; + + (void)default_entry_acl_type; + + if (acl->acl_cnt <= 0) + return (ARCHIVE_OK); + + for (e = 0; e < acl->acl_cnt; e++) { + ae_name = NULL; + ae_tag = 0; + ae_perm = 0; + + if (acl->acl_type == ACE_T) { + ace = &((ace_t *)acl->acl_aclp)[e]; + ae_id = ace->a_who; + + switch(ace->a_type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case ACE_ACCESS_DENIED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + case ACE_SYSTEM_AUDIT_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + break; + case ACE_SYSTEM_ALARM_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + break; + default: + /* Unknown entry type, skip */ + continue; + } + + if ((ace->a_flags & ACE_OWNER) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if ((ace->a_flags & ACE_GROUP) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + else if ((ace->a_flags & ACE_EVERYONE) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) { + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } else { + ae_tag = ARCHIVE_ENTRY_ACL_USER; + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + + for (i = 0; i < (int)(sizeof(acl_inherit_map) / + sizeof(acl_inherit_map[0])); ++i) { + if ((ace->a_flags & + acl_inherit_map[i].platform_inherit) != 0) + ae_perm |= + acl_inherit_map[i].archive_inherit; + } + + for (i = 0; i < (int)(sizeof(acl_perm_map) / + sizeof(acl_perm_map[0])); ++i) { + if ((ace->a_access_mask & + acl_perm_map[i].platform_perm) != 0) + ae_perm |= + acl_perm_map[i].archive_perm; + } + } else { + aclent = &((aclent_t *)acl->acl_aclp)[e]; + if ((aclent->a_type & ACL_DEFAULT) != 0) + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + else + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + ae_id = aclent->a_id; + + switch(aclent->a_type) { + case DEF_USER: + case USER: + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case DEF_GROUP: + case GROUP: + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case DEF_CLASS_OBJ: + case CLASS_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case DEF_USER_OBJ: + case USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case DEF_GROUP_OBJ: + case GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case DEF_OTHER_OBJ: + case OTHER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + default: + /* Unknown tag type, skip */ + continue; + } + + if ((aclent->a_perm & 1) != 0) + ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; + if ((aclent->a_perm & 2) != 0) + ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; + if ((aclent->a_perm & 4) != 0) + ae_perm |= ARCHIVE_ENTRY_ACL_READ; + } /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, ae_id, ae_name); + } + return (ARCHIVE_OK); +} +#else /* !HAVE_SUN_ACL */ +/* + * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and + * MacOS (NFSv4 only) ACLs into libarchive internal structure + */ static int translate_acl(struct archive_read_disk *a, struct archive_entry *entry, acl_t acl, int default_entry_acl_type) { acl_tag_t acl_tag; -#ifdef ACL_TYPE_NFS4 +#if HAVE_ACL_TYPE_NFS4 acl_entry_type_t acl_type; + int brand; +#endif +#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL acl_flagset_t acl_flagset; - int brand, r; #endif acl_entry_t acl_entry; acl_permset_t acl_permset; int i, entry_acl_type; - int s, ae_id, ae_tag, ae_perm; + int r, s, ae_id, ae_tag, ae_perm; +#if !HAVE_DARWIN_ACL + void *q; +#endif const char *ae_name; - -#ifdef ACL_TYPE_NFS4 +#if HAVE_ACL_TYPE_NFS4 // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 // Make sure the "brand" on this ACL is consistent // with the default_entry_acl_type bits provided. - acl_get_brand_np(acl, &brand); + if (acl_get_brand_np(acl, &brand) != 0) { + archive_set_error(&a->archive, errno, + "Failed to read ACL brand"); + return (ARCHIVE_WARN); + } switch (brand) { case ACL_BRAND_POSIX: switch (default_entry_acl_type) { @@ -556,40 +1197,67 @@ translate_acl(struct archive_read_disk *a, case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: break; default: - // XXX set warning message? - return ARCHIVE_FAILED; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ACL entry type for POSIX.1e ACL"); + return (ARCHIVE_WARN); } break; case ACL_BRAND_NFS4: if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - // XXX set warning message? - return ARCHIVE_FAILED; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ACL entry type for NFSv4 ACL"); + return (ARCHIVE_WARN); } break; default: - // XXX set warning message? - return ARCHIVE_FAILED; - break; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown ACL brand"); + return (ARCHIVE_WARN); } #endif - s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); - while (s == 1) { + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get first ACL entry"); + return (ARCHIVE_WARN); + } + +#if HAVE_DARWIN_ACL + while (s == 0) +#else /* FreeBSD, Linux */ + while (s == 1) +#endif + { ae_id = -1; ae_name = NULL; ae_perm = 0; - acl_get_tag_type(acl_entry, &acl_tag); + if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL tag type"); + return (ARCHIVE_WARN); + } switch (acl_tag) { +#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ case ACL_USER: - ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry); - ae_name = archive_read_disk_uname(&a->archive, ae_id); + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(uid_t *)q; + acl_free(q); + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } ae_tag = ARCHIVE_ENTRY_ACL_USER; break; case ACL_GROUP: - ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry); - ae_name = archive_read_disk_gname(&a->archive, ae_id); + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(gid_t *)q; + acl_free(q); + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } ae_tag = ARCHIVE_ENTRY_ACL_GROUP; break; case ACL_MASK: @@ -604,24 +1272,52 @@ translate_acl(struct archive_read_disk *a, case ACL_OTHER: ae_tag = ARCHIVE_ENTRY_ACL_OTHER; break; -#ifdef ACL_TYPE_NFS4 +#if HAVE_ACL_TYPE_NFS4 case ACL_EVERYONE: ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; break; #endif +#else /* HAVE_DARWIN_ACL */ + case ACL_EXTENDED_ALLOW: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + r = translate_guid(&a->archive, acl_entry, &ae_id, + &ae_tag, &ae_name); + break; + case ACL_EXTENDED_DENY: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + r = translate_guid(&a->archive, acl_entry, &ae_id, + &ae_tag, &ae_name); + break; +#endif /* HAVE_DARWIN_ACL */ default: /* Skip types that libarchive can't support. */ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); continue; } - // XXX acl type maps to allow/deny/audit/YYYY bits - // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for - // non-NFSv4 ACLs +#if HAVE_DARWIN_ACL + /* Skip if translate_guid() above failed */ + if (r != 0) { + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } +#endif + +#if !HAVE_DARWIN_ACL + // XXX acl_type maps to allow/deny/audit/YYYY bits entry_acl_type = default_entry_acl_type; -#ifdef ACL_TYPE_NFS4 - r = acl_get_entry_type_np(acl_entry, &acl_type); - if (r == 0) { +#endif +#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL + if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { +#if HAVE_ACL_TYPE_NFS4 + /* + * acl_get_entry_type_np() fails with non-NFSv4 ACLs + */ + if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) { + archive_set_error(&a->archive, errno, "Failed " + "to get ACL type from a NFSv4 ACL entry"); + return (ARCHIVE_WARN); + } switch (acl_type) { case ACL_ENTRY_TYPE_ALLOW: entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; @@ -635,29 +1331,54 @@ translate_acl(struct archive_read_disk *a, case ACL_ENTRY_TYPE_ALARM: entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; break; + default: + archive_set_error(&a->archive, errno, + "Invalid NFSv4 ACL entry type"); + return (ARCHIVE_WARN); } - } - - /* - * Libarchive stores "flag" (NFSv4 inheritance bits) - * in the ae_perm bitmap. - */ - acl_get_flagset_np(acl_entry, &acl_flagset); - for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - if (acl_get_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit)) - ae_perm |= acl_inherit_map[i].archive_inherit; +#endif /* HAVE_ACL_TYPE_NFS4 */ - } -#endif + /* + * Libarchive stores "flag" (NFSv4 inheritance bits) + * in the ae_perm bitmap. + * + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get flagset from a NFSv4 ACL entry"); + return (ARCHIVE_WARN); + } + for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { + r = acl_get_flag_np(acl_flagset, + acl_inherit_map[i].platform_inherit); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check flag in a NFSv4 " + "ACL flagset"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_inherit_map[i].archive_inherit; + } + } +#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */ - acl_get_permset(acl_entry, &acl_permset); + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { /* * acl_get_perm() is spelled differently on different * platforms; see above. */ - if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm)) + r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check permission in an ACL permission set"); + return (ARCHIVE_WARN); + } else if (r) ae_perm |= acl_perm_map[i].archive_perm; } @@ -666,10 +1387,18 @@ translate_acl(struct archive_read_disk *a, ae_id, ae_name); s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); +#if !HAVE_DARWIN_ACL + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get next ACL entry"); + return (ARCHIVE_WARN); + } +#endif } return (ARCHIVE_OK); } -#else +#endif /* !HAVE_SUN_ACL */ +#else /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ static int setup_acls(struct archive_read_disk *a, struct archive_entry *entry, int *fd) @@ -679,7 +1408,7 @@ setup_acls(struct archive_read_disk *a, (void)fd; /* UNUSED */ return (ARCHIVE_OK); } -#endif +#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \ HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \ @@ -699,15 +1428,10 @@ setup_acls(struct archive_read_disk *a, static int setup_xattr(struct archive_read_disk *a, - struct archive_entry *entry, const char *name, int fd) + struct archive_entry *entry, const char *name, int fd, const char *accpath) { ssize_t size; void *value = NULL; - const char *accpath; - - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL) - accpath = archive_entry_pathname(entry); #if HAVE_FGETXATTR if (fd >= 0) @@ -772,21 +1496,23 @@ setup_xattrs(struct archive_read_disk *a, const char *path; ssize_t list_size; - path = archive_entry_sourcepath(entry); - if (path == NULL) - path = archive_entry_pathname(entry); + path = NULL; - if (*fd < 0 && a->tree != NULL) { - if (a->follow_symlinks || - archive_entry_filetype(entry) != AE_IFLNK) - *fd = a->open_on_current_dir(a->tree, path, - O_RDONLY | O_NONBLOCK); - if (*fd < 0) { - if (a->tree_enter_working_dir(a->tree) != 0) { - archive_set_error(&a->archive, errno, - "Couldn't access %s", path); - return (ARCHIVE_FAILED); - } + if (*fd < 0) { + path = archive_entry_sourcepath(entry); + if (path == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + path = archive_entry_pathname(entry); + if (path == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine file path to read " + "extended attributes"); + return (ARCHIVE_WARN); + } + if (a->tree != NULL && (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, + path, O_RDONLY | O_NONBLOCK); } } @@ -849,7 +1575,7 @@ setup_xattrs(struct archive_read_disk *a, if (strncmp(p, "system.", 7) == 0 || strncmp(p, "xfsroot.", 8) == 0) continue; - setup_xattr(a, entry, p, *fd); + setup_xattr(a, entry, p, *fd, path); } free(list); @@ -870,19 +1596,16 @@ setup_xattrs(struct archive_read_disk *a, */ static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, - int namespace, const char *name, const char *fullname, int fd); + int namespace, const char *name, const char *fullname, int fd, + const char *path); static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, - int namespace, const char *name, const char *fullname, int fd) + int namespace, const char *name, const char *fullname, int fd, + const char *accpath) { ssize_t size; void *value = NULL; - const char *accpath; - - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL) - accpath = archive_entry_pathname(entry); if (fd >= 0) size = extattr_get_fd(fd, namespace, name, NULL, 0); @@ -932,21 +1655,23 @@ setup_xattrs(struct archive_read_disk *a, const char *path; int namespace = EXTATTR_NAMESPACE_USER; - path = archive_entry_sourcepath(entry); - if (path == NULL) - path = archive_entry_pathname(entry); + path = NULL; - if (*fd < 0 && a->tree != NULL) { - if (a->follow_symlinks || - archive_entry_filetype(entry) != AE_IFLNK) - *fd = a->open_on_current_dir(a->tree, path, - O_RDONLY | O_NONBLOCK); - if (*fd < 0) { - if (a->tree_enter_working_dir(a->tree) != 0) { - archive_set_error(&a->archive, errno, - "Couldn't access %s", path); - return (ARCHIVE_FAILED); - } + if (*fd < 0) { + path = archive_entry_sourcepath(entry); + if (path == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + path = archive_entry_pathname(entry); + if (path == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine file path to read " + "extended attributes"); + return (ARCHIVE_WARN); + } + if (a->tree != NULL && (a->follow_symlinks || + archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, + path, O_RDONLY | O_NONBLOCK); } } @@ -996,7 +1721,7 @@ setup_xattrs(struct archive_read_disk *a, name = buff + strlen(buff); memcpy(name, p + 1, len); name[len] = '\0'; - setup_xattr(a, entry, namespace, name, buff, *fd); + setup_xattr(a, entry, namespace, name, buff, *fd, path); p += 1 + len; } @@ -1024,7 +1749,7 @@ setup_xattrs(struct archive_read_disk *a, #if defined(HAVE_LINUX_FIEMAP_H) /* - * Linux sparse interface. + * Linux FIEMAP sparse interface. * * The FIEMAP ioctl returns an "extent" for each physical allocation * on disk. We need to process those to generate a more compact list @@ -1039,7 +1764,7 @@ setup_xattrs(struct archive_read_disk *a, */ static int -setup_sparse(struct archive_read_disk *a, +setup_sparse_fiemap(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { char buff[4096]; @@ -1090,8 +1815,8 @@ setup_sparse(struct archive_read_disk *a, if (r < 0) { /* When something error happens, it is better we * should return ARCHIVE_OK because an earlier - * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */ - goto exit_setup_sparse; + * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */ + goto exit_setup_sparse_fiemap; } if (fm->fm_mapped_extents == 0) { if (iters == 0) { @@ -1126,14 +1851,24 @@ setup_sparse(struct archive_read_disk *a, } else break; } -exit_setup_sparse: +exit_setup_sparse_fiemap: return (exit_sts); } -#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE) +#if !defined(SEEK_HOLE) || !defined(SEEK_DATA) +static int +setup_sparse(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + return setup_sparse_fiemap(a, entry, fd); +} +#endif +#endif /* defined(HAVE_LINUX_FIEMAP_H) */ + +#if defined(SEEK_HOLE) && defined(SEEK_DATA) /* - * FreeBSD and Solaris sparse interface. + * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris) */ static int @@ -1141,8 +1876,8 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { int64_t size; - off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */ - off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */ + off_t initial_off; + off_t off_s, off_e; int exit_sts = ARCHIVE_OK; int check_fully_sparse = 0; @@ -1168,8 +1903,10 @@ setup_sparse(struct archive_read_disk *a, } if (*fd >= 0) { +#ifdef _PC_MIN_HOLE_SIZE if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); +#endif initial_off = lseek(*fd, 0, SEEK_CUR); if (initial_off != 0) lseek(*fd, 0, SEEK_SET); @@ -1180,8 +1917,10 @@ setup_sparse(struct archive_read_disk *a, if (path == NULL) path = archive_entry_pathname(entry); +#ifdef _PC_MIN_HOLE_SIZE if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); +#endif *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (*fd < 0) { archive_set_error(&a->archive, errno, @@ -1192,6 +1931,19 @@ setup_sparse(struct archive_read_disk *a, initial_off = 0; } +#ifndef _PC_MIN_HOLE_SIZE + /* Check if the underlying filesystem supports seek hole */ + off_s = lseek(*fd, 0, SEEK_HOLE); + if (off_s < 0) +#if defined(HAVE_LINUX_FIEMAP_H) + return setup_sparse_fiemap(a, entry, fd); +#else + goto exit_setup_sparse; +#endif + else if (off_s > 0) + lseek(*fd, 0, SEEK_SET); +#endif + off_s = 0; size = archive_entry_size(entry); while (off_s < size) { @@ -1223,7 +1975,7 @@ setup_sparse(struct archive_read_disk *a, goto exit_setup_sparse; } if (off_s == 0 && off_e == size) - break;/* This is not spase. */ + break;/* This is not sparse. */ archive_entry_sparse_add_entry(entry, off_s, off_e - off_s); off_s = off_e; @@ -1241,7 +1993,7 @@ exit_setup_sparse: return (exit_sts); } -#else +#elif !defined(HAVE_LINUX_FIEMAP_H) /* * Generic (stub) sparse support. diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c index 22a1f14c0..6961ae6a4 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c @@ -165,7 +165,7 @@ struct filesystem { int synthetic; int remote; int noatime; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) size_t name_max; #endif long incr_xfer_size; @@ -200,7 +200,7 @@ struct tree { DIR *d; #define INVALID_DIR_HANDLE NULL struct dirent *de; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) struct dirent *dirent; size_t dirent_allocated; #endif @@ -244,7 +244,7 @@ struct tree { int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; - int allocated_filesytem; + int allocated_filesystem; int entry_fd; int entry_eof; @@ -465,8 +465,7 @@ archive_read_disk_new(void) a->entry = archive_entry_new2(&a->archive); a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; - a->enable_copyfile = 1; - a->traverse_mount_points = 1; + a->flags = ARCHIVE_READDISK_MAC_COPYFILE; a->open_on_current_dir = open_on_current_dir; a->tree_current_dir_fd = tree_current_dir_fd; a->tree_enter_working_dir = tree_enter_working_dir; @@ -563,25 +562,19 @@ archive_read_disk_set_symlink_hybrid(struct archive *_a) int archive_read_disk_set_atime_restored(struct archive *_a) { -#ifndef HAVE_UTIMES - static int warning_done = 0; -#endif struct archive_read_disk *a = (struct archive_read_disk *)_a; archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime"); #ifdef HAVE_UTIMES - a->restore_time = 1; + a->flags |= ARCHIVE_READDISK_RESTORE_ATIME; if (a->tree != NULL) a->tree->flags |= needsRestoreTimes; return (ARCHIVE_OK); #else - if (warning_done) - /* Warning was already emitted; suppress further warnings. */ - return (ARCHIVE_OK); - + /* Display warning and unset flag */ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Cannot restore access time on this system"); - warning_done = 1; + a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME; return (ARCHIVE_WARN); #endif } @@ -595,29 +588,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags) archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + a->flags = flags; + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) r = archive_read_disk_set_atime_restored(_a); else { - a->restore_time = 0; if (a->tree != NULL) a->tree->flags &= ~needsRestoreTimes; } - if (flags & ARCHIVE_READDISK_HONOR_NODUMP) - a->honor_nodump = 1; - else - a->honor_nodump = 0; - if (flags & ARCHIVE_READDISK_MAC_COPYFILE) - a->enable_copyfile = 1; - else - a->enable_copyfile = 0; - if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) - a->traverse_mount_points = 0; - else - a->traverse_mount_points = 1; - if (flags & ARCHIVE_READDISK_NO_XATTR) - a->suppress_xattr = 1; - else - a->suppress_xattr = 0; return (r); } @@ -675,7 +653,7 @@ setup_suitable_read_buffer(struct archive_read_disk *a) asize = cf->min_xfer_size; /* Increase a buffer size up to 64K bytes in - * a proper incremant size. */ + * a proper increment size. */ while (asize < 1024*64) asize += incr; /* Take a margin to adjust to the filesystem @@ -918,7 +896,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, } while (lst == NULL); #ifdef __APPLE__ - if (a->enable_copyfile) { + if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { /* If we're using copyfile(), ignore "._XXX" files. */ const char *bname = strrchr(tree_current_path(t), '/'); if (bname == NULL) @@ -938,7 +916,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_path_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -989,7 +967,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, } if (t->initial_filesystem_id == -1) t->initial_filesystem_id = t->current_filesystem_id; - if (!a->traverse_mount_points) { + if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { if (t->initial_filesystem_id != t->current_filesystem_id) descend = 0; } @@ -999,12 +977,14 @@ next_entry(struct archive_read_disk *a, struct tree *t, * Honor nodump flag. * If the file is marked with nodump flag, do not return this entry. */ - if (a->honor_nodump) { + if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) { #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) if (st->st_flags & UF_NODUMP) return (ARCHIVE_RETRY); -#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\ - defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) +#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \ + defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \ + defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) { int stflags; @@ -1013,9 +993,18 @@ next_entry(struct archive_read_disk *a, struct tree *t, O_RDONLY | O_NONBLOCK | O_CLOEXEC); __archive_ensure_cloexec_flag(t->entry_fd); if (t->entry_fd >= 0) { - r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS, + r = ioctl(t->entry_fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif &stflags); +#ifdef FS_NODUMP_FL + if (r == 0 && (stflags & FS_NODUMP_FL) != 0) +#else if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0) +#endif return (ARCHIVE_RETRY); } } @@ -1026,7 +1015,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, /* Save the times to be restored. This must be in before * calling archive_read_disk_descend() or any chance of it, - * especially, invokng a callback. */ + * especially, invoking a callback. */ t->restore_time.mtime = archive_entry_mtime(entry); t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry); t->restore_time.atime = archive_entry_atime(entry); @@ -1041,7 +1030,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_time_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1067,7 +1056,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1340,10 +1329,11 @@ _archive_read_disk_open(struct archive *_a, const char *pathname) struct archive_read_disk *a = (struct archive_read_disk *)_a; if (a->tree != NULL) - a->tree = tree_reopen(a->tree, pathname, a->restore_time); + a->tree = tree_reopen(a->tree, pathname, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); else a->tree = tree_open(pathname, a->symlink_mode, - a->restore_time); + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); if (a->tree == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate tar data"); @@ -1382,7 +1372,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) for (i = 0; i < t->max_filesystem_id; i++) { if (t->filesystem_table[i].dev == dev) { - /* There is the filesytem ID we've already generated. */ + /* There is the filesystem ID we've already generated. */ t->current_filesystem_id = i; t->current_filesystem = &(t->filesystem_table[i]); return (ARCHIVE_OK); @@ -1390,10 +1380,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) } /* - * This is the new filesytem which we have to generate a new ID for. + * This is the new filesystem which we have to generate a new ID for. */ fid = t->max_filesystem_id++; - if (t->max_filesystem_id > t->allocated_filesytem) { + if (t->max_filesystem_id > t->allocated_filesystem) { size_t s; void *p; @@ -1406,7 +1396,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) return (ARCHIVE_FATAL); } t->filesystem_table = (struct filesystem *)p; - t->allocated_filesytem = s; + t->allocated_filesystem = s; } t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); @@ -1504,7 +1494,20 @@ setup_current_filesystem(struct archive_read_disk *a) struct tree *t = a->tree; struct statfs sfs; #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) +/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make + * this accurate; some platforms have both and we need the one that's + * used by getvfsbyname() + * + * Then the following would become: + * #if defined(GETVFSBYNAME_ARG_TYPE) + * GETVFSBYNAME_ARG_TYPE vfc; + * #endif + */ +# if defined(HAVE_STRUCT_XVFSCONF) struct xvfsconf vfc; +# else + struct vfsconf vfc; +# endif #endif int r, xr = 0; #if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX) @@ -1579,7 +1582,7 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX) t->current_filesystem->name_max = sfs.f_namemax; @@ -1602,7 +1605,7 @@ setup_current_filesystem(struct archive_read_disk *a) else t->current_filesystem->name_max = nm; #endif -#endif /* HAVE_READDIR_R */ +#endif /* USE_READDIR_R */ return (ARCHIVE_OK); } @@ -1643,7 +1646,7 @@ setup_current_filesystem(struct archive_read_disk *a) archive_set_error(&a->archive, errno, "statvfs failed"); return (ARCHIVE_FAILED); } else if (xr == 1) { - /* Usuall come here unless NetBSD supports _PC_REC_XFER_ALIGN + /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN * for pathconf() function. */ t->current_filesystem->xfer_align = sfs.f_frsize; t->current_filesystem->max_xfer_size = -1; @@ -1804,7 +1807,7 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ t->current_filesystem->name_max = sfs.f_namelen; #endif @@ -1888,7 +1891,7 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ t->current_filesystem->name_max = sfs.f_namemax; #endif @@ -1905,7 +1908,7 @@ static int setup_current_filesystem(struct archive_read_disk *a) { struct tree *t = a->tree; -#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R) +#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R) long nm; #endif t->current_filesystem->synthetic = -1;/* Not supported */ @@ -1917,7 +1920,7 @@ setup_current_filesystem(struct archive_read_disk *a) t->current_filesystem->min_xfer_size = -1; t->current_filesystem->incr_xfer_size = -1; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ # if defined(_PC_NAME_MAX) if (tree_current_is_symblic_link_target(t)) { @@ -1931,7 +1934,7 @@ setup_current_filesystem(struct archive_read_disk *a) if (nm == -1) # endif /* _PC_NAME_MAX */ /* - * Some sysmtes (HP-UX or others?) incorrectly defined + * Some systems (HP-UX or others?) incorrectly defined * NAME_MAX macro to be a smaller value. */ # if defined(NAME_MAX) && NAME_MAX >= 255 @@ -1945,7 +1948,7 @@ setup_current_filesystem(struct archive_read_disk *a) else t->current_filesystem->name_max = nm; # endif /* _PC_NAME_MAX */ -#endif /* HAVE_READDIR_R */ +#endif /* USE_READDIR_R */ return (ARCHIVE_OK); } @@ -2050,8 +2053,7 @@ tree_push(struct tree *t, const char *path, int filesystem_id, { struct tree_entry *te; - te = malloc(sizeof(*te)); - memset(te, 0, sizeof(*te)); + te = calloc(1, sizeof(*te)); te->next = t->stack; te->parent = t->current; if (te->parent) @@ -2109,9 +2111,8 @@ tree_open(const char *path, int symlink_mode, int restore_time) { struct tree *t; - if ((t = malloc(sizeof(*t))) == NULL) + if ((t = calloc(1, sizeof(*t))) == NULL) return (NULL); - memset(t, 0, sizeof(*t)); archive_string_init(&t->path); archive_string_ensure(&t->path, 31); t->initial_symlink_mode = symlink_mode; @@ -2121,7 +2122,7 @@ tree_open(const char *path, int symlink_mode, int restore_time) static struct tree * tree_reopen(struct tree *t, const char *path, int restore_time) { - t->flags = (restore_time)?needsRestoreTimes:0; + t->flags = (restore_time != 0)?needsRestoreTimes:0; t->flags |= onInitialDir; t->visit_type = 0; t->tree_errno = 0; @@ -2353,7 +2354,7 @@ tree_dir_next_posix(struct tree *t) size_t namelen; if (t->d == NULL) { -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) size_t dirent_size; #endif @@ -2374,7 +2375,7 @@ tree_dir_next_posix(struct tree *t) t->visit_type = r != 0 ? r : TREE_ERROR_DIR; return (t->visit_type); } -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) dirent_size = offsetof(struct dirent, d_name) + t->filesystem_table[t->current->filesystem_id].name_max + 1; if (t->dirent == NULL || t->dirent_allocated < dirent_size) { @@ -2391,11 +2392,11 @@ tree_dir_next_posix(struct tree *t) } t->dirent_allocated = dirent_size; } -#endif /* HAVE_READDIR_R */ +#endif /* USE_READDIR_R */ } for (;;) { errno = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) r = readdir_r(t->d, t->dirent, &t->de); #ifdef _AIX /* Note: According to the man page, return value 9 indicates @@ -2647,7 +2648,7 @@ tree_free(struct tree *t) if (t == NULL) return; archive_string_free(&t->path); -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) free(t->dirent); #endif free(t->sparse_list); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h index 2569321da..b5a8328b7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h @@ -63,16 +63,8 @@ struct archive_read_disk { int (*tree_current_dir_fd)(struct tree*); int (*tree_enter_working_dir)(struct tree*); - /* Set 1 if users request to restore atime . */ - int restore_time; - /* Set 1 if users request to honor nodump flag . */ - int honor_nodump; - /* Set 1 if users request to enable mac copyfile. */ - int enable_copyfile; - /* Set 1 if users request to traverse mount points. */ - int traverse_mount_points; - /* Set 1 if users want to suppress xattr information. */ - int suppress_xattr; + /* Bitfield with ARCHIVE_READDISK_* tunables */ + int flags; const char * (*lookup_gname)(void *private, int64_t gid); void (*cleanup_gname)(void *private); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c index d6b2d55b8..c7fd2471e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c @@ -232,6 +232,7 @@ static const char * lookup_uname_helper(struct name_cache *cache, id_t id) { struct passwd *result; + (void)cache; /* UNUSED */ result = getpwuid((uid_t)id); @@ -298,6 +299,7 @@ static const char * lookup_gname_helper(struct name_cache *cache, id_t id) { struct group *result; + (void)cache; /* UNUSED */ result = getgrgid((gid_t)id); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c index 566d264e9..3b903304f 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c @@ -168,7 +168,7 @@ struct tree { int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; - int allocated_filesytem; + int allocated_filesystem; HANDLE entry_fh; int entry_eof; @@ -389,18 +389,16 @@ archive_read_disk_new(void) { struct archive_read_disk *a; - a = (struct archive_read_disk *)malloc(sizeof(*a)); + a = (struct archive_read_disk *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_READ_DISK_MAGIC; a->archive.state = ARCHIVE_STATE_NEW; a->archive.vtable = archive_read_disk_vtable(); a->entry = archive_entry_new2(&a->archive); a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; - a->enable_copyfile = 1; - a->traverse_mount_points = 1; + a->flags = ARCHIVE_READDISK_MAC_COPYFILE; return (&a->archive); } @@ -496,7 +494,7 @@ archive_read_disk_set_atime_restored(struct archive *_a) struct archive_read_disk *a = (struct archive_read_disk *)_a; archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime"); - a->restore_time = 1; + a->flags |= ARCHIVE_READDISK_RESTORE_ATIME; if (a->tree != NULL) a->tree->flags |= needsRestoreTimes; return (ARCHIVE_OK); @@ -511,25 +509,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags) archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + a->flags = flags; + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) r = archive_read_disk_set_atime_restored(_a); else { - a->restore_time = 0; if (a->tree != NULL) a->tree->flags &= ~needsRestoreTimes; } - if (flags & ARCHIVE_READDISK_HONOR_NODUMP) - a->honor_nodump = 1; - else - a->honor_nodump = 0; - if (flags & ARCHIVE_READDISK_MAC_COPYFILE) - a->enable_copyfile = 1; - else - a->enable_copyfile = 0; - if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) - a->traverse_mount_points = 0; - else - a->traverse_mount_points = 1; return (r); } @@ -803,7 +790,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_path_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -853,7 +840,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, } if (t->initial_filesystem_id == -1) t->initial_filesystem_id = t->current_filesystem_id; - if (!a->traverse_mount_points) { + if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { if (t->initial_filesystem_id != t->current_filesystem_id) return (ARCHIVE_RETRY); } @@ -863,7 +850,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, /* Save the times to be restored. This must be in before * calling archive_read_disk_descend() or any chance of it, - * especially, invokng a callback. */ + * especially, invoking a callback. */ t->restore_time.lastWriteTime = st->ftLastWriteTime; t->restore_time.lastAccessTime = st->ftLastAccessTime; t->restore_time.filetype = archive_entry_filetype(entry); @@ -875,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_time_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -901,7 +888,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1220,9 +1207,11 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) struct archive_read_disk *a = (struct archive_read_disk *)_a; if (a->tree != NULL) - a->tree = tree_reopen(a->tree, pathname, a->restore_time); + a->tree = tree_reopen(a->tree, pathname, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); else - a->tree = tree_open(pathname, a->symlink_mode, a->restore_time); + a->tree = tree_open(pathname, a->symlink_mode, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); if (a->tree == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate directory traversal data"); @@ -1261,7 +1250,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) for (i = 0; i < t->max_filesystem_id; i++) { if (t->filesystem_table[i].dev == dev) { - /* There is the filesytem ID we've already generated. */ + /* There is the filesystem ID we've already generated. */ t->current_filesystem_id = i; t->current_filesystem = &(t->filesystem_table[i]); return (ARCHIVE_OK); @@ -1269,10 +1258,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) } /* - * There is a new filesytem, we generate a new ID for. + * There is a new filesystem, we generate a new ID for. */ fid = t->max_filesystem_id++; - if (t->max_filesystem_id > t->allocated_filesytem) { + if (t->max_filesystem_id > t->allocated_filesystem) { size_t s; void *p; @@ -1285,7 +1274,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) return (ARCHIVE_FATAL); } t->filesystem_table = (struct filesystem *)p; - t->allocated_filesytem = (int)s; + t->allocated_filesystem = (int)s; } t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); @@ -1402,7 +1391,7 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt) if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype) return (0); - /* Close a file descritor. + /* Close a file descriptor. * It will not be used for SetFileTime() because it has been opened * by a read only mode. */ @@ -1437,8 +1426,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path, { struct tree_entry *te; - te = malloc(sizeof(*te)); - memset(te, 0, sizeof(*te)); + te = calloc(1, sizeof(*te)); te->next = t->stack; te->parent = t->current; if (te->parent) @@ -1507,8 +1495,7 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time) { struct tree *t; - t = malloc(sizeof(*t)); - memset(t, 0, sizeof(*t)); + t = calloc(1, sizeof(*t)); archive_string_init(&(t->full_path)); archive_string_init(&t->path); archive_wstring_ensure(&t->path, 15); @@ -1522,7 +1509,7 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) struct archive_wstring ws; wchar_t *pathname, *p, *base; - t->flags = (restore_time)?needsRestoreTimes:0; + t->flags = (restore_time != 0)?needsRestoreTimes:0; t->visit_type = 0; t->tree_errno = 0; t->full_path_dir_length = 0; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_extract2.c b/Utilities/cmlibarchive/libarchive/archive_read_extract2.c index 7b2c12631..4febd8ce0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_extract2.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_extract2.c @@ -52,12 +52,11 @@ struct archive_read_extract * __archive_read_get_extract(struct archive_read *a) { if (a->extract == NULL) { - a->extract = (struct archive_read_extract *)malloc(sizeof(*a->extract)); + a->extract = (struct archive_read_extract *)calloc(1, sizeof(*a->extract)); if (a->extract == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't extract"); return (NULL); } - memset(a->extract, 0, sizeof(*a->extract)); a->cleanup_archive_extract = archive_read_extract_cleanup; } return (a->extract); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c index 5611aa85a..86635e219 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c @@ -222,7 +222,7 @@ file_open(struct archive *a, void *client_data) void *buffer; const char *filename = NULL; const wchar_t *wfilename = NULL; - int fd; + int fd = -1; int is_disk_like = 0; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */ @@ -277,7 +277,7 @@ file_open(struct archive *a, void *client_data) #else archive_set_error(a, ARCHIVE_ERRNO_MISC, "Unexpedted operation in archive_read_open_filename"); - return (ARCHIVE_FATAL); + goto fail; #endif } if (fstat(fd, &st) != 0) { @@ -287,7 +287,7 @@ file_open(struct archive *a, void *client_data) else archive_set_error(a, errno, "Can't stat '%s'", filename); - return (ARCHIVE_FATAL); + goto fail; } /* @@ -356,11 +356,9 @@ file_open(struct archive *a, void *client_data) mine->block_size = new_block_size; } buffer = malloc(mine->block_size); - if (mine == NULL || buffer == NULL) { + if (buffer == NULL) { archive_set_error(a, ENOMEM, "No memory"); - free(mine); - free(buffer); - return (ARCHIVE_FATAL); + goto fail; } mine->buffer = buffer; mine->fd = fd; @@ -372,6 +370,14 @@ file_open(struct archive *a, void *client_data) mine->use_lseek = 1; return (ARCHIVE_OK); +fail: + /* + * Don't close file descriptors not opened or ones pointing referring + * to `FNT_STDIN`. + */ + if (fd != -1 && fd != 0) + close(fd); + return (ARCHIVE_FATAL); } static ssize_t diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c index ff935a708..311be4704 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c @@ -70,12 +70,11 @@ archive_read_open_memory2(struct archive *a, const void *buff, { struct read_memory_data *mine; - mine = (struct read_memory_data *)malloc(sizeof(*mine)); + mine = (struct read_memory_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } - memset(mine, 0, sizeof(*mine)); mine->start = mine->p = (const unsigned char *)buff; mine->end = mine->start + size; mine->read_size = read_size; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_private.h b/Utilities/cmlibarchive/libarchive/archive_read_private.h index 9b61a5380..78546dca3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_read_private.h @@ -221,7 +221,7 @@ struct archive_read { struct { struct archive_read_passphrase *first; struct archive_read_passphrase **last; - int candiate; + int candidate; archive_passphrase_callback *callback; void *client_data; } passphrases; @@ -252,7 +252,6 @@ int64_t __archive_read_consume(struct archive_read *, int64_t); int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t); int __archive_read_program(struct archive_read_filter *, const char *); void __archive_read_free_filters(struct archive_read *); -int __archive_read_close_filters(struct archive_read *); struct archive_read_extract *__archive_read_get_extract(struct archive_read *); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c index e877917b9..663e2d3d6 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c @@ -180,7 +180,7 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, return (0); bits_checked += 8; BD = buffer[5]; - /* A block maximum size shuld be more than 3. */ + /* A block maximum size should be more than 3. */ if (((BD & 0x70) >> 4) < 4) return (0); /* Reserved bits must be "0". */ @@ -417,7 +417,7 @@ lz4_filter_read_descriptor(struct archive_read_filter *self) /* Reserved bits must be zero. */ if (bd & 0x8f) goto malformed_error; - /* Get a maxinum block size. */ + /* Get a maximum block size. */ switch (read_buf[1] >> 4) { case 4: /* 64 KB */ state->flags.block_maximum_size = 64 * 1024; @@ -595,7 +595,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) #endif } - /* Check if an error happend in decompression process. */ + /* Check if an error occurred in the decompression process. */ if (uncompressed_size < 0) { archive_set_error(&(self->archive->archive), ARCHIVE_ERRNO_MISC, "lz4 decompression failed"); @@ -627,7 +627,7 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) if (state->stage == SELECT_STREAM) { state->stage = READ_DEFAULT_STREAM; - /* First, read a desciprtor. */ + /* First, read a descriptor. */ if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK) return (ret); state->stage = READ_DEFAULT_BLOCK; @@ -706,6 +706,11 @@ lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p) /* Make sure we have a whole block. */ read_buf = __archive_read_filter_ahead(self->upstream, 4 + compressed, NULL); + if (read_buf == NULL) { + archive_set_error(&(self->archive->archive), + ARCHIVE_ERRNO_MISC, "truncated lz4 input"); + return (ARCHIVE_FATAL); + } ret = LZ4_decompress_safe(read_buf + 4, state->out_block, compressed, (int)state->out_block_size); if (ret < 0) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c index 23c18c7fb..4356b82fd 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c @@ -436,7 +436,7 @@ lzop_filter_read(struct archive_read_filter *self, const void **p) } /* - * Drive lzo uncompresison. + * Drive lzo uncompression. */ out_size = (lzo_uint)state->uncompressed_size; r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c index 66dc2f424..b8bf12886 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c @@ -430,6 +430,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) &state->child_stdout); if (child == -1) { free(state->out_buf); + archive_string_free(&state->description); free(state); archive_set_error(&self->archive->archive, EINVAL, "Can't initialize filter; unable to run program \"%s\"", @@ -441,6 +442,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) if (state->child == NULL) { child_stop(self, state); free(state->out_buf); + archive_string_free(&state->description); free(state); archive_set_error(&self->archive->archive, EINVAL, "Can't initialize filter; unable to run program \"%s\"", diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c index 787a619f2..641297990 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c @@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self, avail -= len; if (l == 6) { + /* "begin " */ if (!uuchar[*b]) return (0); /* Get a length of decoded bytes. */ @@ -319,30 +320,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self, if (l > 45) /* Normally, maximum length is 45(character 'M'). */ return (0); - while (l && len-nl > 0) { - if (l > 0) { - if (!uuchar[*b++]) - return (0); - if (!uuchar[*b++]) - return (0); - len -= 2; - --l; - } - if (l > 0) { - if (!uuchar[*b++]) - return (0); - --len; - --l; - } - if (l > 0) { - if (!uuchar[*b++]) - return (0); - --len; - --l; - } + if (l > len - nl) + return (0); /* Line too short. */ + while (l) { + if (!uuchar[*b++]) + return (0); + --len; + --l; } - if (len-nl < 0) - return (0); if (len-nl == 1 && (uuchar[*b] || /* Check sum. */ (*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */ @@ -352,8 +337,8 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self, b += nl; if (avail && uuchar[*b]) return (firstline+30); - } - if (l == 13) { + } else if (l == 13) { + /* "begin-base64 " */ while (len-nl > 0) { if (!base64[*b++]) return (0); @@ -510,6 +495,13 @@ read_more: } llen = len; if ((nl == 0) && (uudecode->state != ST_UUEND)) { + if (total == 0 && ravail <= 0) { + /* There is nothing more to read, fail */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Missing format data"); + return (ARCHIVE_FATAL); + } /* * Save remaining data which does not contain * NL('\n','\r'). @@ -566,7 +558,7 @@ read_more: "Insufficient compressed data"); return (ARCHIVE_FATAL); } - /* Get length of undecoded bytes of curent line. */ + /* Get length of undecoded bytes of current line. */ l = UUDECODE(*b++); body--; if (l > body) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c index 8f48273ed..a18818638 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c @@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$"); #endif #if HAVE_LZMA_H #include -#elif HAVE_LZMADEC_H -#include #endif #include "archive.h" @@ -82,19 +80,6 @@ static ssize_t xz_filter_read(struct archive_read_filter *, const void **); static int xz_filter_close(struct archive_read_filter *); static int xz_lzma_bidder_init(struct archive_read_filter *); -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - -struct private_data { - lzmadec_stream stream; - unsigned char *out_block; - size_t out_block_size; - int64_t total_out; - char eof; /* True = found end of compressed data. */ -}; - -/* Lzma-only filter */ -static ssize_t lzma_filter_read(struct archive_read_filter *, const void **); -static int lzma_filter_close(struct archive_read_filter *); #endif /* @@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct archive *_a) bidder->free = NULL; #if HAVE_LZMA_H && HAVE_LIBLZMA return (ARCHIVE_OK); -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - return (ARCHIVE_OK); #else archive_set_error(_a, ARCHIVE_ERRNO_MISC, "Using external lzma program for lzma decompression"); @@ -310,7 +293,7 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self, /* Second through fifth bytes are dictionary size, stored in * little-endian order. The minimum dictionary size is * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option - * -d12 and the maxinam dictionary size is 1 << 27(128MiB) + * -d12 and the maximum dictionary size is 1 << 27(128MiB) * which the one uses with option -d27. * NOTE: A comment of LZMA SDK source code says this dictionary * range is from 1 << 12 to 1 << 30. */ @@ -601,9 +584,7 @@ lzip_init(struct archive_read_filter *self) return (ARCHIVE_FATAL); } ret = lzma_raw_decoder(&(state->stream), filters); -#if LZMA_VERSION < 50010000 free(filters[0].options); -#endif if (ret != LZMA_OK) { set_error(self, ret); return (ARCHIVE_FATAL); @@ -763,175 +744,6 @@ xz_filter_close(struct archive_read_filter *self) #else -#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC - -/* - * If we have the older liblzmadec library, then we can handle - * LZMA streams but not XZ streams. - */ - -/* - * Setup the callbacks. - */ -static int -lzma_bidder_init(struct archive_read_filter *self) -{ - static const size_t out_block_size = 64 * 1024; - void *out_block; - struct private_data *state; - ssize_t ret, avail_in; - - self->code = ARCHIVE_FILTER_LZMA; - self->name = "lzma"; - - state = (struct private_data *)calloc(sizeof(*state), 1); - out_block = (unsigned char *)malloc(out_block_size); - if (state == NULL || out_block == NULL) { - archive_set_error(&self->archive->archive, ENOMEM, - "Can't allocate data for lzma decompression"); - free(out_block); - free(state); - return (ARCHIVE_FATAL); - } - - self->data = state; - state->out_block_size = out_block_size; - state->out_block = out_block; - self->read = lzma_filter_read; - self->skip = NULL; /* not supported */ - self->close = lzma_filter_close; - - /* Prime the lzma library with 18 bytes of input. */ - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 18, &avail_in); - if (state->stream.next_in == NULL) - return (ARCHIVE_FATAL); - state->stream.avail_in = avail_in; - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Initialize compression library. */ - ret = lzmadec_init(&(state->stream)); - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - if (ret == LZMADEC_OK) - return (ARCHIVE_OK); - - /* Library setup failed: Clean up. */ - archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, - "Internal error initializing lzma library"); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&self->archive->archive, ENOMEM, - "Internal error initializing compression library: " - "out of memory"); - break; - } - - free(state->out_block); - free(state); - self->data = NULL; - return (ARCHIVE_FATAL); -} - -/* - * Return the next block of decompressed data. - */ -static ssize_t -lzma_filter_read(struct archive_read_filter *self, const void **p) -{ - struct private_data *state; - size_t decompressed; - ssize_t avail_in, ret; - - state = (struct private_data *)self->data; - - /* Empty our output buffer. */ - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Try to fill the output buffer. */ - while (state->stream.avail_out > 0 && !state->eof) { - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 1, &avail_in); - if (state->stream.next_in == NULL && avail_in < 0) { - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "truncated lzma input"); - return (ARCHIVE_FATAL); - } - state->stream.avail_in = avail_in; - - /* Decompress as much as we can in one pass. */ - ret = lzmadec_decode(&(state->stream), avail_in == 0); - switch (ret) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - state->eof = 1; - /* FALL THROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - break; - case LZMADEC_BUF_ERROR: /* Insufficient input data? */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Insufficient compressed data"); - return (ARCHIVE_FATAL); - default: - /* Return an error. */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Lzma decompression failed"); - return (ARCHIVE_FATAL); - } - } - - decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; - if (decompressed == 0) - *p = NULL; - else - *p = state->out_block; - return (decompressed); -} - -/* - * Clean up the decompressor. - */ -static int -lzma_filter_close(struct archive_read_filter *self) -{ - struct private_data *state; - int ret; - - state = (struct private_data *)self->data; - ret = ARCHIVE_OK; - switch (lzmadec_end(&(state->stream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(self->archive->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up %s compressor", - self->archive->archive.compression_name); - ret = ARCHIVE_FATAL; - } - - free(state->out_block); - free(state); - return (ret); -} - -#else - /* * * If we have no suitable library on this system, we can't actually do @@ -953,9 +765,6 @@ lzma_bidder_init(struct archive_read_filter *self) return (r); } -#endif /* HAVE_LZMADEC_H */ - - static int xz_bidder_init(struct archive_read_filter *self) { @@ -984,5 +793,4 @@ lzip_bidder_init(struct archive_read_filter *self) return (r); } - #endif /* HAVE_LZMA_H */ diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c index a33ea4fd4..96774f4e3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c @@ -213,7 +213,7 @@ struct _7zip { int header_is_encoded; uint64_t header_bytes_remaining; unsigned long header_crc32; - /* Header offset to check that reading pointes of the file contens + /* Header offset to check that reading points of the file contents * will not exceed the header. */ uint64_t header_offset; /* Base offset of the archive file for a seek in case reading SFX. */ @@ -263,22 +263,22 @@ struct _7zip { /* * Decompressor controllers. */ - /* Decording LZMA1 and LZMA2 data. */ + /* Decoding LZMA1 and LZMA2 data. */ #ifdef HAVE_LZMA_H lzma_stream lzstream; int lzstream_valid; #endif - /* Decording bzip2 data. */ + /* Decoding bzip2 data. */ #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) bz_stream bzstream; int bzstream_valid; #endif - /* Decording deflate data. */ + /* Decoding deflate data. */ #ifdef HAVE_ZLIB_H z_stream stream; int stream_valid; #endif - /* Decording PPMd data. */ + /* Decoding PPMd data. */ int ppmd7_stat; CPpmd7 ppmd7_context; CPpmd7z_RangeDec range_dec; @@ -552,7 +552,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail) /* * If bytes_avail > SFX_MIN_ADDR we do not have to call * __archive_read_seek() at this time since we have - * alredy had enough data. + * already had enough data. */ if (bytes_avail > SFX_MIN_ADDR) __archive_read_consume(a, SFX_MIN_ADDR); @@ -760,7 +760,7 @@ archive_read_format_7zip_read_header(struct archive_read *a, symsize += size; } if (symsize == 0) { - /* If there is no synname, handle it as a regular + /* If there is no symname, handle it as a regular * file. */ zip_entry->mode &= ~AE_IFMT; zip_entry->mode |= AE_IFREG; @@ -1056,10 +1056,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, #endif { lzma_options_delta delta_opt; - lzma_filter filters[LZMA_FILTERS_MAX]; -#if LZMA_VERSION < 50010000 - lzma_filter *ff; -#endif + lzma_filter filters[LZMA_FILTERS_MAX], *ff; int fi = 0; if (zip->lzstream_valid) { @@ -1144,9 +1141,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, else filters[fi].id = LZMA_FILTER_LZMA1; filters[fi].options = NULL; -#if LZMA_VERSION < 50010000 ff = &filters[fi]; -#endif r = lzma_properties_decode(&filters[fi], NULL, coder1->properties, (size_t)coder1->propertiesSize); if (r != LZMA_OK) { @@ -1158,9 +1153,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, filters[fi].id = LZMA_VLI_UNKNOWN; filters[fi].options = NULL; r = lzma_raw_decoder(&(zip->lzstream), filters); -#if LZMA_VERSION < 50010000 free(ff->options); -#endif if (r != LZMA_OK) { set_error(a, r); return (ARCHIVE_FAILED); @@ -2431,6 +2424,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, switch (type) { case kEmptyStream: + if (h->emptyStreamBools != NULL) + return (-1); h->emptyStreamBools = calloc((size_t)zip->numFiles, sizeof(*h->emptyStreamBools)); if (h->emptyStreamBools == NULL) @@ -2451,6 +2446,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, return (-1); break; } + if (h->emptyFileBools != NULL) + return (-1); h->emptyFileBools = calloc(empty_streams, sizeof(*h->emptyFileBools)); if (h->emptyFileBools == NULL) @@ -2465,6 +2462,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, return (-1); break; } + if (h->antiBools != NULL) + return (-1); h->antiBools = calloc(empty_streams, sizeof(*h->antiBools)); if (h->antiBools == NULL) @@ -2491,6 +2490,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if ((ll & 1) || ll < zip->numFiles * 4) return (-1); + if (zip->entry_names != NULL) + return (-1); zip->entry_names = malloc(ll); if (zip->entry_names == NULL) return (-1); @@ -2543,6 +2544,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if ((p = header_bytes(a, 2)) == NULL) return (-1); allAreDefined = *p; + if (h->attrBools != NULL) + return (-1); h->attrBools = calloc((size_t)zip->numFiles, sizeof(*h->attrBools)); if (h->attrBools == NULL) @@ -3285,7 +3288,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size, return (r); /* - * Skip the bytes we alrady has skipped in skip_stream(). + * Skip the bytes we already has skipped in skip_stream(). */ while (skip_bytes) { ssize_t skipped; @@ -3503,7 +3506,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, return (ARCHIVE_FATAL); } - /* Allocate memory for the decorded data of a sub + /* Allocate memory for the decoded data of a sub * stream. */ b[i] = malloc((size_t)zip->folder_outbytes_remaining); if (b[i] == NULL) { @@ -3588,7 +3591,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes) if (zip->folder_index == 0) { /* * Optimization for a list mode. - * Avoid unncecessary decoding operations. + * Avoid unnecessary decoding operations. */ zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes += skip_bytes; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c index 4b5b66bd5..b6b9fc3c6 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c @@ -104,13 +104,12 @@ archive_read_support_format_ar(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_ar"); - ar = (struct ar *)malloc(sizeof(*ar)); + ar = (struct ar *)calloc(1, sizeof(*ar)); if (ar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data"); return (ARCHIVE_FATAL); } - memset(ar, 0, sizeof(*ar)); ar->strtab = NULL; r = __archive_read_register_format(a, @@ -260,7 +259,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry, archive_entry_set_filetype(entry, AE_IFREG); /* Get the size of the filename table. */ number = ar_atol10(h + AR_size_offset, AR_size_size); - if (number > SIZE_MAX) { + if (number > SIZE_MAX || number > 1024 * 1024 * 1024) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Filename table too large"); return (ARCHIVE_FATAL); @@ -316,7 +315,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry, * If we can't look up the real name, warn and return * the entry with the wrong name. */ - if (ar->strtab == NULL || number > ar->strtab_size) { + if (ar->strtab == NULL || number >= ar->strtab_size) { archive_set_error(&a->archive, EINVAL, "Can't find long filename for GNU/SVR4 archive entry"); archive_entry_copy_pathname(entry, filename); @@ -342,16 +341,19 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry, /* Parse the size of the name, adjust the file size. */ number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); - bsd_name_length = (size_t)number; - /* Guard against the filename + trailing NUL - * overflowing a size_t and against the filename size - * being larger than the entire entry. */ - if (number > (uint64_t)(bsd_name_length + 1) - || (int64_t)bsd_name_length > ar->entry_bytes_remaining) { + /* Sanity check the filename length: + * = Must be <= SIZE_MAX - 1 + * = Must be <= 1MB + * = Cannot be bigger than the entire entry + */ + if (number > SIZE_MAX - 1 + || number > 1024 * 1024 + || (int64_t)number > ar->entry_bytes_remaining) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Bad input file size"); return (ARCHIVE_FATAL); } + bsd_name_length = (size_t)number; ar->entry_bytes_remaining -= bsd_name_length; /* Adjust file size reported to client. */ archive_entry_set_size(entry, ar->entry_bytes_remaining); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c index 63569635e..20eb157f2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c @@ -67,7 +67,7 @@ struct lzx_dec { /* The length how many bytes we can copy decoded code from * the window. */ int copy_len; - /* Translation reversal for x86 proccessor CALL byte sequence(E8). + /* Translation reversal for x86 processor CALL byte sequence(E8). * This is used for LZX only. */ uint32_t translation_size; char translation; @@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a) cab = (struct cab *)(a->format->data); if (cab->found_header == 0 && p[0] == 'M' && p[1] == 'Z') { - /* This is an executable? Must be self-extracting... */ + /* This is an executable? Must be self-extracting... */ err = cab_skip_sfx(a); if (err < ARCHIVE_WARN) return (err); - if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) + /* Re-read header after processing the SFX. */ + if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) return (truncated_error(a)); } @@ -1494,6 +1495,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) /* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */ if (mszip > 0) { + if (bytes_avail <= 0) + goto nomszip; if (bytes_avail <= mszip) { if (mszip == 2) { if (cab->stream.next_in[0] != 0x43) @@ -1554,7 +1557,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) /* * Note: I suspect there is a bug in makecab.exe because, in rare * case, compressed bytes are still remaining regardless we have - * gotten all uncompressed bytes, which size is recoded in CFDATA, + * gotten all uncompressed bytes, which size is recorded in CFDATA, * as much as we need, and we have to use the garbage so as to * correctly compute the sum of CFDATA accordingly. */ @@ -1741,7 +1744,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) } /* - * Translation reversal of x86 proccessor CALL byte sequence(E8). + * Translation reversal of x86 processor CALL byte sequence(E8). */ lzx_translation(&cab->xstrm, cab->uncompressed_buffer, cfdata->uncompressed_size, @@ -2270,7 +2273,7 @@ static int lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br) { /* - * x86 proccessor family can read misaligned data without an access error. + * x86 processor family can read misaligned data without an access error. */ int n = CACHE_BITS - br->cache_avail; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c index b09db0e9a..ffd4a8580 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c @@ -326,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a, cpio = (struct cpio *)(a->format->data); if (strcmp(key, "compat-2x") == 0) { - /* Handle filnames as libarchive 2.x */ + /* Handle filenames as libarchive 2.x */ cpio->init_default_conversion = (val != NULL)?1:0; return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { @@ -356,7 +356,7 @@ archive_read_format_cpio_read_header(struct archive_read *a, struct archive_entry *entry) { struct cpio *cpio; - const void *h; + const void *h, *hl; struct archive_string_conv *sconv; size_t namelength; size_t name_pad; @@ -406,11 +406,11 @@ archive_read_format_cpio_read_header(struct archive_read *a, "Rejecting malformed cpio archive: symlink contents exceed 1 megabyte"); return (ARCHIVE_FATAL); } - h = __archive_read_ahead(a, + hl = __archive_read_ahead(a, (size_t)cpio->entry_bytes_remaining, NULL); - if (h == NULL) + if (hl == NULL) return (ARCHIVE_FATAL); - if (archive_entry_copy_symlink_l(entry, (const char *)h, + if (archive_entry_copy_symlink_l(entry, (const char *)hl, (size_t)cpio->entry_bytes_remaining, sconv) != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, @@ -434,7 +434,8 @@ archive_read_format_cpio_read_header(struct archive_read *a, * header. XXX */ /* Compare name to "TRAILER!!!" to test for end-of-archive. */ - if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) { + if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!", + 11) == 0) { /* TODO: Store file location of start of block. */ archive_clear_error(&a->archive); return (ARCHIVE_EOF); @@ -814,8 +815,8 @@ header_odc(struct archive_read *a, struct cpio *cpio, * NOTE: if a filename suffix is ".z", it is the file gziped by afio. * it would be nice that we can show uncompressed file size and we can * uncompressed file contents automatically, unfortunately we have nothing - * to get a uncompressed file size while reading each header. it means - * we also cannot uncompressed file contens under the our framework. + * to get a uncompressed file size while reading each header. It means + * we also cannot uncompress file contents under our framework. */ static int header_afiol(struct archive_read *a, struct cpio *cpio, diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c index c19614ad9..354133005 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c @@ -322,7 +322,7 @@ struct iso9660 { struct archive_string pathname; char seenRockridge; /* Set true if RR extensions are used. */ - char seenSUSP; /* Set true if SUSP is beging used. */ + char seenSUSP; /* Set true if SUSP is being used. */ char seenJoliet; unsigned char suspOffset; @@ -374,7 +374,7 @@ struct iso9660 { size_t utf16be_path_len; unsigned char *utf16be_previous_path; size_t utf16be_previous_path_len; - /* Null buufer used in bidder to improve its performance. */ + /* Null buffer used in bidder to improve its performance. */ unsigned char null[2048]; }; @@ -1199,7 +1199,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a, archive_string_conversion_from_charset( &(a->archive), "UTF-16BE", 1); if (iso9660->sconv_utf16be == NULL) - /* Coundn't allocate memory */ + /* Couldn't allocate memory */ return (ARCHIVE_FATAL); } if (iso9660->utf16be_path == NULL) { @@ -1864,7 +1864,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, if ((file->utf16be_name = malloc(name_len)) == NULL) { archive_set_error(&a->archive, ENOMEM, "No memory for file name"); - return (NULL); + goto fail; } memcpy(file->utf16be_name, p, name_len); file->utf16be_bytes = name_len; @@ -1943,10 +1943,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent, file->symlink_continues = 0; rr_start += iso9660->suspOffset; r = parse_rockridge(a, file, rr_start, rr_end); - if (r != ARCHIVE_OK) { - free(file); - return (NULL); - } + if (r != ARCHIVE_OK) + goto fail; /* * A file size of symbolic link files in ISO images * made by makefs is not zero and its location is @@ -1990,7 +1988,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge RE"); - return (NULL); + goto fail; } /* * Sanity check: file does not have "CL" extension. @@ -1999,7 +1997,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge RE and CL"); - return (NULL); + goto fail; } /* * Sanity check: The file type must be a directory. @@ -2008,7 +2006,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge RE"); - return (NULL); + goto fail; } } else if (parent != NULL && parent->rr_moved) file->rr_moved_has_re_only = 0; @@ -2022,7 +2020,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } /* * Sanity check: The file type must be a regular file. @@ -2031,7 +2029,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } parent->subdirs++; /* Overwrite an offset and a number of this "CL" entry @@ -2049,7 +2047,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } } if (file->cl_offset == file->offset || @@ -2057,7 +2055,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } } } @@ -2088,6 +2086,10 @@ parse_file_info(struct archive_read *a, struct file_info *parent, #endif register_file(iso9660, file); return (file); +fail: + archive_string_free(&file->name); + free(file); + return (NULL); } static int @@ -2407,7 +2409,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660) return (ARCHIVE_FATAL); } while (heap->cnt && heap->reqs[0].offset == iso9660->current_position); - /* NOTE: Do not move this consume's code to fron of + /* NOTE: Do not move this consume's code to front of * do-while loop. Registration of nested CE extension * might cause error because of current position. */ __archive_read_consume(a, step); @@ -2729,7 +2731,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, if (file == NULL) { /* * If directory entries all which are descendant of - * rr_moved are stil remaning, expose their. + * rr_moved are still remaining, expose their. */ if (iso9660->re_files.first != NULL && iso9660->rr_moved != NULL && @@ -2852,7 +2854,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, empty_files.last = &empty_files.first; /* Collect files which has the same file serial number. * Peek pending_files so that file which number is different - * is not put bak. */ + * is not put back. */ while (iso9660->pending_files.used > 0 && (iso9660->pending_files.files[0]->number == -1 || iso9660->pending_files.files[0]->number == number)) { @@ -2860,7 +2862,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, /* This file has the same offset * but it's wrong offset which empty files * and symlink files have. - * NOTE: This wrong offse was recorded by + * NOTE: This wrong offset was recorded by * old mkisofs utility. If ISO images is * created by latest mkisofs, this does not * happen. diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c index eff02d814..ebd7f2ccb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c @@ -924,6 +924,9 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha) /* Get a real compressed file size. */ lha->compsize -= extdsize - 2; + if (lha->compsize < 0) + goto invalid; /* Invalid compressed file size */ + if (sum_calculated != headersum) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "LHa header sum error"); @@ -1711,14 +1714,18 @@ lha_crc16(uint16_t crc, const void *pp, size_t len) */ for (;len >= 8; len -= 8) { /* This if statement expects compiler optimization will - * remove the stament which will not be executed. */ + * remove the statement which will not be executed. */ +#undef bswap16 #ifndef __has_builtin # define __has_builtin(x) 0 #endif #if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */ # define bswap16(x) _byteswap_ushort(x) -#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \ - || (defined(__clang__) && __has_builtin(__builtin_bswap16)) +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) +/* GCC 4.8 and later has __builtin_bswap16() */ +# define bswap16(x) __builtin_bswap16(x) +#elif defined(__clang__) && __has_builtin(__builtin_bswap16) +/* All clang versions have __builtin_bswap16() */ # define bswap16(x) __builtin_bswap16(x) #else # define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8)) diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c index 8c3be9a29..4231ff500 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c @@ -75,6 +75,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011 #define MTREE_HAS_OPTIONAL 0x0800 #define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */ +#define MTREE_HASHTABLE_SIZE 1024 + struct mtree_option { struct mtree_option *next; char *value; @@ -86,6 +88,8 @@ struct mtree_entry { char *name; char full; char used; + unsigned int name_hash; + struct mtree_entry *hashtable_next; }; struct mtree { @@ -98,6 +102,7 @@ struct mtree { const char *archive_format_name; struct mtree_entry *entries; struct mtree_entry *this_entry; + struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE]; struct archive_string current_dir; struct archive_string contents_name; @@ -110,6 +115,7 @@ struct mtree { static int bid_keycmp(const char *, const char *, ssize_t); static int cleanup(struct archive_read *); static int detect_form(struct archive_read *, int *); +static unsigned int hash(const char *); static int mtree_bid(struct archive_read *, int); static int parse_file(struct archive_read *, struct archive_entry *, struct mtree *, struct mtree_entry *, int *); @@ -223,13 +229,12 @@ archive_read_support_format_mtree(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_mtree"); - mtree = (struct mtree *)malloc(sizeof(*mtree)); + mtree = (struct mtree *)calloc(1, sizeof(*mtree)); if (mtree == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate mtree data"); return (ARCHIVE_FATAL); } - memset(mtree, 0, sizeof(*mtree)); mtree->fd = -1; r = __archive_read_register_format(a, mtree, "mtree", @@ -301,6 +306,15 @@ get_line_size(const char *b, ssize_t avail, ssize_t *nlsize) return (avail); } +/* + * <---------------- ravail ---------------------> + * <-- diff ------> <--- avail -----------------> + * <---- len -----------> + * | Previous lines | line being parsed nl extra | + * ^ + * b + * + */ static ssize_t next_line(struct archive_read *a, const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl) @@ -339,7 +353,7 @@ next_line(struct archive_read *a, *b += diff; *avail -= diff; tested = len;/* Skip some bytes we already determinated. */ - len = get_line_size(*b, *avail, nl); + len = get_line_size(*b + len, *avail - len, nl); if (len >= 0) len += tested; } @@ -701,13 +715,13 @@ detect_form(struct archive_read *a, int *is_form_d) } } else break; - } else if (strncmp(p, "/set", 4) == 0) { + } else if (len > 4 && strncmp(p, "/set", 4) == 0) { if (bid_keyword_list(p+4, len-4, 0, 0) <= 0) break; /* This line continues. */ if (p[len-nl-1] == '\\') multiline = 2; - } else if (strncmp(p, "/unset", 6) == 0) { + } else if (len > 6 && strncmp(p, "/unset", 6) == 0) { if (bid_keyword_list(p+6, len-6, 1, 0) <= 0) break; /* This line continues. */ @@ -853,11 +867,12 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, struct mtree_option **global, const char *line, ssize_t line_len, struct mtree_entry **last_entry, int is_form_d) { - struct mtree_entry *entry; + struct mtree_entry *entry, *ht_iter; struct mtree_option *iter; const char *next, *eq, *name, *end; size_t name_len, len; int r, i; + unsigned int ht_idx; if ((entry = malloc(sizeof(*entry))) == NULL) { archive_set_error(&a->archive, errno, "Can't allocate memory"); @@ -868,6 +883,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, entry->name = NULL; entry->used = 0; entry->full = 0; + entry->name_hash = 0; + entry->hashtable_next = NULL; /* Add this entry to list. */ if (*last_entry == NULL) @@ -920,6 +937,16 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, memcpy(entry->name, name, name_len); entry->name[name_len] = '\0'; parse_escapes(entry->name, entry); + entry->name_hash = hash(entry->name); + + ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE; + if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) { + while (ht_iter->hashtable_next) + ht_iter = ht_iter->hashtable_next; + ht_iter->hashtable_next = entry; + } else { + mtree->entry_hashtable[ht_idx] = entry; + } for (iter = *global; iter != NULL; iter = iter->next) { r = add_option(a, &entry->options, iter->value, @@ -992,11 +1019,11 @@ read_mtree(struct archive_read *a, struct mtree *mtree) if (*p != '/') { r = process_add_entry(a, mtree, &global, p, len, &last_entry, is_form_d); - } else if (strncmp(p, "/set", 4) == 0) { + } else if (len > 4 && strncmp(p, "/set", 4) == 0) { if (p[4] != ' ' && p[4] != '\t') break; r = process_global_set(a, &global, p); - } else if (strncmp(p, "/unset", 6) == 0) { + } else if (len > 6 && strncmp(p, "/unset", 6) == 0) { if (p[6] != ' ' && p[6] != '\t') break; r = process_global_unset(a, &global, p); @@ -1113,9 +1140,10 @@ parse_file(struct archive_read *a, struct archive_entry *entry, * with pathname canonicalization, which is a very * tricky subject.) */ - for (mp = mentry->next; mp != NULL; mp = mp->next) { + for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) { if (mp->full && !mp->used - && strcmp(mentry->name, mp->name) == 0) { + && mentry->name_hash == mp->name_hash + && strcmp(mentry->name, mp->name) == 0) { /* Later lines override earlier ones. */ mp->used = 1; r1 = parse_line(a, entry, mtree, mp, @@ -1580,8 +1608,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, if (*val == '.') { ++val; ns = (long)mtree_atol10(&val); - } else - ns = 0; + if (ns < 0) + ns = 0; + else if (ns > 999999999) + ns = 999999999; + } if (m > my_time_t_max) m = my_time_t_max; else if (m < my_time_t_min) @@ -1991,3 +2022,19 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, find_off = u - mtree->line.s; } } + +static unsigned int +hash(const char *p) +{ + /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm, + as used by ELF for hashing function names. */ + unsigned g, h = 0; + while (*p != '\0') { + h = (h << 4) + *p++; + if ((g = h & 0xF0000000) != 0) { + h ^= g >> 24; + h &= 0x0FFFFFFF; + } + } + return h; +} diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c index fc8153f5b..658d49d50 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c @@ -647,13 +647,12 @@ archive_read_support_format_rar(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_rar"); - rar = (struct rar *)malloc(sizeof(*rar)); + rar = (struct rar *)calloc(sizeof(*rar), 1); if (rar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data"); return (ARCHIVE_FATAL); } - memset(rar, 0, sizeof(*rar)); /* * Until enough data has been read, we cannot tell about @@ -907,7 +906,7 @@ archive_read_format_rar_read_header(struct archive_read *a, sizeof(rar->reserved2)); } - /* Main header is password encrytped, so we cannot read any + /* Main header is password encrypted, so we cannot read any file names or any other info about files from the header. */ if (rar->main_flags & MHD_PASSWORD) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c index b0521a627..bd7f13d52 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,6 +137,7 @@ struct tar { int64_t entry_padding; int64_t entry_bytes_unconsumed; int64_t realsize; + int sparse_allowed; struct sparse_block *sparse_list; struct sparse_block *sparse_last; int64_t sparse_offset; @@ -202,9 +204,14 @@ static int archive_read_format_tar_read_header(struct archive_read *, struct archive_entry *); static int checksum(struct archive_read *, const void *); static int pax_attribute(struct archive_read *, struct tar *, - struct archive_entry *, const char *key, const char *value); + struct archive_entry *, const char *key, const char *value, + size_t value_length); +static int pax_attribute_acl(struct archive_read *, struct tar *, + struct archive_entry *, const char *, int); +static int pax_attribute_xattr(struct archive_entry *, const char *, + const char *); static int pax_header(struct archive_read *, struct tar *, - struct archive_entry *, char *attr); + struct archive_entry *, struct archive_string *); static void pax_time(const char *, int64_t *sec, long *nanos); static ssize_t readline(struct archive_read *, struct tar *, const char **, ssize_t limit, size_t *); @@ -293,6 +300,57 @@ archive_read_format_tar_cleanup(struct archive_read *a) return (ARCHIVE_OK); } +/* + * Validate number field + * + * This has to be pretty lenient in order to accommodate the enormous + * variety of tar writers in the world: + * = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading + * zeros and allows fields to be terminated with space or null characters + * = Many writers use different termination (in particular, libarchive + * omits terminator bytes to squeeze one or two more digits) + * = Many writers pad with space and omit leading zeros + * = GNU tar and star write base-256 values if numbers are too + * big to be represented in octal + * + * Examples of specific tar headers that we should support: + * = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two + * null bytes, pads size with spaces and other numeric fields with zeroes + * = plexus-archiver prior to 2.6.3 (before switching to commons-compress) + * may have uid and gid fields filled with spaces without any octal digits + * at all and pads all numeric fields with spaces + * + * This should tolerate all variants in use. It will reject a field + * where the writer just left garbage after a trailing NUL. + */ +static int +validate_number_field(const char* p_field, size_t i_size) +{ + unsigned char marker = (unsigned char)p_field[0]; + if (marker == 128 || marker == 255 || marker == 0) { + /* Base-256 marker, there's nothing we can check. */ + return 1; + } else { + /* Must be octal */ + size_t i = 0; + /* Skip any leading spaces */ + while (i < i_size && p_field[i] == ' ') { + ++i; + } + /* Skip octal digits. */ + while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') { + ++i; + } + /* Any remaining characters must be space or NUL padding. */ + while (i < i_size) { + if (p_field[i] != ' ' && p_field[i] != 0) { + return 0; + } + ++i; + } + return 1; + } +} static int archive_read_format_tar_bid(struct archive_read *a, int best_bid) @@ -345,23 +403,19 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid) return (0); bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */ - /* Sanity check: Look at first byte of mode field. */ - switch (255 & (unsigned)header->mode[0]) { - case 0: case 255: - /* Base-256 value: No further verification possible! */ - break; - case ' ': /* Not recommended, but not illegal, either. */ - break; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - /* Octal Value. */ - /* TODO: Check format of remainder of this field. */ - break; - default: - /* Not a valid mode; bail out here. */ - return (0); + /* + * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields. + */ + if (bid > 0 && ( + validate_number_field(header->mode, sizeof(header->mode)) == 0 + || validate_number_field(header->uid, sizeof(header->uid)) == 0 + || validate_number_field(header->gid, sizeof(header->gid)) == 0 + || validate_number_field(header->mtime, sizeof(header->mtime)) == 0 + || validate_number_field(header->size, sizeof(header->size)) == 0 + || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0 + || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) { + bid = 0; } - /* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */ return (bid); } @@ -375,7 +429,7 @@ archive_read_format_tar_options(struct archive_read *a, tar = (struct tar *)(a->format->data); if (strcmp(key, "compat-2x") == 0) { - /* Handle UTF-8 filnames as libarchive 2.x */ + /* Handle UTF-8 filenames as libarchive 2.x */ tar->compat_2x = (val != NULL && val[0] != 0); tar->init_default_conversion = tar->compat_2x; return (ARCHIVE_OK); @@ -793,9 +847,9 @@ tar_read_header(struct archive_read *a, struct tar *tar, tar->sparse_gnu_pending = 0; /* Read initial sparse map. */ bytes_read = gnu_sparse_10_read(a, tar, unconsumed); - tar->entry_bytes_remaining -= bytes_read; if (bytes_read < 0) return ((int)bytes_read); + tar->entry_bytes_remaining -= bytes_read; } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -890,7 +944,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, { const struct archive_entry_header_ustar *header; size_t size; - int err; + int err, acl_type; int64_t type; char *acl, *p; @@ -935,11 +989,12 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, switch ((int)type & ~0777777) { case 01000000: /* POSIX.1e ACL */ + acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; break; case 03000000: - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Solaris NFSv4 ACLs not supported"); - return (ARCHIVE_WARN); + /* NFSv4 ACL */ + acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4; + break; default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed Solaris ACL attribute (unsupported type %o)", @@ -968,8 +1023,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, return (ARCHIVE_FATAL); } archive_strncpy(&(tar->localname), acl, p - acl); - err = archive_acl_parse_l(archive_entry_acl(entry), - tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, tar->sconv_acl); + err = archive_acl_from_text_l(archive_entry_acl(entry), + tar->localname.s, acl_type, tar->sconv_acl); if (err != ARCHIVE_OK) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, @@ -1128,8 +1183,15 @@ header_common(struct archive_read *a, struct tar *tar, if (tar->entry_bytes_remaining < 0) { tar->entry_bytes_remaining = 0; archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Tar entry has negative size?"); - err = ARCHIVE_WARN; + "Tar entry has negative size"); + return (ARCHIVE_FATAL); + } + if (tar->entry_bytes_remaining == INT64_MAX) { + /* Note: tar_atol returns INT64_MAX on overflow */ + tar->entry_bytes_remaining = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Tar entry size overflow"); + return (ARCHIVE_FATAL); } tar->realsize = tar->entry_bytes_remaining; archive_entry_set_size(entry, tar->entry_bytes_remaining); @@ -1264,6 +1326,14 @@ header_common(struct archive_read *a, struct tar *tar, * sparse information in the extended area. */ /* FALLTHROUGH */ + case '0': + /* + * Enable sparse file "read" support only for regular + * files and explicit GNU sparse files. However, we + * don't allow non-standard file types to be sparse. + */ + tar->sparse_allowed = 1; + /* FALLTHROUGH */ default: /* Regular file and non-standard types */ /* * Per POSIX: non-recognized types should always be @@ -1415,7 +1485,7 @@ header_pax_extensions(struct archive_read *a, struct tar *tar, * and then skip any fields in the standard header that were * defined in the pax header. */ - err2 = pax_header(a, tar, entry, tar->pax_header.s); + err2 = pax_header(a, tar, entry, &tar->pax_header); err = err_combine(err, err2); tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); return (err); @@ -1496,16 +1566,17 @@ header_ustar(struct archive_read *a, struct tar *tar, */ static int pax_header(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, char *attr) + struct archive_entry *entry, struct archive_string *in_as) { - size_t attr_length, l, line_length; + size_t attr_length, l, line_length, value_length; char *p; char *key, *value; struct archive_string *as; struct archive_string_conv *sconv; int err, err2; + char *attr = in_as->s; - attr_length = strlen(attr); + attr_length = in_as->length; tar->pax_hdrcharset_binary = 0; archive_string_empty(&(tar->entry_gname)); archive_string_empty(&(tar->entry_linkpath)); @@ -1570,11 +1641,13 @@ pax_header(struct archive_read *a, struct tar *tar, } *p = '\0'; - /* Identify null-terminated 'value' portion. */ value = p + 1; + /* Some values may be binary data */ + value_length = attr + line_length - 1 - value; + /* Identify this attribute and set it in the entry. */ - err2 = pax_attribute(a, tar, entry, key, value); + err2 = pax_attribute(a, tar, entry, key, value, value_length); if (err2 == ARCHIVE_FATAL) return (err2); err = err_combine(err, err2); @@ -1695,6 +1768,66 @@ pax_attribute_xattr(struct archive_entry *entry, return 0; } +static int +pax_attribute_schily_xattr(struct archive_entry *entry, + const char *name, const char *value, size_t value_length) +{ + if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0) + return 1; + + name += 13; + + archive_entry_xattr_add_entry(entry, name, value, value_length); + + return 0; +} + +static int +pax_attribute_acl(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const char *value, int type) +{ + int r; + const char* errstr; + + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + errstr = "SCHILY.acl.access"; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + errstr = "SCHILY.acl.default"; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + errstr = "SCHILY.acl.ace"; + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown ACL type: %d", type); + return(ARCHIVE_FATAL); + } + + if (tar->sconv_acl == NULL) { + tar->sconv_acl = + archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (tar->sconv_acl == NULL) + return (ARCHIVE_FATAL); + } + + r = archive_acl_from_text_l(archive_entry_acl(entry), value, type, + tar->sconv_acl); + if (r != ARCHIVE_OK) { + if (r == ARCHIVE_FATAL) { + archive_set_error(&a->archive, ENOMEM, + "%s %s", "Can't allocate memory for ", + errstr); + return (r); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr); + } + return (r); +} + /* * Parse a single key=value attribute. key/value pointers are * assumed to point into reasonably long-lived storage. @@ -1710,7 +1843,7 @@ pax_attribute_xattr(struct archive_entry *entry, */ static int pax_attribute(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, const char *key, const char *value) + struct archive_entry *entry, const char *key, const char *value, size_t value_length) { int64_t s; long n; @@ -1721,6 +1854,14 @@ pax_attribute(struct archive_read *a, struct tar *tar, * NULL pointer to strlen(). */ switch (key[0]) { case 'G': + /* Reject GNU.sparse.* headers on non-regular files. */ + if (strncmp(key, "GNU.sparse", 10) == 0 && + !tar->sparse_allowed) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Non-regular file cannot be sparse"); + return (ARCHIVE_FATAL); + } + /* GNU "0.0" sparse pax format. */ if (strcmp(key, "GNU.sparse.numblocks") == 0) { tar->sparse_offset = -1; @@ -1803,53 +1944,20 @@ pax_attribute(struct archive_read *a, struct tar *tar, case 'S': /* We support some keys used by the "star" archiver */ if (strcmp(key, "SCHILY.acl.access") == 0) { - if (tar->sconv_acl == NULL) { - tar->sconv_acl = - archive_string_conversion_from_charset( - &(a->archive), "UTF-8", 1); - if (tar->sconv_acl == NULL) - return (ARCHIVE_FATAL); - } - - r = archive_acl_parse_l(archive_entry_acl(entry), - value, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, - tar->sconv_acl); - if (r != ARCHIVE_OK) { - err = r; - if (err == ARCHIVE_FATAL) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "SCHILY.acl.access"); - return (err); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Parse error: SCHILY.acl.access"); - } + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + if (r == ARCHIVE_FATAL) + return (r); } else if (strcmp(key, "SCHILY.acl.default") == 0) { - if (tar->sconv_acl == NULL) { - tar->sconv_acl = - archive_string_conversion_from_charset( - &(a->archive), "UTF-8", 1); - if (tar->sconv_acl == NULL) - return (ARCHIVE_FATAL); - } - - r = archive_acl_parse_l(archive_entry_acl(entry), - value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, - tar->sconv_acl); - if (r != ARCHIVE_OK) { - err = r; - if (err == ARCHIVE_FATAL) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "SCHILY.acl.default"); - return (err); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Parse error: SCHILY.acl.default"); - } + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); + if (r == ARCHIVE_FATAL) + return (r); + } else if (strcmp(key, "SCHILY.acl.ace") == 0) { + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + if (r == ARCHIVE_FATAL) + return (r); } else if (strcmp(key, "SCHILY.devmajor") == 0) { archive_entry_set_rdevmajor(entry, (dev_t)tar_atol10(value, strlen(value))); @@ -1870,6 +1978,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, } else if (strcmp(key, "SCHILY.realsize") == 0) { tar->realsize = tar_atol10(value, strlen(value)); archive_entry_set_size(entry, tar->realsize); + } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) { + pax_attribute_schily_xattr(entry, key, value, + value_length); } else if (strcmp(key, "SUN.holesdata") == 0) { /* A Solaris extension for sparse. */ r = solaris_sparse_parse(a, tar, entry, value); @@ -2116,12 +2227,11 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar, { struct sparse_block *p; - p = (struct sparse_block *)malloc(sizeof(*p)); + p = (struct sparse_block *)calloc(1, sizeof(*p)); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - memset(p, 0, sizeof(*p)); if (tar->sparse_last != NULL) tar->sparse_last->next = p; else @@ -2377,6 +2487,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed) tar_flush_unconsumed(a, unconsumed); bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining); to_skip = 0x1ff & -bytes_read; + /* Fail if tar->entry_bytes_remaing would get negative */ + if (to_skip > remaining) + return (ARCHIVE_FATAL); if (to_skip != __archive_read_consume(a, to_skip)) return (ARCHIVE_FATAL); return ((ssize_t)(bytes_read + to_skip)); @@ -2472,7 +2585,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base) last_digit_limit = INT64_MAX % base; /* the pointer will not be dereferenced if char_cnt is zero - * due to the way the && operator is evaulated. + * due to the way the && operator is evaluated. */ while (char_cnt != 0 && (*p == ' ' || *p == '\t')) { p++; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c index 46a59ea14..b16246514 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c @@ -88,7 +88,7 @@ typedef enum { WT_RVIS, /* conversion, unsupported */ WT_CONV, - /* continutation, unsupported at the moment */ + /* continuation, unsupported at the moment */ WT_CONT, /* invalid type */ LAST_WT @@ -134,8 +134,8 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz); static time_t _warc_rdrtm(const char *buf, size_t bsz); static time_t _warc_rdmtm(const char *buf, size_t bsz); static const char *_warc_find_eoh(const char *buf, size_t bsz); +static const char *_warc_find_eol(const char *buf, size_t bsz); - int archive_read_support_format_warc(struct archive *_a) { @@ -146,12 +146,11 @@ archive_read_support_format_warc(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_warc"); - if ((w = malloc(sizeof(*w))) == NULL) { + if ((w = calloc(1, sizeof(*w))) == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate warc data"); return (ARCHIVE_FATAL); } - memset(w, 0, sizeof(*w)); r = __archive_read_register_format( a, w, "warc", @@ -199,8 +198,8 @@ _warc_bid(struct archive_read *a, int best_bid) /* otherwise snarf the record's version number */ ver = _warc_rdver(hdr, nrd); - if (ver == 0U || ver > 10000U) { - /* oh oh oh, best not to wager ... */ + if (ver < 1200U || ver > 10000U) { + /* we only support WARC 0.12 to 1.0 */ return -1; } @@ -255,23 +254,32 @@ start_over: &a->archive, ARCHIVE_ERRNO_MISC, "Bad record header"); return (ARCHIVE_FATAL); - } else if ((ver = _warc_rdver(buf, eoh - buf)) > 10000U) { - /* nawww, I wish they promised backward compatibility - * anyhoo, in their infinite wisdom the 28500 guys might - * come up with something we can't possibly handle so - * best end things here */ + } + ver = _warc_rdver(buf, eoh - buf); + /* we currently support WARC 0.12 to 1.0 */ + if (ver == 0U) { archive_set_error( &a->archive, ARCHIVE_ERRNO_MISC, - "Unsupported record version"); + "Invalid record version"); return (ARCHIVE_FATAL); - } else if ((cntlen = _warc_rdlen(buf, eoh - buf)) < 0) { + } else if (ver < 1200U || ver > 10000U) { + archive_set_error( + &a->archive, ARCHIVE_ERRNO_MISC, + "Unsupported record version: %u.%u", + ver / 10000, (ver % 10000) / 100); + return (ARCHIVE_FATAL); + } + cntlen = _warc_rdlen(buf, eoh - buf); + if (cntlen < 0) { /* nightmare! the specs say content-length is mandatory * so I don't feel overly bad stopping the reader here */ archive_set_error( &a->archive, EINVAL, "Bad content length"); return (ARCHIVE_FATAL); - } else if ((rtime = _warc_rdrtm(buf, eoh - buf)) == (time_t)-1) { + } + rtime = _warc_rdrtm(buf, eoh - buf); + if (rtime == (time_t)-1) { /* record time is mandatory as per WARC/1.0, * so just barf here, fast and loud */ archive_set_error( @@ -285,7 +293,7 @@ start_over: if (ver != w->pver) { /* stringify this entry's version */ archive_string_sprintf(&w->sver, - "WARC/%u.%u", ver / 10000, ver % 10000); + "WARC/%u.%u", ver / 10000, (ver % 10000) / 100); /* remember the version */ w->pver = ver; } @@ -318,7 +326,7 @@ start_over: } memcpy(w->pool.str, fnam.str, fnam.len); w->pool.str[fnam.len] = '\0'; - /* let noone else know about the pool, it's a secret, shhh */ + /* let no one else know about the pool, it's a secret, shhh */ fnam.str = w->pool.str; /* snarf mtime or deduce from rtime @@ -535,7 +543,8 @@ xstrpisotime(const char *s, char **endptr) /* as a courtesy to our callers, and since this is a non-standard * routine, we skip leading whitespace */ - for (; isspace(*s); s++); + while (*s == ' ' || *s == '\t') + ++s; /* read year */ if ((tm.tm_year = strtoi_lim(s, &s, 1583, 4095)) < 0 || *s++ != '-') { @@ -562,7 +571,7 @@ xstrpisotime(const char *s, char **endptr) goto out; } - /* massage TM to fulfill some of POSIX' contraints */ + /* massage TM to fulfill some of POSIX' constraints */ tm.tm_year -= 1900; tm.tm_mon--; @@ -577,51 +586,43 @@ out: } static unsigned int -_warc_rdver(const char buf[10], size_t bsz) +_warc_rdver(const char *buf, size_t bsz) { static const char magic[] = "WARC/"; - unsigned int ver; - - (void)bsz; /* UNUSED */ + const char *c; + unsigned int ver = 0U; + unsigned int end = 0U; - if (memcmp(buf, magic, sizeof(magic) - 1U) != 0) { - /* nope */ - return 99999U; + if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) { + /* buffer too small or invalid magic */ + return ver; } /* looks good so far, read the version number for a laugh */ buf += sizeof(magic) - 1U; - /* most common case gets a quick-check here */ - if (memcmp(buf, "1.0\r\n", 5U) == 0) { - ver = 10000U; - } else { - switch (*buf) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - if (buf[1U] == '.') { - char *on; - - /* set up major version */ - ver = (buf[0U] - '0') * 10000U; - /* minor version, anyone? */ - ver += (strtol(buf + 2U, &on, 10)) * 100U; - /* don't parse anything else */ - if (on > buf + 2U) { - break; - } - } - /* FALLTHROUGH */ - case '9': - default: - /* just make the version ridiculously high */ - ver = 999999U; - break; + + if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) { + /* we support a maximum of 2 digits in the minor version */ + if (isdigit(buf[3U])) + end = 1U; + /* set up major version */ + ver = (buf[0U] - '0') * 10000U; + /* set up minor version */ + if (end == 1U) { + ver += (buf[2U] - '0') * 1000U; + ver += (buf[3U] - '0') * 100U; + } else + ver += (buf[2U] - '0') * 100U; + /* + * WARC below version 0.12 has a space-separated header + * WARC 0.12 and above terminates the version with a CRLF + */ + c = buf + 3U + end; + if (ver >= 1200U) { + if (memcmp(c, "\r\n", 2U) != 0) + ver = 0U; + } else if (ver < 1200U) { + if (*c != ' ' && *c != '\t') + ver = 0U; } } return ver; @@ -631,32 +632,27 @@ static unsigned int _warc_rdtyp(const char *buf, size_t bsz) { static const char _key[] = "\r\nWARC-Type:"; - const char *const eob = buf + bsz; - const char *val; + const char *val, *eol; if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { /* no bother */ return WT_NONE; } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return WT_NONE; + } + /* overread whitespace */ - for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++); - - if (val + 8U > eob) { - ; - } else if (memcmp(val, "resource", 8U) == 0) { - return WT_RSRC; - } else if (memcmp(val, "warcinfo", 8U) == 0) { - return WT_INFO; - } else if (memcmp(val, "metadata", 8U) == 0) { - return WT_META; - } else if (memcmp(val, "request", 7U) == 0) { - return WT_REQ; - } else if (memcmp(val, "response", 8U) == 0) { - return WT_RSP; - } else if (memcmp(val, "conversi", 8U) == 0) { - return WT_CONV; - } else if (memcmp(val, "continua", 8U) == 0) { - return WT_CONT; + while (val < eol && (*val == ' ' || *val == '\t')) + ++val; + + if (val + 8U == eol) { + if (memcmp(val, "resource", 8U) == 0) + return WT_RSRC; + else if (memcmp(val, "response", 8U) == 0) + return WT_RSP; } return WT_NONE; } @@ -665,10 +661,7 @@ static warc_string_t _warc_rduri(const char *buf, size_t bsz) { static const char _key[] = "\r\nWARC-Target-URI:"; - const char *const eob = buf + bsz; - const char *val; - const char *uri; - const char *eol; + const char *val, *uri, *eol, *p; warc_string_t res = {0U, NULL}; if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { @@ -676,23 +669,33 @@ _warc_rduri(const char *buf, size_t bsz) return res; } /* overread whitespace */ - for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++); + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return res; + } + + while (val < eol && (*val == ' ' || *val == '\t')) + ++val; /* overread URL designators */ - if ((uri = xmemmem(val, eob - val, "://", 3U)) == NULL) { + if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) { /* not touching that! */ return res; - } else if ((eol = memchr(uri, '\n', eob - uri)) == NULL) { - /* no end of line? :O */ - return res; } - /* massage uri to point to after :// */ + /* spaces inside uri are not allowed, CRLF should follow */ + for (p = val; p < eol; p++) { + if (isspace(*p)) + return res; + } + + /* there must be at least space for ftp */ + if (uri < (val + 3U)) + return res; + + /* move uri to point to after :// */ uri += 3U; - /* also massage eol to point to the first whitespace - * after the last non-whitespace character before - * the end of the line */ - for (; eol > uri && isspace(eol[-1]); eol--); /* now then, inspect the URI */ if (memcmp(val, "file", 4U) == 0) { @@ -715,7 +718,7 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz) { static const char _key[] = "\r\nContent-Length:"; - const char *val; + const char *val, *eol; char *on = NULL; long int len; @@ -723,14 +726,24 @@ _warc_rdlen(const char *buf, size_t bsz) /* no bother */ return -1; } - - /* strtol kindly overreads whitespace for us, so use that */ val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return -1; + } + + /* skip leading whitespace */ + while (val < eol && (*val == ' ' || *val == '\t')) + val++; + /* there must be at least one digit */ + if (!isdigit(*val)) + return -1; len = strtol(val, &on, 10); - if (on == NULL || !isspace(*on)) { - /* hm, can we trust that number? Best not. */ + if (on != eol) { + /* line must end here */ return -1; } + return (size_t)len; } @@ -738,7 +751,7 @@ static time_t _warc_rdrtm(const char *buf, size_t bsz) { static const char _key[] = "\r\nWARC-Date:"; - const char *val; + const char *val, *eol; char *on = NULL; time_t res; @@ -746,13 +759,17 @@ _warc_rdrtm(const char *buf, size_t bsz) /* no bother */ return (time_t)-1; } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) { + /* no end of line */ + return -1; + } /* xstrpisotime() kindly overreads whitespace for us, so use that */ - val += sizeof(_key) - 1U; res = xstrpisotime(val, &on); - if (on == NULL || !isspace(*on)) { - /* hm, can we trust that number? Best not. */ - return (time_t)-1; + if (on != eol) { + /* line must end here */ + return -1; } return res; } @@ -761,7 +778,7 @@ static time_t _warc_rdmtm(const char *buf, size_t bsz) { static const char _key[] = "\r\nLast-Modified:"; - const char *val; + const char *val, *eol; char *on = NULL; time_t res; @@ -769,13 +786,17 @@ _warc_rdmtm(const char *buf, size_t bsz) /* no bother */ return (time_t)-1; } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) { + /* no end of line */ + return -1; + } /* xstrpisotime() kindly overreads whitespace for us, so use that */ - val += sizeof(_key) - 1U; res = xstrpisotime(val, &on); - if (on == NULL || !isspace(*on)) { - /* hm, can we trust that number? Best not. */ - return (time_t)-1; + if (on != eol) { + /* line must end here */ + return -1; } return res; } @@ -792,4 +813,12 @@ _warc_find_eoh(const char *buf, size_t bsz) return hit; } +static const char* +_warc_find_eol(const char *buf, size_t bsz) +{ + static const char _marker[] = "\r\n"; + const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U); + + return hit; +} /* archive_read_support_format_warc.c ends here */ diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c index ec623c626..eeac1c888 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c @@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$"); #endif #if HAVE_LZMA_H #include -#elif HAVE_LZMADEC_H -#include #endif #ifdef HAVE_ZLIB_H #include @@ -334,9 +332,6 @@ struct xar { #if HAVE_LZMA_H && HAVE_LIBLZMA lzma_stream lzstream; int lzstream_valid; -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - lzmadec_stream lzstream; - int lzstream_valid; #endif /* * For Checksum data. @@ -399,6 +394,7 @@ static void checksum_update(struct archive_read *, const void *, size_t, const void *, size_t); static int checksum_final(struct archive_read *, const void *, size_t, const void *, size_t); +static void checksum_cleanup(struct archive_read *); static int decompression_init(struct archive_read *, enum enctype); static int decompress(struct archive_read *, const void **, size_t *, const void *, size_t *); @@ -928,6 +924,7 @@ xar_cleanup(struct archive_read *a) int r; xar = (struct xar *)(a->format->data); + checksum_cleanup(a); r = decompression_cleanup(a); hdlink = xar->hdlink_list; while (hdlink != NULL) { @@ -938,6 +935,7 @@ xar_cleanup(struct archive_read *a) } for (i = 0; i < xar->file_queue.used; i++) file_free(xar->file_queue.files[i]); + free(xar->file_queue.files); while (xar->unknowntags != NULL) { struct unknown_tag *tag; @@ -1526,34 +1524,6 @@ decompression_init(struct archive_read *a, enum enctype encoding) xar->lzstream.total_in = 0; xar->lzstream.total_out = 0; break; -#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - if (xar->lzstream_valid) - lzmadec_end(&(xar->lzstream)); - r = lzmadec_init(&(xar->lzstream)); - if (r != LZMADEC_OK) { - switch (r) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing " - "compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&a->archive, - ENOMEM, - "Internal error initializing " - "compression library: " - "out of memory"); - break; - } - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 1; - xar->lzstream.total_in = 0; - xar->lzstream.total_out = 0; - break; #endif /* * Unsupported compression. @@ -1563,9 +1533,7 @@ decompression_init(struct archive_read *a, enum enctype encoding) case BZIP2: #endif #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) -#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) case LZMA: -#endif case XZ: #endif switch (xar->entry_encoding) { @@ -1685,46 +1653,12 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes, *used = avail_in - xar->lzstream.avail_in; *outbytes = avail_out - xar->lzstream.avail_out; break; -#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - xar->lzstream.next_in = (unsigned char *)(uintptr_t)b; - xar->lzstream.avail_in = avail_in; - xar->lzstream.next_out = (unsigned char *)outbuff; - xar->lzstream.avail_out = avail_out; - r = lzmadec_decode(&(xar->lzstream), 0); - switch (r) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - switch (lzmadec_end(&(xar->lzstream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up lzmadec decompressor"); - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 0; - /* FALLTHROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "lzmadec decompression failed(%d)", - r); - return (ARCHIVE_FATAL); - } - *used = avail_in - xar->lzstream.avail_in; - *outbytes = avail_out - xar->lzstream.avail_out; - break; #endif #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) case BZIP2: #endif #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) -#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) case LZMA: -#endif case XZ: #endif case NONE: @@ -1787,6 +1721,16 @@ decompression_cleanup(struct archive_read *a) return (r); } +static void +checksum_cleanup(struct archive_read *a) { + struct xar *xar; + + xar = (struct xar *)(a->format->data); + + _checksum_final(&(xar->a_sumwrk), NULL, 0); + _checksum_final(&(xar->e_sumwrk), NULL, 0); +} + static void xmlattr_cleanup(struct xmlattr_list *list) { @@ -3116,7 +3060,7 @@ xml2_read_cb(void *context, char *buffer, int len) struct xar *xar; const void *d; size_t outbytes; - size_t used; + size_t used = 0; int r; a = (struct archive_read *)context; @@ -3240,6 +3184,9 @@ expat_xmlattr_setup(struct archive_read *a, value = strdup(atts[1]); if (attr == NULL || name == NULL || value == NULL) { archive_set_error(&a->archive, ENOMEM, "Out of memory"); + free(attr); + free(name); + free(value); return (ARCHIVE_FATAL); } attr->name = name; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c index 8df52c3cb..e56bd63ac 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c @@ -199,7 +199,7 @@ struct zip { struct trad_enc_ctx tctx; char tctx_valid; - /* WinZip AES decyption. */ + /* WinZip AES decryption. */ /* Contexts used for AES decryption. */ archive_crypto_ctx cctx; char cctx_valid; @@ -242,7 +242,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) } static uint8_t -trad_enc_decypt_byte(struct trad_enc_ctx *ctx) +trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) { unsigned temp = ctx->keys[2] | 2; return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; @@ -257,7 +257,7 @@ trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, max = (unsigned)((in_len < out_len)? in_len: out_len); for (i = 0; i < max; i++) { - uint8_t t = in[i] ^ trad_enc_decypt_byte(ctx); + uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx); out[i] = t; trad_enc_update_keys(ctx, t); } @@ -418,18 +418,30 @@ zip_time(const char *p) * id1+size1+data1 + id2+size2+data2 ... * triplets. id and size are 2 bytes each. */ -static void -process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) +static int +process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry) { unsigned offset = 0; - while (offset < extra_length - 4) { + if (extra_length == 0) { + return ARCHIVE_OK; + } + + if (extra_length < 4) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length); + return ARCHIVE_FAILED; + } + while (offset <= extra_length - 4) { unsigned short headerid = archive_le16dec(p + offset); unsigned short datasize = archive_le16dec(p + offset + 2); offset += 4; if (offset + datasize > extra_length) { - break; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Extra data overflow: Need %d bytes but only found %d bytes", + (int)datasize, (int)(extra_length - offset)); + return ARCHIVE_FAILED; } #ifdef DEBUG fprintf(stderr, "Header id 0x%04x, length %d\n", @@ -440,26 +452,38 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) /* Zip64 extended information extra field. */ zip_entry->flags |= LA_USED_ZIP64; if (zip_entry->uncompressed_size == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->uncompressed_size = - archive_le64dec(p + offset); + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > INT64_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit uncompressed size"); + return ARCHIVE_FAILED; + } + zip_entry->uncompressed_size = t; offset += 8; datasize -= 8; } if (zip_entry->compressed_size == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->compressed_size = - archive_le64dec(p + offset); + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > INT64_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit compressed size"); + return ARCHIVE_FAILED; + } + zip_entry->compressed_size = t; offset += 8; datasize -= 8; } if (zip_entry->local_header_offset == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->local_header_offset = - archive_le64dec(p + offset); + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > INT64_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit local header offset"); + return ARCHIVE_FAILED; + } + zip_entry->local_header_offset = t; offset += 8; datasize -= 8; } @@ -698,7 +722,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) break; } case 0x9901: - /* WinZIp AES extra data field. */ + /* WinZip AES extra data field. */ if (p[offset + 2] == 'A' && p[offset + 3] == 'E') { /* Vendor version. */ zip_entry->aes_extra.vendor = @@ -715,13 +739,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) } offset += datasize; } -#ifdef DEBUG - if (offset != extra_length) - { - fprintf(stderr, - "Extra data field contents do not match reported size!\n"); + if (offset != extra_length) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed extra data: Consumed %d bytes of %d bytes", + (int)offset, (int)extra_length); + return ARCHIVE_FAILED; } -#endif + return ARCHIVE_OK; } /* @@ -840,7 +864,9 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } - process_extra(h, extra_length, zip_entry); + if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) { + return ARCHIVE_FATAL; + } __archive_read_consume(a, extra_length); /* Work around a bug in Info-Zip: When reading from a pipe, it @@ -891,6 +917,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, archive_wstrcat(&s, wp); archive_wstrappend_wchar(&s, L'/'); archive_entry_copy_pathname_w(entry, s.s); + archive_wstring_free(&s); } } else { cp = archive_entry_pathname(entry); @@ -901,6 +928,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, archive_strcat(&s, cp); archive_strappend_char(&s, '/'); archive_entry_set_pathname(entry, s.s); + archive_string_free(&s); } } } @@ -1140,11 +1168,18 @@ zip_read_data_none(struct archive_read *a, const void **_buff, || (zip->hctx_valid && zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) { if (zip->entry->flags & LA_USED_ZIP64) { + uint64_t compressed, uncompressed; zip->entry->crc32 = archive_le32dec(p + 4); - zip->entry->compressed_size = - archive_le64dec(p + 8); - zip->entry->uncompressed_size = - archive_le64dec(p + 16); + compressed = archive_le64dec(p + 8); + uncompressed = archive_le64dec(p + 16); + if (compressed > INT64_MAX || uncompressed > INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Overflow of 64-bit file sizes"); + return ARCHIVE_FAILED; + } + zip->entry->compressed_size = compressed; + zip->entry->uncompressed_size = uncompressed; zip->unconsumed = 24; } else { zip->entry->crc32 = archive_le32dec(p + 4); @@ -1297,7 +1332,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, && bytes_avail > zip->entry_bytes_remaining) { bytes_avail = (ssize_t)zip->entry_bytes_remaining; } - if (bytes_avail <= 0) { + if (bytes_avail < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file body"); return (ARCHIVE_FATAL); @@ -1421,9 +1456,18 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, zip->unconsumed = 4; } if (zip->entry->flags & LA_USED_ZIP64) { + uint64_t compressed, uncompressed; zip->entry->crc32 = archive_le32dec(p); - zip->entry->compressed_size = archive_le64dec(p + 4); - zip->entry->uncompressed_size = archive_le64dec(p + 12); + compressed = archive_le64dec(p + 4); + uncompressed = archive_le64dec(p + 12); + if (compressed > INT64_MAX || uncompressed > INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Overflow of 64-bit file sizes"); + return ARCHIVE_FAILED; + } + zip->entry->compressed_size = compressed; + zip->entry->uncompressed_size = uncompressed; zip->unconsumed += 20; } else { zip->entry->crc32 = archive_le32dec(p); @@ -1504,7 +1548,7 @@ read_decryption_header(struct archive_read *a) case 0x6720:/* Blowfish */ case 0x6721:/* Twofish */ case 0x6801:/* RC4 */ - /* Suuported encryption algorithm. */ + /* Supported encryption algorithm. */ break; default: archive_set_error(&a->archive, @@ -1613,7 +1657,7 @@ read_decryption_header(struct archive_read *a) __archive_read_consume(a, 4); /*return (ARCHIVE_OK); - * This is not fully implemnted yet.*/ + * This is not fully implemented yet.*/ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Encrypted file is unsupported"); return (ARCHIVE_FAILED); @@ -1695,7 +1739,7 @@ init_traditional_PKWARE_decryption(struct archive_read *a) } /* - * Initialize ctx for Traditional PKWARE Decyption. + * Initialize ctx for Traditional PKWARE Decryption. */ r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase), p, ENC_HEADER_SIZE, &crcchk); @@ -2695,7 +2739,9 @@ slurp_central_directory(struct archive_read *a, struct zip *zip) "Truncated ZIP file header"); return ARCHIVE_FATAL; } - process_extra(p + filename_length, extra_length, zip_entry); + if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) { + return ARCHIVE_FATAL; + } /* * Mac resource fork files are stored under the diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c index 282c58e1e..592ead2bd 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string.c +++ b/Utilities/cmlibarchive/libarchive/archive_string.c @@ -219,6 +219,12 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s) return (as); } +struct archive_string * +archive_array_append(struct archive_string *as, const char *p, size_t s) +{ + return archive_string_append(as, p, s); +} + void archive_string_concat(struct archive_string *dest, struct archive_string *src) { @@ -559,7 +565,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest, } if (count == 0 && length != 0) ret = -1; - } while (0); + break; + } while (1); } dest->length += count; dest->s[dest->length] = L'\0'; @@ -596,7 +603,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest, wcs = dest->s + dest->length; /* * We cannot use mbsrtowcs/mbstowcs here because those may convert - * extra MBS when strlen(p) > len and one wide character consis of + * extra MBS when strlen(p) > len and one wide character consists of * multi bytes. */ while (*mbs && mbs_length > 0) { @@ -1247,7 +1254,7 @@ create_sconv_object(const char *fc, const char *tc, sc->cd = iconv_open(tc, fc); if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) { /* - * Unfortunaly, all of iconv implements do support + * Unfortunately, all of iconv implements do support * "CP932" character-set, so we should use "SJIS" * instead if iconv_open failed. */ @@ -1260,7 +1267,7 @@ create_sconv_object(const char *fc, const char *tc, /* * archive_mstring on Windows directly convert multi-bytes * into archive_wstring in order not to depend on locale - * so that you can do a I18N programing. This will be + * so that you can do a I18N programming. This will be * used only in archive_mstring_copy_mbs_len_l so far. */ if (flag & SCONV_FROM_CHARSET) { @@ -1725,7 +1732,7 @@ archive_string_conversion_from_charset(struct archive *a, const char *charset, * in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP * unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP). * So we should make a string conversion between CP_ACP and CP_OEMCP - * for compatibillty. + * for compatibility. */ #if defined(_WIN32) && !defined(__CYGWIN__) struct archive_string_conv * @@ -1826,7 +1833,7 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt) * A filename in UTF-8 was made with libarchive 2.x in a wrong * assumption that wchar_t was Unicode. * This option enables simulating the assumption in order to read - * that filname correctly. + * that filename correctly. */ case SCONV_SET_OPT_UTF8_LIBARCHIVE2X: #if (defined(_WIN32) && !defined(__CYGWIN__)) \ @@ -1938,12 +1945,19 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, struct archive_string_conv *sc) { const void *s; - size_t length; + size_t length = 0; int i, r = 0, r2; + if (_p != NULL && n > 0) { + if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) + length = utf16nbytes(_p, n); + else + length = mbsnbytes(_p, n); + } + /* We must allocate memory even if there is no data for conversion * or copy. This simulates archive_string_append behavior. */ - if (_p == NULL || n == 0) { + if (length == 0) { int tn = 1; if (sc != NULL && (sc->flag & SCONV_TO_UTF16)) tn = 2; @@ -1959,16 +1973,11 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, * If sc is NULL, we just make a copy. */ if (sc == NULL) { - length = mbsnbytes(_p, n); if (archive_string_append(as, _p, length) == NULL) return (-1);/* No memory */ return (0); } - if (sc->flag & SCONV_FROM_UTF16) - length = utf16nbytes(_p, n); - else - length = mbsnbytes(_p, n); s = _p; i = 0; if (sc->nconverter > 1) { @@ -1991,7 +2000,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, #if HAVE_ICONV /* - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int iconv_strncat_in_locale(struct archive_string *as, const void *_p, @@ -2093,7 +2102,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p, /* * Translate a string from a some CodePage to an another CodePage by - * Windows APIs, and copy the result. Return -1 if conversion failes. + * Windows APIs, and copy the result. Return -1 if conversion fails. */ static int strncat_in_codepage(struct archive_string *as, @@ -2217,7 +2226,7 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, /* * If a character is ASCII, this just copies it. If not, this - * assigns '?' charater instead but in UTF-8 locale this assigns + * assigns '?' character instead but in UTF-8 locale this assigns * byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD, * a Replacement Character in Unicode. */ @@ -2297,7 +2306,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) return (0); /* Standard: return 0 for end-of-string. */ cnt = utf8_count[ch]; - /* Invalide sequence or there are not plenty bytes. */ + /* Invalid sequence or there are not plenty bytes. */ if ((int)n < cnt) { cnt = (int)n; for (i = 1; i < cnt; i++) { @@ -2378,7 +2387,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) goto invalid_sequence; } - /* The code point larger than 0x10FFFF is not leagal + /* The code point larger than 0x10FFFF is not legal * Unicode values. */ if (wc > UNICODE_MAX) goto invalid_sequence; @@ -2396,7 +2405,7 @@ utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) int cnt; cnt = _utf8_to_unicode(pwc, s, n); - /* Any of Surrogate pair is not leagal Unicode values. */ + /* Any of Surrogate pair is not legal Unicode values. */ if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc)) return (-3); return (cnt); @@ -2457,7 +2466,7 @@ invalid_sequence: /* * Convert a Unicode code point to a single UTF-8 sequence. * - * NOTE:This function does not check if the Unicode is leagal or not. + * NOTE:This function does not check if the Unicode is legal or not. * Please you definitely check it before calling this. */ static size_t @@ -2551,9 +2560,9 @@ utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be) /* * Surrogate pair values(0xd800 through 0xdfff) are only - * used by UTF-16, so, after above culculation, the code + * used by UTF-16, so, after above calculation, the code * must not be surrogate values, and Unicode has no codes - * larger than 0x10ffff. Thus, those are not leagal Unicode + * larger than 0x10ffff. Thus, those are not legal Unicode * values. */ if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) { @@ -2900,7 +2909,7 @@ get_nfc(uint32_t uc, uint32_t uc2) /* * Normalize UTF-8/UTF-16BE characters to Form C and copy the result. * - * TODO: Convert composition exclusions,which are never converted + * TODO: Convert composition exclusions, which are never converted * from NFC,NFD,NFKC and NFKD, to Form C. */ static int @@ -3434,7 +3443,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as, } /* - * As libarchie 2.x, translates the UTF-8 characters into + * As libarchive 2.x, translates the UTF-8 characters into * wide-characters in the assumption that WCS is Unicode. */ if (n < 0) { @@ -3473,7 +3482,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as, /* * Convert a UTF-16BE/LE string to current locale and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, @@ -3552,18 +3561,19 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, ll = WideCharToMultiByte(sc->to_cp, 0, (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size, NULL, &defchar); - if (ll == 0 && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - /* Need more buffer for MBS. */ - ll = WideCharToMultiByte(sc->to_cp, 0, - (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL); - if (archive_string_ensure(as, ll +1) == NULL) - return (-1); - mbs = as->s + as->length; - mbs_size = as->buffer_length - as->length -1; - continue; + /* Exit loop if we succeeded */ + if (ll != 0 || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; } - } while (0); + /* Else expand buffer and loop to try again. */ + ll = WideCharToMultiByte(sc->to_cp, 0, + (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL); + if (archive_string_ensure(as, ll +1) == NULL) + return (-1); + mbs = as->s + as->length; + mbs_size = as->buffer_length - as->length -1; + } while (1); archive_string_free(&tmp); as->length += ll; as->s[as->length] = '\0'; @@ -3596,7 +3606,7 @@ is_big_endian(void) /* * Convert a current locale string to UTF-16BE/LE and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int win_strncat_to_utf16(struct archive_string *as16, const void *_p, @@ -3634,19 +3644,20 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, do { count = MultiByteToWideChar(sc->from_cp, MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1); - if (count == 0 && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - /* Need more buffer for UTF-16 string */ - count = MultiByteToWideChar(sc->from_cp, - MB_PRECOMPOSED, s, (int)length, NULL, 0); - if (archive_string_ensure(as16, (count +1) * 2) - == NULL) - return (-1); - u16 = as16->s + as16->length; - avail = as16->buffer_length - 2; - continue; + /* Exit loop if we succeeded */ + if (count != 0 || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; } - } while (0); + /* Expand buffer and try again */ + count = MultiByteToWideChar(sc->from_cp, + MB_PRECOMPOSED, s, (int)length, NULL, 0); + if (archive_string_ensure(as16, (count +1) * 2) + == NULL) + return (-1); + u16 = as16->s + as16->length; + avail = as16->buffer_length - 2; + } while (1); as16->length += count * 2; as16->s[as16->length] = 0; as16->s[as16->length+1] = 0; @@ -3700,7 +3711,7 @@ win_strncat_to_utf16le(struct archive_string *as16, const void *_p, /* * Convert a UTF-16BE string to current locale and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int best_effort_strncat_from_utf16(struct archive_string *as, const void *_p, @@ -3758,7 +3769,7 @@ best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p, /* * Convert a current locale string to UTF-16BE/LE and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p, @@ -3942,7 +3953,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes, #if defined(_WIN32) && !defined(__CYGWIN__) /* - * Internationalization programing on Windows must use Wide + * Internationalization programming on Windows must use Wide * characters because Windows platform cannot make locale UTF-8. */ if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) { @@ -4074,7 +4085,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes, archive_string_empty(&(aes->aes_utf8)); #if defined(_WIN32) && !defined(__CYGWIN__) /* - * Internationalization programing on Windows must use Wide + * Internationalization programming on Windows must use Wide * characters because Windows platform cannot make locale UTF-8. */ if (sc == NULL) { diff --git a/Utilities/cmlibarchive/libarchive/archive_string.h b/Utilities/cmlibarchive/libarchive/archive_string.h index 23f491657..56dfbb28f 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string.h +++ b/Utilities/cmlibarchive/libarchive/archive_string.h @@ -81,6 +81,10 @@ archive_strappend_char(struct archive_string *, char); struct archive_wstring * archive_wstrappend_wchar(struct archive_wstring *, wchar_t); +/* Append a raw array to an archive_string, resizing as necessary */ +struct archive_string * +archive_array_append(struct archive_string *, const char *, size_t); + /* Convert a Unicode string to current locale and append the result. */ /* Returns -1 if conversion fails. */ int @@ -115,13 +119,13 @@ archive_string_conversion_set_opt(struct archive_string_conv *, int); /* Copy one archive_string to another in locale conversion. - * Return -1 if conversion failes. */ + * Return -1 if conversion fails. */ int archive_strncpy_l(struct archive_string *, const void *, size_t, struct archive_string_conv *); /* Copy one archive_string to another in locale conversion. - * Return -1 if conversion failes. */ + * Return -1 if conversion fails. */ int archive_strncat_l(struct archive_string *, const void *, size_t, struct archive_string_conv *); diff --git a/Utilities/cmlibarchive/libarchive/archive_string_composition.h b/Utilities/cmlibarchive/libarchive/archive_string_composition.h index be41e3365..8902ac1f7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string_composition.h +++ b/Utilities/cmlibarchive/libarchive/archive_string_composition.h @@ -1009,7 +1009,7 @@ static const char u_decomposable_blocks[0x1D2+1] = { (((uc) > 0x1D244)?0:\ ccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F]) -/* The table of the value of Canonical Cimbining Class */ +/* The table of the value of Canonical Combining Class */ static const unsigned char ccc_val[][16] = { /* idx=0: XXXX0 - XXXXF */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c index f89df1d69..f56ca332d 100644 --- a/Utilities/cmlibarchive/libarchive/archive_util.c +++ b/Utilities/cmlibarchive/libarchive/archive_util.c @@ -580,7 +580,7 @@ void __archive_ensure_cloexec_flag(int fd) { #if defined(_WIN32) && !defined(__CYGWIN__) - (void)fd; /* UNSED */ + (void)fd; /* UNUSED */ #else int flags; diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.c b/Utilities/cmlibarchive/libarchive/archive_windows.c index d4e93fe78..6ff8749ae 100644 --- a/Utilities/cmlibarchive/libarchive/archive_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_windows.c @@ -766,7 +766,7 @@ __la_win_entry_in_posix_pathseparator(struct archive_entry *entry) has_backslash = 1; } /* - * If there is no backslach chars, return the original. + * If there is no backslash chars, return the original. */ if (!has_backslash) return (entry); @@ -891,7 +891,7 @@ __la_dosmaperr(unsigned long e) return; } - for (i = 0; i < (int)sizeof(doserrors); i++) + for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++) { if (doserrors[i].winerr == e) { diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.h b/Utilities/cmlibarchive/libarchive/archive_windows.h index 7c31a1691..c3aed0c90 100644 --- a/Utilities/cmlibarchive/libarchive/archive_windows.h +++ b/Utilities/cmlibarchive/libarchive/archive_windows.h @@ -224,16 +224,20 @@ #define S_IWUSR _S_IWUSR #define S_IRUSR _S_IRUSR #endif +#ifndef S_IRWXG #define S_IRWXG _S_IRWXG #define S_IXGRP _S_IXGRP #define S_IWGRP _S_IWGRP +#endif #ifndef S_IRGRP #define S_IRGRP _S_IRGRP #endif +#ifndef S_IRWXO #define S_IRWXO _S_IRWXO #define S_IXOTH _S_IXOTH #define S_IWOTH _S_IWOTH #define S_IROTH _S_IROTH +#endif #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c index e3fa3357b..0634a2296 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write.c +++ b/Utilities/cmlibarchive/libarchive/archive_write.c @@ -109,10 +109,9 @@ archive_write_new(void) struct archive_write *a; unsigned char *nulls; - a = (struct archive_write *)malloc(sizeof(*a)); + a = (struct archive_write *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_WRITE_MAGIC; a->archive.state = ARCHIVE_STATE_NEW; a->archive.vtable = archive_write_vtable(); @@ -126,12 +125,11 @@ archive_write_new(void) /* Initialize a block of nulls for padding purposes. */ a->null_length = 1024; - nulls = (unsigned char *)malloc(a->null_length); + nulls = (unsigned char *)calloc(1, a->null_length); if (nulls == NULL) { free(a); return (NULL); } - memset(nulls, 0, a->null_length); a->nulls = nulls; return (&a->archive); } @@ -233,7 +231,7 @@ __archive_write_filter(struct archive_write_filter *f, if (length == 0) return(ARCHIVE_OK); if (f->write == NULL) - /* If unset, a fatal error has already ocuured, so this filter + /* If unset, a fatal error has already occurred, so this filter * didn't open. We cannot write anything. */ return(ARCHIVE_FATAL); r = (f->write)(f, buff, length); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c index 1d0ab8c56..e6551859c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c @@ -523,7 +523,7 @@ drive_compressor_independence(struct archive_write_filter *f, const char *p, archive_le32enc(data->out, outsize); data->out += 4; } else { - /* The buffer is not compressed. The commpressed size was + /* The buffer is not compressed. The compressed size was * bigger than its uncompressed size. */ archive_le32enc(data->out, length | 0x80000000); data->out += 4; @@ -608,7 +608,7 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p, archive_le32enc(data->out, outsize); data->out += 4; } else { - /* The buffer is not compressed. The commpressed size was + /* The buffer is not compressed. The compressed size was * bigger than its uncompressed size. */ archive_le32enc(data->out, length | 0x80000000); data->out += 4; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c index 31a1b6f96..55b5e8ecd 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c @@ -200,6 +200,7 @@ __archive_write_program_free(struct archive_write_program_data *data) if (data->child) CloseHandle(data->child); #endif + free(data->program_name); free(data->child_buf); free(data); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c index 4f849ce92..e4a353591 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c @@ -233,7 +233,7 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f, if (f->code == ARCHIVE_FILTER_XZ) { #ifdef HAVE_LZMA_STREAM_ENCODER_MT if (data->threads != 1) { - bzero(&mt_options, sizeof(mt_options)); + memset(&mt_options, 0, sizeof(mt_options)); mt_options.threads = data->threads; mt_options.timeout = 300; mt_options.filters = data->lzmafilters; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c index 5cbba54f0..144ab7e72 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c @@ -34,6 +34,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0 #define _ACL_PRIVATE /* For debugging */ #include #endif +#if HAVE_DARWIN_ACL +#include +#endif #ifdef HAVE_ERRNO_H #include #endif @@ -43,7 +46,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0 #include "archive_acl_private.h" #include "archive_write_disk_private.h" -#ifndef HAVE_POSIX_ACL +#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL /* Default empty function body to satisfy mainline code. */ int archive_write_disk_set_acls(struct archive *a, int fd, const char *name, @@ -56,47 +59,111 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name, return (ARCHIVE_OK); } -#else +#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ + +#if HAVE_SUN_ACL +#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T +#elif HAVE_DARWIN_ACL +#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED +#elif HAVE_ACL_TYPE_NFS4 +#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4 +#endif static int set_acl(struct archive *, int fd, const char *, struct archive_acl *, acl_type_t, int archive_entry_acl_type, const char *tn); -/* - * XXX TODO: What about ACL types other than ACCESS and DEFAULT? - */ int archive_write_disk_set_acls(struct archive *a, int fd, const char *name, struct archive_acl *abstract_acl) { - int ret; + int ret = ARCHIVE_OK; - if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) { - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); - if (ret != ARCHIVE_OK) - return (ret); - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); +#if !HAVE_DARWIN_ACL + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { +#if HAVE_SUN_ACL + /* Solaris writes POSIX.1e access and default ACLs together */ + ret = set_acl(a, fd, name, abstract_acl, ACLENT_T, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e"); +#else /* HAVE_POSIX_ACL */ + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + "access"); + if (ret != ARCHIVE_OK) + return (ret); + } + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + ret = set_acl(a, fd, name, abstract_acl, + ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, + "default"); +#endif /* !HAVE_SUN_ACL */ + /* Simultaneous POSIX.1e and NFSv4 is not supported */ return (ret); -#ifdef ACL_TYPE_NFS4 - } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) { - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4, + } +#endif /* !HAVE_DARWIN_ACL */ +#if HAVE_NFS4_ACL + if ((archive_acl_types(abstract_acl) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_PLATFORM_ACL_TYPE_NFS4, ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); - return (ret); -#endif - } else - return ARCHIVE_OK; + } +#endif /* HAVE_NFS4_ACL */ + return (ret); } -static struct { - int archive_perm; - int platform_perm; +/* + * Translate system ACL permissions into libarchive internal structure + */ +static const struct { + const int archive_perm; + const int platform_perm; } acl_perm_map[] = { +#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */ + {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} +#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */ + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +#else /* POSIX.1e ACL permissions */ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, -#ifdef ACL_TYPE_NFS4 +#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, @@ -114,33 +181,69 @@ static struct { {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} #endif +#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ }; -#ifdef ACL_TYPE_NFS4 -static struct { - int archive_inherit; - int platform_inherit; +#if HAVE_NFS4_ACL +/* + * Translate system NFSv4 inheritance flags into libarchive internal structure + */ +static const struct { + const int archive_inherit; + const int platform_inherit; } acl_inherit_map[] = { +#if HAVE_SUN_ACL /* Solaris NFSv4 inheritance flags */ + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} +#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */ + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} +#else /* FreeBSD NFSv4 ACL inheritance flags */ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} +#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ }; -#endif +#endif /* HAVE_NFS4_ACL */ static int set_acl(struct archive *a, int fd, const char *name, struct archive_acl *abstract_acl, acl_type_t acl_type, int ae_requested_type, const char *tname) { +#if HAVE_SUN_ACL + aclent_t *aclent; + ace_t *ace; + int e, r; + acl_t *acl; +#else acl_t acl; acl_entry_t acl_entry; acl_permset_t acl_permset; -#ifdef ACL_TYPE_NFS4 +#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL acl_flagset_t acl_flagset; +#endif +#endif /* HAVE_SUN_ACL */ +#if HAVE_ACL_TYPE_NFS4 + int r; #endif int ret; int ae_type, ae_permset, ae_tag, ae_id; +#if HAVE_DARWIN_ACL + uuid_t ae_uuid; +#endif uid_t ae_uid; gid_t ae_gid; const char *ae_name; @@ -151,22 +254,165 @@ set_acl(struct archive *a, int fd, const char *name, entries = archive_acl_reset(abstract_acl, ae_requested_type); if (entries == 0) return (ARCHIVE_OK); + +#if HAVE_SUN_ACL + acl = NULL; + acl = malloc(sizeof(acl_t)); + if (acl == NULL) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Invalid ACL type"); + return (ARCHIVE_FAILED); + } + if (acl_type == ACE_T) + acl->acl_entry_size = sizeof(ace_t); + else if (acl_type == ACLENT_T) + acl->acl_entry_size = sizeof(aclent_t); + else { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Invalid ACL type"); + acl_free(acl); + return (ARCHIVE_FAILED); + } + acl->acl_type = acl_type; + acl->acl_cnt = entries; + + acl->acl_aclp = malloc(entries * acl->acl_entry_size); + if (acl->acl_aclp == NULL) { + archive_set_error(a, errno, + "Can't allocate memory for acl buffer"); + acl_free(acl); + return (ARCHIVE_FAILED); + } +#else /* !HAVE_SUN_ACL */ acl = acl_init(entries); + if (acl == (acl_t)NULL) { + archive_set_error(a, errno, + "Failed to initialize ACL working storage"); + return (ARCHIVE_FAILED); + } +#endif /* !HAVE_SUN_ACL */ +#if HAVE_SUN_ACL + e = 0; +#endif while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { - acl_create_entry(&acl, &acl_entry); - +#if HAVE_SUN_ACL + ace = NULL; + aclent = NULL; + if (acl->acl_type == ACE_T) { + ace = &((ace_t *)acl->acl_aclp)[e]; + ace->a_who = -1; + ace->a_access_mask = 0; + ace->a_flags = 0; + } else { + aclent = &((aclent_t *)acl->acl_aclp)[e]; + aclent->a_id = -1; + aclent->a_type = 0; + aclent->a_perm = 0; + } +#else /* !HAVE_SUN_ACL */ +#if HAVE_DARWIN_ACL + /* + * Mac OS doesn't support NFSv4 ACLs for + * owner@, group@ and everyone@. + * We skip any of these ACLs found. + */ + if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ || + ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ || + ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE) + continue; +#endif + if (acl_create_entry(&acl, &acl_entry) != 0) { + archive_set_error(a, errno, + "Failed to create a new ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif /* !HAVE_SUN_ACL */ +#if HAVE_DARWIN_ACL + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY); + break; + default: + /* We don't support any other types on MacOS */ + continue; + } +#endif switch (ae_tag) { +#if HAVE_SUN_ACL + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + if (acl->acl_type == ACE_T) + ace->a_who = ae_uid; + else { + aclent->a_id = ae_uid; + aclent->a_type |= USER; + } + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + if (acl->acl_type == ACE_T) { + ace->a_who = ae_gid; + ace->a_flags |= ACE_IDENTIFIER_GROUP; + } else { + aclent->a_id = ae_gid; + aclent->a_type |= GROUP; + } + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + if (acl->acl_type == ACE_T) + ace->a_flags |= ACE_OWNER; + else + aclent->a_type |= USER_OBJ; + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (acl->acl_type == ACE_T) { + ace->a_flags |= ACE_GROUP; + ace->a_flags |= ACE_IDENTIFIER_GROUP; + } else + aclent->a_type |= GROUP_OBJ; + break; + case ARCHIVE_ENTRY_ACL_MASK: + aclent->a_type |= CLASS_OBJ; + break; + case ARCHIVE_ENTRY_ACL_OTHER: + aclent->a_type |= OTHER_OBJ; + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + ace->a_flags |= ACE_EVERYONE; + break; +#else /* !HAVE_SUN_ACL */ case ARCHIVE_ENTRY_ACL_USER: - acl_set_tag_type(acl_entry, ACL_USER); ae_uid = archive_write_disk_uid(a, ae_name, ae_id); +#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ + acl_set_tag_type(acl_entry, ACL_USER); acl_set_qualifier(acl_entry, &ae_uid); +#else /* MacOS */ + if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid, + sizeof(uid_t), ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; +#endif /* HAVE_DARWIN_ACL */ break; case ARCHIVE_ENTRY_ACL_GROUP: - acl_set_tag_type(acl_entry, ACL_GROUP); ae_gid = archive_write_disk_gid(a, ae_name, ae_id); +#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ + acl_set_tag_type(acl_entry, ACL_GROUP); acl_set_qualifier(acl_entry, &ae_gid); +#else /* MacOS */ + if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid, + sizeof(gid_t), ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; +#endif /* HAVE_DARWIN_ACL */ break; +#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ case ARCHIVE_ENTRY_ACL_USER_OBJ: acl_set_tag_type(acl_entry, ACL_USER_OBJ); break; @@ -179,85 +425,230 @@ set_acl(struct archive *a, int fd, const char *name, case ARCHIVE_ENTRY_ACL_OTHER: acl_set_tag_type(acl_entry, ACL_OTHER); break; -#ifdef ACL_TYPE_NFS4 +#if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */ case ARCHIVE_ENTRY_ACL_EVERYONE: acl_set_tag_type(acl_entry, ACL_EVERYONE); break; #endif +#endif /* !HAVE_DARWIN_ACL */ +#endif /* !HAVE_SUN_ACL */ default: - /* XXX */ - break; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; } -#ifdef ACL_TYPE_NFS4 +#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL + r = 0; switch (ae_type) { +#if HAVE_SUN_ACL + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + if (ace != NULL) + ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + if (ace != NULL) + ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + if (ace != NULL) + ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + if (ace != NULL) + ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + if (aclent == NULL) + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + if (aclent != NULL) + aclent->a_type |= ACL_DEFAULT; + else + r = -1; + break; +#else /* !HAVE_SUN_ACL */ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); + r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); break; case ARCHIVE_ENTRY_ACL_TYPE_DENY: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); + r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); break; case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); + r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); break; case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM); + r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM); break; case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: // These don't translate directly into the system ACL. break; +#endif /* !HAVE_SUN_ACL */ default: - // XXX error handling here. - break; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; } -#endif - acl_get_permset(acl_entry, &acl_permset); - acl_clear_perms(acl_permset); + if (r != 0) { +#if HAVE_SUN_ACL + errno = EINVAL; +#endif + archive_set_error(a, errno, + "Failed to set ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */ +#if HAVE_SUN_ACL + if (acl->acl_type == ACLENT_T) { + if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE) + aclent->a_perm |= 1; + if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE) + aclent->a_perm |= 2; + if (ae_permset & ARCHIVE_ENTRY_ACL_READ) + aclent->a_perm |= 4; + } else +#else + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to get ACL permission set"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_perms(acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to clear ACL permissions"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif /* !HAVE_SUN_ACL */ for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { - if (ae_permset & acl_perm_map[i].archive_perm) - acl_add_perm(acl_permset, - acl_perm_map[i].platform_perm); + if (ae_permset & acl_perm_map[i].archive_perm) { +#if HAVE_SUN_ACL + ace->a_access_mask |= + acl_perm_map[i].platform_perm; +#else + if (acl_add_perm(acl_permset, + acl_perm_map[i].platform_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif + } } -#ifdef ACL_TYPE_NFS4 - acl_get_flagset_np(acl_entry, &acl_flagset); - acl_clear_flags_np(acl_flagset); - for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - if (ae_permset & acl_inherit_map[i].archive_inherit) - acl_add_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit); +#if HAVE_NFS4_ACL +#if HAVE_SUN_ACL + if (acl_type == ACE_T) +#elif HAVE_DARWIN_ACL + if (acl_type == ACL_TYPE_EXTENDED) +#else /* FreeBSD */ + if (acl_type == ACL_TYPE_NFS4) +#endif + { +#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL + /* + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to get flagset from an NFSv4 ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_flags_np(acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to clear flags from an NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */ + for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) { + if (ae_permset & acl_inherit_map[i].archive_inherit) { +#if HAVE_SUN_ACL + ace->a_flags |= + acl_inherit_map[i].platform_inherit; +#else /* !HAVE_SUN_ACL */ + if (acl_add_flag_np(acl_flagset, + acl_inherit_map[i].platform_inherit) != 0) { + archive_set_error(a, errno, + "Failed to add flag to NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif /* HAVE_SUN_ACL */ + } + } } +#endif /* HAVE_NFS4_ACL */ +#if HAVE_SUN_ACL + e++; #endif } +#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL /* Try restoring the ACL through 'fd' if we can. */ -#if HAVE_ACL_SET_FD - if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0) - ret = ARCHIVE_OK; - else -#else -#if HAVE_ACL_SET_FD_NP - if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0) - ret = ARCHIVE_OK; - else +#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP + if (fd >= 0) +#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */ + if (fd >= 0 && acl_type == ACL_TYPE_ACCESS) #endif + { +#if HAVE_SUN_ACL + if (facl_set(fd, acl) == 0) +#elif HAVE_ACL_SET_FD_NP + if (acl_set_fd_np(fd, acl, acl_type) == 0) +#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */ + if (acl_set_fd(fd, acl) == 0) #endif -#if HAVE_ACL_SET_LINK_NP - if (acl_set_link_np(name, acl_type, acl) != 0) { - archive_set_error(a, errno, "Failed to set %s acl", tname); - ret = ARCHIVE_WARN; - } + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set %s acl on fd", tname); + } + } + } else +#endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */ +#if HAVE_SUN_ACL + if (acl_set(name, acl) != 0) +#elif HAVE_ACL_SET_LINK_NP + if (acl_set_link_np(name, acl_type, acl) != 0) #else /* TODO: Skip this if 'name' is a symlink. */ - if (acl_set_file(name, acl_type, acl) != 0) { - archive_set_error(a, errno, "Failed to set %s acl", tname); - ret = ARCHIVE_WARN; - } + if (acl_set_file(name, acl_type, acl) != 0) #endif + { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set %s acl", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: acl_free(acl); return (ret); } -#endif +#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c index 59466838c..a5f30671a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c @@ -110,6 +110,18 @@ __FBSDID("$FreeBSD$"); #include #endif +/* + * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared. + * + * It assumes that the input is an integer type of no more than 64 bits. + * If the number is less than zero, t must be a signed type, so it fits in + * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t + * without loss. But it could be a large unsigned value, so we have to clip it + * to INT64_MAX.* + */ +#define to_int64_time(t) \ + ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t)) + #if __APPLE__ #include #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H @@ -140,7 +152,17 @@ __FBSDID("$FreeBSD$"); #define O_BINARY 0 #endif #ifndef O_CLOEXEC -#define O_CLOEXEC 0 +#define O_CLOEXEC 0 +#endif + +/* Ignore non-int O_NOFOLLOW constant. */ +/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */ +#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) +#undef O_NOFOLLOW +#endif + +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 #endif struct fixup_entry { @@ -298,7 +320,7 @@ struct archive_write_disk { #define MAXIMUM_DIR_MODE 0775 /* - * Maxinum uncompressed size of a decmpfs block. + * Maximum uncompressed size of a decmpfs block. */ #define MAX_DECMPFS_BLOCK_SIZE (64 * 1024) /* @@ -313,7 +335,7 @@ struct archive_write_disk { #define RSRC_F_SIZE 50 /* Size of Resource fork footer. */ /* Size to write compressed data to resource fork. */ #define COMPRESSED_W_SIZE (64 * 1024) -/* decmpfs difinitions. */ +/* decmpfs definitions. */ #define MAX_DECMPFS_XATTR_SIZE 3802 #ifndef DECMPFS_XATTR_NAME #define DECMPFS_XATTR_NAME "com.apple.decmpfs" @@ -326,12 +348,19 @@ struct archive_write_disk { #define HFS_BLOCKS(s) ((s) >> 12) +static void fsobj_error(int *, struct archive_string *, int, const char *, + const char *); +static int check_symlinks_fsobj(char *, int *, struct archive_string *, + int); static int check_symlinks(struct archive_write_disk *); static int create_filesystem_object(struct archive_write_disk *); -static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname); +static struct fixup_entry *current_fixup(struct archive_write_disk *, + const char *pathname); #if defined(HAVE_FCHDIR) && defined(PATH_MAX) static void edit_deep_directories(struct archive_write_disk *ad); #endif +static int cleanup_pathname_fsobj(char *, int *, struct archive_string *, + int); static int cleanup_pathname(struct archive_write_disk *); static int create_dir(struct archive_write_disk *, char *); static int create_parent_dir(struct archive_write_disk *, char *); @@ -362,11 +391,14 @@ static struct archive_vtable *archive_write_disk_vtable(void); static int _archive_write_disk_close(struct archive *); static int _archive_write_disk_free(struct archive *); -static int _archive_write_disk_header(struct archive *, struct archive_entry *); +static int _archive_write_disk_header(struct archive *, + struct archive_entry *); static int64_t _archive_write_disk_filter_bytes(struct archive *, int); static int _archive_write_disk_finish_entry(struct archive *); -static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t); -static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t); +static ssize_t _archive_write_disk_data(struct archive *, const void *, + size_t); +static ssize_t _archive_write_disk_data_block(struct archive *, const void *, + size_t, int64_t); static int lazy_stat(struct archive_write_disk *a) @@ -612,9 +644,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) /* * NOTE: UF_COMPRESSED is ignored even if the filesystem * supports HFS+ Compression because the file should - * have at least an extended attriute "com.apple.decmpfs" + * have at least an extended attribute "com.apple.decmpfs" * before the flag is set to indicate that the file have - * been compressed. If hte filesystem does not support + * been compressed. If the filesystem does not support * HFS+ Compression the system call will fail. */ if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0) @@ -637,7 +669,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) if (a->restore_pwd >= 0) { r = fchdir(a->restore_pwd); if (r != 0) { - archive_set_error(&a->archive, errno, "chdir() failure"); + archive_set_error(&a->archive, errno, + "chdir() failure"); ret = ARCHIVE_FATAL; } close(a->restore_pwd); @@ -685,7 +718,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) } if (archive_entry_birthtime_is_set(entry)) { fe->birthtime = archive_entry_birthtime(entry); - fe->birthtime_nanos = archive_entry_birthtime_nsec(entry); + fe->birthtime_nanos = archive_entry_birthtime_nsec( + entry); } else { /* If birthtime is unset, use mtime. */ fe->birthtime = fe->mtime; @@ -711,7 +745,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) return (ARCHIVE_FATAL); fe->mac_metadata = malloc(metadata_size); if (fe->mac_metadata != NULL) { - memcpy(fe->mac_metadata, metadata, metadata_size); + memcpy(fe->mac_metadata, metadata, + metadata_size); fe->mac_metadata_size = metadata_size; fe->fixup |= TODO_MAC_METADATA; } @@ -1224,7 +1259,7 @@ hfs_drive_compressor(struct archive_write_disk *a, const char *buff, ret = hfs_write_compressed_data(a, bytes_used + rsrc_size); a->compressed_buffer_remaining = a->compressed_buffer_size; - /* If the compressed size is not enouph smaller than + /* If the compressed size is not enough smaller than * the uncompressed size. cancel HFS+ compression. * TODO: study a behavior of ditto utility and improve * the condition to fall back into no HFS+ compression. */ @@ -1329,7 +1364,7 @@ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff, (uint32_t *)(a->resource_fork + RSRC_H_SIZE); /* Set the block count to the resource fork. */ archive_le32enc(a->decmpfs_block_info++, block_count); - /* Get the position where we are goint to set compressed + /* Get the position where we are going to set compressed * data. */ a->compressed_rsrc_position = RSRC_H_SIZE + 4 + (block_count * 8); @@ -1402,7 +1437,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff, bytes_to_write = size; /* Seek if necessary to the specified offset. */ if (a->offset < a->fd_offset) { - /* Can't support backword move. */ + /* Can't support backward move. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek failed"); return (ARCHIVE_FATAL); @@ -1468,7 +1503,8 @@ _archive_write_disk_data_block(struct archive *_a, return (r); if ((size_t)r < size) { archive_set_error(&a->archive, 0, - "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize); + "Too much data: Truncating file at %ju bytes", + (uintmax_t)a->filesize); return (ARCHIVE_WARN); } #if ARCHIVE_VERSION_NUMBER < 3999000 @@ -1666,10 +1702,26 @@ _archive_write_disk_finish_entry(struct archive *_a) * ACLs that prevent attribute changes (including time). */ if (a->todo & TODO_ACLS) { - int r2 = archive_write_disk_set_acls(&a->archive, a->fd, - archive_entry_pathname(a->entry), - archive_entry_acl(a->entry)); + int r2; +#ifdef HAVE_DARWIN_ACL + /* + * On Mac OS, platform ACLs are stored also in mac_metadata by + * the operating system. If mac_metadata is present it takes + * precedence and we skip extracting libarchive NFSv4 ACLs + */ + const void *metadata; + size_t metadata_size; + metadata = archive_entry_mac_metadata(a->entry, &metadata_size); + if ((a->todo & TODO_MAC_METADATA) == 0 || + metadata == NULL || metadata_size == 0) { +#endif + r2 = archive_write_disk_set_acls(&a->archive, a->fd, + archive_entry_pathname(a->entry), + archive_entry_acl(a->entry)); if (r2 < ret) ret = r2; +#ifdef HAVE_DARWIN_ACL + } +#endif } finish_metadata: @@ -1755,10 +1807,9 @@ archive_write_disk_new(void) { struct archive_write_disk *a; - a = (struct archive_write_disk *)malloc(sizeof(*a)); + a = (struct archive_write_disk *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; /* We're ready to write a header immediately. */ a->archive.state = ARCHIVE_STATE_HEADER; @@ -1796,7 +1847,7 @@ edit_deep_directories(struct archive_write_disk *a) char *tail = a->name; /* If path is short, avoid the open() below. */ - if (strlen(tail) <= PATH_MAX) + if (strlen(tail) < PATH_MAX) return; /* Try to record our starting dir. */ @@ -1806,7 +1857,7 @@ edit_deep_directories(struct archive_write_disk *a) return; /* As long as the path is too long... */ - while (strlen(tail) > PATH_MAX) { + while (strlen(tail) >= PATH_MAX) { /* Locate a dir prefix shorter than PATH_MAX. */ tail += PATH_MAX - 8; while (tail > a->name && *tail != '/') @@ -1993,8 +2044,9 @@ restore_entry(struct archive_write_disk *a) if (en) { /* Everything failed; give up here. */ - archive_set_error(&a->archive, en, "Can't create '%s'", - a->name); + if ((&a->archive)->error == NULL) + archive_set_error(&a->archive, en, "Can't create '%s'", + a->name); return (ARCHIVE_FAILED); } @@ -2014,6 +2066,11 @@ create_filesystem_object(struct archive_write_disk *a) const char *linkname; mode_t final_mode, mode; int r; + /* these for check_symlinks_fsobj */ + char *linkname_copy; /* non-const copy of linkname */ + struct stat st; + struct archive_string error_string; + int error_number; /* We identify hard/symlinks according to the link names. */ /* Since link(2) and symlink(2) don't handle modes, we're done here. */ @@ -2022,6 +2079,43 @@ create_filesystem_object(struct archive_write_disk *a) #if !HAVE_LINK return (EPERM); #else + archive_string_init(&error_string); + linkname_copy = strdup(linkname); + if (linkname_copy == NULL) { + return (EPERM); + } + /* + * TODO: consider using the cleaned-up path as the link + * target? + */ + r = cleanup_pathname_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + r = check_symlinks_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + free(linkname_copy); + archive_string_free(&error_string); r = link(linkname, a->name) ? errno : 0; /* * New cpio and pax formats allow hardlink entries @@ -2039,11 +2133,20 @@ create_filesystem_object(struct archive_write_disk *a) a->todo = 0; a->deferred = 0; } else if (r == 0 && a->filesize > 0) { - a->fd = open(a->name, - O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC); - __archive_ensure_cloexec_flag(a->fd); - if (a->fd < 0) +#ifdef HAVE_LSTAT + r = lstat(a->name, &st); +#else + r = stat(a->name, &st); +#endif + if (r != 0) r = errno; + else if ((st.st_mode & AE_IFMT) == AE_IFREG) { + a->fd = open(a->name, O_WRONLY | O_TRUNC | + O_BINARY | O_CLOEXEC | O_NOFOLLOW); + __archive_ensure_cloexec_flag(a->fd); + if (a->fd < 0) + r = errno; + } } return (r); #endif @@ -2190,8 +2293,13 @@ _archive_write_disk_close(struct archive *_a) if (p->fixup & TODO_MODE_BASE) chmod(p->name, p->mode); if (p->fixup & TODO_ACLS) - archive_write_disk_set_acls(&a->archive, - -1, p->name, &p->acl); +#ifdef HAVE_DARWIN_ACL + if ((p->fixup & TODO_MAC_METADATA) == 0 || + p->mac_metadata == NULL || + p->mac_metadata_size == 0) +#endif + archive_write_disk_set_acls(&a->archive, + -1, p->name, &p->acl); if (p->fixup & TODO_FFLAGS) set_fflags_platform(a, -1, p->name, p->mode, p->fflags_set, 0); @@ -2351,116 +2459,283 @@ current_fixup(struct archive_write_disk *a, const char *pathname) return (a->current_fixup); } -/* TODO: Make this work. */ -/* - * TODO: The deep-directory support bypasses this; disable deep directory - * support if we're doing symlink checks. - */ +/* Error helper for new *_fsobj functions */ +static void +fsobj_error(int *a_eno, struct archive_string *a_estr, + int err, const char *errstr, const char *path) +{ + if (a_eno) + *a_eno = err; + if (a_estr) + archive_string_sprintf(a_estr, errstr, path); +} + /* * TODO: Someday, integrate this with the deep dir support; they both * scan the path and both can be optimized by comparing against other * recent paths. */ /* TODO: Extend this to support symlinks on Windows Vista and later. */ + +/* + * Checks the given path to see if any elements along it are symlinks. Returns + * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. + */ static int -check_symlinks(struct archive_write_disk *a) +check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) { #if !defined(HAVE_LSTAT) /* Platform doesn't have lstat, so we can't look for symlinks. */ - (void)a; /* UNUSED */ + (void)path; /* UNUSED */ + (void)error_number; /* UNUSED */ + (void)error_string; /* UNUSED */ + (void)flags; /* UNUSED */ return (ARCHIVE_OK); #else - char *pn; + int res = ARCHIVE_OK; + char *tail; + char *head; + int last; char c; int r; struct stat st; + int restore_pwd; + + /* Nothing to do here if name is empty */ + if(path[0] == '\0') + return (ARCHIVE_OK); /* * Guard against symlink tricks. Reject any archive entry whose * destination would be altered by a symlink. + * + * Walk the filename in chunks separated by '/'. For each segment: + * - if it doesn't exist, continue + * - if it's symlink, abort or remove it + * - if it's a directory and it's not the last chunk, cd into it + * As we go: + * head points to the current (relative) path + * tail points to the temporary \0 terminating the segment we're + * currently examining + * c holds what used to be in *tail + * last is 1 if this is the last tail */ - /* Whatever we checked last time doesn't need to be re-checked. */ - pn = a->name; - if (archive_strlen(&(a->path_safe)) > 0) { - char *p = a->path_safe.s; - while ((*pn != '\0') && (*p == *pn)) - ++p, ++pn; - } + restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(restore_pwd); + if (restore_pwd < 0) + return (ARCHIVE_FATAL); + head = path; + tail = path; + last = 0; + /* TODO: reintroduce a safe cache here? */ /* Skip the root directory if the path is absolute. */ - if(pn == a->name && pn[0] == '/') - ++pn; - c = pn[0]; - /* Keep going until we've checked the entire name. */ - while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) { + if(tail == path && tail[0] == '/') + ++tail; + /* Keep going until we've checked the entire name. + * head, tail, path all alias the same string, which is + * temporarily zeroed at tail, so be careful restoring the + * stashed (c=tail[0]) for error messages. + * Exiting the loop with break is okay; continue is not. + */ + while (!last) { + /* + * Skip the separator we just consumed, plus any adjacent ones + */ + while (*tail == '/') + ++tail; /* Skip the next path element. */ - while (*pn != '\0' && *pn != '/') - ++pn; - c = pn[0]; - pn[0] = '\0'; + while (*tail != '\0' && *tail != '/') + ++tail; + /* is this the last path component? */ + last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0'); + /* temporarily truncate the string here */ + c = tail[0]; + tail[0] = '\0'; /* Check that we haven't hit a symlink. */ - r = lstat(a->name, &st); + r = lstat(head, &st); if (r != 0) { + tail[0] = c; /* We've hit a dir that doesn't exist; stop now. */ - if (errno == ENOENT) + if (errno == ENOENT) { + break; + } else { + /* + * Treat any other error as fatal - best to be + * paranoid here. + * Note: This effectively disables deep + * directory support when security checks are + * enabled. Otherwise, very long pathnames that + * trigger an error here could evade the + * sandbox. + * TODO: We could do better, but it would + * probably require merging the symlink checks + * with the deep-directory editing. + */ + fsobj_error(a_eno, a_estr, errno, + "Could not stat %s", path); + res = ARCHIVE_FAILED; break; + } + } else if (S_ISDIR(st.st_mode)) { + if (!last) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* Our view is now from inside this dir: */ + head = tail + 1; + } } else if (S_ISLNK(st.st_mode)) { - if (c == '\0') { + if (last) { /* * Last element is symlink; remove it * so we can overwrite it with the * item being extracted. */ - if (unlink(a->name)) { - archive_set_error(&a->archive, errno, + if (unlink(head)) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, "Could not remove symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); + path); + res = ARCHIVE_FAILED; + break; } - a->pst = NULL; /* * Even if we did remove it, a warning * is in order. The warning is silly, * though, if we're just replacing one * symlink with another symlink. */ - if (!S_ISLNK(a->mode)) { - archive_set_error(&a->archive, 0, - "Removing symlink %s", - a->name); + tail[0] = c; + /* + * FIXME: not sure how important this is to + * restore + */ + /* + if (!S_ISLNK(path)) { + fsobj_error(a_eno, a_estr, 0, + "Removing symlink %s", path); } + */ /* Symlink gone. No more problem! */ - pn[0] = c; - return (0); - } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) { + res = ARCHIVE_OK; + break; + } else if (flags & ARCHIVE_EXTRACT_UNLINK) { /* User asked us to remove problems. */ - if (unlink(a->name) != 0) { - archive_set_error(&a->archive, 0, - "Cannot remove intervening symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); + if (unlink(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot remove intervening " + "symlink %s", path); + res = ARCHIVE_FAILED; + break; + } + tail[0] = c; + } else if ((flags & + ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { + /* + * We are not the last element and we want to + * follow symlinks if they are a directory. + * + * This is needed to extract hardlinks over + * symlinks. + */ + r = stat(head, &st); + if (r != 0) { + tail[0] = c; + if (errno == ENOENT) { + break; + } else { + fsobj_error(a_eno, a_estr, + errno, + "Could not stat %s", path); + res = (ARCHIVE_FAILED); + break; + } + } else if (S_ISDIR(st.st_mode)) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, + errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* + * Our view is now from inside + * this dir: + */ + head = tail + 1; + } else { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through " + "symlink %s", path); + res = ARCHIVE_FAILED; + break; } - a->pst = NULL; } else { - archive_set_error(&a->archive, 0, - "Cannot extract through symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through symlink %s", path); + res = ARCHIVE_FAILED; + break; } } - pn[0] = c; - if (pn[0] != '\0') - pn++; /* Advance to the next segment. */ + /* be sure to always maintain this */ + tail[0] = c; + if (tail[0] != '\0') + tail++; /* Advance to the next segment. */ + } + /* Catches loop exits via break */ + tail[0] = c; +#ifdef HAVE_FCHDIR + /* If we changed directory above, restore it here. */ + if (restore_pwd >= 0) { + r = fchdir(restore_pwd); + if (r != 0) { + fsobj_error(a_eno, a_estr, errno, + "chdir() failure", ""); + } + close(restore_pwd); + restore_pwd = -1; + if (r != 0) { + res = (ARCHIVE_FATAL); + } } - pn[0] = c; - /* We've checked and/or cleaned the whole path, so remember it. */ - archive_strcpy(&a->path_safe, a->name); - return (ARCHIVE_OK); #endif + /* TODO: reintroduce a safe cache here? */ + return res; +#endif +} + +/* + * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise + * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED} + */ +static int +check_symlinks(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = check_symlinks_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + a->pst = NULL; /* to be safe */ + return rc; } + #if defined(__CYGWIN__) /* * 1. Convert a path separator from '\' to '/' . @@ -2471,7 +2746,7 @@ check_symlinks(struct archive_write_disk *a) * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx */ static void -cleanup_pathname_win(struct archive_write_disk *a) +cleanup_pathname_win(char *path) { wchar_t wc; char *p; @@ -2482,7 +2757,7 @@ cleanup_pathname_win(struct archive_write_disk *a) mb = 0; complete = 1; utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0; - for (p = a->name; *p != '\0'; p++) { + for (p = path; *p != '\0'; p++) { ++alen; if (*p == '\\') { /* If previous byte is smaller than 128, @@ -2507,7 +2782,7 @@ cleanup_pathname_win(struct archive_write_disk *a) /* * Convert path separator in wide-character. */ - p = a->name; + p = path; while (*p != '\0' && alen) { l = mbtowc(&wc, p, alen); if (l == (size_t)-1) { @@ -2534,26 +2809,27 @@ cleanup_pathname_win(struct archive_write_disk *a) * is set) if the path is absolute. */ static int -cleanup_pathname(struct archive_write_disk *a) +cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) { char *dest, *src; char separator = '\0'; - dest = src = a->name; + dest = src = path; if (*src == '\0') { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Invalid empty pathname"); + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Invalid empty ", "pathname"); return (ARCHIVE_FAILED); } #if defined(__CYGWIN__) - cleanup_pathname_win(a); + cleanup_pathname_win(path); #endif /* Skip leading '/'. */ if (*src == '/') { - if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Path is absolute"); + if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Path is ", "absolute"); return (ARCHIVE_FAILED); } @@ -2580,10 +2856,11 @@ cleanup_pathname(struct archive_write_disk *a) } else if (src[1] == '.') { if (src[2] == '/' || src[2] == '\0') { /* Conditionally warn about '..' */ - if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { - archive_set_error(&a->archive, + if (flags + & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, - "Path contains '..'"); + "Path contains ", "'..'"); return (ARCHIVE_FAILED); } } @@ -2614,7 +2891,7 @@ cleanup_pathname(struct archive_write_disk *a) * We've just copied zero or more path elements, not including the * final '/'. */ - if (dest == a->name) { + if (dest == path) { /* * Nothing got copied. The path must have been something * like '.' or '/' or './' or '/././././/./'. @@ -2629,6 +2906,23 @@ cleanup_pathname(struct archive_write_disk *a) return (ARCHIVE_OK); } +static int +cleanup_pathname(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + return rc; +} + /* * Create the parent directory of the specified path, assuming path * is already in mutable storage. @@ -2707,7 +3001,8 @@ create_dir(struct archive_write_disk *a, char *path) } } else if (errno != ENOENT && errno != ENOTDIR) { /* Stat failed? */ - archive_set_error(&a->archive, errno, "Can't test directory '%s'", path); + archive_set_error(&a->archive, errno, + "Can't test directory '%s'", path); return (ARCHIVE_FAILED); } else if (slash != NULL) { *slash = '\0'; @@ -3172,12 +3467,19 @@ set_fflags(struct archive_write_disk *a) #ifdef UF_APPEND critical_flags |= UF_APPEND; #endif -#ifdef EXT2_APPEND_FL +#if defined(FS_APPEND_FL) + critical_flags |= FS_APPEND_FL; +#elif defined(EXT2_APPEND_FL) critical_flags |= EXT2_APPEND_FL; #endif -#ifdef EXT2_IMMUTABLE_FL +#if defined(FS_IMMUTABLE_FL) + critical_flags |= FS_IMMUTABLE_FL; +#elif defined(EXT2_IMMUTABLE_FL) critical_flags |= EXT2_IMMUTABLE_FL; #endif +#ifdef FS_JOURNAL_DATA_FL + critical_flags |= FS_JOURNAL_DATA_FL; +#endif if (a->todo & TODO_FFLAGS) { archive_entry_fflags(a->entry, &set, &clear); @@ -3232,7 +3534,8 @@ clear_nochange_fflags(struct archive_write_disk *a) nochange_flags |= EXT2_IMMUTABLE_FL; #endif - return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags)); + return (set_fflags_platform(a, a->fd, a->name, mode, 0, + nochange_flags)); } @@ -3288,7 +3591,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, return (ARCHIVE_WARN); } -#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) +#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \ + defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \ + defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) /* * Linux uses ioctl() to read and write file flags. */ @@ -3301,7 +3607,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, int newflags, oldflags; int sf_mask = 0; - if (set == 0 && clear == 0) + if (set == 0 && clear == 0) return (ARCHIVE_OK); /* Only regular files and dirs can have flags. */ if (!S_ISREG(mode) && !S_ISDIR(mode)) @@ -3322,11 +3628,18 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, * defines. (?) The code below degrades reasonably gracefully * if sf_mask is incomplete. */ -#ifdef EXT2_IMMUTABLE_FL +#if defined(FS_IMMUTABLE_FL) + sf_mask |= FS_IMMUTABLE_FL; +#elif defined(EXT2_IMMUTABLE_FL) sf_mask |= EXT2_IMMUTABLE_FL; #endif -#ifdef EXT2_APPEND_FL +#if defined(FS_APPEND_FL) + sf_mask |= FS_APPEND_FL; +#elif defined(EXT2_APPEND_FL) sf_mask |= EXT2_APPEND_FL; +#endif +#if defined(FS_JOURNAL_DATA_FL) + sf_mask |= FS_JOURNAL_DATA_FL; #endif /* * XXX As above, this would be way simpler if we didn't have @@ -3335,12 +3648,24 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, ret = ARCHIVE_OK; /* Read the current file flags. */ - if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0) + if (ioctl(myfd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &oldflags) < 0) goto fail; /* Try setting the flags as given. */ newflags = (oldflags & ~clear) | set; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) + if (ioctl(myfd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &newflags) >= 0) goto cleanup; if (errno != EPERM) goto fail; @@ -3349,7 +3674,13 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, newflags &= ~sf_mask; oldflags &= sf_mask; newflags |= oldflags; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) + if (ioctl(myfd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &newflags) >= 0) goto cleanup; /* We couldn't set the flags, so report the failure. */ @@ -3487,6 +3818,9 @@ exit_xattr: static int copy_acls(struct archive_write_disk *a, int tmpfd, int dffd) { +#ifndef HAVE_SYS_ACL_H + return 0; +#else acl_t acl, dfacl = NULL; int acl_r, ret = ARCHIVE_OK; @@ -3514,6 +3848,7 @@ exit_acl: if (dfacl) acl_free(dfacl); return (ret); +#endif } static int @@ -3753,7 +4088,8 @@ set_xattrs(struct archive_write_disk *a) if (errno == ENOTSUP || errno == ENOSYS) { if (!warning_done) { warning_done = 1; - archive_set_error(&a->archive, errno, + archive_set_error(&a->archive, + errno, "Cannot restore extended " "attributes on this file " "system"); @@ -3764,7 +4100,8 @@ set_xattrs(struct archive_write_disk *a) ret = ARCHIVE_WARN; } } else { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Invalid extended attribute encountered"); ret = ARCHIVE_WARN; } @@ -3808,19 +4145,22 @@ set_xattrs(struct archive_write_disk *a) errno = 0; #if HAVE_EXTATTR_SET_FD if (a->fd >= 0) - e = extattr_set_fd(a->fd, namespace, name, value, size); + e = extattr_set_fd(a->fd, namespace, name, + value, size); else #endif /* TODO: should we use extattr_set_link() instead? */ { - e = extattr_set_file(archive_entry_pathname(entry), - namespace, name, value, size); + e = extattr_set_file( + archive_entry_pathname(entry), namespace, + name, value, size); } if (e != (int)size) { if (errno == ENOTSUP || errno == ENOSYS) { if (!warning_done) { warning_done = 1; - archive_set_error(&a->archive, errno, + archive_set_error(&a->archive, + errno, "Cannot restore extended " "attributes on this file " "system"); @@ -3866,10 +4206,10 @@ older(struct stat *st, struct archive_entry *entry) { /* First, test the seconds and return if we have a definite answer. */ /* Definitely older. */ - if (st->st_mtime < archive_entry_mtime(entry)) + if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry))) return (1); /* Definitely younger. */ - if (st->st_mtime > archive_entry_mtime(entry)) + if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry))) return (0); /* If this platform supports fractional seconds, try those. */ #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c index 3b868fbad..5c766d75d 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c @@ -84,15 +84,13 @@ static void cleanup(void *); int archive_write_disk_set_standard_lookup(struct archive *a) { - struct bucket *ucache = malloc(cache_size * sizeof(struct bucket)); - struct bucket *gcache = malloc(cache_size * sizeof(struct bucket)); + struct bucket *ucache = calloc(cache_size, sizeof(struct bucket)); + struct bucket *gcache = calloc(cache_size, sizeof(struct bucket)); if (ucache == NULL || gcache == NULL) { free(ucache); free(gcache); return (ARCHIVE_FATAL); } - memset(ucache, 0, cache_size * sizeof(struct bucket)); - memset(gcache, 0, cache_size * sizeof(struct bucket)); archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup); archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup); return (ARCHIVE_OK); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c index da76c54db..94b016edf 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c @@ -192,7 +192,7 @@ struct archive_write_disk { /* * Default mode for dirs created automatically (will be modified by umask). - * Note that POSIX specifies 0777 for implicity-created dirs, "modified + * Note that POSIX specifies 0777 for implicitly-created dirs, "modified * by the process' file creation mask." */ #define DEFAULT_DIR_MODE 0777 @@ -396,7 +396,7 @@ permissive_name_w(struct archive_write_disk *a) } /* - * A full-pathname pointig a network drive + * A full-pathname pointing to a network drive * like "\\\\file". */ if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') { @@ -1221,10 +1221,9 @@ archive_write_disk_new(void) { struct archive_write_disk *a; - a = (struct archive_write_disk *)malloc(sizeof(*a)); + a = (struct archive_write_disk *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; /* We're ready to write a header immediately. */ a->archive.state = ARCHIVE_STATE_HEADER; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open.3 b/Utilities/cmlibarchive/libarchive/archive_write_open.3 index a52959b98..457873e61 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_open.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_open.3 @@ -66,6 +66,7 @@ Freeze the settings, open the archive, and prepare for writing entries. This is the most generic form of this function, which accepts pointers to three callback functions which will be invoked by the compression layer to write the constructed archive. +This does not alter the default archive padding. .It Fn archive_write_open_fd A convenience form of .Fn archive_write_open @@ -123,12 +124,21 @@ is currently in use. You should be careful to ensure that this variable remains allocated until after the archive is closed. +This function will disable padding unless you +have specifically set the block size. .El More information about the .Va struct archive object and the overall design of the library can be found in the .Xr libarchive 3 overview. +.Pp +Note that the convenience forms above vary in how +they block the output. +See +.Xr archive_write_blocksize 3 +if you need to control the block size used for writes +or the end-of-file padding behavior. .\" .Sh CLIENT CALLBACKS To use this library, you will need to define and register @@ -226,6 +236,7 @@ functions. .Xr tar 1 , .Xr libarchive 3 , .Xr archive_write 3 , +.Xr archive_write_blocksize 3 , .Xr archive_write_filter 3 , .Xr archive_write_format 3 , .Xr archive_write_new 3 , diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c index 4f8d679e5..ea6ae0ac5 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c @@ -53,12 +53,11 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t { struct write_memory_data *mine; - mine = (struct write_memory_data *)malloc(sizeof(*mine)); + mine = (struct write_memory_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } - memset(mine, 0, sizeof(*mine)); mine->buff = buff; mine->size = buffSize; mine->client_size = used; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c index 8718d2581..3fc5a07d7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c @@ -205,7 +205,7 @@ struct _7zip { /* * The list of the file entries which has its contents is used to * manage struct file objects. - * We use 'next' a menber of struct file to chain. + * We use 'next' (a member of struct file) to chain. */ struct { struct file *first; @@ -1358,7 +1358,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, if (r < 0) return (r); - /* Write Nume size. */ + /* Write Name size. */ r = enc_uint64(a, zip->total_bytes_entry_name+1); if (r < 0) return (r); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c index 9f17564c3..c9771d81a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c @@ -126,12 +126,11 @@ archive_write_set_format_ar(struct archive_write *a) if (a->format_free != NULL) (a->format_free)(a); - ar = (struct ar_w *)malloc(sizeof(*ar)); + ar = (struct ar_w *)calloc(1, sizeof(*ar)); if (ar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data"); return (ARCHIVE_FATAL); } - memset(ar, 0, sizeof(*ar)); a->format_data = ar; a->format_name = "ar"; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c index 352649365..a4c9d1ed2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c @@ -289,7 +289,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) sconv = get_sconv(a); #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c index a9bfa808c..957f1a333 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c @@ -116,12 +116,11 @@ archive_write_set_format_cpio_newc(struct archive *_a) if (a->format_free != NULL) (a->format_free)(a); - cpio = (struct cpio *)malloc(sizeof(*cpio)); + cpio = (struct cpio *)calloc(1, sizeof(*cpio)); if (cpio == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); return (ARCHIVE_FATAL); } - memset(cpio, 0, sizeof(*cpio)); a->format_data = cpio; a->format_name = "cpio"; a->format_options = archive_write_newc_options; @@ -232,7 +231,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) sconv = get_sconv(a); #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c index 1d635d2dc..2d858c9f7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c @@ -119,9 +119,9 @@ static const char template_header[] = { '0','0','0','0','0','0', '0','\0', /* gid, null termination: 8 bytes */ '0','0','0','0','0','0', '0','\0', - /* size, space termation: 12 bytes */ + /* size, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', '\0', - /* mtime, space termation: 12 bytes */ + /* mtime, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', '\0', /* Initial checksum value: 8 spaces */ ' ',' ',' ',' ',' ',' ',' ',' ', @@ -368,7 +368,7 @@ archive_write_gnutar_header(struct archive_write *a, } #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { @@ -478,15 +478,15 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_pathname(temp, "././@LongLink"); archive_entry_set_size(temp, length); ret = archive_format_gnutar_header(a, buff, temp, 'K'); + archive_entry_free(temp); if (ret < ARCHIVE_WARN) goto exit_write_header; ret = __archive_write_output(a, buff, 512); - if(ret < ARCHIVE_WARN) + if (ret < ARCHIVE_WARN) goto exit_write_header; - archive_entry_free(temp); /* Write name and trailing null byte. */ ret = __archive_write_output(a, gnutar->linkname, length); - if(ret < ARCHIVE_WARN) + if (ret < ARCHIVE_WARN) goto exit_write_header; /* Pad to 512 bytes */ ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length)); @@ -508,12 +508,12 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_pathname(temp, "././@LongLink"); archive_entry_set_size(temp, length); ret = archive_format_gnutar_header(a, buff, temp, 'L'); + archive_entry_free(temp); if (ret < ARCHIVE_WARN) goto exit_write_header; ret = __archive_write_output(a, buff, 512); if(ret < ARCHIVE_WARN) goto exit_write_header; - archive_entry_free(temp); /* Write pathname + trailing null byte. */ ret = __archive_write_output(a, pathname, length); if(ret < ARCHIVE_WARN) diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c index 879a77695..4adf68e68 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c @@ -161,7 +161,7 @@ struct isofile { /* Used for managing struct isofile list. */ struct isofile *allnext; struct isofile *datanext; - /* Used for managing a hardlined struct isofile list. */ + /* Used for managing a hardlinked struct isofile list. */ struct isofile *hlnext; struct isofile *hardlink_target; @@ -436,7 +436,7 @@ struct iso_option { * Type : string * Default: Auto detect * : We check a size of boot image; - * : If ths size is just 1.22M/1.44M/2.88M, + * : If the size is just 1.22M/1.44M/2.88M, * : we assume boot_type is 'fd'; * : otherwise boot_type is 'no-emulation'. * COMPAT : @@ -528,7 +528,7 @@ struct iso_option { * - allow more then 8 depths of directory trees; * - disable a version number to a File Name; * - disable a forced period to the tail of a File Name; - * - the maxinum length of files and directories is raised to 193. + * - the maximum length of files and directories is raised to 193. * if rockridge option is disabled, raised to 207. */ unsigned int iso_level:3; @@ -626,7 +626,7 @@ struct iso_option { * : NOTE Our rockridge=useful option does not set a zero * : to uid and gid, you should use application * : option such as --gid,--gname,--uid and --uname - * : badtar options instead. + * : bsdtar options instead. * Type : boolean/string * Default: Enabled as rockridge=useful * COMPAT : mkisofs -r / -R @@ -660,7 +660,7 @@ struct iso_option { * : for making zisofs. * : When the file size is less than one Logical Block * : size, that file will not zisofs'ed since it does - * : reduece an ISO-image size. + * : reduce an ISO-image size. * : * : When you specify option 'boot=', that * : 'boot-image' file won't be converted to zisofs file. @@ -680,7 +680,7 @@ struct iso9660 { /* The creation time of ISO image. */ time_t birth_time; /* A file stream of a temporary file, which file contents - * save to until ISO iamge can be created. */ + * save to until ISO image can be created. */ int temp_fd; struct isofile *cur_file; @@ -703,7 +703,7 @@ struct iso9660 { } all_file_list; /* A list of struct isofile entries which have its - * contents and are not a directory, a hardlined file + * contents and are not a directory, a hardlinked file * and a symlink file. */ struct { struct isofile *first; @@ -1907,9 +1907,9 @@ iso9660_close(struct archive_write *a) iso9660->primary.rootent); if (ret < 0) return (ret); - /* Make sure we have UTF-16BE convertors. - * if there is no file entry, convertors are still - * uninitilized. */ + /* Make sure we have UTF-16BE converters. + * if there is no file entry, converters are still + * uninitialized. */ if (iso9660->sconv_to_utf16be == NULL) { iso9660->sconv_to_utf16be = archive_string_conversion_to_charset( @@ -1995,7 +1995,7 @@ iso9660_close(struct archive_write *a) * Write an ISO 9660 image. */ - /* Switc to start using wbuff as file buffer. */ + /* Switch to start using wbuff as file buffer. */ iso9660->wbuff_remaining = wb_buffmax(); iso9660->wbuff_type = WB_TO_STREAM; iso9660->wbuff_offset = 0; @@ -2524,7 +2524,8 @@ get_tmfromtime(struct tm *tm, time_t *t) tzset(); localtime_r(t, tm); #elif HAVE__LOCALTIME64_S - _localtime64_s(tm, t); + __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits + _localtime64_s(tm, &tmp_t); #else memcpy(tm, localtime(t), sizeof(*tm)); #endif @@ -2553,7 +2554,7 @@ set_date_time(unsigned char *p, time_t t) static void set_date_time_null(unsigned char *p) { - memset(p, '0', 16); + memset(p, (int)'0', 16); p[16] = 0; } @@ -2959,7 +2960,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len, gid = archive_entry_gid(file->entry); if (iso9660->opt.rr == OPT_RR_USEFUL) { /* - * This action is simular mkisofs -r option + * This action is similar to mkisofs -r option * but our rockridge=useful option does not * set a zero to uid and gid. */ @@ -3024,8 +3025,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len, * +----+----+----+----+----+ * 10 11 12 13 14 15 * - * - cflg : flag of componet - * - clen : length of componet + * - cflg : flag of component + * - clen : length of component */ const char *sl; char sl_last; @@ -3108,7 +3109,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len, /* * flg len * +----+----+ - * | 02 | 00 | CURREENT component. + * | 02 | 00 | CURRENT component. * +----+----+ (".") */ if (nc != NULL) { @@ -3947,7 +3948,7 @@ write_VD(struct archive_write *a, struct vdd *vdd) "Abstract File", 0, D_CHAR); if (r != ARCHIVE_OK) return (r); - /* Bibliongraphic File Identifier */ + /* Bibliographic File Identifier */ r = set_file_identifier(bp, 777, 813, vdc, a, vdd, &(iso9660->bibliographic_file_identifier), "Bibliongraphic File", 0, D_CHAR); @@ -4073,7 +4074,10 @@ write_information_block(struct archive_write *a) memset(info.s, 0, info_size); opt = 0; #if defined(HAVE__CTIME64_S) - _ctime64_s(buf, sizeof(buf), &(iso9660->birth_time)); + { + __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits + _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + } #elif defined(HAVE_CTIME_R) ctime_r(&(iso9660->birth_time), buf); #else @@ -4558,7 +4562,7 @@ write_file_descriptors(struct archive_write *a) file->cur_content = &(file->content); do { blocks += file->cur_content->blocks; - /* Next fragument */ + /* Next fragment */ file->cur_content = file->cur_content->next; } while (file->cur_content != NULL); } @@ -4748,7 +4752,7 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file) } /* - * Converte a filename to UTF-16BE. + * Convert a filename to UTF-16BE. */ if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len, iso9660->sconv_to_utf16be)) { @@ -5512,7 +5516,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) file->cur_content->location = location; location += file->cur_content->blocks; total_block += file->cur_content->blocks; - /* Next fragument */ + /* Next fragment */ file->cur_content = file->cur_content->next; } while (file->cur_content != NULL); } @@ -6135,7 +6139,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, off = ffmax - extlen; if (off == 0) { /* A dot('.') character - * does't place to the first + * doesn't place to the first * byte of identifier. */ off ++; extlen --; @@ -6164,7 +6168,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, np->id_len = l = ext_off + np->ext_len; /* Make an offset of the number which is used to be set - * hexadecimal number to avoid duplicate identififier. */ + * hexadecimal number to avoid duplicate identifier. */ if (iso9660->opt.iso_level == 1) { if (ext_off >= 5) noff = 5; @@ -6742,7 +6746,7 @@ isoent_rr_move(struct archive_write *a) int r; pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]); - /* Theare aren't level 8 directories reaching a deepr level. */ + /* There aren't level 8 directories reaching a deeper level. */ if (pt->cnt == 0) return (ARCHIVE_OK); @@ -6813,7 +6817,7 @@ _compare_path_table(const void *v1, const void *v2) if (cmp != 0) return (cmp); - /* Compare indetifier */ + /* Compare identifier */ s1 = p1->identifier; s2 = p2->identifier; l = p1->ext_off; @@ -6855,7 +6859,7 @@ _compare_path_table_joliet(const void *v1, const void *v2) if (cmp != 0) return (cmp); - /* Compare indetifier */ + /* Compare identifier */ s1 = (const unsigned char *)p1->identifier; s2 = (const unsigned char *)p2->identifier; l = p1->ext_off; @@ -7149,7 +7153,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent) iso9660->el_torito.catalog = isoent; /* - * Get a boot medai type. + * Get a boot media type. */ switch (iso9660->opt.boot_type) { default: diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c index b686303d9..493d47356 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c @@ -1840,9 +1840,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, len = strlen(p); /* - * Add "./" prefiex. + * Add "./" prefix. * NOTE: If the pathname does not have a path separator, we have - * to add "./" to the head of the pathename because mtree reader + * to add "./" to the head of the pathname because mtree reader * will suppose that it is v1(a.k.a classic) mtree format and * change the directory unexpectedly and so it will make a wrong * path. diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c index 6f7fe7839..6a301ac2d 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,15 +62,24 @@ struct pax { struct sparse_block *sparse_tail; struct archive_string_conv *sconv_utf8; int opt_binary; + + unsigned flags; +#define WRITE_SCHILY_XATTR (1 << 0) +#define WRITE_LIBARCHIVE_XATTR (1 << 1) }; static void add_pax_attr(struct archive_string *, const char *key, const char *value); +static void add_pax_attr_binary(struct archive_string *, + const char *key, + const char *value, size_t value_len); static void add_pax_attr_int(struct archive_string *, const char *key, int64_t value); static void add_pax_attr_time(struct archive_string *, const char *key, int64_t sec, unsigned long nanos); +static int add_pax_acl(struct archive_write *, + struct archive_entry *, struct pax *, int); static ssize_t archive_write_pax_data(struct archive_write *, const void *, size_t); static int archive_write_pax_close(struct archive_write *); @@ -127,13 +137,14 @@ archive_write_set_format_pax(struct archive *_a) if (a->format_free != NULL) (a->format_free)(a); - pax = (struct pax *)malloc(sizeof(*pax)); + pax = (struct pax *)calloc(1, sizeof(*pax)); if (pax == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate pax data"); return (ARCHIVE_FATAL); } - memset(pax, 0, sizeof(*pax)); + pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR; + a->format_data = pax; a->format_name = "pax"; a->format_options = archive_write_pax_options; @@ -272,6 +283,17 @@ add_pax_attr_int(struct archive_string *as, const char *key, int64_t value) */ static void add_pax_attr(struct archive_string *as, const char *key, const char *value) +{ + add_pax_attr_binary(as, key, value, strlen(value)); +} + +/* + * Add a key/value attribute to the pax header. This function handles + * binary values. + */ +static void +add_pax_attr_binary(struct archive_string *as, const char *key, + const char *value, size_t value_len) { int digits, i, len, next_ten; char tmp[1 + 3 * sizeof(int)]; /* < 3 base-10 digits per byte */ @@ -280,7 +302,7 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value) * PAX attributes have the following layout: * <=> */ - len = 1 + (int)strlen(key) + 1 + (int)strlen(value) + 1; + len = 1 + (int)strlen(key) + 1 + (int)value_len + 1; /* * The field includes the length of the field, so @@ -311,21 +333,47 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value) archive_strappend_char(as, ' '); archive_strcat(as, key); archive_strappend_char(as, '='); - archive_strcat(as, value); + archive_array_append(as, value, value_len); archive_strappend_char(as, '\n'); } +static void +archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name, + const void *value, size_t value_len) +{ + struct archive_string s; + char *encoded_value; + + if (pax->flags & WRITE_LIBARCHIVE_XATTR) { + encoded_value = base64_encode((const char *)value, value_len); + + if (encoded_name != NULL && encoded_value != NULL) { + archive_string_init(&s); + archive_strcpy(&s, "LIBARCHIVE.xattr."); + archive_strcat(&s, encoded_name); + add_pax_attr(&(pax->pax_header), s.s, encoded_value); + archive_string_free(&s); + } + free(encoded_value); + } + if (pax->flags & WRITE_SCHILY_XATTR) { + archive_string_init(&s); + archive_strcpy(&s, "SCHILY.xattr."); + archive_strcat(&s, encoded_name); + add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len); + archive_string_free(&s); + } +} + static int archive_write_pax_header_xattrs(struct archive_write *a, struct pax *pax, struct archive_entry *entry) { - struct archive_string s; int i = archive_entry_xattr_reset(entry); while (i--) { const char *name; const void *value; - char *encoded_value; char *url_encoded_name = NULL, *encoded_name = NULL; size_t size; int r; @@ -346,16 +394,9 @@ archive_write_pax_header_xattrs(struct archive_write *a, } } - encoded_value = base64_encode((const char *)value, size); + archive_write_pax_header_xattr(pax, encoded_name, + value, size); - if (encoded_name != NULL && encoded_value != NULL) { - archive_string_init(&s); - archive_strcpy(&s, "LIBARCHIVE.xattr."); - archive_strcat(&s, encoded_name); - add_pax_attr(&(pax->pax_header), s.s, encoded_value); - archive_string_free(&s); - } - free(encoded_value); } return (ARCHIVE_OK); } @@ -450,6 +491,45 @@ get_entry_symlink(struct archive_write *a, struct archive_entry *entry, return (ARCHIVE_OK); } +/* Add ACL to pax header */ +static int +add_pax_acl(struct archive_write *a, + struct archive_entry *entry, struct pax *pax, int flags) +{ + char *p; + const char *attr; + int acl_types; + + acl_types = archive_entry_acl_types(entry); + + if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) + attr = "SCHILY.acl.ace"; + else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + attr = "SCHILY.acl.access"; + else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + attr = "SCHILY.acl.default"; + else + return (ARCHIVE_FATAL); + + p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8); + if (p == NULL) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, "%s %s", + "Can't allocate memory for ", attr); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s", + "Can't translate ", attr, " to UTF-8"); + return(ARCHIVE_WARN); + } else if (*p != '\0') { + add_pax_attr(&(pax->pax_header), + attr, p); + free(p); + } + return(ARCHIVE_OK); +} + /* * TODO: Consider adding 'comment' and 'charset' fields to * archive_entry so that clients can specify them. Also, consider @@ -466,6 +546,7 @@ archive_write_pax_header(struct archive_write *a, const char *p; const char *suffix; int need_extension, r, ret; + int acl_types; int sparse_count; uint64_t sparse_total, real_size; struct pax *pax; @@ -709,7 +790,7 @@ archive_write_pax_header(struct archive_write *a, /* Copy entry so we can modify it as needed. */ #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry_original); if (entry_main == entry_original) @@ -1017,16 +1098,6 @@ archive_write_pax_header(struct archive_write *a, if (!need_extension && p != NULL && *p != '\0') need_extension = 1; - /* If there are non-trivial ACL entries, we need an extension. */ - if (!need_extension && archive_entry_acl_count(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0) - need_extension = 1; - - /* If there are non-trivial ACL entries, we need an extension. */ - if (!need_extension && archive_entry_acl_count(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0) - need_extension = 1; - /* If there are extended attributes, we need an extension */ if (!need_extension && archive_entry_xattr_count(entry_original) > 0) need_extension = 1; @@ -1035,6 +1106,12 @@ archive_write_pax_header(struct archive_write *a, if (!need_extension && sparse_count > 0) need_extension = 1; + acl_types = archive_entry_acl_types(entry_original); + + /* If there are any ACL entries, we need an extension */ + if (!need_extension && acl_types != 0) + need_extension = 1; + /* * Libarchive used to include these in extended headers for * restricted pax format, but that confused people who @@ -1086,43 +1163,29 @@ archive_write_pax_header(struct archive_write *a, add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p); /* I use star-compatible ACL attributes. */ - r = archive_entry_acl_text_l(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS | - ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, - &p, NULL, pax->sconv_utf8); - if (r != 0) { - if (errno == ENOMEM) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "ACL.access"); + if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT); + if (ret == ARCHIVE_FATAL) return (ARCHIVE_FATAL); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate ACL.access to UTF-8"); - ret = ARCHIVE_WARN; - } else if (p != NULL && *p != '\0') { - add_pax_attr(&(pax->pax_header), - "SCHILY.acl.access", p); } - r = archive_entry_acl_text_l(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | - ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, - &p, NULL, pax->sconv_utf8); - if (r != 0) { - if (errno == ENOMEM) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "ACL.default"); + if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA); + if (ret == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + } + if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA); + if (ret == ARCHIVE_FATAL) return (ARCHIVE_FATAL); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate ACL.default to UTF-8"); - ret = ARCHIVE_WARN; - } else if (p != NULL && *p != '\0') { - add_pax_attr(&(pax->pax_header), - "SCHILY.acl.default", p); } /* We use GNU-tar-compatible sparse attributes. */ diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c index c033fb32f..5be310a07 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c @@ -113,12 +113,11 @@ archive_write_set_format_shar(struct archive *_a) if (a->format_free != NULL) (a->format_free)(a); - shar = (struct shar *)malloc(sizeof(*shar)); + shar = (struct shar *)calloc(1, sizeof(*shar)); if (shar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data"); return (ARCHIVE_FATAL); } - memset(shar, 0, sizeof(*shar)); archive_string_init(&shar->work); archive_string_init(&shar->quoted_name); a->format_data = shar; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c index 484ab34b2..c54aeabdb 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c @@ -114,9 +114,9 @@ static const char template_header[] = { '0','0','0','0','0','0', ' ','\0', /* gid, space-null termination: 8 bytes */ '0','0','0','0','0','0', ' ','\0', - /* size, space termation: 12 bytes */ + /* size, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', - /* mtime, space termation: 12 bytes */ + /* mtime, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', /* Initial checksum value: 8 spaces */ ' ',' ',' ',' ',' ',' ',' ',' ', @@ -184,13 +184,12 @@ archive_write_set_format_ustar(struct archive *_a) return (ARCHIVE_FATAL); } - ustar = (struct ustar *)malloc(sizeof(*ustar)); + ustar = (struct ustar *)calloc(1, sizeof(*ustar)); if (ustar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data"); return (ARCHIVE_FATAL); } - memset(ustar, 0, sizeof(*ustar)); a->format_data = ustar; a->format_name = "ustar"; a->format_options = archive_write_ustar_options; @@ -307,7 +306,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) * case getting WCS failed. On POSIX, this is a * normal operation. */ - if (p != NULL && p[strlen(p) - 1] != '/') { + if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { struct archive_string as; archive_string_init(&as); @@ -336,7 +335,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) } #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c index 17efbaf75..62b152294 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c @@ -98,9 +98,9 @@ static const char template_header[] = { '0','0','0','0','0','0', ' ','\0', /* gid, space-null termination: 8 bytes */ '0','0','0','0','0','0', ' ','\0', - /* size, space termation: 12 bytes */ + /* size, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', - /* mtime, space termation: 12 bytes */ + /* mtime, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', /* Initial checksum value: 8 spaces */ ' ',' ',' ',' ',' ',' ',' ',' ', @@ -161,13 +161,12 @@ archive_write_set_format_v7tar(struct archive *_a) return (ARCHIVE_FATAL); } - v7tar = (struct v7tar *)malloc(sizeof(*v7tar)); + v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar)); if (v7tar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate v7tar data"); return (ARCHIVE_FATAL); } - memset(v7tar, 0, sizeof(*v7tar)); a->format_data = v7tar; a->format_name = "tar (non-POSIX)"; a->format_options = archive_write_v7tar_options; @@ -314,7 +313,7 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) } #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c index ea66929a9..8b6daf942 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c @@ -79,7 +79,7 @@ typedef enum { WT_RVIS, /* conversion, unsupported */ WT_CONV, - /* continutation, unsupported at the moment */ + /* continuation, unsupported at the moment */ WT_CONT, /* invalid type */ LAST_WT diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c index 58ad9e0ea..3c617ecd9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c @@ -63,7 +63,7 @@ __FBSDID("$FreeBSD$"); * - When writing an XML element , * which is a file type a symbolic link is referencing is always marked * as "broken". Xar utility uses stat(2) to get the file type, but, in - * libarcive format writer, we should not use it; if it is needed, we + * libarchive format writer, we should not use it; if it is needed, we * should get about it at archive_read_disk.c. * - It is possible to appear both and elements. * Xar utility generates on BSD platform and on Linux @@ -192,7 +192,7 @@ struct file { struct file *parent; /* parent directory entry */ /* * To manage sub directory files. - * We use 'chnext' a menber of struct file to chain. + * We use 'chnext' (a member of struct file) to chain. */ struct { struct file *first; @@ -258,7 +258,7 @@ struct xar { /* * The list of all file entries is used to manage struct file * objects. - * We use 'next' a menber of struct file to chain. + * We use 'next' (a member of struct file) to chain. */ struct { struct file *first; @@ -266,7 +266,7 @@ struct xar { } file_list; /* * The list of hard-linked file entries. - * We use 'hlnext' a menber of struct file to chain. + * We use 'hlnext' (a member of struct file) to chain. */ struct archive_rb_tree hardlink_rbtree; }; @@ -1227,7 +1227,7 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer, case AE_IFLNK: /* * xar utility has checked a file type, which - * a symblic-link file has referenced. + * a symbolic-link file has referenced. * For example: * ../ref/ * The symlink target file is "../ref/" and its @@ -1237,8 +1237,8 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer, * The symlink target file is "../f" and its * file type is a regular file. * - * But our implemention cannot do it, and then we - * always record that a attribute "type" is "borken", + * But our implementation cannot do it, and then we + * always record that a attribute "type" is "broken", * for example: * foo/bar * It means "foo/bar" is not reachable. @@ -1544,7 +1544,7 @@ make_toc(struct archive_write *a) } /* - * Start recoding TOC + * Start recording TOC */ r = xmlTextWriterStartElement(writer, BAD_CAST("xar")); if (r < 0) { @@ -1961,6 +1961,7 @@ file_free(struct file *file) archive_string_free(&(file->basename)); archive_string_free(&(file->symlink)); archive_string_free(&(file->script)); + archive_entry_free(file->entry); free(file); } @@ -2484,7 +2485,7 @@ file_connect_hardlink_files(struct xar *xar) archive_entry_set_nlink(target->entry, hl->nlink); if (hl->nlink > 1) /* It means this file is a hardlink - * targe itself. */ + * target itself. */ target->hardlink_target = target; for (nf = target->hlnext; nf != NULL; nf = nf->hlnext) { @@ -2913,7 +2914,7 @@ compression_init_encoder_xz(struct archive *a, *strm = lzma_init_data; #ifdef HAVE_LZMA_STREAM_ENCODER_MT if (threads > 1) { - bzero(&mt_options, sizeof(mt_options)); + memset(&mt_options, 0, sizeof(mt_options)); mt_options.threads = threads; mt_options.timeout = 300; mt_options.filters = lzmafilters; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c index 0b2c69b93..a4ae229b2 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c @@ -592,7 +592,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ zip->entry = __la_win_entry_in_posix_pathseparator(entry); if (zip->entry == entry) @@ -878,7 +878,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) { memcpy(e, "\001\231\007\000\001\000AE", 8); - /* AES vendoer version AE-2 does not store a CRC. + /* AES vendor version AE-2 does not store a CRC. * WinZip 11 uses AE-1, which does store the CRC, * but it does not store the CRC when the file size * is less than 20 bytes. So we simulate what @@ -1013,7 +1013,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { switch (zip->entry_encryption) { case ENCRYPTION_TRADITIONAL: - /* Initialize traditoinal PKWARE encryption context. */ + /* Initialize traditional PKWARE encryption context. */ if (!zip->tctx_valid) { ret = init_traditional_pkware_encryption(a); if (ret != ARCHIVE_OK) @@ -1499,7 +1499,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) } static uint8_t -trad_enc_decypt_byte(struct trad_enc_ctx *ctx) +trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) { unsigned temp = ctx->keys[2] | 2; return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; @@ -1515,7 +1515,7 @@ trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, for (i = 0; i < max; i++) { uint8_t t = in[i]; - out[i] = t ^ trad_enc_decypt_byte(ctx); + out[i] = t ^ trad_enc_decrypt_byte(ctx); trad_enc_update_keys(ctx, t); } return i; @@ -1626,7 +1626,7 @@ init_winzip_aes_encryption(struct archive_write *a) return (ARCHIVE_FAILED); } - /* Set a passowrd verification value after the 'salt'. */ + /* Set a password verification value after the 'salt'. */ salt[salt_len] = derived_key[key_len * 2]; salt[salt_len + 1] = derived_key[key_len * 2 + 1]; diff --git a/Utilities/cmlibarchive/libarchive/config_freebsd.h b/Utilities/cmlibarchive/libarchive/config_freebsd.h index 207343163..215e886be 100644 --- a/Utilities/cmlibarchive/libarchive/config_freebsd.h +++ b/Utilities/cmlibarchive/libarchive/config_freebsd.h @@ -28,6 +28,7 @@ /* FreeBSD 5.0 and later have ACL and extattr support. */ #if __FreeBSD__ > 4 #define HAVE_ACL_CREATE_ENTRY 1 +#define HAVE_ACL_GET_FD_NP 1 #define HAVE_ACL_GET_LINK_NP 1 #define HAVE_ACL_GET_PERM_NP 1 #define HAVE_ACL_INIT 1 @@ -39,6 +40,7 @@ #define HAVE_EXTATTR_LIST_FILE 1 #define HAVE_EXTATTR_SET_FD 1 #define HAVE_EXTATTR_SET_FILE 1 +#define HAVE_STRUCT_XVFSCONF 1 #define HAVE_SYS_ACL_H 1 #define HAVE_SYS_EXTATTR_H 1 #endif diff --git a/Utilities/cmlibarchive/libarchive/libarchive-formats.5 b/Utilities/cmlibarchive/libarchive/libarchive-formats.5 index 9cec76005..62359ddc2 100644 --- a/Utilities/cmlibarchive/libarchive/libarchive-formats.5 +++ b/Utilities/cmlibarchive/libarchive/libarchive-formats.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 18, 2012 +.Dd December 27, 2016 .Dt LIBARCHIVE-FORMATS 5 .Os .Sh NAME @@ -191,8 +191,6 @@ and device numbers. .It Solaris extensions Libarchive recognizes ACL and extended attribute records written by Solaris tar. -Currently, libarchive only has support for old-style ACLs; the -newer NFSv4 ACLs are recognized but discarded. .El .Pp The first tar program appeared in Seventh Edition Unix in 1979. diff --git a/Utilities/cmlibarchive/libarchive/tar.5 b/Utilities/cmlibarchive/libarchive/tar.5 index 6e6f0c096..30b837dc4 100644 --- a/Utilities/cmlibarchive/libarchive/tar.5 +++ b/Utilities/cmlibarchive/libarchive/tar.5 @@ -1,4 +1,5 @@ .\" Copyright (c) 2003-2009 Tim Kientzle +.\" Copyright (c) 2016 Martin Matuska .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 23, 2011 +.Dd December 27, 2016 .Dt TAR 5 .Os .Sh NAME @@ -440,11 +441,11 @@ archives to store files much larger than the historic 8GB limit. Vendor-specific attributes used by Joerg Schilling's .Nm star implementation. -.It Cm SCHILY.acl.access , Cm SCHILY.acl.default -Stores the access and default ACLs as textual strings in a format +.It Cm SCHILY.acl.access , Cm SCHILY.acl.default, Cm SCHILY.acl.ace +Stores the access, default and NFSv4 ACLs as textual strings in a format that is an extension of the format specified by POSIX.1e draft 17. -In particular, each user or group access specification can include a fourth -colon-separated field with the numeric UID or GID. +In particular, each user or group access specification can include +an additional colon-separated field with the numeric UID or GID. This allows ACLs to be restored on systems that may not have complete user or group information available (such as when NIS/YP or LDAP services are temporarily unavailable). diff --git a/Utilities/cmlibarchive/libarchive/xxhash.c b/Utilities/cmlibarchive/libarchive/xxhash.c index 262fecb30..6f5ba52fa 100644 --- a/Utilities/cmlibarchive/libarchive/xxhash.c +++ b/Utilities/cmlibarchive/libarchive/xxhash.c @@ -29,13 +29,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - xxHash source repository : http://code.google.com/p/xxhash/ */ - #include "archive_platform.h" -#include "archive_xxhash.h" #include #include +#include "archive_xxhash.h" + #ifdef HAVE_LIBLZ4 /*************************************** @@ -61,7 +61,7 @@ You can contact the author at : ** By default, xxHash library provides endian-independent Hash values, based on little-endian convention. ** Results are therefore identical for little-endian and big-endian CPU. ** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. -** Should endian-independance be of no importance for your application, you may set the #define below to 1. +** Should endian-independence be of no importance for your application, you may set the #define below to 1. ** It will improve speed for Big-endian CPU. ** This option has no impact on Little_Endian CPU. */ diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt index e80668002..bb3b8a71f 100644 --- a/Utilities/cmliblzma/CMakeLists.txt +++ b/Utilities/cmliblzma/CMakeLists.txt @@ -15,11 +15,11 @@ CHECK_C_SOURCE_COMPILES( HAVE___RESTRICT) CHECK_C_SOURCE_COMPILES( - "inline int test (void) {return 0;}\nint main (void) {return test();}" + "static inline int test (void) {return 0;}\nint main (void) {return test();}" HAVE_INLINE) CHECK_C_SOURCE_COMPILES ( - "__inline int test (void) {return 0;}\nint main (void) {return test();}" + "static __inline int test (void) {return 0;}\nint main (void) {return test();}" HAVE___INLINE) CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H) diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index a8e25bae7..4c8e2289d 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -133,6 +133,27 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX") ) endif() +if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") + list(APPEND uv_libraries + ) + list(APPEND uv_headers + include/uv-posix.h + ) + list(APPEND uv_defines + ) + list(APPEND uv_sources + src/unix/cygwin.c + src/unix/bsd-ifaddrs.c + src/unix/no-fsevents.c + src/unix/no-proctitle.c + src/unix/posix-hrtime.c + src/unix/posix-poll.c + src/unix/procfs-exepath.c + src/unix/sysinfo-loadavg.c + src/unix/sysinfo-memory.c + ) +endif() + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") list(APPEND uv_headers include/uv-darwin.h @@ -143,6 +164,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") _DARWIN_UNLIMITED_SELECT=1 ) list(APPEND uv_sources + src/unix/bsd-ifaddrs.c src/unix/darwin.c src/unix/darwin-proctitle.c src/unix/fsevents.c @@ -163,7 +185,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") src/unix/linux-inotify.c src/unix/linux-syscalls.c src/unix/linux-syscalls.h + src/unix/procfs-exepath.c src/unix/proctitle.c + src/unix/sysinfo-loadavg.c + src/unix/sysinfo-memory.c ) endif() @@ -175,8 +200,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") include/uv-bsd.h ) list(APPEND uv_sources + src/unix/bsd-ifaddrs.c src/unix/freebsd.c src/unix/kqueue.c + src/unix/posix-hrtime.c ) endif() @@ -188,8 +215,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") include/uv-bsd.h ) list(APPEND uv_sources + src/unix/bsd-ifaddrs.c src/unix/netbsd.c src/unix/kqueue.c + src/unix/posix-hrtime.c ) endif() @@ -201,8 +230,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") include/uv-bsd.h ) list(APPEND uv_sources + src/unix/bsd-ifaddrs.c src/unix/openbsd.c src/unix/kqueue.c + src/unix/posix-hrtime.c ) endif() @@ -212,6 +243,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") nsl sendfile socket + rt ) list(APPEND uv_headers include/uv-sunos.h @@ -220,15 +252,28 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") __EXTENSIONS__ ) if(CMAKE_SYSTEM_VERSION STREQUAL "5.10") + set(CMAKE_C_STANDARD 90) + if(CMAKE_VERSION VERSION_LESS 3.8.20170504 AND CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.14) + # The running version of CMake does not know how to add this flag. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c90") + endif() list(APPEND uv_defines _XOPEN_SOURCE=500 ) else() + if(NOT CMAKE_C_STANDARD OR CMAKE_C_STANDARD EQUAL 90) + set(CMAKE_C_STANDARD 11) + endif() + if(CMAKE_VERSION VERSION_LESS 3.8.20170505 AND CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.14) + # The running version of CMake does not know how to add this flag. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -xc99") + endif() list(APPEND uv_defines _XOPEN_SOURCE=600 ) endif() list(APPEND uv_sources + src/unix/no-proctitle.c src/unix/sunos.c ) endif() diff --git a/Utilities/cmlibuv/include/pthread-barrier.h b/Utilities/cmlibuv/include/pthread-barrier.h index 3e01705d9..900ebedd3 100644 --- a/Utilities/cmlibuv/include/pthread-barrier.h +++ b/Utilities/cmlibuv/include/pthread-barrier.h @@ -18,7 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define _UV_PTHREAD_BARRIER_ #include #include +#if !defined(__MVS__) #include /* sem_t */ +#endif #define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 diff --git a/Utilities/cmlibuv/include/uv-os390.h b/Utilities/cmlibuv/include/uv-os390.h index b0b068f44..58f926111 100644 --- a/Utilities/cmlibuv/include/uv-os390.h +++ b/Utilities/cmlibuv/include/uv-os390.h @@ -24,4 +24,7 @@ #define UV_PLATFORM_SEM_T int +#define UV_PLATFORM_LOOP_FIELDS \ + void* ep; \ + #endif /* UV_MVS_H */ diff --git a/Utilities/cmlibuv/include/uv-posix.h b/Utilities/cmlibuv/include/uv-posix.h new file mode 100644 index 000000000..9a96634db --- /dev/null +++ b/Utilities/cmlibuv/include/uv-posix.h @@ -0,0 +1,31 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_POSIX_H +#define UV_POSIX_H + +#define UV_PLATFORM_LOOP_FIELDS \ + struct pollfd* poll_fds; \ + size_t poll_fds_used; \ + size_t poll_fds_size; \ + unsigned char poll_fds_iterating; \ + +#endif /* UV_POSIX_H */ diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv-unix.h index bca271447..d7754509b 100644 --- a/Utilities/cmlibuv/include/uv-unix.h +++ b/Utilities/cmlibuv/include/uv-unix.h @@ -36,7 +36,9 @@ #include #include +#if !defined(__MVS__) #include +#endif #include #include @@ -44,6 +46,8 @@ #if defined(__linux__) # include "uv-linux.h" +#elif defined (__MVS__) +# include "uv-os390.h" #elif defined(_AIX) # include "uv-aix.h" #elif defined(__sun) @@ -56,6 +60,8 @@ defined(__OpenBSD__) || \ defined(__NetBSD__) # include "uv-bsd.h" +#elif defined(__CYGWIN__) || defined(__MSYS__) +# include "uv-posix.h" #endif #ifndef PTHREAD_BARRIER_SERIAL_THREAD @@ -75,7 +81,6 @@ #endif struct uv__io_s; -struct uv__async; struct uv_loop_s; typedef void (*uv__io_cb)(struct uv_loop_s* loop, @@ -93,16 +98,6 @@ struct uv__io_s { UV_IO_PRIVATE_PLATFORM_FIELDS }; -typedef void (*uv__async_cb)(struct uv_loop_s* loop, - struct uv__async* w, - unsigned int nevents); - -struct uv__async { - uv__async_cb cb; - uv__io_t io_watcher; - int wfd; -}; - #ifndef UV_PLATFORM_SEM_T # define UV_PLATFORM_SEM_T sem_t #endif @@ -212,7 +207,9 @@ typedef struct { void* check_handles[2]; \ void* idle_handles[2]; \ void* async_handles[2]; \ - struct uv__async async_watcher; \ + void (*async_unused)(void); /* TODO(bnoordhuis) Remove in libuv v2. */ \ + uv__io_t async_io_watcher; \ + int async_wfd; \ struct { \ void* min; \ unsigned int nelts; \ diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv-version.h index 3cb9b5fdd..e16580903 100644 --- a/Utilities/cmlibuv/include/uv-version.h +++ b/Utilities/cmlibuv/include/uv-version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 9 -#define UV_VERSION_PATCH 2 +#define UV_VERSION_MINOR 11 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 0 #define UV_VERSION_SUFFIX "dev" diff --git a/Utilities/cmlibuv/include/uv-win.h b/Utilities/cmlibuv/include/uv-win.h index 89ee09a53..d3e32a508 100644 --- a/Utilities/cmlibuv/include/uv-win.h +++ b/Utilities/cmlibuv/include/uv-win.h @@ -49,6 +49,7 @@ typedef struct pollfd { #include #include +#include #include #if defined(_MSC_VER) && _MSC_VER < 1600 diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h index e3e20dc19..38f567644 100644 --- a/Utilities/cmlibuv/include/uv.h +++ b/Utilities/cmlibuv/include/uv.h @@ -278,6 +278,7 @@ UV_EXTERN void uv_loop_delete(uv_loop_t*); UV_EXTERN size_t uv_loop_size(void); UV_EXTERN int uv_loop_alive(const uv_loop_t* loop); UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...); +UV_EXTERN int uv_loop_fork(uv_loop_t* loop); UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode); UV_EXTERN void uv_stop(uv_loop_t*); @@ -367,6 +368,8 @@ typedef enum { } uv_membership; +UV_EXTERN int uv_translate_sys_error(int sys_errno); + UV_EXTERN const char* uv_strerror(int err); UV_EXTERN const char* uv_err_name(int err); @@ -1075,6 +1078,12 @@ UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses, UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses, int count); +UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size); +UV_EXTERN int uv_os_setenv(const char* name, const char* value); +UV_EXTERN int uv_os_unsetenv(const char* name); + +UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size); + typedef enum { UV_FS_UNKNOWN = -1, @@ -1326,6 +1335,9 @@ UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle); UV_EXTERN int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum); +UV_EXTERN int uv_signal_start_oneshot(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum); UV_EXTERN int uv_signal_stop(uv_signal_t* handle); UV_EXTERN void uv_loadavg(double avg[3]); diff --git a/Utilities/cmlibuv/src/threadpool.c b/Utilities/cmlibuv/src/threadpool.c index 2c5152b42..108934112 100644 --- a/Utilities/cmlibuv/src/threadpool.c +++ b/Utilities/cmlibuv/src/threadpool.c @@ -23,18 +23,6 @@ #if !defined(_WIN32) # include "unix/internal.h" -#else -# include "win/req-inl.h" -/* TODO(saghul): unify internal req functions */ -static void uv__req_init(uv_loop_t* loop, - uv_req_t* req, - uv_req_type type) { - uv_req_init(loop, req); - req->type = type; - uv__req_register(loop, req); -} -# define uv__req_init(loop, req, type) \ - uv__req_init((loop), (uv_req_t*)(req), (type)) #endif #include @@ -139,7 +127,7 @@ UV_DESTRUCTOR(static void cleanup(void)) { #endif -static void init_once(void) { +static void init_threads(void) { unsigned int i; const char* val; @@ -177,6 +165,27 @@ static void init_once(void) { } +#ifndef _WIN32 +static void reset_once(void) { + uv_once_t child_once = UV_ONCE_INIT; + memcpy(&once, &child_once, sizeof(child_once)); +} +#endif + + +static void init_once(void) { +#ifndef _WIN32 + /* Re-initialize the threadpool after fork. + * Note that this discards the global mutex and condition as well + * as the work queue. + */ + if (pthread_atfork(NULL, NULL, &reset_once)) + abort(); +#endif + init_threads(); +} + + void uv__work_submit(uv_loop_t* loop, struct uv__work* w, void (*work)(struct uv__work* w), diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c index 652cd980f..388c9cca9 100644 --- a/Utilities/cmlibuv/src/unix/aix.c +++ b/Utilities/cmlibuv/src/unix/aix.c @@ -64,6 +64,11 @@ #define RDWR_BUF_SIZE 4096 #define EQ(a,b) (strcmp(a,b) == 0) +static void* args_mem = NULL; +static char** process_argv = NULL; +static int process_argc = 0; +static char* process_title_ptr = NULL; + int uv__platform_loop_init(uv_loop_t* loop) { loop->fs_fd = -1; @@ -91,6 +96,13 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } +int uv__io_fork(uv_loop_t* loop) { + uv__platform_loop_delete(loop); + + return uv__platform_loop_init(loop); +} + + int uv__io_check_fd(uv_loop_t* loop, int fd) { struct poll_ctl pc; @@ -753,6 +765,13 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); + /* In file / directory move cases, AIX Event infrastructure + * produces a second event with no data. + * Ignore it and return gracefully. + */ + if(bytes == 0) + return; + /* Parse the data */ if(bytes > 0) rc = uv__parse_data(result_data, &events, handle); @@ -881,24 +900,94 @@ void uv__fs_event_close(uv_fs_event_t* handle) { char** uv_setup_args(int argc, char** argv) { - return argv; + char** new_argv; + size_t size; + char* s; + int i; + + if (argc <= 0) + return argv; + + /* Save the original pointer to argv. + * AIX uses argv to read the process name. + * (Not the memory pointed to by argv[0..n] as on Linux.) + */ + process_argv = argv; + process_argc = argc; + + /* Calculate how much memory we need for the argv strings. */ + size = 0; + for (i = 0; i < argc; i++) + size += strlen(argv[i]) + 1; + + /* Add space for the argv pointers. */ + size += (argc + 1) * sizeof(char*); + + new_argv = uv__malloc(size); + if (new_argv == NULL) + return argv; + args_mem = new_argv; + + /* Copy over the strings and set up the pointer table. */ + s = (char*) &new_argv[argc + 1]; + for (i = 0; i < argc; i++) { + size = strlen(argv[i]) + 1; + memcpy(s, argv[i], size); + new_argv[i] = s; + s += size; + } + new_argv[i] = NULL; + + return new_argv; } int uv_set_process_title(const char* title) { + char* new_title; + + /* We cannot free this pointer when libuv shuts down, + * the process may still be using it. + */ + new_title = uv__strdup(title); + if (new_title == NULL) + return -ENOMEM; + + /* If this is the first time this is set, + * don't free and set argv[1] to NULL. + */ + if (process_title_ptr != NULL) + uv__free(process_title_ptr); + + process_title_ptr = new_title; + + process_argv[0] = process_title_ptr; + if (process_argc > 1) + process_argv[1] = NULL; + return 0; } int uv_get_process_title(char* buffer, size_t size) { + size_t len; + len = strlen(process_argv[0]); if (buffer == NULL || size == 0) return -EINVAL; + else if (size <= len) + return -ENOBUFS; + + memcpy(buffer, process_argv[0], len + 1); - buffer[0] = '\0'; return 0; } +UV_DESTRUCTOR(static void free_args_mem(void)) { + uv__free(args_mem); /* Keep valgrind happy. */ + args_mem = NULL; +} + + int uv_resident_set_memory(size_t* rss) { char pp[64]; psinfo_t psinfo; diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c index 393cdebd4..45c088ea1 100644 --- a/Utilities/cmlibuv/src/unix/async.c +++ b/Utilities/cmlibuv/src/unix/async.c @@ -33,16 +33,15 @@ #include #include -static void uv__async_event(uv_loop_t* loop, - struct uv__async* w, - unsigned int nevents); +static void uv__async_send(uv_loop_t* loop); +static int uv__async_start(uv_loop_t* loop); static int uv__async_eventfd(void); int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { int err; - err = uv__async_start(loop, &loop->async_watcher, uv__async_event); + err = uv__async_start(loop); if (err) return err; @@ -63,7 +62,7 @@ int uv_async_send(uv_async_t* handle) { return 0; if (cmpxchgi(&handle->pending, 0, 1) == 0) - uv__async_send(&handle->loop->async_watcher); + uv__async_send(handle->loop); return 0; } @@ -75,44 +74,18 @@ void uv__async_close(uv_async_t* handle) { } -static void uv__async_event(uv_loop_t* loop, - struct uv__async* w, - unsigned int nevents) { +static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { + char buf[1024]; + ssize_t r; QUEUE queue; QUEUE* q; uv_async_t* h; - QUEUE_MOVE(&loop->async_handles, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - h = QUEUE_DATA(q, uv_async_t, queue); - - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&loop->async_handles, q); - - if (cmpxchgi(&h->pending, 1, 0) == 0) - continue; - - if (h->async_cb == NULL) - continue; - h->async_cb(h); - } -} - + assert(w == &loop->async_io_watcher); -static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - struct uv__async* wa; - char buf[1024]; - unsigned n; - ssize_t r; - - n = 0; for (;;) { r = read(w->fd, buf, sizeof(buf)); - if (r > 0) - n += r; - if (r == sizeof(buf)) continue; @@ -128,23 +101,26 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { abort(); } - wa = container_of(w, struct uv__async, io_watcher); + QUEUE_MOVE(&loop->async_handles, &queue); + while (!QUEUE_EMPTY(&queue)) { + q = QUEUE_HEAD(&queue); + h = QUEUE_DATA(q, uv_async_t, queue); + + QUEUE_REMOVE(q); + QUEUE_INSERT_TAIL(&loop->async_handles, q); -#if defined(__linux__) - if (wa->wfd == -1) { - uint64_t val; - assert(n == sizeof(val)); - memcpy(&val, buf, sizeof(val)); /* Avoid alignment issues. */ - wa->cb(loop, wa, val); - return; - } -#endif + if (cmpxchgi(&h->pending, 1, 0) == 0) + continue; + + if (h->async_cb == NULL) + continue; - wa->cb(loop, wa, n); + h->async_cb(h); + } } -void uv__async_send(struct uv__async* wa) { +static void uv__async_send(uv_loop_t* loop) { const void* buf; ssize_t len; int fd; @@ -152,14 +128,14 @@ void uv__async_send(struct uv__async* wa) { buf = ""; len = 1; - fd = wa->wfd; + fd = loop->async_wfd; #if defined(__linux__) if (fd == -1) { static const uint64_t val = 1; buf = &val; len = sizeof(val); - fd = wa->io_watcher.fd; /* eventfd */ + fd = loop->async_io_watcher.fd; /* eventfd */ } #endif @@ -178,17 +154,11 @@ void uv__async_send(struct uv__async* wa) { } -void uv__async_init(struct uv__async* wa) { - wa->io_watcher.fd = -1; - wa->wfd = -1; -} - - -int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) { +static int uv__async_start(uv_loop_t* loop) { int pipefd[2]; int err; - if (wa->io_watcher.fd != -1) + if (loop->async_io_watcher.fd != -1) return 0; err = uv__async_eventfd(); @@ -222,32 +192,41 @@ int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) { if (err < 0) return err; - uv__io_init(&wa->io_watcher, uv__async_io, pipefd[0]); - uv__io_start(loop, &wa->io_watcher, POLLIN); - wa->wfd = pipefd[1]; - wa->cb = cb; + uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]); + uv__io_start(loop, &loop->async_io_watcher, POLLIN); + loop->async_wfd = pipefd[1]; return 0; } -void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) { - if (wa->io_watcher.fd == -1) +int uv__async_fork(uv_loop_t* loop) { + if (loop->async_io_watcher.fd == -1) /* never started */ + return 0; + + uv__async_stop(loop); + + return uv__async_start(loop); +} + + +void uv__async_stop(uv_loop_t* loop) { + if (loop->async_io_watcher.fd == -1) return; - if (wa->wfd != -1) { - if (wa->wfd != wa->io_watcher.fd) - uv__close(wa->wfd); - wa->wfd = -1; + if (loop->async_wfd != -1) { + if (loop->async_wfd != loop->async_io_watcher.fd) + uv__close(loop->async_wfd); + loop->async_wfd = -1; } - uv__io_stop(loop, &wa->io_watcher, POLLIN); - uv__close(wa->io_watcher.fd); - wa->io_watcher.fd = -1; + uv__io_stop(loop, &loop->async_io_watcher, POLLIN); + uv__close(loop->async_io_watcher.fd); + loop->async_io_watcher.fd = -1; } -static int uv__async_eventfd() { +static int uv__async_eventfd(void) { #if defined(__linux__) static int no_eventfd2; static int no_eventfd; diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h index 815e35523..9dac2557f 100644 --- a/Utilities/cmlibuv/src/unix/atomic-ops.h +++ b/Utilities/cmlibuv/src/unix/atomic-ops.h @@ -43,8 +43,12 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { __compare_and_swap(ptr, &oldval, newval); return out; #elif defined(__MVS__) - return __plo_CS(ptr, (unsigned int*) ptr, - oldval, (unsigned int*) &newval); + unsigned int op4; + if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, + (unsigned int*) ptr, *ptr, &op4)) + return oldval; + else + return op4; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif @@ -67,13 +71,18 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { # endif /* if defined(__64BIT__) */ return out; #elif defined (__MVS__) -# ifdef _LP64 - return __plo_CSGR(ptr, (unsigned long long*) ptr, - oldval, (unsigned long long*) &newval); -# else - return __plo_CS(ptr, (unsigned int*) ptr, - oldval, (unsigned int*) &newval); -# endif +#ifdef _LP64 + unsigned long long op4; + if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval, + (unsigned long long*) ptr, *ptr, &op4)) +#else + unsigned long op4; + if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, + (unsigned int*) ptr, *ptr, &op4)) +#endif + return oldval; + else + return op4; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c new file mode 100644 index 000000000..414789451 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c @@ -0,0 +1,139 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +#include +#include +#if !defined(__CYGWIN__) && !defined(__MSYS__) +#include +#endif + +static int uv__ifaddr_exclude(struct ifaddrs *ent) { + if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) + return 1; + if (ent->ifa_addr == NULL) + return 1; +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) + /* + * On BSD getifaddrs returns information related to the raw underlying + * devices. We're not interested in this information. + */ + if (ent->ifa_addr->sa_family == AF_LINK) + return 1; +#elif defined(__NetBSD__) || defined(__OpenBSD__) + if (ent->ifa_addr->sa_family != PF_INET) + return 1; +#endif + return 0; +} + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + struct ifaddrs* addrs; + struct ifaddrs* ent; + uv_interface_address_t* address; + int i; + + if (getifaddrs(&addrs) != 0) + return -errno; + + *count = 0; + + /* Count the number of interfaces */ + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent)) + continue; + (*count)++; + } + + *addresses = uv__malloc(*count * sizeof(**addresses)); + + if (*addresses == NULL) { + freeifaddrs(addrs); + return -ENOMEM; + } + + address = *addresses; + + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent)) + continue; + + address->name = uv__strdup(ent->ifa_name); + + if (ent->ifa_addr->sa_family == AF_INET6) { + address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); + } else { + address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); + } + + if (ent->ifa_netmask->sa_family == AF_INET6) { + address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); + } else { + address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); + } + + address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); + + address++; + } + + /* Fill in physical addresses for each interface */ + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent)) + continue; + + address = *addresses; + + for (i = 0; i < *count; i++) { + if (strcmp(address->name, ent->ifa_name) == 0) { +#if defined(__CYGWIN__) || defined(__MSYS__) + memset(address->phys_addr, 0, sizeof(address->phys_addr)); +#else + struct sockaddr_dl* sa_addr; + sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); + memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); +#endif + } + address++; + } + } + + freeifaddrs(addrs); + + return 0; +} + + +void uv_free_interface_addresses(uv_interface_address_t* addresses, + int count) { + int i; + + for (i = 0; i < count; i++) { + uv__free(addresses[i].name); + } + + uv__free(addresses); +} diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c index d88fc1de8..30cdaef7b 100644 --- a/Utilities/cmlibuv/src/unix/core.c +++ b/Utilities/cmlibuv/src/unix/core.c @@ -28,6 +28,7 @@ #include #include #include +#include /* MAXHOSTNAMELEN on Linux and the BSDs */ #include #include #include @@ -42,6 +43,7 @@ #include #ifdef __sun +# include /* MAXHOSTNAMELEN on Solaris */ # include # include # include @@ -80,6 +82,11 @@ #include #endif +/* Fallback for the maximum hostname length */ +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ @@ -98,7 +105,7 @@ uint64_t uv_hrtime(void) { void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); handle->flags |= UV_CLOSING; handle->close_cb = close_cb; @@ -517,6 +524,9 @@ int uv__close_nocheckstdio(int fd) { int uv__close(int fd) { assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ +#if defined(__MVS__) + epoll_file_close(fd); +#endif return uv__close_nocheckstdio(fd); } @@ -535,6 +545,7 @@ int uv__nonblock_ioctl(int fd, int set) { } +#if !defined(__CYGWIN__) && !defined(__MSYS__) int uv__cloexec_ioctl(int fd, int set) { int r; @@ -547,6 +558,7 @@ int uv__cloexec_ioctl(int fd, int set) { return 0; } +#endif int uv__nonblock_fcntl(int fd, int set) { @@ -836,13 +848,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { * every tick of the event loop but the other backends allow us to * short-circuit here if the event mask is unchanged. */ - if (w->events == w->pevents) { - if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) { - QUEUE_REMOVE(&w->watcher_queue); - QUEUE_INIT(&w->watcher_queue); - } + if (w->events == w->pevents) return; - } #endif if (QUEUE_EMPTY(&w->watcher_queue)) @@ -1236,3 +1243,84 @@ void uv_os_free_passwd(uv_passwd_t* pwd) { int uv_os_get_passwd(uv_passwd_t* pwd) { return uv__getpwuid_r(pwd); } + + +int uv_translate_sys_error(int sys_errno) { + /* If < 0 then it's already a libuv error. */ + return sys_errno <= 0 ? sys_errno : -sys_errno; +} + + +int uv_os_getenv(const char* name, char* buffer, size_t* size) { + char* var; + size_t len; + + if (name == NULL || buffer == NULL || size == NULL || *size == 0) + return -EINVAL; + + var = getenv(name); + + if (var == NULL) + return -ENOENT; + + len = strlen(var); + + if (len >= *size) { + *size = len + 1; + return -ENOBUFS; + } + + memcpy(buffer, var, len + 1); + *size = len; + + return 0; +} + + +int uv_os_setenv(const char* name, const char* value) { + if (name == NULL || value == NULL) + return -EINVAL; + + if (setenv(name, value, 1) != 0) + return -errno; + + return 0; +} + + +int uv_os_unsetenv(const char* name) { + if (unsetenv(name) != 0) + return -errno; + + return 0; +} + + +int uv_os_gethostname(char* buffer, size_t* size) { + /* + On some platforms, if the input buffer is not large enough, gethostname() + succeeds, but truncates the result. libuv can detect this and return ENOBUFS + instead by creating a large enough buffer and comparing the hostname length + to the size input. + */ + char buf[MAXHOSTNAMELEN + 1]; + size_t len; + + if (buffer == NULL || size == NULL || *size == 0) + return -EINVAL; + + if (gethostname(buf, sizeof(buf)) != 0) + return -errno; + + buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */ + len = strlen(buf); + + if (len >= *size) { + *size = len + 1; + return -ENOBUFS; + } + + memcpy(buffer, buf, len + 1); + *size = len; + return 0; +} diff --git a/Utilities/cmlibuv/src/unix/cygwin.c b/Utilities/cmlibuv/src/unix/cygwin.c new file mode 100644 index 000000000..5a887dd4c --- /dev/null +++ b/Utilities/cmlibuv/src/unix/cygwin.c @@ -0,0 +1,54 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +int uv_uptime(double* uptime) { + struct sysinfo info; + + if (sysinfo(&info) < 0) + return -errno; + + *uptime = info.uptime; + return 0; +} + +int uv_resident_set_memory(size_t* rss) { + /* FIXME: read /proc/meminfo? */ + *rss = 0; + return UV_ENOSYS; +} + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + /* FIXME: read /proc/stat? */ + *cpu_infos = NULL; + *count = 0; + return UV_ENOSYS; +} + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + (void)cpu_infos; + (void)count; +} diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c index cf95da216..df6dd1c61 100644 --- a/Utilities/cmlibuv/src/unix/darwin.c +++ b/Utilities/cmlibuv/src/unix/darwin.c @@ -25,10 +25,6 @@ #include #include -#include -#include -#include - #include #include #include /* _NSGetExecutablePath */ @@ -233,103 +229,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == AF_LINK)) { - continue; - } - - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On Mac OS X getifaddrs returns information related to Mac Addresses for - * various devices, such as firewire, etc. These are not relevant here. - */ - if (ent->ifa_addr->sa_family == AF_LINK) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c index cba44a3e0..e52ae99db 100644 --- a/Utilities/cmlibuv/src/unix/freebsd.c +++ b/Utilities/cmlibuv/src/unix/freebsd.c @@ -25,10 +25,6 @@ #include #include -#include -#include -#include - #include #include #include @@ -41,9 +37,6 @@ #include /* sysconf */ #include -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - #ifndef CPUSTATES # define CPUSTATES 5U #endif @@ -67,13 +60,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - #ifdef __DragonFly__ int uv_exepath(char* buffer, size_t* size) { char abspath[PATH_MAX * 2 + 1]; @@ -358,103 +344,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == AF_LINK)) { - continue; - } - - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On FreeBSD getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information yet. - */ - if (ent->ifa_addr->sa_family == AF_LINK) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c index 3d478b790..8a4ba7a2f 100644 --- a/Utilities/cmlibuv/src/unix/fs.c +++ b/Utilities/cmlibuv/src/unix/fs.c @@ -129,8 +129,23 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { #if defined(__linux__) || defined(__sun) || defined(__NetBSD__) return fdatasync(req->file); -#elif defined(__APPLE__) && defined(SYS_fdatasync) - return syscall(SYS_fdatasync, req->file); +#elif defined(__APPLE__) + /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache + * to the drive platters. This is in contrast to Linux's fdatasync and fsync + * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent + * for flushing buffered data to permanent storage. + */ + return fcntl(req->file, F_FULLFSYNC); +#else + return fsync(req->file); +#endif +} + + +static ssize_t uv__fs_fsync(uv_fs_t* req) { +#if defined(__APPLE__) + /* See the comment in uv__fs_fdatasync. */ + return fcntl(req->file, F_FULLFSYNC); #else return fsync(req->file); #endif @@ -229,9 +244,19 @@ skip: #endif } +#if defined(__sun) && _XOPEN_SOURCE < 600 +static char* uv__mkdtemp(char *template) +{ + if (!mktemp(template) || mkdir(template, 0700)) + return NULL; + return template; +} +#else +#define uv__mkdtemp mkdtemp +#endif static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { - return mkdtemp((char*) req->path) ? 0 : -1; + return uv__mkdtemp((char*) req->path) ? 0 : -1; } @@ -365,7 +390,6 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { static ssize_t uv__fs_scandir(uv_fs_t* req) { uv__dirent_t **dents; - int saved_errno; int n; dents = NULL; @@ -374,28 +398,17 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { /* NOTE: We will use nbufs as an index field */ req->nbufs = 0; - if (n == 0) - goto out; /* osx still needs to deallocate some memory */ - else if (n == -1) - return n; - - req->ptr = dents; - - return n; - -out: - saved_errno = errno; - if (dents != NULL) { - int i; - - /* Memory was allocated using the system allocator, so use free() here. */ - for (i = 0; i < n; i++) - free(dents[i]); + if (n == 0) { + /* OS X still needs to deallocate some memory. + * Memory was allocated using the system allocator, so use free() here. + */ free(dents); + dents = NULL; + } else if (n == -1) { + return n; } - errno = saved_errno; - req->ptr = NULL; + req->ptr = dents; return n; } @@ -798,6 +811,10 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_flags = 0; dst->st_gen = 0; #elif !defined(_AIX) && ( \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) || \ defined(_GNU_SOURCE) || \ defined(_BSD_SOURCE) || \ defined(_SVID_SOURCE) || \ @@ -809,9 +826,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec; dst->st_ctim.tv_sec = src->st_ctim.tv_sec; dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec; -# if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ +# if defined(__FreeBSD__) || \ defined(__NetBSD__) dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec; dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec; @@ -945,7 +960,7 @@ static void uv__fs_work(struct uv__work* w) { X(FCHOWN, fchown(req->file, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); - X(FSYNC, fsync(req->file)); + X(FSYNC, uv__fs_fsync(req)); X(FTRUNCATE, ftruncate(req->file, req->off)); X(FUTIME, uv__fs_futime(req)); X(LSTAT, uv__fs_lstat(req->path, &req->statbuf)); diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c index d331a1317..643e233cf 100644 --- a/Utilities/cmlibuv/src/unix/fsevents.c +++ b/Utilities/cmlibuv/src/unix/fsevents.c @@ -378,9 +378,6 @@ static void uv__fsevents_destroy_stream(uv_loop_t* loop) { if (state->fsevent_stream == NULL) return; - /* Flush all accumulated events */ - pFSEventStreamFlushSync(state->fsevent_stream); - /* Stop emitting events */ pFSEventStreamStop(state->fsevent_stream); diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h index 257002657..2e3afa6c8 100644 --- a/Utilities/cmlibuv/src/unix/internal.h +++ b/Utilities/cmlibuv/src/unix/internal.h @@ -38,6 +38,10 @@ # include "linux-syscalls.h" #endif /* __linux__ */ +#if defined(__MVS__) +# include "os390-syscalls.h" +#endif /* __MVS__ */ + #if defined(__sun) # include # include @@ -51,6 +55,10 @@ # include #endif /* _AIX */ +#if defined(__APPLE__) && !TARGET_OS_IPHONE +# include +#endif + #if defined(__ANDROID__) int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); # ifdef pthread_sigmask @@ -154,7 +162,8 @@ struct uv__stream_queued_fds_s { defined(__DragonFly__) || \ defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || \ - defined(__linux__) + defined(__linux__) || \ + defined(__OpenBSD__) #define uv__cloexec uv__cloexec_ioctl #define uv__nonblock uv__nonblock_ioctl #else @@ -183,12 +192,12 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w); int uv__io_active(const uv__io_t* w, unsigned int events); int uv__io_check_fd(uv_loop_t* loop, int fd); void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */ +int uv__io_fork(uv_loop_t* loop); /* async */ -void uv__async_send(struct uv__async* wa); -void uv__async_init(struct uv__async* wa); -int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb); -void uv__async_stop(uv_loop_t* loop, struct uv__async* wa); +void uv__async_stop(uv_loop_t* loop); +int uv__async_fork(uv_loop_t* loop); + /* loop */ void uv__run_idle(uv_loop_t* loop); @@ -224,6 +233,7 @@ int uv__next_timeout(const uv_loop_t* loop); void uv__signal_close(uv_signal_t* handle); void uv__signal_global_once_init(void); void uv__signal_loop_cleanup(uv_loop_t* loop); +int uv__signal_loop_fork(uv_loop_t* loop); /* platform specific */ uint64_t uv__hrtime(uv_clocktype_t type); @@ -268,7 +278,6 @@ int uv__make_socketpair(int fds[2], int flags); int uv__make_pipe(int fds[2], int flags); #if defined(__APPLE__) -#include int uv__fsevents_init(uv_fs_event_t* handle); int uv__fsevents_close(uv_fs_event_t* handle); @@ -294,15 +303,6 @@ static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000; #endif /* defined(__APPLE__) */ -UV_UNUSED(static void uv__req_init(uv_loop_t* loop, - uv_req_t* req, - uv_req_type type)) { - req->type = type; - uv__req_register(loop, req); -} -#define uv__req_init(loop, req, type) \ - uv__req_init((loop), (uv_req_t*)(req), (type)) - UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) { /* Use a fast time source if available. We only need millisecond precision. */ @@ -319,4 +319,8 @@ UV_UNUSED(static char* uv__basename_r(const char* path)) { return s + 1; } +#if defined(__linux__) +int uv__inotify_fork(uv_loop_t* loop, void* old_watchers); +#endif + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c index fffd4626f..6bc60bbe4 100644 --- a/Utilities/cmlibuv/src/unix/kqueue.c +++ b/Utilities/cmlibuv/src/unix/kqueue.c @@ -48,6 +48,37 @@ int uv__kqueue_init(uv_loop_t* loop) { } +static int uv__has_forked_with_cfrunloop; + +int uv__io_fork(uv_loop_t* loop) { + int err; + uv__close(loop->backend_fd); + loop->backend_fd = -1; + err = uv__kqueue_init(loop); + if (err) + return err; + +#if defined(__APPLE__) + if (loop->cf_state != NULL) { + /* We cannot start another CFRunloop and/or thread in the child + process; CF aborts if you try or if you try to touch the thread + at all to kill it. So the best we can do is ignore it from now + on. This means we can't watch directories in the same way + anymore (like other BSDs). It also means we cannot properly + clean up the allocated resources; calling + uv__fsevents_loop_delete from uv_loop_close will crash the + process. So we sidestep the issue by pretending like we never + started it in the first place. + */ + uv__has_forked_with_cfrunloop = 1; + uv__free(loop->cf_state); + loop->cf_state = NULL; + } +#endif + return err; +} + + int uv__io_check_fd(uv_loop_t* loop, int fd) { struct kevent ev; int rc; @@ -404,6 +435,9 @@ int uv_fs_event_start(uv_fs_event_t* handle, handle->cb = cb; #if defined(__APPLE__) + if (uv__has_forked_with_cfrunloop) + goto fallback; + /* Nullify field to perform checks later */ handle->cf_cb = NULL; handle->realpath = NULL; @@ -438,7 +472,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); #if defined(__APPLE__) - if (uv__fsevents_close(handle)) + if (uv__has_forked_with_cfrunloop || uv__fsevents_close(handle)) #endif /* defined(__APPLE__) */ { uv__io_close(handle->loop, &handle->event_watcher); diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c index 58dd813dd..2866e9385 100644 --- a/Utilities/cmlibuv/src/unix/linux-core.c +++ b/Utilities/cmlibuv/src/unix/linux-core.c @@ -107,6 +107,24 @@ int uv__platform_loop_init(uv_loop_t* loop) { } +int uv__io_fork(uv_loop_t* loop) { + int err; + void* old_watchers; + + old_watchers = loop->inotify_watchers; + + uv__close(loop->backend_fd); + loop->backend_fd = -1; + uv__platform_loop_delete(loop); + + err = uv__platform_loop_init(loop); + if (err) + return err; + + return uv__inotify_fork(loop, old_watchers); +} + + void uv__platform_loop_delete(uv_loop_t* loop) { if (loop->inotify_fd == -1) return; uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN); @@ -454,55 +472,6 @@ uint64_t uv__hrtime(uv_clocktype_t type) { } -void uv_loadavg(double avg[3]) { - struct sysinfo info; - - if (sysinfo(&info) < 0) return; - - avg[0] = (double) info.loads[0] / 65536.0; - avg[1] = (double) info.loads[1] / 65536.0; - avg[2] = (double) info.loads[2] / 65536.0; -} - - -int uv_exepath(char* buffer, size_t* size) { - ssize_t n; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - n = *size - 1; - if (n > 0) - n = readlink("/proc/self/exe", buffer, n); - - if (n == -1) - return -errno; - - buffer[n] = '\0'; - *size = n; - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - struct sysinfo info; - - if (sysinfo(&info) == 0) - return (uint64_t) info.freeram * info.mem_unit; - return 0; -} - - -uint64_t uv_get_total_memory(void) { - struct sysinfo info; - - if (sysinfo(&info) == 0) - return (uint64_t) info.totalram * info.mem_unit; - return 0; -} - - int uv_resident_set_memory(size_t* rss) { char buf[1024]; const char* s; @@ -868,6 +837,19 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } +static int uv__ifaddr_exclude(struct ifaddrs *ent) { + if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) + return 1; + if (ent->ifa_addr == NULL) + return 1; + /* + * On Linux getifaddrs returns information related to the raw underlying + * devices. We're not interested in this information yet. + */ + if (ent->ifa_addr->sa_family == PF_PACKET) + return 1; + return 0; +} int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { @@ -887,11 +869,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == PF_PACKET)) { + if (uv__ifaddr_exclude(ent)) continue; - } (*count)++; } @@ -908,17 +887,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, address = *addresses; for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On Linux getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information yet. - */ - if (ent->ifa_addr->sa_family == PF_PACKET) + if (uv__ifaddr_exclude(ent)) continue; address->name = uv__strdup(ent->ifa_name); @@ -942,11 +911,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, /* Fill in physical addresses for each interface */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_PACKET)) { + if (uv__ifaddr_exclude(ent)) continue; - } address = *addresses; diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c index 4708c051d..5934c5d8c 100644 --- a/Utilities/cmlibuv/src/unix/linux-inotify.c +++ b/Utilities/cmlibuv/src/unix/linux-inotify.c @@ -61,6 +61,8 @@ static void uv__inotify_read(uv_loop_t* loop, uv__io_t* w, unsigned int revents); +static void maybe_free_watcher_list(struct watcher_list* w, + uv_loop_t* loop); static int new_inotify_fd(void) { int err; @@ -108,6 +110,71 @@ static int init_inotify(uv_loop_t* loop) { } +int uv__inotify_fork(uv_loop_t* loop, void* old_watchers) { + /* Open the inotify_fd, and re-arm all the inotify watchers. */ + int err; + struct watcher_list* tmp_watcher_list_iter; + struct watcher_list* watcher_list; + struct watcher_list tmp_watcher_list; + QUEUE queue; + QUEUE* q; + uv_fs_event_t* handle; + char* tmp_path; + + if (old_watchers != NULL) { + /* We must restore the old watcher list to be able to close items + * out of it. + */ + loop->inotify_watchers = old_watchers; + + QUEUE_INIT(&tmp_watcher_list.watchers); + /* Note that the queue we use is shared with the start and stop() + * functions, making QUEUE_FOREACH unsafe to use. So we use the + * QUEUE_MOVE trick to safely iterate. Also don't free the watcher + * list until we're done iterating. c.f. uv__inotify_read. + */ + RB_FOREACH_SAFE(watcher_list, watcher_root, + CAST(&old_watchers), tmp_watcher_list_iter) { + watcher_list->iterating = 1; + QUEUE_MOVE(&watcher_list->watchers, &queue); + while (!QUEUE_EMPTY(&queue)) { + q = QUEUE_HEAD(&queue); + handle = QUEUE_DATA(q, uv_fs_event_t, watchers); + /* It's critical to keep a copy of path here, because it + * will be set to NULL by stop() and then deallocated by + * maybe_free_watcher_list + */ + tmp_path = uv__strdup(handle->path); + assert(tmp_path != NULL); + QUEUE_REMOVE(q); + QUEUE_INSERT_TAIL(&watcher_list->watchers, q); + uv_fs_event_stop(handle); + + QUEUE_INSERT_TAIL(&tmp_watcher_list.watchers, &handle->watchers); + handle->path = tmp_path; + } + watcher_list->iterating = 0; + maybe_free_watcher_list(watcher_list, loop); + } + + QUEUE_MOVE(&tmp_watcher_list.watchers, &queue); + while (!QUEUE_EMPTY(&queue)) { + q = QUEUE_HEAD(&queue); + QUEUE_REMOVE(q); + handle = QUEUE_DATA(q, uv_fs_event_t, watchers); + tmp_path = handle->path; + handle->path = NULL; + err = uv_fs_event_start(handle, handle->cb, tmp_path, 0); + uv__free(tmp_path); + if (err) + return err; + } + } + + return 0; +} + + static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) { struct watcher_list w; w.wd = wd; diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c index bd63c2f9d..bcd49242c 100644 --- a/Utilities/cmlibuv/src/unix/loop.c +++ b/Utilities/cmlibuv/src/unix/loop.c @@ -54,7 +54,8 @@ int uv_loop_init(uv_loop_t* loop) { loop->closing_handles = NULL; uv__update_time(loop); - uv__async_init(&loop->async_watcher); + loop->async_io_watcher.fd = -1; + loop->async_wfd = -1; loop->signal_pipefd[0] = -1; loop->signal_pipefd[1] = -1; loop->backend_fd = -1; @@ -108,10 +109,43 @@ fail_signal_init: } +int uv_loop_fork(uv_loop_t* loop) { + int err; + unsigned int i; + uv__io_t* w; + + err = uv__io_fork(loop); + if (err) + return err; + + err = uv__async_fork(loop); + if (err) + return err; + + err = uv__signal_loop_fork(loop); + if (err) + return err; + + /* Rearm all the watchers that aren't re-queued by the above. */ + for (i = 0; i < loop->nwatchers; i++) { + w = loop->watchers[i]; + if (w == NULL) + continue; + + if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) { + w->events = 0; /* Force re-registration in uv__io_poll. */ + QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); + } + } + + return 0; +} + + void uv__loop_close(uv_loop_t* loop) { uv__signal_loop_cleanup(loop); uv__platform_loop_delete(loop); - uv__async_stop(loop, &loop->async_watcher); + uv__async_stop(loop); if (loop->emfile_fd != -1) { uv__close(loop->emfile_fd); diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c index 4a9e6cbc1..9b5546b7e 100644 --- a/Utilities/cmlibuv/src/unix/netbsd.c +++ b/Utilities/cmlibuv/src/unix/netbsd.c @@ -27,14 +27,11 @@ #include #include -#include #include #include #include #include -#include -#include #include #include #include @@ -43,9 +40,6 @@ #include #include -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - static char *process_title; @@ -58,13 +52,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); @@ -283,98 +270,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_INET)) { - continue; - } - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - if (ent->ifa_addr->sa_family != PF_INET) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/Utilities/cmlibuv/src/unix/no-fsevents.c b/Utilities/cmlibuv/src/unix/no-fsevents.c new file mode 100644 index 000000000..38fb6ab0b --- /dev/null +++ b/Utilities/cmlibuv/src/unix/no-fsevents.c @@ -0,0 +1,42 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include + +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + return -ENOSYS; +} + +int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, + const char* filename, unsigned int flags) { + return -ENOSYS; +} + +int uv_fs_event_stop(uv_fs_event_t* handle) { + return -ENOSYS; +} + +void uv__fs_event_close(uv_fs_event_t* handle) { + UNREACHABLE(); +} diff --git a/Utilities/cmlibuv/src/unix/no-proctitle.c b/Utilities/cmlibuv/src/unix/no-proctitle.c new file mode 100644 index 000000000..a5c19fbff --- /dev/null +++ b/Utilities/cmlibuv/src/unix/no-proctitle.c @@ -0,0 +1,42 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +char** uv_setup_args(int argc, char** argv) { + return argv; +} + +int uv_set_process_title(const char* title) { + return 0; +} + +int uv_get_process_title(char* buffer, size_t size) { + if (buffer == NULL || size == 0) + return -EINVAL; + + buffer[0] = '\0'; + return 0; +} diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c index 909288cc8..56f0af15c 100644 --- a/Utilities/cmlibuv/src/unix/openbsd.c +++ b/Utilities/cmlibuv/src/unix/openbsd.c @@ -28,21 +28,13 @@ #include #include -#include -#include -#include - #include #include -#include #include #include #include #include -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - static char *process_title; @@ -56,13 +48,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); @@ -163,7 +148,7 @@ char** uv_setup_args(int argc, char** argv) { int uv_set_process_title(const char* title) { uv__free(process_title); process_title = uv__strdup(title); - setproctitle(title); + setproctitle("%s", title); return 0; } @@ -297,100 +282,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs) != 0) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_INET)) { - continue; - } - (*count)++; - } - - *addresses = uv__malloc(*count * sizeof(**addresses)); - - if (!(*addresses)) { - freeifaddrs(addrs); - return -ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - if (ent->ifa_addr->sa_family != PF_INET) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c new file mode 100644 index 000000000..7edf2358d --- /dev/null +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c @@ -0,0 +1,334 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + + +#include "os390-syscalls.h" +#include +#include +#include +#include + +#define CW_CONDVAR 32 + +#pragma linkage(BPX4CTW, OS) +#pragma linkage(BPX1CTW, OS) + +static int number_of_epolls; +static QUEUE global_epoll_queue; +static uv_mutex_t global_epoll_lock; +static uv_once_t once = UV_ONCE_INIT; + +int scandir(const char* maindir, struct dirent*** namelist, + int (*filter)(const struct dirent*), + int (*compar)(const struct dirent**, + const struct dirent **)) { + struct dirent** nl; + struct dirent* dirent; + unsigned count; + size_t allocated; + DIR* mdir; + + nl = NULL; + count = 0; + allocated = 0; + mdir = opendir(maindir); + if (!mdir) + return -1; + + while (1) { + dirent = readdir(mdir); + if (!dirent) + break; + if (!filter || filter(dirent)) { + struct dirent* copy; + copy = uv__malloc(sizeof(*copy)); + if (!copy) { + while (count) { + dirent = nl[--count]; + uv__free(dirent); + } + uv__free(nl); + closedir(mdir); + errno = ENOMEM; + return -1; + } + memcpy(copy, dirent, sizeof(*copy)); + + nl = uv__realloc(nl, sizeof(*copy) * (count + 1)); + nl[count++] = copy; + } + } + + qsort(nl, count, sizeof(struct dirent *), + (int (*)(const void *, const void *)) compar); + + closedir(mdir); + + *namelist = nl; + return count; +} + + +static unsigned int next_power_of_two(unsigned int val) { + val -= 1; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + val += 1; + return val; +} + + +static void maybe_resize(uv__os390_epoll* lst, unsigned int len) { + unsigned int newsize; + unsigned int i; + struct pollfd* newlst; + + if (len <= lst->size) + return; + + newsize = next_power_of_two(len); + newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0])); + + if (newlst == NULL) + abort(); + for (i = lst->size; i < newsize; ++i) + newlst[i].fd = -1; + + lst->items = newlst; + lst->size = newsize; +} + + +static void epoll_init(void) { + QUEUE_INIT(&global_epoll_queue); + if (uv_mutex_init(&global_epoll_lock)) + abort(); +} + + +uv__os390_epoll* epoll_create1(int flags) { + uv__os390_epoll* lst; + + uv_once(&once, epoll_init); + uv_mutex_lock(&global_epoll_lock); + lst = uv__malloc(sizeof(*lst)); + if (lst == -1) + return NULL; + QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member); + uv_mutex_unlock(&global_epoll_lock); + + /* initialize list */ + lst->size = 0; + lst->items = NULL; + return lst; +} + + +int epoll_ctl(uv__os390_epoll* lst, + int op, + int fd, + struct epoll_event *event) { + if(op == EPOLL_CTL_DEL) { + if (fd >= lst->size || lst->items[fd].fd == -1) { + errno = ENOENT; + return -1; + } + lst->items[fd].fd = -1; + } else if(op == EPOLL_CTL_ADD) { + maybe_resize(lst, fd + 1); + if (lst->items[fd].fd != -1) { + errno = EEXIST; + return -1; + } + lst->items[fd].fd = fd; + lst->items[fd].events = event->events; + } else if(op == EPOLL_CTL_MOD) { + if (fd >= lst->size || lst->items[fd].fd == -1) { + errno = ENOENT; + return -1; + } + lst->items[fd].events = event->events; + } else + abort(); + + return 0; +} + + +int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, + int maxevents, int timeout) { + size_t size; + struct pollfd* pfds; + int pollret; + int reventcount; + + uv_mutex_lock(&global_epoll_lock); + uv_mutex_unlock(&global_epoll_lock); + size = lst->size; + pfds = lst->items; + pollret = poll(pfds, size, timeout); + if(pollret == -1) + return pollret; + + reventcount = 0; + for (int i = 0; i < lst->size && i < maxevents; ++i) { + struct epoll_event ev; + + ev.events = 0; + ev.fd = pfds[i].fd; + if(!pfds[i].revents) + continue; + + if(pfds[i].revents & POLLRDNORM) + ev.events = ev.events | POLLIN; + + if(pfds[i].revents & POLLWRNORM) + ev.events = ev.events | POLLOUT; + + if(pfds[i].revents & POLLHUP) + ev.events = ev.events | POLLHUP; + + pfds[i].revents = 0; + events[reventcount++] = ev; + } + + return reventcount; +} + + +int epoll_file_close(int fd) { + QUEUE* q; + + uv_once(&once, epoll_init); + uv_mutex_lock(&global_epoll_lock); + QUEUE_FOREACH(q, &global_epoll_queue) { + uv__os390_epoll* lst; + + lst = QUEUE_DATA(q, uv__os390_epoll, member); + if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1) + lst->items[fd].fd = -1; + } + + uv_mutex_unlock(&global_epoll_lock); + return 0; +} + +void epoll_queue_close(uv__os390_epoll* lst) { + uv_mutex_lock(&global_epoll_lock); + QUEUE_REMOVE(&lst->member); + uv_mutex_unlock(&global_epoll_lock); + uv__free(lst->items); + lst->items = NULL; +} + + +int nanosleep(const struct timespec* req, struct timespec* rem) { + unsigned nano; + unsigned seconds; + unsigned events; + unsigned secrem; + unsigned nanorem; + int rv; + int rc; + int rsn; + + nano = (int)req->tv_nsec; + seconds = req->tv_sec; + events = CW_CONDVAR; + +#if defined(_LP64) + BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); +#else + BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); +#endif + + assert(rv == -1 && errno == EAGAIN); + + if(rem != NULL) { + rem->tv_nsec = nanorem; + rem->tv_sec = secrem; + } + + return 0; +} + + +char* mkdtemp(char* path) { + static const char* tempchars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + static const size_t num_chars = 62; + static const size_t num_x = 6; + char *ep, *cp; + unsigned int tries, i; + size_t len; + uint64_t v; + int fd; + int retval; + int saved_errno; + + len = strlen(path); + ep = path + len; + if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) { + errno = EINVAL; + return NULL; + } + + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + return NULL; + + tries = TMP_MAX; + retval = -1; + do { + if (read(fd, &v, sizeof(v)) != sizeof(v)) + break; + + cp = ep - num_x; + for (i = 0; i < num_x; i++) { + *cp++ = tempchars[v % num_chars]; + v /= num_chars; + } + + if (mkdir(path, S_IRWXU) == 0) { + retval = 0; + break; + } + else if (errno != EEXIST) + break; + } while (--tries); + + saved_errno = errno; + uv__close(fd); + if (tries == 0) { + errno = EEXIST; + return NULL; + } + + if (retval == -1) { + errno = saved_errno; + return NULL; + } + + return path; +} diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.h b/Utilities/cmlibuv/src/unix/os390-syscalls.h new file mode 100644 index 000000000..61a7cee83 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.h @@ -0,0 +1,69 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + + +#ifndef UV_OS390_SYSCALL_H_ +#define UV_OS390_SYSCALL_H_ + +#include "uv.h" +#include "internal.h" +#include +#include +#include + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 +#define MAX_EPOLL_INSTANCES 256 +#define MAX_ITEMS_PER_EPOLL 1024 + +#define UV__O_CLOEXEC 0x80000 +#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC +#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD +#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL +#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD + +struct epoll_event { + int events; + int fd; +}; + +typedef struct { + QUEUE member; + struct pollfd* items; + unsigned long size; +} uv__os390_epoll; + +/* epoll api */ +uv__os390_epoll* epoll_create1(int flags); +int epoll_ctl(uv__os390_epoll* ep, int op, int fd, struct epoll_event *event); +int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, int timeout); +int epoll_file_close(int fd); + +/* utility functions */ +int nanosleep(const struct timespec* req, struct timespec* rem); +int scandir(const char* maindir, struct dirent*** namelist, + int (*filter)(const struct dirent *), + int (*compar)(const struct dirent **, + const struct dirent **)); +char *mkdtemp(char* path); + +#endif /* UV_OS390_SYSCALL_H_ */ diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c index bcdbc4b6a..2ba5abf35 100644 --- a/Utilities/cmlibuv/src/unix/os390.c +++ b/Utilities/cmlibuv/src/unix/os390.c @@ -20,6 +20,628 @@ */ #include "internal.h" +#include +#include +#include +#include +#include +#if defined(__clang__) +#include "csrsic.h" +#else +#include "//'SYS1.SAMPLIB(CSRSIC)'" +#endif + +#define CVT_PTR 0x10 +#define CSD_OFFSET 0x294 + +/* + Long-term average CPU service used by this logical partition, + in millions of service units per hour. If this value is above + the partition's defined capacity, the partition will be capped. + It is calculated using the physical CPU adjustment factor + (RCTPCPUA) so it may not match other measures of service which + are based on the logical CPU adjustment factor. It is available + if the hardware supports LPAR cluster. +*/ +#define RCTLACS_OFFSET 0xC4 + +/* 32-bit count of alive CPUs. This includes both CPs and IFAs */ +#define CSD_NUMBER_ONLINE_CPUS 0xD4 + +/* Address of system resources manager (SRM) control table */ +#define CVTOPCTP_OFFSET 0x25C + +/* Address of the RCT table */ +#define RMCTRCT_OFFSET 0xE4 + +/* Address of the rsm control and enumeration area. */ +#define CVTRCEP_OFFSET 0x490 + +/* + Number of frames currently available to system. + Excluded are frames backing perm storage, frames offline, and bad frames. +*/ +#define RCEPOOL_OFFSET 0x004 + +/* Total number of frames currently on all available frame queues. */ +#define RCEAFC_OFFSET 0x088 + +/* CPC model length from the CSRSI Service. */ +#define CPCMODEL_LENGTH 16 + +/* Thread Entry constants */ +#define PGTH_CURRENT 1 +#define PGTH_LEN 26 +#define PGTHAPATH 0x20 +#pragma linkage(BPX4GTH, OS) +#pragma linkage(BPX1GTH, OS) + +typedef unsigned data_area_ptr_assign_type; + +typedef union { + struct { +#if defined(_LP64) + data_area_ptr_assign_type lower; +#endif + data_area_ptr_assign_type assign; + }; + char* deref; +} data_area_ptr; + + +void uv_loadavg(double avg[3]) { + /* TODO: implement the following */ + avg[0] = 0; + avg[1] = 0; + avg[2] = 0; +} + + +int uv__platform_loop_init(uv_loop_t* loop) { + uv__os390_epoll* ep; + + ep = epoll_create1(UV__EPOLL_CLOEXEC); + loop->ep = ep; + if (ep == NULL) + return -errno; + + return 0; +} + + +void uv__platform_loop_delete(uv_loop_t* loop) { + if (loop->ep != NULL) { + epoll_queue_close(loop->ep); + loop->ep = NULL; + } +} + + +uint64_t uv__hrtime(uv_clocktype_t type) { + struct timeval time; + gettimeofday(&time, NULL); + return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3; +} + + +/* + Get the exe path using the thread entry information + in the address space. +*/ +static int getexe(const int pid, char* buf, size_t len) { + struct { + int pid; + int thid[2]; + char accesspid; + char accessthid; + char asid[2]; + char loginname[8]; + char flag; + char len; + } Input_data; + + union { + struct { + char gthb[4]; + int pid; + int thid[2]; + char accesspid; + char accessthid[3]; + int lenused; + int offsetProcess; + int offsetConTTY; + int offsetPath; + int offsetCommand; + int offsetFileData; + int offsetThread; + } Output_data; + char buf[2048]; + } Output_buf; + + struct Output_path_type { + char gthe[4]; + short int len; + char path[1024]; + }; + + int Input_length; + int Output_length; + void* Input_address; + void* Output_address; + struct Output_path_type* Output_path; + int rv; + int rc; + int rsn; + + Input_length = PGTH_LEN; + Output_length = sizeof(Output_buf); + Output_address = &Output_buf; + Input_address = &Input_data; + memset(&Input_data, 0, sizeof Input_data); + Input_data.flag |= PGTHAPATH; + Input_data.pid = pid; + Input_data.accesspid = PGTH_CURRENT; + +#ifdef _LP64 + BPX4GTH(&Input_length, + &Input_address, + &Output_length, + &Output_address, + &rv, + &rc, + &rsn); +#else + BPX1GTH(&Input_length, + &Input_address, + &Output_length, + &Output_address, + &rv, + &rc, + &rsn); +#endif + + if (rv == -1) { + errno = rc; + return -1; + } + + /* Check highest byte to ensure data availability */ + assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A'); + + /* Get the offset from the lowest 3 bytes */ + Output_path = (char*)(&Output_buf) + + (Output_buf.Output_data.offsetPath & 0x00FFFFFF); + + if (Output_path->len >= len) { + errno = ENOBUFS; + return -1; + } + + strncpy(buf, Output_path->path, len); + + return 0; +} + + +/* + * We could use a static buffer for the path manipulations that we need outside + * of the function, but this function could be called by multiple consumers and + * we don't want to potentially create a race condition in the use of snprintf. + * There is no direct way of getting the exe path in zOS - either through /procfs + * or through some libc APIs. The below approach is to parse the argv[0]'s pattern + * and use it in conjunction with PATH environment variable to craft one. + */ +int uv_exepath(char* buffer, size_t* size) { + int res; + char args[PATH_MAX]; + char abspath[PATH_MAX]; + size_t abspath_size; + int pid; + + if (buffer == NULL || size == NULL || *size == 0) + return -EINVAL; + + pid = getpid(); + res = getexe(pid, args, sizeof(args)); + if (res < 0) + return -EINVAL; + + /* + * Possibilities for args: + * i) an absolute path such as: /home/user/myprojects/nodejs/node + * ii) a relative path such as: ./node or ../myprojects/nodejs/node + * iii) a bare filename such as "node", after exporting PATH variable + * to its location. + */ + + /* Case i) and ii) absolute or relative paths */ + if (strchr(args, '/') != NULL) { + if (realpath(args, abspath) != abspath) + return -errno; + + abspath_size = strlen(abspath); + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + + return 0; + } else { + /* Case iii). Search PATH environment variable */ + char trypath[PATH_MAX]; + char* clonedpath = NULL; + char* token = NULL; + char* path = getenv("PATH"); + + if (path == NULL) + return -EINVAL; + + clonedpath = uv__strdup(path); + if (clonedpath == NULL) + return -ENOMEM; + + token = strtok(clonedpath, ":"); + while (token != NULL) { + snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); + if (realpath(trypath, abspath) == abspath) { + /* Check the match is executable */ + if (access(abspath, X_OK) == 0) { + abspath_size = strlen(abspath); + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + + uv__free(clonedpath); + return 0; + } + } + token = strtok(NULL, ":"); + } + uv__free(clonedpath); + + /* Out of tokens (path entries), and no match found */ + return -EINVAL; + } +} + + +uint64_t uv_get_free_memory(void) { + uint64_t freeram; + + data_area_ptr cvt = {0}; + data_area_ptr rcep = {0}; + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); + freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4; + return freeram; +} + + +uint64_t uv_get_total_memory(void) { + uint64_t totalram; + + data_area_ptr cvt = {0}; + data_area_ptr rcep = {0}; + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); + totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4; + return totalram; +} + + +int uv_resident_set_memory(size_t* rss) { + W_PSPROC buf; + + memset(&buf, 0, sizeof(buf)); + if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1) + return -EINVAL; + + *rss = buf.ps_size; + return 0; +} + + +int uv_uptime(double* uptime) { + struct utmpx u ; + struct utmpx *v; + time64_t t; + + u.ut_type = BOOT_TIME; + v = getutxid(&u); + if (v == NULL) + return -1; + *uptime = difftime64(time64(&t), v->ut_tv.tv_sec); + return 0; +} + + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + uv_cpu_info_t* cpu_info; + int result; + int idx; + siv1v2 info; + data_area_ptr cvt = {0}; + data_area_ptr csd = {0}; + data_area_ptr rmctrct = {0}; + data_area_ptr cvtopctp = {0}; + int cpu_usage_avg; + + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + + csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET)); + cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET)); + rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET)); + + *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS)); + cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET)); + + *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t)); + if (!*cpu_infos) + return -ENOMEM; + + cpu_info = *cpu_infos; + idx = 0; + while (idx < *count) { + cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability); + cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1); + memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1); + memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH); + cpu_info->cpu_times.user = cpu_usage_avg; + /* TODO: implement the following */ + cpu_info->cpu_times.sys = 0; + cpu_info->cpu_times.idle = 0; + cpu_info->cpu_times.irq = 0; + cpu_info->cpu_times.nice = 0; + ++cpu_info; + ++idx; + } + + return 0; +} + + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + for (int i = 0; i < count; ++i) + uv__free(cpu_infos[i].model); + uv__free(cpu_infos); +} + + +static int uv__interface_addresses_v6(uv_interface_address_t** addresses, + int* count) { + uv_interface_address_t* address; + int sockfd; + int maxsize; + __net_ifconf6header_t ifc; + __net_ifconf6entry_t* ifr; + __net_ifconf6entry_t* p; + __net_ifconf6entry_t flg; + + *count = 0; + /* Assume maximum buffer size allowable */ + maxsize = 16384; + + if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) + return -errno; + + ifc.__nif6h_version = 1; + ifc.__nif6h_buflen = maxsize; + ifc.__nif6h_buffer = uv__calloc(1, maxsize);; + + if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { + uv__close(sockfd); + return -errno; + } + + + *count = 0; + ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); + while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { + p = ifr; + ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); + + if (!(p->__nif6e_addr.sin6_family == AF_INET6 || + p->__nif6e_addr.sin6_family == AF_INET)) + continue; + + if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) + continue; + + ++(*count); + } + + /* Alloc the return interface structs */ + *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); + if (!(*addresses)) { + uv__close(sockfd); + return -ENOMEM; + } + address = *addresses; + + ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); + while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { + p = ifr; + ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); + + if (!(p->__nif6e_addr.sin6_family == AF_INET6 || + p->__nif6e_addr.sin6_family == AF_INET)) + continue; + + if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) + continue; + + /* All conditions above must match count loop */ + + address->name = uv__strdup(p->__nif6e_name); + + if (p->__nif6e_addr.sin6_family == AF_INET6) + address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); + else + address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr); + + /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ + + address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; + + address++; + } + + uv__close(sockfd); + return 0; +} + + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + uv_interface_address_t* address; + int sockfd; + int maxsize; + struct ifconf ifc; + struct ifreq flg; + struct ifreq* ifr; + struct ifreq* p; + int count_v6; + + /* get the ipv6 addresses first */ + uv_interface_address_t* addresses_v6; + uv__interface_addresses_v6(&addresses_v6, &count_v6); + + /* now get the ipv4 addresses */ + *count = 0; + + /* Assume maximum buffer size allowable */ + maxsize = 16384; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (0 > sockfd) + return -errno; + + ifc.ifc_req = uv__calloc(1, maxsize); + ifc.ifc_len = maxsize; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { + uv__close(sockfd); + return -errno; + } + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) + + /* Count all up and running ipv4/ipv6 addresses */ + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + uv__close(sockfd); + return -errno; + } + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + (*count)++; + } + + /* Alloc the return interface structs */ + *addresses = uv__malloc((*count + count_v6) * + sizeof(uv_interface_address_t)); + + if (!(*addresses)) { + uv__close(sockfd); + return -ENOMEM; + } + address = *addresses; + + /* copy over the ipv6 addresses */ + memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); + address += count_v6; + *count += count_v6; + uv__free(addresses_v6); + + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + uv__close(sockfd); + return -ENOSYS; + } + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + /* All conditions above must match count loop */ + + address->name = uv__strdup(p->ifr_name); + + if (p->ifr_addr.sa_family == AF_INET6) { + address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); + } else { + address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); + } + + address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; + address++; + } + +#undef ADDR_SIZE +#undef MAX + + uv__close(sockfd); + return 0; +} + + +void uv_free_interface_addresses(uv_interface_address_t* addresses, + int count) { + int i; + for (i = 0; i < count; ++i) + uv__free(addresses[i].name); + uv__free(addresses); +} + + +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { + struct epoll_event* events; + struct epoll_event dummy; + uintptr_t i; + uintptr_t nfds; + + assert(loop->watchers != NULL); + + events = (struct epoll_event*) loop->watchers[loop->nwatchers]; + nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; + if (events != NULL) + /* Invalidate events with same file descriptor */ + for (i = 0; i < nfds; i++) + if ((int) events[i].fd == fd) + events[i].fd = -1; + + /* Remove the file descriptor from the epoll. */ + if (loop->ep != NULL) + epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy); +} + int uv__io_check_fd(uv_loop_t* loop, int fd) { struct pollfd p[1]; @@ -40,3 +662,188 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { return 0; } + +void uv__io_poll(uv_loop_t* loop, int timeout) { + static const int max_safe_timeout = 1789569; + struct epoll_event events[1024]; + struct epoll_event* pe; + struct epoll_event e; + int real_timeout; + QUEUE* q; + uv__io_t* w; + uint64_t base; + int count; + int nfds; + int fd; + int op; + int i; + + if (loop->nfds == 0) { + assert(QUEUE_EMPTY(&loop->watcher_queue)); + return; + } + + while (!QUEUE_EMPTY(&loop->watcher_queue)) { + uv_stream_t* stream; + + q = QUEUE_HEAD(&loop->watcher_queue); + QUEUE_REMOVE(q); + QUEUE_INIT(q); + w = QUEUE_DATA(q, uv__io_t, watcher_queue); + + assert(w->pevents != 0); + assert(w->fd >= 0); + + stream= container_of(w, uv_stream_t, io_watcher); + + assert(w->fd < (int) loop->nwatchers); + + e.events = w->pevents; + e.fd = w->fd; + + if (w->events == 0) + op = UV__EPOLL_CTL_ADD; + else + op = UV__EPOLL_CTL_MOD; + + /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching + * events, skip the syscall and squelch the events after epoll_wait(). + */ + if (epoll_ctl(loop->ep, op, w->fd, &e)) { + if (errno != EEXIST) + abort(); + + assert(op == UV__EPOLL_CTL_ADD); + + /* We've reactivated a file descriptor that's been watched before. */ + if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e)) + abort(); + } + + w->events = w->pevents; + } + + assert(timeout >= -1); + base = loop->time; + count = 48; /* Benchmarks suggest this gives the best throughput. */ + real_timeout = timeout; + int nevents = 0; + + nfds = 0; + for (;;) { + if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) + timeout = max_safe_timeout; + + nfds = epoll_wait(loop->ep, events, + ARRAY_SIZE(events), timeout); + + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + base = loop->time; + SAVE_ERRNO(uv__update_time(loop)); + if (nfds == 0) { + assert(timeout != -1); + timeout = real_timeout - timeout; + if (timeout > 0) + continue; + + return; + } + + if (nfds == -1) { + + if (errno != EINTR) + abort(); + + if (timeout == -1) + continue; + + if (timeout == 0) + return; + + /* Interrupted by a signal. Update timeout and poll again. */ + goto update_timeout; + } + + + assert(loop->watchers != NULL); + loop->watchers[loop->nwatchers] = (void*) events; + loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; + for (i = 0; i < nfds; i++) { + pe = events + i; + fd = pe->fd; + + /* Skip invalidated events, see uv__platform_invalidate_fd */ + if (fd == -1) + continue; + + assert(fd >= 0); + assert((unsigned) fd < loop->nwatchers); + + w = loop->watchers[fd]; + + if (w == NULL) { + /* File descriptor that we've stopped watching, disarm it. + * + * Ignore all errors because we may be racing with another thread + * when the file descriptor is closed. + */ + epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe); + continue; + } + + /* Give users only events they're interested in. Prevents spurious + * callbacks when previous callback invocation in this loop has stopped + * the current watcher. Also, filters out events that users has not + * requested us to watch. + */ + pe->events &= w->pevents | POLLERR | POLLHUP; + + if (pe->events == POLLERR || pe->events == POLLHUP) + pe->events |= w->pevents & (POLLIN | POLLOUT); + + if (pe->events != 0) { + w->cb(loop, w, pe->events); + nevents++; + } + } + loop->watchers[loop->nwatchers] = NULL; + loop->watchers[loop->nwatchers + 1] = NULL; + + if (nevents != 0) { + if (nfds == ARRAY_SIZE(events) && --count != 0) { + /* Poll for more events but don't block this time. */ + timeout = 0; + continue; + } + return; + } + + if (timeout == 0) + return; + + if (timeout == -1) + continue; + +update_timeout: + assert(timeout > 0); + + real_timeout -= (loop->time - base); + if (real_timeout <= 0) + return; + + timeout = real_timeout; + } +} + +void uv__set_process_title(const char* title) { + /* do nothing */ +} + +int uv__io_fork(uv_loop_t* loop) { + uv__platform_loop_delete(loop); + + return uv__platform_loop_init(loop); +} diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c index 80f5e6f80..7ba1bf879 100644 --- a/Utilities/cmlibuv/src/unix/pipe.c +++ b/Utilities/cmlibuv/src/unix/pipe.c @@ -73,7 +73,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* Convert ENOENT to EACCES for compatibility with Windows. */ if (err == -ENOENT) err = -EACCES; - goto err_bind; + + uv__close(sockfd); + goto err_socket; } /* Success. */ @@ -82,9 +84,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { handle->io_watcher.fd = sockfd; return 0; -err_bind: - uv__close(sockfd); - err_socket: uv__free((void*)pipe_fname); return err; @@ -180,6 +179,14 @@ void uv_pipe_connect(uv_connect_t* req, if (r == -1 && errno != EINPROGRESS) { err = -errno; +#if defined(__CYGWIN__) || defined(__MSYS__) + /* EBADF is supposed to mean that the socket fd is bad, but + Cygwin reports EBADF instead of ENOTSOCK when the file is + not a socket. We do not expect to see a bad fd here + (e.g. due to new_sock), so translate the error. */ + if (err == -EBADF) + err = -ENOTSOCK; +#endif goto out; } diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c index 4c0d478ee..370994bd5 100644 --- a/Utilities/cmlibuv/src/unix/poll.c +++ b/Utilities/cmlibuv/src/unix/poll.c @@ -92,7 +92,7 @@ static void uv__poll_stop(uv_poll_t* handle) { int uv_poll_stop(uv_poll_t* handle) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); uv__poll_stop(handle); return 0; } @@ -102,7 +102,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { int events; assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); uv__poll_stop(handle); diff --git a/Utilities/cmlibuv/src/unix/posix-hrtime.c b/Utilities/cmlibuv/src/unix/posix-hrtime.c new file mode 100644 index 000000000..323dfc203 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/posix-hrtime.c @@ -0,0 +1,35 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +#undef NANOSEC +#define NANOSEC ((uint64_t) 1e9) + +uint64_t uv__hrtime(uv_clocktype_t type) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); +} diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c new file mode 100644 index 000000000..3fba96e1b --- /dev/null +++ b/Utilities/cmlibuv/src/unix/posix-poll.c @@ -0,0 +1,324 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +/* POSIX defines poll() as a portable way to wait on file descriptors. + * Here we maintain a dynamically sized array of file descriptors and + * events to pass as the first argument to poll(). + */ + +#include +#include +#include +#include +#include + +int uv__platform_loop_init(uv_loop_t* loop) { + loop->poll_fds = NULL; + loop->poll_fds_used = 0; + loop->poll_fds_size = 0; + loop->poll_fds_iterating = 0; + return 0; +} + +void uv__platform_loop_delete(uv_loop_t* loop) { + uv__free(loop->poll_fds); + loop->poll_fds = NULL; +} + +int uv__io_fork(uv_loop_t* loop) { + uv__platform_loop_delete(loop); + return uv__platform_loop_init(loop); +} + +/* Allocate or dynamically resize our poll fds array. */ +static void uv__pollfds_maybe_resize(uv_loop_t* loop) { + size_t i; + size_t n; + struct pollfd* p; + + if (loop->poll_fds_used < loop->poll_fds_size) + return; + + n = loop->poll_fds_size ? loop->poll_fds_size * 2 : 64; + p = uv__realloc(loop->poll_fds, n * sizeof(*loop->poll_fds)); + if (p == NULL) + abort(); + + loop->poll_fds = p; + for (i = loop->poll_fds_size; i < n; i++) { + loop->poll_fds[i].fd = -1; + loop->poll_fds[i].events = 0; + loop->poll_fds[i].revents = 0; + } + loop->poll_fds_size = n; +} + +/* Primitive swap operation on poll fds array elements. */ +static void uv__pollfds_swap(uv_loop_t* loop, size_t l, size_t r) { + struct pollfd pfd; + pfd = loop->poll_fds[l]; + loop->poll_fds[l] = loop->poll_fds[r]; + loop->poll_fds[r] = pfd; +} + +/* Add a watcher's fd to our poll fds array with its pending events. */ +static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) { + size_t i; + struct pollfd* pe; + + /* If the fd is already in the set just update its events. */ + assert(!loop->poll_fds_iterating); + for (i = 0; i < loop->poll_fds_used; ++i) { + if (loop->poll_fds[i].fd == w->fd) { + loop->poll_fds[i].events = w->pevents; + return; + } + } + + /* Otherwise, allocate a new slot in the set for the fd. */ + uv__pollfds_maybe_resize(loop); + pe = &loop->poll_fds[loop->poll_fds_used++]; + pe->fd = w->fd; + pe->events = w->pevents; +} + +/* Remove a watcher's fd from our poll fds array. */ +static void uv__pollfds_del(uv_loop_t* loop, int fd) { + size_t i; + assert(!loop->poll_fds_iterating); + for (i = 0; i < loop->poll_fds_used; ++i) { + if (loop->poll_fds[i].fd == fd) { + /* swap to last position and remove */ + --loop->poll_fds_used; + uv__pollfds_swap(loop, i, loop->poll_fds_used); + loop->poll_fds[loop->poll_fds_used].fd = -1; + loop->poll_fds[loop->poll_fds_used].events = 0; + loop->poll_fds[loop->poll_fds_used].revents = 0; + return; + } + } +} + + +void uv__io_poll(uv_loop_t* loop, int timeout) { + sigset_t* pset; + sigset_t set; + uint64_t time_base; + uint64_t time_diff; + QUEUE* q; + uv__io_t* w; + size_t i; + unsigned int nevents; + int nfds; + int have_signals; + struct pollfd* pe; + int fd; + + if (loop->nfds == 0) { + assert(QUEUE_EMPTY(&loop->watcher_queue)); + return; + } + + /* Take queued watchers and add their fds to our poll fds array. */ + while (!QUEUE_EMPTY(&loop->watcher_queue)) { + q = QUEUE_HEAD(&loop->watcher_queue); + QUEUE_REMOVE(q); + QUEUE_INIT(q); + + w = QUEUE_DATA(q, uv__io_t, watcher_queue); + assert(w->pevents != 0); + assert(w->fd >= 0); + assert(w->fd < (int) loop->nwatchers); + + uv__pollfds_add(loop, w); + + w->events = w->pevents; + } + + /* Prepare a set of signals to block around poll(), if any. */ + pset = NULL; + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { + pset = &set; + sigemptyset(pset); + sigaddset(pset, SIGPROF); + } + + assert(timeout >= -1); + time_base = loop->time; + + /* Loop calls to poll() and processing of results. If we get some + * results from poll() but they turn out not to be interesting to + * our caller then we need to loop around and poll() again. + */ + for (;;) { + if (pset != NULL) + if (pthread_sigmask(SIG_BLOCK, pset, NULL)) + abort(); + nfds = poll(loop->poll_fds, (nfds_t)loop->poll_fds_used, timeout); + if (pset != NULL) + if (pthread_sigmask(SIG_UNBLOCK, pset, NULL)) + abort(); + + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + SAVE_ERRNO(uv__update_time(loop)); + + if (nfds == 0) { + assert(timeout != -1); + return; + } + + if (nfds == -1) { + if (errno != EINTR) + abort(); + + if (timeout == -1) + continue; + + if (timeout == 0) + return; + + /* Interrupted by a signal. Update timeout and poll again. */ + goto update_timeout; + } + + /* Tell uv__platform_invalidate_fd not to manipulate our array + * while we are iterating over it. + */ + loop->poll_fds_iterating = 1; + + /* Initialize a count of events that we care about. */ + nevents = 0; + have_signals = 0; + + /* Loop over the entire poll fds array looking for returned events. */ + for (i = 0; i < loop->poll_fds_used; i++) { + pe = loop->poll_fds + i; + fd = pe->fd; + + /* Skip invalidated events, see uv__platform_invalidate_fd. */ + if (fd == -1) + continue; + + assert(fd >= 0); + assert((unsigned) fd < loop->nwatchers); + + w = loop->watchers[fd]; + + if (w == NULL) { + /* File descriptor that we've stopped watching, ignore. */ + uv__platform_invalidate_fd(loop, fd); + continue; + } + + /* Filter out events that user has not requested us to watch + * (e.g. POLLNVAL). + */ + pe->revents &= w->pevents | POLLERR | POLLHUP; + + if (pe->revents != 0) { + /* Run signal watchers last. */ + if (w == &loop->signal_io_watcher) { + have_signals = 1; + } else { + w->cb(loop, w, pe->revents); + } + + nevents++; + } + } + + if (have_signals != 0) + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + + loop->poll_fds_iterating = 0; + + /* Purge invalidated fds from our poll fds array. */ + uv__pollfds_del(loop, -1); + + if (have_signals != 0) + return; /* Event loop should cycle now so don't poll again. */ + + if (nevents != 0) + return; + + if (timeout == 0) + return; + + if (timeout == -1) + continue; + +update_timeout: + assert(timeout > 0); + + time_diff = loop->time - time_base; + if (time_diff >= (uint64_t) timeout) + return; + + timeout -= time_diff; + } +} + +/* Remove the given fd from our poll fds array because no one + * is interested in its events anymore. + */ +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { + size_t i; + + if (loop->poll_fds_iterating) { + /* uv__io_poll is currently iterating. Just invalidate fd. */ + for (i = 0; i < loop->poll_fds_used; i++) + if (loop->poll_fds[i].fd == fd) { + loop->poll_fds[i].fd = -1; + loop->poll_fds[i].events = 0; + loop->poll_fds[i].revents = 0; + } + } else { + /* uv__io_poll is not iterating. Delete fd from the set. */ + uv__pollfds_del(loop, fd); + } +} + +/* Check whether the given fd is supported by poll(). */ +int uv__io_check_fd(uv_loop_t* loop, int fd) { + struct pollfd p[1]; + int rv; + + p[0].fd = fd; + p[0].events = POLLIN; + + do + rv = poll(p, 1, 0); + while (rv == -1 && (errno == EINTR || errno == EAGAIN)); + + if (rv == -1) + return -errno; + + if (p[0].revents & POLLNVAL) + return -EINVAL; + + return 0; +} diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c index 45f5b4526..f2fe30521 100644 --- a/Utilities/cmlibuv/src/unix/process.c +++ b/Utilities/cmlibuv/src/unix/process.c @@ -323,7 +323,7 @@ static void uv__process_child_init(const uv_process_options_t* options, } if (fd == use_fd) - uv__cloexec(use_fd, 0); + uv__cloexec_fcntl(use_fd, 0); else fd = dup2(use_fd, fd); @@ -333,7 +333,7 @@ static void uv__process_child_init(const uv_process_options_t* options, } if (fd <= 2) - uv__nonblock(fd, 0); + uv__nonblock_fcntl(fd, 0); if (close_fd >= stdio_count) uv__close(close_fd); diff --git a/Utilities/cmlibuv/src/unix/procfs-exepath.c b/Utilities/cmlibuv/src/unix/procfs-exepath.c new file mode 100644 index 000000000..5fdb61155 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/procfs-exepath.c @@ -0,0 +1,45 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +int uv_exepath(char* buffer, size_t* size) { + ssize_t n; + + if (buffer == NULL || size == NULL || *size == 0) + return -EINVAL; + + n = *size - 1; + if (n > 0) + n = readlink("/proc/self/exe", buffer, n); + + if (n == -1) + return -errno; + + buffer[n] = '\0'; + *size = n; + + return 0; +} diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c index 08d875f7a..9160f7eaf 100644 --- a/Utilities/cmlibuv/src/unix/proctitle.c +++ b/Utilities/cmlibuv/src/unix/proctitle.c @@ -48,9 +48,15 @@ char** uv_setup_args(int argc, char** argv) { for (i = 0; i < argc; i++) size += strlen(argv[i]) + 1; +#if defined(__MVS__) + /* argv is not adjacent. So just use argv[0] */ + process_title.str = argv[0]; + process_title.len = strlen(argv[0]); +#else process_title.str = argv[0]; process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0]; assert(process_title.len + 1 == size); /* argv memory should be adjacent. */ +#endif /* Add space for the argv pointers. */ size += (argc + 1) * sizeof(char*); diff --git a/Utilities/cmlibuv/src/unix/pthread-barrier.c b/Utilities/cmlibuv/src/unix/pthread-barrier.c index f57bf2508..b6e604d46 100644 --- a/Utilities/cmlibuv/src/unix/pthread-barrier.c +++ b/Utilities/cmlibuv/src/unix/pthread-barrier.c @@ -73,7 +73,8 @@ int pthread_barrier_wait(pthread_barrier_t* barrier) { if (++b->in == b->threshold) { b->in = 0; b->out = b->threshold - 1; - assert(pthread_cond_signal(&b->cond) == 0); + rc = pthread_cond_signal(&b->cond); + assert(rc == 0); pthread_mutex_unlock(&b->mutex); return PTHREAD_BARRIER_SERIAL_THREAD; diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c index d82b9b7cf..cb09ead50 100644 --- a/Utilities/cmlibuv/src/unix/signal.c +++ b/Utilities/cmlibuv/src/unix/signal.c @@ -38,12 +38,17 @@ RB_HEAD(uv__signal_tree_s, uv_signal_s); static int uv__signal_unlock(void); +static int uv__signal_start(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum, + int oneshot); static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events); static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2); static void uv__signal_stop(uv_signal_t* handle); +static void uv__signal_unregister_handler(int signum); -static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT; +static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT; static struct uv__signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); static int uv__signal_lock_pipefd[2]; @@ -53,8 +58,19 @@ RB_GENERATE_STATIC(uv__signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare) +static void uv__signal_global_reinit(void); static void uv__signal_global_init(void) { + if (!uv__signal_lock_pipefd[0]) + /* pthread_atfork can register before and after handlers, one + * for each child. This only registers one for the child. That + * state is both persistent and cumulative, so if we keep doing + * it the handler functions will be called multiple times. Thus + * we only want to do it once. + */ + if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit)) + abort(); + if (uv__make_pipe(uv__signal_lock_pipefd, 0)) abort(); @@ -63,8 +79,24 @@ static void uv__signal_global_init(void) { } +static void uv__signal_global_reinit(void) { + /* We can only use signal-safe functions here. + * That includes read/write and close, fortunately. + * We do all of this directly here instead of resetting + * uv__signal_global_init_guard because + * uv__signal_global_once_init is only called from uv_loop_init + * and this needs to function in existing loops. + */ + uv__close(uv__signal_lock_pipefd[0]); + uv__signal_lock_pipefd[0] = -1; + uv__close(uv__signal_lock_pipefd[1]); + uv__signal_lock_pipefd[1] = -1; + uv__signal_global_init(); +} + + void uv__signal_global_once_init(void) { - pthread_once(&uv__signal_global_init_guard, uv__signal_global_init); + uv_once(&uv__signal_global_init_guard, uv__signal_global_init); } @@ -122,6 +154,7 @@ static uv_signal_t* uv__signal_first_handle(int signum) { uv_signal_t* handle; lookup.signum = signum; + lookup.flags = 0; lookup.loop = NULL; handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup); @@ -174,7 +207,7 @@ static void uv__signal_handler(int signum) { } -static int uv__signal_register_handler(int signum) { +static int uv__signal_register_handler(int signum, int oneshot) { /* When this function is called, the signal lock must be held. */ struct sigaction sa; @@ -183,6 +216,7 @@ static int uv__signal_register_handler(int signum) { if (sigfillset(&sa.sa_mask)) abort(); sa.sa_handler = uv__signal_handler; + sa.sa_flags = oneshot ? SA_RESETHAND : 0; /* XXX save old action so we can restore it later on? */ if (sigaction(signum, &sa, NULL)) @@ -228,6 +262,16 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) { } +int uv__signal_loop_fork(uv_loop_t* loop) { + uv__io_stop(loop, &loop->signal_io_watcher, POLLIN); + uv__close(loop->signal_pipefd[0]); + uv__close(loop->signal_pipefd[1]); + loop->signal_pipefd[0] = -1; + loop->signal_pipefd[1] = -1; + return uv__signal_loop_once_init(loop); +} + + void uv__signal_loop_cleanup(uv_loop_t* loop) { QUEUE* q; @@ -287,10 +331,26 @@ void uv__signal_close(uv_signal_t* handle) { int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { + return uv__signal_start(handle, signal_cb, signum, 0); +} + + +int uv_signal_start_oneshot(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum) { + return uv__signal_start(handle, signal_cb, signum, 1); +} + + +static int uv__signal_start(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum, + int oneshot) { sigset_t saved_sigmask; int err; + uv_signal_t* first_handle; - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); /* If the user supplies signum == 0, then return an error already. If the * signum is otherwise invalid then uv__signal_register will find out @@ -318,9 +378,12 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { /* If at this point there are no active signal watchers for this signum (in * any of the loops), it's time to try and register a handler for it here. + * Also in case there's only one-shot handlers and a regular handler comes in. */ - if (uv__signal_first_handle(signum) == NULL) { - err = uv__signal_register_handler(signum); + first_handle = uv__signal_first_handle(signum); + if (first_handle == NULL || + (!oneshot && (first_handle->flags & UV__SIGNAL_ONE_SHOT))) { + err = uv__signal_register_handler(signum, oneshot); if (err) { /* Registering the signal handler failed. Must be an invalid signal. */ uv__signal_unlock_and_unblock(&saved_sigmask); @@ -329,6 +392,9 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { } handle->signum = signum; + if (oneshot) + handle->flags |= UV__SIGNAL_ONE_SHOT; + RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle); uv__signal_unlock_and_unblock(&saved_sigmask); @@ -390,6 +456,9 @@ static void uv__signal_event(uv_loop_t* loop, handle->dispatched_signals++; + if (handle->flags & UV__SIGNAL_ONE_SHOT) + uv__signal_stop(handle); + /* If uv_close was called while there were caught signals that were not * yet dispatched, the uv__finish_close was deferred. Make close pending * now if this has happened. @@ -414,12 +483,22 @@ static void uv__signal_event(uv_loop_t* loop, static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { + int f1; + int f2; /* Compare signums first so all watchers with the same signnum end up * adjacent. */ if (w1->signum < w2->signum) return -1; if (w1->signum > w2->signum) return 1; + /* Handlers without UV__SIGNAL_ONE_SHOT set will come first, so if the first + * handler returned is a one-shot handler, the rest will be too. + */ + f1 = w1->flags & UV__SIGNAL_ONE_SHOT; + f2 = w2->flags & UV__SIGNAL_ONE_SHOT; + if (f1 < f2) return -1; + if (f1 > f2) return 1; + /* Sort by loop pointer, so we can easily look up the first item after * { .signum = x, .loop = NULL }. */ @@ -434,7 +513,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { int uv_signal_stop(uv_signal_t* handle) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); uv__signal_stop(handle); return 0; } @@ -443,6 +522,10 @@ int uv_signal_stop(uv_signal_t* handle) { static void uv__signal_stop(uv_signal_t* handle) { uv_signal_t* removed_handle; sigset_t saved_sigmask; + uv_signal_t* first_handle; + int rem_oneshot; + int first_oneshot; + int ret; /* If the watcher wasn't started, this is a no-op. */ if (handle->signum == 0) @@ -457,8 +540,17 @@ static void uv__signal_stop(uv_signal_t* handle) { /* Check if there are other active signal watchers observing this signal. If * not, unregister the signal handler. */ - if (uv__signal_first_handle(handle->signum) == NULL) + first_handle = uv__signal_first_handle(handle->signum); + if (first_handle == NULL) { uv__signal_unregister_handler(handle->signum); + } else { + rem_oneshot = handle->flags & UV__SIGNAL_ONE_SHOT; + first_oneshot = first_handle->flags & UV__SIGNAL_ONE_SHOT; + if (first_oneshot && !rem_oneshot) { + ret = uv__signal_register_handler(handle->signum, 1); + assert(ret == 0); + } + } uv__signal_unlock_and_unblock(&saved_sigmask); diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c index d20d0bcb3..7b23d16ec 100644 --- a/Utilities/cmlibuv/src/unix/stream.c +++ b/Utilities/cmlibuv/src/unix/stream.c @@ -785,7 +785,12 @@ start: struct msghdr msg; struct cmsghdr *cmsg; int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle); - char scratch[64] = {0}; + union { + char data[64]; + struct cmsghdr alias; + } scratch; + + memset(&scratch, 0, sizeof(scratch)); assert(fd_to_send >= 0); @@ -795,7 +800,7 @@ start: msg.msg_iovlen = iovcnt; msg.msg_flags = 0; - msg.msg_control = (void*) scratch; + msg.msg_control = &scratch.alias; msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send)); cmsg = CMSG_FIRSTHDR(&msg); @@ -1168,6 +1173,11 @@ static void uv__read(uv_stream_t* stream) { uv__stream_osx_interrupt_select(stream); } stream->read_cb(stream, 0, &buf); +#if defined(__CYGWIN__) || defined(__MSYS__) + } else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) { + uv__stream_eof(stream, &buf); + return; +#endif } else { /* Error. User should call uv_close(). */ stream->read_cb(stream, -errno, &buf); @@ -1194,6 +1204,30 @@ static void uv__read(uv_stream_t* stream) { return; } } + +#if defined(__MVS__) + if (is_ipc && msg.msg_controllen > 0) { + uv_buf_t blankbuf; + int nread; + struct iovec *old; + + blankbuf.base = 0; + blankbuf.len = 0; + old = msg.msg_iov; + msg.msg_iov = (struct iovec*) &blankbuf; + nread = 0; + do { + nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0); + err = uv__stream_recv_cmsg(stream, &msg); + if (err != 0) { + stream->read_cb(stream, err, &buf); + msg.msg_iov = old; + return; + } + } while (nread == 0 && msg.msg_controllen > 0); + msg.msg_iov = old; + } +#endif stream->read_cb(stream, nread, &buf); /* Return if we didn't fill the buffer, there is no more data to read. */ @@ -1221,8 +1255,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { if (!(stream->flags & UV_STREAM_WRITABLE) || stream->flags & UV_STREAM_SHUT || stream->flags & UV_STREAM_SHUTTING || - stream->flags & UV_CLOSED || - stream->flags & UV_CLOSING) { + uv__is_closing(stream)) { return -ENOTCONN; } @@ -1377,6 +1410,12 @@ int uv_write2(uv_write_t* req, */ if (uv__handle_fd((uv_handle_t*) send_handle) < 0) return -EBADF; + +#if defined(__CYGWIN__) || defined(__MSYS__) + /* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it. + See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */ + return -ENOSYS; +#endif } /* It's legal for write_queue_size > 0 even when the write_queue is empty; diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c index 3e7a7592d..041f3f336 100644 --- a/Utilities/cmlibuv/src/unix/sunos.c +++ b/Utilities/cmlibuv/src/unix/sunos.c @@ -28,6 +28,10 @@ #include #include +#if !defined(SUNOS_NO_IFADDRS) && _XOPEN_SOURCE < 600 +#define SUNOS_NO_IFADDRS +#endif + #ifndef SUNOS_NO_IFADDRS # include #endif @@ -99,6 +103,18 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } +int uv__io_fork(uv_loop_t* loop) { +#if defined(PORT_SOURCE_FILE) + if (loop->fs_fd != -1) { + /* stop the watcher before we blow away its fileno */ + uv__io_stop(loop, &loop->fs_event_watcher, POLLIN); + } +#endif + uv__platform_loop_delete(loop); + return uv__platform_loop_init(loop); +} + + void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { struct port_event* events; uintptr_t i; @@ -469,8 +485,10 @@ int uv_fs_event_start(uv_fs_event_t* handle, memset(&handle->fo, 0, sizeof handle->fo); handle->fo.fo_name = handle->path; err = uv__fs_event_rearm(handle); - if (err != 0) + if (err != 0) { + uv_fs_event_stop(handle); return err; + } if (first_run) { uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd); @@ -531,25 +549,6 @@ void uv__fs_event_close(uv_fs_event_t* handle) { #endif /* defined(PORT_SOURCE_FILE) */ -char** uv_setup_args(int argc, char** argv) { - return argv; -} - - -int uv_set_process_title(const char* title) { - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (buffer == NULL || size == 0) - return -EINVAL; - - buffer[0] = '\0'; - return 0; -} - - int uv_resident_set_memory(size_t* rss) { psinfo_t psinfo; int err; @@ -695,6 +694,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } +#ifdef SUNOS_NO_IFADDRS +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + return -ENOSYS; +} +#else /* SUNOS_NO_IFADDRS */ /* * Inspired By: * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris @@ -741,10 +745,18 @@ static int uv__set_phys_addr(uv_interface_address_t* address, return 0; } + +static int uv__ifaddr_exclude(struct ifaddrs *ent) { + if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) + return 1; + if (ent->ifa_addr == NULL) + return 1; + if (ent->ifa_addr->sa_family == PF_PACKET) + return 1; + return 0; +} + int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { -#ifdef SUNOS_NO_IFADDRS - return -ENOSYS; -#else uv_interface_address_t* address; struct ifaddrs* addrs; struct ifaddrs* ent; @@ -757,12 +769,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == PF_PACKET)) { + if (uv__ifaddr_exclude(ent)) continue; - } - (*count)++; } @@ -775,10 +783,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address = *addresses; for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) + if (uv__ifaddr_exclude(ent)) continue; address->name = uv__strdup(ent->ifa_name); @@ -805,9 +810,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { freeifaddrs(addrs); return 0; -#endif /* SUNOS_NO_IFADDRS */ } - +#endif /* SUNOS_NO_IFADDRS */ void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { diff --git a/Utilities/cmlibuv/src/unix/sysinfo-loadavg.c b/Utilities/cmlibuv/src/unix/sysinfo-loadavg.c new file mode 100644 index 000000000..ebad0e89d --- /dev/null +++ b/Utilities/cmlibuv/src/unix/sysinfo-loadavg.c @@ -0,0 +1,36 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +void uv_loadavg(double avg[3]) { + struct sysinfo info; + + if (sysinfo(&info) < 0) return; + + avg[0] = (double) info.loads[0] / 65536.0; + avg[1] = (double) info.loads[1] / 65536.0; + avg[2] = (double) info.loads[2] / 65536.0; +} diff --git a/Utilities/cmlibuv/src/unix/sysinfo-memory.c b/Utilities/cmlibuv/src/unix/sysinfo-memory.c new file mode 100644 index 000000000..23b4fc6e9 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/sysinfo-memory.c @@ -0,0 +1,42 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +uint64_t uv_get_free_memory(void) { + struct sysinfo info; + + if (sysinfo(&info) == 0) + return (uint64_t) info.freeram * info.mem_unit; + return 0; +} + +uint64_t uv_get_total_memory(void) { + struct sysinfo info; + + if (sysinfo(&info) == 0) + return (uint64_t) info.totalram * info.mem_unit; + return 0; +} diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c index 52989f7f0..a9b5e4c02 100644 --- a/Utilities/cmlibuv/src/unix/thread.c +++ b/Utilities/cmlibuv/src/unix/thread.c @@ -40,28 +40,8 @@ #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) -struct thread_ctx { - void (*entry)(void* arg); - void* arg; -}; - - -static void* uv__thread_start(void *arg) -{ - struct thread_ctx *ctx_p; - struct thread_ctx ctx; - - ctx_p = arg; - ctx = *ctx_p; - uv__free(ctx_p); - ctx.entry(ctx.arg); - - return 0; -} - int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - struct thread_ctx* ctx; int err; pthread_attr_t* attr; #if defined(__APPLE__) @@ -69,13 +49,6 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { struct rlimit lim; #endif - ctx = uv__malloc(sizeof(*ctx)); - if (ctx == NULL) - return UV_ENOMEM; - - ctx->entry = entry; - ctx->arg = arg; - /* On OSX threads other than the main thread are created with a reduced stack * size by default, adjust it to RLIMIT_STACK. */ @@ -99,14 +72,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { attr = NULL; #endif - err = pthread_create(tid, attr, uv__thread_start, ctx); + err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg); if (attr != NULL) pthread_attr_destroy(attr); - if (err) - uv__free(ctx); - return -err; } diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c index 1cd492578..c556325de 100644 --- a/Utilities/cmlibuv/src/unix/udp.c +++ b/Utilities/cmlibuv/src/unix/udp.c @@ -307,7 +307,7 @@ int uv__udp_bind(uv_udp_t* handle, if (flags & UV_UDP_REUSEADDR) { err = uv__set_reuse(fd); if (err) - goto out; + return err; } if (flags & UV_UDP_IPV6ONLY) { @@ -315,11 +315,11 @@ int uv__udp_bind(uv_udp_t* handle, yes = 1; if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) { err = -errno; - goto out; + return err; } #else err = -ENOTSUP; - goto out; + return err; #endif } @@ -329,27 +329,25 @@ int uv__udp_bind(uv_udp_t* handle, /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a * socket created with AF_INET to an AF_INET6 address or vice versa. */ err = -EINVAL; - goto out; + return err; } if (addr->sa_family == AF_INET6) handle->flags |= UV_HANDLE_IPV6; handle->flags |= UV_HANDLE_BOUND; - return 0; - -out: - uv__close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; - return err; } static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain, unsigned int flags) { - unsigned char taddr[sizeof(struct sockaddr_in6)]; + union { + struct sockaddr_in6 in6; + struct sockaddr_in in; + struct sockaddr addr; + } taddr; socklen_t addrlen; if (handle->io_watcher.fd != -1) @@ -358,7 +356,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, switch (domain) { case AF_INET: { - struct sockaddr_in* addr = (void*)&taddr; + struct sockaddr_in* addr = &taddr.in; memset(addr, 0, sizeof *addr); addr->sin_family = AF_INET; addr->sin_addr.s_addr = INADDR_ANY; @@ -367,7 +365,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, } case AF_INET6: { - struct sockaddr_in6* addr = (void*)&taddr; + struct sockaddr_in6* addr = &taddr.in6; memset(addr, 0, sizeof *addr); addr->sin6_family = AF_INET6; addr->sin6_addr = in6addr_any; @@ -379,7 +377,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, abort(); } - return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, flags); + return uv__udp_bind(handle, &taddr.addr, addrlen, flags); } @@ -429,6 +427,13 @@ int uv__udp_send(uv_udp_send_t* req, if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) { uv__udp_sendmsg(handle); + + /* `uv__udp_sendmsg` may not be able to do non-blocking write straight + * away. In such cases the `io_watcher` has to be queued for asynchronous + * write. + */ + if (!QUEUE_EMPTY(&handle->write_queue)) + uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); } else { uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); } diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c index 46d954673..bc7d1379d 100644 --- a/Utilities/cmlibuv/src/uv-common.c +++ b/Utilities/cmlibuv/src/uv-common.c @@ -512,8 +512,18 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) { int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { uv__dirent_t** dents; uv__dirent_t* dent; + unsigned int* nbufs; - unsigned int* nbufs = uv__get_nbufs(req); + /* Check to see if req passed */ + if (req->result < 0) + return req->result; + + /* Ptr will be null if req was canceled or no files found */ + if (!req->ptr) + return UV_EOF; + + nbufs = uv__get_nbufs(req); + assert(nbufs); dents = req->ptr; diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h index 27902fdf8..781a8559d 100644 --- a/Utilities/cmlibuv/src/uv-common.h +++ b/Utilities/cmlibuv/src/uv-common.h @@ -55,16 +55,19 @@ extern int snprintf(char*, size_t, const char*, ...); #ifndef _WIN32 enum { + UV__SIGNAL_ONE_SHOT = 0x80000, /* On signal reception remove sighandler */ UV__HANDLE_INTERNAL = 0x8000, UV__HANDLE_ACTIVE = 0x4000, UV__HANDLE_REF = 0x2000, UV__HANDLE_CLOSING = 0 /* no-op on unix */ }; #else -# define UV__HANDLE_INTERNAL 0x80 -# define UV__HANDLE_ACTIVE 0x40 -# define UV__HANDLE_REF 0x20 -# define UV__HANDLE_CLOSING 0x01 +# define UV__SIGNAL_ONE_SHOT_DISPATCHED 0x200 +# define UV__SIGNAL_ONE_SHOT 0x100 +# define UV__HANDLE_INTERNAL 0x80 +# define UV__HANDLE_ACTIVE 0x40 +# define UV__HANDLE_REF 0x20 +# define UV__HANDLE_CLOSING 0x01 #endif int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); @@ -215,6 +218,30 @@ void uv__fs_scandir_cleanup(uv_fs_t* req); } \ while (0) +/* Note: uses an open-coded version of SET_REQ_SUCCESS() because of + * a circular dependency between src/uv-common.h and src/win/internal.h. + */ +#if defined(_WIN32) +# define UV_REQ_INIT(req, typ) \ + do { \ + (req)->type = (typ); \ + (req)->u.io.overlapped.Internal = 0; /* SET_REQ_SUCCESS() */ \ + } \ + while (0) +#else +# define UV_REQ_INIT(req, typ) \ + do { \ + (req)->type = (typ); \ + } \ + while (0) +#endif + +#define uv__req_init(loop, req, typ) \ + do { \ + UV_REQ_INIT(req, typ); \ + uv__req_register(loop, req); \ + } \ + while (0) /* Allocator prototypes */ void *uv__calloc(size_t count, size_t size); diff --git a/Utilities/cmlibuv/src/win/async.c b/Utilities/cmlibuv/src/win/async.c index ad240ab89..0b636ed1e 100644 --- a/Utilities/cmlibuv/src/win/async.c +++ b/Utilities/cmlibuv/src/win/async.c @@ -45,8 +45,7 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { handle->async_cb = async_cb; req = &handle->async_req; - uv_req_init(loop, req); - req->type = UV_WAKEUP; + UV_REQ_INIT(req, UV_WAKEUP); req->data = handle; uv__handle_start(handle); diff --git a/Utilities/cmlibuv/src/win/atomicops-inl.h b/Utilities/cmlibuv/src/win/atomicops-inl.h index 61e006026..6d8126f69 100644 --- a/Utilities/cmlibuv/src/win/atomicops-inl.h +++ b/Utilities/cmlibuv/src/win/atomicops-inl.h @@ -23,6 +23,7 @@ #define UV_WIN_ATOMICOPS_INL_H_ #include "uv.h" +#include "internal.h" /* Atomic set operation on char */ @@ -34,7 +35,7 @@ /* target to be aligned. */ #pragma intrinsic(_InterlockedOr8) -static char __declspec(inline) uv__atomic_exchange_set(char volatile* target) { +static char INLINE uv__atomic_exchange_set(char volatile* target) { return _InterlockedOr8(target, 1); } diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c index 9d00afc6b..9ed4e824c 100644 --- a/Utilities/cmlibuv/src/win/core.c +++ b/Utilities/cmlibuv/src/win/core.c @@ -35,10 +35,6 @@ #include "handle-inl.h" #include "req-inl.h" - -static uv_loop_t default_loop_struct; -static uv_loop_t* default_loop_ptr; - /* uv_once initialization guards */ static uv_once_t uv_init_guard_ = UV_ONCE_INIT; @@ -87,13 +83,8 @@ static int uv__loops_capacity; #define UV__LOOPS_CHUNK_SIZE 8 static uv_mutex_t uv__loops_lock; -static void uv__loops_init() { +static void uv__loops_init(void) { uv_mutex_init(&uv__loops_lock); - uv__loops = uv__calloc(UV__LOOPS_CHUNK_SIZE, sizeof(uv_loop_t*)); - if (!uv__loops) - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - uv__loops_size = 0; - uv__loops_capacity = UV__LOOPS_CHUNK_SIZE; } static int uv__loops_add(uv_loop_t* loop) { @@ -142,6 +133,13 @@ static void uv__loops_remove(uv_loop_t* loop) { uv__loops[uv__loops_size - 1] = NULL; --uv__loops_size; + if (uv__loops_size == 0) { + uv__loops_capacity = 0; + uv__free(uv__loops); + uv__loops = NULL; + goto loop_removed; + } + /* If we didn't grow to big skip downsizing */ if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE) goto loop_removed; @@ -160,7 +158,7 @@ loop_removed: uv_mutex_unlock(&uv__loops_lock); } -void uv__wake_all_loops() { +void uv__wake_all_loops(void) { int i; uv_loop_t* loop; @@ -336,6 +334,11 @@ int uv_backend_fd(const uv_loop_t* loop) { } +int uv_loop_fork(uv_loop_t* loop) { + return UV_ENOSYS; +} + + int uv_backend_timeout(const uv_loop_t* loop) { if (loop->stop_flag != 0) return 0; diff --git a/Utilities/cmlibuv/src/win/detect-wakeup.c b/Utilities/cmlibuv/src/win/detect-wakeup.c index a12179f79..72dfb7a17 100644 --- a/Utilities/cmlibuv/src/win/detect-wakeup.c +++ b/Utilities/cmlibuv/src/win/detect-wakeup.c @@ -2,9 +2,9 @@ #include "internal.h" #include "winapi.h" -static void uv__register_system_resume_callback(); +static void uv__register_system_resume_callback(void); -void uv__init_detect_system_wakeup() { +void uv__init_detect_system_wakeup(void) { /* Try registering system power event callback. This is the cleanest * method, but it will only work on Win8 and above. */ @@ -20,7 +20,7 @@ static ULONG CALLBACK uv__system_resume_callback(PVOID Context, return 0; } -static void uv__register_system_resume_callback() { +static void uv__register_system_resume_callback(void) { _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS recipient; _HPOWERNOTIFY registration_handle; diff --git a/Utilities/cmlibuv/src/win/error.c b/Utilities/cmlibuv/src/win/error.c index c512f35af..642d1112e 100644 --- a/Utilities/cmlibuv/src/win/error.c +++ b/Utilities/cmlibuv/src/win/error.c @@ -71,6 +71,7 @@ int uv_translate_sys_error(int sys_errno) { switch (sys_errno) { case ERROR_NOACCESS: return UV_EACCES; case WSAEACCES: return UV_EACCES; + case ERROR_ELEVATION_REQUIRED: return UV_EACCES; case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE; case WSAEADDRINUSE: return UV_EADDRINUSE; case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL; diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c index 03e4adc05..95f843ad0 100644 --- a/Utilities/cmlibuv/src/win/fs-event.c +++ b/Utilities/cmlibuv/src/win/fs-event.c @@ -81,8 +81,17 @@ static void uv_relative_path(const WCHAR* filename, static int uv_split_path(const WCHAR* filename, WCHAR** dir, WCHAR** file) { - int len = wcslen(filename); - int i = len; + size_t len, i; + + if (filename == NULL) { + if (dir != NULL) + *dir = NULL; + *file = NULL; + return 0; + } + + len = wcslen(filename); + i = len; while (i > 0 && filename[--i] != '\\' && filename[i] != '/'); if (i == 0) { @@ -131,8 +140,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { handle->short_filew = NULL; handle->dirw = NULL; - uv_req_init(loop, (uv_req_t*)&handle->req); - handle->req.type = UV_FS_EVENT_REQ; + UV_REQ_INIT(&handle->req, UV_FS_EVENT_REQ); handle->req.data = handle; return 0; @@ -146,7 +154,8 @@ int uv_fs_event_start(uv_fs_event_t* handle, int name_size, is_path_dir; DWORD attr, last_error; WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL; - WCHAR short_path[MAX_PATH]; + WCHAR short_path_buffer[MAX_PATH]; + WCHAR* short_path; if (uv__is_active(handle)) return UV_EINVAL; @@ -188,7 +197,6 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (is_path_dir) { /* path is a directory, so that's the directory that we will watch. */ - handle->dirw = pathw; dir_to_watch = pathw; } else { /* @@ -197,9 +205,9 @@ int uv_fs_event_start(uv_fs_event_t* handle, */ /* Convert to short path. */ + short_path = short_path_buffer; if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) { - last_error = GetLastError(); - goto error; + short_path = NULL; } if (uv_split_path(pathw, &dir, &handle->filew) != 0) { @@ -274,6 +282,8 @@ int uv_fs_event_start(uv_fs_event_t* handle, goto error; } + assert(is_path_dir ? pathw != NULL : pathw == NULL); + handle->dirw = pathw; handle->req_pending = 1; return 0; @@ -305,6 +315,9 @@ error: handle->buffer = NULL; } + if (uv__is_active(handle)) + uv__handle_stop(handle); + return uv_translate_sys_error(last_error); } @@ -344,8 +357,11 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { } -static int file_info_cmp(WCHAR* str, WCHAR* file_name, int file_name_len) { - int str_len; +static int file_info_cmp(WCHAR* str, WCHAR* file_name, size_t file_name_len) { + size_t str_len; + + if (str == NULL) + return -1; str_len = wcslen(str); diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c index f1711acf1..2d72cdc70 100644 --- a/Utilities/cmlibuv/src/win/fs.c +++ b/Utilities/cmlibuv/src/win/fs.c @@ -114,7 +114,7 @@ const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\"; const WCHAR UNC_PATH_PREFIX_LEN = 8; -void uv_fs_init() { +void uv_fs_init(void) { _fmode = _O_BINARY; } @@ -123,7 +123,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, const char* new_path, const int copy_path) { char* buf; char* pos; - ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0; + ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0; /* new_path can only be set if path is also set. */ assert(new_path == NULL || path != NULL); @@ -220,9 +220,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, uv_fs_type fs_type, const uv_fs_cb cb) { - uv_req_init(loop, (uv_req_t*) req); - - req->type = UV_FS; + UV_REQ_INIT(req, UV_FS); req->loop = loop; req->flags = 0; req->fs_type = fs_type; @@ -403,7 +401,6 @@ void fs__open(uv_fs_t* req) { switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { case _O_RDONLY: access = FILE_GENERIC_READ; - attributes |= FILE_FLAG_BACKUP_SEMANTICS; break; case _O_WRONLY: access = FILE_GENERIC_WRITE; @@ -418,7 +415,6 @@ void fs__open(uv_fs_t* req) { if (flags & _O_APPEND) { access &= ~FILE_WRITE_DATA; access |= FILE_APPEND_DATA; - attributes &= ~FILE_FLAG_BACKUP_SEMANTICS; } /* @@ -1375,7 +1371,7 @@ static void fs__access(uv_fs_t* req) { * - or it's a directory. * (Directories cannot be read-only on Windows.) */ - if (!(req->flags & W_OK) || + if (!(req->fs.info.mode & W_OK) || !(attr & FILE_ATTRIBUTE_READONLY) || (attr & FILE_ATTRIBUTE_DIRECTORY)) { SET_REQ_RESULT(req, 0); @@ -2402,7 +2398,7 @@ int uv_fs_access(uv_loop_t* loop, if (err) return uv_translate_sys_error(err); - req->flags = flags; + req->fs.info.mode = flags; if (cb) { QUEUE_FS_TP_JOB(loop, req); diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c index 744f8e026..baab83889 100644 --- a/Utilities/cmlibuv/src/win/getaddrinfo.c +++ b/Utilities/cmlibuv/src/win/getaddrinfo.c @@ -262,15 +262,12 @@ int uv_getaddrinfo(uv_loop_t* loop, int err; if (req == NULL || (node == NULL && service == NULL)) { - err = WSAEINVAL; - goto error; + return UV_EINVAL; } - uv_req_init(loop, (uv_req_t*)req); - + UV_REQ_INIT(req, UV_GETADDRINFO); req->getaddrinfo_cb = getaddrinfo_cb; req->addrinfo = NULL; - req->type = UV_GETADDRINFO; req->loop = loop; req->retcode = 0; diff --git a/Utilities/cmlibuv/src/win/getnameinfo.c b/Utilities/cmlibuv/src/win/getnameinfo.c index 66b64b883..9f10cd2a5 100644 --- a/Utilities/cmlibuv/src/win/getnameinfo.c +++ b/Utilities/cmlibuv/src/win/getnameinfo.c @@ -127,12 +127,11 @@ int uv_getnameinfo(uv_loop_t* loop, return UV_EINVAL; } - uv_req_init(loop, (uv_req_t*)req); + UV_REQ_INIT(req, UV_GETNAMEINFO); uv__req_register(loop, req); req->getnameinfo_cb = getnameinfo_cb; req->flags = flags; - req->type = UV_GETNAMEINFO; req->loop = loop; req->retcode = 0; diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h index 8a17e9462..83601d57a 100644 --- a/Utilities/cmlibuv/src/win/internal.h +++ b/Utilities/cmlibuv/src/win/internal.h @@ -210,7 +210,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle); /* * TTY */ -void uv_console_init(); +void uv_console_init(void); int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb); @@ -263,7 +263,7 @@ void uv_prepare_invoke(uv_loop_t* loop); void uv_check_invoke(uv_loop_t* loop); void uv_idle_invoke(uv_loop_t* loop); -void uv__once_init(); +void uv__once_init(void); /* @@ -279,7 +279,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, /* * Signal watcher */ -void uv_signals_init(); +void uv_signals_init(void); int uv__signal_dispatch(int signum); void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle); @@ -306,7 +306,7 @@ int uv_translate_sys_error(int sys_errno); /* * FS */ -void uv_fs_init(); +void uv_fs_init(void); /* @@ -327,14 +327,15 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle); /* * Utilities. */ -void uv__util_init(); +void uv__util_init(void); uint64_t uv__hrtime(double scale); -int uv_parent_pid(); -int uv_current_pid(); +int uv_parent_pid(void); +int uv_current_pid(void); __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); int uv__getpwuid_r(uv_passwd_t* pwd); int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8); +int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16); /* @@ -353,13 +354,13 @@ HANDLE uv__stdio_handle(BYTE* buffer, int fd); /* * Winapi and ntapi utility functions */ -void uv_winapi_init(); +void uv_winapi_init(void); /* * Winsock utility functions */ -void uv_winsock_init(); +void uv_winsock_init(void); int uv_ntstatus_to_winsock_error(NTSTATUS status); @@ -388,11 +389,11 @@ extern struct sockaddr_in6 uv_addr_ip6_any_; /* * Wake all loops with fake message */ -void uv__wake_all_loops(); +void uv__wake_all_loops(void); /* * Init system wake-up detection */ -void uv__init_detect_system_wakeup(); +void uv__init_detect_system_wakeup(void); #endif /* UV_WIN_INTERNAL_H_ */ diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c index 2442be730..edf300212 100644 --- a/Utilities/cmlibuv/src/win/pipe.c +++ b/Utilities/cmlibuv/src/win/pipe.c @@ -103,7 +103,7 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { handle->pipe.conn.non_overlapped_writes_tail = NULL; handle->pipe.conn.readfile_thread = NULL; - uv_req_init(loop, (uv_req_t*) &handle->pipe.conn.ipc_header_write_req); + UV_REQ_INIT(&handle->pipe.conn.ipc_header_write_req, UV_UNKNOWN_REQ); return 0; } @@ -505,8 +505,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { for (i = 0; i < handle->pipe.serv.pending_instances; i++) { req = &handle->pipe.serv.accept_reqs[i]; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_ACCEPT; + UV_REQ_INIT(req, UV_ACCEPT); req->data = handle; req->pipeHandle = INVALID_HANDLE_VALUE; req->next_pending = NULL; @@ -626,8 +625,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, HANDLE pipeHandle = INVALID_HANDLE_VALUE; DWORD duplex_flags; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_CONNECT; + UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; @@ -962,7 +960,7 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */ if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hThread, - 0, TRUE, DUPLICATE_SAME_ACCESS)) { + 0, FALSE, DUPLICATE_SAME_ACCESS)) { handle->pipe.conn.readfile_thread = hThread; } else { hThread = NULL; @@ -1239,8 +1237,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, assert(handle->handle != INVALID_HANDLE_VALUE); - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; + UV_REQ_INIT(req, UV_WRITE); req->handle = (uv_stream_t*) handle; req->cb = cb; req->ipc_header = 0; @@ -1301,8 +1298,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } } - uv_req_init(loop, (uv_req_t*) ipc_header_req); - ipc_header_req->type = UV_WRITE; + UV_REQ_INIT(ipc_header_req, UV_WRITE); ipc_header_req->handle = (uv_stream_t*) handle; ipc_header_req->cb = NULL; ipc_header_req->ipc_header = 1; @@ -2076,7 +2072,6 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) buffer[addrlen] = '\0'; err = 0; - goto cleanup; error: uv__free(name_info); diff --git a/Utilities/cmlibuv/src/win/poll.c b/Utilities/cmlibuv/src/win/poll.c index d479e521e..a648ba711 100644 --- a/Utilities/cmlibuv/src/win/poll.c +++ b/Utilities/cmlibuv/src/win/poll.c @@ -61,13 +61,13 @@ static void uv__init_overlapped_dummy(void) { } -static OVERLAPPED* uv__get_overlapped_dummy() { +static OVERLAPPED* uv__get_overlapped_dummy(void) { uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy); return &overlapped_dummy_; } -static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() { +static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) { return &afd_poll_info_dummy_; } @@ -572,13 +572,11 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, /* Initialize 2 poll reqs. */ handle->submitted_events_1 = 0; - uv_req_init(loop, (uv_req_t*) &(handle->poll_req_1)); - handle->poll_req_1.type = UV_POLL_REQ; + UV_REQ_INIT(&handle->poll_req_1, UV_POLL_REQ); handle->poll_req_1.data = handle; handle->submitted_events_2 = 0; - uv_req_init(loop, (uv_req_t*) &(handle->poll_req_2)); - handle->poll_req_2.type = UV_POLL_REQ; + UV_REQ_INIT(&handle->poll_req_2, UV_POLL_REQ); handle->poll_req_2.data = handle; return 0; diff --git a/Utilities/cmlibuv/src/win/process-stdio.c b/Utilities/cmlibuv/src/win/process-stdio.c index e3c06f57d..032e30935 100644 --- a/Utilities/cmlibuv/src/win/process-stdio.c +++ b/Utilities/cmlibuv/src/win/process-stdio.c @@ -372,6 +372,7 @@ int uv__stdio_create(uv_loop_t* loop, case FILE_TYPE_PIPE: CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; + break; case FILE_TYPE_CHAR: case FILE_TYPE_REMOTE: diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c index 855c37408..d14160160 100644 --- a/Utilities/cmlibuv/src/win/process.c +++ b/Utilities/cmlibuv/src/win/process.c @@ -148,8 +148,7 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) { handle->child_stdio_buffer = NULL; handle->exit_cb_pending = 0; - uv_req_init(loop, (uv_req_t*)&handle->exit_req); - handle->exit_req.type = UV_PROCESS_EXIT; + UV_REQ_INIT(&handle->exit_req, UV_PROCESS_EXIT); handle->exit_req.data = handle; } @@ -492,7 +491,7 @@ WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) { * input : hello\\"world * output: "hello\\\\\"world" * input : hello world\ - * output: "hello world\" + * output: "hello world\\" */ *(target++) = L'"'; diff --git a/Utilities/cmlibuv/src/win/req-inl.h b/Utilities/cmlibuv/src/win/req-inl.h index b5e502eef..f2513b7d3 100644 --- a/Utilities/cmlibuv/src/win/req-inl.h +++ b/Utilities/cmlibuv/src/win/req-inl.h @@ -34,6 +34,9 @@ #define SET_REQ_ERROR(req, error) \ SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error))) +/* Note: used open-coded in UV_REQ_INIT() because of a circular dependency + * between src/uv-common.h and src/win/internal.h. + */ #define SET_REQ_SUCCESS(req) \ SET_REQ_STATUS((req), STATUS_SUCCESS) @@ -79,12 +82,6 @@ } -INLINE static void uv_req_init(uv_loop_t* loop, uv_req_t* req) { - req->type = UV_UNKNOWN_REQ; - SET_REQ_SUCCESS(req); -} - - INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped); } diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c index 2c64a55dc..7b42dd992 100644 --- a/Utilities/cmlibuv/src/win/signal.c +++ b/Utilities/cmlibuv/src/win/signal.c @@ -30,12 +30,19 @@ RB_HEAD(uv_signal_tree_s, uv_signal_s); static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); -static ssize_t volatile uv__signal_control_handler_refs = 0; static CRITICAL_SECTION uv__signal_lock; +static BOOL WINAPI uv__signal_control_handler(DWORD type); -void uv_signals_init() { +int uv__signal_start(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum, + int oneshot); + +void uv_signals_init(void) { InitializeCriticalSection(&uv__signal_lock); + if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) + abort(); } @@ -68,7 +75,9 @@ RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare int uv__signal_dispatch(int signum) { uv_signal_t lookup; uv_signal_t* handle; - int dispatched = 0; + int dispatched; + + dispatched = 0; EnterCriticalSection(&uv__signal_lock); @@ -81,11 +90,16 @@ int uv__signal_dispatch(int signum) { unsigned long previous = InterlockedExchange( (volatile LONG*) &handle->pending_signum, signum); + if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED) + continue; + if (!previous) { POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req); } dispatched = 1; + if (handle->flags & UV__SIGNAL_ONE_SHOT) + handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED; } LeaveCriticalSection(&uv__signal_lock); @@ -125,114 +139,14 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) { } -static int uv__signal_register_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - - /* If the console control handler has already been hooked, just add a */ - /* reference. */ - if (uv__signal_control_handler_refs > 0) { - uv__signal_control_handler_refs++; - return 0; - } - - if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) - return GetLastError(); - - uv__signal_control_handler_refs++; - - return 0; -} - - -static void uv__signal_unregister_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - BOOL r; - - /* Don't unregister if the number of console control handlers exceeds one. */ - /* Just remove a reference in that case. */ - if (uv__signal_control_handler_refs > 1) { - uv__signal_control_handler_refs--; - return; - } - - assert(uv__signal_control_handler_refs == 1); - - r = SetConsoleCtrlHandler(uv__signal_control_handler, FALSE); - /* This should never fail; if it does it is probably a bug in libuv. */ - assert(r); - - uv__signal_control_handler_refs--; -} - - -static int uv__signal_register(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - return uv__signal_register_control_handler(); - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to register anything. */ - return 0; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Signal is never raised. */ - return 0; - - default: - /* Invalid signal. */ - return ERROR_INVALID_PARAMETER; - } -} - - -static void uv__signal_unregister(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - uv__signal_unregister_control_handler(); - return; - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to unregister anything. */ - return; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Nothing is registered for this signal. */ - return; - - default: - /* Libuv bug. */ - assert(0 && "Invalid signum"); - return; - } -} - - int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { - uv_req_t* req; - uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL); handle->pending_signum = 0; handle->signum = 0; handle->signal_cb = NULL; - req = &handle->signal_req; - uv_req_init(loop, req); - req->type = UV_SIGNAL_REQ; - req->data = handle; + UV_REQ_INIT(&handle->signal_req, UV_SIGNAL_REQ); + handle->signal_req.data = handle; return 0; } @@ -247,8 +161,6 @@ int uv_signal_stop(uv_signal_t* handle) { EnterCriticalSection(&uv__signal_lock); - uv__signal_unregister(handle->signum); - removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle); assert(removed_handle == handle); @@ -262,14 +174,24 @@ int uv_signal_stop(uv_signal_t* handle) { int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { - int err; + return uv__signal_start(handle, signal_cb, signum, 0); +} + + +int uv_signal_start_oneshot(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum) { + return uv__signal_start(handle, signal_cb, signum, 1); +} - /* If the user supplies signum == 0, then return an error already. If the */ - /* signum is otherwise invalid then uv__signal_register will find out */ - /* eventually. */ - if (signum == 0) { + +int uv__signal_start(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum, + int oneshot) { + /* Test for invalid signal values. */ + if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG)) return UV_EINVAL; - } /* Short circuit: if the signal watcher is already watching {signum} don't */ /* go through the process of deregistering and registering the handler. */ @@ -289,14 +211,10 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { EnterCriticalSection(&uv__signal_lock); - err = uv__signal_register(signum); - if (err) { - /* Uh-oh, didn't work. */ - LeaveCriticalSection(&uv__signal_lock); - return uv_translate_sys_error(err); - } - handle->signum = signum; + if (oneshot) + handle->flags |= UV__SIGNAL_ONE_SHOT; + RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle); LeaveCriticalSection(&uv__signal_lock); @@ -325,6 +243,9 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, if (dispatched_signum == handle->signum) handle->signal_cb(handle, dispatched_signum); + if (handle->flags & UV__SIGNAL_ONE_SHOT) + uv_signal_stop(handle); + if (handle->flags & UV__HANDLE_CLOSING) { /* When it is closing, it must be stopped at this point. */ assert(handle->signum == 0); diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h index b7a3c1195..bf12148af 100644 --- a/Utilities/cmlibuv/src/win/stream-inl.h +++ b/Utilities/cmlibuv/src/win/stream-inl.h @@ -43,10 +43,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) { handle->flags |= UV_HANDLE_CONNECTION; handle->stream.conn.write_reqs_pending = 0; - uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req)); + UV_REQ_INIT(&handle->read_req, UV_READ); handle->read_req.event_handle = NULL; handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - handle->read_req.type = UV_READ; handle->read_req.data = handle; handle->stream.conn.shutdown_req = NULL; diff --git a/Utilities/cmlibuv/src/win/stream.c b/Utilities/cmlibuv/src/win/stream.c index a2466e5e9..13cbfdcb9 100644 --- a/Utilities/cmlibuv/src/win/stream.c +++ b/Utilities/cmlibuv/src/win/stream.c @@ -210,8 +210,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { return UV_EPIPE; } - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_SHUTDOWN; + UV_REQ_INIT(req, UV_SHUTDOWN); req->handle = handle; req->cb = cb; diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c index 0709696ff..972539f4d 100644 --- a/Utilities/cmlibuv/src/win/tcp.c +++ b/Utilities/cmlibuv/src/win/tcp.c @@ -555,7 +555,6 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { - uv_loop_t* loop = handle->loop; unsigned int i, simultaneous_accepts; uv_tcp_accept_t* req; int err; @@ -612,8 +611,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { for (i = 0; i < simultaneous_accepts; i++) { req = &handle->tcp.serv.accept_reqs[i]; - uv_req_init(loop, (uv_req_t*)req); - req->type = UV_ACCEPT; + UV_REQ_INIT(req, UV_ACCEPT); req->accept_socket = INVALID_SOCKET; req->data = handle; @@ -635,8 +633,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { /* try to clean up {uv_simultaneous_server_accepts} requests. */ for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) { req = &handle->tcp.serv.accept_reqs[i]; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_ACCEPT; + UV_REQ_INIT(req, UV_ACCEPT); req->accept_socket = INVALID_SOCKET; req->data = handle; req->wait_handle = INVALID_HANDLE_VALUE; @@ -779,8 +776,7 @@ static int uv_tcp_try_connect(uv_connect_t* req, } } - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_CONNECT; + UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); @@ -863,8 +859,7 @@ int uv_tcp_write(uv_loop_t* loop, int result; DWORD bytes; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; + UV_REQ_INIT(req, UV_WRITE); req->handle = (uv_stream_t*) handle; req->cb = cb; diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c index 18d68d094..a6f583956 100644 --- a/Utilities/cmlibuv/src/win/tty.c +++ b/Utilities/cmlibuv/src/win/tty.c @@ -56,6 +56,7 @@ #define ANSI_BACKSLASH_SEEN 0x80 #define MAX_INPUT_BUFFER_LENGTH 8192 +#define MAX_CONSOLE_CHAR 8192 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 @@ -137,7 +138,7 @@ typedef enum { static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED; static void uv__determine_vterm_state(HANDLE handle); -void uv_console_init() { +void uv_console_init(void) { if (uv_sem_init(&uv_tty_output_lock, 1)) abort(); } @@ -1003,6 +1004,9 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, if (handle->tty.rd.last_key_len > 0) { SET_REQ_SUCCESS(&handle->read_req); uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); + /* Make sure no attempt is made to insert it again until it's handled. */ + handle->flags |= UV_HANDLE_READ_PENDING; + handle->reqs_pending++; return 0; } @@ -1616,17 +1620,29 @@ static int uv_tty_write_bufs(uv_tty_t* handle, DWORD* error) { /* We can only write 8k characters at a time. Windows can't handle */ /* much more characters in a single console write anyway. */ - WCHAR utf16_buf[8192]; + WCHAR utf16_buf[MAX_CONSOLE_CHAR]; + WCHAR* utf16_buffer; DWORD utf16_buf_used = 0; - unsigned int i; - -#define FLUSH_TEXT() \ - do { \ - if (utf16_buf_used > 0) { \ - uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \ - utf16_buf_used = 0; \ - } \ - } while (0) + unsigned int i, len, max_len, pos; + int allocate = 0; + +#define FLUSH_TEXT() \ + do { \ + pos = 0; \ + do { \ + len = utf16_buf_used - pos; \ + if (len > MAX_CONSOLE_CHAR) \ + len = MAX_CONSOLE_CHAR; \ + uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \ + pos += len; \ + } while (pos < utf16_buf_used); \ + if (allocate) { \ + uv__free(utf16_buffer); \ + allocate = 0; \ + utf16_buffer = utf16_buf; \ + } \ + utf16_buf_used = 0; \ + } while (0) #define ENSURE_BUFFER_SPACE(wchars_needed) \ if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \ @@ -1644,38 +1660,47 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* state. */ *error = ERROR_SUCCESS; + utf16_buffer = utf16_buf; + uv_sem_wait(&uv_tty_output_lock); for (i = 0; i < nbufs; i++) { uv_buf_t buf = bufs[i]; unsigned int j; - if (uv__vterm_state == UV_SUPPORTED) { - utf16_buf_used = MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - NULL, - 0); + if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) { + utf16_buf_used = MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + NULL, + 0); + + if (utf16_buf_used == 0) { + *error = GetLastError(); + break; + } - if (utf16_buf_used == 0) { - *error = GetLastError(); - break; - } + max_len = (utf16_buf_used + 1) * sizeof(WCHAR); + allocate = max_len > MAX_CONSOLE_CHAR; + if (allocate) + utf16_buffer = uv__malloc(max_len); + if (!MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + utf16_buffer, + utf16_buf_used)) { + if (allocate) + uv__free(utf16_buffer); + *error = GetLastError(); + break; + } - if (!MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - utf16_buf, - utf16_buf_used)) { - *error = GetLastError(); - break; - } + FLUSH_TEXT(); - FLUSH_TEXT(); - continue; - } + continue; + } for (j = 0; j < buf.len; j++) { unsigned char c = buf.base[j]; @@ -2101,8 +2126,7 @@ int uv_tty_write(uv_loop_t* loop, uv_write_cb cb) { DWORD error; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; + UV_REQ_INIT(req, UV_WRITE); req->handle = (uv_stream_t*) handle; req->cb = cb; diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c index 9bf1453e5..2fd15cfa9 100644 --- a/Utilities/cmlibuv/src/win/udp.c +++ b/Utilities/cmlibuv/src/win/udp.c @@ -142,8 +142,7 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { handle->func_wsarecvfrom = WSARecvFrom; handle->send_queue_size = 0; handle->send_queue_count = 0; - uv_req_init(loop, (uv_req_t*) &(handle->recv_req)); - handle->recv_req.type = UV_UDP_RECV; + UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV); handle->recv_req.data = handle; /* If anything fails beyond this point we need to remove the handle from @@ -417,8 +416,7 @@ static int uv__send(uv_udp_send_t* req, uv_loop_t* loop = handle->loop; DWORD result, bytes; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_UDP_SEND; + UV_REQ_INIT(req, UV_UDP_SEND); req->handle = handle; req->cb = cb; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c index 050058afa..d2e7f772c 100644 --- a/Utilities/cmlibuv/src/win/util.c +++ b/Utilities/cmlibuv/src/win/util.c @@ -59,6 +59,17 @@ # define UNLEN 256 #endif +/* + Max hostname length. The Windows gethostname() documentation states that 256 + bytes will always be large enough to hold the null-terminated hostname. +*/ +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +/* Maximum environment variable size, including the terminating null */ +#define MAX_ENV_VAR_LENGTH 32767 + /* Cached copy of the process title, plus a mutex guarding it. */ static char *process_title; static CRITICAL_SECTION process_title_lock; @@ -74,7 +85,7 @@ static double hrtime_interval_ = 0; /* * One-time initialization code for functionality defined in util.c. */ -void uv__util_init() { +void uv__util_init(void) { LARGE_INTEGER perf_frequency; /* Initialize process title access mutex. */ @@ -320,7 +331,7 @@ uint64_t uv_get_total_memory(void) { } -int uv_parent_pid() { +int uv_parent_pid(void) { int parent_pid = -1; HANDLE handle; PROCESSENTRY32 pe; @@ -343,7 +354,7 @@ int uv_parent_pid() { } -int uv_current_pid() { +int uv_current_pid(void) { if (current_pid == 0) { current_pid = GetCurrentProcessId(); } @@ -405,7 +416,7 @@ done: } -static int uv__get_process_title() { +static int uv__get_process_title(void) { WCHAR title_w[MAX_TITLE_LENGTH]; if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) { @@ -1322,6 +1333,47 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) { } +/* + * Converts a UTF-8 string into a UTF-16 one. The resulting string is + * null-terminated. + * + * If utf8 is null terminated, utf8len can be set to -1, otherwise it must + * be specified. + */ +int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) { + int bufsize; + + if (utf8 == NULL) + return UV_EINVAL; + + /* Check how much space we need */ + bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0); + + if (bufsize == 0) + return uv_translate_sys_error(GetLastError()); + + /* Allocate the destination buffer adding an extra byte for the terminating + * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so + * we do it ourselves always, just in case. */ + *utf16 = uv__malloc(sizeof(WCHAR) * (bufsize + 1)); + + if (*utf16 == NULL) + return UV_ENOMEM; + + /* Convert to UTF-16 */ + bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize); + + if (bufsize == 0) { + uv__free(*utf16); + *utf16 = NULL; + return uv_translate_sys_error(GetLastError()); + } + + (*utf16)[bufsize] = '\0'; + return 0; +} + + int uv__getpwuid_r(uv_passwd_t* pwd) { HANDLE token; wchar_t username[UNLEN + 1]; @@ -1387,3 +1439,138 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { int uv_os_get_passwd(uv_passwd_t* pwd) { return uv__getpwuid_r(pwd); } + + +int uv_os_getenv(const char* name, char* buffer, size_t* size) { + wchar_t var[MAX_ENV_VAR_LENGTH]; + wchar_t* name_w; + DWORD bufsize; + size_t len; + int r; + + if (name == NULL || buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + + r = uv__convert_utf8_to_utf16(name, -1, &name_w); + + if (r != 0) + return r; + + len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH); + uv__free(name_w); + assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */ + + if (len == 0) { + r = GetLastError(); + + if (r == ERROR_ENVVAR_NOT_FOUND) + return UV_ENOENT; + + return uv_translate_sys_error(r); + } + + /* Check how much space we need */ + bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL); + + if (bufsize == 0) { + return uv_translate_sys_error(GetLastError()); + } else if (bufsize > *size) { + *size = bufsize; + return UV_ENOBUFS; + } + + /* Convert to UTF-8 */ + bufsize = WideCharToMultiByte(CP_UTF8, + 0, + var, + -1, + buffer, + *size, + NULL, + NULL); + + if (bufsize == 0) + return uv_translate_sys_error(GetLastError()); + + *size = bufsize - 1; + return 0; +} + + +int uv_os_setenv(const char* name, const char* value) { + wchar_t* name_w; + wchar_t* value_w; + int r; + + if (name == NULL || value == NULL) + return UV_EINVAL; + + r = uv__convert_utf8_to_utf16(name, -1, &name_w); + + if (r != 0) + return r; + + r = uv__convert_utf8_to_utf16(value, -1, &value_w); + + if (r != 0) { + uv__free(name_w); + return r; + } + + r = SetEnvironmentVariableW(name_w, value_w); + uv__free(name_w); + uv__free(value_w); + + if (r == 0) + return uv_translate_sys_error(GetLastError()); + + return 0; +} + + +int uv_os_unsetenv(const char* name) { + wchar_t* name_w; + int r; + + if (name == NULL) + return UV_EINVAL; + + r = uv__convert_utf8_to_utf16(name, -1, &name_w); + + if (r != 0) + return r; + + r = SetEnvironmentVariableW(name_w, NULL); + uv__free(name_w); + + if (r == 0) + return uv_translate_sys_error(GetLastError()); + + return 0; +} + + +int uv_os_gethostname(char* buffer, size_t* size) { + char buf[MAXHOSTNAMELEN + 1]; + size_t len; + + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + + uv__once_init(); /* Initialize winsock */ + + if (gethostname(buf, sizeof(buf)) != 0) + return uv_translate_sys_error(WSAGetLastError()); + + buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */ + len = strlen(buf); + + if (len >= *size) { + *size = len + 1; + return UV_ENOBUFS; + } + + memcpy(buffer, buf, len + 1); + *size = len; + return 0; +} diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c index 1fa179b57..aa5d719fb 100644 --- a/Utilities/cmlibuv/src/win/winapi.c +++ b/Utilities/cmlibuv/src/win/winapi.c @@ -53,7 +53,7 @@ sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; -void uv_winapi_init() { +void uv_winapi_init(void) { HMODULE ntdll_module; HMODULE kernel32_module; HMODULE powrprof_module; diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h index 597a93d76..4b0eeca15 100644 --- a/Utilities/cmlibuv/src/win/winapi.h +++ b/Utilities/cmlibuv/src/win/winapi.h @@ -4615,6 +4615,10 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) #endif /* from winerror.h */ +#ifndef ERROR_ELEVATION_REQUIRED +# define ERROR_ELEVATION_REQUIRED 740 +#endif + #ifndef ERROR_SYMLINK_NOT_SUPPORTED # define ERROR_SYMLINK_NOT_SUPPORTED 1464 #endif diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c index d2e667e9f..e86d76b13 100644 --- a/Utilities/cmlibuv/src/win/winsock.c +++ b/Utilities/cmlibuv/src/win/winsock.c @@ -80,7 +80,7 @@ static int error_means_no_support(DWORD error) { } -void uv_winsock_init() { +void uv_winsock_init(void) { WSADATA wsa_data; int errorno; SOCKET dummy; diff --git a/bootstrap b/bootstrap index 8063edb19..84df54a00 100755 --- a/bootstrap +++ b/bootstrap @@ -6,6 +6,17 @@ die() { echo "$@" 1>&2 ; exit 1 } +# Compile flag extraction function. +cmake_extract_standard_flags() +{ + cd "${cmake_source_dir}/Modules/Compiler/" + for file in ${1:-*}-${2}.cmake; do + cat "${file}" \ + | sed -n "s/ *set *( *CMAKE_${2}${3}_EXTENSION_COMPILE_OPTION *\"\{0,1\}\([^\")]*\).*/\1/p" \ + | tr ';' ' ' + done +} + # Version number extraction function. cmake_version_component() { @@ -255,8 +266,6 @@ CMAKE_CXX_SOURCES="\ cmCPackPropertiesGenerator \ cmCacheManager \ cmCommand \ - cmCommandArgumentLexer \ - cmCommandArgumentParser \ cmCommandArgumentParserHelper \ cmCommandArgumentsHelper \ cmCommands \ @@ -276,6 +285,7 @@ CMAKE_CXX_SOURCES="\ cmDefinitions \ cmDepends \ cmDependsC \ + cmDisallowedCommand \ cmDocumentationFormatter \ cmEnableLanguageCommand \ cmEnableTestingCommand \ @@ -288,8 +298,6 @@ CMAKE_CXX_SOURCES="\ cmExportSet \ cmExportSetMap \ cmExportTryCompileFileGenerator \ - cmExprLexer \ - cmExprParser \ cmExprParserHelper \ cmExternalMakefileProjectGenerator \ cmFileCommand \ @@ -404,6 +412,7 @@ CMAKE_CXX_SOURCES="\ cmUnsetCommand \ cmVersion \ cmWhileCommand \ + cmWorkingDirectory \ cmake \ cmakemain \ cmcmd \ @@ -415,9 +424,16 @@ if ${cmake_system_mingw}; then cmGlobalMinGWMakefileGenerator" fi -CMAKE_C_SOURCES="\ +LexerParser_CXX_SOURCES="\ + cmCommandArgumentLexer \ + cmCommandArgumentParser \ + cmExprLexer \ + cmExprParser \ +" + +LexerParser_C_SOURCES="\ cmListFileLexer \ - " +" if ${cmake_system_mingw}; then KWSYS_C_SOURCES="\ @@ -855,7 +871,7 @@ cmake_toolchains='' case "${cmake_system}" in *AIX*) cmake_toolchains='XL GNU' ;; *CYGWIN*) cmake_toolchains='GNU' ;; - *Darwin*) cmake_toolchains='GNU Clang' ;; + *Darwin*) cmake_toolchains='Clang GNU' ;; *Linux*) cmake_toolchains='GNU Clang XL PGI PathScale' ;; *MINGW*) cmake_toolchains='GNU' ;; esac @@ -949,6 +965,17 @@ for a in ${cmake_c_compilers}; do cmake_c_compiler="${a}" fi done +for std in 11 99 90; do + try_flags="`cmake_extract_standard_flags \"${cmake_toolchain}\" C \"${std}\"`" + for flag in $try_flags; do + echo "Checking whether ${cmake_c_compiler} supports ${flag}" >> cmake_bootstrap.log 2>&1 + if cmake_try_run "${cmake_c_compiler}" "${cmake_c_flags} ${flag}" \ + "${TMPFILE}.c" >> cmake_bootstrap.log 2>&1; then + cmake_c_flags="${cmake_c_flags} ${flag}" + break 2 + fi + done +done rm -f "${TMPFILE}.c" if [ -z "${cmake_c_compiler}" ]; then @@ -983,6 +1010,10 @@ echo ' # include #endif +#if __cplusplus >= 201103L && defined(__SUNPRO_CC) && __SUNPRO_CC < 0x5140 +#error "SunPro <= 5.13 C++ 11 mode not supported due to bug in move semantics." +#endif + class NeedCXX { public: @@ -1010,6 +1041,17 @@ for a in ${cmake_cxx_compilers}; do fi done done +for std in 14 11 98; do + try_flags="`cmake_extract_standard_flags \"${cmake_toolchain}\" CXX \"${std}\"`" + for flag in $try_flags; do + echo "Checking for wheter ${cmake_cxx_flags} supports ${flag}" >> cmake_bootstrap.log 2>&1 + if cmake_try_run "${cmake_cxx_compiler}" "${cmake_cxx_flags} ${flag} -DTEST1" \ + "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then + cmake_cxx_flags="${cmake_cxx_flags} ${flag} " + break 2 + fi + done +done rm -f "${TMPFILE}.cxx" if [ -z "${cmake_cxx_compiler}" ]; then @@ -1106,84 +1148,6 @@ rm -f "${TMPFILE}.cxx" if [ "x${cmake_cxx_compiler_is_gnu}" != "x1" ]; then # Check for non-GNU compiler flags - # If we are on IRIX, check for -LANG:std - cmake_test_flags="-LANG:std" - if [ "x${cmake_system}" = "xIRIX64" ]; then - TMPFILE=`cmake_tmp_file` - echo ' - #include - int main() { std::cout << "No need for '"${cmake_test_flags}"'" << std::endl; return 0;} -' > ${TMPFILE}.cxx - cmake_need_lang_std=0 - if cmake_try_run "${cmake_cxx_compiler}" \ - "${cmake_cxx_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then - : - else - if cmake_try_run "${cmake_cxx_compiler}" \ - "${cmake_cxx_flags} ${cmake_test_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then - cmake_need_lang_std=1 - fi - fi - if [ "x${cmake_need_lang_std}" = "x1" ]; then - cmake_cxx_flags="${cmake_cxx_flags} ${cmake_test_flags}" - echo "${cmake_cxx_compiler} needs ${cmake_test_flags}" - else - echo "${cmake_cxx_compiler} does not need ${cmake_test_flags}" - fi - rm -f "${TMPFILE}.cxx" - fi - cmake_test_flags= - - # If we are on OSF, check for -timplicit_local -no_implicit_include - cmake_test_flags="-timplicit_local -no_implicit_include" - if [ "x${cmake_system}" = "xOSF1" ]; then - TMPFILE=`cmake_tmp_file` - echo ' - #include - int main() { std::cout << "We need '"${cmake_test_flags}"'" << std::endl; return 0;} -' > ${TMPFILE}.cxx - cmake_need_flags=1 - if cmake_try_run "${cmake_cxx_compiler}" \ - "${cmake_cxx_flags} ${cmake_test_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then - : - else - cmake_need_flags=0 - fi - if [ "x${cmake_need_flags}" = "x1" ]; then - cmake_cxx_flags="${cmake_cxx_flags} ${cmake_test_flags}" - echo "${cmake_cxx_compiler} needs ${cmake_test_flags}" - else - echo "${cmake_cxx_compiler} does not need ${cmake_test_flags}" - fi - rm -f "${TMPFILE}.cxx" - fi - cmake_test_flags= - - # If we are on OSF, check for -std strict_ansi -nopure_cname - cmake_test_flags="-std strict_ansi -nopure_cname" - if [ "x${cmake_system}" = "xOSF1" ]; then - TMPFILE=`cmake_tmp_file` - echo ' - #include - int main() { std::cout << "We need '"${cmake_test_flags}"'" << std::endl; return 0;} -' > ${TMPFILE}.cxx - cmake_need_flags=1 - if cmake_try_run "${cmake_cxx_compiler}" \ - "${cmake_cxx_flags} ${cmake_test_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then - : - else - cmake_need_flags=0 - fi - if [ "x${cmake_need_flags}" = "x1" ]; then - cmake_cxx_flags="${cmake_cxx_flags} ${cmake_test_flags}" - echo "${cmake_cxx_compiler} needs ${cmake_test_flags}" - else - echo "${cmake_cxx_compiler} does not need ${cmake_test_flags}" - fi - rm -f "${TMPFILE}.cxx" - fi - cmake_test_flags= - # If we are on HP-UX, check for -Ae for the C compiler. if [ "x${cmake_system}" = "xHP-UX" ]; then cmake_test_flags="-Ae" @@ -1235,34 +1199,6 @@ if [ "x${cmake_cxx_compiler_is_gnu}" != "x1" ]; then fi -if [ "x${cmake_cxx_compiler_is_gnu}" != "x1" ]; then - # Are we SolarisStudio? - - TMPFILE=`cmake_tmp_file` - echo ' - #if defined(__SUNPRO_CC) - #include - int main() { std::cout << "This is SolarisStudio" << std::endl; return 0;} - #endif - ' > ${TMPFILE}.cxx - cmake_cxx_compiler_is_solarisstudio=0 - if cmake_try_run "${cmake_cxx_compiler}" \ - "${cmake_cxx_flags} " "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then - cmake_cxx_compiler_is_solarisstudio=1 - fi - if [ "x${cmake_cxx_compiler_is_solarisstudio}" = "x1" ]; then - echo "${cmake_cxx_compiler} is SolarisStudio compiler" - else - echo "${cmake_cxx_compiler} is not SolarisStudio compiler" - fi - rm -f "${TMPFILE}.cxx" - - if [ "x${cmake_cxx_compiler_is_solarisstudio}" = "x1" ]; then - cmake_cxx_flags="${cmake_cxx_flags} -library=stlport4" - fi -fi - - # Test for kwsys features KWSYS_NAME_IS_KWSYS=0 KWSYS_BUILD_SHARED=0 @@ -1341,6 +1277,8 @@ cmake_compiler_settings_comment="/* * * Sources: * ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} + * LexerParser Sources: + * ${LexerParser_CXX_SOURCES} ${LexerParser_C_SOURCES} * kwSys Sources: * ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES} */ @@ -1368,8 +1306,11 @@ cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP_BINARY_DIR \"${CMAKE_ cmake_report cmConfigure.h${_tmp} "#define CMAKE_BIN_DIR \"/bootstrap-not-insalled\"" cmake_report cmConfigure.h${_tmp} "#define CMAKE_DATA_DIR \"/bootstrap-not-insalled\"" cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP" +cmake_report cmConfigure.h${_tmp} "#define CM_EQ_DELETE" +cmake_report cmConfigure.h${_tmp} "#define CM_FALLTHROUGH" cmake_report cmConfigure.h${_tmp} "#define CM_NULLPTR 0" cmake_report cmConfigure.h${_tmp} "#define CM_OVERRIDE" +cmake_report cmConfigure.h${_tmp} "#define CM_DISABLE_COPY(Class)" # Regenerate configured headers for h in Configure VersionConfig; do @@ -1400,7 +1341,7 @@ cmake_generate_file "${cmake_bootstrap_dir}/cmThirdParty.h" "" # Generate Makefile dep="cmConfigure.h cmsys/*.hxx cmsys/*.h `cmake_escape \"${cmake_source_dir}\"`/Source/*.h" objs="" -for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES}; do +for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${LexerParser_CXX_SOURCES} ${LexerParser_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES}; do objs="${objs} ${a}.o" done @@ -1419,6 +1360,7 @@ fi cmake_c_flags_String="-DKWSYS_STRING_C" if ${cmake_system_mingw}; then cmake_c_flags_EncodingC="-DKWSYS_ENCODING_DEFAULT_CODEPAGE=CP_ACP" + cmake_cxx_flags_EncodingCXX="${cmake_c_flags_EncodingC}" cmake_cxx_flags_cmProcessOutput="${cmake_c_flags_EncodingC}" fi cmake_cxx_flags_SystemTools=" @@ -1428,9 +1370,15 @@ cmake_cxx_flags_SystemTools=" -DKWSYS_CXX_HAS_UTIMENSAT=${KWSYS_CXX_HAS_UTIMENSAT} -DKWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES} " -cmake_c_flags="${cmake_c_flags}-I`cmake_escape \"${cmake_bootstrap_dir}\"` -I`cmake_escape \"${cmake_source_dir}/Source\"` \ +cmake_c_flags="${cmake_c_flags} \ + -I`cmake_escape \"${cmake_bootstrap_dir}\"` \ + -I`cmake_escape \"${cmake_source_dir}/Source\"` \ + -I`cmake_escape \"${cmake_source_dir}/Source/LexerParser\"` \ -I`cmake_escape \"${cmake_source_dir}/Utilities\"`" -cmake_cxx_flags="${cmake_cxx_flags} -I`cmake_escape \"${cmake_bootstrap_dir}\"` -I`cmake_escape \"${cmake_source_dir}/Source\"` \ +cmake_cxx_flags="${cmake_cxx_flags} \ + -I`cmake_escape \"${cmake_bootstrap_dir}\"` \ + -I`cmake_escape \"${cmake_source_dir}/Source\"` \ + -I`cmake_escape \"${cmake_source_dir}/Source/LexerParser\"` \ -I`cmake_escape \"${cmake_source_dir}/Utilities\"`" echo "cmake: ${objs}" > "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_ld_flags} ${cmake_cxx_flags} ${objs} -o cmake" >> "${cmake_bootstrap_dir}/Makefile" @@ -1440,13 +1388,22 @@ for a in ${CMAKE_CXX_SOURCES}; do echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done -echo "cmBootstrapCommands1.o : $cmBootstrapCommands1Deps" >> "${cmake_bootstrap_dir}/Makefile" -echo "cmBootstrapCommands2.o : $cmBootstrapCommands2Deps" >> "${cmake_bootstrap_dir}/Makefile" for a in ${CMAKE_C_SOURCES}; do src=`cmake_escape "${cmake_source_dir}/Source/${a}.c"` echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_c_compiler} ${cmake_c_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done +for a in ${LexerParser_CXX_SOURCES}; do + src=`cmake_escape "${cmake_source_dir}/Source/LexerParser/${a}.cxx"` + src_flags=`eval echo \\${cmake_cxx_flags_\${a}}` + echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" + echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" +done +for a in ${LexerParser_C_SOURCES}; do + src=`cmake_escape "${cmake_source_dir}/Source/LexerParser/${a}.c"` + echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" + echo " ${cmake_c_compiler} ${cmake_c_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" +done for a in ${KWSYS_C_SOURCES}; do src=`cmake_escape "${cmake_source_dir}/Source/kwsys/${a}.c"` src_flags=`eval echo \\${cmake_c_flags_\${a}}`