(* (or (not (any space "()#\\\n")) (and ?\\ nonl)))))
(defconst cmake-regex-token
(rx-to-string `(group (or (regexp ,cmake-regex-comment)
- ?( ?)
+ ?\( ?\)
(regexp ,cmake-regex-argument-unquoted)
(regexp ,cmake-regex-argument-quoted)))))
(defconst cmake-regex-indented
let s:keepcpo= &cpo
set cpo&vim
-syn region cmakeComment start="#" end="$" contains=cmakeTodo,cmakeLuaComment,@Spell
-syn region cmakeLuaComment start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
+syn region cmakeBracketArgument start="\[\z(=\?\|=[0-9]*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
+
+syn region cmakeComment start="#" end="$" contains=cmakeTodo,@Spell
+syn region cmakeBracketComment start="#\[\z(=\?\|=[0-9]*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained
syn region cmakeRegistry start="\[" end="]" contained oneline contains=cmakeTodo,cmakeEscaped
syn region cmakeEnvironment start="$ENV{" end="}" contained oneline contains=cmakeTodo
-syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeCommand,cmakeCommandConditional,cmakeCommandRepeat,cmakeCommandDeprecated,cmakeArguments,cmakeTodo
+syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeCommand,cmakeCommandConditional,cmakeCommandRepeat,cmakeCommandDeprecated,cmakeCommandManuallyAdded,cmakeArguments,cmakeTodo
syn case match
\ TODO FIXME XXX
\ contained
+hi def link cmakeBracketArgument String
+hi def link cmakeBracketComment Comment
hi def link cmakeCommand Function
hi def link cmakeCommandConditional Conditional
hi def link cmakeCommandDeprecated WarningMsg
hi def link cmakeEscaped Special
hi def link cmakeGeneratorExpression WarningMsg
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
@KEYWORDS_HIGHLIGHT@
+" Manually added - difficult to parse out of documentation
+syn case ignore
+
+syn keyword cmakeCommandManuallyAdded
+ \ configure_package_config_file write_basic_package_version_file
+ \ nextgroup=cmakeArguments
+
+syn case match
+
+syn keyword cmakeKWconfigure_package_config_file contained
+ \ INSTALL_DESTINATION PATH_VARS NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO INSTALL_PREFIX
+
+syn keyword cmakeKWconfigure_package_config_file_constants contained
+ \ AnyNewerVersion SameMajorVersion SameMinorVersion ExactVersion
+
+syn keyword cmakeKWwrite_basic_package_version_file contained
+ \ VERSION COMPATIBILITY
+
+hi def link cmakeCommandManuallyAdded Function
+
+hi def link cmakeKWconfigure_package_config_file ModeMsg
+hi def link cmakeKWwrite_basic_package_version_file ModeMsg
+hi def link cmakeKWconfigure_package_config_file_constants Constant
+
let b:current_syntax = "cmake"
let &cpo = s:keepcpo
my @tmp = grep { ! exists $conditional{$_} and
! exists $loop{$_} and
! exists $deprecated{$_} } @commands;
- print OUT " " x 12 , "\\ ", join(" ", @tmp), "\n";
+ print_list(\*OUT, @tmp);
} elsif ($1 eq "VARIABLE_LIST") {
- print OUT " " x 12 , "\\ ", join(" ", sort keys %variables), "\n";
+ print_list(\*OUT, keys %variables);
} elsif ($1 eq "MODULES") {
- print OUT " " x 12 , "\\ ", join("\n", @modules), "\n";
+ print_list(\*OUT, @modules);
} elsif ($1 eq "GENERATOR_EXPRESSIONS") {
- print OUT " " x 12 , "\\ ", join(" ", @generator_expr), "\n";
+ print_list(\*OUT, @generator_expr);
} elsif ($1 eq "CONDITIONALS") {
- print OUT " " x 12 , "\\ ", join(" ", sort keys %conditional), "\n";
+ print_list(\*OUT, keys %conditional);
} elsif ($1 eq "LOOPS") {
- print OUT " " x 12 , "\\ ", join(" ", sort keys %loop), "\n";
+ print_list(\*OUT, keys %loop);
} elsif ($1 eq "DEPRECATED") {
- print OUT " " x 12 , "\\ ", join(" ", sort keys %deprecated), "\n";
+ print_list(\*OUT, keys %deprecated);
} elsif ($1 eq "PROPERTIES") {
- print OUT " " x 12 , "\\ ", join(" ", sort keys %properties), "\n";
+ print_list(\*OUT, keys %properties);
} elsif ($1 eq "KEYWORDS") {
foreach my $k (sort keys %keywords) {
print OUT "syn keyword cmakeKW$k contained\n";
- print OUT " " x 12, "\\ ", join(" ", @{$keywords{$k}}), "\n";
+ print_list(\*OUT, @{$keywords{$k}});
print OUT "\n";
push @keyword_hi, "hi def link cmakeKW$k ModeMsg";
}
return @word;
}
+
+sub print_list
+{
+ my $O = shift;
+ my $indent = " " x 12 . "\\ ";
+ print $O $indent, join("\n" . $indent, sort @_), "\n";
+}
" Vim syntax file
" Program: CMake - Cross-Platform Makefile Generator
-" Version: cmake version 3.10.20171031-gfd2e6
+" Version: cmake version 3.13.20181010-ga3598
" Language: CMake
" Author: Andy Cedilnik <andy.cedilnik@kitware.com>,
" Nicholas Hutchinson <nshutchinson@gmail.com>,
" Patrick Boettcher <patrick.boettcher@posteo.de>
" Maintainer: Dimitri Merejkowsky <d.merej@gmail.com>
" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
-" Last Change: 2017 Oct 31
+" Last Change: 2018 Oct 18
"
" Licence: The CMake license applies to this file. See
" https://cmake.org/licensing
let s:keepcpo= &cpo
set cpo&vim
-syn region cmakeComment start="#" end="$" contains=cmakeTodo,cmakeLuaComment,@Spell
-syn region cmakeLuaComment start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
+syn region cmakeBracketArgument start="\[\z(=\?\|=[0-9]*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
+
+syn region cmakeComment start="#" end="$" contains=cmakeTodo,@Spell
+syn region cmakeBracketComment start="#\[\z(=\?\|=[0-9]*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained
syn region cmakeRegistry start="\[" end="]" contained oneline contains=cmakeTodo,cmakeEscaped
syn region cmakeEnvironment start="$ENV{" end="}" contained oneline contains=cmakeTodo
-syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeCommand,cmakeCommandConditional,cmakeCommandRepeat,cmakeCommandDeprecated,cmakeArguments,cmakeTodo
+syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeCommand,cmakeCommandConditional,cmakeCommandRepeat,cmakeCommandDeprecated,cmakeCommandManuallyAdded,cmakeArguments,cmakeTodo
syn case match
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_NAME ATTACHED_FILES ATTACHED_FILES_ON_FAIL AUTOGEN_BUILD_DIR AUTOGEN_SOURCE_GROUP AUTOGEN_TARGETS_FOLDER AUTOGEN_TARGET_DEPENDS AUTOMOC AUTOMOC_COMPILER_PREDEFINES AUTOMOC_DEPEND_FILTERS AUTOMOC_MACRO_NAMES AUTOMOC_MOC_OPTIONS AUTOMOC_SOURCE_GROUP AUTOMOC_TARGETS_FOLDER AUTORCC AUTORCC_OPTIONS AUTORCC_SOURCE_GROUP AUTOUIC AUTOUIC_OPTIONS AUTOUIC_SEARCH_PATHS BINARY_DIR BUILDSYSTEM_TARGETS BUILD_RPATH BUILD_WITH_INSTALL_NAME_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_FEATURES COMPILE_FLAGS COMPILE_OPTIONS COMPILE_PDB_NAME COMPILE_PDB_OUTPUT_DIRECTORY COST CPACK_DESKTOP_SHORTCUTS CPACK_NEVER_OVERWRITE CPACK_PERMANENT CPACK_STARTUP_SHORTCUTS CPACK_START_MENU_SHORTCUTS CPACK_WIX_ACL CROSSCOMPILING_EMULATOR CUDA_EXTENSIONS CUDA_PTX_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS CUDA_SEPARABLE_COMPILATION CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEBUG_CONFIGURATIONS DEBUG_POSTFIX DEFINE_SYMBOL DEFINITIONS DEPENDS DEPLOYMENT_REMOTE_DIRECTORY DISABLED DISABLED_FEATURES ECLIPSE_EXTRA_NATURES ENABLED_FEATURES ENABLED_LANGUAGES ENABLE_EXPORTS ENVIRONMENT EXCLUDE_FROM_ALL EXCLUDE_FROM_DEFAULT_BUILD EXPORT_NAME EXTERNAL_OBJECT EchoString FAIL_REGULAR_EXPRESSION FIND_LIBRARY_USE_LIB32_PATHS FIND_LIBRARY_USE_LIB64_PATHS FIND_LIBRARY_USE_LIBX32_PATHS FIND_LIBRARY_USE_OPENBSD_VERSIONING FIXTURES_CLEANUP FIXTURES_REQUIRED FIXTURES_SETUP FOLDER FRAMEWORK FRAMEWORK_VERSION Fortran_FORMAT Fortran_MODULE_DIRECTORY GENERATED GENERATOR_FILE_NAME GENERATOR_IS_MULTI_CONFIG 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_LIBNAME IMPORTED_LINK_DEPENDENT_LIBRARIES IMPORTED_LINK_INTERFACE_LANGUAGES IMPORTED_LINK_INTERFACE_LIBRARIES IMPORTED_LINK_INTERFACE_MULTIPLICITY IMPORTED_LOCATION IMPORTED_NO_SONAME IMPORTED_OBJECTS IMPORTED_SONAME 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 IN_TRY_COMPILE IOS_INSTALL_COMBINED JOB_POOLS JOB_POOL_COMPILE JOB_POOL_LINK KEEP_EXTENSION LABELS LANGUAGE LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_NAME LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED LINK_DIRECTORIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_MULTIPLICITY LINK_LIBRARIES LINK_SEARCH_END_STATIC LINK_SEARCH_START_STATIC LINK_WHAT_YOU_USE LISTFILE_STACK LOCATION MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_PACKAGE_LOCATION MACOSX_RPATH MACROS MANUALLY_ADDED_DEPENDENCIES MEASUREMENT MODIFIED NAME NO_SONAME NO_SYSTEM_FROM_IMPORTED OBJECT_DEPENDS OBJECT_OUTPUTS OSX_ARCHITECTURES OUTPUT_NAME PACKAGES_FOUND PACKAGES_NOT_FOUND PARENT_DIRECTORY PASS_REGULAR_EXPRESSION PDB_NAME PDB_OUTPUT_DIRECTORY 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_NAME RUN_SERIAL SKIP_AUTOGEN SKIP_AUTOMOC SKIP_AUTORCC SKIP_AUTOUIC SKIP_BUILD_RPATH SKIP_RETURN_CODE SOURCES SOURCE_DIR SOVERSION STATIC_LIBRARY_FLAGS STRINGS SUBDIRECTORIES SUFFIX SYMBOLIC TARGET_ARCHIVES_MAY_BE_SHARED_LIBS TARGET_MESSAGES TARGET_SUPPORTS_SHARED_LIBS TEST_INCLUDE_FILE TEST_INCLUDE_FILES TIMEOUT TIMEOUT_AFTER_MATCH TYPE USE_FOLDERS VALUE VARIABLES VERSION VISIBILITY_INLINES_HIDDEN VS_CONFIGURATION_TYPE VS_COPY_TO_OUT_DIR VS_DEBUGGER_WORKING_DIRECTORY VS_DEPLOYMENT_CONTENT VS_DEPLOYMENT_LOCATION VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_REFERENCES_COPY_LOCAL VS_DOTNET_TARGET_FRAMEWORK_VERSION VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_INCLUDE_IN_VSIX VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION VS_RESOURCE_GENERATOR VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER VS_SDK_REFERENCES VS_SHADER_ENTRYPOINT VS_SHADER_FLAGS VS_SHADER_MODEL VS_SHADER_OUTPUT_HEADER_FILE VS_SHADER_TYPE VS_SHADER_VARIABLE_NAME VS_STARTUP_PROJECT VS_TOOL_OVERRIDE VS_USER_PROPS 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_EMIT_EFFECTIVE_PLATFORM_NAME XCODE_EXPLICIT_FILE_TYPE XCODE_FILE_ATTRIBUTES XCODE_LAST_KNOWN_FILE_TYPE XCODE_PRODUCT_TYPE XCTEST
+ \ 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_NAME
+ \ ATTACHED_FILES
+ \ ATTACHED_FILES_ON_FAIL
+ \ AUTOGEN_BUILD_DIR
+ \ AUTOGEN_PARALLEL
+ \ AUTOGEN_SOURCE_GROUP
+ \ AUTOGEN_TARGETS_FOLDER
+ \ AUTOGEN_TARGET_DEPENDS
+ \ AUTOMOC
+ \ AUTOMOC_COMPILER_PREDEFINES
+ \ AUTOMOC_DEPEND_FILTERS
+ \ AUTOMOC_MACRO_NAMES
+ \ AUTOMOC_MOC_OPTIONS
+ \ AUTOMOC_SOURCE_GROUP
+ \ AUTOMOC_TARGETS_FOLDER
+ \ AUTORCC
+ \ AUTORCC_OPTIONS
+ \ AUTORCC_SOURCE_GROUP
+ \ AUTOUIC
+ \ AUTOUIC_OPTIONS
+ \ AUTOUIC_SEARCH_PATHS
+ \ BINARY_DIR
+ \ BUILDSYSTEM_TARGETS
+ \ BUILD_RPATH
+ \ BUILD_WITH_INSTALL_NAME_DIR
+ \ BUILD_WITH_INSTALL_RPATH
+ \ BUNDLE
+ \ BUNDLE_EXTENSION
+ \ CACHE_VARIABLES
+ \ CLEAN_NO_CUSTOM
+ \ CMAKE_CONFIGURE_DEPENDS
+ \ CMAKE_CXX_KNOWN_FEATURES
+ \ CMAKE_C_KNOWN_FEATURES
+ \ COMMON_LANGUAGE_RUNTIME
+ \ COMPATIBLE_INTERFACE_BOOL
+ \ COMPATIBLE_INTERFACE_NUMBER_MAX
+ \ COMPATIBLE_INTERFACE_NUMBER_MIN
+ \ COMPATIBLE_INTERFACE_STRING
+ \ COMPILE_DEFINITIONS
+ \ COMPILE_FEATURES
+ \ COMPILE_FLAGS
+ \ COMPILE_OPTIONS
+ \ COMPILE_PDB_NAME
+ \ COMPILE_PDB_OUTPUT_DIRECTORY
+ \ COST
+ \ CPACK_DESKTOP_SHORTCUTS
+ \ CPACK_NEVER_OVERWRITE
+ \ CPACK_PERMANENT
+ \ CPACK_STARTUP_SHORTCUTS
+ \ CPACK_START_MENU_SHORTCUTS
+ \ CPACK_WIX_ACL
+ \ CROSSCOMPILING_EMULATOR
+ \ CUDA_EXTENSIONS
+ \ CUDA_PTX_COMPILATION
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_SEPARABLE_COMPILATION
+ \ CUDA_STANDARD
+ \ CUDA_STANDARD_REQUIRED
+ \ CXX_EXTENSIONS
+ \ CXX_STANDARD
+ \ CXX_STANDARD_REQUIRED
+ \ C_EXTENSIONS
+ \ C_STANDARD
+ \ C_STANDARD_REQUIRED
+ \ DEBUG_CONFIGURATIONS
+ \ DEBUG_POSTFIX
+ \ DEFINE_SYMBOL
+ \ DEFINITIONS
+ \ DEPENDS
+ \ DEPLOYMENT_ADDITIONAL_FILES
+ \ DEPLOYMENT_REMOTE_DIRECTORY
+ \ DISABLED
+ \ DISABLED_FEATURES
+ \ DOTNET_TARGET_FRAMEWORK_VERSION
+ \ ECLIPSE_EXTRA_CPROJECT_CONTENTS
+ \ ECLIPSE_EXTRA_NATURES
+ \ ENABLED_FEATURES
+ \ ENABLED_LANGUAGES
+ \ ENABLE_EXPORTS
+ \ ENVIRONMENT
+ \ EXCLUDE_FROM_ALL
+ \ EXCLUDE_FROM_DEFAULT_BUILD
+ \ EXPORT_NAME
+ \ EXPORT_PROPERTIES
+ \ EXTERNAL_OBJECT
+ \ EchoString
+ \ FAIL_REGULAR_EXPRESSION
+ \ FIND_LIBRARY_USE_LIB32_PATHS
+ \ FIND_LIBRARY_USE_LIB64_PATHS
+ \ FIND_LIBRARY_USE_LIBX32_PATHS
+ \ FIND_LIBRARY_USE_OPENBSD_VERSIONING
+ \ FIXTURES_CLEANUP
+ \ FIXTURES_REQUIRED
+ \ FIXTURES_SETUP
+ \ FOLDER
+ \ FRAMEWORK
+ \ FRAMEWORK_VERSION
+ \ Fortran_FORMAT
+ \ Fortran_MODULE_DIRECTORY
+ \ GENERATED
+ \ GENERATOR_FILE_NAME
+ \ GENERATOR_IS_MULTI_CONFIG
+ \ GLOBAL_DEPENDS_DEBUG_MODE
+ \ GLOBAL_DEPENDS_NO_CYCLES
+ \ GNUtoMS
+ \ HAS_CXX
+ \ HEADER_FILE_ONLY
+ \ HELPSTRING
+ \ IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
+ \ IMPORTED
+ \ IMPORTED_COMMON_LANGUAGE_RUNTIME
+ \ IMPORTED_CONFIGURATIONS
+ \ IMPORTED_GLOBAL
+ \ IMPORTED_IMPLIB
+ \ IMPORTED_LIBNAME
+ \ IMPORTED_LINK_DEPENDENT_LIBRARIES
+ \ IMPORTED_LINK_INTERFACE_LANGUAGES
+ \ IMPORTED_LINK_INTERFACE_LIBRARIES
+ \ IMPORTED_LINK_INTERFACE_MULTIPLICITY
+ \ IMPORTED_LOCATION
+ \ IMPORTED_NO_SONAME
+ \ IMPORTED_OBJECTS
+ \ IMPORTED_SONAME
+ \ 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_DEPENDS
+ \ INTERFACE_LINK_DIRECTORIES
+ \ INTERFACE_LINK_LIBRARIES
+ \ INTERFACE_LINK_OPTIONS
+ \ INTERFACE_POSITION_INDEPENDENT_CODE
+ \ INTERFACE_SOURCES
+ \ INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
+ \ INTERPROCEDURAL_OPTIMIZATION
+ \ IN_TRY_COMPILE
+ \ IOS_INSTALL_COMBINED
+ \ JOB_POOLS
+ \ JOB_POOL_COMPILE
+ \ JOB_POOL_LINK
+ \ KEEP_EXTENSION
+ \ LABELS
+ \ LANGUAGE
+ \ LIBRARY_OUTPUT_DIRECTORY
+ \ LIBRARY_OUTPUT_NAME
+ \ LINKER_LANGUAGE
+ \ LINK_DEPENDS
+ \ LINK_DEPENDS_NO_SHARED
+ \ LINK_DIRECTORIES
+ \ LINK_FLAGS
+ \ LINK_INTERFACE_LIBRARIES
+ \ LINK_INTERFACE_MULTIPLICITY
+ \ LINK_LIBRARIES
+ \ LINK_OPTIONS
+ \ LINK_SEARCH_END_STATIC
+ \ LINK_SEARCH_START_STATIC
+ \ LINK_WHAT_YOU_USE
+ \ LISTFILE_STACK
+ \ LOCATION
+ \ MACOSX_BUNDLE
+ \ MACOSX_BUNDLE_INFO_PLIST
+ \ MACOSX_FRAMEWORK_INFO_PLIST
+ \ MACOSX_PACKAGE_LOCATION
+ \ MACOSX_RPATH
+ \ MACROS
+ \ MANUALLY_ADDED_DEPENDENCIES
+ \ MEASUREMENT
+ \ MODIFIED
+ \ NAME
+ \ NO_SONAME
+ \ NO_SYSTEM_FROM_IMPORTED
+ \ OBJECT_DEPENDS
+ \ OBJECT_OUTPUTS
+ \ OSX_ARCHITECTURES
+ \ OUTPUT_NAME
+ \ PACKAGES_FOUND
+ \ PACKAGES_NOT_FOUND
+ \ PARENT_DIRECTORY
+ \ PASS_REGULAR_EXPRESSION
+ \ PDB_NAME
+ \ PDB_OUTPUT_DIRECTORY
+ \ POSITION_INDEPENDENT_CODE
+ \ POST_INSTALL_SCRIPT
+ \ PREDEFINED_TARGETS_FOLDER
+ \ PREFIX
+ \ PRE_INSTALL_SCRIPT
+ \ PRIVATE_HEADER
+ \ PROCESSORS
+ \ PROCESSOR_AFFINITY
+ \ 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_NAME
+ \ RUN_SERIAL
+ \ SKIP_AUTOGEN
+ \ SKIP_AUTOMOC
+ \ SKIP_AUTORCC
+ \ SKIP_AUTOUIC
+ \ SKIP_BUILD_RPATH
+ \ SKIP_RETURN_CODE
+ \ SOURCES
+ \ SOURCE_DIR
+ \ SOVERSION
+ \ STATIC_LIBRARY_FLAGS
+ \ STATIC_LIBRARY_OPTIONS
+ \ STRINGS
+ \ SUBDIRECTORIES
+ \ SUFFIX
+ \ SYMBOLIC
+ \ TARGET_ARCHIVES_MAY_BE_SHARED_LIBS
+ \ TARGET_MESSAGES
+ \ TARGET_SUPPORTS_SHARED_LIBS
+ \ TESTS
+ \ TEST_INCLUDE_FILE
+ \ TEST_INCLUDE_FILES
+ \ TIMEOUT
+ \ TIMEOUT_AFTER_MATCH
+ \ TYPE
+ \ USE_FOLDERS
+ \ VALUE
+ \ VARIABLES
+ \ VERSION
+ \ VISIBILITY_INLINES_HIDDEN
+ \ VS_CONFIGURATION_TYPE
+ \ VS_COPY_TO_OUT_DIR
+ \ VS_DEBUGGER_COMMAND
+ \ VS_DEBUGGER_COMMAND_ARGUMENTS
+ \ VS_DEBUGGER_ENVIRONMENT
+ \ VS_DEBUGGER_WORKING_DIRECTORY
+ \ VS_DEPLOYMENT_CONTENT
+ \ VS_DEPLOYMENT_LOCATION
+ \ VS_DESKTOP_EXTENSIONS_VERSION
+ \ VS_DOTNET_REFERENCES
+ \ VS_DOTNET_REFERENCES_COPY_LOCAL
+ \ VS_DOTNET_TARGET_FRAMEWORK_VERSION
+ \ VS_GLOBAL_KEYWORD
+ \ VS_GLOBAL_PROJECT_TYPES
+ \ VS_GLOBAL_ROOTNAMESPACE
+ \ VS_INCLUDE_IN_VSIX
+ \ VS_IOT_EXTENSIONS_VERSION
+ \ VS_IOT_STARTUP_TASK
+ \ VS_KEYWORD
+ \ VS_MOBILE_EXTENSIONS_VERSION
+ \ VS_RESOURCE_GENERATOR
+ \ VS_SCC_AUXPATH
+ \ VS_SCC_LOCALPATH
+ \ VS_SCC_PROJECTNAME
+ \ VS_SCC_PROVIDER
+ \ VS_SDK_REFERENCES
+ \ VS_SHADER_DISABLE_OPTIMIZATIONS
+ \ VS_SHADER_ENABLE_DEBUG
+ \ VS_SHADER_ENTRYPOINT
+ \ VS_SHADER_FLAGS
+ \ VS_SHADER_MODEL
+ \ VS_SHADER_OBJECT_FILE_NAME
+ \ VS_SHADER_OUTPUT_HEADER_FILE
+ \ VS_SHADER_TYPE
+ \ VS_SHADER_VARIABLE_NAME
+ \ VS_STARTUP_PROJECT
+ \ VS_TOOL_OVERRIDE
+ \ VS_USER_PROPS
+ \ 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_EMIT_EFFECTIVE_PLATFORM_NAME
+ \ XCODE_EXPLICIT_FILE_TYPE
+ \ XCODE_FILE_ATTRIBUTES
+ \ XCODE_LAST_KNOWN_FILE_TYPE
+ \ XCODE_PRODUCT_TYPE
+ \ XCODE_SCHEME_ADDRESS_SANITIZER
+ \ XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+ \ XCODE_SCHEME_ARGUMENTS
+ \ XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+ \ XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
+ \ XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ \ XCODE_SCHEME_ENVIRONMENT
+ \ XCODE_SCHEME_EXECUTABLE
+ \ XCODE_SCHEME_GUARD_MALLOC
+ \ XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+ \ XCODE_SCHEME_MALLOC_GUARD_EDGES
+ \ XCODE_SCHEME_MALLOC_SCRIBBLE
+ \ XCODE_SCHEME_MALLOC_STACK
+ \ XCODE_SCHEME_THREAD_SANITIZER
+ \ XCODE_SCHEME_THREAD_SANITIZER_STOP
+ \ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+ \ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ XCODE_SCHEME_ZOMBIE_OBJECTS
+ \ XCTEST
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_DEPRECATED_HEADERS 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_COMPILER_PREDEFINES CMAKE_AUTOMOC_DEPEND_FILTERS CMAKE_AUTOMOC_MACRO_NAMES 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_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES 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_HOST_COMPILER 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_DIRECTORY_LABELS 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_INSTANCE 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_MSVCIDE_RUN_PATH CMAKE_NETRC CMAKE_NETRC_FILE 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_SYSROOT_COMPILE CMAKE_SYSROOT_LINK 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_LABELS_FOR_SUBPROJECTS 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
+ \ ANDROID
+ \ APPLE
+ \ BORLAND
+ \ BUILD_SHARED_LIBS
+ \ CACHE
+ \ 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_DEPRECATED_HEADERS
+ \ 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_AUTOGEN_PARALLEL
+ \ CMAKE_AUTOGEN_VERBOSE
+ \ CMAKE_AUTOMOC
+ \ CMAKE_AUTOMOC_COMPILER_PREDEFINES
+ \ CMAKE_AUTOMOC_DEPEND_FILTERS
+ \ CMAKE_AUTOMOC_MACRO_NAMES
+ \ 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_CODEBLOCKS_COMPILER_ID
+ \ CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES
+ \ 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_CPACK_COMMAND
+ \ CMAKE_CROSSCOMPILING
+ \ CMAKE_CROSSCOMPILING_EMULATOR
+ \ CMAKE_CTEST_COMMAND
+ \ CMAKE_CUDA_EXTENSIONS
+ \ CMAKE_CUDA_HOST_COMPILER
+ \ CMAKE_CUDA_SEPARABLE_COMPILATION
+ \ 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_DIRECTORY_LABELS
+ \ CMAKE_DL_LIBS
+ \ CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
+ \ 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_FOLDER
+ \ 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_INSTANCE
+ \ 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_DEFAULT_DIRECTORY_PERMISSIONS
+ \ 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_POOLS
+ \ 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_DIRECTORIES_BEFORE
+ \ 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_MSVCIDE_RUN_PATH
+ \ CMAKE_NETRC
+ \ CMAKE_NETRC_FILE
+ \ 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_HOMEPAGE_URL
+ \ CMAKE_PROJECT_NAME
+ \ CMAKE_PROJECT_VERSION
+ \ CMAKE_PROJECT_VERSION_MAJOR
+ \ CMAKE_PROJECT_VERSION_MINOR
+ \ CMAKE_PROJECT_VERSION_PATCH
+ \ CMAKE_PROJECT_VERSION_TWEAK
+ \ CMAKE_RANLIB
+ \ CMAKE_ROOT
+ \ CMAKE_RULE_MESSAGES
+ \ 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_SUPPRESS_REGENERATION
+ \ CMAKE_SYSROOT
+ \ CMAKE_SYSROOT_COMPILE
+ \ CMAKE_SYSROOT_LINK
+ \ 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_GLOBALS
+ \ 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_PLATFORM_TOOLSET_VERSION
+ \ CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
+ \ CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES
+ \ CMAKE_VS_SDK_INCLUDE_DIRECTORIES
+ \ CMAKE_VS_SDK_LIBRARY_DIRECTORIES
+ \ CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES
+ \ CMAKE_VS_SDK_REFERENCE_DIRECTORIES
+ \ CMAKE_VS_SDK_SOURCE_DIRECTORIES
+ \ CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
+ \ CMAKE_VS_WINRT_BY_DEFAULT
+ \ CMAKE_WARN_DEPRECATED
+ \ CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
+ \ CMAKE_WIN32_EXECUTABLE
+ \ CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
+ \ CMAKE_XCODE_GENERATE_SCHEME
+ \ CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY
+ \ CMAKE_XCODE_PLATFORM_TOOLSET
+ \ CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER
+ \ CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+ \ CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+ \ CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
+ \ CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ \ CMAKE_XCODE_SCHEME_GUARD_MALLOC
+ \ CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+ \ CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
+ \ CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
+ \ CMAKE_XCODE_SCHEME_MALLOC_STACK
+ \ CMAKE_XCODE_SCHEME_THREAD_SANITIZER
+ \ CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP
+ \ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+ \ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
+ \ CPACK_ABSOLUTE_DESTINATION_FILES
+ \ CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
+ \ CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
+ \ CPACK_INCLUDE_TOPLEVEL_DIRECTORY
+ \ CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+ \ CPACK_INSTALL_SCRIPT
+ \ CPACK_PACKAGING_INSTALL_PREFIX
+ \ CPACK_SET_DESTDIR
+ \ CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
+ \ 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_LABELS_FOR_SUBPROJECTS
+ \ 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_RUN_CURRENT_SCRIPT
+ \ 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_TOOLSET_VERSION
+ \ MSVC_VERSION
+ \ PROJECT_BINARY_DIR
+ \ PROJECT_DESCRIPTION
+ \ PROJECT_HOMEPAGE_URL
+ \ 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
syn keyword cmakeKWExternalProject contained
- \ ALGO AWS BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY COMMENT CONFIGURE_COMMAND CVS 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 IGNORED INDEPENDENT_STEP_TARGETS INSTALL_COMMAND INSTALL_DIR JOB_POOLS LIST_SEPARATOR LOG_ LOG_BUILD LOG_CONFIGURE LOG_DOWNLOAD LOG_INSTALL LOG_TEST LOG_UPDATE MAKE_EXE NAMES NETRC NETRC_FILE NOTE NO_DEPENDS OPTIONAL PATCH_COMMAND PREFIX PROPERTY REQUIRED SOURCE_DIR SOURCE_SUBDIR STAMP_DIR STEP_TARGETS STRING 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 TRUE 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
+ \ AWS
+ \ BINARY_DIR
+ \ BUILD_ALWAYS
+ \ BUILD_BYPRODUCTS
+ \ BUILD_COMMAND
+ \ BUILD_IN_SOURCE
+ \ CMAKE_ARGS
+ \ CMAKE_CACHE_ARGS
+ \ CMAKE_CACHE_DEFAULT_ARGS
+ \ CMAKE_TLS_CAINFO
+ \ CMAKE_TLS_VERIFY
+ \ COMMENT
+ \ CONFIGURE_COMMAND
+ \ CVS
+ \ 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
+ \ IGNORED
+ \ INDEPENDENT_STEP_TARGETS
+ \ INSTALL_COMMAND
+ \ INSTALL_DIR
+ \ JOB_POOLS
+ \ LIST_SEPARATOR
+ \ LOG_
+ \ LOG_BUILD
+ \ LOG_CONFIGURE
+ \ LOG_DOWNLOAD
+ \ LOG_INSTALL
+ \ LOG_TEST
+ \ LOG_UPDATE
+ \ MAKE_EXE
+ \ NAMES
+ \ NETRC
+ \ NETRC_FILE
+ \ NOTE
+ \ NO_DEPENDS
+ \ OPTIONAL
+ \ PATCH_COMMAND
+ \ PREFIX
+ \ PROPERTY
+ \ REQUIRED
+ \ SOURCE_DIR
+ \ SOURCE_SUBDIR
+ \ STAMP_DIR
+ \ STEP_TARGETS
+ \ STRING
+ \ 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
+ \ TRUE
+ \ 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_definitions contained
+ \ COMPILE_DEFINITIONS
+ \ VAR
syn keyword cmakeKWadd_compile_options contained
\ COMPILE_OPTIONS
+ \ SHELL
+ \ UNIX_COMMAND
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
+ \ 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 contained
- \ ALL BYPRODUCTS CC COMMAND COMMAND_EXPAND_LISTS COMMENT CROSSCOMPILING_EMULATOR DEPENDS GENERATED INCLUDE_DIRECTORIES JOIN SOURCES TARGET_PROPERTY USES_TERMINAL VERBATIM WORKING_DIRECTORY
+ \ 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 contained
\ COMPILE_DEFINITIONS
syn keyword cmakeKWadd_dependencies contained
- \ DEPENDS OBJECT_DEPENDS
+ \ DEPENDS
+ \ OBJECT_DEPENDS
syn keyword cmakeKWadd_executable contained
- \ ALIAS CONFIG EXCLUDE_FROM_ALL GLOBAL HEADER_FILE_ONLY IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ MACOSX_BUNDLE OUTPUT_NAME RUNTIME_OUTPUT_DIRECTORY TARGET
+ \ ALIAS
+ \ CONFIG
+ \ EXCLUDE_FROM_ALL
+ \ GLOBAL
+ \ HEADER_FILE_ONLY
+ \ IMPORTED
+ \ IMPORTED_
+ \ IMPORTED_LOCATION
+ \ IMPORTED_LOCATION_
+ \ MACOSX_BUNDLE
+ \ OUTPUT_NAME
+ \ RUNTIME_OUTPUT_DIRECTORY
+ \ TARGET
syn keyword cmakeKWadd_library contained
- \ ALIAS ARCHIVE_OUTPUT_DIRECTORY CLI CONFIG DLL EXCLUDE_FROM_ALL FRAMEWORK GLOBAL HEADER_FILE_ONLY 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
+ \ ALIAS
+ \ ARCHIVE_OUTPUT_DIRECTORY
+ \ CLI
+ \ CONFIG
+ \ DLL
+ \ EXCLUDE_FROM_ALL
+ \ FRAMEWORK
+ \ GLOBAL
+ \ HEADER_FILE_ONLY
+ \ IMPORTED
+ \ IMPORTED_
+ \ IMPORTED_LOCATION
+ \ IMPORTED_LOCATION_
+ \ IMPORTED_OBJECTS
+ \ IMPORTED_OBJECTS_
+ \ 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_link_options contained
+ \ CMAKE_
+ \ GCC
+ \ GNU
+ \ LANG
+ \ LINKER
+ \ LINK_OPTIONS
+ \ SHELL
+ \ UNIX_COMMAND
+ \ _LINKER_WRAPPER_FLAG
+ \ _LINKER_WRAPPER_FLAG_SEP
syn keyword cmakeKWadd_subdirectory contained
\ EXCLUDE_FROM_ALL
syn keyword cmakeKWadd_test contained
- \ BUILD_TESTING COMMAND CONFIGURATIONS FAIL_REGULAR_EXPRESSION NAME PASS_REGULAR_EXPRESSION TARGET_FILE WILL_FAIL WORKING_DIRECTORY
+ \ BUILD_TESTING
+ \ COMMAND
+ \ CONFIGURATIONS
+ \ FAIL_REGULAR_EXPRESSION
+ \ NAME
+ \ PASS_REGULAR_EXPRESSION
+ \ TARGET_FILE
+ \ WILL_FAIL
+ \ WORKING_DIRECTORY
syn keyword cmakeKWbuild_command contained
- \ CONFIGURATION TARGET
+ \ CONFIGURATION
+ \ TARGET
syn keyword cmakeKWbuild_name contained
\ CMAKE_CXX_COMPILER
syn keyword cmakeKWcmake_host_system_information contained
- \ AVAILABLE_PHYSICAL_MEMORY AVAILABLE_VIRTUAL_MEMORY FQDN HAS_FPU HAS_MMX HAS_MMX_PLUS HAS_SERIAL_NUMBER HAS_SSE HAS_SSE_FP HAS_SSE_MMX HOSTNAME ID NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES OS_NAME OS_PLATFORM OS_RELEASE OS_VERSION PROCESSOR_DESCRIPTION PROCESSOR_NAME PROCESSOR_SERIAL_NUMBER QUERY RESULT TOTAL_PHYSICAL_MEMORY TOTAL_VIRTUAL_MEMORY
+ \ AVAILABLE_PHYSICAL_MEMORY
+ \ AVAILABLE_VIRTUAL_MEMORY
+ \ FQDN
+ \ HAS_FPU
+ \ HAS_MMX
+ \ HAS_MMX_PLUS
+ \ HAS_SERIAL_NUMBER
+ \ HAS_SSE
+ \ HAS_SSE_FP
+ \ HAS_SSE_MMX
+ \ HOSTNAME
+ \ ID
+ \ NUMBER_OF_LOGICAL_CORES
+ \ NUMBER_OF_PHYSICAL_CORES
+ \ OS_NAME
+ \ OS_PLATFORM
+ \ OS_RELEASE
+ \ OS_VERSION
+ \ PROCESSOR_DESCRIPTION
+ \ PROCESSOR_NAME
+ \ PROCESSOR_SERIAL_NUMBER
+ \ QUERY
+ \ RESULT
+ \ TOTAL_PHYSICAL_MEMORY
+ \ TOTAL_VIRTUAL_MEMORY
syn keyword cmakeKWcmake_minimum_required contained
- \ FATAL_ERROR VERSION
+ \ FATAL_ERROR
+ \ VERSION
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 UNDEFINED _UNPARSED_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
+ \ PARSE_ARGV
+ \ RENAME
+ \ TARGETS
+ \ TRUE
+ \ UNDEFINED
+ \ _UNPARSED_ARGUMENTS
syn keyword cmakeKWcmake_policy contained
- \ CMAKE_POLICY_DEFAULT_CMP CMP GET NNNN NO_POLICY_SCOPE OLD POP PUSH SET VERSION
+ \ CMAKE_POLICY_DEFAULT_CMP
+ \ CMP
+ \ GET
+ \ NNNN
+ \ NO_POLICY_SCOPE
+ \ OLD
+ \ POP
+ \ PUSH
+ \ SET
+ \ VERSION
syn keyword cmakeKWconfigure_file contained
- \ COPYONLY CRLF DOS ESCAPE_QUOTES FOO_ENABLE FOO_STRING LF NEWLINE_STYLE VAR
+ \ COPYONLY
+ \ CRLF
+ \ DOS
+ \ ESCAPE_QUOTES
+ \ FOO_ENABLE
+ \ FOO_STRING
+ \ LF
+ \ NEWLINE_STYLE
+ \ VAR
syn keyword cmakeKWcreate_test_sourcelist contained
- \ CMAKE_TESTDRIVER_AFTER_TESTMAIN CMAKE_TESTDRIVER_BEFORE_TESTMAIN EXTRA_INCLUDE FUNCTION
+ \ CMAKE_TESTDRIVER_AFTER_TESTMAIN
+ \ CMAKE_TESTDRIVER_BEFORE_TESTMAIN
+ \ EXTRA_INCLUDE
+ \ FUNCTION
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
+ \ 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 contained
- \ APPEND BUILD CAPTURE_CMAKE_ERROR OPTIONS QUIET RETURN_VALUE SOURCE
+ \ APPEND
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ OPTIONS
+ \ QUIET
+ \ RETURN_VALUE
+ \ SOURCE
syn keyword cmakeKWctest_coverage contained
- \ APPEND BUILD CAPTURE_CMAKE_ERROR LABELS QUIET RETURN_VALUE
+ \ APPEND
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ LABELS
+ \ QUIET
+ \ RETURN_VALUE
syn keyword cmakeKWctest_memcheck contained
- \ APPEND BUILD DEFECT_COUNT EXCLUDE EXCLUDE_FIXTURE EXCLUDE_FIXTURE_CLEANUP EXCLUDE_FIXTURE_SETUP EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
+ \ APPEND
+ \ BUILD
+ \ DEFECT_COUNT
+ \ EXCLUDE
+ \ EXCLUDE_FIXTURE
+ \ EXCLUDE_FIXTURE_CLEANUP
+ \ EXCLUDE_FIXTURE_SETUP
+ \ 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 contained
- \ NEW_PROCESS RETURN_VALUE
+ \ NEW_PROCESS
+ \ RETURN_VALUE
syn keyword cmakeKWctest_start contained
- \ APPEND QUIET TAG TRACK
+ \ APPEND
+ \ QUIET
+ \ TAG
+ \ TRACK
syn keyword cmakeKWctest_submit contained
- \ API CDASH_UPLOAD CDASH_UPLOAD_TYPE CTEST_EXTRA_SUBMIT_FILES CTEST_NOTES_FILES FILES HTTPHEADER PARTS QUIET RETRY_COUNT RETRY_DELAY RETURN_VALUE
+ \ API
+ \ CAPTURE_CMAKE_ERROR
+ \ CDASH_UPLOAD
+ \ CDASH_UPLOAD_TYPE
+ \ CTEST_EXTRA_SUBMIT_FILES
+ \ CTEST_NOTES_FILES
+ \ FILES
+ \ HTTPHEADER
+ \ PARTS
+ \ QUIET
+ \ RETRY_COUNT
+ \ RETRY_DELAY
+ \ RETURN_VALUE
syn keyword cmakeKWctest_test contained
- \ APPEND BUILD CAPTURE_CMAKE_ERROR CPU EXCLUDE EXCLUDE_FIXTURE EXCLUDE_FIXTURE_CLEANUP EXCLUDE_FIXTURE_SETUP EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
+ \ APPEND
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ CPU
+ \ EXCLUDE
+ \ EXCLUDE_FIXTURE
+ \ EXCLUDE_FIXTURE_CLEANUP
+ \ EXCLUDE_FIXTURE_SETUP
+ \ EXCLUDE_LABEL
+ \ INCLUDE
+ \ INCLUDE_LABEL
+ \ OFF
+ \ ON
+ \ PARALLEL_LEVEL
+ \ QUIET
+ \ RETURN_VALUE
+ \ SCHEDULE_RANDOM
+ \ START
+ \ STOP_TIME
+ \ STRIDE
+ \ TEST_LOAD
syn keyword cmakeKWctest_update contained
- \ QUIET RETURN_VALUE SOURCE
+ \ CAPTURE_CMAKE_ERROR
+ \ QUIET
+ \ RETURN_VALUE
+ \ SOURCE
syn keyword cmakeKWctest_upload contained
- \ CAPTURE_CMAKE_ERROR FILES QUIET
+ \ CAPTURE_CMAKE_ERROR
+ \ FILES
+ \ QUIET
syn keyword cmakeKWdefine_property contained
- \ BRIEF_DOCS CACHED_VARIABLE DIRECTORY FULL_DOCS GLOBAL INHERITED PROPERTY SOURCE TARGET TEST VARIABLE
+ \ APPEND
+ \ APPEND_STRING
+ \ BRIEF_DOCS
+ \ CACHED_VARIABLE
+ \ DIRECTORY
+ \ FULL_DOCS
+ \ GLOBAL
+ \ INHERITED
+ \ PROPERTY
+ \ SOURCE
+ \ TARGET
+ \ TEST
+ \ VARIABLE
syn keyword cmakeKWenable_language contained
+ \ ASM
+ \ CUDA
\ OPTIONAL
syn keyword cmakeKWexec_program contained
- \ ARGS OUTPUT_VARIABLE RETURN_VALUE
+ \ ARGS
+ \ OUTPUT_VARIABLE
+ \ RETURN_VALUE
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 RESULTS_VARIABLE RESULT_VARIABLE TIMEOUT UTF VERBATIM WORKING_DIRECTORY
+ \ 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
+ \ RESULTS_VARIABLE
+ \ RESULT_VARIABLE
+ \ RFC
+ \ TIMEOUT
+ \ UTF
+ \ VERBATIM
+ \ WORKING_DIRECTORY
syn keyword cmakeKWexport contained
- \ ANDROID_MK APPEND CONFIG EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE IMPORTED IMPORTED_ NAMESPACE NDK OLD PACKAGE TARGETS
+ \ ANDROID_MK
+ \ APPEND
+ \ CONFIG
+ \ EXPORT
+ \ EXPORT_LINK_INTERFACE_LIBRARIES
+ \ FILE
+ \ IMPORTED
+ \ IMPORTED_
+ \ NAMESPACE
+ \ NDK
+ \ OLD
+ \ PACKAGE
+ \ TARGETS
syn keyword cmakeKWexport_library_dependencies contained
- \ APPEND EXPORT INCLUDE LINK_INTERFACE_LIBRARIES SET
+ \ APPEND
+ \ EXPORT
+ \ INCLUDE
+ \ LINK_INTERFACE_LIBRARIES
+ \ SET
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 IGNORED INACTIVITY_TIMEOUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NETRC NETRC_FILE NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS OFFSET OLD OPTIONAL PATTERN PROCESS READ REGEX RELATIVE RELATIVE_PATH RELEASE REMOVE REMOVE_RECURSE RENAME REQUIRED RESULT_VARIABLE SHOW_PROGRESS SSL STATUS STRINGS TIMESTAMP TLS_CAINFO TLS_VERIFY TO_CMAKE_PATH TO_NATIVE_PATH UPLOAD URL USERPWD USE_SOURCE_PERMISSIONS UTC UTF WRITE
+ \ ALGO
+ \ APPEND
+ \ ASCII
+ \ CMAKE_TLS_CAINFO
+ \ CMAKE_TLS_VERIFY
+ \ CONDITION
+ \ CONFIG
+ \ CONFIGURE_DEPENDS
+ \ CONTENT
+ \ COPY
+ \ DESTINATION
+ \ DIRECTORY_PERMISSIONS
+ \ DOWNLOAD
+ \ ENCODING
+ \ EXCLUDE
+ \ EXPECTED_HASH
+ \ FILES_MATCHING
+ \ FILE_PERMISSIONS
+ \ FOLLOW_SYMLINKS
+ \ FUNCTION
+ \ GENERATE
+ \ GLOB
+ \ GLOB_RECURSE
+ \ GUARD
+ \ HASH
+ \ HEX
+ \ HTTPHEADER
+ \ IGNORED
+ \ INACTIVITY_TIMEOUT
+ \ INSTALL
+ \ LENGTH_MAXIMUM
+ \ LENGTH_MINIMUM
+ \ LF
+ \ LIMIT
+ \ LIMIT_COUNT
+ \ LIMIT_INPUT
+ \ LIMIT_OUTPUT
+ \ LIST_DIRECTORIES
+ \ LOCK
+ \ LOG
+ \ MAKE_DIRECTORY
+ \ NETRC
+ \ NETRC_FILE
+ \ NEWLINE_CONSUME
+ \ NO_HEX_CONVERSION
+ \ NO_SOURCE_PERMISSIONS
+ \ OFFSET
+ \ OLD
+ \ OPTIONAL
+ \ OUTPUT
+ \ PATTERN
+ \ PROCESS
+ \ READ
+ \ REGEX
+ \ RELATIVE_PATH
+ \ RELEASE
+ \ REMOVE
+ \ REMOVE_RECURSE
+ \ RENAME
+ \ REQUIRED
+ \ RESULT_VARIABLE
+ \ SHOW_PROGRESS
+ \ SSL
+ \ STATUS
+ \ STRINGS
+ \ TIMESTAMP
+ \ TLS_CAINFO
+ \ TLS_VERIFY
+ \ TOUCH
+ \ TOUCH_NOCREATE
+ \ TO_CMAKE_PATH
+ \ TO_NATIVE_PATH
+ \ UPLOAD
+ \ URL
+ \ USERPWD
+ \ USE_SOURCE_PERMISSIONS
+ \ UTC
+ \ UTF
+ \ WRITE
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
+ \ 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_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ VAR
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
+ \ 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_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ VAR
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
+ \ ABI
+ \ 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_PACKAGE_ROOT_PATH
+ \ NO_POLICY_SCOPE
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ OPTIONAL_COMPONENTS
+ \ 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 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
+ \ 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_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ VAR
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
+ \ 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_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ VAR
syn keyword cmakeKWfltk_wrap_ui contained
\ FLTK
syn keyword cmakeKWforeach contained
- \ ARGS IN ITEMS LISTS RANGE
+ \ ARGS
+ \ IN
+ \ ITEMS
+ \ LISTS
+ \ RANGE
syn keyword cmakeKWfunction contained
- \ ARGC ARGN ARGS ARGV PARENT_SCOPE
+ \ ARGC
+ \ ARGN
+ \ ARGS
+ \ ARGV
+ \ PARENT_SCOPE
syn keyword cmakeKWget_cmake_property contained
- \ COMPONENTS GLOBAL MACROS VAR VARIABLES
+ \ COMPONENTS
+ \ GLOBAL
+ \ MACROS
+ \ VAR
+ \ VARIABLES
syn keyword cmakeKWget_directory_property contained
- \ DEFINITION DIRECTORY
+ \ DEFINITION
+ \ DIRECTORY
+ \ INHERITED
syn keyword cmakeKWget_filename_component contained
- \ ABSOLUTE ARG_VAR BASE_DIR CACHE COMP DIRECTORY EXT NAME NAME_WE PATH PROGRAM PROGRAM_ARGS REALPATH VAR
+ \ ABSOLUTE
+ \ ARG_VAR
+ \ BASE_DIR
+ \ COMP
+ \ DIRECTORY
+ \ EXT
+ \ NAME
+ \ NAME_WE
+ \ PATH
+ \ PROGRAM
+ \ PROGRAM_ARGS
+ \ REALPATH
+ \ VAR
syn keyword cmakeKWget_property contained
- \ BRIEF_DOCS CACHE DEFINED DIRECTORY FULL_DOCS GLOBAL INSTALL PROPERTY SET SOURCE TARGET TEST VARIABLE
+ \ BRIEF_DOCS
+ \ DEFINED
+ \ DIRECTORY
+ \ FULL_DOCS
+ \ GLOBAL
+ \ INSTALL
+ \ PROPERTY
+ \ SET
+ \ SOURCE
+ \ TARGET
+ \ TEST
+ \ VARIABLE
syn keyword cmakeKWget_source_file_property contained
- \ LOCATION VAR
+ \ INHERITED
+ \ LOCATION
+ \ VAR
syn keyword cmakeKWget_target_property contained
+ \ INHERITED
\ VAR
syn keyword cmakeKWget_test_property contained
+ \ INHERITED
\ VAR
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
+ \ 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 contained
- \ NO_POLICY_SCOPE OPTIONAL RESULT_VARIABLE
+ \ NO_POLICY_SCOPE
+ \ OPTIONAL
+ \ RESULT_VARIABLE
syn keyword cmakeKWinclude_directories contained
- \ AFTER BEFORE INCLUDE_DIRECTORIES ON SYSTEM
+ \ AFTER
+ \ BEFORE
+ \ INCLUDE_DIRECTORIES
+ \ ON
+ \ SYSTEM
syn keyword cmakeKWinclude_external_msproject contained
- \ GUID MAP_IMPORTED_CONFIG_ PLATFORM TYPE WIX
+ \ GUID
+ \ MAP_IMPORTED_CONFIG_
+ \ PLATFORM
+ \ TYPE
+ \ WIX
syn keyword cmakeKWinclude_guard contained
- \ DIRECTORY GLOBAL TRUE __CURRENT_FILE_VAR__
+ \ DIRECTORY
+ \ GLOBAL
+ \ TRUE
+ \ __CURRENT_FILE_VAR__
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
+ \ AFTER
+ \ APT
+ \ ARCHIVE
+ \ BEFORE
+ \ BUILD_TYPE
+ \ BUNDLE
+ \ CODE
+ \ COMPONENT
+ \ CONFIGURATIONS
+ \ CVS
+ \ DBUILD_TYPE
+ \ DCOMPONENT
+ \ 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_COMPONENT
+ \ 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
+ \ RPM
+ \ RUNTIME
+ \ SCRIPT
+ \ SETGID
+ \ SETUID
+ \ SOVERSION
+ \ TARGETS
+ \ TRUE
+ \ USE_SOURCE_PERMISSIONS
+ \ VERSION
+ \ WORLD_EXECUTE
+ \ WORLD_READ
+ \ WORLD_WRITE
syn keyword cmakeKWinstall_files contained
- \ FILES GLOB
+ \ FILES
+ \ GLOB
syn keyword cmakeKWinstall_programs contained
- \ FILES GLOB PROGRAMS TARGETS
+ \ FILES
+ \ GLOB
+ \ PROGRAMS
+ \ TARGETS
syn keyword cmakeKWinstall_targets contained
- \ DLL RUNTIME_DIRECTORY TARGETS
+ \ DLL
+ \ RUNTIME_DIRECTORY
+ \ TARGETS
+
+syn keyword cmakeKWlink_directories contained
+ \ AFTER
+ \ BEFORE
+ \ LINK_DIRECTORIES
+ \ ON
+ \ ORIGIN
+ \ RPATH
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
+ \ ACTION
+ \ APPEND
+ \ ASCENDING
+ \ CASE
+ \ COMPARE
+ \ DESCENDING
+ \ EXCLUDE
+ \ FILE_BASENAME
+ \ FILTER
+ \ FIND
+ \ GENEX_STRIP
+ \ GET
+ \ INCLUDE
+ \ INSENSITIVE
+ \ INSERT
+ \ INTERNAL
+ \ JOIN
+ \ LENGTH
+ \ ORDER
+ \ OUTPUT_VARIABLE
+ \ PARENT_SCOPE
+ \ PREPEND
+ \ REGEX
+ \ REMOVE_AT
+ \ REMOVE_DUPLICATES
+ \ REMOVE_ITEM
+ \ REPLACE
+ \ REVERSE
+ \ SELECTOR
+ \ SENSITIVE
+ \ SORT
+ \ STRING
+ \ STRIP
+ \ SUBLIST
+ \ TOLOWER
+ \ TOUPPER
+ \ TRANSFORM
syn keyword cmakeKWload_cache contained
- \ EXCLUDE INCLUDE_INTERNALS READ_WITH_PREFIX
+ \ EXCLUDE
+ \ INCLUDE_INTERNALS
+ \ READ_WITH_PREFIX
syn keyword cmakeKWload_command contained
- \ CMAKE_LOADED_COMMAND_ COMMAND_NAME
+ \ CMAKE_LOADED_COMMAND_
+ \ COMMAND_NAME
syn keyword cmakeKWmacro contained
- \ ARGC ARGN ARGS ARGV DEFINED GREATER LISTS NOT _BAR _FOO
+ \ ARGC
+ \ ARGN
+ \ ARGS
+ \ ARGV
+ \ DEFINED
+ \ GREATER
+ \ LISTS
+ \ NOT
+ \ _BAR
+ \ _FOO
syn keyword cmakeKWmake_directory contained
\ MAKE_DIRECTORY
syn keyword cmakeKWmark_as_advanced contained
- \ CLEAR FORCE VAR
+ \ CLEAR
+ \ FORCE
+ \ VAR
syn keyword cmakeKWmath contained
\ EXPR
+ \ HEXADECIMAL
+ \ OUTPUT_FORMAT
syn keyword cmakeKWmessage contained
- \ AUTHOR_WARNING DEPRECATION FATAL_ERROR GUI SEND_ERROR STATUS WARNING
+ \ AUTHOR_WARNING
+ \ DEPRECATION
+ \ FATAL_ERROR
+ \ GUI
+ \ SEND_ERROR
+ \ STATUS
+ \ WARNING
syn keyword cmakeKWoption contained
- \ OFF ON
+ \ OFF
+ \ ON
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
+ \ ASM
+ \ CMAKE_PROJECT_
+ \ CUDA
+ \ DESCRIPTION
+ \ HOMEPAGE_URL
+ \ LANGUAGES
+ \ NAME
+ \ NONE
+ \ PROJECT
+ \ VERSION
+ \ _BINARY_DIR
+ \ _DESCRIPTION
+ \ _HOMEPAGE_URL
+ \ _INCLUDE
+ \ _SOURCE_DIR
+ \ _VERSION
+ \ _VERSION_MAJOR
+ \ _VERSION_MINOR
+ \ _VERSION_PATCH
+ \ _VERSION_TWEAK
syn keyword cmakeKWremove contained
- \ REMOVE_ITEM VALUE VAR
+ \ REMOVE_ITEM
+ \ VALUE
+ \ VAR
syn keyword cmakeKWseparate_arguments contained
- \ MSDN NATIVE NATIVE_COMMAND UNIX_COMMAND WINDOWS WINDOWS_COMMAND _COMMAND
+ \ MSDN
+ \ NATIVE
+ \ NATIVE_COMMAND
+ \ UNIX_COMMAND
+ \ WINDOWS
+ \ WINDOWS_COMMAND
+ \ _COMMAND
syn keyword cmakeKWset contained
- \ BOOL CACHE FILEPATH FORCE INTERNAL OFF ON PARENT_SCOPE STRING STRINGS
+ \ BOOL
+ \ FILEPATH
+ \ FORCE
+ \ INTERNAL
+ \ OFF
+ \ ON
+ \ PARENT_SCOPE
+ \ STRING
+ \ STRINGS
syn keyword cmakeKWset_directory_properties contained
\ PROPERTIES
syn keyword cmakeKWset_property contained
- \ APPEND APPEND_STRING CACHE DIRECTORY GLOBAL INSTALL PROPERTY SOURCE TARGET TEST WIX
+ \ APPEND
+ \ APPEND_STRING
+ \ DIRECTORY
+ \ GLOBAL
+ \ INHERITED
+ \ INSTALL
+ \ PROPERTY
+ \ SOURCE
+ \ TARGET
+ \ TEST
+ \ WIX
syn keyword cmakeKWset_source_files_properties contained
\ PROPERTIES
syn keyword cmakeKWset_target_properties contained
\ PROPERTIES
+ \ TARGET
syn keyword cmakeKWset_tests_properties contained
\ PROPERTIES
syn keyword cmakeKWsource_group contained
- \ FILES PREFIX REGULAR_EXPRESSION TREE
+ \ FILES
+ \ PREFIX
+ \ REGULAR_EXPRESSION
+ \ TREE
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 PREPEND RANDOM RANDOM_SEED REGEX REPLACE REVERSE RFC SHA SOURCE_DATE_EPOCH STRIP SUBSTRING SZ TIMESTAMP TOLOWER TOUPPER TYPE US UTC UUID
+ \ ALPHABET
+ \ APPEND
+ \ ASCII
+ \ CMAKE_MATCH_
+ \ COMPARE
+ \ CONCAT
+ \ CONFIGURE
+ \ EQUAL
+ \ ESCAPE_QUOTES
+ \ FIND
+ \ GENEX_STRIP
+ \ GREATER
+ \ GREATER_EQUAL
+ \ GUID
+ \ HASH
+ \ JOIN
+ \ LENGTH
+ \ LESS
+ \ LESS_EQUAL
+ \ MAKE_C_IDENTIFIER
+ \ MATCH
+ \ MATCHALL
+ \ MATCHES
+ \ NAMESPACE
+ \ NOTEQUAL
+ \ ONLY
+ \ PREPEND
+ \ RANDOM
+ \ RANDOM_SEED
+ \ REGEX
+ \ REPLACE
+ \ REVERSE
+ \ RFC
+ \ SHA
+ \ SOURCE_DATE_EPOCH
+ \ STRIP
+ \ SUBSTRING
+ \ SZ
+ \ TIMESTAMP
+ \ TOLOWER
+ \ TOUPPER
+ \ TYPE
+ \ US
+ \ UTC
+ \ UUID
syn keyword cmakeKWsubdirs contained
- \ EXCLUDE_FROM_ALL PREORDER
+ \ EXCLUDE_FROM_ALL
+ \ PREORDER
syn keyword cmakeKWtarget_compile_definitions contained
- \ ALIAS COMPILE_DEFINITIONS IMPORTED INTERFACE INTERFACE_COMPILE_DEFINITIONS PRIVATE PUBLIC
+ \ ALIAS
+ \ COMPILE_DEFINITIONS
+ \ FOO
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_COMPILE_DEFINITIONS
+ \ PRIVATE
+ \ PUBLIC
syn keyword cmakeKWtarget_compile_features contained
- \ ALIAS COMPILE_FEATURES IMPORTED INTERFACE INTERFACE_COMPILE_FEATURES PRIVATE PUBLIC
+ \ ALIAS
+ \ COMPILE_FEATURES
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_COMPILE_FEATURES
+ \ PRIVATE
+ \ PUBLIC
syn keyword cmakeKWtarget_compile_options contained
- \ ALIAS BEFORE COMPILE_OPTIONS IMPORTED INTERFACE INTERFACE_COMPILE_OPTIONS PRIVATE PUBLIC
+ \ ALIAS
+ \ BEFORE
+ \ COMPILE_OPTIONS
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_COMPILE_OPTIONS
+ \ PRIVATE
+ \ PUBLIC
+ \ SHELL
+ \ UNIX_COMMAND
syn keyword cmakeKWtarget_include_directories contained
- \ ALIAS BEFORE BUILD_INTERFACE IMPORTED INCLUDE_DIRECTORIES INSTALL_INTERFACE INTERFACE INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES PRIVATE PUBLIC SYSTEM
+ \ ALIAS
+ \ BEFORE
+ \ BUILD_INTERFACE
+ \ IMPORTED
+ \ INCLUDE_DIRECTORIES
+ \ INSTALL_INTERFACE
+ \ INTERFACE
+ \ INTERFACE_INCLUDE_DIRECTORIES
+ \ INTERFACE_LINK_LIBRARIES
+ \ INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
+ \ PRIVATE
+ \ PUBLIC
+ \ SYSTEM
+
+syn keyword cmakeKWtarget_link_directories contained
+ \ ALIAS
+ \ BEFORE
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_LINK_DIRECTORIES
+ \ LINK_DIRECTORIES
+ \ ORIGIN
+ \ PRIVATE
+ \ PUBLIC
+ \ RPATH
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
+ \ ALIAS
+ \ DA
+ \ DAG
+ \ DEBUG_CONFIGURATIONS
+ \ DOBJ
+ \ IMPORTED
+ \ IMPORTED_NO_SONAME
+ \ INTERFACE
+ \ INTERFACE_LINK_LIBRARIES
+ \ LINK_INTERFACE_LIBRARIES
+ \ LINK_INTERFACE_LIBRARIES_DEBUG
+ \ LINK_INTERFACE_MULTIPLICITY
+ \ LINK_OPTIONS
+ \ LINK_PRIVATE
+ \ LINK_PUBLIC
+ \ OBJECT
+ \ OLD
+ \ OSX
+ \ PRIVATE
+ \ PUBLIC
+ \ SHARED
+ \ STATIC
+
+syn keyword cmakeKWtarget_link_options contained
+ \ ALIAS
+ \ BEFORE
+ \ CMAKE_
+ \ GCC
+ \ GNU
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_LINK_OPTIONS
+ \ LANG
+ \ LINKER
+ \ LINK_OPTIONS
+ \ PRIVATE
+ \ PUBLIC
+ \ SHELL
+ \ UNIX_COMMAND
+ \ _LINKER_WRAPPER_FLAG
+ \ _LINKER_WRAPPER_FLAG_SEP
syn keyword cmakeKWtarget_sources contained
- \ ALIAS IMPORTED INTERFACE INTERFACE_SOURCES PRIVATE PUBLIC SOURCES
+ \ ALIAS
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_SOURCES
+ \ PRIVATE
+ \ PUBLIC
+ \ SOURCES
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
+ \ 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 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
+ \ 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 contained
- \ CACHE LD_LIBRARY_PATH PARENT_SCOPE
+ \ LD_LIBRARY_PATH
+ \ PARENT_SCOPE
+ \ VAR
syn keyword cmakeKWuse_mangled_mesa contained
- \ GL OUTPUT_DIRECTORY PATH_TO_MESA
+ \ GL
+ \ OUTPUT_DIRECTORY
+ \ PATH_TO_MESA
syn keyword cmakeKWvariable_requires contained
- \ RESULT_VARIABLE TEST_VARIABLE
+ \ RESULT_VARIABLE
+ \ TEST_VARIABLE
syn keyword cmakeKWvariable_watch contained
\ COMMAND
\ ARGS
syn keyword cmakeKWwrite_file contained
- \ APPEND CONFIGURE_FILE NOTE WRITE
+ \ APPEND
+ \ CONFIGURE_FILE
+ \ NOTE
+ \ WRITE
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
+ \ AND
+ \ ANGLE
+ \ BOOL
+ \ BUILD_INTERFACE
+ \ CMAKE_
+ \ CMAKE_CXX_COMPILER_VERSION
+ \ COMMA
+ \ COMMAND
+ \ COMPILE_DEFINITIONS
+ \ COMPILE_FEATURES
+ \ COMPILE_LANGUAGE
+ \ COMPILING_CUDA
+ \ COMPILING_CXX
+ \ CONFIG
+ \ CONFIGURATION
+ \ CUDA
+ \ CUSTOM_KEYS
+ \ CXX_COMPILER_ID
+ \ CXX_COMPILER_VERSION
+ \ CXX_STANDARD
+ \ C_COMPILER_ID
+ \ C_COMPILER_VERSION
+ \ C_STANDARD
+ \ DEBUG_MODE
+ \ EXPORT
+ \ FOO_EXTRA_THINGS
+ \ GENEX_EVAL
+ \ GNU
+ \ IF
+ \ INCLUDE_DIRECTORIES
+ \ INSTALL_INTERFACE
+ \ INSTALL_PREFIX
+ \ INTERFACE_LINK_LIBRARIES
+ \ IN_LIST
+ \ JOIN
+ \ LANG
+ \ LINK_LIBRARIES
+ \ LINK_ONLY
+ \ LOWER_CASE
+ \ MAKE_C_IDENTIFIER
+ \ MAP_IMPORTED_CONFIG_
+ \ MSYS
+ \ NOT
+ \ OBJECT_LIBRARY
+ \ OLD_COMPILER
+ \ PDB_NAME
+ \ PDB_NAME_
+ \ PDB_OUTPUT_DIRECTORY
+ \ PDB_OUTPUT_DIRECTORY_
+ \ PLATFORM_ID
+ \ PRIVATE
+ \ PUBLIC
+ \ SDK
+ \ SEMICOLON
+ \ SHELL_PATH
+ \ STREQUAL
+ \ TARGET_BUNDLE_CONTENT_DIR
+ \ TARGET_BUNDLE_DIR
+ \ TARGET_EXISTS
+ \ TARGET_FILE
+ \ TARGET_FILE_DIR
+ \ TARGET_FILE_NAME
+ \ TARGET_GENEX_EVAL
+ \ TARGET_LINKER_FILE
+ \ TARGET_LINKER_FILE_DIR
+ \ TARGET_LINKER_FILE_NAME
+ \ TARGET_NAME
+ \ TARGET_NAME_IF_EXISTS
+ \ TARGET_OBJECTS
+ \ TARGET_PDB_FILE
+ \ TARGET_PDB_FILE_DIR
+ \ TARGET_PDB_FILE_NAME
+ \ TARGET_POLICY
+ \ TARGET_PROPERTY
+ \ TARGET_SONAME_FILE
+ \ TARGET_SONAME_FILE_DIR
+ \ TARGET_SONAME_FILE_NAME
+ \ UPPER_CASE
+ \ VERSION_EQUAL
+ \ VERSION_GREATER
+ \ VERSION_GREATER_EQUAL
+ \ VERSION_LESS
+ \ VERSION_LESS_EQUAL
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_guard 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
+ \ add_compile_definitions
+ \ add_compile_options
+ \ add_custom_command
+ \ add_custom_target
+ \ add_definitions
+ \ add_dependencies
+ \ add_executable
+ \ add_library
+ \ add_link_options
+ \ 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_guard
+ \ 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_directories
+ \ target_link_libraries
+ \ target_link_options
+ \ target_sources
+ \ try_compile
+ \ try_run
+ \ unset
+ \ variable_watch
\ nextgroup=cmakeArguments
syn keyword cmakeCommandConditional
- \ else elseif endif if
+ \ else
+ \ elseif
+ \ endif
+ \ if
\ nextgroup=cmakeArguments
syn keyword cmakeCommandRepeat
- \ endforeach endwhile foreach while
+ \ 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
+ \ 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
\ TODO FIXME XXX
\ contained
+hi def link cmakeBracketArgument String
+hi def link cmakeBracketComment Comment
hi def link cmakeCommand Function
hi def link cmakeCommandConditional Conditional
hi def link cmakeCommandDeprecated WarningMsg
hi def link cmakeEscaped Special
hi def link cmakeGeneratorExpression WarningMsg
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 cmakeVariable Identifier
hi def link cmakeKWExternalProject ModeMsg
+hi def link cmakeKWadd_compile_definitions ModeMsg
hi def link cmakeKWadd_compile_options ModeMsg
hi def link cmakeKWadd_custom_command ModeMsg
hi def link cmakeKWadd_custom_target ModeMsg
hi def link cmakeKWadd_dependencies ModeMsg
hi def link cmakeKWadd_executable ModeMsg
hi def link cmakeKWadd_library ModeMsg
+hi def link cmakeKWadd_link_options ModeMsg
hi def link cmakeKWadd_subdirectory ModeMsg
hi def link cmakeKWadd_test ModeMsg
hi def link cmakeKWbuild_command ModeMsg
hi def link cmakeKWinstall_files ModeMsg
hi def link cmakeKWinstall_programs ModeMsg
hi def link cmakeKWinstall_targets ModeMsg
+hi def link cmakeKWlink_directories ModeMsg
hi def link cmakeKWlist ModeMsg
hi def link cmakeKWload_cache ModeMsg
hi def link cmakeKWload_command ModeMsg
hi def link cmakeKWtarget_compile_features ModeMsg
hi def link cmakeKWtarget_compile_options ModeMsg
hi def link cmakeKWtarget_include_directories ModeMsg
+hi def link cmakeKWtarget_link_directories ModeMsg
hi def link cmakeKWtarget_link_libraries ModeMsg
+hi def link cmakeKWtarget_link_options ModeMsg
hi def link cmakeKWtarget_sources ModeMsg
hi def link cmakeKWtry_compile ModeMsg
hi def link cmakeKWtry_run ModeMsg
hi def link cmakeKWwhile ModeMsg
hi def link cmakeKWwrite_file ModeMsg
+" Manually added - difficult to parse out of documentation
+syn case ignore
+
+syn keyword cmakeCommandManuallyAdded
+ \ configure_package_config_file write_basic_package_version_file
+ \ nextgroup=cmakeArguments
+
+syn case match
+
+syn keyword cmakeKWconfigure_package_config_file contained
+ \ INSTALL_DESTINATION PATH_VARS NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO INSTALL_PREFIX
+
+syn keyword cmakeKWconfigure_package_config_file_constants contained
+ \ AnyNewerVersion SameMajorVersion SameMinorVersion ExactVersion
+
+syn keyword cmakeKWwrite_basic_package_version_file contained
+ \ VERSION COMPATIBILITY
+
+hi def link cmakeCommandManuallyAdded Function
+
+hi def link cmakeKWconfigure_package_config_file ModeMsg
+hi def link cmakeKWwrite_basic_package_version_file ModeMsg
+hi def link cmakeKWconfigure_package_config_file_constants Constant
+
let b:current_syntax = "cmake"
let &cpo = s:keepcpo
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;-w;-DCMAKE_IWYU")
+ "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp;-w")
+ list(APPEND CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${CMake_IWYU_OPTIONS})
endif()
set(CURL_SPECIAL_ZLIB_H ${CMAKE_ZLIB_HEADER})
set(CURL_SPECIAL_LIBZ_INCLUDES ${CMAKE_ZLIB_INCLUDES})
set(CURL_SPECIAL_LIBZ ${CMAKE_ZLIB_LIBRARIES})
- add_definitions(-DCURL_STATICLIB)
set(CMAKE_CURL_INCLUDES)
set(CMAKE_CURL_LIBRARIES cmcurl)
if(CMAKE_TESTS_CDASH_SERVER)
#---------------------------------------------------------------------
# Build or use system libarchive for CMake and CTest.
if(CMAKE_USE_SYSTEM_LIBARCHIVE)
- find_package(LibArchive 3.0.0)
+ find_package(LibArchive 3.1.0)
if(NOT LibArchive_FOUND)
message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBARCHIVE is ON but LibArchive is not found!")
endif()
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 LZMA library if found")
+ set(ENABLE_LZ4 OFF CACHE INTERNAL "Enable the use of the system LZ4 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")
endif()
endif()
-# add a test
-add_test(SystemInformationNew "${CMAKE_CMAKE_COMMAND}"
- --system-information -G "${CMAKE_GENERATOR}" )
+if(BUILD_TESTING)
+ add_test(SystemInformationNew "${CMAKE_CMAKE_COMMAND}"
+ --system-information -G "${CMAKE_GENERATOR}" )
+endif()
if(NOT CMake_TEST_EXTERNAL_CMAKE)
# Install license file as it requires.
#. Push a topic branch to a personal repository fork on GitLab.
#. Create a GitLab Merge Request targeting the upstream ``master`` branch
(even if the change is intended for merge to the ``release`` branch).
- Check the box to allow edits from maintainers.
+ Check the box labelled "Allow commits from members who can merge to the
+ target branch". This will allow maintainers to make minor edits on your
+ behalf.
The merge request will enter the `CMake Review Process`_ for consideration.
.. _`commit messages`: Help/dev/review.rst#commit-messages
.. _`CMake Review Process`: Help/dev/review.rst
+CMake Dashboard Client
+======================
+
+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.
+
+See documentation on `CMake Testing Process`_ for more information.
+
+.. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake
+.. _`CMake Testing Process`: Help/dev/testing.rst
+
License
=======
"ERROR:")
list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
+ "warning: cast from 'char\\*' to 'cmCursesWidget\\*' increases required alignment of target type" # Occurs when using Solaris's system libform
"xtree.[0-9]+. : warning C4702: unreachable code"
"warning LNK4221"
"warning LNK4204" # Occurs by race condition with objects in small libs
"cmFortranLexer.cxx:[0-9]+:[0-9]+: warning: Call to 'realloc' has an allocation size of 0 bytes"
"testProcess.*warning: Dereference of null pointer .loaded from variable .invalidAddress.."
"liblzma/simple/x86.c:[0-9]+:[0-9]+: warning: The result of the '<<' expression is undefined"
+ "liblzma/common/index_encoder.c:[0-9]+:[0-9]+: warning: Value stored to .* during its initialization is never read"
"libuv/src/.*:[0-9]+:[0-9]+: warning: Dereference of null pointer"
"libuv/src/.*:[0-9]+:[0-9]+: warning: The left operand of '==' is a garbage value"
)
.. |FIND_ARGS_XXX| replace:: <VAR> NAMES name
-On OS X the :variable:`CMAKE_FIND_FRAMEWORK` and
+On macOS the :variable:`CMAKE_FIND_FRAMEWORK` and
:variable:`CMAKE_FIND_APPBUNDLE` variables determine the order of
preference between Apple-style and unix-style package components.
--- /dev/null
+To pass options to the linker tool, each compiler driver has is own syntax.
+The ``LINKER:`` prefix can be used to specify, in a portable way, options
+to pass to the linker tool. The ``LINKER:`` prefix is replaced by the required
+driver option and the rest of the option string defines linker arguments using
+``,`` as separator. These arguments will be formatted according to the
+:variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG` and
+:variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP` variables.
+
+For example, ``"LINKER:-z,defs"`` becomes ``-Xlinker -z -Xlinker defs`` for
+``Clang`` and ``-Wl,-z,defs`` for ``GNU GCC``.
+
+The ``LINKER:`` prefix can be specified as part of a ``SHELL:`` prefix
+expression.
+
+The ``LINKER:`` prefix supports, as alternate syntax, specification of
+arguments using ``SHELL:`` prefix and space as separator. Previous example
+becomes ``"LINKER:SHELL:-z defs"``.
+
+.. note::
+
+ Specifying ``SHELL:`` prefix elsewhere than at the beginning of the
+ ``LINKER:`` prefix is not supported.
-The final set of compile options used for a target is constructed by
+The final set of compile or link options used for a target is constructed by
accumulating options from the current target and the usage requirements of
it dependencies. The set of options is de-duplicated to avoid repetition.
While beneficial for individual options, the de-duplication step can break
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
-.. include:: COMPILE_OPTIONS_SHELL.txt
+.. include:: OPTIONS_SHELL.txt
If it is a relative path it will be interpreted relative to the
build tree directory corresponding to the current source directory.
+ Arguments to ``WORKING_DIRECTORY`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
``DEPFILE``
Specify a ``.d`` depfile for the :generator:`Ninja` generator.
A ``.d`` file holds dependencies usually emitted by the custom
Execute the command with the given current working directory.
If it is a relative path it will be interpreted relative to the
build tree directory corresponding to the current source directory.
+
+ Arguments to ``WORKING_DIRECTORY`` may use
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
``MODULE`` libraries the :prop_tgt:`POSITION_INDEPENDENT_CODE` target
property is set to ``ON`` automatically.
A ``SHARED`` or ``STATIC`` library may be marked with the :prop_tgt:`FRAMEWORK`
-target property to create an OS X Framework.
+target property to create an macOS Framework.
If a library does not export any symbols, it must not be declared as a
``SHARED`` library. For example, a Windows resource DLL or a managed C++/CLI
* :command:`set_property`,
* :command:`target_link_libraries(INTERFACE)`,
+* :command:`target_link_options(INTERFACE)`,
* :command:`target_include_directories(INTERFACE)`,
* :command:`target_compile_options(INTERFACE)`,
* :command:`target_compile_definitions(INTERFACE)`, and
--- /dev/null
+add_link_options
+----------------
+
+Adds options to the link of shared library, module and executable targets.
+
+::
+
+ add_link_options(<option> ...)
+
+Adds options to the link step for targets in the current directory and below
+that are added after this command is invoked. See documentation of the
+:prop_dir:`directory <LINK_OPTIONS>` and
+:prop_tgt:`target <LINK_OPTIONS>` ``LINK_OPTIONS`` properties.
+
+This command can be used to add any options, but alternative commands
+exist to add libraries (:command:`target_link_libraries` or
+:command:`link_libraries`).
+
+Arguments to ``add_link_options`` may use "generator expressions" with
+the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+manual for more on defining buildsystem properties.
+
+.. include:: OPTIONS_SHELL.txt
+
+.. include:: LINK_OPTIONS_LINKER.txt
``NUMBER_OF_PHYSICAL_CORES`` Number of physical cores
``HOSTNAME`` Hostname
``FQDN`` Fully qualified domain name
-``TOTAL_VIRTUAL_MEMORY`` Total virtual memory in megabytes
-``AVAILABLE_VIRTUAL_MEMORY`` Available virtual memory in megabytes
-``TOTAL_PHYSICAL_MEMORY`` Total physical memory in megabytes
-``AVAILABLE_PHYSICAL_MEMORY`` Available physical memory in megabytes
+``TOTAL_VIRTUAL_MEMORY`` Total virtual memory in MiB [#mebibytes]_
+``AVAILABLE_VIRTUAL_MEMORY`` Available virtual memory in MiB [#mebibytes]_
+``TOTAL_PHYSICAL_MEMORY`` Total physical memory in MiB [#mebibytes]_
+``AVAILABLE_PHYSICAL_MEMORY`` Available physical memory in MiB [#mebibytes]_
``IS_64BIT`` One if processor is 64Bit
``HAS_FPU`` One if processor has floating point unit
``HAS_MMX`` One if processor supports MMX instructions
``OS_VERSION`` The OS build ID
``OS_PLATFORM`` See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`
============================= ================================================
+
+.. rubric:: Footnotes
+
+.. [#mebibytes] One MiB (mebibyte) is equal to 1024x1024 bytes.
[RETRY_COUNT <count>]
[RETRY_DELAY <delay>]
[RETURN_VALUE <result-var>]
+ [CAPTURE_CMAKE_ERROR <result-var>]
[QUIET]
)
Store in the ``<result-var>`` variable ``0`` for success and
non-zero on failure.
+``CAPTURE_CMAKE_ERROR <result-var>``
+ Store in the ``<result-var>`` variable -1 if there are any errors running
+ the command and prevent ctest from returning non-zero if an error occurs.
+
``QUIET``
Suppress all non-error messages that would have otherwise been
printed to the console.
[HTTPHEADER <header>]
[RETRY_COUNT <count>]
[RETRY_DELAY <delay>]
+ [RETURN_VALUE <result-var>]
[QUIET])
This second signature is used to upload files to CDash via the CDash
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 ``HTTPHEADER``, ``RETRY_COUNT``, ``RETRY_DELAY``, and
-``QUIET`` options as described above.
+This signature accepts the ``HTTPHEADER``, ``RETRY_COUNT``, ``RETRY_DELAY``,
+``RETURN_VALUE`` and ``QUIET`` options as described above.
::
- ctest_update([SOURCE <source-dir>] [RETURN_VALUE <result-var>] [QUIET])
+ ctest_update([SOURCE <source-dir>]
+ [RETURN_VALUE <result-var>]
+ [CAPTURE_CMAKE_ERROR <result-var>]
+ [QUIET])
Update the source tree from version control and record results in
``Update.xml`` for submission with the :command:`ctest_submit` command.
Store in the ``<result-var>`` variable the number of files
updated or ``-1`` on error.
+``CAPTURE_CMAKE_ERROR <result-var>``
+ Store in the ``<result-var>`` variable -1 if there are any errors running
+ the command and prevent ctest from returning non-zero if an error occurs.
+
``QUIET``
Tell CTest to suppress most non-error messages that it would
have otherwise printed to the console. CTest will still report
::
- export(PACKAGE <name>)
+ export(PACKAGE <PackageName>)
Store the current build directory in the CMake user package registry
-for package ``<name>``. The find_package command may consider the
-directory while searching for package ``<name>``. This helps dependent
+for package ``<PackageName>``. The find_package command may consider the
+directory while searching for package ``<PackageName>``. This helps dependent
projects find and use a package from the current project's build tree
without help from the user. Note that the entry in the package
registry that this command creates works only in conjunction with a
-package configuration file (``<name>Config.cmake``) that works with the
+package configuration file (``<PackageName>Config.cmake``) that works with the
build tree. In some cases, for example for packaging and for system
wide installations, it is not desirable to write the user package
registry. If the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable
find_package
------------
-Load settings for an external project.
+.. only:: html
+
+ .. contents::
+
+Find an external project, and load its settings.
+
+.. _`basic signature`:
+
+Basic Signature and Module Mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- find_package(<package> [version] [EXACT] [QUIET] [MODULE]
+ find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
-Finds and loads settings from an external project. ``<package>_FOUND``
+Finds and loads settings from an external project. ``<PackageName>_FOUND``
will be set to indicate whether the package was found. When the
package is found package-specific information is provided through
variables and :ref:`Imported Targets` documented by the package itself. The
``QUIET`` option disables messages if the package cannot be found. The
-``MODULE`` option disables the second signature documented below. The
``REQUIRED`` option stops processing with an error message if the package
cannot be found.
inside a find-module, the corresponding arguments are forwarded
automatically from the outer call (including the ``EXACT`` flag for
``[version]``). Version support is currently provided only on a
-package-by-package basis (details below).
+package-by-package basis (see the `Version Selection`_ section below).
-User code should generally look for packages using the above simple
-signature. The remainder of this command documentation specifies the
+See the :command:`cmake_policy` command documentation for discussion
+of the ``NO_POLICY_SCOPE`` option.
+
+The command has two modes by which it searches for packages: "Module"
+mode and "Config" mode. The above signature selects Module mode.
+If no module is found the command falls back to Config mode, described
+below. This fall back is disabled if the ``MODULE`` option is given.
+
+In Module mode, CMake searches for a file called ``Find<PackageName>.cmake``
+in the :variable:`CMAKE_MODULE_PATH` followed by the CMake installation.
+If the file is found, it is read and processed by CMake. It is responsible
+for finding the package, checking the version, and producing any needed
+messages. Some find-modules provide limited or no support for versioning;
+check the module documentation.
+
+Full Signature and Config Mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+User code should generally look for packages using the above `basic
+signature`_. The remainder of this command documentation specifies the
full command signature and details of the search process. Project
maintainers wishing to provide a package to be found by this command
are encouraged to read on.
-The command has two modes by which it searches for packages: "Module"
-mode and "Config" mode. Module mode is available when the command is
-invoked with the above reduced signature. CMake searches for a file
-called ``Find<package>.cmake`` in the :variable:`CMAKE_MODULE_PATH`
-followed by the CMake installation. If the file is found, it is read
-and processed by CMake. It is responsible for finding the package,
-checking the version, and producing any needed messages. Many
-find-modules provide limited or no support for versioning; check
-the module documentation. If no module is found and the ``MODULE``
-option is not given the command proceeds to Config mode.
-
The complete Config mode command signature is::
- find_package(<package> [version] [EXACT] [QUIET]
+ find_package(<PackageName> [version] [EXACT] [QUIET]
[REQUIRED] [[COMPONENTS] [components...]]
[CONFIG|NO_MODULE]
[NO_POLICY_SCOPE]
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH])
-The ``CONFIG`` option may be used to skip Module mode explicitly and
-switch to Config mode. It is synonymous to using ``NO_MODULE``. Config
-mode is also implied by use of options not specified in the reduced
-signature.
+The ``CONFIG`` option, the synonymous ``NO_MODULE`` option, or the use
+of options not specified in the `basic signature`_ all enforce pure Config
+mode. In pure Config mode, the command skips Module mode search and
+proceeds at once with Config mode search.
-Config mode attempts to locate a configuration file provided by the
-package to be found. A cache entry called ``<package>_DIR`` is created to
+Config mode search attempts to locate a configuration file provided by the
+package to be found. A cache entry called ``<PackageName>_DIR`` is created to
hold the directory containing the file. By default the command
-searches for a package with the name ``<package>``. If the ``NAMES`` option
-is given the names following it are used instead of ``<package>``. The
-command searches for a file called ``<name>Config.cmake`` or
-``<lower-case-name>-config.cmake`` for each name specified. A
-replacement set of possible configuration file names may be given
+searches for a package with the name ``<PackageName>``. If the ``NAMES`` option
+is given the names following it are used instead of ``<PackageName>``.
+The command searches for a file called ``<PackageName>Config.cmake`` or
+``<lower-case-package-name>-config.cmake`` for each name specified.
+A replacement set of possible configuration file names may be given
using the ``CONFIGS`` option. The search procedure is specified below.
Once found, the configuration file is read and processed by CMake.
Since the file is provided by the package it already knows the
location of package contents. The full path to the configuration file
-is stored in the cmake variable ``<package>_CONFIG``.
+is stored in the cmake variable ``<PackageName>_CONFIG``.
All configuration files which have been considered by CMake while
searching for an installation of the package with an appropriate
-version are stored in the cmake variable ``<package>_CONSIDERED_CONFIGS``,
-the associated versions in ``<package>_CONSIDERED_VERSIONS``.
+version are stored in the cmake variable ``<PackageName>_CONSIDERED_CONFIGS``,
+the associated versions in ``<PackageName>_CONSIDERED_VERSIONS``.
If the package configuration file cannot be found CMake will generate
an error describing the problem unless the ``QUIET`` argument is
specified. If ``REQUIRED`` is specified and the package is not found a
fatal error is generated and the configure step stops executing. If
-``<package>_DIR`` has been set to a directory not containing a
+``<PackageName>_DIR`` has been set to a directory not containing a
configuration file CMake will ignore it and search from scratch.
+Package maintainers providing CMake package configuration files are
+encouraged to name and install them such that the `Search Procedure`_
+outlined below will find them without requiring use of additional options.
+
+Version Selection
+^^^^^^^^^^^^^^^^^
+
When the ``[version]`` argument is given Config mode will only find a
version of the package that claims compatibility with the requested
version (format is ``major[.minor[.patch[.tweak]]]``). If the ``EXACT``
variables have been defined:
``PACKAGE_FIND_NAME``
- the ``<package>`` name
+ the ``<PackageName>``
``PACKAGE_FIND_VERSION``
full requested version string
``PACKAGE_FIND_VERSION_MAJOR``
are not available after the find_package call returns. If the version
is acceptable the following variables are set:
-``<package>_VERSION``
+``<PackageName>_VERSION``
full provided version string
-``<package>_VERSION_MAJOR``
+``<PackageName>_VERSION_MAJOR``
major version if provided, else 0
-``<package>_VERSION_MINOR``
+``<PackageName>_VERSION_MINOR``
minor version if provided, else 0
-``<package>_VERSION_PATCH``
+``<PackageName>_VERSION_PATCH``
patch version if provided, else 0
-``<package>_VERSION_TWEAK``
+``<PackageName>_VERSION_TWEAK``
tweak version if provided, else 0
-``<package>_VERSION_COUNT``
+``<PackageName>_VERSION_COUNT``
number of version components, 0 to 4
and the corresponding package configuration file is loaded.
before calling ``find_package``.
-Config mode provides an elaborate interface and search procedure.
-Much of the interface is provided for completeness and for use
-internally by find-modules loaded by Module mode. Most user code
-should simply call::
-
- find_package(<package> [major[.minor]] [EXACT] [REQUIRED|QUIET])
-
-in order to find a package. Package maintainers providing CMake
-package configuration files are encouraged to name and install them
-such that the procedure outlined below will find them without
-requiring use of additional options.
+Search Procedure
+^^^^^^^^^^^^^^^^
CMake constructs a set of possible installation prefixes for the
package. Under each prefix several directories are searched for a
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/ (W/U)
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (W/U)
-On systems supporting OS X Frameworks and Application Bundles the
+On systems supporting macOS Frameworks and Application Bundles the
following directories are searched for frameworks or bundles
containing a configuration file::
<prefix>/<name>.app/Contents/Resources/CMake/ (A)
In all cases the ``<name>`` is treated as case-insensitive and corresponds
-to any of the names specified (``<package>`` or names given by ``NAMES``).
+to any of the names specified (``<PackageName>`` or names given by ``NAMES``).
Paths with ``lib/<arch>`` are enabled if the
:variable:`CMAKE_LIBRARY_ARCHITECTURE` variable is set. ``lib*`` includes one
(``;`` on Windows and ``:`` on UNIX).
This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed::
- <package>_DIR
+ <PackageName>_DIR
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
hard-coded guesses.
.. |FIND_XXX| replace:: find_package
-.. |FIND_ARGS_XXX| replace:: <package>
+.. |FIND_ARGS_XXX| replace:: <PackageName>
.. |CMAKE_FIND_ROOT_PATH_MODE_XXX| replace::
:variable:`CMAKE_FIND_ROOT_PATH_MODE_PACKAGE`
Every non-REQUIRED ``find_package`` call can be disabled by setting the
:variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to ``TRUE``.
+Package File Interface Variables
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
When loading a find module or package configuration file ``find_package``
defines variables to provide information about the call arguments (and
restores their original state before returning):
``CMAKE_FIND_PACKAGE_NAME``
- the ``<package>`` name which is searched for
-``<package>_FIND_REQUIRED``
+ the ``<PackageName>`` which is searched for
+``<PackageName>_FIND_REQUIRED``
true if ``REQUIRED`` option was given
-``<package>_FIND_QUIETLY``
+``<PackageName>_FIND_QUIETLY``
true if ``QUIET`` option was given
-``<package>_FIND_VERSION``
+``<PackageName>_FIND_VERSION``
full requested version string
-``<package>_FIND_VERSION_MAJOR``
+``<PackageName>_FIND_VERSION_MAJOR``
major version if requested, else 0
-``<package>_FIND_VERSION_MINOR``
+``<PackageName>_FIND_VERSION_MINOR``
minor version if requested, else 0
-``<package>_FIND_VERSION_PATCH``
+``<PackageName>_FIND_VERSION_PATCH``
patch version if requested, else 0
-``<package>_FIND_VERSION_TWEAK``
+``<PackageName>_FIND_VERSION_TWEAK``
tweak version if requested, else 0
-``<package>_FIND_VERSION_COUNT``
+``<PackageName>_FIND_VERSION_COUNT``
number of version components, 0 to 4
-``<package>_FIND_VERSION_EXACT``
+``<PackageName>_FIND_VERSION_EXACT``
true if ``EXACT`` option was given
-``<package>_FIND_COMPONENTS``
+``<PackageName>_FIND_COMPONENTS``
list of requested components
-``<package>_FIND_REQUIRED_<c>``
+``<PackageName>_FIND_REQUIRED_<c>``
true if component ``<c>`` is required,
false if component ``<c>`` is optional
``[version]`` options automatically but leaves it to the package
configuration file to handle components in a way that makes sense
for the package. The package configuration file may set
-``<package>_FOUND`` to false to tell ``find_package`` that component
+``<PackageName>_FOUND`` to false to tell ``find_package`` that component
requirements are not satisfied.
-
-See the :command:`cmake_policy` command documentation for discussion
-of the ``NO_POLICY_SCOPE`` option.
``if(<variable|string> VERSION_LESS <variable|string>)``
Component-wise integer version number comparison (version format is
- ``major[.minor[.patch[.tweak]]]``).
+ ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
+ Any non-integer version component or non-integer trailing part of a version
+ component effectively truncates the string at that point.
``if(<variable|string> VERSION_GREATER <variable|string>)``
Component-wise integer version number comparison (version format is
- ``major[.minor[.patch[.tweak]]]``).
+ ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
+ Any non-integer version component or non-integer trailing part of a version
+ component effectively truncates the string at that point.
``if(<variable|string> VERSION_EQUAL <variable|string>)``
Component-wise integer version number comparison (version format is
- ``major[.minor[.patch[.tweak]]]``).
+ ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
+ Any non-integer version component or non-integer trailing part of a version
+ component effectively truncates the string at that point.
``if(<variable|string> VERSION_LESS_EQUAL <variable|string>)``
Component-wise integer version number comparison (version format is
- ``major[.minor[.patch[.tweak]]]``).
+ ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
+ Any non-integer version component or non-integer trailing part of a version
+ component effectively truncates the string at that point.
``if(<variable|string> VERSION_GREATER_EQUAL <variable|string>)``
Component-wise integer version number comparison (version format is
- ``major[.minor[.patch[.tweak]]]``).
+ ``major[.minor[.patch[.tweak]]]``, omitted components are treated as zero).
+ Any non-integer version component or non-integer trailing part of a version
+ component effectively truncates the string at that point.
``if(<variable|string> IN_LIST <variable>)``
True if the given element is contained in the named list variable.
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.
+
+.. note::
+
+ Prefer the :command:`target_include_directories` command to add include
+ directories to individual targets and optionally propagate/export them
+ to dependents.
installation. Use the :variable:`CMAKE_INSTALL_MESSAGE` variable
to control which messages are printed.
+Many of the ``install()`` variants implicitly create the directories
+containing the installed files. If
+:variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` is set, these
+directories will be created with the permissions specified. Otherwise,
+they will be created according to the uname rules on Unix-like platforms.
+Windows platforms are unaffected.
+
Installing Targets
^^^^^^^^^^^^^^^^^^
``ARCHIVE``
Static libraries are treated as ``ARCHIVE`` targets, except those
- marked with the ``FRAMEWORK`` property on OS X (see ``FRAMEWORK``
+ marked with the ``FRAMEWORK`` property on macOS (see ``FRAMEWORK``
below.) For DLL platforms (all Windows-based systems including
Cygwin), the DLL import library is treated as an ``ARCHIVE`` target.
``LIBRARY``
Module libraries are always treated as ``LIBRARY`` targets. For non-
DLL platforms shared libraries are treated as ``LIBRARY`` targets,
- except those marked with the ``FRAMEWORK`` property on OS X (see
+ except those marked with the ``FRAMEWORK`` property on macOS (see
``FRAMEWORK`` below.)
``RUNTIME``
Executables are treated as ``RUNTIME`` objects, except those marked
- with the ``MACOSX_BUNDLE`` property on OS X (see ``BUNDLE`` below.)
+ with the ``MACOSX_BUNDLE`` property on macOS (see ``BUNDLE`` below.)
For DLL platforms (all Windows-based systems including Cygwin), the
DLL part of a shared library is treated as a ``RUNTIME`` target.
``FRAMEWORK``
Both static and shared libraries marked with the ``FRAMEWORK``
- property are treated as ``FRAMEWORK`` targets on OS X.
+ property are treated as ``FRAMEWORK`` targets on macOS.
``BUNDLE``
Executables marked with the ``MACOSX_BUNDLE`` property are treated as
- ``BUNDLE`` targets on OS X.
+ ``BUNDLE`` targets on macOS.
``PUBLIC_HEADER``
Any ``PUBLIC_HEADER`` files associated with a library are installed in
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
set to ``TRUE`` has undefined behavior.
+:command:`install(TARGETS)` can install targets that were created in
+other directories. When using such cross-directory install rules, running
+``make install`` (or similar) from a subdirectory will not guarantee that
+targets from other directories are up-to-date. You can use
+:command:`target_link_libraries` or :command:`add_dependencies`
+to ensure that such out-of-directory targets are built before the
+subdirectory-specific install rules are run.
+
The install destination given to the target install ``DESTINATION`` may
use "generator expressions" with the syntax ``$<...>``. See the
:manual:`cmake-generator-expressions(7)` manual for available expressions.
link_directories
----------------
-Specify directories in which the linker will look for libraries.
+Add directories in which the linker will look for libraries.
::
- link_directories(directory1 directory2 ...)
+ link_directories([AFTER|BEFORE] directory1 [directory2 ...])
-Specify the paths in which the linker should search for libraries.
-The command will apply only to targets created after it is called.
+Add the paths in which the linker should search for libraries.
Relative paths given to this command are interpreted as relative to
the current source directory, see :policy:`CMP0015`.
-Note that this command is rarely necessary. Library locations
-returned by :command:`find_package` and :command:`find_library` are
-absolute paths. Pass these absolute library file paths directly to the
-:command:`target_link_libraries` command. CMake will ensure the linker finds
-them.
+The directories are added to the :prop_dir:`LINK_DIRECTORIES` directory
+property for the current ``CMakeLists.txt`` file, converting relative
+paths to absolute as needed.
+The command will apply only to targets created after it is called.
+
+By default the directories specified are appended onto the current list of
+directories. This default behavior can be changed by setting
+:variable:`CMAKE_LINK_DIRECTORIES_BEFORE` to ``ON``. By using
+``AFTER`` or ``BEFORE`` explicitly, you can select between appending and
+prepending, independent of the default.
+
+Arguments to ``link_directories`` may use "generator expressions" with
+the syntax "$<...>". See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+manual for more on defining buildsystem properties.
+
+.. note::
+
+ This command is rarely necessary and should be avoided where there are
+ other choices. Prefer to pass full absolute paths to libraries where
+ possible, since this ensures the correct library will always be linked.
+ The :command:`find_library` command provides the full path, which can
+ generally be used directly in calls to :command:`target_link_libraries`.
+ Situations where a library search path may be needed include:
+
+ - Project generators like Xcode where the user can switch target
+ architecture at build time, but a full path to a library cannot
+ be used because it only provides one architecture (i.e. it is not
+ a universal binary).
+ - Libraries may themselves have other private library dependencies
+ that expect to be found via ``RPATH`` mechanisms, but some linkers
+ are not able to fully decode those paths (e.g. due to the presence
+ of things like ``$ORIGIN``).
+
+ If a library search path must be provided, prefer to localize the effect
+ where possible by using the :command:`target_link_directories` command
+ rather than ``link_directories()``. The target-specific command can also
+ control how the search directories propagate to other dependent targets.
`Ordering`_
list(`REVERSE`_ <list>)
- list(`SORT`_ <list>)
+ list(`SORT`_ <list> [...])
Introduction
^^^^^^^^^^^^
::
- list(SORT <list>)
-
+ list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
Sorts the list in-place alphabetically.
+Use the ``COMPARE`` keyword to select the comparison method for sorting.
+The ``<compare>`` option should be one of:
+
+* ``STRING``: Sorts a list of strings alphabetically. This is the
+ default behavior if the ``COMPARE`` option is not given.
+* ``FILE_BASENAME``: Sorts a list of pathnames of files by their basenames.
+
+Use the ``CASE`` keyword to select a case sensitive or case insensitive
+sort mode. The ``<case>`` option should be one of:
+
+* ``SENSITIVE``: List items are sorted in a case-sensitive manner. This is
+ the default behavior if the ``CASE`` option is not given.
+* ``INSENSITIVE``: List items are sorted case insensitively. The order of
+ items which differ only by upper/lowercase is not specified.
+
+To control the sort order, the ``ORDER`` keyword can be given.
+The ``<order>`` option should be one of:
+
+* ``ASCENDING``: Sorts the list in ascending order. This is the default
+ behavior when the ``ORDER`` option is not given.
+* ``DESCENDING``: Sorts the list in descending order.
::
- math(EXPR <output-variable> <math-expression>)
+ math(EXPR <output-variable> <math-expression> [OUTPUT_FORMAT <format>])
``EXPR`` evaluates mathematical expression and returns result in the
output variable. Example mathematical expression is ``5 * (10 + 13)``.
Supported operators are ``+``, ``-``, ``*``, ``/``, ``%``, ``|``, ``&``,
``^``, ``~``, ``<<``, ``>>``, and ``(...)``. They have the same meaning
as they do in C code.
+
+Numeric constants are evaluated in decimal or hexadecimal representation.
+
+The result is formatted according to the option "OUTPUT_FORMAT" ,
+where ``<format>`` is one of:
+::
+
+ HEXADECIMAL = Result in output variable will be formatted in C code
+ Hexadecimal notation.
+ DECIMAL = Result in output variable will be formatted in decimal notation.
+
+
+For example::
+
+ math(EXPR value "100 * 0xA" DECIMAL) results in value is set to "1000"
+ math(EXPR value "100 * 0xA" HEXADECIMAL) results in value is set to "0x3e8"
[initial value])
Provide an option for the user to select as ``ON`` or ``OFF``. If no
-initial value is provided, ``OFF`` is used.
+initial value is provided, ``OFF`` is used. If the option is already
+set as a normal variable then the command does nothing
+(see policy :policy:`CMP0077`).
If you have options that depend on the values of other options, see
the module help for :module:`CMakeDependentOption`.
If the optional ``DESCRIPTION`` is given, then :variable:`PROJECT_DESCRIPTION`
and :variable:`<PROJECT-NAME>_DESCRIPTION` will be set to its argument.
+These variables will be cleared if ``DESCRIPTION`` is not given.
The description is expected to be a relatively short string, usually no more
than a few words.
:variable:`PROJECT_HOMEPAGE_URL` and :variable:`<PROJECT-NAME>_HOMEPAGE_URL`.
When this option is given, the URL provided should be the canonical home for
the project.
+These variables will be cleared if ``HOMEPAGE_URL`` is not given.
Note that the description and homepage URL may be used as defaults for
things like packaging meta-data, documentation, etc.
set_directory_properties
------------------------
-Set a property of the directory.
+Set properties of the current directory and subdirectories in key-value pairs.
::
set_directory_properties(PROPERTIES prop1 value1 prop2 value2)
-Set a property for the current directory and subdirectories. See
-:ref:`Directory Properties` for the list of properties known
-to CMake.
+See :ref:`Directory Properties` for the list of properties known to CMake
+and their individual documentation for the behavior of each property.
Matches at end of input
``.``
Matches any single character
+``\<char>``
+ Matches the single character specified by ``<char>``. Use this to
+ match special regex characters, e.g. ``\.`` for a literal ``.``
+ or ``\\`` for a literal backslash ``\``. Escaping a non-special
+ character is unnecessary but allowed, e.g. ``\a`` matches ``a``.
``[ ]``
Matches any character(s) inside the brackets
``[^ ]``
expression ``^ab+d$`` matches ``abbd`` but not ``ababd``, and the regular
expression ``^(ab|cd)$`` matches ``ab`` but not ``abd``.
+CMake language :ref:`Escape Sequences` such as ``\t``, ``\r``, ``\n``,
+and ``\\`` may be used to construct literal tabs, carriage returns,
+newlines, and backslashes (respectively) to pass in a regex. For example:
+
+* The quoted argument ``"[ \t\r\n]"`` specifies a regex that matches
+ any single whitespace character.
+* The quoted argument ``"[/\\]"`` specifies a regex that matches
+ a single forward slash ``/`` or backslash ``\``.
+* The quoted argument ``"[A-Za-z0-9_]"`` specifies a regex that matches
+ any single "word" character in the C locale.
+* The quoted argument ``"\\(\\a\\+b\\)"`` specifies a regex that matches
+ the exact string ``(a+b)``. Each ``\\`` is parsed in a quoted argument
+ as just ``\``, so the regex itself is actually ``\(\a\+\b\)``. This
+ can alternatively be specified in a :ref:`bracket argument` without
+ having to escape the backslashes, e.g. ``[[\(\a\+\b\)]]``.
+
Manipulation
^^^^^^^^^^^^
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
-.. include:: COMPILE_OPTIONS_SHELL.txt
+.. include:: OPTIONS_SHELL.txt
--- /dev/null
+target_link_directories
+-----------------------
+
+Add link directories to a target.
+
+::
+
+ target_link_directories(<target> [BEFORE]
+ <INTERFACE|PUBLIC|PRIVATE> [items1...]
+ [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
+
+Specify the paths in which the linker should search for libraries when
+linking a given target. Each item can be an absolute or relative path,
+with the latter being interpreted as relative to the current source
+directory. These items will be added to the link command.
+
+The named ``<target>`` must have been created by a command such as
+:command:`add_executable` or :command:`add_library` and must not be an
+:ref:`ALIAS target <Alias Targets>`.
+
+The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
+specify the scope of the items that follow them. ``PRIVATE`` and
+``PUBLIC`` items will populate the :prop_tgt:`LINK_DIRECTORIES` property
+of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
+:prop_tgt:`INTERFACE_LINK_DIRECTORIES` property of ``<target>``
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items).
+Each item specifies a link directory and will be converted to an absolute
+path if necessary before adding it to the relevant property. Repeated
+calls for the same ``<target>`` append items in the order called.
+
+If ``BEFORE`` is specified, the content will be prepended to the relevant
+property instead of being appended.
+
+Arguments to ``target_link_directories`` may use "generator expressions"
+with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+manual for more on defining buildsystem properties.
+
+.. note::
+
+ This command is rarely necessary and should be avoided where there are
+ other choices. Prefer to pass full absolute paths to libraries where
+ possible, since this ensures the correct library will always be linked.
+ The :command:`find_library` command provides the full path, which can
+ generally be used directly in calls to :command:`target_link_libraries`.
+ Situations where a library search path may be needed include:
+
+ - Project generators like Xcode where the user can switch target
+ architecture at build time, but a full path to a library cannot
+ be used because it only provides one architecture (i.e. it is not
+ a universal binary).
+ - Libraries may themselves have other private library dependencies
+ that expect to be found via ``RPATH`` mechanisms, but some linkers
+ are not able to fully decode those paths (e.g. due to the presence
+ of things like ``$ORIGIN``).
target_link_libraries(<target> ... <item>... ...)
-The named ``<target>`` must have been created in the current directory by
-a command such as :command:`add_executable` or :command:`add_library` and
-must not be an :ref:`ALIAS target <Alias Targets>`.
-Repeated calls for the same ``<target>`` append items in the order called.
+The named ``<target>`` must have been created by a command such as
+:command:`add_executable` or :command:`add_library` and must not be an
+:ref:`ALIAS target <Alias Targets>`. If policy :policy:`CMP0079` is not
+set to ``NEW`` then the target must have been created in the current
+directory. Repeated calls for the same ``<target>`` append items in
+the order called.
+
Each ``<item>`` may be:
* **A library target name**: The generated link line will have the
the library instead of using the full path
(e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``).
+ The full path to the target's artifact will be quoted/escaped for
+ the shell automatically.
+
* **A full path to a library file**: The generated link line will
normally preserve the full path to the file. The buildsystem will
have a dependency to re-link ``<target>`` if the library file changes.
imported into generated project files. This is not supported by other
generators.
+ The full path to the library file will be quoted/escaped for
+ the shell automatically.
+
* **A plain library name**: The generated link line will ask the linker
to search for the library (e.g. ``foo`` becomes ``-lfoo`` or ``foo.lib``).
+ The library name/flag is treated as a command-line string fragment and
+ will be used with no extra quoting or escaping.
+
* **A link flag**: Item names starting with ``-``, but not ``-l`` or
``-framework``, are treated as linker flags. Note that such flags will
be treated like any other library link item for purposes of transitive
Link flags specified here are inserted into the link command in the same
place as the link libraries. This might not be correct, depending on
- the linker. Use the :prop_tgt:`LINK_FLAGS` target property to add link
+ the linker. Use the :prop_tgt:`LINK_OPTIONS` target property or
+ :command:`target_link_options` command to add link
flags explicitly. The flags will then be placed at the toolchain-defined
flag position in the link command.
+ The link flag is treated as a command-line string fragment and
+ will be used with no extra quoting or escaping.
+
+* **A generator expression**: A ``$<...>`` :manual:`generator expression
+ <cmake-generator-expressions(7)>` may evaluate to any of the above
+ items or to a :ref:`;-list <CMake Language Lists>` of them.
+ If the ``...`` contains any ``;`` characters, e.g. after evaluation
+ of a ``${list}`` variable, be sure to use an explicitly quoted
+ argument ``"$<...>"`` so that this command receives it as a
+ single ``<item>``.
+
+ Additionally, a generator expression may be used as a fragment of
+ any of the above items, e.g. ``foo$<1:_d>``.
+
+ Note that generator expressions will not be used in OLD handling of
+ policy :policy:`CMP0003` or policy :policy:`CMP0004`.
+
* A ``debug``, ``optimized``, or ``general`` keyword immediately followed
by another ``<item>``. The item following such a keyword will be used
only for the corresponding build configuration. The ``debug`` keyword
optional. Higher granularity may be achieved for per-configuration
rules by creating and linking to
:ref:`IMPORTED library targets <Imported Targets>`.
+ These keywords are interpreted immediately by this command and therefore
+ have no special meaning when produced by a generator expression.
Items containing ``::``, such as ``Foo::Bar``, are assumed to be
:ref:`IMPORTED <Imported Targets>` or :ref:`ALIAS <Alias Targets>` library
target names and will cause an error if no such target exists.
See policy :policy:`CMP0028`.
-Arguments to ``target_link_libraries`` may use "generator expressions"
-with the syntax ``$<...>``. Note however, that generator expressions
-will not be used in OLD handling of :policy:`CMP0003` or :policy:`CMP0004`.
-See the :manual:`cmake-generator-expressions(7)` manual for available
-expressions. See the :manual:`cmake-buildsystem(7)` manual for more on
-defining buildsystem properties.
+See the :manual:`cmake-buildsystem(7)` manual for more on defining
+buildsystem properties.
Libraries for a Target and/or its Dependents
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--- /dev/null
+target_link_options
+-------------------
+
+Add link options to a target.
+
+::
+
+ target_link_options(<target> [BEFORE]
+ <INTERFACE|PUBLIC|PRIVATE> [items1...]
+ [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
+
+Specify link options to use when linking a given target. The
+named ``<target>`` must have been created by a command such as
+:command:`add_executable` or :command:`add_library` and must not be an
+:ref:`ALIAS target <Alias Targets>`.
+
+If ``BEFORE`` is specified, the content will be prepended to the property
+instead of being appended.
+
+This command can be used to add any options, but
+alternative commands exist to add libraries
+(:command:`target_link_libraries` and :command:`link_libraries`).
+See documentation of the :prop_dir:`directory <LINK_OPTIONS>` and
+:prop_tgt:`target <LINK_OPTIONS>` ``LINK_OPTIONS`` properties.
+
+The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
+specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC``
+items will populate the :prop_tgt:`LINK_OPTIONS` property of
+``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
+:prop_tgt:`INTERFACE_LINK_OPTIONS` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify link options. Repeated calls for the same
+``<target>`` append items in the order called.
+
+Arguments to ``target_link_options`` may use "generator expressions"
+with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+manual for more on defining buildsystem properties.
+
+.. include:: OPTIONS_SHELL.txt
+
+.. include:: LINK_OPTIONS_LINKER.txt
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
-Specify sources to use when compiling a given target. The
+Specify sources to use when compiling a given target. Relative
+source file paths are interpreted as being relative to the current
+source directory (i.e. :variable:`CMAKE_CURRENT_SOURCE_DIR`). The
named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be an
:ref:`ALIAS target <Alias Targets>`.
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
+
+See also the :policy:`CMP0076` policy for older behavior related to the
+handling of relative source file paths.
unset(<variable> [CACHE | PARENT_SCOPE])
-Removes the specified variable causing it to become undefined. If
-``CACHE`` is present then the variable is removed from the cache instead
-of the current scope.
+Removes a normal variable from the current scope, causing it
+to become undefined. If ``CACHE`` is present, then a cache variable
+is removed instead of a normal variable. Note that when evaluating
+:ref:`Variable References` of the form ``${VAR}``, CMake first searches
+for a normal variable with that name. If no such normal variable exists,
+CMake will then search for a cache entry with that name. Because of this
+unsetting a normal variable can expose a cache variable that was previously
+hidden. To force a variable reference of the form ``${VAR}`` to return an
+empty string, use ``set(<variable> "")``, which clears the normal variable
+but leaves it defined.
If ``PARENT_SCOPE`` is present then the variable is removed from the scope
above the current scope. See the same option in the :command:`set` command
--- /dev/null
+CPack Archive Generator
+-----------------------
+
+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_<component>_FILE_NAME
+
+ Package file name without extension which is added automatically depending
+ on the archive format.
+
+ * Mandatory : YES
+ * Default : ``<CPACK_PACKAGE_FILE_NAME>[-<component>].<extension>`` 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.
--- /dev/null
+CPack Bundle Generator
+----------------------
+
+CPack Bundle generator (macOS) specific options
+
+Variables specific to CPack Bundle generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Installers built on macOS using the Bundle generator use the
+aforementioned DragNDrop (``CPACK_DMG_xxx``) variables, plus the following
+Bundle-specific parameters (``CPACK_BUNDLE_xxx``).
+
+.. variable:: CPACK_BUNDLE_NAME
+
+ The name of the generated bundle. This appears in the OSX finder as the
+ bundle name. Required.
+
+.. variable:: CPACK_BUNDLE_PLIST
+
+ Path to an OSX plist file that will be used for the generated bundle. This
+ assumes that the caller has generated or specified their own Info.plist
+ file. Required.
+
+.. variable:: CPACK_BUNDLE_ICON
+
+ Path to an OSX icon file that will be used as the icon for the generated
+ bundle. This is the icon that appears in the OSX finder for the bundle, and
+ in the OSX dock when the bundle is opened. Required.
+
+.. variable:: CPACK_BUNDLE_STARTUP_COMMAND
+
+ Path to a startup script. This is a path to an executable or script that
+ will be run whenever an end-user double-clicks the generated bundle in the
+ OSX Finder. Optional.
+
+.. variable:: CPACK_BUNDLE_APPLE_CERT_APP
+
+ The name of your Apple supplied code signing certificate for the application.
+ The name usually takes the form ``Developer ID Application: [Name]`` or
+ ``3rd Party Mac Developer Application: [Name]``. If this variable is not set
+ the application will not be signed.
+
+.. variable:: CPACK_BUNDLE_APPLE_ENTITLEMENTS
+
+ The name of the ``Plist`` file that contains your apple entitlements for sandboxing
+ your application. This file is required for submission to the Mac App Store.
+
+.. variable:: CPACK_BUNDLE_APPLE_CODESIGN_FILES
+
+ A list of additional files that you wish to be signed. You do not need to
+ list the main application folder, or the main executable. You should
+ list any frameworks and plugins that are included in your app bundle.
+
+.. variable:: CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER
+
+ Additional parameter that will passed to ``codesign``.
+ Default value: ``--deep -f``
+
+.. variable:: CPACK_COMMAND_CODESIGN
+
+ Path to the ``codesign(1)`` command used to sign applications with an
+ Apple cert. This variable can be used to override the automatically
+ detected command (or specify its location if the auto-detection fails
+ to find it).
--- /dev/null
+CPack Cygwin Generator
+----------------------
+
+Cygwin CPack generator (Cygwin).
+
+Variables specific to CPack Cygwin generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The
+following variable is specific to installers build on and/or for
+Cygwin:
+
+.. variable:: CPACK_CYGWIN_PATCH_NUMBER
+
+ The Cygwin patch number. FIXME: This documentation is incomplete.
+
+.. variable:: CPACK_CYGWIN_PATCH_FILE
+
+ The Cygwin patch file. FIXME: This documentation is incomplete.
+
+.. variable:: CPACK_CYGWIN_BUILD_SCRIPT
+
+ The Cygwin build script. FIXME: This documentation is incomplete.
--- /dev/null
+CPack DEB Generator
+-------------------
+
+The built in (binary) CPack DEB generator (Unix only)
+
+Variables specific to CPack Debian (DEB) generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack DEB generator may be used to create DEB package using :module:`CPack`.
+The CPack DEB generator is a :module:`CPack` generator thus it uses the
+``CPACK_XXX`` variables used by :module:`CPack`.
+
+The CPack DEB generator should work on any Linux host but it will produce
+better deb package when Debian specific tools ``dpkg-xxx`` are usable on
+the build system.
+
+The CPack DEB generator has specific features which are controlled by the
+specifics :code:`CPACK_DEBIAN_XXX` variables.
+
+:code:`CPACK_DEBIAN_<COMPONENT>_XXXX` variables may be used in order to have
+**component** specific values. Note however that ``<COMPONENT>`` refers to
+the **grouping name** written in upper case. It may be either a component name
+or a component GROUP name.
+
+Here are some CPack DEB generator wiki resources that are here for historic
+reasons and are no longer maintained but may still prove useful:
+
+ - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/Configuration
+ - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/PackageGenerators#deb-unix-only
+
+List of CPack DEB generator specific variables:
+
+.. variable:: CPACK_DEB_COMPONENT_INSTALL
+
+ Enable component packaging for CPackDEB
+
+ * Mandatory : NO
+ * Default : OFF
+
+ If enabled (ON) multiple packages are generated. By default a single package
+ containing files of all components is generated.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_NAME
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_NAME
+
+ Set Package control field (variable is automatically transformed to lower
+ case).
+
+ * Mandatory : YES
+ * Default :
+
+ - :variable:`CPACK_PACKAGE_NAME` for non-component based
+ installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_NAME` suffixed with -<COMPONENT>
+ for component-based installations.
+
+ See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
+
+.. variable:: CPACK_DEBIAN_FILE_NAME
+ CPACK_DEBIAN_<COMPONENT>_FILE_NAME
+
+ Package file name.
+
+ * Mandatory : YES
+ * Default : ``<CPACK_PACKAGE_FILE_NAME>[-<component>].deb``
+
+ This may be set to ``DEB-DEFAULT`` to allow the CPack DEB generator to generate
+ package file name by itself in deb format::
+
+ <PackageName>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
+
+ Alternatively provided package file name must end
+ with either ``.deb`` or ``.ipk`` suffix.
+
+ .. note::
+
+ Preferred setting of this variable is ``DEB-DEFAULT`` but for backward
+ compatibility with the CPack DEB generator in CMake prior to version 3.6 this
+ feature is disabled by default.
+
+ .. note::
+
+ By using non default filenames duplicate names may occur. Duplicate files
+ get overwritten and it is up to the packager to set the variables in a
+ manner that will prevent such errors.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_EPOCH
+
+ The Debian package epoch
+
+ * Mandatory : No
+ * Default : -
+
+ Optional number that should be incremented when changing versioning schemas
+ or fixing mistakes in the version numbers of older packages.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_VERSION
+
+ The Debian package version
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VERSION`
+
+ This variable may contain only alphanumerics (A-Za-z0-9) and the characters
+ . + - ~ (full stop, plus, hyphen, tilde) and should start with a digit. If
+ :variable:`CPACK_DEBIAN_PACKAGE_RELEASE` is not set then hyphens are not
+ allowed.
+
+ .. note::
+
+ For backward compatibility with CMake 3.9 and lower a failed test of this
+ variable's content is not a hard error when both
+ :variable:`CPACK_DEBIAN_PACKAGE_RELEASE` and
+ :variable:`CPACK_DEBIAN_PACKAGE_EPOCH` variables are not set. An author
+ warning is reported instead.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_RELEASE
+
+ The Debian package release - Debian revision number.
+
+ * Mandatory : No
+ * Default : -
+
+ This is the numbering of the DEB package itself, i.e. the version of the
+ packaging and not the version of the content (see
+ :variable:`CPACK_DEBIAN_PACKAGE_VERSION`). One may change the default value
+ if the previous packaging was buggy and/or you want to put here a fancy Linux
+ distro specific numbering.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_ARCHITECTURE
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_ARCHITECTURE
+
+ The Debian package architecture
+
+ * Mandatory : YES
+ * Default : Output of :code:`dpkg --print-architecture` (or :code:`i386`
+ if :code:`dpkg` is not found)
+
+.. variable:: CPACK_DEBIAN_PACKAGE_DEPENDS
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS
+
+ Sets the Debian dependencies of this package.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_DEPENDS` for component-based
+ installations.
+
+ .. note::
+
+ If :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS` or
+ more specifically :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS`
+ is set for this component, the discovered dependencies will be appended
+ to :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS` instead of
+ :variable:`CPACK_DEBIAN_PACKAGE_DEPENDS`. If
+ :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS` is an empty string,
+ only the automatically discovered dependencies will be set for this
+ component.
+
+ Example::
+
+ set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libc6 (< 2.4)")
+
+.. variable:: CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS
+
+ Sets inter component dependencies if listed with
+ :variable:`CPACK_COMPONENT_<compName>_DEPENDS` variables.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_DEBIAN_PACKAGE_MAINTAINER
+
+ The Debian package maintainer
+
+ * Mandatory : YES
+ * Default : :code:`CPACK_PACKAGE_CONTACT`
+
+.. variable:: CPACK_DEBIAN_PACKAGE_DESCRIPTION
+ CPACK_COMPONENT_<COMPONENT>_DESCRIPTION
+
+ The Debian package description
+
+ * Mandatory : YES
+ * Default :
+
+ - :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` if set or
+ - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+
+
+.. variable:: CPACK_DEBIAN_PACKAGE_SECTION
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_SECTION
+
+ Set Section control field e.g. admin, devel, doc, ...
+
+ * Mandatory : YES
+ * Default : "devel"
+
+ See https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
+
+.. variable:: CPACK_DEBIAN_ARCHIVE_TYPE
+
+ The archive format used for creating the Debian package.
+
+ * Mandatory : YES
+ * Default : "paxr"
+
+ Possible values are:
+
+ - paxr
+ - gnutar
+
+ .. note::
+
+ Default pax archive format is the most portable format and generates
+ packages that do not treat sparse files specially.
+ GNU tar format on the other hand supports longer filenames.
+
+.. variable:: CPACK_DEBIAN_COMPRESSION_TYPE
+
+ The compression used for creating the Debian package.
+
+ * Mandatory : YES
+ * Default : "gzip"
+
+ Possible values are:
+
+ - lzma
+ - xz
+ - bzip2
+ - gzip
+
+.. variable:: CPACK_DEBIAN_PACKAGE_PRIORITY
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY
+
+ Set Priority control field e.g. required, important, standard, optional,
+ extra
+
+ * Mandatory : YES
+ * Default : "optional"
+
+ See https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities
+
+.. variable:: CPACK_DEBIAN_PACKAGE_HOMEPAGE
+
+ The URL of the web site for this package, preferably (when applicable) the
+ site from which the original source can be obtained and any additional
+ upstream documentation or information may be found.
+
+ * Mandatory : NO
+ * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
+
+ .. note::
+
+ The content of this field is a simple URL without any surrounding
+ characters such as <>.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_SHLIBDEPS
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS
+
+ May be set to ON in order to use :code:`dpkg-shlibdeps` to generate
+ better package dependency list.
+
+ * Mandatory : NO
+ * Default :
+
+ - :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS` if set or
+ - OFF
+
+ .. note::
+
+ You may need set :variable:`CMAKE_INSTALL_RPATH` to an appropriate value
+ if you use this feature, because if you don't :code:`dpkg-shlibdeps`
+ may fail to find your own shared libs.
+ See https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling
+
+.. variable:: CPACK_DEBIAN_PACKAGE_DEBUG
+
+ May be set when invoking cpack in order to trace debug information
+ during the CPack DEB generator run.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_DEBIAN_PACKAGE_PREDEPENDS
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_PREDEPENDS
+
+ Sets the `Pre-Depends` field of the Debian package.
+ Like :variable:`Depends <CPACK_DEBIAN_PACKAGE_DEPENDS>`, except that it
+ also forces :code:`dpkg` to complete installation of the packages named
+ before even starting the installation of the package which declares the
+ pre-dependency.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_PREDEPENDS` for component-based
+ installations.
+
+ See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+
+.. variable:: CPACK_DEBIAN_PACKAGE_ENHANCES
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_ENHANCES
+
+ Sets the `Enhances` field of the Debian package.
+ Similar to :variable:`Suggests <CPACK_DEBIAN_PACKAGE_SUGGESTS>` but works
+ in the opposite direction: declares that a package can enhance the
+ functionality of another package.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_ENHANCES` for component-based
+ installations.
+
+ See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+
+.. variable:: CPACK_DEBIAN_PACKAGE_BREAKS
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_BREAKS
+
+ Sets the `Breaks` field of the Debian package.
+ When a binary package (P) declares that it breaks other packages (B),
+ :code:`dpkg` will not allow the package (P) which declares `Breaks` be
+ **unpacked** unless the packages that will be broken (B) are deconfigured
+ first.
+ As long as the package (P) is configured, the previously deconfigured
+ packages (B) cannot be reconfigured again.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_BREAKS` for component-based
+ installations.
+
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-breaks
+
+.. variable:: CPACK_DEBIAN_PACKAGE_CONFLICTS
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONFLICTS
+
+ Sets the `Conflicts` field of the Debian package.
+ When one binary package declares a conflict with another using a `Conflicts`
+ field, :code:`dpkg` will not allow them to be unpacked on the system at
+ the same time.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_CONFLICTS` for component-based
+ installations.
+
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-conflicts
+
+ .. note::
+
+ This is a stronger restriction than
+ :variable:`Breaks <CPACK_DEBIAN_PACKAGE_BREAKS>`, which prevents the
+ broken package from being configured while the breaking package is in
+ the "Unpacked" state but allows both packages to be unpacked at the same
+ time.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_PROVIDES
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_PROVIDES
+
+ Sets the `Provides` field of the Debian package.
+ A virtual package is one which appears in the `Provides` control field of
+ another package.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_PROVIDES` for component-based
+ installations.
+
+ See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-virtual
+
+.. variable:: CPACK_DEBIAN_PACKAGE_REPLACES
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_REPLACES
+
+ Sets the `Replaces` field of the Debian package.
+ Packages can declare in their control file that they should overwrite
+ files in certain other packages, or completely replace other packages.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_REPLACES` for component-based
+ installations.
+
+ See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+
+.. variable:: CPACK_DEBIAN_PACKAGE_RECOMMENDS
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_RECOMMENDS
+
+ Sets the `Recommends` field of the Debian package.
+ Allows packages to declare a strong, but not absolute, dependency on other
+ packages.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_RECOMMENDS` for component-based
+ installations.
+
+ See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+
+.. variable:: CPACK_DEBIAN_PACKAGE_SUGGESTS
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_SUGGESTS
+
+ Sets the `Suggests` field of the Debian package.
+ Allows packages to declare a suggested package install grouping.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_SUGGESTS` for component-based
+ installations.
+
+ See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
+
+.. variable:: CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS
+
+ * Mandatory : NO
+ * Default : OFF
+
+ Allows to generate shlibs control file automatically. Compatibility is defined by
+ :variable:`CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY` variable value.
+
+ .. note::
+
+ Libraries are only considered if they have both library name and version
+ set. This can be done by setting SOVERSION property with
+ :command:`set_target_properties` command.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY
+
+ Compatibility policy for auto-generated shlibs control file.
+
+ * Mandatory : NO
+ * Default : "="
+
+ Defines compatibility policy for auto-generated shlibs control file.
+ Possible values: "=", ">="
+
+ See https://www.debian.org/doc/debian-policy/ch-sharedlibs.html#s-sharedlibs-shlibdeps
+
+.. variable:: CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONTROL_EXTRA
+
+ This variable allow advanced user to add custom script to the
+ control.tar.gz.
+ Typical usage is for conffiles, postinst, postrm, prerm.
+
+ * Mandatory : NO
+ * Default : -
+
+ Usage::
+
+ set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
+ "${CMAKE_CURRENT_SOURCE_DIR}/prerm;${CMAKE_CURRENT_SOURCE_DIR}/postrm")
+
+ .. note::
+
+ The original permissions of the files will be used in the final
+ package unless the variable
+ :variable:`CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION` is set.
+ In particular, the scripts should have the proper executable
+ flag prior to the generation of the package.
+
+.. variable:: CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONTROL_STRICT_PERMISSION
+
+ This variable indicates if the Debian policy on control files should be
+ strictly followed.
+
+ * Mandatory : NO
+ * Default : FALSE
+
+ Usage::
+
+ set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
+
+ .. note::
+
+ This overrides the permissions on the original files, following the rules
+ set by Debian policy
+ https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
+
+.. variable:: CPACK_DEBIAN_PACKAGE_SOURCE
+ CPACK_DEBIAN_<COMPONENT>_PACKAGE_SOURCE
+
+ Sets the ``Source`` field of the binary Debian package.
+ When the binary package name is not the same as the source package name
+ (in particular when several components/binaries are generated from one
+ source) the source from which the binary has been generated should be
+ indicated with the field ``Source``.
+
+ * Mandatory : NO
+ * Default :
+
+ - An empty string for non-component based installations
+ - :variable:`CPACK_DEBIAN_PACKAGE_SOURCE` for component-based
+ installations.
+
+ See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
+
+ .. note::
+
+ This value is not interpreted. It is possible to pass an optional
+ revision number of the referenced source package as well.
+
+Packaging of debug information
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Dbgsym packages contain debug symbols for debugging packaged binaries.
+
+Dbgsym packaging has its own set of variables:
+
+.. variable:: CPACK_DEBIAN_DEBUGINFO_PACKAGE
+ CPACK_DEBIAN_<component>_DEBUGINFO_PACKAGE
+
+ Enable generation of dbgsym .ddeb package(s).
+
+ * Mandatory : NO
+ * Default : OFF
+
+.. note::
+
+ Binaries must contain debug symbols before packaging so use either ``Debug``
+ or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value.
+
+Building Debian packages on Windows
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To communicate UNIX file permissions from the install stage
+to the CPack DEB generator the "cmake_mode_t" NTFS
+alternate data stream (ADT) is used.
+
+When a filesystem without ADT support is used only owner read/write
+permissions can be preserved.
+
+Reproducible packages
+^^^^^^^^^^^^^^^^^^^^^
+
+The environment variable ``SOURCE_DATE_EPOCH`` may be set to a UNIX
+timestamp, defined as the number of seconds, excluding leap seconds,
+since 01 Jan 1970 00:00:00 UTC. If set, the CPack DEB generator will
+use its value for timestamps in the package.
--- /dev/null
+CPack DragNDrop Generator
+-------------------------
+
+The DragNDrop CPack generator (macOS) creates a DMG image.
+
+Variables specific to CPack DragNDrop generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following variables are specific to the DragNDrop installers built
+on macOS:
+
+.. variable:: CPACK_DMG_VOLUME_NAME
+
+ The volume name of the generated disk image. Defaults to
+ CPACK_PACKAGE_FILE_NAME.
+
+.. variable:: CPACK_DMG_FORMAT
+
+ The disk image format. Common values are ``UDRO`` (UDIF read-only), ``UDZO`` (UDIF
+ zlib-compressed) or ``UDBZ`` (UDIF bzip2-compressed). Refer to ``hdiutil(1)`` for
+ more information on other available formats. Defaults to ``UDZO``.
+
+.. variable:: CPACK_DMG_DS_STORE
+
+ Path to a custom ``.DS_Store`` file. This ``.DS_Store`` file can be used to
+ specify the Finder window position/geometry and layout (such as hidden
+ toolbars, placement of the icons etc.). This file has to be generated by
+ the Finder (either manually or through AppleScript) using a normal folder
+ from which the ``.DS_Store`` file can then be extracted.
+
+.. variable:: CPACK_DMG_DS_STORE_SETUP_SCRIPT
+
+ Path to a custom AppleScript file. This AppleScript is used to generate
+ a ``.DS_Store`` file which specifies the Finder window position/geometry and
+ layout (such as hidden toolbars, placement of the icons etc.).
+ By specifying a custom AppleScript there is no need to use
+ ``CPACK_DMG_DS_STORE``, as the ``.DS_Store`` that is generated by the AppleScript
+ will be packaged.
+
+.. variable:: CPACK_DMG_BACKGROUND_IMAGE
+
+ Path to an image file to be used as the background. This file will be
+ copied to ``.background``/``background.<ext>``, where ``<ext>`` is the original image file
+ extension. The background image is installed into the image before
+ ``CPACK_DMG_DS_STORE_SETUP_SCRIPT`` is executed or ``CPACK_DMG_DS_STORE`` is
+ installed. By default no background image is set.
+
+.. variable:: CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK
+
+ Default behaviour is to include a symlink to ``/Applications`` in the DMG.
+ Set this option to ``ON`` to avoid adding the symlink.
+
+.. variable:: CPACK_DMG_SLA_DIR
+
+ Directory where license and menu files for different languages are stored.
+ Setting this causes CPack to look for a ``<language>.menu.txt`` and
+ ``<language>.license.txt`` file for every language defined in
+ ``CPACK_DMG_SLA_LANGUAGES``. If both this variable and
+ ``CPACK_RESOURCE_FILE_LICENSE`` are set, CPack will only look for the menu
+ files and use the same license file for all languages.
+
+.. variable:: CPACK_DMG_SLA_LANGUAGES
+
+ Languages for which a license agreement is provided when mounting the
+ generated DMG. A menu file consists of 9 lines of text. The first line is
+ is the name of the language itself, uppercase, in English (e.g. German).
+ The other lines are translations of the following strings:
+
+ - Agree
+ - Disagree
+ - Print
+ - Save...
+ - You agree to the terms of the License Agreement when you click the
+ "Agree" button.
+ - Software License Agreement
+ - This text cannot be saved. The disk may be full or locked, or the file
+ may be locked.
+ - Unable to print. Make sure you have selected a printer.
+
+ For every language in this list, CPack will try to find files
+ ``<language>.menu.txt`` and ``<language>.license.txt`` in the directory
+ specified by the :variable:`CPACK_DMG_SLA_DIR` variable.
+
+.. variable:: CPACK_COMMAND_HDIUTIL
+
+ Path to the ``hdiutil(1)`` command used to operate on disk image files on
+ macOS. This variable can be used to override the automatically detected
+ command (or specify its location if the auto-detection fails to find it).
+
+.. variable:: CPACK_COMMAND_SETFILE
+
+ Path to the ``SetFile(1)`` command used to set extended attributes on files and
+ directories on macOS. This variable can be used to override the
+ automatically detected command (or specify its location if the
+ auto-detection fails to find it).
+
+.. variable:: CPACK_COMMAND_REZ
+
+ Path to the ``Rez(1)`` command used to compile resources on macOS. This
+ variable can be used to override the automatically detected command (or
+ specify its location if the auto-detection fails to find it).
--- /dev/null
+CPack External Generator
+------------------------
+
+CPack provides many generators to create packages for a variety of platforms
+and packaging systems. The intention is for CMake/CPack to be a complete
+end-to-end solution for building and packaging a software project. However, it
+may not always be possible to use CPack for the entire packaging process, due
+to either technical limitations or policies that require the use of certain
+tools. For this reason, CPack provides the "External" generator, which allows
+external packaging software to take advantage of some of the functionality
+provided by CPack, such as component installation and the dependency graph.
+
+Integration with External Packaging Tools
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack External generator generates a .json file containing the
+CPack internal metadata, which gives external software information
+on how to package the software. External packaging software may itself
+invoke CPack, consume the generated metadata,
+install and package files as required.
+
+Alternatively CPack can invoke an external packaging software
+through an optional custom CMake script in
+:variable:`CPACK_EXTERNAL_PACKAGE_SCRIPT` instead.
+
+Staging of installation files may also optionally be
+taken care of by the generator when enabled through the
+:variable:`CPACK_EXTERNAL_ENABLE_STAGING` variable.
+
+JSON Format
+^^^^^^^^^^^
+
+The JSON metadata file contains a list of CPack components and component groups,
+the various options passed to :command:`cpack_add_component` and
+:command:`cpack_add_component_group`, the dependencies between the components
+and component groups, and various other options passed to CPack.
+
+The JSON's root object will always provide two fields:
+``formatVersionMajor`` and ``formatVersionMinor``, which are always integers
+that describe the output format of the generator. Backwards-compatible changes
+to the output format (for example, adding a new field that didn't exist before)
+cause the minor version to be incremented, and backwards-incompatible changes
+(for example, deleting a field or changing its meaning) cause the major version
+to be incremented and the minor version reset to 0. The format version is
+always of the format ``major.minor``. In other words, it always has exactly two
+parts, separated by a period.
+
+You can request one or more specific versions of the output format as described
+below with :variable:`CPACK_EXTERNAL_REQUESTED_VERSIONS`. The output format will
+have a major version that exactly matches the requested major version, and a
+minor version that is greater than or equal to the requested minor version. If
+no version is requested with :variable:`CPACK_EXTERNAL_REQUESTED_VERSIONS`, the
+latest known major version is used by default. Currently, the only supported
+format is 1.0, which is described below.
+
+Version 1.0
+***********
+
+In addition to the standard format fields, format version 1.0 provides the
+following fields in the root:
+
+``components``
+ The ``components`` field is an object with component names as the keys and
+ objects describing the components as the values. The component objects have
+ the following fields:
+
+ ``name``
+ The name of the component. This is always the same as the key in the
+ ``components`` object.
+
+ ``displayName``
+ The value of the ``DISPLAY_NAME`` field passed to
+ :command:`cpack_add_component`.
+
+ ``description``
+ The value of the ``DESCRIPTION`` field passed to
+ :command:`cpack_add_component`.
+
+ ``isHidden``
+ True if ``HIDDEN`` was passed to :command:`cpack_add_component`, false if
+ it was not.
+
+ ``isRequired``
+ True if ``REQUIRED`` was passed to :command:`cpack_add_component`, false if
+ it was not.
+
+ ``isDisabledByDefault``
+ True if ``DISABLED`` was passed to :command:`cpack_add_component`, false if
+ it was not.
+
+ ``group``
+ Only present if ``GROUP`` was passed to :command:`cpack_add_component`. If
+ so, this field is a string value containing the component's group.
+
+ ``dependencies``
+ An array of components the component depends on. This contains the values
+ in the ``DEPENDS`` argument passed to :command:`cpack_add_component`. If no
+ ``DEPENDS`` argument was passed, this is an empty list.
+
+ ``installationTypes``
+ An array of installation types the component is part of. This contains the
+ values in the ``INSTALL_TYPES`` argument passed to
+ :command:`cpack_add_component`. If no ``INSTALL_TYPES`` argument was
+ passed, this is an empty list.
+
+ ``isDownloaded``
+ True if ``DOWNLOADED`` was passed to :command:`cpack_add_component`, false
+ if it was not.
+
+ ``archiveFile``
+ The name of the archive file passed with the ``ARCHIVE_FILE`` argument to
+ :command:`cpack_add_component`. If no ``ARCHIVE_FILE`` argument was passed,
+ this is an empty string.
+
+``componentGroups``
+ The ``componentGroups`` field is an object with component group names as the
+ keys and objects describing the component groups as the values. The component
+ group objects have the following fields:
+
+ ``name``
+ The name of the component group. This is always the same as the key in the
+ ``componentGroups`` object.
+
+ ``displayName``
+ The value of the ``DISPLAY_NAME`` field passed to
+ :command:`cpack_add_component_group`.
+
+ ``description``
+ The value of the ``DESCRIPTION`` field passed to
+ :command:`cpack_add_component_group`.
+
+ ``parentGroup``
+ Only present if ``PARENT_GROUP`` was passed to
+ :command:`cpack_add_component_group`. If so, this field is a string value
+ containing the component group's parent group.
+
+ ``isExpandedByDefault``
+ True if ``EXPANDED`` was passed to :command:`cpack_add_component_group`,
+ false if it was not.
+
+ ``isBold``
+ True if ``BOLD_TITLE`` was passed to :command:`cpack_add_component_group`,
+ false if it was not.
+
+ ``components``
+ An array of names of components that are direct members of the group
+ (components that have this group as their ``GROUP``). Components of
+ subgroups are not included.
+
+ ``subgroups``
+ An array of names of component groups that are subgroups of the group
+ (groups that have this group as their ``PARENT_GROUP``).
+
+``installationTypes``
+ The ``installationTypes`` field is an object with installation type names as
+ the keys and objects describing the installation types as the values. The
+ installation type objects have the following fields:
+
+ ``name``
+ The name of the installation type. This is always the same as the key in
+ the ``installationTypes`` object.
+
+ ``displayName``
+ The value of the ``DISPLAY_NAME`` field passed to
+ :command:`cpack_add_install_type`.
+
+ ``index``
+ The integer index of the installation type in the list.
+
+``projects``
+ The ``projects`` field is an array of objects describing CMake projects which
+ comprise the CPack project. The values in this field are derived from
+ :variable:`CPACK_INSTALL_CMAKE_PROJECTS`. In most cases, this will be only a
+ single project. The project objects have the following fields:
+
+ ``projectName``
+ The project name passed to :variable:`CPACK_INSTALL_CMAKE_PROJECTS`.
+
+ ``component``
+ The name of the component or component set which comprises the project.
+
+ ``directory``
+ The build directory of the CMake project. This is the directory which
+ contains the ``cmake_install.cmake`` script.
+
+ ``subDirectory``
+ The subdirectory to install the project into inside the CPack package.
+
+``packageName``
+ The package name given in :variable:`CPACK_PACKAGE_NAME`. Only present if
+ this option is set.
+
+``packageVersion``
+ The package version given in :variable:`CPACK_PACKAGE_VERSION`. Only present
+ if this option is set.
+
+``packageDescriptionFile``
+ The package description file given in
+ :variable:`CPACK_PACKAGE_DESCRIPTION_FILE`. Only present if this option is
+ set.
+
+``packageDescriptionSummary``
+ The package description summary given in
+ :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`. Only present if this option is
+ set.
+
+``buildConfig``
+ The build configuration given to CPack with the ``-C`` option. Only present
+ if this option is set.
+
+``defaultDirectoryPermissions``
+ The default directory permissions given in
+ :variable:`CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`. Only present if this
+ option is set.
+
+``setDestdir``
+ True if :variable:`CPACK_SET_DESTDIR` is true, false if it is not.
+
+``packagingInstallPrefix``
+ The install prefix given in :variable:`CPACK_PACKAGING_INSTALL_PREFIX`. Only
+ present if :variable:`CPACK_SET_DESTDIR` is true.
+
+``stripFiles``
+ True if :variable:`CPACK_STRIP_FILES` is true, false if it is not.
+
+``warnOnAbsoluteInstallDestination``
+ True if :variable:`CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION` is true, false
+ if it is not.
+
+``errorOnAbsoluteInstallDestination``
+ True if :variable:`CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION` is true,
+ false if it is not.
+
+Variables specific to CPack External generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. variable:: CPACK_EXTERNAL_REQUESTED_VERSIONS
+
+ This variable is used to request a specific version of the CPack External
+ generator. It is a list of ``major.minor`` values, separated by semicolons.
+
+ If this variable is set to a non-empty value, the CPack External generator
+ will iterate through each item in the list to search for a version that it
+ knows how to generate. Requested versions should be listed in order of
+ descending preference by the client software, as the first matching version
+ in the list will be generated.
+
+ The generator knows how to generate the version if it has a versioned
+ generator whose major version exactly matches the requested major version,
+ and whose minor version is greater than or equal to the requested minor
+ version. For example, if ``CPACK_EXTERNAL_REQUESTED_VERSIONS`` contains 1.0, and
+ the CPack External generator knows how to generate 1.1, it will generate 1.1.
+ If the generator doesn't know how to generate a version in the list, it skips
+ the version and looks at the next one. If it doesn't know how to generate any
+ of the requested versions, an error is thrown.
+
+ If this variable is not set, or is empty, the CPack External generator will
+ generate the highest major and minor version that it knows how to generate.
+
+ If an invalid version is encountered in ``CPACK_EXTERNAL_REQUESTED_VERSIONS`` (one
+ that doesn't match ``major.minor``, where ``major`` and ``minor`` are
+ integers), it is ignored.
+
+.. variable:: CPACK_EXTERNAL_ENABLE_STAGING
+
+ This variable can be set to true to enable optional installation
+ into a temporary staging area which can then be picked up
+ and packaged by an external packaging tool.
+ The top level directory used by CPack for the current packaging
+ task is contained in ``CPACK_TOPLEVEL_DIRECTORY``.
+ It is automatically cleaned up on each run before packaging is initiated
+ and can be used for custom temporary files required by
+ the external packaging tool.
+ It also contains the staging area ``CPACK_TEMPORARY_DIRECTORY``
+ into which CPack performs the installation when staging is enabled.
+
+.. variable:: CPACK_EXTERNAL_PACKAGE_SCRIPT
+
+ This variable can optionally specify the full path to
+ a CMake script file to be run as part of the CPack invocation.
+ It is invoked after (optional) staging took place and may
+ run an external packaging tool. The script has access to
+ the variables defined by the CPack config file.
--- /dev/null
+CPack FreeBSD Generator
+-----------------------
+
+The built in (binary) CPack FreeBSD (pkg) generator (Unix only)
+
+Variables specific to CPack FreeBSD (pkg) generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack FreeBSD generator may be used to create pkg(8) packages -- these may
+be used on FreeBSD, DragonflyBSD, NetBSD, OpenBSD, but also on Linux or OSX,
+depending on the installed package-management tools -- using :module:`CPack`.
+
+The CPack FreeBSD generator is a :module:`CPack` generator and uses the
+``CPACK_XXX`` variables used by :module:`CPack`. It tries to re-use packaging
+information that may already be specified for Debian packages for the
+:cpack_gen:`CPack DEB Generator`. It also tries to re-use RPM packaging
+information when Debian does not specify.
+
+The CPack FreeBSD generator should work on any host with libpkg installed. The
+packages it produces are specific to the host architecture and ABI.
+
+The CPack FreeBSD generator sets package-metadata through
+:code:`CPACK_FREEBSD_XXX` variables. The CPack FreeBSD generator, unlike the
+CPack Deb generator, does not specially support componentized packages; a
+single package is created from all the software artifacts created through
+CMake.
+
+All of the variables can be set specifically for FreeBSD packaging in
+the CPackConfig file or in CMakeLists.txt, but most of them have defaults
+that use general settings (e.g. CMAKE_PROJECT_NAME) or Debian-specific
+variables when those make sense (e.g. the homepage of an upstream project
+is usually unchanged by the flavor of packaging). When there is no Debian
+information to fall back on, but the RPM packaging has it, fall back to
+the RPM information (e.g. package license).
+
+.. variable:: CPACK_FREEBSD_PACKAGE_NAME
+
+ Sets the package name (in the package manifest, but also affects the
+ output filename).
+
+ * Mandatory: YES
+ * Default:
+
+ - :variable:`CPACK_PACKAGE_NAME` (this is always set by CPack itself,
+ based on CMAKE_PROJECT_NAME).
+
+.. variable:: CPACK_FREEBSD_PACKAGE_COMMENT
+
+ Sets the package comment. This is the short description displayed by
+ pkg(8) in standard "pkg info" output.
+
+ * Mandatory: YES
+ * Default:
+
+ - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set
+ by CPack itself, if nothing else sets it explicitly).
+ - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION
+ parameter for :command:`project`).
+
+.. variable:: CPACK_FREEBSD_PACKAGE_DESCRIPTION
+
+ Sets the package description. This is the long description of the package,
+ given by "pkg info" with a specific package as argument.
+
+ * Mandatory: YES
+ * Default:
+
+ - :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` (this may be set already
+ for Debian packaging, so we may as well re-use it).
+
+.. variable:: CPACK_FREEBSD_PACKAGE_WWW
+
+ The URL of the web site for this package, preferably (when applicable) the
+ site from which the original source can be obtained and any additional
+ upstream documentation or information may be found.
+
+ * Mandatory: YES
+ * Default:
+
+ - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set,
+ :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
+ for Debian packaging, so we may as well re-use it).
+
+.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE
+
+ The license, or licenses, which apply to this software package. This must
+ be one or more license-identifiers that pkg recognizes as acceptable license
+ identifiers (e.g. "GPLv2").
+
+ * Mandatory: YES
+ * Default:
+
+ - :variable:`CPACK_RPM_PACKAGE_LICENSE`
+
+.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE_LOGIC
+
+ This variable is only of importance if there is more than one license.
+ The default is "single", which is only applicable to a single license.
+ Other acceptable values are determined by pkg -- those are "dual" or "multi" --
+ meaning choice (OR) or simultaneous (AND) application of the licenses.
+
+ * Mandatory: NO
+ * Default: single
+
+.. variable:: CPACK_FREEBSD_PACKAGE_MAINTAINER
+
+ The FreeBSD maintainer (e.g. kde@freebsd.org) of this package.
+
+ * Mandatory: YES
+ * Default: none
+
+.. variable:: CPACK_FREEBSD_PACKAGE_ORIGIN
+
+ The origin (ports label) of this package; for packages built by CPack
+ outside of the ports system this is of less importance. The default
+ puts the package somewhere under misc/, as a stopgap.
+
+ * Mandatory: YES
+ * Default: misc/<package name>
+
+.. variable:: CPACK_FREEBSD_PACKAGE_CATEGORIES
+
+ The ports categories where this package lives (if it were to be built
+ from ports). If none is set a single category is determined based on
+ the package origin.
+
+ * Mandatory: YES
+ * Default: derived from ORIGIN
+
+.. variable:: CPACK_FREEBSD_PACKAGE_DEPS
+
+ A list of package origins that should be added as package dependencies.
+ These are in the form <category>/<packagename>, e.g. x11/libkonq.
+ No version information needs to be provided (this is not included
+ in the manifest).
+
+ * Mandatory: NO
+ * Default: empty
--- /dev/null
+CPack IFW Generator
+-------------------
+
+See :module:`CPackIFW` for details on the CPackIFW module.
+
+.. _QtIFW: http://doc.qt.io/qtinstallerframework/index.html
+
+
+Overview
+^^^^^^^^
+
+CPack ``IFW`` generator helps you to create online and offline
+binary cross-platform installers with a graphical user interface.
+
+CPack IFW generator prepares project installation and generates configuration
+and meta information for QtIFW_ tools.
+
+The QtIFW_ provides a set of tools and utilities to create
+installers for the supported desktop Qt platforms: Linux, Microsoft Windows,
+and macOS.
+
+You should also install QtIFW_ to use CPack ``IFW`` generator.
+
+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
+^^^^^^^^^
+
+You can use the following variables to change behavior of CPack ``IFW``
+generator.
+
+Debug
+"""""
+
+.. variable:: CPACK_IFW_VERBOSE
+
+ Set to ``ON`` to enable addition debug output.
+ By default is ``OFF``.
+
+Package
+"""""""
+
+.. variable:: CPACK_IFW_PACKAGE_TITLE
+
+ Name of the installer as displayed on the title bar.
+ By default used :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`.
+
+.. variable:: CPACK_IFW_PACKAGE_PUBLISHER
+
+ Publisher of the software (as shown in the Windows Control Panel).
+ By default used :variable:`CPACK_PACKAGE_VENDOR`.
+
+.. variable:: CPACK_IFW_PRODUCT_URL
+
+ URL to a page that contains product information on your web site.
+
+.. variable:: CPACK_IFW_PACKAGE_ICON
+
+ Filename for a custom installer icon. The actual file is '.icns' (macOS),
+ '.ico' (Windows). No functionality on Unix.
+
+.. variable:: CPACK_IFW_PACKAGE_WINDOW_ICON
+
+ Filename for a custom window icon in PNG format for the Installer
+ application.
+
+.. variable:: CPACK_IFW_PACKAGE_LOGO
+
+ Filename for a logo is used as QWizard::LogoPixmap.
+
+.. variable:: CPACK_IFW_PACKAGE_WATERMARK
+
+ Filename for a watermark is used as QWizard::WatermarkPixmap.
+
+.. variable:: CPACK_IFW_PACKAGE_BANNER
+
+ Filename for a banner is used as QWizard::BannerPixmap.
+
+.. variable:: CPACK_IFW_PACKAGE_BACKGROUND
+
+ Filename for an image used as QWizard::BackgroundPixmap (only used by MacStyle).
+
+.. variable:: CPACK_IFW_PACKAGE_WIZARD_STYLE
+
+ Wizard style to be used ("Modern", "Mac", "Aero" or "Classic").
+
+.. variable:: CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH
+
+ Default width of the wizard in pixels. Setting a banner image will override this.
+
+.. variable:: CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT
+
+ Default height of the wizard in pixels. Setting a watermark image will override this.
+
+.. variable:: CPACK_IFW_PACKAGE_TITLE_COLOR
+
+ Color of the titles and subtitles (takes an HTML color code, such as "#88FF33").
+
+.. variable:: CPACK_IFW_PACKAGE_START_MENU_DIRECTORY
+
+ Name of the default program group for the product in the Windows Start menu.
+
+ By default used :variable:`CPACK_IFW_PACKAGE_NAME`.
+
+.. variable:: CPACK_IFW_TARGET_DIRECTORY
+
+ Default target directory for installation.
+ By default used
+ "@ApplicationsDir@/:variable:`CPACK_PACKAGE_INSTALL_DIRECTORY`"
+
+ You can use predefined variables.
+
+.. variable:: CPACK_IFW_ADMIN_TARGET_DIRECTORY
+
+ Default target directory for installation with administrator rights.
+
+ You can use predefined variables.
+
+.. variable:: CPACK_IFW_PACKAGE_GROUP
+
+ The group, which will be used to configure the root package
+
+.. variable:: CPACK_IFW_PACKAGE_NAME
+
+ The root package name, which will be used if configuration group is not
+ specified
+
+.. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME
+
+ Filename of the generated maintenance tool.
+ The platform-specific executable file extension is appended.
+
+ By default used QtIFW_ defaults (``maintenancetool``).
+
+.. variable:: CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR
+
+ Set to ``OFF`` if the target directory should not be deleted when uninstalling.
+
+ Is ``ON`` by default
+
+.. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE
+
+ Filename for the configuration of the generated maintenance tool.
+
+ By default used QtIFW_ defaults (``maintenancetool.ini``).
+
+.. variable:: CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS
+
+ Set to ``ON`` if the installation path can contain non-ASCII characters.
+
+ Is ``ON`` for QtIFW_ less 2.0 tools.
+
+.. variable:: CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH
+
+ Set to ``OFF`` if the installation path cannot contain space characters.
+
+ Is ``ON`` for QtIFW_ less 2.0 tools.
+
+.. variable:: CPACK_IFW_PACKAGE_CONTROL_SCRIPT
+
+ Filename for a custom installer control script.
+
+.. variable:: CPACK_IFW_PACKAGE_RESOURCES
+
+ List of additional resources ('.qrc' files) to include in the installer
+ binary.
+
+ You can use :command:`cpack_ifw_add_package_resources` command to resolve
+ relative paths.
+
+.. variable:: CPACK_IFW_PACKAGE_FILE_EXTENSION
+
+ The target binary extension.
+
+ On Linux, the name of the target binary is automatically extended with
+ '.run', if you do not specify the extension.
+
+ On Windows, the target is created as an application with the extension
+ '.exe', which is automatically added, if not supplied.
+
+ On Mac, the target is created as an DMG disk image with the extension
+ '.dmg', which is automatically added, if not supplied.
+
+.. variable:: CPACK_IFW_REPOSITORIES_ALL
+
+ The list of remote repositories.
+
+ The default value of this variable is computed by CPack and contains
+ all repositories added with command :command:`cpack_ifw_add_repository`
+ or updated with command :command:`cpack_ifw_update_repository`.
+
+.. variable:: CPACK_IFW_DOWNLOAD_ALL
+
+ If this is ``ON`` all components will be downloaded.
+ By default is ``OFF`` or used value
+ from ``CPACK_DOWNLOAD_ALL`` if set
+
+Components
+""""""""""
+
+.. variable:: CPACK_IFW_RESOLVE_DUPLICATE_NAMES
+
+ Resolve duplicate names when installing components with groups.
+
+.. variable:: CPACK_IFW_PACKAGES_DIRECTORIES
+
+ Additional prepared packages dirs that will be used to resolve
+ dependent components.
+
+.. variable:: CPACK_IFW_REPOSITORIES_DIRECTORIES
+
+ Additional prepared repository dirs that will be used to resolve and
+ repack dependent components. This feature available only
+ since QtIFW_ 3.1.
+
+Tools
+"""""
+
+.. variable:: CPACK_IFW_FRAMEWORK_VERSION
+
+ The version of used QtIFW_ tools.
+
+.. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE
+
+ The path to "binarycreator" command line client.
+
+ 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 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.
+
+
+Online installer
+^^^^^^^^^^^^^^^^
+
+By default CPack IFW generator makes offline installer. This means that all
+components will be packaged into a binary file.
+
+To make a component downloaded, you must set the ``DOWNLOADED`` option in
+:command:`cpack_add_component`.
+
+Then you would use the command :command:`cpack_configure_downloads`.
+If you set ``ALL`` option all components will be downloaded.
+
+You also can use command :command:`cpack_ifw_add_repository` and
+variable :variable:`CPACK_IFW_DOWNLOAD_ALL` for more specific configuration.
+
+CPack IFW generator creates "repository" dir in current binary dir. You
+would copy content of this dir to specified ``site`` (``url``).
+
+See Also
+^^^^^^^^
+
+Qt Installer Framework Manual:
+
+* Index page:
+ http://doc.qt.io/qtinstallerframework/index.html
+
+* Component Scripting:
+ http://doc.qt.io/qtinstallerframework/scripting.html
+
+* Predefined Variables:
+ http://doc.qt.io/qtinstallerframework/scripting.html#predefined-variables
+
+* Promoting Updates:
+ http://doc.qt.io/qtinstallerframework/ifw-updates.html
+
+Download Qt Installer Framework for you platform from Qt site:
+ http://download.qt.io/official_releases/qt-installer-framework
--- /dev/null
+CPack NSIS Generator
+--------------------
+
+CPack NSIS generator specific options
+
+Variables specific to CPack NSIS generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following variables are specific to the graphical installers built
+on Windows using the Nullsoft Installation System.
+
+.. variable:: CPACK_NSIS_INSTALL_ROOT
+
+ The default installation directory presented to the end user by the NSIS
+ installer is under this root dir. The full directory presented to the end
+ user is: ${CPACK_NSIS_INSTALL_ROOT}/${CPACK_PACKAGE_INSTALL_DIRECTORY}
+
+.. variable:: CPACK_NSIS_MUI_ICON
+
+ An icon filename. The name of a ``*.ico`` file used as the main icon for the
+ generated install program.
+
+.. variable:: CPACK_NSIS_MUI_UNIICON
+
+ An icon filename. The name of a ``*.ico`` file used as the main icon for the
+ generated uninstall program.
+
+.. variable:: CPACK_NSIS_INSTALLER_MUI_ICON_CODE
+
+ undocumented.
+
+.. variable:: CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP
+
+ The filename of a bitmap to use as the NSIS MUI_WELCOMEFINISHPAGE_BITMAP.
+
+.. variable:: CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP
+
+ The filename of a bitmap to use as the NSIS MUI_UNWELCOMEFINISHPAGE_BITMAP.
+
+.. variable:: CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS
+
+ Extra NSIS commands that will be added to the beginning of the install
+ Section, before your install tree is available on the target system.
+
+.. variable:: CPACK_NSIS_EXTRA_INSTALL_COMMANDS
+
+ Extra NSIS commands that will be added to the end of the install Section,
+ after your install tree is available on the target system.
+
+.. variable:: CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
+
+ Extra NSIS commands that will be added to the uninstall Section, before
+ your install tree is removed from the target system.
+
+.. variable:: CPACK_NSIS_COMPRESSOR
+
+ The arguments that will be passed to the NSIS SetCompressor command.
+
+.. variable:: CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL
+
+ Ask about uninstalling previous versions first. If this is set to "ON",
+ then an installer will look for previous installed versions and if one is
+ found, ask the user whether to uninstall it before proceeding with the
+ install.
+
+.. variable:: CPACK_NSIS_MODIFY_PATH
+
+ Modify PATH toggle. If this is set to "ON", then an extra page will appear
+ in the installer that will allow the user to choose whether the program
+ directory should be added to the system PATH variable.
+
+.. variable:: CPACK_NSIS_DISPLAY_NAME
+
+ The display name string that appears in the Windows Add/Remove Program
+ control panel
+
+.. variable:: CPACK_NSIS_PACKAGE_NAME
+
+ The title displayed at the top of the installer.
+
+.. variable:: CPACK_NSIS_INSTALLED_ICON_NAME
+
+ A path to the executable that contains the installer icon.
+
+.. variable:: CPACK_NSIS_HELP_LINK
+
+ URL to a web site providing assistance in installing your application.
+
+.. variable:: CPACK_NSIS_URL_INFO_ABOUT
+
+ URL to a web site providing more information about your application.
+
+.. variable:: CPACK_NSIS_CONTACT
+
+ Contact information for questions and comments about the installation
+ process.
+
+.. variable:: CPACK_NSIS_<compName>_INSTALL_DIRECTORY
+
+ Custom install directory for the specified component <compName> instead
+ of $INSTDIR.
+
+.. variable:: CPACK_NSIS_CREATE_ICONS_EXTRA
+
+ Additional NSIS commands for creating start menu shortcuts.
+
+.. variable:: CPACK_NSIS_DELETE_ICONS_EXTRA
+
+ Additional NSIS commands to uninstall start menu shortcuts.
+
+.. variable:: CPACK_NSIS_EXECUTABLES_DIRECTORY
+
+ Creating NSIS start menu links assumes that they are in 'bin' unless this
+ variable is set. For example, you would set this to 'exec' if your
+ executables are in an exec directory.
+
+.. variable:: CPACK_NSIS_MUI_FINISHPAGE_RUN
+
+ Specify an executable to add an option to run on the finish page of the
+ NSIS installer.
+
+.. variable:: CPACK_NSIS_MENU_LINKS
+
+ Specify links in [application] menu. This should contain a list of pair
+ "link" "link name". The link may be a URL or a path relative to
+ installation prefix. Like::
+
+ set(CPACK_NSIS_MENU_LINKS
+ "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html"
+ "CMake Help" "https://cmake.org" "CMake Web Site")
--- /dev/null
+CPack NuGet Generator
+---------------------
+
+When build a NuGet package there is no direct way to control an output
+filename due a lack of the corresponding CLI option of NuGet, so there
+is no ``CPACK_NUGET_PACKAGE_FILENAME`` variable. To form the output filename
+NuGet uses the package name and the version according to its built-in rules.
+
+Also, be aware that including a top level directory
+(``CPACK_INCLUDE_TOPLEVEL_DIRECTORY``) is ignored by this generator.
+
+
+Variables specific to CPack NuGet generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack NuGet generator may be used to create NuGet packages using
+:module:`CPack`. The CPack NuGet generator is a :module:`CPack` generator thus
+it uses the ``CPACK_XXX`` variables used by :module:`CPack`.
+
+The CPack NuGet generator has specific features which are controlled by the
+specifics :code:`CPACK_NUGET_XXX` variables. In the "one per group" mode
+(see :variable:`CPACK_COMPONENTS_GROUPING`), ``<compName>`` placeholder
+in the variables below would contain a group name (uppercased and turned into
+a "C" identifier).
+
+List of CPack NuGet generator specific variables:
+
+.. variable:: CPACK_NUGET_COMPONENT_INSTALL
+
+ Enable component packaging for CPack NuGet generator
+
+ * Mandatory : NO
+ * Default : OFF
+
+.. variable:: CPACK_NUGET_PACKAGE_NAME
+ CPACK_NUGET_<compName>_PACKAGE_NAME
+
+ The NUGET package name.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_NAME`
+
+.. variable:: CPACK_NUGET_PACKAGE_VERSION
+ CPACK_NUGET_<compName>_PACKAGE_VERSION
+
+ The NuGet package version.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VERSION`
+
+.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION
+ CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION
+
+ A long description of the package for UI display.
+
+ * Mandatory : YES
+ * Default :
+ - :variable:`CPACK_COMPONENT_<compName>_DESCRIPTION`,
+ - ``CPACK_COMPONENT_GROUP_<groupName>_DESCRIPTION``,
+ - :variable:`CPACK_PACKAGE_DESCRIPTION`
+
+.. variable:: CPACK_NUGET_PACKAGE_AUTHORS
+ CPACK_NUGET_<compName>_PACKAGE_AUTHORS
+
+ A comma-separated list of packages authors, matching the profile names
+ on nuget.org_. These are displayed in the NuGet Gallery on
+ nuget.org_ and are used to cross-reference packages by the same
+ authors.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VENDOR`
+
+.. variable:: CPACK_NUGET_PACKAGE_TITLE
+ CPACK_NUGET_<compName>_PACKAGE_TITLE
+
+ A human-friendly title of the package, typically used in UI displays
+ as on nuget.org_ and the Package Manager in Visual Studio. If not
+ specified, the package ID is used.
+
+ * Mandatory : NO
+ * Default :
+ - :variable:`CPACK_COMPONENT_<compName>_DISPLAY_NAME`,
+ - ``CPACK_COMPONENT_GROUP_<groupName>_DISPLAY_NAME``
+
+.. variable:: CPACK_NUGET_PACKAGE_OWNERS
+ CPACK_NUGET_<compName>_PACKAGE_OWNERS
+
+ A comma-separated list of the package creators using profile names
+ on nuget.org_. This is often the same list as in authors,
+ and is ignored when uploading the package to nuget.org_.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_HOMEPAGE_URL
+ CPACK_NUGET_<compName>_PACKAGE_HOMEPAGE_URL
+
+ A URL for the package's home page, often shown in UI displays as well
+ as nuget.org_.
+
+ * Mandatory : NO
+ * Default : :variable:`CPACK_PACKAGE_HOMEPAGE_URL`
+
+.. variable:: CPACK_NUGET_PACKAGE_LICENSEURL
+ CPACK_NUGET_<compName>_PACKAGE_LICENSEURL
+
+ A URL for the package's license, often shown in UI displays as well
+ as nuget.org_.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_ICONURL
+ CPACK_NUGET_<compName>_PACKAGE_ICONURL
+
+ A URL for a 64x64 image with transparency background to use as the
+ icon for the package in UI display.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION_SUMMARY
+ CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION_SUMMARY
+
+ A short description of the package for UI display. If omitted, a
+ truncated version of description is used.
+
+ * Mandatory : NO
+ * Default : :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+
+.. variable:: CPACK_NUGET_PACKAGE_RELEASE_NOTES
+ CPACK_NUGET_<compName>_PACKAGE_RELEASE_NOTES
+
+ A description of the changes made in this release of the package,
+ often used in UI like the Updates tab of the Visual Studio Package
+ Manager in place of the package description.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_COPYRIGHT
+ CPACK_NUGET_<compName>_PACKAGE_COPYRIGHT
+
+ Copyright details for the package.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_TAGS
+ CPACK_NUGET_<compName>_PACKAGE_TAGS
+
+ A space-delimited list of tags and keywords that describe the
+ package and aid discoverability of packages through search and
+ filtering.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES
+ CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES
+
+ A list of package dependencies.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES_<dependency>_VERSION
+ CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES_<dependency>_VERSION
+
+ A `version specification`_ for the particular dependency, where
+ ``<dependency>`` is an item of the dependency list (see above)
+ transformed with ``MAKE_C_IDENTIFIER`` function of :command:`string`
+ command.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEBUG
+
+ Enable debug messages while executing CPack NuGet generator.
+
+ * Mandatory : NO
+ * Default : OFF
+
+
+.. _nuget.org: http://nuget.org
+.. _version specification: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
+
+.. NuGet spec docs https://docs.microsoft.com/en-us/nuget/reference/nuspec
--- /dev/null
+CPack PackageMaker Generator
+----------------------------
+
+PackageMaker CPack generator (macOS).
+
+Variables specific to CPack PackageMaker generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following variable is specific to installers built on Mac
+macOS using PackageMaker:
+
+.. variable:: CPACK_OSX_PACKAGE_VERSION
+
+ The version of macOS that the resulting PackageMaker archive should be
+ compatible with. Different versions of macOS support different
+ features. For example, CPack can only build component-based installers for
+ macOS 10.4 or newer, and can only build installers that download
+ component son-the-fly for macOS 10.5 or newer. If left blank, this value
+ will be set to the minimum version of macOS that supports the requested
+ features. Set this variable to some value (e.g., 10.4) only if you want to
+ guarantee that your installer will work on that version of macOS, and
+ don't mind missing extra features available in the installer shipping with
+ later versions of macOS.
--- /dev/null
+CPack productbuild Generator
+----------------------------
+
+productbuild CPack generator (macOS).
+
+Variables specific to CPack productbuild generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following variable is specific to installers built on Mac
+macOS using ProductBuild:
+
+.. variable:: CPACK_COMMAND_PRODUCTBUILD
+
+ Path to the ``productbuild(1)`` command used to generate a product archive for
+ the macOS Installer or Mac App Store. This variable can be used to override
+ the automatically detected command (or specify its location if the
+ auto-detection fails to find it).
+
+.. variable:: CPACK_PRODUCTBUILD_IDENTITY_NAME
+
+ Adds a digital signature to the resulting package.
+
+
+.. variable:: CPACK_PRODUCTBUILD_KEYCHAIN_PATH
+
+ Specify a specific keychain to search for the signing identity.
+
+
+.. variable:: CPACK_COMMAND_PKGBUILD
+
+ Path to the ``pkgbuild(1)`` command used to generate an macOS component package
+ on macOS. This variable can be used to override the automatically detected
+ command (or specify its location if the auto-detection fails to find it).
+
+
+.. variable:: CPACK_PKGBUILD_IDENTITY_NAME
+
+ Adds a digital signature to the resulting package.
+
+
+.. variable:: CPACK_PKGBUILD_KEYCHAIN_PATH
+
+ Specify a specific keychain to search for the signing identity.
+
+
+.. variable:: CPACK_PREFLIGHT_<COMP>_SCRIPT
+
+ Full path to a file that will be used as the ``preinstall`` script for the
+ named ``<COMP>`` component's package, where ``<COMP>`` is the uppercased
+ component name. No ``preinstall`` script is added if this variable is not
+ defined for a given component.
+
+
+.. variable:: CPACK_POSTFLIGHT_<COMP>_SCRIPT
+
+ Full path to a file that will be used as the ``postinstall`` script for the
+ named ``<COMP>`` component's package, where ``<COMP>`` is the uppercased
+ component name. No ``postinstall`` script is added if this variable is not
+ defined for a given component.
+
+
+.. 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.
--- /dev/null
+CPack RPM Generator
+-------------------
+
+The built in (binary) CPack RPM generator (Unix only)
+
+Variables specific to CPack RPM generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack RPM generator may be used to create RPM packages using :module:`CPack`.
+The CPack RPM generator is a :module:`CPack` generator thus it uses the
+``CPACK_XXX`` variables used by :module:`CPack`.
+
+The CPack RPM generator has specific features which are controlled by the specifics
+:code:`CPACK_RPM_XXX` variables.
+
+:code:`CPACK_RPM_<COMPONENT>_XXXX` variables may be used in order to have
+**component** specific values. Note however that ``<COMPONENT>`` refers to the
+**grouping name** written in upper case. It may be either a component name or
+a component GROUP name. Usually those variables correspond to RPM spec file
+entities. One may find information about spec files here
+http://www.rpm.org/wiki/Docs
+
+.. note::
+
+ `<COMPONENT>` part of variables is preferred to be in upper case (for e.g. if
+ component is named `foo` then use `CPACK_RPM_FOO_XXXX` variable name format)
+ as is with other `CPACK_<COMPONENT>_XXXX` variables.
+ For the purposes of back compatibility (CMake/CPack version 3.5 and lower)
+ support for same cased component (e.g. `fOo` would be used as
+ `CPACK_RPM_fOo_XXXX`) is still supported for variables defined in older
+ versions of CMake/CPack but is not guaranteed for variables that
+ will be added in the future. For the sake of back compatibility same cased
+ component variables also override upper cased versions where both are
+ present.
+
+Here are some CPack RPM generator wiki resources that are here for historic reasons and
+are no longer maintained but may still prove useful:
+
+ - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/Configuration
+ - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/PackageGenerators#rpm-unix-only
+
+List of CPack RPM generator specific variables:
+
+.. variable:: CPACK_RPM_COMPONENT_INSTALL
+
+ Enable component packaging for CPack RPM generator
+
+ * Mandatory : NO
+ * Default : OFF
+
+ If enabled (ON) multiple packages are generated. By default a single package
+ containing files of all components is generated.
+
+.. variable:: CPACK_RPM_PACKAGE_SUMMARY
+ CPACK_RPM_<component>_PACKAGE_SUMMARY
+
+ The RPM package summary.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+
+.. variable:: CPACK_RPM_PACKAGE_NAME
+ CPACK_RPM_<component>_PACKAGE_NAME
+
+ The RPM package name.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_NAME`
+
+.. variable:: CPACK_RPM_FILE_NAME
+ CPACK_RPM_<component>_FILE_NAME
+
+ Package file name.
+
+ * Mandatory : YES
+ * Default : ``<CPACK_PACKAGE_FILE_NAME>[-<component>].rpm`` with spaces
+ replaced by '-'
+
+ This may be set to ``RPM-DEFAULT`` to allow rpmbuild tool to generate package
+ file name by itself.
+ Alternatively provided package file name must end with ``.rpm`` suffix.
+
+ .. note::
+
+ By using user provided spec file, rpm macro extensions such as for
+ generating debuginfo packages or by simply using multiple components more
+ than one rpm file may be generated, either from a single spec file or from
+ multiple spec files (each component execution produces its own spec file).
+ In such cases duplicate file names may occur as a result of this variable
+ setting or spec file content structure. Duplicate files get overwritten
+ and it is up to the packager to set the variables in a manner that will
+ prevent such errors.
+
+.. variable:: CPACK_RPM_MAIN_COMPONENT
+
+ Main component that is packaged without component suffix.
+
+ * Mandatory : NO
+ * Default : -
+
+ This variable can be set to any component or group name so that component or
+ group rpm package is generated without component suffix in filename and
+ package name.
+
+.. variable:: CPACK_RPM_PACKAGE_EPOCH
+
+ The RPM package epoch
+
+ * Mandatory : No
+ * Default : -
+
+ Optional number that should be incremented when changing versioning schemas
+ or fixing mistakes in the version numbers of older packages.
+
+.. variable:: CPACK_RPM_PACKAGE_VERSION
+
+ The RPM package version.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VERSION`
+
+.. variable:: CPACK_RPM_PACKAGE_ARCHITECTURE
+ CPACK_RPM_<component>_PACKAGE_ARCHITECTURE
+
+ The RPM package architecture.
+
+ * Mandatory : YES
+ * Default : Native architecture output by ``uname -m``
+
+ This may be set to ``noarch`` if you know you are building a noarch package.
+
+.. variable:: CPACK_RPM_PACKAGE_RELEASE
+
+ The RPM package release.
+
+ * Mandatory : YES
+ * Default : 1
+
+ This is the numbering of the RPM package itself, i.e. the version of the
+ packaging and not the version of the content (see
+ :variable:`CPACK_RPM_PACKAGE_VERSION`). One may change the default value if
+ the previous packaging was buggy and/or you want to put here a fancy Linux
+ distro specific numbering.
+
+.. note::
+
+ This is the string that goes into the RPM ``Release:`` field. Some distros
+ (e.g. Fedora, CentOS) require ``1%{?dist}`` format and not just a number.
+ ``%{?dist}`` part can be added by setting :variable:`CPACK_RPM_PACKAGE_RELEASE_DIST`.
+
+.. variable:: CPACK_RPM_PACKAGE_RELEASE_DIST
+
+ The dist tag that is added RPM ``Release:`` field.
+
+ * Mandatory : NO
+ * Default : OFF
+
+ This is the reported ``%{dist}`` tag from the current distribution or empty
+ ``%{dist}`` if RPM macro is not set. If this variable is set then RPM
+ ``Release:`` field value is set to ``${CPACK_RPM_PACKAGE_RELEASE}%{?dist}``.
+
+.. variable:: CPACK_RPM_PACKAGE_LICENSE
+
+ The RPM package license policy.
+
+ * Mandatory : YES
+ * Default : "unknown"
+
+.. variable:: CPACK_RPM_PACKAGE_GROUP
+ CPACK_RPM_<component>_PACKAGE_GROUP
+
+ The RPM package group.
+
+ * Mandatory : YES
+ * Default : "unknown"
+
+.. variable:: CPACK_RPM_PACKAGE_VENDOR
+
+ The RPM package vendor.
+
+ * Mandatory : YES
+ * Default : CPACK_PACKAGE_VENDOR if set or "unknown"
+
+.. variable:: CPACK_RPM_PACKAGE_URL
+ CPACK_RPM_<component>_PACKAGE_URL
+
+ The projects URL.
+
+ * Mandatory : NO
+ * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
+
+.. variable:: CPACK_RPM_PACKAGE_DESCRIPTION
+ CPACK_RPM_<component>_PACKAGE_DESCRIPTION
+
+ RPM package description.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_COMPONENT_<compName>_DESCRIPTION` (component
+ based installers only) if set, :variable:`CPACK_PACKAGE_DESCRIPTION_FILE`
+ if set or "no package description available"
+
+.. variable:: CPACK_RPM_COMPRESSION_TYPE
+
+ RPM compression type.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to override RPM compression type to be used to build the
+ RPM. For example some Linux distribution now default to lzma or xz
+ compression whereas older cannot use such RPM. Using this one can enforce
+ compression type to be used.
+
+ Possible values are:
+
+ - lzma
+ - xz
+ - bzip2
+ - gzip
+
+.. variable:: CPACK_RPM_PACKAGE_AUTOREQ
+ CPACK_RPM_<component>_PACKAGE_AUTOREQ
+
+ RPM spec autoreq field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to enable (1, yes) or disable (0, no) automatic shared libraries
+ dependency detection. Dependencies are added to requires list.
+
+ .. note::
+
+ By default automatic dependency detection is enabled by rpm generator.
+
+.. variable:: CPACK_RPM_PACKAGE_AUTOPROV
+ CPACK_RPM_<component>_PACKAGE_AUTOPROV
+
+ RPM spec autoprov field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to enable (1, yes) or disable (0, no) automatic listing of shared
+ libraries that are provided by the package. Shared libraries are added to
+ provides list.
+
+ .. note::
+
+ By default automatic provides detection is enabled by rpm generator.
+
+.. variable:: CPACK_RPM_PACKAGE_AUTOREQPROV
+ CPACK_RPM_<component>_PACKAGE_AUTOREQPROV
+
+ RPM spec autoreqprov field.
+
+ * Mandatory : NO
+ * Default : -
+
+ Variable enables/disables autoreq and autoprov at the same time.
+ See :variable:`CPACK_RPM_PACKAGE_AUTOREQ` and :variable:`CPACK_RPM_PACKAGE_AUTOPROV`
+ for more details.
+
+ .. note::
+
+ By default automatic detection feature is enabled by rpm.
+
+.. variable:: CPACK_RPM_PACKAGE_REQUIRES
+ CPACK_RPM_<component>_PACKAGE_REQUIRES
+
+ RPM spec requires field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set RPM dependencies (requires). Note that you must enclose
+ the complete requires string between quotes, for example::
+
+ set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.5.0, cmake >= 2.8")
+
+ The required package list of an RPM file could be printed with::
+
+ rpm -qp --requires file.rpm
+
+.. variable:: CPACK_RPM_PACKAGE_CONFLICTS
+ CPACK_RPM_<component>_PACKAGE_CONFLICTS
+
+ RPM spec conflicts field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set negative RPM dependencies (conflicts). Note that you must
+ enclose the complete requires string between quotes, for example::
+
+ set(CPACK_RPM_PACKAGE_CONFLICTS "libxml2")
+
+ The conflicting package list of an RPM file could be printed with::
+
+ rpm -qp --conflicts file.rpm
+
+.. variable:: CPACK_RPM_PACKAGE_REQUIRES_PRE
+ CPACK_RPM_<component>_PACKAGE_REQUIRES_PRE
+
+ RPM spec requires(pre) field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set RPM preinstall dependencies (requires(pre)). Note that
+ you must enclose the complete requires string between quotes, for example::
+
+ set(CPACK_RPM_PACKAGE_REQUIRES_PRE "shadow-utils, initscripts")
+
+.. variable:: CPACK_RPM_PACKAGE_REQUIRES_POST
+ CPACK_RPM_<component>_PACKAGE_REQUIRES_POST
+
+ RPM spec requires(post) field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set RPM postinstall dependencies (requires(post)). Note that
+ you must enclose the complete requires string between quotes, for example::
+
+ set(CPACK_RPM_PACKAGE_REQUIRES_POST "shadow-utils, initscripts")
+
+.. variable:: CPACK_RPM_PACKAGE_REQUIRES_POSTUN
+ CPACK_RPM_<component>_PACKAGE_REQUIRES_POSTUN
+
+ RPM spec requires(postun) field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set RPM postuninstall dependencies (requires(postun)). Note
+ that you must enclose the complete requires string between quotes, for
+ example::
+
+ set(CPACK_RPM_PACKAGE_REQUIRES_POSTUN "shadow-utils, initscripts")
+
+.. variable:: CPACK_RPM_PACKAGE_REQUIRES_PREUN
+ CPACK_RPM_<component>_PACKAGE_REQUIRES_PREUN
+
+ RPM spec requires(preun) field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set RPM preuninstall dependencies (requires(preun)). Note that
+ you must enclose the complete requires string between quotes, for example::
+
+ set(CPACK_RPM_PACKAGE_REQUIRES_PREUN "shadow-utils, initscripts")
+
+.. variable:: CPACK_RPM_PACKAGE_SUGGESTS
+ CPACK_RPM_<component>_PACKAGE_SUGGESTS
+
+ RPM spec suggest field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set weak RPM dependencies (suggests). Note that you must
+ enclose the complete requires string between quotes.
+
+.. variable:: CPACK_RPM_PACKAGE_PROVIDES
+ CPACK_RPM_<component>_PACKAGE_PROVIDES
+
+ RPM spec provides field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set RPM dependencies (provides). The provided package list
+ of an RPM file could be printed with::
+
+ rpm -qp --provides file.rpm
+
+.. variable:: CPACK_RPM_PACKAGE_OBSOLETES
+ CPACK_RPM_<component>_PACKAGE_OBSOLETES
+
+ RPM spec obsoletes field.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set RPM packages that are obsoleted by this one.
+
+.. variable:: CPACK_RPM_PACKAGE_RELOCATABLE
+
+ build a relocatable RPM.
+
+ * Mandatory : NO
+ * Default : CPACK_PACKAGE_RELOCATABLE
+
+ If this variable is set to TRUE or ON, the CPack RPM generator will try
+ to build a relocatable RPM package. A relocatable RPM may
+ be installed using::
+
+ rpm --prefix or --relocate
+
+ in order to install it at an alternate place see rpm(8). Note that
+ currently this may fail if :variable:`CPACK_SET_DESTDIR` is set to ``ON``. If
+ :variable:`CPACK_SET_DESTDIR` is set then you will get a warning message but
+ if there is file installed with absolute path you'll get unexpected behavior.
+
+.. variable:: CPACK_RPM_SPEC_INSTALL_POST
+
+ Deprecated - use :variable:`CPACK_RPM_SPEC_MORE_DEFINE` instead.
+
+ * Mandatory : NO
+ * Default : -
+ * Deprecated: YES
+
+ May be used to override the ``__spec_install_post`` section within the
+ generated spec file. This affects the install step during package creation,
+ not during package installation. For adding operations to be performed
+ during package installation, use
+ :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE` instead.
+
+.. variable:: CPACK_RPM_SPEC_MORE_DEFINE
+
+ RPM extended spec definitions lines.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to add any ``%define`` lines to the generated spec file. An
+ example of its use is to prevent stripping of executables (but note that
+ this may also disable other default post install processing)::
+
+ set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true")
+
+.. variable:: CPACK_RPM_PACKAGE_DEBUG
+
+ Toggle CPack RPM generator debug output.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be set when invoking cpack in order to trace debug information
+ during CPack RPM run. For example you may launch CPack like this::
+
+ cpack -D CPACK_RPM_PACKAGE_DEBUG=1 -G RPM
+
+.. variable:: CPACK_RPM_USER_BINARY_SPECFILE
+ CPACK_RPM_<componentName>_USER_BINARY_SPECFILE
+
+ A user provided spec file.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be set by the user in order to specify a USER binary spec file
+ to be used by the CPack RPM generator instead of generating the file.
+ The specified file will be processed by configure_file( @ONLY).
+
+.. variable:: CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE
+
+ Spec file template.
+
+ * Mandatory : NO
+ * Default : -
+
+ If set CPack will generate a template for USER specified binary
+ spec file and stop with an error. For example launch CPack like this::
+
+ cpack -D CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE=1 -G RPM
+
+ The user may then use this file in order to hand-craft is own
+ binary spec file which may be used with
+ :variable:`CPACK_RPM_USER_BINARY_SPECFILE`.
+
+.. variable:: CPACK_RPM_PRE_INSTALL_SCRIPT_FILE
+ CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE
+
+ Path to file containing pre (un)install script.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to embed a pre (un)installation script in the spec file.
+ The referred script file (or both) will be read and directly
+ put after the ``%pre`` or ``%preun`` section
+ If :variable:`CPACK_RPM_COMPONENT_INSTALL` is set to ON the (un)install
+ script for each component can be overridden with
+ ``CPACK_RPM_<COMPONENT>_PRE_INSTALL_SCRIPT_FILE`` and
+ ``CPACK_RPM_<COMPONENT>_PRE_UNINSTALL_SCRIPT_FILE``.
+ One may verify which scriptlet has been included with::
+
+ rpm -qp --scripts package.rpm
+
+.. variable:: CPACK_RPM_POST_INSTALL_SCRIPT_FILE
+ CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE
+
+ Path to file containing post (un)install script.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to embed a post (un)installation script in the spec file.
+ The referred script file (or both) will be read and directly
+ put after the ``%post`` or ``%postun`` section.
+ If :variable:`CPACK_RPM_COMPONENT_INSTALL` is set to ON the (un)install
+ script for each component can be overridden with
+ ``CPACK_RPM_<COMPONENT>_POST_INSTALL_SCRIPT_FILE`` and
+ ``CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE``.
+ One may verify which scriptlet has been included with::
+
+ rpm -qp --scripts package.rpm
+
+.. variable:: CPACK_RPM_USER_FILELIST
+ CPACK_RPM_<COMPONENT>_USER_FILELIST
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to explicitly specify ``%(<directive>)`` file line
+ in the spec file. Like ``%config(noreplace)`` or any other directive
+ that be found in the ``%files`` section. You can have multiple directives
+ per line, as in ``%attr(600,root,root) %config(noreplace)``. Since
+ the CPack RPM generator is generating the list of files (and directories) the
+ user specified files of the ``CPACK_RPM_<COMPONENT>_USER_FILELIST`` list will
+ be removed from the generated list. If referring to directories do
+ not add a trailing slash.
+
+.. variable:: CPACK_RPM_CHANGELOG_FILE
+
+ RPM changelog file.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to embed a changelog in the spec file.
+ The referred file will be read and directly put after the ``%changelog``
+ section.
+
+.. variable:: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST
+
+ list of path to be excluded.
+
+ * Mandatory : NO
+ * Default : /etc /etc/init.d /usr /usr/bin /usr/include /usr/lib
+ /usr/libx32 /usr/lib64 /usr/share /usr/share/aclocal
+ /usr/share/doc
+
+ May be used to exclude path (directories or files) from the auto-generated
+ list of paths discovered by CPack RPM. The default value contains a
+ reasonable set of values if the variable is not defined by the user. If the
+ variable is defined by the user then the CPack RPM generator will NOT any of
+ the default path. If you want to add some path to the default list then you
+ can use :variable:`CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION` variable.
+
+.. variable:: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
+
+ additional list of path to be excluded.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to add more exclude path (directories or files) from the initial
+ default list of excluded paths. See
+ :variable:`CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST`.
+
+.. variable:: CPACK_RPM_RELOCATION_PATHS
+
+ Packages relocation paths list.
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to specify more than one relocation path per relocatable RPM.
+ Variable contains a list of relocation paths that if relative are prefixed
+ by the value of :variable:`CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX` or by the
+ value of :variable:`CPACK_PACKAGING_INSTALL_PREFIX` if the component version
+ is not provided.
+ Variable is not component based as its content can be used to set a different
+ path prefix for e.g. binary dir and documentation dir at the same time.
+ Only prefixes that are required by a certain component are added to that
+ component - component must contain at least one file/directory/symbolic link
+ with :variable:`CPACK_RPM_RELOCATION_PATHS` prefix for a certain relocation
+ path to be added. Package will not contain any relocation paths if there are
+ no files/directories/symbolic links on any of the provided prefix locations.
+ Packages that either do not contain any relocation paths or contain
+ files/directories/symbolic links that are outside relocation paths print
+ out an ``AUTHOR_WARNING`` that RPM will be partially relocatable.
+
+.. variable:: CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
+
+ Per component relocation path install prefix.
+
+ * Mandatory : NO
+ * Default : CPACK_PACKAGING_INSTALL_PREFIX
+
+ May be used to set per component :variable:`CPACK_PACKAGING_INSTALL_PREFIX`
+ for relocatable RPM packages.
+
+.. variable:: CPACK_RPM_NO_INSTALL_PREFIX_RELOCATION
+ CPACK_RPM_NO_<COMPONENT>_INSTALL_PREFIX_RELOCATION
+
+ Removal of default install prefix from relocation paths list.
+
+ * Mandatory : NO
+ * Default : CPACK_PACKAGING_INSTALL_PREFIX or CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
+ are treated as one of relocation paths
+
+ May be used to remove CPACK_PACKAGING_INSTALL_PREFIX and CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
+ from relocatable RPM prefix paths.
+
+.. variable:: CPACK_RPM_ADDITIONAL_MAN_DIRS
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to set additional man dirs that could potentially be compressed
+ by brp-compress RPM macro. Variable content must be a list of regular
+ expressions that point to directories containing man files or to man files
+ directly. Note that in order to compress man pages a path must also be
+ present in brp-compress RPM script and that brp-compress script must be
+ added to RPM configuration by the operating system.
+
+ Regular expressions that are added by default were taken from brp-compress
+ RPM macro:
+
+ - /usr/man/man.*
+ - /usr/man/.*/man.*
+ - /usr/info.*
+ - /usr/share/man/man.*
+ - /usr/share/man/.*/man.*
+ - /usr/share/info.*
+ - /usr/kerberos/man.*
+ - /usr/X11R6/man/man.*
+ - /usr/lib/perl5/man/man.*
+ - /usr/share/doc/.*/man/man.*
+ - /usr/lib/.*/man/man.*
+
+.. variable:: CPACK_RPM_DEFAULT_USER
+ CPACK_RPM_<compName>_DEFAULT_USER
+
+ default user ownership of RPM content
+
+ * Mandatory : NO
+ * Default : root
+
+ Value should be user name and not UID.
+ Note that <compName> must be in upper-case.
+
+.. variable:: CPACK_RPM_DEFAULT_GROUP
+ CPACK_RPM_<compName>_DEFAULT_GROUP
+
+ default group ownership of RPM content
+
+ * Mandatory : NO
+ * Default : root
+
+ Value should be group name and not GID.
+ Note that <compName> must be in upper-case.
+
+.. variable:: CPACK_RPM_DEFAULT_FILE_PERMISSIONS
+ CPACK_RPM_<compName>_DEFAULT_FILE_PERMISSIONS
+
+ default permissions used for packaged files
+
+ * Mandatory : NO
+ * Default : - (system default)
+
+ Accepted values are lists with ``PERMISSIONS``. Valid permissions
+ are:
+
+ - OWNER_READ
+ - OWNER_WRITE
+ - OWNER_EXECUTE
+ - GROUP_READ
+ - GROUP_WRITE
+ - GROUP_EXECUTE
+ - WORLD_READ
+ - WORLD_WRITE
+ - WORLD_EXECUTE
+
+ Note that <compName> must be in upper-case.
+
+.. variable:: CPACK_RPM_DEFAULT_DIR_PERMISSIONS
+ CPACK_RPM_<compName>_DEFAULT_DIR_PERMISSIONS
+
+ default permissions used for packaged directories
+
+ * Mandatory : NO
+ * Default : - (system default)
+
+ Accepted values are lists with PERMISSIONS. Valid permissions
+ are the same as for :variable:`CPACK_RPM_DEFAULT_FILE_PERMISSIONS`.
+ Note that <compName> must be in upper-case.
+
+.. variable:: CPACK_RPM_INSTALL_WITH_EXEC
+
+ force execute permissions on programs and shared libraries
+
+ * Mandatory : NO
+ * Default : - (system default)
+
+ Force set owner, group and world execute permissions on programs and shared
+ libraries. This can be used for creating valid rpm packages on systems such
+ as Debian where shared libraries do not have execute permissions set.
+
+.. note::
+
+ Programs and shared libraries without execute permissions are ignored during
+ separation of debug symbols from the binary for debuginfo packages.
+
+Packaging of Symbolic Links
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack RPM generator supports packaging of symbolic links::
+
+ execute_process(COMMAND ${CMAKE_COMMAND}
+ -E create_symlink <relative_path_location> <symlink_name>)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/<symlink_name>
+ DESTINATION <symlink_location> COMPONENT libraries)
+
+Symbolic links will be optimized (paths will be shortened if possible)
+before being added to the package or if multiple relocation paths are
+detected, a post install symlink relocation script will be generated.
+
+Symbolic links may point to locations that are not packaged by the same
+package (either a different component or even not packaged at all) but
+those locations will be treated as if they were a part of the package
+while determining if symlink should be either created or present in a
+post install script - depending on relocation paths.
+
+Symbolic links that point to locations outside packaging path produce a
+warning and are treated as non relocatable permanent symbolic links.
+
+Currently there are a few limitations though:
+
+* For component based packaging component interdependency is not checked
+ when processing symbolic links. Symbolic links pointing to content of
+ a different component are treated the same way as if pointing to location
+ that will not be packaged.
+
+* Symbolic links pointing to a location through one or more intermediate
+ symbolic links will not be handled differently - if the intermediate
+ symbolic link(s) is also on a relocatable path, relocating it during
+ package installation may cause initial symbolic link to point to an
+ invalid location.
+
+Packaging of debug information
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Debuginfo packages contain debug symbols and sources for debugging packaged
+binaries.
+
+Debuginfo RPM packaging has its own set of variables:
+
+.. variable:: CPACK_RPM_DEBUGINFO_PACKAGE
+ CPACK_RPM_<component>_DEBUGINFO_PACKAGE
+
+ Enable generation of debuginfo RPM package(s).
+
+ * Mandatory : NO
+ * Default : OFF
+
+.. note::
+
+ Binaries must contain debug symbols before packaging so use either ``Debug``
+ or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value.
+
+.. note::
+
+ Packages generated from packages without binary files, with binary files but
+ without execute permissions or without debug symbols will cause packaging
+ termination.
+
+.. variable:: CPACK_BUILD_SOURCE_DIRS
+
+ Provides locations of root directories of source files from which binaries
+ were built.
+
+ * Mandatory : YES if :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is set
+ * Default : -
+
+.. note::
+
+ For CMake project :variable:`CPACK_BUILD_SOURCE_DIRS` is set by default to
+ point to :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR` paths.
+
+.. note::
+
+ Sources with path prefixes that do not fall under any location provided with
+ :variable:`CPACK_BUILD_SOURCE_DIRS` will not be present in debuginfo package.
+
+.. variable:: CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX
+ CPACK_RPM_<component>_BUILD_SOURCE_DIRS_PREFIX
+
+ Prefix of location where sources will be placed during package installation.
+
+ * Mandatory : YES if :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is set
+ * Default : "/usr/src/debug/<CPACK_PACKAGE_FILE_NAME>" and
+ for component packaging "/usr/src/debug/<CPACK_PACKAGE_FILE_NAME>-<component>"
+
+.. note::
+
+ Each source path prefix is additionally suffixed by ``src_<index>`` where
+ index is index of the path used from :variable:`CPACK_BUILD_SOURCE_DIRS`
+ variable. This produces ``<CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX>/src_<index>``
+ replacement path.
+ Limitation is that replaced path part must be shorter or of equal
+ length than the length of its replacement. If that is not the case either
+ :variable:`CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX` variable has to be set to
+ a shorter path or source directories must be placed on a longer path.
+
+.. variable:: CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS
+
+ Directories containing sources that should be excluded from debuginfo packages.
+
+ * Mandatory : NO
+ * Default : "/usr /usr/src /usr/src/debug"
+
+ Listed paths are owned by other RPM packages and should therefore not be
+ deleted on debuginfo package uninstallation.
+
+.. variable:: CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS_ADDITION
+
+ Paths that should be appended to :variable:`CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS`
+ for exclusion.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE
+
+ Create a single debuginfo package even if components packaging is set.
+
+ * Mandatory : NO
+ * Default : OFF
+
+ When this variable is enabled it produces a single debuginfo package even if
+ component packaging is enabled.
+
+ When using this feature in combination with components packaging and there is
+ more than one component this variable requires :variable:`CPACK_RPM_MAIN_COMPONENT`
+ to be set.
+
+.. note::
+
+ If none of the :variable:`CPACK_RPM_<component>_DEBUGINFO_PACKAGE` variables
+ 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_<component>_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)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+SRPM packaging is enabled by setting :variable:`CPACK_RPM_PACKAGE_SOURCES`
+variable while usually using :variable:`CPACK_INSTALLED_DIRECTORIES` variable
+to provide directory containing CMakeLists.txt and source files.
+
+For CMake projects SRPM package would be produced by executing::
+
+ cpack -G RPM --config ./CPackSourceConfig.cmake
+
+.. note::
+
+ Produced SRPM package is expected to be built with :manual:`cmake(1)` executable
+ and packaged with :manual:`cpack(1)` executable so CMakeLists.txt has to be
+ located in root source directory and must be able to generate binary rpm
+ packages by executing ``cpack -G`` command. The two executables as well as
+ rpmbuild must also be present when generating binary rpm packages from the
+ produced SRPM package.
+
+Once the SRPM package is generated it can be used to generate binary packages
+by creating a directory structure for rpm generation and executing rpmbuild
+tool::
+
+ mkdir -p build_dir/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
+ rpmbuild --define "_topdir <path_to_build_dir>" --rebuild <SRPM_file_name>
+
+Generated packages will be located in build_dir/RPMS directory or its sub
+directories.
+
+.. note::
+
+ SRPM package internally uses CPack/RPM generator to generate binary packages
+ so CMakeScripts.txt can decide during the SRPM to binary rpm generation step
+ what content the package(s) should have as well as how they should be packaged
+ (monolithic or components). CMake can decide this for e.g. by reading environment
+ variables set by the package manager before starting the process of generating
+ binary rpm packages. This way a single SRPM package can be used to produce
+ different binary rpm packages on different platforms depending on the platform's
+ packaging rules.
+
+Source RPM packaging has its own set of variables:
+
+.. variable:: CPACK_RPM_PACKAGE_SOURCES
+
+ Should the content be packaged as a source rpm (default is binary rpm).
+
+ * Mandatory : NO
+ * Default : OFF
+
+.. note::
+
+ For cmake projects :variable:`CPACK_RPM_PACKAGE_SOURCES` variable is set
+ to ``OFF`` in CPackConfig.cmake and ``ON`` in CPackSourceConfig.cmake
+ generated files.
+
+.. variable:: CPACK_RPM_SOURCE_PKG_BUILD_PARAMS
+
+ Additional command-line parameters provided to :manual:`cmake(1)` executable.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX
+
+ Packaging install prefix that would be provided in :variable:`CPACK_PACKAGING_INSTALL_PREFIX`
+ variable for producing binary RPM packages.
+
+ * 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")
--- /dev/null
+CPack WIX Generator
+-------------------
+
+CPack WIX generator specific options
+
+Variables specific to CPack WIX generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following variables are specific to the installers built on
+Windows using WiX.
+
+.. variable:: CPACK_WIX_UPGRADE_GUID
+
+ Upgrade GUID (``Product/@UpgradeCode``)
+
+ Will be automatically generated unless explicitly provided.
+
+ It should be explicitly set to a constant generated globally unique
+ identifier (GUID) to allow your installers to replace existing
+ installations that use the same GUID.
+
+ You may for example explicitly set this variable in your
+ CMakeLists.txt to the value that has been generated per default. You
+ should not use GUIDs that you did not generate yourself or which may
+ belong to other projects.
+
+ A GUID shall have the following fixed length syntax::
+
+ XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+
+ (each X represents an uppercase hexadecimal digit)
+
+.. variable:: CPACK_WIX_PRODUCT_GUID
+
+ Product GUID (``Product/@Id``)
+
+ Will be automatically generated unless explicitly provided.
+
+ If explicitly provided this will set the Product Id of your installer.
+
+ The installer will abort if it detects a pre-existing installation that
+ uses the same GUID.
+
+ The GUID shall use the syntax described for CPACK_WIX_UPGRADE_GUID.
+
+.. variable:: CPACK_WIX_LICENSE_RTF
+
+ RTF License File
+
+ If CPACK_RESOURCE_FILE_LICENSE has an .rtf extension it is used as-is.
+
+ If CPACK_RESOURCE_FILE_LICENSE has an .txt extension it is implicitly
+ converted to RTF by the WIX Generator.
+ The expected encoding of the .txt file is UTF-8.
+
+ With CPACK_WIX_LICENSE_RTF you can override the license file used by the
+ WIX Generator in case CPACK_RESOURCE_FILE_LICENSE is in an unsupported
+ format or the .txt -> .rtf conversion does not work as expected.
+
+.. variable:: CPACK_WIX_PRODUCT_ICON
+
+ The Icon shown next to the program name in Add/Remove programs.
+
+ If set, this icon is used in place of the default icon.
+
+.. variable:: CPACK_WIX_UI_REF
+
+ This variable allows you to override the Id of the ``<UIRef>`` element
+ in the WiX template.
+
+ The default is ``WixUI_InstallDir`` in case no CPack components have
+ been defined and ``WixUI_FeatureTree`` otherwise.
+
+.. variable:: CPACK_WIX_UI_BANNER
+
+ The bitmap will appear at the top of all installer pages other than the
+ welcome and completion dialogs.
+
+ If set, this image will replace the default banner image.
+
+ This image must be 493 by 58 pixels.
+
+.. variable:: CPACK_WIX_UI_DIALOG
+
+ Background bitmap used on the welcome and completion dialogs.
+
+ If this variable is set, the installer will replace the default dialog
+ image.
+
+ This image must be 493 by 312 pixels.
+
+.. variable:: CPACK_WIX_PROGRAM_MENU_FOLDER
+
+ Start menu folder name for launcher.
+
+ If this variable is not set, it will be initialized with CPACK_PACKAGE_NAME
+
+.. variable:: CPACK_WIX_CULTURES
+
+ Language(s) of the installer
+
+ Languages are compiled into the WixUI extension library. To use them,
+ simply provide the name of the culture. If you specify more than one
+ culture identifier in a comma or semicolon delimited list, the first one
+ that is found will be used. You can find a list of supported languages at:
+ http://wix.sourceforge.net/manual-wix3/WixUI_localization.htm
+
+.. variable:: CPACK_WIX_TEMPLATE
+
+ Template file for WiX generation
+
+ If this variable is set, the specified template will be used to generate
+ the WiX wxs file. This should be used if further customization of the
+ output is required.
+
+ If this variable is not set, the default MSI template included with CMake
+ will be used.
+
+.. variable:: CPACK_WIX_PATCH_FILE
+
+ Optional list of XML files with fragments to be inserted into
+ generated WiX sources
+
+ This optional variable can be used to specify an XML file that the
+ WIX generator will use to inject fragments into its generated
+ source files.
+
+ Patch files understood by the CPack WIX generator
+ roughly follow this RELAX NG compact schema:
+
+ .. code-block:: none
+
+ start = CPackWiXPatch
+
+ CPackWiXPatch = element CPackWiXPatch { CPackWiXFragment* }
+
+ CPackWiXFragment = element CPackWiXFragment
+ {
+ attribute Id { string },
+ fragmentContent*
+ }
+
+ fragmentContent = element * - CPackWiXFragment
+ {
+ (attribute * { text } | text | fragmentContent)*
+ }
+
+ Currently fragments can be injected into most
+ Component, File, Directory and Feature elements.
+
+ The following additional special Ids can be used:
+
+ * ``#PRODUCT`` for the ``<Product>`` element.
+ * ``#PRODUCTFEATURE`` for the root ``<Feature>`` element.
+
+ The following example illustrates how this works.
+
+ Given that the WIX generator creates the following XML element:
+
+ .. code-block:: xml
+
+ <Component Id="CM_CP_applications.bin.my_libapp.exe" Guid="*"/>
+
+ The following XML patch file may be used to inject an Environment element
+ into it:
+
+ .. code-block:: xml
+
+ <CPackWiXPatch>
+ <CPackWiXFragment Id="CM_CP_applications.bin.my_libapp.exe">
+ <Environment Id="MyEnvironment" Action="set"
+ Name="MyVariableName" Value="MyVariableValue"/>
+ </CPackWiXFragment>
+ </CPackWiXPatch>
+
+.. variable:: CPACK_WIX_EXTRA_SOURCES
+
+ Extra WiX source files
+
+ This variable provides an optional list of extra WiX source files (.wxs)
+ that should be compiled and linked. The full path to source files is
+ required.
+
+.. variable:: CPACK_WIX_EXTRA_OBJECTS
+
+ Extra WiX object files or libraries
+
+ This variable provides an optional list of extra WiX object (.wixobj)
+ and/or WiX library (.wixlib) files. The full path to objects and libraries
+ is required.
+
+.. variable:: CPACK_WIX_EXTENSIONS
+
+ This variable provides a list of additional extensions for the WiX
+ tools light and candle.
+
+.. variable:: CPACK_WIX_<TOOL>_EXTENSIONS
+
+ This is the tool specific version of CPACK_WIX_EXTENSIONS.
+ ``<TOOL>`` can be either LIGHT or CANDLE.
+
+.. variable:: CPACK_WIX_<TOOL>_EXTRA_FLAGS
+
+ This list variable allows you to pass additional
+ flags to the WiX tool ``<TOOL>``.
+
+ Use it at your own risk.
+ Future versions of CPack may generate flags which may be in conflict
+ with your own flags.
+
+ ``<TOOL>`` can be either LIGHT or CANDLE.
+
+.. variable:: CPACK_WIX_CMAKE_PACKAGE_REGISTRY
+
+ If this variable is set the generated installer will create
+ an entry in the windows registry key
+ ``HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\<PackageName>``
+ The value for ``<PackageName>`` is provided by this variable.
+
+ Assuming you also install a CMake configuration file this will
+ allow other CMake projects to find your package with
+ the :command:`find_package` command.
+
+.. variable:: CPACK_WIX_PROPERTY_<PROPERTY>
+
+ This variable can be used to provide a value for
+ the Windows Installer property ``<PROPERTY>``
+
+ The following list contains some example properties that can be used to
+ customize information under
+ "Programs and Features" (also known as "Add or Remove Programs")
+
+ * ARPCOMMENTS - Comments
+ * ARPHELPLINK - Help and support information URL
+ * ARPURLINFOABOUT - General information URL
+ * ARPURLUPDATEINFO - Update information URL
+ * ARPHELPTELEPHONE - Help and support telephone number
+ * ARPSIZE - Size (in kilobytes) of the application
+
+.. variable:: CPACK_WIX_ROOT_FEATURE_TITLE
+
+ Sets the name of the root install feature in the WIX installer. Same as
+ CPACK_COMPONENT_<compName>_DISPLAY_NAME for components.
+
+.. variable:: CPACK_WIX_ROOT_FEATURE_DESCRIPTION
+
+ Sets the description of the root install feature in the WIX installer. Same as
+ CPACK_COMPONENT_<compName>_DESCRIPTION for components.
+
+.. variable:: CPACK_WIX_SKIP_PROGRAM_FOLDER
+
+ 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
+ between the system on which the installer is created
+ and the system on which the installer might be used into account.
+
+ It is therefore possible that the installer e.g. might try to install
+ onto a drive that is unavailable or unintended or a path that does not
+ 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.
number of the current release in the form ``$major.$minor``. It is always
merged into ``master`` before publishing.
-To merge some ``$topic`` branch into ``release``, first create the local
-branch:
+Before merging a ``$topic`` branch into ``release``, verify that the
+``$topic`` branch has already been merged to ``master`` via the usual
+``Do: merge`` process. Then, to merge the ``$topic`` branch into
+``release``, start by creating the local branch:
.. code-block:: shell
git fetch origin
git checkout -b release-$ver origin/release
-Merge the ``$topic`` branch into the local ``release-$ver`` branch:
+Merge the ``$topic`` branch into the local ``release-$ver`` branch, making
+sure to include a ``Merge-request: !xxxx`` footer in the commit message:
.. code-block:: shell
$ git clone https://gitlab.kitware.com/cmake/dashboard-scripts.git CMakeScripts
$ cd CMakeScripts
-The ``cmake_common.cmake`` script contains comments at the top with
+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
+.. _`cmake_common.cmake`: https://gitlab.kitware.com/cmake/dashboard-scripts/blob/master/cmake_common.cmake
Nightly Start Time
------------------
CMAKE_OSX_ARCHITECTURES
-----------------------
-Target specific architectures for OS X.
+Target specific architectures for macOS.
The ``CMAKE_OSX_ARCHITECTURES`` environment variable sets the default value for
the :variable:`CMAKE_OSX_ARCHITECTURES` variable. See
--- /dev/null
+CTEST_PROGRESS_OUTPUT
+---------------------
+
+Boolean environment variable that affects how :manual:`ctest <ctest(1)>`
+command output reports overall progress. When set to 1, TRUE, ON or anything
+else that evaluates to boolean true, progress is reported by repeatedly
+updating the same line. This greatly reduces the overall verbosity, but is
+only supported when output is sent directly to a terminal. If the environment
+variable is not set or has a value that evaluates to false, output is reported
+normally with each test having its own start and end lines logged to the
+output.
+
+The ``--progress`` option to :manual:`ctest <ctest(1)>` overrides this
+environment variable if both are given.
stored in the cache as :variable:`CMAKE_CUDA_HOST_COMPILER`. For any
configuration run (including the first), the environment variable will be
ignored if the :variable:`CMAKE_CUDA_HOST_COMPILER` variable is defined.
+
+This environment variable is primarily meant for use with projects that
+enable ``CUDA`` as a first-class language. The :module:`FindCUDA`
+module will also use it to initialize its ``CUDA_HOST_COMPILER`` setting.
MACOSX_DEPLOYMENT_TARGET
------------------------
-Specify the minimum version of OS X on which the target binaries are
+Specify the minimum version of macOS on which the target binaries are
to be deployed.
The ``MACOSX_DEPLOYMENT_TARGET`` environment variable sets the default value for
Generates Green Hills MULTI project files (experimental, work-in-progress).
-Customizations are available through the following cache variables:
+Customizations that are used to pick toolset and target system:
+
+The ``-A <arch>`` can be supplied for setting the target architecture.
+``<arch>`` usually is one of "arm", "ppc", "86", etcetera. If the target architecture
+is not specified then the default architecture of "arm" will be used.
+
+The ``-T <toolset>`` can be supplied for setting the toolset to be used.
+All toolsets are expected to be located at ``GHS_TOOLSET_ROOT``.
+If the toolset is not specified then the latest toolset will be used.
+
+* ``GHS_TARGET_PLATFORM``
+
+Default to ``integrity``.
+Usual values are ``integrity``, ``threadx``, ``uvelosity``,
+``velosity``, ``vxworks``, ``standalone``.
+
+* ``GHS_PRIMARY_TARGET``
+
+Sets ``primaryTarget`` field in project file.
+Defaults to ``<arch>_<GHS_TARGET_PLATFORM>.tgt``.
+
+* ``GHS_TOOLSET_ROOT``
+
+Default to ``C:/ghs``. Root path for ``toolset``.
+
+* ``GHS_OS_ROOT``
+
+Default to ``C:/ghs``. Root path for RTOS searches.
+
+* ``GHS_OS_DIR``
+
+Default to latest platform OS installation at ``GHS_OS_ROOT``. Set this value if
+a specific RTOS is to be used.
* ``GHS_BSP_NAME``
+
+Defaults to ``sim<arch>`` if not set by user.
+
+Customizations are available through the following cache variables:
+
* ``GHS_CUSTOMIZATION``
* ``GHS_GPJ_MACROS``
-* ``GHS_OS_DIR``
.. note::
This generator is deemed experimental as of CMake |release|
Generates Visual Studio 10 (VS 2010) project files.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
-to specify a target platform name (architecture).
+For compatibility with CMake versions prior to 3.0, one may specify this
+generator using the name ``Visual Studio 10`` without the year component.
+
+Project Types
+^^^^^^^^^^^^^
+
+Only Visual C++ and C# projects may be generated. Other types of
+projects (Database, Website, etc.) are not supported.
+
+Platform Selection
+^^^^^^^^^^^^^^^^^^
+
+The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+name (architecture). For example:
+
+* ``cmake -G "Visual Studio 10 2010" -A Win32``
+* ``cmake -G "Visual Studio 10 2010" -A x64``
+* ``cmake -G "Visual Studio 10 2010" -A Itanium``
For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of this generator name:
+a target platform name optionally at the end of the generator name.
+This is supported only for:
``Visual Studio 10 2010 Win64``
Specify target platform ``x64``.
``Visual Studio 10 2010 IA64``
Specify target platform ``Itanium``.
-For compatibility with CMake versions prior to 3.0, one may specify this
-generator using the name ``Visual Studio 10`` without the year component.
-
Toolset Selection
^^^^^^^^^^^^^^^^^
Generates Visual Studio 11 (VS 2012) project files.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
-to specify a target platform name (architecture).
+For compatibility with CMake versions prior to 3.0, one may specify this
+generator using the name "Visual Studio 11" without the year component.
+
+Project Types
+^^^^^^^^^^^^^
+
+Only Visual C++ and C# projects may be generated. Other types of
+projects (JavaScript, Database, Website, etc.) are not supported.
+
+Platform Selection
+^^^^^^^^^^^^^^^^^^
+
+The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+name (architecture). For example:
+
+* ``cmake -G "Visual Studio 11 2012" -A Win32``
+* ``cmake -G "Visual Studio 11 2012" -A x64``
+* ``cmake -G "Visual Studio 11 2012" -A ARM``
+* ``cmake -G "Visual Studio 11 2012" -A <WinCE-SDK>``
+ (Specify a target platform matching a Windows CE SDK name.)
For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of this generator name:
+a target platform name optionally at the end of the generator name.
+This is supported only for:
``Visual Studio 11 2012 Win64``
Specify target platform ``x64``.
``Visual Studio 11 2012 <WinCE-SDK>``
Specify target platform matching a Windows CE SDK name.
-For compatibility with CMake versions prior to 3.0, one may specify this
-generator using the name "Visual Studio 11" without the year component.
-
Toolset Selection
^^^^^^^^^^^^^^^^^
Generates Visual Studio 12 (VS 2013) project files.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
-to specify a target platform name (architecture).
+For compatibility with CMake versions prior to 3.0, one may specify this
+generator using the name "Visual Studio 12" without the year component.
+
+Project Types
+^^^^^^^^^^^^^
+
+Only Visual C++ and C# projects may be generated. Other types of
+projects (JavaScript, Powershell, Python, etc.) are not supported.
+
+Platform Selection
+^^^^^^^^^^^^^^^^^^
+
+The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+name (architecture). For example:
+
+* ``cmake -G "Visual Studio 12 2013" -A Win32``
+* ``cmake -G "Visual Studio 12 2013" -A x64``
+* ``cmake -G "Visual Studio 12 2013" -A ARM``
For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of this generator name:
+a target platform name optionally at the end of the generator name.
+This is supported only for:
``Visual Studio 12 2013 Win64``
Specify target platform ``x64``.
``Visual Studio 12 2013 ARM``
Specify target platform ``ARM``.
-For compatibility with CMake versions prior to 3.0, one may specify this
-generator using the name "Visual Studio 12" without the year component.
-
Toolset Selection
^^^^^^^^^^^^^^^^^
Generates Visual Studio 14 (VS 2015) project files.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
-to specify a target platform name (architecture).
+Project Types
+^^^^^^^^^^^^^
+
+Only Visual C++ and C# projects may be generated. Other types of
+projects (JavaScript, Powershell, Python, etc.) are not supported.
+
+Platform Selection
+^^^^^^^^^^^^^^^^^^
+
+The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+name (architecture). For example:
+
+* ``cmake -G "Visual Studio 14 2015" -A Win32``
+* ``cmake -G "Visual Studio 14 2015" -A x64``
+* ``cmake -G "Visual Studio 14 2015" -A ARM``
For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of this generator name:
+a target platform name optionally at the end of the generator name.
+This is supported only for:
``Visual Studio 14 2015 Win64``
Specify target platform ``x64``.
Generates Visual Studio 15 (VS 2017) project files.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
-to specify a target platform name (architecture).
+Project Types
+^^^^^^^^^^^^^
-For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of this generator name:
-
-``Visual Studio 15 2017 Win64``
- Specify target platform ``x64``.
-
-``Visual Studio 15 2017 ARM``
- Specify target platform ``ARM``.
+Only Visual C++ and C# projects may be generated. Other types of
+projects (JavaScript, Powershell, Python, etc.) are not supported.
Instance Selection
^^^^^^^^^^^^^^^^^^
than one instance is installed we do not define which one is chosen
by default.
+Platform Selection
+^^^^^^^^^^^^^^^^^^
+
+The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+name (architecture). For example:
+
+* ``cmake -G "Visual Studio 15 2017" -A Win32``
+* ``cmake -G "Visual Studio 15 2017" -A x64``
+* ``cmake -G "Visual Studio 15 2017" -A ARM``
+* ``cmake -G "Visual Studio 15 2017" -A ARM64``
+
+For compatibility with CMake versions prior to 3.1, one may specify
+a target platform name optionally at the end of the generator name.
+This is supported only for:
+
+``Visual Studio 15 2017 Win64``
+ Specify target platform ``x64``.
+
+``Visual Studio 15 2017 ARM``
+ Specify target platform ``ARM``.
+
Toolset Selection
^^^^^^^^^^^^^^^^^
Generates Visual Studio 9 2008 project files.
-The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
-to specify a target platform name.
+Platform Selection
+^^^^^^^^^^^^^^^^^^
+
+The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps
+via the :manual:`cmake(1)` ``-A`` option, to specify a target platform
+name (architecture). For example:
+
+* ``cmake -G "Visual Studio 9 2008" -A Win32``
+* ``cmake -G "Visual Studio 9 2008" -A x64``
+* ``cmake -G "Visual Studio 9 2008" -A Itanium``
+* ``cmake -G "Visual Studio 9 2008" -A <WinCE-SDK>``
+ (Specify a target platform matching a Windows CE SDK name.)
For compatibility with CMake versions prior to 3.1, one may specify
-a target platform name optionally at the end of this generator name:
+a target platform name optionally at the end of the generator name.
+This is supported only for:
``Visual Studio 9 2008 Win64``
Specify target platform ``x64``.
/manual/cmake-server.7
/manual/cmake-toolchains.7
/manual/cmake-variables.7
+ /manual/cpack-generators.7
.. only:: html or text
+``-S <path-to-source>``
+ Path to root directory of the CMake project to build.
+
+``-B <path-to-build>``
+ Path to directory which CMake will use as the root of build directory.
+
+ If the directory doesn't already exist CMake will make it.
+
``-C <initial-cache>``
Pre-load a script to populate the cache.
""""""""""""""""
A ``SHARED`` library may be marked with the :prop_tgt:`FRAMEWORK`
-target property to create an OS X or iOS Framework Bundle.
+target property to create an macOS or iOS Framework Bundle.
The ``MACOSX_FRAMEWORK_IDENTIFIER`` sets ``CFBundleIdentifier`` key
and it uniquely identifies the bundle.
with the ``MODULE`` option.
* On non-DLL platforms: the shared library file (e.g. ``.so`` or ``.dylib``)
- of a shared shared library target created by the :command:`add_library`
+ of a shared library target created by the :command:`add_library`
command with the ``SHARED`` option.
The :prop_tgt:`LIBRARY_OUTPUT_DIRECTORY` and :prop_tgt:`LIBRARY_OUTPUT_NAME`
/command/add_dependencies
/command/add_executable
/command/add_library
+ /command/add_link_options
/command/add_subdirectory
/command/add_test
/command/aux_source_directory
/command/target_compile_features
/command/target_compile_options
/command/target_include_directories
+ /command/target_link_directories
/command/target_link_libraries
+ /command/target_link_options
/command/target_sources
/command/try_compile
/command/try_run
Find Modules
------------
-A "find module" is a ``Modules/Find<package>.cmake`` file to be loaded
-by the :command:`find_package` command when invoked for ``<package>``.
+A "find module" is a ``Modules/Find<PackageName>.cmake`` file to be loaded
+by the :command:`find_package` command when invoked for ``<PackageName>``.
The primary task of a find module is to determine whether a package
-exists on the system, set the ``<package>_FOUND`` variable to reflect
+exists on the system, set the ``<PackageName>_FOUND`` variable to reflect
this and provide any variables, macros and imported targets required to
use the package. A find module is useful in cases where an upstream
library does not provide a
/envvar/CTEST_INTERACTIVE_DEBUG_MODE
/envvar/CTEST_OUTPUT_ON_FAILURE
/envvar/CTEST_PARALLEL_LEVEL
+ /envvar/CTEST_PROGRESS_OUTPUT
/envvar/CTEST_USE_LAUNCHERS_DEFAULT
/envvar/DASHBOARD_TEST_FROM_CTEST
``0`` if all ``?`` are ``0``, else ``1``
``$<NOT:?>``
``0`` if ``?`` is ``1``, else ``1``
-``$<IF:?,true-value...,false-value...>```
+``$<IF:?,true-value...,false-value...>``
``true-value...`` if ``?`` is ``1``, ``false-value...`` if ``?`` is ``0``
``$<STREQUAL:a,b>``
``1`` if ``a`` is STREQUAL ``b``, else ``0``
target.
``$<PLATFORM_ID:comp>``
``1`` if the CMake-id of the platform matches ``comp``, otherwise ``0``.
+ See also the :variable:`CMAKE_SYSTEM_NAME` variable.
``$<C_COMPILER_ID:comp>``
``1`` if the CMake-id of the C compiler matches ``comp``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<CXX_COMPILER_ID:comp>``
``1`` if the CMake-id of the CXX compiler matches ``comp``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
``$<VERSION_LESS:v1,v2>``
``1`` if ``v1`` is a version less than ``v2``, else ``0``.
``$<VERSION_GREATER:v1,v2>``
``1`` if ``v1`` is a version greater than or equal to ``v2``, else ``0``.
``$<C_COMPILER_VERSION:ver>``
``1`` if the version of the C compiler matches ``ver``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<CXX_COMPILER_VERSION:ver>``
``1`` if the version of the CXX compiler matches ``ver``, otherwise ``0``.
+ See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
``$<TARGET_POLICY:pol>``
``1`` if the policy ``pol`` was NEW when the 'head' target was created,
else ``0``. If the policy was not set, the warning message for the policy
Literal variable references may consist of alphanumeric characters,
the characters ``/_.+-``, and `Escape Sequences`_. Nested references
-may be used to evaluate variables of any name. (See also policy
-:policy:`CMP0053` documentation for historical considerations.)
+may be used to evaluate variables of any name. See also policy
+:policy:`CMP0053` documentation for historical considerations and reasons why
+the ``$`` is also technically permitted but is discouraged.
The `Variables`_ section documents the scope of variable names
and how their values are set.
An *environment variable reference* has the form ``$ENV{VAR}`` and
is evaluated in the same contexts as a normal variable reference.
+See :variable:`ENV` for more information.
+
+A *cache variable reference* has the form ``$CACHE{VAR}`` and
+is evaluated in the same contexts as a normal variable reference.
+See :variable:`CACHE` for more information.
Comments
--------
is found, or no binding is found, CMake then searches for a
cache entry. If a cache entry is found, its value is used.
Otherwise, the variable reference evaluates to an empty string.
+The ``$CACHE{VAR}`` syntax can be used to do direct cache entry
+lookups.
The :manual:`cmake-variables(7)` manual documents many variables
that are provided by CMake or have meaning to CMake when set
/module/CMakePrintSystemInformation
/module/CMakePushCheckState
/module/CMakeVerifyManifest
- /module/CPackArchive
- /module/CPackBundle
/module/CPackComponent
- /module/CPackCygwin
- /module/CPackDeb
- /module/CPackDMG
- /module/CPackFreeBSD
/module/CPackIFW
/module/CPackIFWConfigureFile
- /module/CPackNSIS
- /module/CPackNuGet
- /module/CPackPackageMaker
- /module/CPackProductBuild
- /module/CPackRPM
/module/CPack
- /module/CPackWIX
/module/CSharpUtilities
/module/CTest
/module/CTestCoverageCollectGCOV
/module/Use_wxWindows
/module/WriteBasicConfigVersionFile
/module/WriteCompilerDetectionHeader
+
+Legacy CPack Modules
+====================
+
+These modules used to be mistakenly exposed to the user, and have been moved
+out of user visibility. They are for CPack internal use, and should never be
+used directly.
+
+.. toctree::
+ :maxdepth: 1
+
+ /module/CPackArchive
+ /module/CPackBundle
+ /module/CPackCygwin
+ /module/CPackDeb
+ /module/CPackDMG
+ /module/CPackFreeBSD
+ /module/CPackNSIS
+ /module/CPackNuGet
+ /module/CPackPackageMaker
+ /module/CPackProductBuild
+ /module/CPackRPM
+ /module/CPackWIX
package.
By setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to
-``TRUE``, the ``PackageName`` package will not be searched, and will always
+``TRUE``, the ``<PackageName>`` package will not be searched, and will always
be ``NOTFOUND``.
.. _`Config File Packages`:
provided to assist downstreams in using the package.
A set of variables which provide package status information are also set
-automatically when using a config-file package. The ``<Package>_FOUND``
+automatically when using a config-file package. The ``<PackageName>_FOUND``
variable is set to true or false, depending on whether the package was
-found. The ``<Package>_DIR`` cache variable is set to the location of the
+found. The ``<PackageName>_DIR`` cache variable is set to the location of the
package configuration file.
Find-module Packages
files by guessing locations of files with platform-specific hints.
Unlike the case of an upstream-provided package configuration file, no single point
-of reference identifies the package as being found, so the ``<Package>_FOUND``
+of reference identifies the package as being found, so the ``<PackageName>_FOUND``
variable is not automatically set by the :command:`find_package` command. It
can still be expected to be set by convention however and should be set by
-the author of the Find-module. Similarly there is no ``<Package>_DIR`` variable,
+the author of the Find-module. Similarly there is no ``<PackageName>_DIR`` variable,
but each of the artifacts such as library locations and header file locations
provide a separate cache variable.
following variables:
``PACKAGE_FIND_NAME``
- The <package> name
+ The ``<PackageName>``
``PACKAGE_FIND_VERSION``
Full requested version string
requested version the find_package command sets the following variables for
use by the project:
-``<package>_VERSION``
+``<PackageName>_VERSION``
Full provided version string
-``<package>_VERSION_MAJOR``
+``<PackageName>_VERSION_MAJOR``
Major version if provided, else 0
-``<package>_VERSION_MINOR``
+``<PackageName>_VERSION_MINOR``
Minor version if provided, else 0
-``<package>_VERSION_PATCH``
+``<PackageName>_VERSION_PATCH``
Patch version if provided, else 0
-``<package>_VERSION_TWEAK``
+``<PackageName>_VERSION_TWEAK``
Tweak version if provided, else 0
-``<package>_VERSION_COUNT``
+``<PackageName>_VERSION_COUNT``
Number of version components, 0 to 4
The variables report the version of the package that was actually found.
-The ``<package>`` part of their name matches the argument given to the
+The ``<PackageName>`` part of their name matches the argument given to the
:command:`find_package` command.
.. _`Creating Packages`:
a simple ``ConfigVersion.cmake`` file. This file sets the version of the
package. It is read by CMake when :command:`find_package` is called to
determine the compatibility with the requested version, and to set some
-version-specific variables ``<Package>_VERSION``, ``<Package>_VERSION_MAJOR``,
-``<Package>_VERSION_MINOR`` etc. The :command:`install(EXPORT)` command is
+version-specific variables ``<PackageName>_VERSION``, ``<PackageName>_VERSION_MAJOR``,
+``<PackageName>_VERSION_MINOR`` etc. The :command:`install(EXPORT)` command is
used to export the targets in the ``ClimbingStatsTargets`` export-set, defined
previously by the :command:`install(TARGETS)` command. This command generates
the ``ClimbingStatsTargets.cmake`` file to contain :prop_tgt:`IMPORTED`
package can not be used without the ``Stats`` package.
If ``COMPONENTS`` are specified when the downstream uses :command:`find_package`,
-they are listed in the ``<Package>_FIND_COMPONENTS`` variable. If a particular
-component is non-optional, then the ``<Package>_FIND_REQUIRED_<comp>`` will
+they are listed in the ``<PackageName>_FIND_COMPONENTS`` variable. If a particular
+component is non-optional, then the ``<PackageName>_FIND_REQUIRED_<comp>`` will
be true. This can be tested with logic in the package configuration file:
.. code-block:: cmake
A project may populate either the user or system registry (using its own
means, see below) to refer to its location.
In either case the package should store at the registered location a
-`Package Configuration File`_ (``<package>Config.cmake``) and optionally a
-`Package Version File`_ (``<package>ConfigVersion.cmake``).
+`Package Configuration File`_ (``<PackageName>Config.cmake``) and optionally a
+`Package Version File`_ (``<PackageName>ConfigVersion.cmake``).
The :command:`find_package` command searches the two package registries
as two of the search steps specified in its documentation. If it has
On Windows the user package registry is stored in the Windows registry
under a key in ``HKEY_CURRENT_USER``.
-A ``<package>`` may appear under registry key::
+A ``<PackageName>`` may appear under registry key::
- HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\<package>
+ HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\<PackageName>
as a ``REG_SZ`` value, with arbitrary name, that specifies the directory
containing the package configuration file.
On UNIX platforms the user package registry is stored in the user home
-directory under ``~/.cmake/packages``. A ``<package>`` may appear under
+directory under ``~/.cmake/packages``. A ``<PackageName>`` may appear under
the directory::
- ~/.cmake/packages/<package>
+ ~/.cmake/packages/<PackageName>
as a file, with arbitrary name, whose content specifies the directory
containing the package configuration file.
Installers must be manually taught to register their packages if desired.
On Windows the system package registry is stored in the Windows registry
-under a key in ``HKEY_LOCAL_MACHINE``. A ``<package>`` may appear under
+under a key in ``HKEY_LOCAL_MACHINE``. A ``<PackageName>`` may appear under
registry key::
- HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\<package>
+ HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\<PackageName>
as a ``REG_SZ`` value, with arbitrary name, that specifies the directory
containing the package configuration file.
to determine whether to report an error on use of deprecated macros or
functions.
+Policies Introduced by CMake 3.13
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0081: Relative paths not allowed in LINK_DIRECTORIES target property. </policy/CMP0081>
+ CMP0080: BundleUtilities cannot be included at configure time. </policy/CMP0080>
+ CMP0079: target_link_libraries allows use with targets in other directories. </policy/CMP0079>
+ CMP0078: UseSWIG generates standard target names. </policy/CMP0078>
+ CMP0077: option() honors normal variables. </policy/CMP0077>
+ CMP0076: target_sources() command converts relative paths to absolute. </policy/CMP0076>
+
Policies Introduced by CMake 3.12
=================================
/prop_dir/INTERPROCEDURAL_OPTIMIZATION
/prop_dir/LABELS
/prop_dir/LINK_DIRECTORIES
+ /prop_dir/LINK_OPTIONS
/prop_dir/LISTFILE_STACK
/prop_dir/MACROS
/prop_dir/PARENT_DIRECTORY
/prop_tgt/DEBUG_POSTFIX
/prop_tgt/DEFINE_SYMBOL
/prop_tgt/DEPLOYMENT_REMOTE_DIRECTORY
+ /prop_tgt/DEPLOYMENT_ADDITIONAL_FILES
/prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION
/prop_tgt/EchoString
/prop_tgt/ENABLE_EXPORTS
/prop_tgt/IMPORTED_LIBNAME_CONFIG
/prop_tgt/IMPORTED_LIBNAME
/prop_tgt/IMPORTED_LINK_DEPENDENT_LIBRARIES_CONFIG
+ /prop_tgt/IMPORTED_LINK_DEPENDENT_LIBRARIES_CONFIG
/prop_tgt/IMPORTED_LINK_DEPENDENT_LIBRARIES
/prop_tgt/IMPORTED_LINK_INTERFACE_LANGUAGES_CONFIG
/prop_tgt/IMPORTED_LINK_INTERFACE_LANGUAGES
/prop_tgt/INTERFACE_COMPILE_FEATURES
/prop_tgt/INTERFACE_COMPILE_OPTIONS
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
+ /prop_tgt/INTERFACE_LINK_DEPENDS
+ /prop_tgt/INTERFACE_LINK_DIRECTORIES
/prop_tgt/INTERFACE_LINK_LIBRARIES
+ /prop_tgt/INTERFACE_LINK_OPTIONS
/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE
/prop_tgt/INTERFACE_SOURCES
/prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
/prop_tgt/LINK_DEPENDS_NO_SHARED
/prop_tgt/LINK_DEPENDS
/prop_tgt/LINKER_LANGUAGE
+ /prop_tgt/LINK_DIRECTORIES
/prop_tgt/LINK_FLAGS_CONFIG
/prop_tgt/LINK_FLAGS
/prop_tgt/LINK_INTERFACE_LIBRARIES_CONFIG
/prop_tgt/LINK_INTERFACE_MULTIPLICITY_CONFIG
/prop_tgt/LINK_INTERFACE_MULTIPLICITY
/prop_tgt/LINK_LIBRARIES
+ /prop_tgt/LINK_OPTIONS
/prop_tgt/LINK_SEARCH_END_STATIC
/prop_tgt/LINK_SEARCH_START_STATIC
/prop_tgt/LINK_WHAT_YOU_USE
/prop_tgt/SOVERSION
/prop_tgt/STATIC_LIBRARY_FLAGS_CONFIG
/prop_tgt/STATIC_LIBRARY_FLAGS
+ /prop_tgt/STATIC_LIBRARY_OPTIONS
/prop_tgt/SUFFIX
/prop_tgt/TYPE
/prop_tgt/VERSION
/prop_tgt/VISIBILITY_INLINES_HIDDEN
/prop_tgt/VS_CONFIGURATION_TYPE
- /prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY
/prop_tgt/VS_DEBUGGER_COMMAND
+ /prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS
+ /prop_tgt/VS_DEBUGGER_ENVIRONMENT
+ /prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY
/prop_tgt/VS_DESKTOP_EXTENSIONS_VERSION
/prop_tgt/VS_DOTNET_REFERENCE_refname
/prop_tgt/VS_DOTNET_REFERENCEPROP_refname_TAG_tagname
/prop_tgt/XCODE_ATTRIBUTE_an-attribute
/prop_tgt/XCODE_EXPLICIT_FILE_TYPE
/prop_tgt/XCODE_PRODUCT_TYPE
+ /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER
+ /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+ /prop_tgt/XCODE_SCHEME_THREAD_SANITIZER
+ /prop_tgt/XCODE_SCHEME_THREAD_SANITIZER_STOP
+ /prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+ /prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ /prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+ /prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+ /prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE
+ /prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES
+ /prop_tgt/XCODE_SCHEME_GUARD_MALLOC
+ /prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS
+ /prop_tgt/XCODE_SCHEME_MALLOC_STACK
+ /prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ /prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
+ /prop_tgt/XCODE_SCHEME_EXECUTABLE
+ /prop_tgt/XCODE_SCHEME_ARGUMENTS
+ /prop_tgt/XCODE_SCHEME_ENVIRONMENT
/prop_tgt/XCTEST
.. _`Test Properties`:
/variable/CMAKE_CACHE_PATCH_VERSION
/variable/CMAKE_CFG_INTDIR
/variable/CMAKE_COMMAND
+ /variable/CMAKE_CPACK_COMMAND
/variable/CMAKE_CROSSCOMPILING
/variable/CMAKE_CROSSCOMPILING_EMULATOR
/variable/CMAKE_CTEST_COMMAND
/variable/CMAKE_PROJECT_VERSION_TWEAK
/variable/CMAKE_RANLIB
/variable/CMAKE_ROOT
+ /variable/CMAKE_RULE_MESSAGES
/variable/CMAKE_SCRIPT_MODE_FILE
/variable/CMAKE_SHARED_LIBRARY_PREFIX
/variable/CMAKE_SHARED_LIBRARY_SUFFIX
/variable/CMAKE_INSTALL_PREFIX
/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
/variable/CMAKE_LIBRARY_PATH
+ /variable/CMAKE_LINK_DIRECTORIES_BEFORE
/variable/CMAKE_MFC_FLAG
/variable/CMAKE_MODULE_PATH
/variable/CMAKE_NOT_USING_CONFIG_FLAGS
/variable/CMAKE_WARN_DEPRECATED
/variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
/variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY
+ /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER
+ /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+ /variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER
+ /variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP
+ /variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+ /variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ /variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+ /variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+ /variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
+ /variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
+ /variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC
+ /variable/CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
+ /variable/CMAKE_XCODE_SCHEME_MALLOC_STACK
+ /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
/variable/PackageName_ROOT
Variables that Describe the System
/variable/ANDROID
/variable/APPLE
/variable/BORLAND
+ /variable/CACHE
/variable/CMAKE_CL_64
/variable/CMAKE_COMPILER_2005
/variable/CMAKE_HOST_APPLE
/variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY
/variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG
/variable/CMAKE_AUTOGEN_PARALLEL
+ /variable/CMAKE_AUTOGEN_VERBOSE
/variable/CMAKE_AUTOMOC
/variable/CMAKE_AUTOMOC_COMPILER_PREDEFINES
/variable/CMAKE_AUTOMOC_DEPEND_FILTERS
/variable/CMAKE_TRY_COMPILE_TARGET_TYPE
/variable/CMAKE_USE_RELATIVE_PATHS
/variable/CMAKE_VISIBILITY_INLINES_HIDDEN
+ /variable/CMAKE_VS_GLOBALS
/variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
/variable/CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD
/variable/CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
/variable/CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES
/variable/CMAKE_VS_SDK_REFERENCE_DIRECTORIES
/variable/CMAKE_VS_SDK_SOURCE_DIRECTORIES
+ /variable/CMAKE_VS_WINRT_BY_DEFAULT
/variable/CMAKE_WIN32_EXECUTABLE
/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute
/variable/CMAKE_LANG_LIBRARY_ARCHITECTURE
/variable/CMAKE_LANG_LINKER_PREFERENCE
/variable/CMAKE_LANG_LINKER_PREFERENCE_PROPAGATES
+ /variable/CMAKE_LANG_LINKER_WRAPPER_FLAG
+ /variable/CMAKE_LANG_LINKER_WRAPPER_FLAG_SEP
/variable/CMAKE_LANG_LINK_EXECUTABLE
/variable/CMAKE_LANG_OUTPUT_EXTENSION
/variable/CMAKE_LANG_PLATFORM_ID
.. parsed-literal::
cmake [<options>] {<path-to-source> | <path-to-existing-build>}
+ cmake [<options>] -S <path-to-source> -B <path-to-build>
cmake [{-D <var>=<value>}...] -P <cmake-script-file>
cmake --build <dir> [<options>...] [-- <build-tool-options>...]
cmake --open <dir>
Touch a file if it exists but do not create it. If a file does
not exist it will be silently ignored.
-UNIX-specific Command-Line Tools
---------------------------------
-
-The following ``cmake -E`` commands are available only on UNIX:
-
``create_symlink <old> <new>``
Create a symbolic link ``<new>`` naming ``<old>``.
--- /dev/null
+.. cmake-manual-description: CPack Generator Reference
+
+cpack-generators(7)
+*******************
+
+.. only:: html
+
+ .. contents::
+
+Generators
+==========
+
+.. toctree::
+ :maxdepth: 1
+
+ /cpack_gen/archive
+ /cpack_gen/bundle
+ /cpack_gen/cygwin
+ /cpack_gen/deb
+ /cpack_gen/dmg
+ /cpack_gen/external
+ /cpack_gen/freebsd
+ /cpack_gen/ifw
+ /cpack_gen/nsis
+ /cpack_gen/nuget
+ /cpack_gen/packagemaker
+ /cpack_gen/productbuild
+ /cpack_gen/rpm
+ /cpack_gen/wix
package(s) in that generator's format according to the details provided in
the ``CPackConfig.cmake`` configuration file. A generator is responsible for
generating the required inputs for a particular package system and invoking
- that system's package creation tools. Possible generator names are specified
- in the :manual:`Generators <cmake-generators(7)>` section of the manual and
+ that system's package creation tools. All supported generators are specified
+ in the :manual:`Generators <cpack-generators(7)>` section of the manual and
the ``--help`` option lists the generators supported for the target platform.
+
If this option is not given, the :variable:`CPACK_GENERATOR` variable
determines the default set of generators that will be used.
which one should be tested. Example configurations are "Debug" and
"Release".
+``--progress``
+ Enable short progress output from tests.
+
+ When the output of ``ctest`` is being sent directly to a terminal, the
+ progress through the set of tests is reported by updating the same line
+ rather than printing start and end messages for each test on new lines.
+ This can significantly reduce the verbosity of the test output.
+ Test completion messages are still output on their own line for failed
+ tests and the final test summary will also still be logged.
+
+ This option can also be enabled by setting the environment variable
+ :envvar:`CTEST_PROGRESS_OUTPUT`.
+
``-V,--verbose``
Enable verbose output from tests.
``--output-on-failure``
Output anything outputted by the test program if the test should fail.
- This option can also be enabled by setting the environment variable
- ``CTEST_OUTPUT_ON_FAILURE``.
+ This option can also be enabled by setting the
+ :envvar:`CTEST_OUTPUT_ON_FAILURE` environment variable
``-F``
Enable failover.
This option tells CTest to run the tests in parallel using given
number of jobs. This option can also be set by setting the
- environment variable ``CTEST_PARALLEL_LEVEL``.
+ :envvar:`CTEST_PARALLEL_LEVEL` environment variable.
This option can be used with the :prop_test:`PROCESSORS` test property.
* `CTest Script`_ variable: :variable:`CTEST_CONFIGURATION_TYPE`
* :module:`CTest` module variable: ``DEFAULT_CTEST_CONFIGURATION_TYPE``,
- initialized by the ``CMAKE_CONFIG_TYPE`` environment variable
+ initialized by the :envvar:`CMAKE_CONFIG_TYPE` environment variable
``LabelsForSubprojects``
Specify a semicolon-separated list of labels that will be treated as
-.. cmake-module:: ../../Modules/CPackArchive.cmake
+CPackArchive
+------------
+
+The documentation for the CPack Archive generator has moved here: :cpack_gen:`CPack Archive Generator`
-.. cmake-module:: ../../Modules/CPackBundle.cmake
+CPackBundle
+-----------
+
+The documentation for the CPack Bundle generator has moved here: :cpack_gen:`CPack Bundle Generator`
-.. cmake-module:: ../../Modules/CPackCygwin.cmake
+CPackCygwin
+-----------
+
+The documentation for the CPack Cygwin generator has moved here: :cpack_gen:`CPack Cygwin Generator`
-.. cmake-module:: ../../Modules/CPackDMG.cmake
+CPackDMG
+--------
+
+The documentation for the CPack DragNDrop generator has moved here: :cpack_gen:`CPack DragNDrop Generator`
-.. cmake-module:: ../../Modules/CPackDeb.cmake
+CPackDeb
+--------
+
+The documentation for the CPack DEB generator has moved here: :cpack_gen:`CPack DEB Generator`
-.. cmake-module:: ../../Modules/CPackFreeBSD.cmake
+CPackFreeBSD
+------------
+
+The documentation for the CPack FreeBSD generator has moved here: :cpack_gen:`CPack FreeBSD Generator`
-.. cmake-module:: ../../Modules/CPackNSIS.cmake
+CPackNSIS
+---------
+
+The documentation for the CPack NSIS generator has moved here: :cpack_gen:`CPack NSIS Generator`
-.. cmake-module:: ../../Modules/CPackNuGet.cmake
+CPackNuGet
+----------
+
+The documentation for the CPack NuGet generator has moved here: :cpack_gen:`CPack NuGet Generator`
-.. cmake-module:: ../../Modules/CPackPackageMaker.cmake
+CPackPackageMaker
+-----------------
+
+The documentation for the CPack PackageMaker generator has moved here: :cpack_gen:`CPack PackageMaker Generator`
-.. cmake-module:: ../../Modules/CPackProductBuild.cmake
+CPackProductBuild
+-----------------
+
+The documentation for the CPack productbuild generator has moved here: :cpack_gen:`CPack productbuild Generator`
-.. cmake-module:: ../../Modules/CPackRPM.cmake
+CPackRPM
+--------
+
+The documentation for the CPack RPM generator has moved here: :cpack_gen:`CPack RPM Generator`
-.. cmake-module:: ../../Modules/CPackWIX.cmake
+CPackWIX
+--------
+
+The documentation for the CPack WIX generator has moved here: :cpack_gen:`CPack WIX Generator`
* Literal ``${VAR}`` reference syntax may contain only
alphanumeric characters (``A-Z``, ``a-z``, ``0-9``) and
the characters ``_``, ``.``, ``/``, ``-``, and ``+``.
+ Note that ``$`` is technically allowed in the ``NEW`` behavior, but is
+ invalid for ``OLD`` behavior. This is due to an oversight during the
+ implementation of :policy:`CMP0053` and its use as a literal variable
+ reference is discouraged for this reason.
Variables with other characters in their name may still
be referenced indirectly, e.g.
--- /dev/null
+CMP0076
+-------
+
+The :command:`target_sources` command converts relative paths to absolute.
+
+In CMake 3.13 and above, the :command:`target_sources` command now converts
+relative source file paths to absolute paths in the following cases:
+
+* Source files are added to the target's :prop_tgt:`INTERFACE_SOURCES`
+ property.
+* The target's :prop_tgt:`SOURCE_DIR` property differs from
+ :variable:`CMAKE_CURRENT_SOURCE_DIR`.
+
+A path that begins with a generator expression is always left unmodified.
+
+This policy provides compatibility with projects that have not been updated
+to expect this behavior. The ``OLD`` behavior for this policy is to leave
+all relative source file paths unmodified. The ``NEW`` behavior of this
+policy is to convert relative paths to absolute according to above rules.
+
+This policy was introduced in CMake version 3.13. 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
--- /dev/null
+CMP0077
+-------
+
+:command:`option` honors normal variables.
+
+The :command:`option` command is typically used to create a cache entry
+to allow users to set the option. However, there are cases in which a
+normal (non-cached) variable of the same name as the option may be
+defined by the project prior to calling the :command:`option` command.
+For example, a project that embeds another project as a subdirectory
+may want to hard-code options of the subproject to build the way it needs.
+
+For historical reasons in CMake 3.12 and below the :command:`option`
+command *removes* a normal (non-cached) variable of the same name when:
+
+* a cache entry of the specified name does not exist at all, or
+* a cache entry of the specified name exists but has not been given
+ a type (e.g. via ``-D<name>=ON`` on the command line).
+
+In both of these cases (typically on the first run in a new build tree),
+the :command:`option` command gives the cache entry type ``BOOL`` and
+removes any normal (non-cached) variable of the same name. In the
+remaining case that the cache entry of the specified name already
+exists and has a type (typically on later runs in a build tree), the
+:command:`option` command changes nothing and any normal variable of
+the same name remains set.
+
+In CMake 3.13 and above the :command:`option` command prefers to
+do nothing when a normal variable of the given name already exists.
+It does not create or update a cache entry or remove the normal variable.
+The new behavior is consistent between the first and later runs in a
+build tree. This policy provides compatibility with projects that have
+not been updated to expect the new behavior.
+
+When the :command:`option` command sees a normal variable of the given
+name:
+
+* The ``OLD`` behavior for this policy is to proceed even when a normal
+ variable of the same name exists. If the cache entry does not already
+ exist and have a type then it is created and/or given a type and the
+ normal variable is removed.
+
+* The ``NEW`` behavior for this policy is to do nothing when a normal
+ variable of the same name exists. The normal variable is not removed.
+ The cache entry is not created or updated and is ignored if it exists.
+
+This policy was introduced in CMake version 3.13. 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
--- /dev/null
+CMP0078
+-------
+
+Starting with CMake 3.13, :module:`UseSWIG` generates now standard target
+names. This policy provides compatibility with projects that expect the legacy
+behavior.
+
+The ``OLD`` behavior for this policy relies on
+``UseSWIG_TARGET_NAME_PREFERENCE`` variable that can be used to specify an
+explicit preference. The value may be one of:
+
+* ``LEGACY``: legacy strategy is applied. Variable
+ ``SWIG_MODULE_<name>_REAL_NAME`` must be used to get real target name.
+ This is the default if not specified.
+* ``STANDARD``: target name matches specified name.
+
+This policy was introduced in CMake version 3.13. 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
--- /dev/null
+CMP0079
+-------
+
+:command:`target_link_libraries` allows use with targets in other directories.
+
+Prior to CMake 3.13 the :command:`target_link_libraries` command did not
+accept targets not created in the calling directory as its first argument
+for calls that update the :prop_tgt:`LINK_LIBRARIES` of the target itself.
+It did accidentally accept targets from other directories on calls that
+only update the :prop_tgt:`INTERFACE_LINK_LIBRARIES`, but would simply
+add entries to the property as if the call were made in the original
+directory. Thus link interface libraries specified this way were always
+looked up by generators in the scope of the original target rather than
+in the scope that called :command:`target_link_libraries`.
+
+CMake 3.13 now allows the :command:`target_link_libraries` command to
+be called from any directory to add link dependencies and link interface
+libraries to targets created in other directories. The entries are added
+to :prop_tgt:`LINK_LIBRARIES` and :prop_tgt:`INTERFACE_LINK_LIBRARIES`
+using a special (internal) suffix to tell the generators to look up the
+names in the calling scope rather than the scope that created the target.
+
+This policy provides compatibility with projects that already use
+:command:`target_link_libraries` with the ``INTERFACE`` keyword
+on a target in another directory to add :prop_tgt:`INTERFACE_LINK_LIBRARIES`
+entries to be looked up in the target's directory. Such projects should
+be updated to be aware of the new scoping rules in that case.
+
+The ``OLD`` behavior of this policy is to disallow
+:command:`target_link_libraries` calls naming targets from another directory
+except in the previously accidentally allowed case of using the ``INTERFACE``
+keyword only. The ``NEW`` behavior of this policy is to allow all such
+calls but use the new scoping rules.
+
+This policy was introduced in CMake version 3.13. 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
--- /dev/null
+CMP0080
+-------
+
+:module:`BundleUtilities` cannot be included at configure time.
+
+The macros provided by :module:`BundleUtilities` are intended to be invoked
+at install time rather than at configure time, because they depend on the
+listed targets already existing at the time they are invoked. If they are
+invoked at configure time, the targets haven't been built yet, and the
+commands will fail.
+
+This policy restricts the inclusion of :module:`BundleUtilities` to
+``cmake -P`` style scripts and install rules. Specifically, it looks for the
+presence of :variable:`CMAKE_GENERATOR` and throws a fatal error if it exists.
+
+The ``OLD`` behavior of this policy is to allow :module:`BundleUtilities` to
+be included at configure time. The ``NEW`` behavior of this policy is to
+disallow such inclusion.
+
+This policy was introduced in CMake version 3.13. 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
--- /dev/null
+CMP0081
+-------
+
+Relative paths not allowed in :prop_tgt:`LINK_DIRECTORIES` target property.
+
+CMake 3.12 and lower allowed the :prop_dir:`LINK_DIRECTORIES` directory
+property to contain relative paths. The base path for such relative
+entries is not well defined. CMake 3.13 and later will issue a
+``FATAL_ERROR`` if the :prop_tgt:`LINK_DIRECTORIES` target property
+(which is initialized by the :prop_dir:`LINK_DIRECTORIES` directory property)
+contains a relative path.
+
+The ``OLD`` behavior for this policy is not to warn about relative paths
+in the :prop_tgt:`LINK_DIRECTORIES` target property. The ``NEW`` behavior for
+this policy is to issue a ``FATAL_ERROR`` if :prop_tgt:`LINK_DIRECTORIES`
+contains a relative path.
+
+This policy was introduced in CMake version 3.13. 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
directories for the compiler.
In addition to accepting values from that command, values may be set
-directly on any directory using the :command:`set_property` command. A
-directory gets its initial value from its parent directory if it has one.
-The initial value of the :prop_tgt:`INCLUDE_DIRECTORIES` target property
+directly on any directory using the :command:`set_property` command, and can be
+set on the current directory using the :command:`set_directory_properties`
+command. A directory gets its initial value from its parent directory if it has
+one. The initial value of the :prop_tgt:`INCLUDE_DIRECTORIES` target property
comes from the value of this property. Both directory and target property
values are adjusted by calls to the :command:`include_directories` command.
+Calls to :command:`set_property` or :command:`set_directory_properties`,
+however, will update the directory property value without updating target
+property values. Therefore direct property updates must be made before
+calls to :command:`add_executable` or :command:`add_library` for targets
+they are meant to affect.
The target property values are used by the generators to set the
include paths for the compiler.
List of linker search directories.
-This read-only property specifies the list of directories given so far
-to the link_directories command. It is intended for debugging
-purposes.
+This property holds a :ref:`;-list <CMake Language Lists>` of directories
+and is typically populated using the :command:`link_directories` command.
+It gets its initial value from its parent directory, if it has one.
+
+The directory property is used to initialize the :prop_tgt:`LINK_DIRECTORIES`
+target property when a target is created. That target property is used
+by the generators to set the library search directories for the linker.
+
+Contents of ``LINK_DIRECTORIES`` may use "generator expressions" with
+the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+manual for more on defining buildsystem properties.
--- /dev/null
+LINK_OPTIONS
+------------
+
+List of options to use for the link step of shared library, module
+and executable targets.
+
+This property holds a :ref:`;-list <CMake Language Lists>` of options
+given so far to the :command:`add_link_options` command.
+
+This property is used to initialize the :prop_tgt:`LINK_OPTIONS` target
+property when a target is created, which is used by the generators to set
+the options for the compiler.
+
+Contents of ``LINK_OPTIONS`` may use "generator expressions" with the
+syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
+for available expressions. See the :manual:`cmake-buildsystem(7)` manual
+for more on defining buildsystem properties.
property is not set the default is ON. Set the property to OFF to
disable granular messages and report only as each target completes.
This is intended to allow scripted builds to avoid the build time cost
-of detailed reports. If a ``CMAKE_RULE_MESSAGES`` cache entry exists
+of detailed reports. If a :variable:`CMAKE_RULE_MESSAGES` cache entry exists
its value initializes the value of this property. Non-Makefile
generators currently ignore this property.
Place a source file inside a Application Bundle
(:prop_tgt:`MACOSX_BUNDLE`), Core Foundation Bundle (:prop_tgt:`BUNDLE`),
-or Framework Bundle (:prop_tgt:`FRAMEWORK`). It is applicable for OS X
+or Framework Bundle (:prop_tgt:`FRAMEWORK`). It is applicable for macOS
and iOS.
Executable targets with the :prop_tgt:`MACOSX_BUNDLE` property set are
-built as OS X or iOS application bundles on Apple platforms. Shared
+built as macOS or iOS application bundles on Apple platforms. Shared
library targets with the :prop_tgt:`FRAMEWORK` property set are built as
-OS X or iOS frameworks on Apple platforms. Module library targets with
-the :prop_tgt:`BUNDLE` property set are built as OS X ``CFBundle`` bundles
+macOS or iOS frameworks on Apple platforms. Module library targets with
+the :prop_tgt:`BUNDLE` property set are built as macOS ``CFBundle`` bundles
on Apple platforms. Source files listed in the target with this property
set will be copied to a directory inside the bundle or framework content
-folder specified by the property value. For OS X Application Bundles the
-content folder is ``<name>.app/Contents``. For OS X Frameworks the
-content folder is ``<name>.framework/Versions/<version>``. For OS X
+folder specified by the property value. For macOS Application Bundles the
+content folder is ``<name>.app/Contents``. For macOS Frameworks the
+content folder is ``<name>.framework/Versions/<version>``. For macOS
CFBundles the content folder is ``<name>.bundle/Contents`` (unless the
extension is changed). See the :prop_tgt:`PUBLIC_HEADER`,
:prop_tgt:`PRIVATE_HEADER`, and :prop_tgt:`RESOURCE` target properties for
BUNDLE
------
-This target is a ``CFBundle`` on the OS X.
+This target is a ``CFBundle`` on the macOS.
If a module library target has this property set to true it will be
built as a ``CFBundle`` when built on the mac. It will have the directory
----------------
The file extension used to name a :prop_tgt:`BUNDLE`, a :prop_tgt:`FRAMEWORK`,
-or a :prop_tgt:`MACOSX_BUNDLE` target on the OS X and iOS.
+or a :prop_tgt:`MACOSX_BUNDLE` target on the macOS and iOS.
The default value is ``bundle``, ``framework``, or ``app`` for the respective
target types.
--- /dev/null
+DEPLOYMENT_ADDITIONAL_FILES
+---------------------------
+
+Set the WinCE project ``AdditionalFiles`` in ``DeploymentTool`` in ``.vcproj``
+files generated by the :generator:`Visual Studio 9 2008` generator.
+This is useful when you want to debug on remote WinCE device.
+Specify additional files that will be copied to the device.
+For example:
+
+.. code-block:: cmake
+
+ set_property(TARGET ${TARGET} PROPERTY
+ DEPLOYMENT_ADDITIONAL_FILES "english.lng|local_folder|remote_folder|0"
+ "german.lng|local_folder|remote_folder|0")
+
+produces::
+
+ <DeploymentTool AdditionalFiles="english.lng|local_folder|remote_folder|0;german.lng|local_folder|remote_folder|0" ... />
For DLL platforms an import library will be created for the exported
symbols and then used for linking. All Windows-based systems
including Cygwin are DLL platforms. For non-DLL platforms that
-require all symbols to be resolved at link time, such as OS X, the
+require all symbols to be resolved at link time, such as macOS, the
module will "link" to the executable using a flag like
``-bundle_loader``. For other non-DLL platforms the link rule is simply
ignored since the dynamic loader will automatically bind symbols when
FRAMEWORK
---------
-Build ``SHARED`` or ``STATIC`` library as Framework Bundle on the OS X and iOS.
+Build ``SHARED`` or ``STATIC`` library as Framework Bundle on the macOS and iOS.
If such a library target has this property set to ``TRUE`` it will be
-built as a framework when built on the OS X and iOS. It will have the
+built as a framework when built on the macOS and iOS. It will have the
directory structure required for a framework and will be suitable to
be used with the ``-framework`` option
To customize ``Info.plist`` file in the framework, use
:prop_tgt:`MACOSX_FRAMEWORK_INFO_PLIST` target property.
-For OS X see also the :prop_tgt:`FRAMEWORK_VERSION` target property.
+For macOS see also the :prop_tgt:`FRAMEWORK_VERSION` target property.
Example of creation ``dynamicFramework``:
Version of a framework created using the :prop_tgt:`FRAMEWORK` target
property (e.g. ``A``).
-This property only affects OS X, as iOS doesn't have versioned
+This property only affects macOS, as iOS doesn't have versioned
directory structure.
Set this to the location of an IMPORTED target file on disk. For
executables this is the location of the executable file. For bundles
-on OS X this is the location of the executable file inside
+on macOS this is the location of the executable file inside
Contents/MacOS under the application bundle folder. For static
libraries and modules this is the location of the library or module.
For shared libraries on non-DLL platforms this is the location of the
-shared library. For frameworks on OS X this is the location of the
+shared library. For frameworks on macOS this is the location of the
library file symlink just inside the framework folder. For DLLs this
is the location of the ".dll" part of the library. For UNKNOWN
libraries this is the location of the file to be linked. Ignored for
--- /dev/null
+INTERFACE_LINK_DEPENDS
+----------------------
+
+Additional public interface files on which a target binary depends for linking.
+
+This property is supported only by Makefile and Ninja generators. It is
+intended to specify dependencies on "linker scripts" for custom Makefile link
+rules.
+
+When target dependencies are specified using :command:`target_link_libraries`,
+CMake will read this property from all target dependencies to determine the
+build properties of the consumer.
+
+Contents of ``INTERFACE_LINK_DEPENDS`` may use "generator expressions"
+with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+-manual for more on defining buildsystem properties.
+
+Link dependency files usage requirements commonly differ between the build-tree
+and the install-tree. The ``BUILD_INTERFACE`` and ``INSTALL_INTERFACE``
+generator expressions can be used to describe separate usage requirements
+based on the usage location. Relative paths are allowed within the
+``INSTALL_INTERFACE`` expression and are interpreted relative to the
+installation prefix. For example:
+
+.. code-block:: cmake
+
+ set_property(TARGET mylib PROPERTY INTERFACE_LINK_DEPENDS
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/mylinkscript>
+ $<INSTALL_INTERFACE:mylinkscript> # <prefix>/mylinkscript
+ )
--- /dev/null
+INTERFACE_LINK_DIRECTORIES
+--------------------------
+
+.. |property_name| replace:: link directories
+.. |command_name| replace:: :command:`target_link_directories`
+.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_LINK_DIRECTORIES``
+.. |PROPERTY_LINK| replace:: :prop_tgt:`LINK_DIRECTORIES`
+.. |PROPERTY_GENEX| replace:: ``$<TARGET_PROPERTY:foo,INTERFACE_LINK_DIRECTORIES>``
+.. include:: INTERFACE_BUILD_PROPERTY.txt
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
+.. include:: LINK_LIBRARIES_INDIRECTION.txt
+
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--- /dev/null
+INTERFACE_LINK_OPTIONS
+----------------------
+
+.. |property_name| replace:: link options
+.. |command_name| replace:: :command:`target_link_options`
+.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_LINK_OPTIONS``
+.. |PROPERTY_LINK| replace:: :prop_tgt:`LINK_OPTIONS`
+.. |PROPERTY_GENEX| replace:: ``$<TARGET_PROPERTY:foo,INTERFACE_LINK_OPTIONS>``
+.. include:: INTERFACE_BUILD_PROPERTY.txt
the link rule for this target depends. The target binary will be
linked if any of the named files is newer than it.
-This property is ignored by non-Makefile generators. It is intended
-to specify dependencies on "linker scripts" for custom Makefile link
+This property is supported only by Makefile and Ninja generators. It is
+intended to specify dependencies on "linker scripts" for custom Makefile link
rules.
+
+Contents of ``LINK_DEPENDS`` may use "generator expressions" with
+the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
+manual for available expressions. See the :manual:`cmake-buildsystem(7)`
+manual for more on defining buildsystem properties.
--- /dev/null
+LINK_DIRECTORIES
+----------------
+
+List of directories to use for the link step of shared library, module
+and executable targets.
+
+This property holds a :ref:`;-list <CMake Language Lists>` of directories
+specified so far for its target. Use the :command:`target_link_directories`
+command to append more search directories.
+
+This property is initialized by the :prop_dir:`LINK_DIRECTORIES` directory
+property when a target is created, and is used by the generators to set
+the search directories for the linker.
+
+Contents of ``LINK_DIRECTORIES`` may use "generator expressions" with the
+syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
+for available expressions. See the :manual:`cmake-buildsystem(7)` manual
+for more on defining buildsystem properties.
LINK_FLAGS
----------
-Additional flags to use when linking this target.
+Additional flags to use when linking this target if it is a shared library,
+module library, or an executable. Static libraries need to use
+:prop_tgt:`STATIC_LIBRARY_OPTIONS` or :prop_tgt:`STATIC_LIBRARY_FLAGS`
+properties.
-The LINK_FLAGS property can be used to add extra flags to the link
-step of a target. :prop_tgt:`LINK_FLAGS_<CONFIG>` will add to the
-configuration ``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``,
+The ``LINK_FLAGS`` property, managed as a string, can be used to add extra
+flags to the link step of a target. :prop_tgt:`LINK_FLAGS_<CONFIG>` will add
+to the configuration ``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``,
``MINSIZEREL``, ``RELWITHDEBINFO``, ...
+
+.. note::
+
+ This property has been superseded by :prop_tgt:`LINK_OPTIONS` property.
LINK_FLAGS_<CONFIG>
-------------------
-Per-configuration linker flags for a target.
+Per-configuration linker flags for a shared library, module or executable
+target.
-This is the configuration-specific version of LINK_FLAGS.
+This is the configuration-specific version of :prop_tgt:`LINK_FLAGS`.
+
+.. note::
+
+ This property has been superseded by :prop_tgt:`LINK_OPTIONS` property.
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
for available expressions. See the :manual:`cmake-buildsystem(7)` manual
for more on defining buildsystem properties.
+
+.. include:: LINK_LIBRARIES_INDIRECTION.txt
--- /dev/null
+.. note::
+ A call to :command:`target_link_libraries(<target> ...)` may update this
+ property on ``<target>``. If ``<target>`` was not created in the same
+ directory as the call then :command:`target_link_libraries` will add a
+ suffix of the form ``::@<directory-id>`` to each entry, where the
+ ``::@`` is a separator and the ``<directory-id>`` is unspecified.
+ This tells the generators that the named libraries must be looked up in
+ the scope of the caller rather than in the scope in which the
+ ``<target>`` was created. Valid directory ids are stripped on export
+ by the :command:`install(EXPORT)` and :command:`export` commands.
--- /dev/null
+LINK_OPTIONS
+------------
+
+List of options to use for the link step of shared library, module
+and executable targets. Targets that are static libraries need to use
+the :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property.
+
+
+This property holds a :ref:`;-list <CMake Language Lists>` of options
+specified so far for its target. Use the :command:`target_link_options`
+command to append more options.
+
+This property is initialized by the :prop_dir:`LINK_OPTIONS` directory
+property when a target is created, and is used by the generators to set
+the options for the compiler.
+
+Contents of ``LINK_OPTIONS`` may use "generator expressions" with the
+syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
+for available expressions. See the :manual:`cmake-buildsystem(7)` manual
+for more on defining buildsystem properties.
+
+.. note::
+
+ This property must be used in preference to :prop_tgt:`LINK_FLAGS` property.
MACOSX_BUNDLE
-------------
-Build an executable as an Application Bundle on OS X or iOS.
+Build an executable as an Application Bundle on macOS or iOS.
-When this property is set to ``TRUE`` the executable when built on OS X
+When this property is set to ``TRUE`` the executable when built on macOS
or iOS will be created as an application bundle. This makes it
a GUI executable that can be launched from the Finder. See the
:prop_tgt:`MACOSX_BUNDLE_INFO_PLIST` target property for information about
MACOSX_BUNDLE_INFO_PLIST
------------------------
-Specify a custom ``Info.plist`` template for a OS X and iOS Application Bundle.
+Specify a custom ``Info.plist`` template for a macOS and iOS Application Bundle.
An executable target with :prop_tgt:`MACOSX_BUNDLE` enabled will be built as an
-application bundle on OS X. By default its ``Info.plist`` file is created
+application bundle on macOS. By default its ``Info.plist`` file is created
by configuring a template called ``MacOSXBundleInfo.plist.in`` located in the
:variable:`CMAKE_MODULE_PATH`. This property specifies an alternative template
file name which may be a full path.
MACOSX_FRAMEWORK_INFO_PLIST
---------------------------
-Specify a custom ``Info.plist`` template for a OS X and iOS Framework.
+Specify a custom ``Info.plist`` template for a macOS and iOS Framework.
A library target with :prop_tgt:`FRAMEWORK` enabled will be built as a
-framework on OS X. By default its ``Info.plist`` file is created by
+framework on macOS. By default its ``Info.plist`` file is created by
configuring a template called ``MacOSXFrameworkInfo.plist.in`` located in the
:variable:`CMAKE_MODULE_PATH`. This property specifies an alternative template
file name which may be a full path.
MACOSX_RPATH
------------
-Whether this target on OS X or iOS is located at runtime using rpaths.
+Whether this target on macOS or iOS is located at runtime using rpaths.
When this property is set to ``TRUE``, the directory portion of
the ``install_name`` field of this shared library will be ``@rpath``
OSX_ARCHITECTURES
-----------------
-Target specific architectures for OS X.
+Target specific architectures for macOS.
The ``OSX_ARCHITECTURES`` property sets the target binary architecture for
-targets on OS X (``-arch``). This property is initialized by the value of the
+targets on macOS (``-arch``). This property is initialized by the value of the
variable :variable:`CMAKE_OSX_ARCHITECTURES` if it is set when a target is
created. Use :prop_tgt:`OSX_ARCHITECTURES_<CONFIG>` to set the binary
architectures on a per-configuration basis, where ``<CONFIG>`` is an
OSX_ARCHITECTURES_<CONFIG>
--------------------------
-Per-configuration OS X and iOS binary architectures for a target.
+Per-configuration macOS and iOS binary architectures for a target.
This property is the configuration-specific version of
:prop_tgt:`OSX_ARCHITECTURES`.
Specify private header files in a :prop_tgt:`FRAMEWORK` shared library target.
Shared library targets marked with the :prop_tgt:`FRAMEWORK` property generate
-frameworks on OS X, iOS and normal shared libraries on other platforms.
+frameworks on macOS, iOS and normal shared libraries on other platforms.
This property may be set to a list of header files to be placed in the
PrivateHeaders directory inside the framework folder. On non-Apple
platforms these headers may be installed using the ``PRIVATE_HEADER``
Specify public header files in a :prop_tgt:`FRAMEWORK` shared library target.
Shared library targets marked with the :prop_tgt:`FRAMEWORK` property generate
-frameworks on OS X, iOS and normal shared libraries on other platforms.
+frameworks on macOS, iOS and normal shared libraries on other platforms.
This property may be set to a list of header files to be placed in the
``Headers`` directory inside the framework folder. On non-Apple platforms
these headers may be installed using the ``PUBLIC_HEADER`` option to the
Specify resource files in a :prop_tgt:`FRAMEWORK` or :prop_tgt:`BUNDLE`.
Target marked with the :prop_tgt:`FRAMEWORK` or :prop_tgt:`BUNDLE` property
-generate framework or application bundle (both OS X and iOS is supported)
+generate framework or application bundle (both macOS and iOS is supported)
or normal shared libraries on other platforms.
This property may be set to a list of files to be placed in the corresponding
-directory (eg. ``Resources`` directory for OS X) inside the bundle.
+directory (eg. ``Resources`` directory for macOS) inside the bundle.
On non-Apple platforms these files may be installed using the ``RESOURCE``
option to the ``install(TARGETS)`` command.
Info.plist
resourcefile.txt
-For OS X systems it will produce following directory structure::
+For macOS systems it will produce following directory structure::
ExecutableTarget.app/
Contents
Mach-O Versions
^^^^^^^^^^^^^^^
-For shared libraries and executables on Mach-O systems (e.g. OS X, iOS),
+For shared libraries and executables on Mach-O systems (e.g. macOS, iOS),
the ``SOVERSION`` property corresponds to *compatibility version* and
:prop_tgt:`VERSION` to *current version*. See the :prop_tgt:`FRAMEWORK` target
property for an example. Versions of Mach-O binaries may be checked with the
STATIC_LIBRARY_FLAGS
--------------------
-Extra flags to use when linking static libraries.
+Archiver (or MSVC librarian) flags for a static library target.
+Targets that are shared libraries, modules, or executables need to use
+the :prop_tgt:`LINK_OPTIONS` or :prop_tgt:`LINK_FLAGS` target properties.
-Extra flags to use when linking a static library.
+The ``STATIC_LIBRARY_FLAGS`` property, managed as a string, can be used to add
+extra flags to the link step of a static library target.
+:prop_tgt:`STATIC_LIBRARY_FLAGS_<CONFIG>` will add to the configuration
+``<CONFIG>``, for example, ``DEBUG``, ``RELEASE``, ``MINSIZEREL``,
+``RELWITHDEBINFO``, ...
+
+.. note::
+
+ This property has been superseded by :prop_tgt:`STATIC_LIBRARY_OPTIONS`
+ property.
STATIC_LIBRARY_FLAGS_<CONFIG>
-----------------------------
-Per-configuration flags for creating a static library.
+Per-configuration archiver (or MSVC librarian) flags for a static library
+target.
-This is the configuration-specific version of STATIC_LIBRARY_FLAGS.
+This is the configuration-specific version of :prop_tgt:`STATIC_LIBRARY_FLAGS`.
+
+.. note::
+
+ This property has been superseded by :prop_tgt:`STATIC_LIBRARY_OPTIONS`
+ property.
--- /dev/null
+STATIC_LIBRARY_OPTIONS
+----------------------
+
+Archiver (or MSVC librarian) flags for a static library target.
+Targets that are shared libraries, modules, or executables need to use
+the :prop_tgt:`LINK_OPTIONS` target property.
+
+This property holds a :ref:`;-list <CMake Language Lists>` of options
+specified so far for its target. Use :command:`set_target_properties` or
+:command:`set_property` commands to set its content.
+
+Contents of ``STATIC_LIBRARY_OPTIONS`` may use "generator expressions" with the
+syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
+for available expressions. See the :manual:`cmake-buildsystem(7)` manual
+for more on defining buildsystem properties.
+
+.. note::
+
+ This property must be used in preference to :prop_tgt:`STATIC_LIBRARY_FLAGS`
+ property.
Mach-O Versions
^^^^^^^^^^^^^^^
-For shared libraries and executables on Mach-O systems (e.g. OS X, iOS),
+For shared libraries and executables on Mach-O systems (e.g. macOS, iOS),
the :prop_tgt:`SOVERSION` property correspond to *compatibility version* and
``VERSION`` to *current version*. See the :prop_tgt:`FRAMEWORK` target
property for an example. Versions of Mach-O binaries may be checked with the
-------------------
Sets the local debugger command for Visual Studio C++ targets.
+The property value may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
This is defined in ``<LocalDebuggerCommand>`` in the Visual Studio
project file.
--- /dev/null
+VS_DEBUGGER_COMMAND_ARGUMENTS
+-----------------------------
+
+Sets the local debugger command line arguments for Visual Studio C++ targets.
+The property value may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+This is defined in ``<LocalDebuggerCommandArguments>`` in the Visual Studio
+project file.
+
+This property only works for Visual Studio 2010 and above;
+it is ignored on other generators.
--- /dev/null
+VS_DEBUGGER_ENVIRONMENT
+-----------------------
+
+Sets the local debugger environment for Visual Studio C++ targets.
+The property value may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+This is defined in ``<LocalDebuggerEnvironment>`` in the Visual Studio
+project file.
+
+This property only works for Visual Studio 2010 and above;
+it is ignored on other generators.
-----------------------------
Sets the local debugger working directory for Visual Studio C++ targets.
+The property value may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
This is defined in ``<LocalDebuggerWorkingDirectory>`` in the Visual Studio
project file.
--- /dev/null
+XCODE_SCHEME_ADDRESS_SANITIZER
+------------------------------
+
+Whether to enable ``Address Sanitizer`` in the Diagnostics
+section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+-----------------------------------------------
+
+Whether to enable ``Detect use of stack after return``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN`
+if it is set when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_ARGUMENTS
+----------------------
+
+Specify command line arguments that should be added to the Arguments
+section of the generated Xcode scheme.
+
+If set to a list of arguments those will be added to the scheme.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+----------------------------------------
+
+Whether to disable the ``Main Thread Checker``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER`
+if it is set when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
+----------------------------------
+
+Whether to enable ``Dynamic Library Loads``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+-------------------------------------
+
+Whether to enable ``Dynamic Linker API usage``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_ENVIRONMENT
+------------------------
+
+Specify environment variables that should be added to the Arguments
+section of the generated Xcode scheme.
+
+If set to a list of environment variables and values of the form
+``MYVAR=value`` those environment variables will be added to the
+scheme.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_EXECUTABLE
+-----------------------
+
+Specify path to executable in the Info section of the generated
+Xcode scheme. If not set the schema generator will select the
+current target if it is actually executable.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_GUARD_MALLOC
+------------------------------
+
+Whether to enable ``Guard Malloc``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_GUARD_MALLOC` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+-------------------------------------
+
+Whether to enable the ``Main Thread Checker`` option
+``Pause on issues``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_MALLOC_GUARD_EDGES
+-------------------------------
+
+Whether to enable ``Malloc Guard Edges``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_MALLOC_SCRIBBLE
+------------------------------
+
+Whether to enable ``Malloc Scribble``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_MALLOC_STACK
+-------------------------
+
+Whether to enable ``Malloc Stack`` in the Diagnostics
+section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_MALLOC_STACK` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_THREAD_SANITIZER
+-----------------------------
+
+Whether to enable ``Thread Sanitizer`` in the Diagnostics
+section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_THREAD_SANITIZER` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_THREAD_SANITIZER_STOP
+----------------------------------
+
+Whether to enable ``Thread Sanitizer - Pause on issues``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+------------------------------------------
+
+Whether to enable ``Undefined Behavior Sanitizer``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER`
+if it is set when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+-----------------------------------------------
+
+Whether to enable ``Undefined Behavior Sanitizer`` option
+``Pause on issues``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP`
+if it is set when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+XCODE_SCHEME_ZOMBIE_OBJECTS
+------------------------------
+
+Whether to enable ``Zombie Objects``
+in the Diagnostics section of the generated Xcode scheme.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS` if it is set
+when a target is created.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
-----
* :manual:`cpack(1)` gained an ``IFW`` generator to package using
- Qt Framework Installer tools. See the :module:`CPackIFW` module.
+ Qt Framework Installer tools. See the :cpack_gen:`CPack IFW Generator`.
* :manual:`cpack(1)` gained ``7Z`` and ``TXZ`` generators supporting
lzma-compressed archives.
-* The :module:`CPackDeb` module learned a new
+* The :cpack_gen:`CPack DEB Generator` learned a new
:variable:`CPACK_DEBIAN_COMPRESSION_TYPE` variable to set the
tarball compression type.
-* The :manual:`cpack(1)` ``WiX`` generator learned to support
+* The :cpack_gen:`CPack WIX Generator` learned to support
a :prop_inst:`CPACK_WIX_ACL` installed file property to
specify an Access Control List.
CPack
-----
-* CPack gained a ``FREEBSD`` generator for FreeBSD ``pkg(8)``, configured
- by the :module:`CPackFreeBSD` module.
+* A :cpack_gen:`CPack FreeBSD Generator` was added for FreeBSD ``pkg(8)``.
-* The CPack ``DEB`` generator, configured by the :module:`CPackDeb` module,
- was enabled on Windows. While not fully featured (due to the lack of
- external UNIX tools) this will allow building basic cross-platform Debian
- packages.
+* The :cpack_gen:`CPack DEB Generator` was enabled on Windows. While not
+ fully featured (due to the lack of external UNIX tools) this will allow
+ building basic cross-platform Debian packages.
-* The :module:`CPackDeb` module learned to set package release version in
- ``Version`` info property.
+* The :cpack_gen:`CPack DEB Generator` learned to set package release
+ version in ``Version`` info property.
See the :variable:`CPACK_DEBIAN_PACKAGE_RELEASE` variable.
-* The :module:`CPackDeb` module learned more strict package version checking
- that complies with Debian rules.
+* The :cpack_gen:`CPack DEB Generator` learned more strict package
+ version checking that complies with Debian rules.
* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and
:command:`cpack_ifw_configure_component_group` commands gained a new
``REPLACES`` and ``CHECKABLE`` options.
-* The :module:`CPackIFW` module gained new
+* The :cpack_gen:`CPack IFW Generator` gained new
:variable:`CPACK_IFW_PACKAGE_FILE_EXTENSION` variable to customize
target binary format.
-* The :module:`CPackIFW` module gained new
+* The :cpack_gen:`CPack IFW Generator` gained new
:variable:`CPACK_IFW_REPOSITORIES_DIRECTORIES` variable to specify
additional repositories dirs that will be used to resolve and
repack dependent components. This feature is only available when
using QtIFW 3.1 or later.
-* Modules :module:`CPackRPM` and :module:`CPackDeb` learned to set package epoch
- version.
+* The :cpack_gen:`CPack RPM Generator` and :cpack_gen:`CPack DEB Generator`
+ learned to set the package epoch version.
See :variable:`CPACK_RPM_PACKAGE_EPOCH` and
:variable:`CPACK_DEBIAN_PACKAGE_EPOCH` variables.
* :manual:`cpack(1)` gained ``--trace`` and ``--trace-expand`` options.
-* The :module:`CPackIFW` module gained new
+* The :cpack_gen:`CPack IFW Generator` gained new
:variable:`CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR` variable to control
if the target directory should not be deleted when uninstalling.
-* The :module:`CPackRPM` module learned to enable enforcing of execute
+* The :cpack_gen:`CPack RPM Generator` learned to enable enforcing of execute
privileges on programs and shared libraries.
See :variable:`CPACK_RPM_INSTALL_WITH_EXEC` variable.
:variable:`CMAKE_PROJECT_VERSION_PATCH`
to initialize corresponding CPack variables.
-* :manual:`cpack(1)` gained basic support for `NuGet`_.
- See the :module:`CPackNuGet` module.
+* A :cpack_gen:`CPack NuGet Generator` was was added with basic
+ support for `NuGet`_.
.. _NuGet: https://docs.microsoft.com/en-us/nuget/what-is-nuget
--- /dev/null
+CMake 3.13 Release Notes
+************************
+
+.. only:: html
+
+ .. contents::
+
+Changes made since CMake 3.12 include the following.
+
+New Features
+============
+
+Generators
+----------
+
+* The :ref:`Visual Studio Generators` for VS 2010 and above learned to
+ support the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property
+ and supporting :module:`CheckIPOSupported` module.
+
+* The :generator:`Xcode` generator learned to configure more Xcode Scheme
+ fields. See the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable.
+
+* The :generator:`Green Hills MULTI` generator has been updated:
+
+ - Added support for architecture selection through
+ :variable:`CMAKE_GENERATOR_PLATFORM`:
+ e.g. ``arm``, ``ppc``, and ``86``.
+
+ - Added support for toolset selection through
+ :variable:`CMAKE_GENERATOR_TOOLSET`,
+ e.g. ``comp_201205``, ``comp_201510``, ``comp_201722_beta``.
+
+ - Added support for platform selection through ``GHS_TARGET_PLATFORM``,
+ e.g. ``integrity``, ``linux``, ``standalone``, etc.
+
+ - No longer checks that ``arm`` based compilers are installed but ensures
+ that the correct ``gbuild.exe`` exists.
+
+ - No longer hard-codes ARM files, BSP, toolset, or OS locations.
+
+Command-Line
+------------
+
+* The :manual:`cmake(1)` command gained the ``-S <source_dir>``
+ command line option to specify the location of the source directory.
+ This option can be used independently of ``-B``.
+
+* The :manual:`cmake(1)` command gained the ``-B <build_dir>``
+ command line option to specify the location of the build directory.
+ This option can be used independently of ``-S``.
+
+* The :manual:`cmake(1)` ``-E create_symlink`` command can now be used
+ on Windows.
+
+Commands
+--------
+
+* The :command:`add_custom_command` and :command:`add_custom_target` commands
+ learned to support generator expressions in ``WORKING_DIRECTORY`` options.
+
+* The :command:`add_link_options` command was created to add link
+ options in the current directory.
+
+* The :command:`install(TARGETS)` command learned to install targets
+ created outside the current directory.
+
+* The :command:`link_directories` command gained options to control
+ insertion position.
+
+* The :command:`list(SORT)` command gained options to control the
+ comparison operation used to order the entries.
+
+* The :command:`math` command gained options for hexadecimal.
+
+* The :command:`target_link_directories` command was created to
+ specify link directories for targets and their dependents.
+
+* The :command:`target_link_options` command was created to
+ specify link options for targets and their dependents.
+
+* The :command:`target_link_libraries` command may now be called
+ to modify targets created outside the current directory.
+ See policy :policy:`CMP0079`.
+
+Variables
+---------
+
+* A :variable:`CMAKE_AUTOGEN_VERBOSE` variable was added to optionally
+ increase the verbosity of :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTOUIC`
+ and :prop_tgt:`AUTORCC` from within CMake project code.
+
+* A :variable:`CMAKE_VS_GLOBALS` variable was added to initialize
+ :prop_tgt:`VS_GLOBAL_<variable>` target properties on targets as
+ they are created.
+
+Properties
+----------
+
+* The :prop_tgt:`DEPLOYMENT_ADDITIONAL_FILES` target property was
+ added to tell the :generator:`Visual Studio 9 2008` generator
+ to specify additional files for deployment to WinCE devices
+ for remote debugging.
+
+* The :prop_tgt:`INTERFACE_LINK_DEPENDS` target property was created
+ to specify transitive link dependencies on files.
+
+* The :prop_tgt:`LINK_DEPENDS` target property learned to support
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+* :prop_tgt:`LINK_DIRECTORIES` and :prop_tgt:`INTERFACE_LINK_DIRECTORIES`
+ target properties were added to collect link directories for a target
+ and its dependents. Use the :command:`target_link_directories` command
+ to set them.
+
+* :prop_tgt:`LINK_OPTIONS` and :prop_tgt:`INTERFACE_LINK_OPTIONS` target
+ properties were added to collect link options for a target and its
+ dependents. Use the :command:`target_link_options` command to set them.
+
+* A :prop_dir:`LINK_OPTIONS` directory property was added to collect
+ link options for targets created under the current directory.
+ Use the :command:`add_link_options` command to set it.
+
+* A :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property was created
+ to specify archiver options to use when creating static libraries.
+
+* A :prop_tgt:`VS_DEBUGGER_COMMAND_ARGUMENTS` target property was created to
+ set the debugging command line arguments with
+ :ref:`Visual Studio Generators` for VS 2010 and above.
+
+* A :prop_tgt:`VS_DEBUGGER_ENVIRONMENT` target property was created to
+ set the debugging environment with
+ :ref:`Visual Studio Generators` for VS 2010 and above.
+
+* The :prop_tgt:`VS_DEBUGGER_COMMAND` and
+ :prop_tgt:`VS_DEBUGGER_WORKING_DIRECTORY` target properties
+ now support generator expressions.
+
+Modules
+-------
+
+* The :module:`FindBoost` module gained a ``Boost_ARCHITECTURE`` option
+ to specify a Boost architecture-specific library filename fragment.
+
+* The :module:`FindCURL` module learned to find debug and release variants
+ separately.
+
+* The :module:`FindMatlab` module gained new components ``ENGINE_LIBRARY`` and
+ ``DATAARRAY_LIBRARY`` to request finding the Matlab C++ Engine and DataArray
+ libraries respectively.
+
+* The :module:`FindMatlab` module now explicitly exports mexFunction in Visual
+ Studio.
+
+* The :module:`FindMatlab` module gained a new ``MCC_COMPILER``
+ component to request finding the Matlab Compiler add-on.
+
+* The :module:`FindPkgConfig` module gained an option to create imported
+ targets in global scope.
+
+* The :module:`FindPkgConfig` module gained support for ``<`` and ``>``
+ operators for version checks in addition to the already supported
+ operators ``>=``, ``<=``, and ``=``.
+
+* Modules :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython`
+ gain capability to control order of resource lookup on macOS (Framework) and
+ Windows (Registry).
+
+* The :module:`FindSubversion` module ``Subversion_WC_INFO`` command
+ gained an ``IGNORE_SVN_FAILURE`` option to suppress failures,
+ e.g. when the source tree is not under Subversion control.
+
+* The :module:`UseSWIG` module learned to manage target property
+ :prop_tgt:`INCLUDE_DIRECTORIES` for ``SWIG`` compilation.
+
+CTest
+-----
+
+* :manual:`ctest(1)` gained a ``--progress`` option to enable a live
+ test progress summary when output goes to a terminal.
+
+CPack
+-----
+
+* The :cpack_gen:`CPack DEB Generator` learned to split debug symbols into
+ a corresponding .ddeb package when ``CPACK_DEBIAN_DEBUGINFO_PACKAGE`` is
+ set.
+
+* The :cpack_gen:`CPack DEB Generator` learned to honor the ``SOURCE_DATE_EPOCH``
+ environment variable when packaging files. This is useful for generating
+ reproducible packages.
+
+* CPack gained a new :cpack_gen:`CPack External Generator` which is used to
+ export the CPack metadata in a format that other software can understand. The
+ intention of this generator is to allow external packaging software to take
+ advantage of CPack's features when it may not be possible to use CPack for
+ the entire packaging process.
+
+Deprecated and Removed Features
+===============================
+
+* An explicit deprecation diagnostic was added for policies ``CMP0055``
+ through ``CMP0063`` (``CMP0054`` and below were already deprecated).
+ The :manual:`cmake-policies(7)` manual explains that the OLD behaviors
+ of all policies are deprecated and that projects should port to the
+ NEW behaviors.
+
+Other Changes
+=============
+
+* The precompiled binaries provided on ``cmake.org`` now include
+ qthelp-format documentation.
+
+* The :command:`option` command now honors an existing normal variable
+ of the same name and does nothing instead of possibly creating a cache
+ entry (or setting its type) and removing the normal variable.
+ See policy :policy:`CMP0077`.
+
+* The :ref:`Makefile Generators` learned to remove custom command and
+ custom target byproducts during ``make clean``.
+
+* The :command:`target_sources` command now interprets relative source file
+ paths as relative to the current source directory. This simplifies
+ incrementally building up a target's sources from subdirectories. The
+ :policy:`CMP0076` policy was added to provide backward compatibility with
+ the old behavior where required.
+
+* The :module:`BundleUtilities` module may no longer be included at configure
+ time. This was always a bug anyway. See policy :policy:`CMP0080`.
+
+* The :module:`UseSWIG` module has changed strategy for target naming.
+ See policy :policy:`CMP0078`.
+
+* The :prop_tgt:`LINK_DIRECTORIES` target property now expects absolute paths.
+ See policy :policy:`CMP0081`.
+
+* The CPack generators have been moved into their own separate section
+ in the documentation, rather than having the documentation in their
+ internal implementation modules.
+ These internal implementation modules are also no longer available
+ to scripts that may have been incorrectly including them, because
+ they should never have been available in the first place.
CPack
-----
-* The :module:`CPackRPM` module learned options to set per-component
+* The :cpack_gen:`CPack RPM Generator` learned options to set per-component
descriptions and summaries. See the
:variable:`CPACK_RPM_<component>_PACKAGE_DESCRIPTION` and
:variable:`CPACK_RPM_<component>_PACKAGE_SUMMARY` variables.
-* The :module:`CPackRPM` module learned options to specify
+* The :cpack_gen:`CPack RPM Generator` learned options to specify
requirements for pre- and post-install scripts. See the
:variable:`CPACK_RPM_PACKAGE_REQUIRES_PRE` and
:variable:`CPACK_RPM_PACKAGE_REQUIRES_POST` variables.
-* The :module:`CPackRPM` module learned options to specify
+* The :cpack_gen:`CPack RPM Generator` learned options to specify
requirements for pre- and post-uninstall scripts. See the
:variable:`CPACK_RPM_PACKAGE_REQUIRES_PREUN` and
:variable:`CPACK_RPM_PACKAGE_REQUIRES_POSTUN` variables.
-* The :module:`CPackRPM` module learned a new
+* The :cpack_gen:`CPack RPM Generator` learned a new
:variable:`CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX` variable to
specify a component-specific value to use instead of
:variable:`CPACK_PACKAGING_INSTALL_PREFIX`.
-* The :module:`CPackRPM` module learned a new
+* The :cpack_gen:`CPack RPM Generator` learned a new
:variable:`CPACK_RPM_RELOCATION_PATHS` variable to
specify multiple relocation prefixes for a single rpm package.
CPack
-----
-* The :manual:`cpack(1)` ``IFW`` generator and the :module:`CPackIFW`
- module learned to support Qt Framework Installer 2.0 tools.
+* The :cpack_gen:`CPack IFW Generator` learned to support
+ Qt Framework Installer 2.0 tools.
-* The :module:`CPackDeb` module learned a new
+* The :cpack_gen:`CPack DEB Generator` learned a new
:variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS`
variable to specify per-component use of ``dpkg-shlibdeps``.
-* The :module:`CPackDeb` module learned a new
+* The :cpack_gen:`CPack DEB Generator` learned a new
:variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS`
option to specify per-component dependencies.
-* The :module:`CPackRPM` module learned to package symbolic links
+* The :cpack_gen:`CPack RPM Generator` learned to package symbolic links
more cleanly and now supports directory symlinks with recent
``rpmbuild`` versions.
-* The :module:`CPackRPM` module learned a new
+* The :cpack_gen:`CPack RPM Generator` learned a new
:variable:`CPACK_RPM_ADDITIONAL_MAN_DIRS` variable to specify
directories containing man pages for the brp-compress RPM macro.
-* The :module:`CPackRPM` module learned a new
+* The :cpack_gen:`CPack RPM Generator` learned a new
:variable:`CPACK_RPM_<component>_PACKAGE_ARCHITECTURE` variable
to specify a component-specific package architecture.
CPack
-----
-* The :module:`CPackDeb` module learned to set package dependencies
+* The :cpack_gen:`CPack DEB Generator` learned to set package dependencies
per component. See variables:
* :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_BREAKS`
:module:`CheckSymbolExists`, and :module:`FindThreads` modules learned to
work in environments where only CXX is enabled.
-* The :module:`CPackDeb` module now correctly excludes symlinks during package
- checksum calculation.
+* The :cpack_gen:`CPack DEB Generator` now correctly excludes symlinks
+ during package checksum calculation.
-* The :module:`CPackDeb` no longer uses fakeroot and system tar program for
- packaging.
+* The :cpack_gen:`CPack DEB Generator` no longer uses fakeroot and
+ system tar program for packaging.
* The :module:`CPack` module no longer mangles settings with CMake-special
characters when they're used as defaults for other settings. The macro
CPack
-----
-* The :module:`CPackDMG` module learned new variable to specify AppleScript
- file run to customize appearance of ``DragNDrop`` installer folder,
- including background image setting using supplied PNG or multi-resolution
- TIFF file. See the :variable:`CPACK_DMG_DS_STORE_SETUP_SCRIPT` and
+* The :cpack_gen:`CPack DragNDrop Generator` learned new variable to
+ specify AppleScript file run to customize appearance of ``DragNDrop``
+ installer folder, including background image setting using supplied
+ PNG or multi-resolution TIFF file.
+ See the :variable:`CPACK_DMG_DS_STORE_SETUP_SCRIPT` and
:variable:`CPACK_DMG_BACKGROUND_IMAGE` variables.
-* The :module:`CPackDeb` module learned to set the optional config
+* The :cpack_gen:`CPack DEB Generator` learned to set the optional config
file ``Source`` field using a monolithic or per-component variable.
See :variable:`CPACK_DEBIAN_PACKAGE_SOURCE`.
-* The :module:`CPackDeb` module learned to set Package, Section
+* The :cpack_gen:`CPack DEB Generator` learned to set Package, Section
and Priority control fields per-component.
See variables :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_SECTION` and
:variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY`.
-* The :module:`CPack DragNDrop generator <CPackDMG>` learned to add
+* The :cpack_gen:`CPack DragNDrop Generator` learned to add
multi-lingual SLAs to a DMG which is presented to the user when they try to
mount the DMG. See the :variable:`CPACK_DMG_SLA_LANGUAGES` and
:variable:`CPACK_DMG_SLA_DIR` variables for details.
-* The :module:`CPackNSIS` module learned new variables to add bitmaps to the
- installer. See the :variable:`CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP`
+* The :cpack_gen:`CPack NSIS Generator` learned new variables to
+ add bitmaps to the installer.
+ See the :variable:`CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP`
and :variable:`CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP` variables.
-* The :module:`CPackRPM` module learned to set Name and Group
+* The :cpack_gen:`CPack RPM Generator` learned to set Name and Group
control fields per-component.
See :variable:`CPACK_RPM_<component>_PACKAGE_NAME`
and :variable:`CPACK_RPM_<component>_PACKAGE_GROUP`.
CPack
-----
-* The :module:`CPackDeb` module learned how to handle ``$ORIGIN``
+* The :cpack_gen:`CPack DEB Generator` learned how to handle ``$ORIGIN``
in ``CMAKE_INSTALL_RPATH`` when :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS`
is used for dependency auto detection.
-* The :module:`CPackDeb` module learned how to generate ``DEBIAN/shlibs``
- contorl file when package contains shared libraries.
+* The :cpack_gen:`CPack DEB Generator` learned how to generate
+ ``DEBIAN/shlibs`` contorl file when package contains shared libraries.
-* The :module:`CPackDeb` module learned how to generate ``DEBIAN/postinst`` and
- ``DEBIAN/postrm`` files if the package installs libraries in
- ldconfig-controlled locations (e.g. ``/lib/``, ``/usr/lib/``).
+* The :cpack_gen:`CPack DEB Generator` learned how to generate
+ ``DEBIAN/postinst`` and ``DEBIAN/postrm`` files if the package installs
+ libraries in ldconfig-controlled locations (e.g. ``/lib/``, ``/usr/lib/``).
-* The :module:`CPackDeb` module learned how to generate dependencies between
- Debian packages if multi-component setup is used and
+* The :cpack_gen:`CPack DEB Generator` learned how to generate dependencies
+ between Debian packages if multi-component setup is used and
:variable:`CPACK_COMPONENT_<compName>_DEPENDS` variables are set.
For backward compatibility this feature is disabled by default.
See :variable:`CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS`.
-* The :module:`CPackDeb` module learned how to set custom package file names
- including how to generate properly-named Debian packages::
+* The :cpack_gen:`CPack DEB Generator` learned how to set custom package
+ file names including how to generate properly-named Debian packages::
<PackageName>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
:variable:`CPACK_DEBIAN_FILE_NAME` and
:variable:`CPACK_DEBIAN_<COMPONENT>_FILE_NAME`.
-* The :module:`CPackDeb` module learned how to set the package release number
- (``DebianRevisionNumber`` in package file name when used in combination with
- ``DEB-DEFAULT`` value set by :variable:`CPACK_DEBIAN_FILE_NAME`). See
- :variable:`CPACK_DEBIAN_PACKAGE_RELEASE`.
+* The :cpack_gen:`CPack DEB Generator` learned how to set the package
+ release number (``DebianRevisionNumber`` in package file name when
+ used in combination with ``DEB-DEFAULT`` value set by
+ :variable:`CPACK_DEBIAN_FILE_NAME`).
+ See :variable:`CPACK_DEBIAN_PACKAGE_RELEASE`.
-* The :module:`CPackDeb` module learned how to set the package architecture
- per-component. See :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_ARCHITECTURE`.
+* The :cpack_gen:`CPack DEB Generator` learned how to set the package
+ architecture per-component.
+ See :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_ARCHITECTURE`.
-* The :module:`CPackDMG` module learned a new option to tell the CPack
- ``DragNDrop`` generaor to skip the ``/Applications`` symlink.
+* The :cpack_gen:`CPack DragNDrop Generator` learned a new option to skip the
+ ``/Applications`` symlink.
See the :variable:`CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK` variable.
* The :module:`CPackIFW` module gained a new
:command:`cpack_ifw_update_repository` command to update a QtIFW-specific
repository from a remote repository.
-* The :module:`CPackRPM` module learned how to set RPM ``dist`` tag as part of
- RPM ``Release:`` tag when enabled (mandatory on some Linux distributions for
- e.g. on Fedora).
+* The :cpack_gen:`CPack RPM Generator` learned how to set RPM ``dist`` tag
+ as part of RPM ``Release:`` tag when enabled (mandatory on some Linux
+ distributions for e.g. on Fedora).
See :variable:`CPACK_RPM_PACKAGE_RELEASE_DIST`.
-* The :module:`CPackRPM` module learned how to set default values for owning
- user/group and file/directory permissions of package content.
+* The :cpack_gen:`CPack RPM Generator` learned how to set default values
+ for owning user/group and file/directory permissions of package content.
See :variable:`CPACK_RPM_DEFAULT_USER`, :variable:`CPACK_RPM_DEFAULT_GROUP`,
:variable:`CPACK_RPM_DEFAULT_FILE_PERMISSIONS`,
:variable:`CPACK_RPM_DEFAULT_DIR_PERMISSIONS` and their per component
counterparts.
-* The :module:`CPackRPM` module learned how to set user defined package file
- names, how to specify that rpmbuild should decide on file name format as
- well as handling of multiple rpm packages generated by a single user defined
- spec file.
+* The :cpack_gen:`CPack RPM Generator` learned how to set user defined
+ package file names, how to specify that rpmbuild should decide on file
+ name format as well as handling of multiple rpm packages generated by a
+ single user defined spec file.
See :variable:`CPACK_RPM_PACKAGE_NAME` and
:variable:`CPACK_RPM_<component>_PACKAGE_NAME`.
-* The :module:`CPackRPM` module learned how to correctly handle symlinks
+* The :cpack_gen:`CPack RPM Generator` learned how to correctly handle symlinks
that are pointing outside generated packages.
Other
Input variables of the old case will be honored if provided, and output
variables of the old case are always provided.
-* The :module:`CPackRPM` module now supports upper cased component
+* The :cpack_gen:`CPack RPM Generator` now supports upper cased component
names in per component CPackRPM specific variables.
E.g. component named ``foo`` now expects component specific
variable to be ``CPACK_RPM_FOO_PACKAGE_NAME`` while before
CPack
-----
-* CPack gained a ``productbuild`` generator on OS X, configured by
- the :module:`CPackProductBuild` module.
+* CPack gained a :cpack_gen:`CPack productbuild Generator` on OS X.
* CPack gained a new :variable:`CPACK_PACKAGE_CHECKSUM` variable to
enable generation of a checksum file for each package file.
-* The :module:`CPackDeb` module learned to support long file names
+* The :cpack_gen:`CPack DEB Generator` learned to support long file names
when archive format is set to GNU tar.
See :variable:`CPACK_DEBIAN_ARCHIVE_TYPE`
``USER_INTERFACES`` option to add a list of additional pages to the IFW
installer.
-* The :module:`CPackRPM` module learned to generate debuginfo
+* The :cpack_gen:`CPack RPM Generator` learned to generate debuginfo
packages on demand. See :variable:`CPACK_RPM_DEBUGINFO_PACKAGE`
and its per component version.
-* The :module:`CPackRPM` module learned to generate source rpm
+* The :cpack_gen:`CPack RPM Generator` learned to generate source rpm
(SRPM) packages on demand. See :variable:`CPACK_RPM_PACKAGE_SOURCES`,
:variable:`CPACK_RPM_SOURCE_PKG_BUILD_PARAMS` and
:variable:`CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX`.
-* The CPack NSIS generator now supports
+* The :cpack_gen:`CPack NSIS Generator` now supports
:variable:`CPACK_NSIS_<compName>_INSTALL_DIRECTORY`.
This can be used to set component specific installation directories.
-* The CPack WIX generator now supports
+* The :cpack_gen:`CPack WIX Generator` now supports
:variable:`CPACK_WIX_SKIP_PROGRAM_FOLDER` to allow specification
of a custom absolute installation prefix outside
of the ProgramFiles folders.
-* The CPack WIX generator now supports
+* The :cpack_gen:`CPack WIX Generator` now supports
:variable:`CPACK_COMPONENT_<compName>_DISABLED`.
This can be used to deselect a component from being installed by default.
-* The CPack WIX generator now supports :variable:`CPACK_WIX_PATCH_FILE`
- fragments for Feature elements.
+* The :cpack_gen:`CPack WIX Generator` now supports
+ :variable:`CPACK_WIX_PATCH_FILE` fragments for Feature elements.
-* The CPack WIX generator now supports
+* The :cpack_gen:`CPack WIX Generator` now supports
:variable:`CPACK_WIX_ROOT_FEATURE_TITLE` and
:variable:`CPACK_WIX_ROOT_FEATURE_DESCRIPTION` to allow the specification
of a custom title and description for the root feature element.
option now is deprecated and will be removed in a future version of CMake.
Please use new ``SORTING_PRIORITY`` option instead.
-* The :module:`CPackIFW` module gained new
+* The :cpack_gen:`CPack IFW Generator` gained new
:variable:`CPACK_IFW_PACKAGE_WATERMARK`,
:variable:`CPACK_IFW_PACKAGE_BANNER`,
:variable:`CPACK_IFW_PACKAGE_BACKGROUND`,
:variable:`CPACK_IFW_PACKAGE_TITLE_COLOR`
variables to customize a QtIFW installer look.
-* The :module:`CPackProductBuild` module gained options to sign packages.
+* The :cpack_gen:`CPack productbuild Generator` gained options to sign packages.
See the variables :variable:`CPACK_PRODUCTBUILD_IDENTITY_NAME`,
:variable:`CPACK_PRODUCTBUILD_KEYCHAIN_PATH`,
:variable:`CPACK_PKGBUILD_IDENTITY_NAME`, and
:variable:`CPACK_PKGBUILD_KEYCHAIN_PATH`.
-* The :module:`CPackRPM` module learned to omit tags that are not supported by
- provided ``rpmbuild`` tool. If unsupported tags are set they are ignored
- and a developer warning is printed out.
+* The :cpack_gen:`CPack RPM Generator` learned to omit tags that are not
+ supported by provided ``rpmbuild`` tool. If unsupported tags are set they
+ are ignored and a developer warning is printed out.
-* The :module:`CPackRPM` module learned to generate main component package
- which forces generation of a rpm for defined component without component
- suffix in filename and package name.
+* The :cpack_gen:`CPack RPM Generator` learned to generate main component
+ package which forces generation of a rpm for defined component without
+ component suffix in filename and package name.
See :variable:`CPACK_RPM_MAIN_COMPONENT` variable.
-* The :module:`CPackRPM` module learned to generate a single ``debuginfo``
- package on demand even if components packaging is used.
+* The :cpack_gen:`CPack RPM Generator` learned to generate a single
+ ``debuginfo`` package on demand even if components packaging is used.
See :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` variable.
-* The :module:`CPackRPM` module learned to support
+* The :cpack_gen:`CPack RPM Generator` learned to support
multiple directives per file when using
:variable:`CPACK_RPM_USER_FILELIST` variable.
CPack
-----
-* The :module:`CPackArchive` module learned to modify the filename
+* The :cpack_gen:`CPack Archive Generator` learned to modify the filename
per-component. See the :variable:`CPACK_ARCHIVE_FILE_NAME` variable and
its per-component version :variable:`CPACK_ARCHIVE_<component>_FILE_NAME`.
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 :cpack_gen:`CPack IFW Generator` 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
+* The :cpack_gen:`CPack productbuild Generator` 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 :cpack_gen:`CPack RPM Generator` 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.
+* The :cpack_gen:`CPack WIX Generator` 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
+* The :cpack_gen:`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``.
.. toctree::
:maxdepth: 1
+ 3.13 <3.13>
3.12 <3.12>
3.11 <3.11>
3.10 <3.10>
--- /dev/null
+CACHE
+-----
+
+Read cache variables.
+
+Use the syntax ``$CACHE{VAR}`` to read cache entry ``VAR``.
+See the :ref:`cmake-language(7) variables <CMake Language Variables>`
+documentation for more complete documentation of the interaction of
+normal variables and cache entries.
+
+When evaluating :ref:`Variable References` of the form ``${VAR}``,
+CMake first searches for a normal variable with that name, and if not
+found CMake will search for a cache entry with that name.
+The ``$CACHE{VAR}`` syntax can be used to do direct cache lookup and
+ignore any existing normal variable.
+
+See the :command:`set` command to see how to write cache variables.
--------------------
:ref:`;-list <CMake Language Lists>` of directories specifying a search path
-for OS X application bundles used by the :command:`find_program`, and
+for macOS application bundles used by the :command:`find_program`, and
:command:`find_package` commands.
--- /dev/null
+CMAKE_AUTOGEN_VERBOSE
+---------------------
+
+Sets the verbosity of :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTOUIC` and
+:prop_tgt:`AUTORCC`. A positive integer value or a true boolean value
+lets the ``AUTO*`` generators output additional processing information.
+
+Setting :variable:`CMAKE_AUTOGEN_VERBOSE` has the same effect
+as setting the ``VERBOSE`` environment variable during
+generation (e.g. by calling ``make VERBOSE=1``).
+The extra verbosity is limited to the ``AUTO*`` generators though.
+
+By default :variable:`CMAKE_AUTOGEN_VERBOSE` is unset.
--- /dev/null
+CMAKE_CPACK_COMMAND
+-------------------
+
+Full path to :manual:`cpack(1)` command installed with CMake.
+
+This is the full path to the CPack executable :manual:`cpack(1)` which is
+useful from custom commands that want to use the :manual:`cmake(1)` ``-E``
+option for portable system commands.
This variable can be populated with a list of properties to generate
debug output for when evaluating target properties. Currently it can
-only be used when evaluating the :prop_tgt:`INCLUDE_DIRECTORIES`,
-:prop_tgt:`COMPILE_DEFINITIONS`, :prop_tgt:`COMPILE_OPTIONS`,
-:prop_tgt:`AUTOUIC_OPTIONS`, :prop_tgt:`SOURCES`, :prop_tgt:`COMPILE_FEATURES`,
-:prop_tgt:`POSITION_INDEPENDENT_CODE` target properties and any other property
-listed in :prop_tgt:`COMPATIBLE_INTERFACE_STRING` and other
-``COMPATIBLE_INTERFACE_`` properties. It outputs an origin for each entry in
-the target property. Default is unset.
+only be used when evaluating:
+
+* :prop_tgt:`AUTOUIC_OPTIONS`
+* :prop_tgt:`COMPILE_DEFINITIONS`
+* :prop_tgt:`COMPILE_FEATURES`
+* :prop_tgt:`COMPILE_OPTIONS`
+* :prop_tgt:`INCLUDE_DIRECTORIES`
+* :prop_tgt:`LINK_DIRECTORIES`
+* :prop_tgt:`LINK_OPTIONS`
+* :prop_tgt:`POSITION_INDEPENDENT_CODE`
+* :prop_tgt:`SOURCES`
+
+target properties and any other property listed in
+:prop_tgt:`COMPATIBLE_INTERFACE_STRING` and other
+``COMPATIBLE_INTERFACE_`` properties. It outputs an origin for each entry
+in the target property. Default is unset.
For DLL platforms an import library will be created for the exported
symbols and then used for linking. All Windows-based systems
including Cygwin are DLL platforms. For non-DLL platforms that
-require all symbols to be resolved at link time, such as OS X, the
+require all symbols to be resolved at link time, such as macOS, the
module will ``link`` to the executable using a flag like
``-bundle_loader``. For other non-DLL platforms the link rule is simply
ignored since the dynamic loader will automatically bind symbols when
--------------------
This variable affects how ``find_*`` commands choose between
-OS X Application Bundles and unix-style package components.
+macOS Application Bundles and unix-style package components.
-On Darwin or systems supporting OS X Application Bundles, the
+On Darwin or systems supporting macOS Application Bundles, the
``CMAKE_FIND_APPBUNDLE`` variable can be set to empty or
one of the following:
--------------------
This variable affects how ``find_*`` commands choose between
-OS X Frameworks and unix-style package components.
+macOS Frameworks and unix-style package components.
-On Darwin or systems supporting OS X Frameworks, the
+On Darwin or systems supporting macOS Frameworks, the
``CMAKE_FIND_FRAMEWORK`` variable can be set to empty or
one of the following:
--------------------
:ref:`;-list <CMake Language Lists>` of directories specifying a search path
-for OS X frameworks used by the :command:`find_library`,
+for macOS frameworks used by the :command:`find_library`,
:command:`find_package`, :command:`find_path`, and :command:`find_file`
commands.
* For :ref:`Visual Studio Generators` with VS 2005 and above this
specifies the target architecture.
+* For :generator:`Green Hills MULTI` this specifies the target architecture.
+
See native build system documentation for allowed platform names.
Visual Studio Platform Selection
* :ref:`Visual Studio Generators` for VS 2010 and above
* The :generator:`Xcode` generator for Xcode 3.0 and above
+* The :generator:`Green Hills MULTI` generator
See native build system documentation for allowed toolset names.
CMAKE_HOST_APPLE
----------------
-``True`` for Apple OS X operating systems.
+``True`` for Apple macOS operating systems.
-Set to ``true`` when the host system is Apple OS X.
+Set to ``true`` when the host system is Apple macOS.
Name of the OS CMake is running on.
On systems that have the uname command, this variable is set to the
-output of ``uname -s``. ``Linux``, ``Windows``, and ``Darwin`` for OS X
+output of ``uname -s``. ``Linux``, ``Windows``, and ``Darwin`` for macOS
are the values found on the big three operating systems.
CMAKE_INSTALL_NAME_DIR
----------------------
-OS X directory name for installed targets.
+macOS directory name for installed targets.
``CMAKE_INSTALL_NAME_DIR`` is used to initialize the
:prop_tgt:`INSTALL_NAME_DIR` property on all targets. See that target
--- /dev/null
+CMAKE_<LANG>_LINKER_WRAPPER_FLAG
+--------------------------------
+
+Defines the syntax of compiler driver option to pass options to the linker
+tool. It will be used to translate the ``LINKER:`` prefix in the link options
+(see :command:`add_link_options` and :command:`target_link_options`).
+
+This variable holds a :ref:`;-list <CMake Language Lists>` of tokens.
+If a space (i.e. " ") is specified as last token, flag and ``LINKER:``
+arguments will be specified as separate arguments to the compiler driver.
+The :variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP` variable can be specified
+to manage concatenation of arguments.
+
+For example, for ``Clang`` we have:
+
+.. code-block:: cmake
+
+ set (CMAKE_C_LINKER_WRAPPER_FLAG "-Xlinker" " ")
+
+Specifying ``"LINKER:-z,defs"`` will be transformed in
+``-Xlinker -z -Xlinker defs``.
+
+For ``GNU GCC``:
+
+.. code-block:: cmake
+
+ set (CMAKE_C_LINKER_WRAPPER_FLAG "-Wl,")
+ set (CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",")
+
+Specifying ``"LINKER:-z,defs"`` will be transformed in ``-Wl,-z,defs``.
+
+And for ``SunPro``:
+
+.. code-block:: cmake
+
+ set (CMAKE_C_LINKER_WRAPPER_FLAG "-Qoption" "ld" " ")
+ set (CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",")
+
+Specifying ``"LINKER:-z,defs"`` will be transformed in ``-Qoption ld -z,defs``.
--- /dev/null
+CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP
+------------------------------------
+
+This variable is used with :variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG`
+variable to format ``LINKER:`` prefix in the link options
+(see :command:`add_link_options` and :command:`target_link_options`).
+
+When specified, arguments of the ``LINKER:`` prefix will be concatenated using
+this value as separator.
--- /dev/null
+CMAKE_LINK_DIRECTORIES_BEFORE
+-----------------------------
+
+Whether to append or prepend directories by default in
+:command:`link_directories`.
+
+This variable affects the default behavior of the :command:`link_directories`
+command. Setting this variable to ``ON`` is equivalent to using the ``BEFORE``
+option in all uses of that command.
CMAKE_MACOSX_RPATH
-------------------
-Whether to use rpaths on OS X and iOS.
+Whether to use rpaths on macOS and iOS.
This variable is used to initialize the :prop_tgt:`MACOSX_RPATH` property on
all targets.
the CMake cache then CMake will use the specified value if
possible.
-* The :generator:`Green Hills MULTI` generator sets this to ``gbuild``.
- If a user or project explicitly adds ``CMAKE_MAKE_PROGRAM`` to
- the CMake cache then CMake will use the specified value.
+* The :generator:`Green Hills MULTI` generator sets this to the full
+ path to ``gbuild.exe`` based upon the toolset being used.
+
+ Once the generator has initialized a particular value for this
+ variable, changing the value has undefined behavior.
The ``CMAKE_MAKE_PROGRAM`` variable is set for use by project code.
The value is also used by the :manual:`cmake(1)` ``--build`` and
CMAKE_OSX_ARCHITECTURES
-----------------------
-Target specific architectures for OS X and iOS.
+Target specific architectures for macOS and iOS.
This variable is used to initialize the :prop_tgt:`OSX_ARCHITECTURES`
property on each target as it is created. See that target property
CMAKE_OSX_SYSROOT
-----------------
-Specify the location or name of the OS X platform SDK to be used.
+Specify the location or name of the macOS platform SDK to be used.
CMake uses this value to compute the value of the ``-isysroot`` flag
or equivalent and to help the ``find_*`` commands locate files in
the SDK.
:command:`project` or :command:`enable_language` command invocation
because it may influence configuration of the toolchain and flags.
It is intended to be set locally by the user creating a build tree.
+This variable should be set as a ``CACHE`` entry (or else CMake may
+remove it while initializing a cache entry of the same name).
Despite the ``OSX`` part in the variable name(s) they apply also to
other SDKs than macOS like iOS, tvOS, or watchOS.
--- /dev/null
+CMAKE_RULE_MESSAGES
+-------------------
+
+Specify whether to report a message for each make rule.
+
+If set in the cache it is used to initialize the value of the :prop_gbl:`RULE_MESSAGES` property.
+Users may disable the option in their local build tree to disable granular messages
+and report only as each target completes in Makefile builds.
CMAKE_SYSTEM_APPBUNDLE_PATH
---------------------------
-Search path for OS X application bundles used by the :command:`find_program`,
+Search path for macOS application bundles used by the :command:`find_program`,
and :command:`find_package` commands. By default it contains the standard
directories for the current system. It is *not* intended to be modified by
the project, use :variable:`CMAKE_APPBUNDLE_PATH` for this.
CMAKE_SYSTEM_FRAMEWORK_PATH
---------------------------
-Search path for OS X frameworks used by the :command:`find_library`,
+Search path for macOS frameworks used by the :command:`find_library`,
:command:`find_package`, :command:`find_path`, and :command:`find_file`
commands. By default it contains the standard directories for the
current system. It is *not* intended to be modified by the project,
This variable is the same as :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` if
you build for the host system instead of the target system when
cross compiling.
-
-* The :generator:`Green Hills MULTI` generator sets this to ``ARM`` by default.
--- /dev/null
+CMAKE_VS_GLOBALS
+----------------
+
+List of ``Key=Value`` records to be set per target as target properties
+:prop_tgt:`VS_GLOBAL_<variable>` with ``variable=Key`` and value ``Value``.
+
+For example:
+
+.. code-block:: cmake
+
+ set(CMAKE_VS_GLOBALS
+ "DefaultLanguage=en-US"
+ "MinimumVisualStudioVersion=14.0"
+ )
+
+will set properties ``VS_GLOBAL_DefaultLanguage`` to ``en-US`` and
+``VS_GLOBAL_MinimumVisualStudioVersion`` to ``14.0`` for all targets
+(except for ``INTERFACE`` libraries).
+
+This variable is meant to be set by a
+:variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>`.
--- /dev/null
+CMAKE_VS_WINRT_BY_DEFAULT
+-------------------------
+
+Tell :ref:`Visual Studio Generators` for VS 2010 and above that the
+target platform compiles as WinRT by default (compiles with ``/ZW``).
+
+This variable is meant to be set by a
+:variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>` for such platforms.
The Xcode Schema Generator is still experimental and subject to
change.
+
+The following target properties overwrite the default of the
+corresponding settings on the "Diagnostic" tab for each schema file.
+Each of those is initialized by the respective ``CMAKE_`` variable
+at target creation time.
+
+- :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER`
+- :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN`
+- :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER`
+- :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER_STOP`
+- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER`
+- :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP`
+- :prop_tgt:`XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER`
+- :prop_tgt:`XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP`
+- :prop_tgt:`XCODE_SCHEME_MALLOC_SCRIBBLE`
+- :prop_tgt:`XCODE_SCHEME_MALLOC_GUARD_EDGES`
+- :prop_tgt:`XCODE_SCHEME_GUARD_MALLOC`
+- :prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS`
+- :prop_tgt:`XCODE_SCHEME_MALLOC_STACK`
+- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE`
+- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS`
+
+The following target properties will be applied on the
+"Info" and "Arguments" tab:
+
+- :prop_tgt:`XCODE_SCHEME_EXECUTABLE`
+- :prop_tgt:`XCODE_SCHEME_ARGUMENTS`
+- :prop_tgt:`XCODE_SCHEME_ENVIRONMENT`
--- /dev/null
+CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER
+------------------------------------
+
+Whether to enable ``Address Sanitizer`` in the Diagnostics
+section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+-----------------------------------------------------
+
+Whether to enable ``Detect use of stack after return``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+----------------------------------------------
+
+Whether to disable the ``Main Thread Checker``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
+----------------------------------------
+
+Whether to enable ``Dynamic Library Loads``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+-------------------------------------------
+
+Whether to enable ``Dynamic Linker API usage``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_GUARD_MALLOC
+-------------------------------
+
+Whether to enable ``Guard Malloc``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_GUARD_MALLOC`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+-------------------------------------------
+
+Whether to enable the ``Main Thread Checker`` option
+``Pause on issues``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
+-------------------------------------
+
+Whether to enable ``Malloc Guard Edges``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_MALLOC_GUARD_EDGES`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
+----------------------------------
+
+Whether to enable ``Malloc Scribble``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_MALLOC_SCRIBBLE`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_MALLOC_STACK
+-------------------------------
+
+Whether to enable ``Malloc Stack`` in the Diagnostics
+section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_MALLOC_STACK`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_THREAD_SANITIZER
+-----------------------------------
+
+Whether to enable ``Thread Sanitizer`` in the Diagnostics
+section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP
+----------------------------------------
+
+Whether to enable ``Thread Sanitizer - Pause on issues``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER_STOP`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+------------------------------------------------
+
+Whether to enable ``Undefined Behavior Sanitizer``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+-----------------------------------------------------
+
+Whether to enable ``Undefined Behavior Sanitizer`` option
+``Pause on issues``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
--- /dev/null
+CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
+---------------------------------
+
+Whether to enable ``Zombie Objects``
+in the Diagnostics section of the generated Xcode scheme.
+
+This variable initializes the
+:prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS`
+property on all targets.
+
+Please refer to the :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable
+documentation to see all Xcode schema related properties.
ENV
---
-Access environment variables.
+Read environment variables.
-Use the syntax ``$ENV{VAR}`` to read environment variable ``VAR``. See also
-the :command:`set` command to set ``ENV{VAR}``.
+Use the syntax ``$ENV{VAR}`` to read environment variable ``VAR``.
+
+See the :command:`set` command to see how to write environment variables.
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# BundleUtilities
-# ---------------
-#
-# Functions to help assemble a standalone bundle application.
-#
-# A collection of CMake utility functions useful for dealing with .app
-# bundles on the Mac and bundle-like directories on any OS.
-#
-# The following functions are provided by this module:
-#
-# ::
-#
-# fixup_bundle
-# copy_and_fixup_bundle
-# verify_app
-# get_bundle_main_executable
-# get_dotapp_dir
-# get_bundle_and_executable
-# get_bundle_all_executables
-# get_item_key
-# get_item_rpaths
-# clear_bundle_keys
-# set_bundle_key_values
-# get_bundle_keys
-# copy_resolved_item_into_bundle
-# copy_resolved_framework_into_bundle
-# fixup_bundle_item
-# verify_bundle_prerequisites
-# verify_bundle_symlinks
-#
-# Requires CMake 2.6 or greater because it uses function, break and
-# PARENT_SCOPE. Also depends on GetPrerequisites.cmake.
-#
-# ::
-#
-# FIXUP_BUNDLE(<app> <libs> <dirs>)
-#
-# Fix up a bundle in-place and make it standalone, such that it can be
-# drag-n-drop copied to another machine and run on that machine as long
-# as all of the system libraries are compatible.
-#
-# If you pass plugins to fixup_bundle as the libs parameter, you should
-# install them or copy them into the bundle before calling fixup_bundle.
-# The "libs" parameter is a list of libraries that must be fixed up, but
-# that cannot be determined by otool output analysis. (i.e., plugins)
-#
-# Gather all the keys for all the executables and libraries in a bundle,
-# and then, for each key, copy each prerequisite into the bundle. Then
-# fix each one up according to its own list of prerequisites.
-#
-# Then clear all the keys and call verify_app on the final bundle to
-# ensure that it is truly standalone.
-#
-# As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
-# which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
-#
-# ::
-#
-# COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>)
-#
-# Makes a copy of the bundle <src> at location <dst> and then fixes up
-# the new copied bundle in-place at <dst>...
-#
-# ::
-#
-# VERIFY_APP(<app>)
-#
-# Verifies that an application <app> appears valid based on running
-# analysis tools on it. Calls "message(FATAL_ERROR" if the application
-# is not verified.
-#
-# As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
-# which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
-#
-# ::
-#
-# GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>)
-#
-# The result will be the full path name of the bundle's main executable
-# file or an "error:" prefixed string if it could not be determined.
-#
-# ::
-#
-# GET_DOTAPP_DIR(<exe> <dotapp_dir_var>)
-#
-# Returns the nearest parent dir whose name ends with ".app" given the
-# full path to an executable. If there is no such parent dir, then
-# simply return the dir containing the executable.
-#
-# The returned directory may or may not exist.
-#
-# ::
-#
-# GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>)
-#
-# Takes either a ".app" directory name or the name of an executable
-# nested inside a ".app" directory and returns the path to the ".app"
-# directory in <bundle_var> and the path to its main executable in
-# <executable_var>
-#
-# ::
-#
-# GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>)
-#
-# Scans the given bundle recursively for all executable files and
-# accumulates them into a variable.
-#
-# ::
-#
-# GET_ITEM_KEY(<item> <key_var>)
-#
-# Given a file (item) name, generate a key that should be unique
-# considering the set of libraries that need copying or fixing up to
-# make a bundle standalone. This is essentially the file name including
-# extension with "." replaced by "_"
-#
-# This key is used as a prefix for CMake variables so that we can
-# associate a set of variables with a given item based on its key.
-#
-# ::
-#
-# CLEAR_BUNDLE_KEYS(<keys_var>)
-#
-# Loop over the list of keys, clearing all the variables associated with
-# each key. After the loop, clear the list of keys itself.
-#
-# Caller of get_bundle_keys should call clear_bundle_keys when done with
-# list of keys.
-#
-# ::
-#
-# SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs>
-# <copyflag> [<rpaths>])
-#
-# Add a key to the list (if necessary) for the given item. If added,
-# also set all the variables associated with that key.
-#
-# ::
-#
-# GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>)
-#
-# Loop over all the executable and library files within the bundle (and
-# given as extra <libs>) and accumulate a list of keys representing
-# them. Set values associated with each key such that we can loop over
-# all of them and copy prerequisite libs into the bundle and then do
-# appropriate install_name_tool fixups.
-#
-# As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
-# which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
-#
-# ::
-#
-# COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
-#
-# Copy a resolved item into the bundle if necessary. Copy is not
-# necessary if the resolved_item is "the same as" the
-# resolved_embedded_item.
-#
-# ::
-#
-# COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
-#
-# Copy a resolved framework into the bundle if necessary. Copy is not
-# necessary if the resolved_item is "the same as" the
-# resolved_embedded_item.
-#
-# By default, BU_COPY_FULL_FRAMEWORK_CONTENTS is not set. If you want
-# full frameworks embedded in your bundles, set
-# BU_COPY_FULL_FRAMEWORK_CONTENTS to ON before calling fixup_bundle. By
-# default, COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework
-# dylib itself plus the framework Resources directory.
-#
-# ::
-#
-# FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>)
-#
-# Get the direct/non-system prerequisites of the resolved embedded item.
-# For each prerequisite, change the way it is referenced to the value of
-# the _EMBEDDED_ITEM keyed variable for that prerequisite. (Most likely
-# changing to an "@executable_path" style reference.)
-#
-# This function requires that the resolved_embedded_item be "inside" the
-# bundle already. In other words, if you pass plugins to fixup_bundle
-# as the libs parameter, you should install them or copy them into the
-# bundle before calling fixup_bundle. The "libs" parameter is a list of
-# libraries that must be fixed up, but that cannot be determined by
-# otool output analysis. (i.e., plugins)
-#
-# Also, change the id of the item being fixed up to its own
-# _EMBEDDED_ITEM value.
-#
-# Accumulate changes in a local variable and make *one* call to
-# install_name_tool at the end of the function with all the changes at
-# once.
-#
-# If the BU_CHMOD_BUNDLE_ITEMS variable is set then bundle items will be
-# marked writable before install_name_tool tries to change them.
-#
-# ::
-#
-# VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>)
-#
-# Verifies that the sum of all prerequisites of all files inside the
-# bundle are contained within the bundle or are "system" libraries,
-# presumed to exist everywhere.
-#
-# As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
-# which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
-#
-# ::
-#
-# VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>)
-#
-# Verifies that any symlinks found in the bundle point to other files
-# that are already also in the bundle... Anything that points to an
-# external file causes this function to fail the verification.
+#[=======================================================================[.rst:
+BundleUtilities
+---------------
+
+Functions to help assemble a standalone bundle application.
+
+A collection of CMake utility functions useful for dealing with .app
+bundles on the Mac and bundle-like directories on any OS.
+
+The following functions are provided by this module:
+
+::
+
+ fixup_bundle
+ copy_and_fixup_bundle
+ verify_app
+ get_bundle_main_executable
+ get_dotapp_dir
+ get_bundle_and_executable
+ get_bundle_all_executables
+ get_item_key
+ get_item_rpaths
+ clear_bundle_keys
+ set_bundle_key_values
+ get_bundle_keys
+ copy_resolved_item_into_bundle
+ copy_resolved_framework_into_bundle
+ fixup_bundle_item
+ verify_bundle_prerequisites
+ verify_bundle_symlinks
+
+Requires CMake 2.6 or greater because it uses function, break and
+PARENT_SCOPE. Also depends on GetPrerequisites.cmake.
+
+DO NOT USE THESE FUNCTIONS AT CONFIGURE TIME (from ``CMakeLists.txt``)!
+Instead, invoke them from an :command:`install(CODE)` or
+:command:`install(SCRIPT)` rule.
+
+::
+
+ FIXUP_BUNDLE(<app> <libs> <dirs>)
+
+Fix up a bundle in-place and make it standalone, such that it can be
+drag-n-drop copied to another machine and run on that machine as long
+as all of the system libraries are compatible.
+
+If you pass plugins to fixup_bundle as the libs parameter, you should
+install them or copy them into the bundle before calling fixup_bundle.
+The "libs" parameter is a list of libraries that must be fixed up, but
+that cannot be determined by otool output analysis. (i.e., plugins)
+
+Gather all the keys for all the executables and libraries in a bundle,
+and then, for each key, copy each prerequisite into the bundle. Then
+fix each one up according to its own list of prerequisites.
+
+Then clear all the keys and call verify_app on the final bundle to
+ensure that it is truly standalone.
+
+As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
+which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
+
+::
+
+ COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>)
+
+Makes a copy of the bundle <src> at location <dst> and then fixes up
+the new copied bundle in-place at <dst>...
+
+::
+
+ VERIFY_APP(<app>)
+
+Verifies that an application <app> appears valid based on running
+analysis tools on it. Calls "message(FATAL_ERROR" if the application
+is not verified.
+
+As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
+which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
+
+::
+
+ GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>)
+
+The result will be the full path name of the bundle's main executable
+file or an "error:" prefixed string if it could not be determined.
+
+::
+
+ GET_DOTAPP_DIR(<exe> <dotapp_dir_var>)
+
+Returns the nearest parent dir whose name ends with ".app" given the
+full path to an executable. If there is no such parent dir, then
+simply return the dir containing the executable.
+
+The returned directory may or may not exist.
+
+::
+
+ GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>)
+
+Takes either a ".app" directory name or the name of an executable
+nested inside a ".app" directory and returns the path to the ".app"
+directory in <bundle_var> and the path to its main executable in
+<executable_var>
+
+::
+
+ GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>)
+
+Scans the given bundle recursively for all executable files and
+accumulates them into a variable.
+
+::
+
+ GET_ITEM_KEY(<item> <key_var>)
+
+Given a file (item) name, generate a key that should be unique
+considering the set of libraries that need copying or fixing up to
+make a bundle standalone. This is essentially the file name including
+extension with "." replaced by "_"
+
+This key is used as a prefix for CMake variables so that we can
+associate a set of variables with a given item based on its key.
+
+::
+
+ CLEAR_BUNDLE_KEYS(<keys_var>)
+
+Loop over the list of keys, clearing all the variables associated with
+each key. After the loop, clear the list of keys itself.
+
+Caller of get_bundle_keys should call clear_bundle_keys when done with
+list of keys.
+
+::
+
+ SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs>
+ <copyflag> [<rpaths>])
+
+Add a key to the list (if necessary) for the given item. If added,
+also set all the variables associated with that key.
+
+::
+
+ GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>)
+
+Loop over all the executable and library files within the bundle (and
+given as extra <libs>) and accumulate a list of keys representing
+them. Set values associated with each key such that we can loop over
+all of them and copy prerequisite libs into the bundle and then do
+appropriate install_name_tool fixups.
+
+As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
+which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
+
+::
+
+ COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
+
+Copy a resolved item into the bundle if necessary. Copy is not
+necessary if the resolved_item is "the same as" the
+resolved_embedded_item.
+
+::
+
+ COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
+
+Copy a resolved framework into the bundle if necessary. Copy is not
+necessary if the resolved_item is "the same as" the
+resolved_embedded_item.
+
+By default, BU_COPY_FULL_FRAMEWORK_CONTENTS is not set. If you want
+full frameworks embedded in your bundles, set
+BU_COPY_FULL_FRAMEWORK_CONTENTS to ON before calling fixup_bundle. By
+default, COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework
+dylib itself plus the framework Resources directory.
+
+::
+
+ FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>)
+
+Get the direct/non-system prerequisites of the resolved embedded item.
+For each prerequisite, change the way it is referenced to the value of
+the _EMBEDDED_ITEM keyed variable for that prerequisite. (Most likely
+changing to an "@executable_path" style reference.)
+
+This function requires that the resolved_embedded_item be "inside" the
+bundle already. In other words, if you pass plugins to fixup_bundle
+as the libs parameter, you should install them or copy them into the
+bundle before calling fixup_bundle. The "libs" parameter is a list of
+libraries that must be fixed up, but that cannot be determined by
+otool output analysis. (i.e., plugins)
+
+Also, change the id of the item being fixed up to its own
+_EMBEDDED_ITEM value.
+
+Accumulate changes in a local variable and make *one* call to
+install_name_tool at the end of the function with all the changes at
+once.
+
+If the BU_CHMOD_BUNDLE_ITEMS variable is set then bundle items will be
+marked writable before install_name_tool tries to change them.
+
+::
+
+ VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>)
+
+Verifies that the sum of all prerequisites of all files inside the
+bundle are contained within the bundle or are "system" libraries,
+presumed to exist everywhere.
+
+As an optional parameter (IGNORE_ITEM) a list of file names can be passed,
+which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe")
+
+::
+
+ VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>)
+
+Verifies that any symlinks found in the bundle point to other files
+that are already also in the bundle... Anything that points to an
+external file causes this function to fail the verification.
+#]=======================================================================]
+
+function(_warn_cmp0080)
+ message(AUTHOR_WARNING
+ "Policy CMP0080 is not set: BundleUtilities prefers not to be included at configure time. "
+ "Run \"cmake --help-policy CMP0080\" for policy details. "
+ "Use the cmake_policy command to set the policy and suppress this warning."
+ )
+endfunction()
+
+# Do not include this module at configure time!
+if(DEFINED CMAKE_GENERATOR)
+ cmake_policy(GET CMP0080 _BundleUtilities_CMP0080)
+ if(_BundleUtilities_CMP0080 STREQUAL "NEW")
+ message(FATAL_ERROR "BundleUtilities cannot be included at configure time!")
+ elseif(NOT _BundleUtilities_CMP0080 STREQUAL "OLD" AND NOT _CMP0080_SUPPRESS_WARNING)
+ _warn_cmp0080()
+ endif()
+endif()
# The functions defined in this file depend on the get_prerequisites function
# (and possibly others) found in:
execute_process(
COMMAND "${otool_cmd}" -l "${item}"
OUTPUT_VARIABLE load_cmds_ov
+ RESULT_VARIABLE otool_rv
+ ERROR_VARIABLE otool_ev
)
+ if(NOT otool_rv STREQUAL "0")
+ message(FATAL_ERROR "otool -l failed: ${otool_rv}\n${otool_ev}")
+ endif()
string(REGEX REPLACE "[^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n" "rpath \\1\n" load_cmds_ov "${load_cmds_ov}")
string(REGEX MATCHALL "rpath [^\n]+" load_cmds_ov "${load_cmds_ov}")
string(REGEX REPLACE "rpath " "" load_cmds_ov "${load_cmds_ov}")
if("ASM${ASM_DIALECT}" STREQUAL "ASM") # the generic assembler support
if(NOT CMAKE_ASM_COMPILER_INIT)
if(CMAKE_C_COMPILER)
- set(CMAKE_ASM_COMPILER "${CMAKE_C_COMPILER}" CACHE FILEPATH "The ASM compiler")
- set(CMAKE_ASM_COMPILER_ID "${CMAKE_C_COMPILER_ID}")
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_LIST ${CMAKE_C_COMPILER})
elseif(CMAKE_CXX_COMPILER)
- set(CMAKE_ASM_COMPILER "${CMAKE_CXX_COMPILER}" CACHE FILEPATH "The ASM compiler")
- set(CMAKE_ASM_COMPILER_ID "${CMAKE_CXX_COMPILER_ID}")
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_LIST ${CMAKE_CXX_COMPILER})
else()
# List all default C and CXX compilers
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_LIST
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_GNU "--version")
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_GNU "(GNU assembler)|(GCC)|(Free Software Foundation)")
+ list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS Clang )
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_Clang "--version")
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_Clang "(clang version)")
+
+ list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS AppleClang )
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_AppleClang "--version")
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_AppleClang "(Apple LLVM version)")
+
list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS HP )
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_HP "-V")
set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_HP "HP C")
else()
set(id_development_team "")
endif()
+ if(DEFINED CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY)
+ set(id_code_sign_identity
+ "CODE_SIGN_IDENTITY = \"${CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY}\";")
+ else()
+ set(id_code_sign_identity "")
+ endif()
configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-3.pbxproj.in
${id_dir}/CompilerId${lang}.xcodeproj/project.pbxproj @ONLY)
unset(_ENV_MACOSX_DEPLOYMENT_TARGET)
${CMAKE_${lang}_COMPILER_ID_STRINGS_PARAMETERS}
REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
set(COMPILER_ID_TWICE)
+ # With the IAR Compiler, some strings are found twice, first time as incomplete
+ # list like "?<Constant "INFO:compiler[IAR]">". Remove the incomplete copies.
+ list(FILTER CMAKE_${lang}_COMPILER_ID_STRINGS EXCLUDE REGEX "\\?<Constant \\\"")
# In C# binaries, some strings are found more than once.
list(REMOVE_DUPLICATES CMAKE_${lang}_COMPILER_ID_STRINGS)
foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
set(_compilerExecutable "${CMAKE_C_COMPILER}")
set(_arg1 "${CMAKE_C_COMPILER_ARG1}")
endif ()
+ separate_arguments(_arg1 NATIVE_COMMAND "${_arg1}")
execute_process(COMMAND ${_compilerExecutable} ${_arg1} ${_stdver} ${_stdlib} -v -E -x ${_lang} -dD dummy
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/CMakeFiles
ERROR_VARIABLE _gccOutput
#message(STATUS "m1: -${CMAKE_MATCH_1}- m2: -${CMAKE_MATCH_2}- m3: -${CMAKE_MATCH_3}-")
list(APPEND ${_resultDefines} "${_name}")
- if(_value)
- list(APPEND ${_resultDefines} "${_value}")
- else()
+ if ("${_value}" STREQUAL "")
list(APPEND ${_resultDefines} " ")
+ else()
+ list(APPEND ${_resultDefines} "${_value}")
endif()
endforeach()
endif()
endif()
+set(_CMAKE_TOOL_VARS "")
+
# if it's the MS C/CXX compiler, search for link
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC"
OR "x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xMSVC"
find_program(CMAKE_LINKER NAMES link HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- mark_as_advanced(CMAKE_LINKER)
+ list(APPEND _CMAKE_TOOL_VARS CMAKE_LINKER)
# in all other cases search for ar, ranlib, etc.
else()
find_program(CMAKE_OBJDUMP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objdump HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
find_program(CMAKE_OBJCOPY NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objcopy HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
- mark_as_advanced(CMAKE_AR CMAKE_RANLIB CMAKE_STRIP CMAKE_LINKER CMAKE_NM CMAKE_OBJDUMP CMAKE_OBJCOPY)
+ list(APPEND _CMAKE_TOOL_VARS CMAKE_AR CMAKE_RANLIB CMAKE_STRIP CMAKE_LINKER CMAKE_NM CMAKE_OBJDUMP CMAKE_OBJCOPY)
endif()
message(FATAL_ERROR "Could not find install_name_tool, please check your installation.")
endif()
- mark_as_advanced(CMAKE_INSTALL_NAME_TOOL)
+ list(APPEND _CMAKE_TOOL_VARS CMAKE_INSTALL_NAME_TOOL)
endif()
+
+# Mark any tool cache entries as advanced.
+foreach(var IN LISTS _CMAKE_TOOL_VARS)
+ get_property(_CMAKE_TOOL_CACHED CACHE ${var} PROPERTY TYPE)
+ if(_CMAKE_TOOL_CACHED)
+ mark_as_advanced(${var})
+ endif()
+endforeach()
+unset(_CMAKE_TOOL_VARS)
+unset(_CMAKE_TOOL_CACHED)
It is designed to be used in a
:ref:`Package Configuration File <Config File Packages>`
- (``<package>Config.cmake``). ``find_dependency`` forwards the correct
+ (``<PackageName>Config.cmake``). ``find_dependency`` forwards the correct
parameters for ``QUIET`` and ``REQUIRED`` which were passed to
the original :command:`find_package` call. Any additional arguments
specified are forwarded to :command:`find_package`.
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
# Function to print messages of this module
function(_ios_install_combined_message)
# Get architectures of given SDK (iphonesimulator/iphoneos)
function(_ios_install_combined_get_valid_archs sdk resultvar)
+ cmake_policy(PUSH)
cmake_policy(SET CMP0007 NEW)
if("${resultvar}" STREQUAL "")
_ios_install_combined_message("Architectures (${sdk}): ${printable}")
set("${resultvar}" "${valid_archs}" PARENT_SCOPE)
+
+ cmake_policy(POP)
endfunction()
# Final target can contain more architectures that specified by SDK. This
endfunction()
function(_ios_install_combined_detect_sdks this_sdk_var corr_sdk_var)
- cmake_policy(SET CMP0057 NEW)
-
set(this_sdk "$ENV{PLATFORM_NAME}")
if("${this_sdk}" STREQUAL "")
message(FATAL_ERROR "Environment variable PLATFORM_NAME is empty")
_ios_install_combined_message("Install done: ${destination}")
endfunction()
+
+cmake_policy(POP)
# )
#
# ``configure_package_config_file()`` should be used instead of the plain
-# :command:`configure_file()` command when creating the ``<Name>Config.cmake``
-# or ``<Name>-config.cmake`` file for installing a project or library. It helps
-# making the resulting package relocatable by avoiding hardcoded paths in the
-# installed ``Config.cmake`` file.
+# :command:`configure_file()` command when creating the ``<PackageName>Config.cmake``
+# or ``<PackageName>-config.cmake`` file for installing a project or library.
+# It helps making the resulting package relocatable by avoiding hardcoded paths
+# in the installed ``Config.cmake`` file.
#
# In a ``FooConfig.cmake`` file there may be code like this to make the install
# destinations know to the using project:
# When using the ``NO_SET_AND_CHECK_MACRO``, this macro is not generated
# into the ``FooConfig.cmake`` file.
#
-# ``check_required_components(<package_name>)`` should be called at the end of
+# ``check_required_components(<PackageName>)`` should be called at the end of
# the ``FooConfig.cmake`` file. This macro checks whether all requested,
# non-optional components have been found, and if this is not the case, sets
# the ``Foo_FOUND`` variable to ``FALSE``, so that the package is considered to
# COMPATIBILITY <AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion> )
#
#
-# Writes a file for use as ``<package>ConfigVersion.cmake`` file to
+# Writes a file for use as ``<PackageName>ConfigVersion.cmake`` file to
# ``<filename>``. See the documentation of :command:`find_package()` for
# details on this.
#
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+cmake_policy(PUSH)
+cmake_policy(SET CMP0053 NEW)
+cmake_policy(SET CMP0054 NEW)
# Function parse implicit linker options.
# This is used internally by CMake and should not be included by user
set(${fwk_var} "${implicit_fwks}" PARENT_SCOPE)
set(${log_var} "${log}" PARENT_SCOPE)
endfunction()
+
+cmake_policy(POP)
:command:`install_programs` and :command:`install_targets` commands).
For certain kinds of binary installers (including the graphical
-installers on Mac OS X and Windows), CPack generates installers that
+installers on macOS and Windows), CPack generates installers that
allow users to select individual application components to install.
See :module:`CPackComponent` module for further details.
+++ /dev/null
-# 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_<component>_FILE_NAME
-#
-# Package file name without extension which is added automatically depending
-# on the archive format.
-#
-# * Mandatory : YES
-# * Default : ``<CPACK_PACKAGE_FILE_NAME>[-<component>].<extension>`` 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.
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#.rst:
-# CPackBundle
-# -----------
-#
-# CPack Bundle generator (Mac OS X) specific options
-#
-# Variables specific to CPack Bundle generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# Installers built on Mac OS X using the Bundle generator use the
-# aforementioned DragNDrop (CPACK_DMG_xxx) variables, plus the following
-# Bundle-specific parameters (CPACK_BUNDLE_xxx).
-#
-# .. variable:: CPACK_BUNDLE_NAME
-#
-# The name of the generated bundle. This appears in the OSX finder as the
-# bundle name. Required.
-#
-# .. variable:: CPACK_BUNDLE_PLIST
-#
-# Path to an OSX plist file that will be used for the generated bundle. This
-# assumes that the caller has generated or specified their own Info.plist
-# file. Required.
-#
-# .. variable:: CPACK_BUNDLE_ICON
-#
-# Path to an OSX icon file that will be used as the icon for the generated
-# bundle. This is the icon that appears in the OSX finder for the bundle, and
-# in the OSX dock when the bundle is opened. Required.
-#
-# .. variable:: CPACK_BUNDLE_STARTUP_COMMAND
-#
-# Path to a startup script. This is a path to an executable or script that
-# will be run whenever an end-user double-clicks the generated bundle in the
-# OSX Finder. Optional.
-#
-# .. variable:: CPACK_BUNDLE_APPLE_CERT_APP
-#
-# The name of your Apple supplied code signing certificate for the application.
-# The name usually takes the form "Developer ID Application: [Name]" or
-# "3rd Party Mac Developer Application: [Name]". If this variable is not set
-# the application will not be signed.
-#
-# .. variable:: CPACK_BUNDLE_APPLE_ENTITLEMENTS
-#
-# The name of the plist file that contains your apple entitlements for sandboxing
-# your application. This file is required for submission to the Mac App Store.
-#
-# .. variable:: CPACK_BUNDLE_APPLE_CODESIGN_FILES
-#
-# A list of additional files that you wish to be signed. You do not need to
-# list the main application folder, or the main executable. You should
-# list any frameworks and plugins that are included in your app bundle.
-#
-# .. variable:: CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER
-#
-# Additional parameter that will passed to codesign.
-# Default value: "--deep -f"
-#
-# .. variable:: CPACK_COMMAND_CODESIGN
-#
-# Path to the codesign(1) command used to sign applications with an
-# Apple cert. This variable can be used to override the automatically
-# detected command (or specify its location if the auto-detection fails
-# to find it.)
-
-#Bundle Generator specific code should be put here
# part of CPack. See CPack module for general information about CPack.
#
# For certain kinds of binary installers (including the graphical
-# installers on Mac OS X and Windows), CPack generates installers that
+# installers on macOS and Windows), CPack generates installers that
# allow users to select individual application components to install.
# The contents of each of the components are identified by the COMPONENT
# argument of CMake's INSTALL command. These components can be
#
#
#
-# On Mac OS X, installers that download components on-the-fly can only
-# be built and installed on system using Mac OS X 10.5 or later.
+# On macOS, installers that download components on-the-fly can only
+# be built and installed on system using macOS 10.5 or later.
#
# The site argument is a URL where the archives for downloadable
# components will reside, e.g.,
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#.rst:
-# CPackCygwin
-# -----------
-#
-# Cygwin CPack generator (Cygwin).
-#
-# Variables specific to CPack Cygwin generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The
-# following variable is specific to installers build on and/or for
-# Cygwin:
-#
-# .. variable:: CPACK_CYGWIN_PATCH_NUMBER
-#
-# The Cygwin patch number. FIXME: This documentation is incomplete.
-#
-# .. variable:: CPACK_CYGWIN_PATCH_FILE
-#
-# The Cygwin patch file. FIXME: This documentation is incomplete.
-#
-# .. variable:: CPACK_CYGWIN_BUILD_SCRIPT
-#
-# The Cygwin build script. FIXME: This documentation is incomplete.
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#.rst:
-# CPackDMG
-# --------
-#
-# DragNDrop CPack generator (Mac OS X).
-#
-# Variables specific to CPack DragNDrop generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The following variables are specific to the DragNDrop installers built
-# on Mac OS X:
-#
-# .. variable:: CPACK_DMG_VOLUME_NAME
-#
-# The volume name of the generated disk image. Defaults to
-# CPACK_PACKAGE_FILE_NAME.
-#
-# .. variable:: CPACK_DMG_FORMAT
-#
-# The disk image format. Common values are UDRO (UDIF read-only), UDZO (UDIF
-# zlib-compressed) or UDBZ (UDIF bzip2-compressed). Refer to hdiutil(1) for
-# more information on other available formats. Defaults to UDZO.
-#
-# .. variable:: CPACK_DMG_DS_STORE
-#
-# Path to a custom DS_Store file. This .DS_Store file e.g. can be used to
-# specify the Finder window position/geometry and layout (such as hidden
-# toolbars, placement of the icons etc.). This file has to be generated by
-# the Finder (either manually or through AppleScript) using a normal folder
-# from which the .DS_Store file can then be extracted.
-#
-# .. variable:: CPACK_DMG_DS_STORE_SETUP_SCRIPT
-#
-# Path to a custom AppleScript file. This AppleScript is used to generate
-# a .DS_Store file which specifies the Finder window position/geometry and
-# layout (such as hidden toolbars, placement of the icons etc.).
-# By specifying a custom AppleScript there is no need to use
-# CPACK_DMG_DS_STORE, as the .DS_Store that is generated by the AppleScript
-# will be packaged.
-#
-# .. variable:: CPACK_DMG_BACKGROUND_IMAGE
-#
-# Path to an image file to be used as the background. This file will be
-# copied to .background/background.<ext>, where ext is the original image file
-# extension. The background image is installed into the image before
-# CPACK_DMG_DS_STORE_SETUP_SCRIPT is executed or CPACK_DMG_DS_STORE is
-# installed. By default no background image is set.
-#
-# .. variable:: CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK
-#
-# Default behaviour is to include a symlink to ``/Applications`` in the DMG.
-# Set this option to ``ON`` to avoid adding the symlink.
-#
-# .. variable:: CPACK_DMG_SLA_DIR
-#
-# Directory where license and menu files for different languages are stored.
-# Setting this causes CPack to look for a ``<language>.menu.txt`` and
-# ``<language>.license.txt`` file for every language defined in
-# ``CPACK_DMG_SLA_LANGUAGES``. If both this variable and
-# ``CPACK_RESOURCE_FILE_LICENSE`` are set, CPack will only look for the menu
-# files and use the same license file for all languages.
-#
-# .. variable:: CPACK_DMG_SLA_LANGUAGES
-#
-# Languages for which a license agreement is provided when mounting the
-# generated DMG. A menu file consists of 9 lines of text. The first line is
-# is the name of the language itself, uppercase, in English (e.g. German).
-# The other lines are translations of the following strings:
-#
-# - Agree
-# - Disagree
-# - Print
-# - Save...
-# - You agree to the terms of the License Agreement when you click the
-# "Agree" button.
-# - Software License Agreement
-# - This text cannot be saved. The disk may be full or locked, or the file
-# may be locked.
-# - Unable to print. Make sure you have selected a printer.
-#
-# For every language in this list, CPack will try to find files
-# ``<language>.menu.txt`` and ``<language>.license.txt`` in the directory
-# specified by the :variable:`CPACK_DMG_SLA_DIR` variable.
-#
-# .. variable:: CPACK_COMMAND_HDIUTIL
-#
-# Path to the hdiutil(1) command used to operate on disk image files on Mac
-# OS X. This variable can be used to override the automatically detected
-# command (or specify its location if the auto-detection fails to find it.)
-#
-# .. variable:: CPACK_COMMAND_SETFILE
-#
-# Path to the SetFile(1) command used to set extended attributes on files and
-# directories on Mac OS X. This variable can be used to override the
-# automatically detected command (or specify its location if the
-# auto-detection fails to find it.)
-#
-# .. variable:: CPACK_COMMAND_REZ
-#
-# Path to the Rez(1) command used to compile resources on Mac OS X. This
-# variable can be used to override the automatically detected command (or
-# specify its location if the auto-detection fails to find it.)
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#[=======================================================================[.rst:
-CPackFreeBSD
-------------
-
-The built in (binary) CPack FreeBSD (pkg) generator (Unix only)
-
-Variables specific to CPack FreeBSD (pkg) generator
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-CPackFreeBSD may be used to create pkg(8) packages -- these may be used
-on FreeBSD, DragonflyBSD, NetBSD, OpenBSD, but also on Linux or OSX,
-depending on the installed package-management tools -- using :module:`CPack`.
-
-CPackFreeBSD is a :module:`CPack` generator and uses the ``CPACK_XXX``
-variables used by :module:`CPack`. It tries to re-use packaging information
-that may already be specified for Debian packages for the :module:`CPackDeb`
-generator. it also tries to re-use RPM packaging information when Debian
-does not specify.
-
-CPackFreeBSD generator should work on any host with libpkg installed. The
-packages it produces are specific to the host architecture and ABI.
-
-CPackFreeBSD sets package-metadata through :code:`CPACK_FREEBSD_XXX` variables.
-CPackFreeBSD, unlike CPackDeb, does not specially support componentized
-packages; a single package is created from all the software artifacts
-created through CMake.
-
-All of the variables can be set specifically for FreeBSD packaging in
-the CPackConfig file or in CMakeLists.txt, but most of them have defaults
-that use general settings (e.g. CMAKE_PROJECT_NAME) or Debian-specific
-variables when those make sense (e.g. the homepage of an upstream project
-is usually unchanged by the flavor of packaging). When there is no Debian
-information to fall back on, but the RPM packaging has it, fall back to
-the RPM information (e.g. package license).
-
-.. variable:: CPACK_FREEBSD_PACKAGE_NAME
-
- Sets the package name (in the package manifest, but also affects the
- output filename).
-
- * Mandatory: YES
- * Default:
-
- - :variable:`CPACK_PACKAGE_NAME` (this is always set by CPack itself,
- based on CMAKE_PROJECT_NAME).
-
-.. variable:: CPACK_FREEBSD_PACKAGE_COMMENT
-
- Sets the package comment. This is the short description displayed by
- pkg(8) in standard "pkg info" output.
-
- * Mandatory: YES
- * Default:
-
- - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set
- by CPack itself, if nothing else sets it explicitly).
- - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION
- parameter for :command:`project`).
-
-.. variable:: CPACK_FREEBSD_PACKAGE_DESCRIPTION
-
- Sets the package description. This is the long description of the package,
- given by "pkg info" with a specific package as argument.
-
- * Mandatory: YES
- * Default:
-
- - :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` (this may be set already
- for Debian packaging, so we may as well re-use it).
-
-.. variable:: CPACK_FREEBSD_PACKAGE_WWW
-
- The URL of the web site for this package, preferably (when applicable) the
- site from which the original source can be obtained and any additional
- upstream documentation or information may be found.
-
- * Mandatory: YES
- * Default:
-
- - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set,
- :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
- for Debian packaging, so we may as well re-use it).
-
-.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE
-
- The license, or licenses, which apply to this software package. This must
- be one or more license-identifiers that pkg recognizes as acceptable license
- identifiers (e.g. "GPLv2").
-
- * Mandatory: YES
- * Default:
-
- - :variable:`CPACK_RPM_PACKAGE_LICENSE`
-
-.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE_LOGIC
-
- This variable is only of importance if there is more than one license.
- The default is "single", which is only applicable to a single license.
- Other acceptable values are determined by pkg -- those are "dual" or "multi" --
- meaning choice (OR) or simultaneous (AND) application of the licenses.
-
- * Mandatory: NO
- * Default: single
-
-.. variable:: CPACK_FREEBSD_PACKAGE_MAINTAINER
-
- The FreeBSD maintainer (e.g. kde@freebsd.org) of this package.
-
- * Mandatory: YES
- * Default: none
-
-.. variable:: CPACK_FREEBSD_PACKAGE_ORIGIN
-
- The origin (ports label) of this package; for packages built by CPack
- outside of the ports system this is of less importance. The default
- puts the package somewhere under misc/, as a stopgap.
-
- * Mandatory: YES
- * Default: misc/<package name>
-
-.. variable:: CPACK_FREEBSD_PACKAGE_CATEGORIES
-
- The ports categories where this package lives (if it were to be built
- from ports). If none is set a single category is determined based on
- the package origin.
-
- * Mandatory: YES
- * Default: derived from ORIGIN
-
-.. variable:: CPACK_FREEBSD_PACKAGE_DEPS
-
- A list of package origins that should be added as package dependencies.
- These are in the form <category>/<packagename>, e.g. x11/libkonq.
- No version information needs to be provided (this is not included
- in the manifest).
-
- * Mandatory: NO
- * Default: empty
-#]=======================================================================]
-
-
-
-if(CMAKE_BINARY_DIR)
- message(FATAL_ERROR "CPackFreeBSD.cmake may only be used by CPack internally.")
-endif()
-
-if(NOT UNIX)
- message(FATAL_ERROR "CPackFreeBSD.cmake may only be used under UNIX.")
-endif()
-
-
-###
-#
-# These bits are copied from the Debian packaging file; slightly modified.
-# They are used for filling in FreeBSD-packaging variables that can take
-# on values from elsewhere -- e.g. the package description may as well be
-# copied from Debian.
-#
-function(_cpack_freebsd_fallback_var OUTPUT_VAR_NAME)
- set(FALLBACK_VAR_NAMES ${ARGN})
-
- set(VALUE "${${OUTPUT_VAR_NAME}}")
- if(VALUE)
- return()
- endif()
-
- foreach(variable_name IN LISTS FALLBACK_VAR_NAMES)
- if(${variable_name})
- set(${OUTPUT_VAR_NAME} "${${variable_name}}" PARENT_SCOPE)
- set(VALUE "${${variable_name}}")
- break()
- endif()
- endforeach()
- if(NOT VALUE)
- message(WARNING "Variable ${OUTPUT_VAR_NAME} could not be given a fallback value from any variable ${FALLBACK_VAR_NAMES}.")
- endif()
-endfunction()
-
-function(check_required_var VAR_NAME)
- if(NOT ${VAR_NAME})
- message(FATAL_ERROR "Variable ${VAR_NAME} is not set.")
- endif()
-endfunction()
-
-set(_cpack_freebsd_fallback_origin "misc/bogus")
-
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_NAME"
- "CPACK_PACKAGE_NAME"
- "CMAKE_PROJECT_NAME"
- )
-
-set(_cpack_freebsd_fallback_www "http://example.com/?pkg=${CPACK_FREEBSD_PACKAGE_NAME}")
-
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_COMMENT"
- "CPACK_PACKAGE_DESCRIPTION_SUMMARY"
- )
-
-# TODO: maybe read the PACKAGE_DESCRIPTION file for the longer
-# FreeBSD pkg-descr?
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_DESCRIPTION"
- "CPACK_DEBIAN_PACKAGE_DESCRIPTION"
- "CPACK_PACKAGE_DESCRIPTION_SUMMARY"
- "PACKAGE_DESCRIPTION"
- )
-
-# There's really only one homepage for a project, so
-# re-use the Debian setting if it's there.
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_WWW"
- "CMAKE_PROJECT_HOMEPAGE_URL"
- "CPACK_DEBIAN_PACKAGE_HOMEPAGE"
- "_cpack_freebsd_fallback_www"
- )
-
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_VERSION"
- "CMAKE_PROJECT_VERSION"
- "${CMAKE_PROJECT_NAME}_VERSION"
- "PROJECT_VERSION"
- "CPACK_PACKAGE_VERSION"
- "CPACK_PACKAGE_VERSION"
- )
-
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_MAINTAINER"
- "CPACK_PACKAGE_CONTACT"
- )
-
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_LICENSE"
- "CPACK_RPM_PACKAGE_LICENSE"
- )
-
-_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_ORIGIN"
- "_cpack_freebsd_fallback_origin"
- )
-
-if(NOT CPACK_FREEBSD_PACKAGE_CATEGORIES)
- string(REGEX REPLACE "/.*" "" CPACK_FREEBSD_PACKAGE_CATEGORIES ${CPACK_FREEBSD_PACKAGE_ORIGIN})
-endif()
-
-check_required_var("CPACK_FREEBSD_PACKAGE_NAME")
-check_required_var("CPACK_FREEBSD_PACKAGE_ORIGIN")
-check_required_var("CPACK_FREEBSD_PACKAGE_VERSION")
-check_required_var("CPACK_FREEBSD_PACKAGE_MAINTAINER")
-check_required_var("CPACK_FREEBSD_PACKAGE_COMMENT")
-check_required_var("CPACK_FREEBSD_PACKAGE_DESCRIPTION")
-check_required_var("CPACK_FREEBSD_PACKAGE_WWW")
-check_required_var("CPACK_FREEBSD_PACKAGE_LICENSE")
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# CPackIFW
-# --------
-#
-# .. _QtIFW: http://doc.qt.io/qtinstallerframework/index.html
-#
-# This module looks for the location of the command line utilities supplied
-# with the Qt Installer Framework (QtIFW_).
-#
-# The module also defines several commands to control the behavior of the
-# CPack ``IFW`` generator.
-#
-#
-# Overview
-# ^^^^^^^^
-#
-# CPack ``IFW`` generator helps you to create online and offline
-# binary cross-platform installers with a graphical user interface.
-#
-# CPack IFW generator prepares project installation and generates configuration
-# and meta information for QtIFW_ tools.
-#
-# The QtIFW_ provides a set of tools and utilities to create
-# installers for the supported desktop Qt platforms: Linux, Microsoft Windows,
-# and Mac OS X.
-#
-# You should also install QtIFW_ to use CPack ``IFW`` generator.
-#
-# 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
-# ^^^^^^^^^
-#
-# You can use the following variables to change behavior of CPack ``IFW``
-# generator.
-#
-# Debug
-# """"""
-#
-# .. variable:: CPACK_IFW_VERBOSE
-#
-# Set to ``ON`` to enable addition debug output.
-# By default is ``OFF``.
-#
-# Package
-# """""""
-#
-# .. variable:: CPACK_IFW_PACKAGE_TITLE
-#
-# Name of the installer as displayed on the title bar.
-# By default used :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`.
-#
-# .. variable:: CPACK_IFW_PACKAGE_PUBLISHER
-#
-# Publisher of the software (as shown in the Windows Control Panel).
-# By default used :variable:`CPACK_PACKAGE_VENDOR`.
-#
-# .. variable:: CPACK_IFW_PRODUCT_URL
-#
-# URL to a page that contains product information on your web site.
-#
-# .. variable:: CPACK_IFW_PACKAGE_ICON
-#
-# Filename for a custom installer icon. The actual file is '.icns' (Mac OS X),
-# '.ico' (Windows). No functionality on Unix.
-#
-# .. variable:: CPACK_IFW_PACKAGE_WINDOW_ICON
-#
-# Filename for a custom window icon in PNG format for the Installer
-# application.
-#
-# .. variable:: CPACK_IFW_PACKAGE_LOGO
-#
-# Filename for a logo is used as QWizard::LogoPixmap.
-#
-# .. variable:: CPACK_IFW_PACKAGE_WATERMARK
-#
-# Filename for a watermark is used as QWizard::WatermarkPixmap.
-#
-# .. variable:: CPACK_IFW_PACKAGE_BANNER
-#
-# Filename for a banner is used as QWizard::BannerPixmap.
-#
-# .. variable:: CPACK_IFW_PACKAGE_BACKGROUND
-#
-# Filename for an image used as QWizard::BackgroundPixmap (only used by MacStyle).
-#
-# .. variable:: CPACK_IFW_PACKAGE_WIZARD_STYLE
-#
-# Wizard style to be used ("Modern", "Mac", "Aero" or "Classic").
-#
-# .. variable:: CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH
-#
-# Default width of the wizard in pixels. Setting a banner image will override this.
-#
-# .. variable:: CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT
-#
-# Default height of the wizard in pixels. Setting a watermark image will override this.
-#
-# .. variable:: CPACK_IFW_PACKAGE_TITLE_COLOR
-#
-# Color of the titles and subtitles (takes an HTML color code, such as "#88FF33").
-#
-# .. variable:: CPACK_IFW_PACKAGE_START_MENU_DIRECTORY
-#
-# Name of the default program group for the product in the Windows Start menu.
-#
-# By default used :variable:`CPACK_IFW_PACKAGE_NAME`.
-#
-# .. variable:: CPACK_IFW_TARGET_DIRECTORY
-#
-# Default target directory for installation.
-# By default used
-# "@ApplicationsDir@/:variable:`CPACK_PACKAGE_INSTALL_DIRECTORY`"
-#
-# You can use predefined variables.
-#
-# .. variable:: CPACK_IFW_ADMIN_TARGET_DIRECTORY
-#
-# Default target directory for installation with administrator rights.
-#
-# You can use predefined variables.
-#
-# .. variable:: CPACK_IFW_PACKAGE_GROUP
-#
-# The group, which will be used to configure the root package
-#
-# .. variable:: CPACK_IFW_PACKAGE_NAME
-#
-# The root package name, which will be used if configuration group is not
-# specified
-#
-# .. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME
-#
-# Filename of the generated maintenance tool.
-# The platform-specific executable file extension is appended.
-#
-# By default used QtIFW_ defaults (``maintenancetool``).
-#
-# .. variable:: CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR
-#
-# Set to ``OFF`` if the target directory should not be deleted when uninstalling.
-#
-# Is ``ON`` by default
-#
-# .. variable:: CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE
-#
-# Filename for the configuration of the generated maintenance tool.
-#
-# By default used QtIFW_ defaults (``maintenancetool.ini``).
-#
-# .. variable:: CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS
-#
-# Set to ``ON`` if the installation path can contain non-ASCII characters.
-#
-# Is ``ON`` for QtIFW_ less 2.0 tools.
-#
-# .. variable:: CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH
-#
-# Set to ``OFF`` if the installation path cannot contain space characters.
-#
-# Is ``ON`` for QtIFW_ less 2.0 tools.
-#
-# .. variable:: CPACK_IFW_PACKAGE_CONTROL_SCRIPT
-#
-# Filename for a custom installer control script.
-#
-# .. variable:: CPACK_IFW_PACKAGE_RESOURCES
-#
-# List of additional resources ('.qrc' files) to include in the installer
-# binary.
-#
-# You can use :command:`cpack_ifw_add_package_resources` command to resolve
-# relative paths.
-#
-# .. variable:: CPACK_IFW_PACKAGE_FILE_EXTENSION
-#
-# The target binary extension.
-#
-# On Linux, the name of the target binary is automatically extended with
-# '.run', if you do not specify the extension.
-#
-# On Windows, the target is created as an application with the extension
-# '.exe', which is automatically added, if not supplied.
-#
-# On Mac, the target is created as an DMG disk image with the extension
-# '.dmg', which is automatically added, if not supplied.
-#
-# .. variable:: CPACK_IFW_REPOSITORIES_ALL
-#
-# The list of remote repositories.
-#
-# The default value of this variable is computed by CPack and contains
-# all repositories added with command :command:`cpack_ifw_add_repository`
-# or updated with command :command:`cpack_ifw_update_repository`.
-#
-# .. variable:: CPACK_IFW_DOWNLOAD_ALL
-#
-# If this is ``ON`` all components will be downloaded.
-# By default is ``OFF`` or used value
-# from ``CPACK_DOWNLOAD_ALL`` if set
-#
-# Components
-# """"""""""
-#
-# .. variable:: CPACK_IFW_RESOLVE_DUPLICATE_NAMES
-#
-# Resolve duplicate names when installing components with groups.
-#
-# .. variable:: CPACK_IFW_PACKAGES_DIRECTORIES
-#
-# Additional prepared packages dirs that will be used to resolve
-# dependent components.
-#
-# .. variable:: CPACK_IFW_REPOSITORIES_DIRECTORIES
-#
-# Additional prepared repository dirs that will be used to resolve and
-# repack dependent components. This feature available only
-# since QtIFW_ 3.1.
-#
-# Tools
-# """""
-#
-# .. variable:: CPACK_IFW_FRAMEWORK_VERSION
-#
-# The version of used QtIFW_ tools.
-#
-# .. variable:: CPACK_IFW_BINARYCREATOR_EXECUTABLE
-#
-# The path to "binarycreator" command line client.
-#
-# 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 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
-# ^^^^^^^^^
-#
-# The module defines the following commands:
-#
-# .. command:: cpack_ifw_configure_component
-#
-# Sets the arguments specific to the CPack IFW generator.
-#
-# ::
-#
-# cpack_ifw_configure_component(<compname> [COMMON] [ESSENTIAL] [VIRTUAL]
-# [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS]
-# [NAME <name>]
-# [DISPLAY_NAME <display_name>] # Note: Internationalization supported
-# [DESCRIPTION <description>] # Note: Internationalization supported
-# [UPDATE_TEXT <update_text>]
-# [VERSION <version>]
-# [RELEASE_DATE <release_date>]
-# [SCRIPT <script>]
-# [PRIORITY|SORTING_PRIORITY <sorting_priority>] # Note: PRIORITY is deprecated
-# [DEPENDS|DEPENDENCIES <com_id> ...]
-# [AUTO_DEPEND_ON <comp_id> ...]
-# [LICENSES <display_name> <file_path> ...]
-# [DEFAULT <value>]
-# [USER_INTERFACES <file_path> <file_path> ...]
-# [TRANSLATIONS <file_path> <file_path> ...]
-# [REPLACES <comp_id> ...]
-# [CHECKABLE <value>])
-#
-# This command should be called after :command:`cpack_add_component` command.
-#
-# ``COMMON``
-# if set, then the component will be packaged and installed as part
-# of a group to which it belongs.
-#
-# ``ESSENTIAL``
-# if set, then the package manager stays disabled until that
-# component is updated.
-#
-# ``VIRTUAL``
-# if set, then the component will be hidden from the installer.
-# It is a equivalent of the ``HIDDEN`` option from the
-# :command:`cpack_add_component` command.
-#
-# ``FORCED_INSTALLATION``
-# if set, then the component must always be installed.
-# It is a equivalent of the ``REQUARED`` option from the
-# :command:`cpack_add_component` command.
-#
-# ``REQUIRES_ADMIN_RIGHTS``
-# set it if the component needs to be installed with elevated permissions.
-#
-# ``NAME``
-# is used to create domain-like identification for this component.
-# By default used origin component name.
-#
-# ``DISPLAY_NAME``
-# set to rewrite original name configured by
-# :command:`cpack_add_component` command.
-#
-# ``DESCRIPTION``
-# set to rewrite original description configured by
-# :command:`cpack_add_component` command.
-#
-# ``UPDATE_TEXT``
-# will be added to the component description if this is an update to
-# the component.
-#
-# ``VERSION``
-# is version of component.
-# By default used :variable:`CPACK_PACKAGE_VERSION`.
-#
-# ``RELEASE_DATE``
-# keep empty to auto generate.
-#
-# ``SCRIPT``
-# is a relative or absolute path to operations script
-# for this component.
-#
-# ``PRIORITY`` | ``SORTING_PRIORITY``
-# is priority of the component in the tree.
-# The ``PRIORITY`` option is deprecated and will be removed in a future
-# version of CMake. Please use ``SORTING_PRIORITY`` option instead.
-#
-# ``DEPENDS`` | ``DEPENDENCIES``
-# list of dependency component or component group identifiers in
-# QtIFW_ style.
-#
-# ``AUTO_DEPEND_ON``
-# list of identifiers of component or component group in QtIFW_ style
-# that this component has an automatic dependency on.
-#
-# ``LICENSES``
-# pair of <display_name> and <file_path> of license text for this
-# component. You can specify more then one license.
-#
-# ``DEFAULT``
-# Possible values are: TRUE, FALSE, and SCRIPT.
-# Set to FALSE to disable the component in the installer or to SCRIPT
-# to resolved during runtime (don't forget add the file of the script
-# as a value of the ``SCRIPT`` option).
-#
-# ``USER_INTERFACES``
-# is a list of <file_path> ('.ui' files) representing pages to load.
-#
-# ``TRANSLATIONS``
-# is a list of <file_path> ('.qm' files) representing translations to load.
-#
-# ``REPLACES``
-# list of identifiers of component or component group to replace.
-#
-# ``CHECKABLE``
-# Possible values are: TRUE, FALSE.
-# Set to FALSE if you want to hide the checkbox for an item.
-# This is useful when only a few subcomponents should be selected
-# instead of all.
-#
-#
-# .. command:: cpack_ifw_configure_component_group
-#
-# Sets the arguments specific to the CPack IFW generator.
-#
-# ::
-#
-# cpack_ifw_configure_component_group(<groupname> [VIRTUAL]
-# [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS]
-# [NAME <name>]
-# [DISPLAY_NAME <display_name>] # Note: Internationalization supported
-# [DESCRIPTION <description>] # Note: Internationalization supported
-# [UPDATE_TEXT <update_text>]
-# [VERSION <version>]
-# [RELEASE_DATE <release_date>]
-# [SCRIPT <script>]
-# [PRIORITY|SORTING_PRIORITY <sorting_priority>] # Note: PRIORITY is deprecated
-# [DEPENDS|DEPENDENCIES <com_id> ...]
-# [AUTO_DEPEND_ON <comp_id> ...]
-# [LICENSES <display_name> <file_path> ...]
-# [DEFAULT <value>]
-# [USER_INTERFACES <file_path> <file_path> ...]
-# [TRANSLATIONS <file_path> <file_path> ...]
-# [REPLACES <comp_id> ...]
-# [CHECKABLE <value>])
-#
-# This command should be called after :command:`cpack_add_component_group`
-# command.
-#
-# ``VIRTUAL``
-# if set, then the group will be hidden from the installer.
-# Note that setting this on a root component does not work.
-#
-# ``FORCED_INSTALLATION``
-# if set, then the group must always be installed.
-#
-# ``REQUIRES_ADMIN_RIGHTS``
-# set it if the component group needs to be installed with elevated
-# permissions.
-#
-# ``NAME``
-# is used to create domain-like identification for this component group.
-# By default used origin component group name.
-#
-# ``DISPLAY_NAME``
-# set to rewrite original name configured by
-# :command:`cpack_add_component_group` command.
-#
-# ``DESCRIPTION``
-# set to rewrite original description configured by
-# :command:`cpack_add_component_group` command.
-#
-# ``UPDATE_TEXT``
-# will be added to the component group description if this is an update to
-# the component group.
-#
-# ``VERSION``
-# is version of component group.
-# By default used :variable:`CPACK_PACKAGE_VERSION`.
-#
-# ``RELEASE_DATE``
-# keep empty to auto generate.
-#
-# ``SCRIPT``
-# is a relative or absolute path to operations script
-# for this component group.
-#
-# ``PRIORITY`` | ``SORTING_PRIORITY``
-# is priority of the component group in the tree.
-# The ``PRIORITY`` option is deprecated and will be removed in a future
-# version of CMake. Please use ``SORTING_PRIORITY`` option instead.
-#
-# ``DEPENDS`` | ``DEPENDENCIES``
-# list of dependency component or component group identifiers in
-# QtIFW_ style.
-#
-# ``AUTO_DEPEND_ON``
-# list of identifiers of component or component group in QtIFW_ style
-# that this component group has an automatic dependency on.
-#
-# ``LICENSES``
-# pair of <display_name> and <file_path> of license text for this
-# component group. You can specify more then one license.
-#
-# ``DEFAULT``
-# Possible values are: TRUE, FALSE, and SCRIPT.
-# Set to TRUE to preselect the group in the installer
-# (this takes effect only on groups that have no visible child components)
-# or to SCRIPT to resolved during runtime (don't forget add the file of
-# the script as a value of the ``SCRIPT`` option).
-#
-# ``USER_INTERFACES``
-# is a list of <file_path> ('.ui' files) representing pages to load.
-#
-# ``TRANSLATIONS``
-# is a list of <file_path> ('.qm' files) representing translations to load.
-#
-# ``REPLACES``
-# list of identifiers of component or component group to replace.
-#
-# ``CHECKABLE``
-# Possible values are: TRUE, FALSE.
-# Set to FALSE if you want to hide the checkbox for an item.
-# This is useful when only a few subcomponents should be selected
-# instead of all.
-#
-#
-# .. command:: cpack_ifw_add_repository
-#
-# Add QtIFW_ specific remote repository to binary installer.
-#
-# ::
-#
-# cpack_ifw_add_repository(<reponame> [DISABLED]
-# URL <url>
-# [USERNAME <username>]
-# [PASSWORD <password>]
-# [DISPLAY_NAME <display_name>])
-#
-# This command will also add the <reponame> repository
-# to a variable :variable:`CPACK_IFW_REPOSITORIES_ALL`.
-#
-# ``DISABLED``
-# if set, then the repository will be disabled by default.
-#
-# ``URL``
-# is points to a list of available components.
-#
-# ``USERNAME``
-# is used as user on a protected repository.
-#
-# ``PASSWORD``
-# is password to use on a protected repository.
-#
-# ``DISPLAY_NAME``
-# is string to display instead of the URL.
-#
-#
-# .. command:: cpack_ifw_update_repository
-#
-# Update QtIFW_ specific repository from remote repository.
-#
-# ::
-#
-# cpack_ifw_update_repository(<reponame>
-# [[ADD|REMOVE] URL <url>]|
-# [REPLACE OLD_URL <old_url> NEW_URL <new_url>]]
-# [USERNAME <username>]
-# [PASSWORD <password>]
-# [DISPLAY_NAME <display_name>])
-#
-# This command will also add the <reponame> repository
-# to a variable :variable:`CPACK_IFW_REPOSITORIES_ALL`.
-#
-# ``URL``
-# is points to a list of available components.
-#
-# ``OLD_URL``
-# is points to a list that will replaced.
-#
-# ``NEW_URL``
-# is points to a list that will replace to.
-#
-# ``USERNAME``
-# is used as user on a protected repository.
-#
-# ``PASSWORD``
-# is password to use on a protected repository.
-#
-# ``DISPLAY_NAME``
-# is string to display instead of the URL.
-#
-#
-# .. command:: cpack_ifw_add_package_resources
-#
-# Add additional resources in the installer binary.
-#
-# ::
-#
-# cpack_ifw_add_package_resources(<file_path> <file_path> ...)
-#
-# This command will also add the specified files
-# to a variable :variable:`CPACK_IFW_PACKAGE_RESOURCES`.
-#
-#
-# Example usage
-# ^^^^^^^^^^^^^
-#
-# .. code-block:: cmake
-#
-# set(CPACK_PACKAGE_NAME "MyPackage")
-# set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyPackage Installation Example")
-# set(CPACK_PACKAGE_VERSION "1.0.0") # Version of installer
-#
-# include(CPack)
-# include(CPackIFW)
-#
-# cpack_add_component(myapp
-# DISPLAY_NAME "MyApp"
-# 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
-# DISPLAY_NAME "MyBigPlugin"
-# DESCRIPTION "My Big Downloadable Plugin"
-# DOWNLOADED)
-# cpack_ifw_add_repository(myrepo
-# URL "http://example.com/ifw/repo/myapp"
-# DISPLAY_NAME "My Application Repository")
-#
-#
-# Online installer
-# ^^^^^^^^^^^^^^^^
-#
-# By default CPack IFW generator makes offline installer. This means that all
-# components will be packaged into a binary file.
-#
-# To make a component downloaded, you must set the ``DOWNLOADED`` option in
-# :command:`cpack_add_component`.
-#
-# Then you would use the command :command:`cpack_configure_downloads`.
-# If you set ``ALL`` option all components will be downloaded.
-#
-# You also can use command :command:`cpack_ifw_add_repository` and
-# variable :variable:`CPACK_IFW_DOWNLOAD_ALL` for more specific configuration.
-#
-# CPack IFW generator creates "repository" dir in current binary dir. You
-# would copy content of this dir to specified ``site`` (``url``).
-#
-# See Also
-# ^^^^^^^^
-#
-# Qt Installer Framework Manual:
-#
-# * Index page:
-# http://doc.qt.io/qtinstallerframework/index.html
-#
-# * Component Scripting:
-# http://doc.qt.io/qtinstallerframework/scripting.html
-#
-# * Predefined Variables:
-# http://doc.qt.io/qtinstallerframework/scripting.html#predefined-variables
-#
-# * Promoting Updates:
-# http://doc.qt.io/qtinstallerframework/ifw-updates.html
-#
-# Download Qt Installer Framework for you platform from Qt site:
-# http://download.qt.io/official_releases/qt-installer-framework
-#
+#[=======================================================================[.rst:
+CPackIFW
+--------
+
+The documentation for the CPack IFW generator has moved here: :cpack_gen:`CPack IFW Generator`
+
+.. _QtIFW: http://doc.qt.io/qtinstallerframework/index.html
+
+This module looks for the location of the command line utilities supplied
+with the Qt Installer Framework (QtIFW_).
+
+The module also defines several commands to control the behavior of the
+CPack ``IFW`` generator.
+
+Commands
+^^^^^^^^
+
+The module defines the following commands:
+
+.. command:: cpack_ifw_configure_component
+
+ Sets the arguments specific to the CPack IFW generator.
+
+ ::
+
+ cpack_ifw_configure_component(<compname> [COMMON] [ESSENTIAL] [VIRTUAL]
+ [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS]
+ [NAME <name>]
+ [DISPLAY_NAME <display_name>] # Note: Internationalization supported
+ [DESCRIPTION <description>] # Note: Internationalization supported
+ [UPDATE_TEXT <update_text>]
+ [VERSION <version>]
+ [RELEASE_DATE <release_date>]
+ [SCRIPT <script>]
+ [PRIORITY|SORTING_PRIORITY <sorting_priority>] # Note: PRIORITY is deprecated
+ [DEPENDS|DEPENDENCIES <com_id> ...]
+ [AUTO_DEPEND_ON <comp_id> ...]
+ [LICENSES <display_name> <file_path> ...]
+ [DEFAULT <value>]
+ [USER_INTERFACES <file_path> <file_path> ...]
+ [TRANSLATIONS <file_path> <file_path> ...]
+ [REPLACES <comp_id> ...]
+ [CHECKABLE <value>])
+
+ This command should be called after :command:`cpack_add_component` command.
+
+ ``COMMON``
+ if set, then the component will be packaged and installed as part
+ of a group to which it belongs.
+
+ ``ESSENTIAL``
+ if set, then the package manager stays disabled until that
+ component is updated.
+
+ ``VIRTUAL``
+ if set, then the component will be hidden from the installer.
+ It is a equivalent of the ``HIDDEN`` option from the
+ :command:`cpack_add_component` command.
+
+ ``FORCED_INSTALLATION``
+ if set, then the component must always be installed.
+ It is a equivalent of the ``REQUARED`` option from the
+ :command:`cpack_add_component` command.
+
+ ``REQUIRES_ADMIN_RIGHTS``
+ set it if the component needs to be installed with elevated permissions.
+
+ ``NAME``
+ is used to create domain-like identification for this component.
+ By default used origin component name.
+
+ ``DISPLAY_NAME``
+ set to rewrite original name configured by
+ :command:`cpack_add_component` command.
+
+ ``DESCRIPTION``
+ set to rewrite original description configured by
+ :command:`cpack_add_component` command.
+
+ ``UPDATE_TEXT``
+ will be added to the component description if this is an update to
+ the component.
+
+ ``VERSION``
+ is version of component.
+ By default used :variable:`CPACK_PACKAGE_VERSION`.
+
+ ``RELEASE_DATE``
+ keep empty to auto generate.
+
+ ``SCRIPT``
+ is a relative or absolute path to operations script
+ for this component.
+
+ ``PRIORITY`` | ``SORTING_PRIORITY``
+ is priority of the component in the tree.
+ The ``PRIORITY`` option is deprecated and will be removed in a future
+ version of CMake. Please use ``SORTING_PRIORITY`` option instead.
+
+ ``DEPENDS`` | ``DEPENDENCIES``
+ list of dependency component or component group identifiers in
+ QtIFW_ style.
+
+ ``AUTO_DEPEND_ON``
+ list of identifiers of component or component group in QtIFW_ style
+ that this component has an automatic dependency on.
+
+ ``LICENSES``
+ pair of <display_name> and <file_path> of license text for this
+ component. You can specify more then one license.
+
+ ``DEFAULT``
+ Possible values are: TRUE, FALSE, and SCRIPT.
+ Set to FALSE to disable the component in the installer or to SCRIPT
+ to resolved during runtime (don't forget add the file of the script
+ as a value of the ``SCRIPT`` option).
+
+ ``USER_INTERFACES``
+ is a list of <file_path> ('.ui' files) representing pages to load.
+
+ ``TRANSLATIONS``
+ is a list of <file_path> ('.qm' files) representing translations to load.
+
+ ``REPLACES``
+ list of identifiers of component or component group to replace.
+
+ ``CHECKABLE``
+ Possible values are: TRUE, FALSE.
+ Set to FALSE if you want to hide the checkbox for an item.
+ This is useful when only a few subcomponents should be selected
+ instead of all.
+
+
+.. command:: cpack_ifw_configure_component_group
+
+ Sets the arguments specific to the CPack IFW generator.
+
+ ::
+
+ cpack_ifw_configure_component_group(<groupname> [VIRTUAL]
+ [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS]
+ [NAME <name>]
+ [DISPLAY_NAME <display_name>] # Note: Internationalization supported
+ [DESCRIPTION <description>] # Note: Internationalization supported
+ [UPDATE_TEXT <update_text>]
+ [VERSION <version>]
+ [RELEASE_DATE <release_date>]
+ [SCRIPT <script>]
+ [PRIORITY|SORTING_PRIORITY <sorting_priority>] # Note: PRIORITY is deprecated
+ [DEPENDS|DEPENDENCIES <com_id> ...]
+ [AUTO_DEPEND_ON <comp_id> ...]
+ [LICENSES <display_name> <file_path> ...]
+ [DEFAULT <value>]
+ [USER_INTERFACES <file_path> <file_path> ...]
+ [TRANSLATIONS <file_path> <file_path> ...]
+ [REPLACES <comp_id> ...]
+ [CHECKABLE <value>])
+
+ This command should be called after :command:`cpack_add_component_group`
+ command.
+
+ ``VIRTUAL``
+ if set, then the group will be hidden from the installer.
+ Note that setting this on a root component does not work.
+
+ ``FORCED_INSTALLATION``
+ if set, then the group must always be installed.
+
+ ``REQUIRES_ADMIN_RIGHTS``
+ set it if the component group needs to be installed with elevated
+ permissions.
+
+ ``NAME``
+ is used to create domain-like identification for this component group.
+ By default used origin component group name.
+
+ ``DISPLAY_NAME``
+ set to rewrite original name configured by
+ :command:`cpack_add_component_group` command.
+
+ ``DESCRIPTION``
+ set to rewrite original description configured by
+ :command:`cpack_add_component_group` command.
+
+ ``UPDATE_TEXT``
+ will be added to the component group description if this is an update to
+ the component group.
+
+ ``VERSION``
+ is version of component group.
+ By default used :variable:`CPACK_PACKAGE_VERSION`.
+
+ ``RELEASE_DATE``
+ keep empty to auto generate.
+
+ ``SCRIPT``
+ is a relative or absolute path to operations script
+ for this component group.
+
+ ``PRIORITY`` | ``SORTING_PRIORITY``
+ is priority of the component group in the tree.
+ The ``PRIORITY`` option is deprecated and will be removed in a future
+ version of CMake. Please use ``SORTING_PRIORITY`` option instead.
+
+ ``DEPENDS`` | ``DEPENDENCIES``
+ list of dependency component or component group identifiers in
+ QtIFW_ style.
+
+ ``AUTO_DEPEND_ON``
+ list of identifiers of component or component group in QtIFW_ style
+ that this component group has an automatic dependency on.
+
+ ``LICENSES``
+ pair of <display_name> and <file_path> of license text for this
+ component group. You can specify more then one license.
+
+ ``DEFAULT``
+ Possible values are: TRUE, FALSE, and SCRIPT.
+ Set to TRUE to preselect the group in the installer
+ (this takes effect only on groups that have no visible child components)
+ or to SCRIPT to resolved during runtime (don't forget add the file of
+ the script as a value of the ``SCRIPT`` option).
+
+ ``USER_INTERFACES``
+ is a list of <file_path> ('.ui' files) representing pages to load.
+
+ ``TRANSLATIONS``
+ is a list of <file_path> ('.qm' files) representing translations to load.
+
+ ``REPLACES``
+ list of identifiers of component or component group to replace.
+
+ ``CHECKABLE``
+ Possible values are: TRUE, FALSE.
+ Set to FALSE if you want to hide the checkbox for an item.
+ This is useful when only a few subcomponents should be selected
+ instead of all.
+
+
+.. command:: cpack_ifw_add_repository
+
+ Add QtIFW_ specific remote repository to binary installer.
+
+ ::
+
+ cpack_ifw_add_repository(<reponame> [DISABLED]
+ URL <url>
+ [USERNAME <username>]
+ [PASSWORD <password>]
+ [DISPLAY_NAME <display_name>])
+
+ This command will also add the <reponame> repository
+ to a variable :variable:`CPACK_IFW_REPOSITORIES_ALL`.
+
+ ``DISABLED``
+ if set, then the repository will be disabled by default.
+
+ ``URL``
+ is points to a list of available components.
+
+ ``USERNAME``
+ is used as user on a protected repository.
+
+ ``PASSWORD``
+ is password to use on a protected repository.
+
+ ``DISPLAY_NAME``
+ is string to display instead of the URL.
+
+
+.. command:: cpack_ifw_update_repository
+
+ Update QtIFW_ specific repository from remote repository.
+
+ ::
+
+ cpack_ifw_update_repository(<reponame>
+ [[ADD|REMOVE] URL <url>]|
+ [REPLACE OLD_URL <old_url> NEW_URL <new_url>]]
+ [USERNAME <username>]
+ [PASSWORD <password>]
+ [DISPLAY_NAME <display_name>])
+
+ This command will also add the <reponame> repository
+ to a variable :variable:`CPACK_IFW_REPOSITORIES_ALL`.
+
+ ``URL``
+ is points to a list of available components.
+
+ ``OLD_URL``
+ is points to a list that will replaced.
+
+ ``NEW_URL``
+ is points to a list that will replace to.
+
+ ``USERNAME``
+ is used as user on a protected repository.
+
+ ``PASSWORD``
+ is password to use on a protected repository.
+
+ ``DISPLAY_NAME``
+ is string to display instead of the URL.
+
+
+.. command:: cpack_ifw_add_package_resources
+
+ Add additional resources in the installer binary.
+
+ ::
+
+ cpack_ifw_add_package_resources(<file_path> <file_path> ...)
+
+ This command will also add the specified files
+ to a variable :variable:`CPACK_IFW_PACKAGE_RESOURCES`.
+
+#]=======================================================================]
+
+# TODO:
+# All of the internal implementation CMake modules for other CPack generators
+# have been moved into the Internal/CPack directory. This one has not, because
+# it contains user-facing macros which would be lost if it were moved. At some
+# point, this module should be split into user-facing macros (which would live
+# in this module) and internal implementation details (which would live in
+# Internal/CPack/CPackIFW.cmake).
#=============================================================================
# Search Qt Installer Framework tools
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#.rst:
-# CPackNSIS
-# ---------
-#
-# CPack NSIS generator specific options
-#
-# Variables specific to CPack NSIS generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The following variables are specific to the graphical installers built
-# on Windows using the Nullsoft Installation System.
-#
-# .. variable:: CPACK_NSIS_INSTALL_ROOT
-#
-# The default installation directory presented to the end user by the NSIS
-# installer is under this root dir. The full directory presented to the end
-# user is: ${CPACK_NSIS_INSTALL_ROOT}/${CPACK_PACKAGE_INSTALL_DIRECTORY}
-#
-# .. variable:: CPACK_NSIS_MUI_ICON
-#
-# An icon filename. The name of a ``*.ico`` file used as the main icon for the
-# generated install program.
-#
-# .. variable:: CPACK_NSIS_MUI_UNIICON
-#
-# An icon filename. The name of a ``*.ico`` file used as the main icon for the
-# generated uninstall program.
-#
-# .. variable:: CPACK_NSIS_INSTALLER_MUI_ICON_CODE
-#
-# undocumented.
-#
-# .. variable:: CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP
-#
-# The filename of a bitmap to use as the NSIS MUI_WELCOMEFINISHPAGE_BITMAP.
-#
-# .. variable:: CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP
-#
-# The filename of a bitmap to use as the NSIS MUI_UNWELCOMEFINISHPAGE_BITMAP.
-#
-# .. variable:: CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS
-#
-# Extra NSIS commands that will be added to the beginning of the install
-# Section, before your install tree is available on the target system.
-#
-# .. variable:: CPACK_NSIS_EXTRA_INSTALL_COMMANDS
-#
-# Extra NSIS commands that will be added to the end of the install Section,
-# after your install tree is available on the target system.
-#
-# .. variable:: CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS
-#
-# Extra NSIS commands that will be added to the uninstall Section, before
-# your install tree is removed from the target system.
-#
-# .. variable:: CPACK_NSIS_COMPRESSOR
-#
-# The arguments that will be passed to the NSIS SetCompressor command.
-#
-# .. variable:: CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL
-#
-# Ask about uninstalling previous versions first. If this is set to "ON",
-# then an installer will look for previous installed versions and if one is
-# found, ask the user whether to uninstall it before proceeding with the
-# install.
-#
-# .. variable:: CPACK_NSIS_MODIFY_PATH
-#
-# Modify PATH toggle. If this is set to "ON", then an extra page will appear
-# in the installer that will allow the user to choose whether the program
-# directory should be added to the system PATH variable.
-#
-# .. variable:: CPACK_NSIS_DISPLAY_NAME
-#
-# The display name string that appears in the Windows Add/Remove Program
-# control panel
-#
-# .. variable:: CPACK_NSIS_PACKAGE_NAME
-#
-# The title displayed at the top of the installer.
-#
-# .. variable:: CPACK_NSIS_INSTALLED_ICON_NAME
-#
-# A path to the executable that contains the installer icon.
-#
-# .. variable:: CPACK_NSIS_HELP_LINK
-#
-# URL to a web site providing assistance in installing your application.
-#
-# .. variable:: CPACK_NSIS_URL_INFO_ABOUT
-#
-# URL to a web site providing more information about your application.
-#
-# .. variable:: CPACK_NSIS_CONTACT
-#
-# Contact information for questions and comments about the installation
-# process.
-#
-# .. variable:: CPACK_NSIS_<compName>_INSTALL_DIRECTORY
-#
-# Custom install directory for the specified component <compName> instead
-# of $INSTDIR.
-#
-# .. variable:: CPACK_NSIS_CREATE_ICONS_EXTRA
-#
-# Additional NSIS commands for creating start menu shortcuts.
-#
-# .. variable:: CPACK_NSIS_DELETE_ICONS_EXTRA
-#
-# Additional NSIS commands to uninstall start menu shortcuts.
-#
-# .. variable:: CPACK_NSIS_EXECUTABLES_DIRECTORY
-#
-# Creating NSIS start menu links assumes that they are in 'bin' unless this
-# variable is set. For example, you would set this to 'exec' if your
-# executables are in an exec directory.
-#
-# .. variable:: CPACK_NSIS_MUI_FINISHPAGE_RUN
-#
-# Specify an executable to add an option to run on the finish page of the
-# NSIS installer.
-#
-# .. variable:: CPACK_NSIS_MENU_LINKS
-#
-# Specify links in [application] menu. This should contain a list of pair
-# "link" "link name". The link may be a URL or a path relative to
-# installation prefix. Like::
-#
-# set(CPACK_NSIS_MENU_LINKS
-# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html"
-# "CMake Help" "https://cmake.org" "CMake Web Site")
-#
-
-#FIXME we should put NSIS specific code here
-#FIXME but I'm not doing it because I'm not able to test it...
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#.rst:
-# CPackPackageMaker
-# -----------------
-#
-# PackageMaker CPack generator (Mac OS X).
-#
-# Variables specific to CPack PackageMaker generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The following variable is specific to installers built on Mac
-# OS X using PackageMaker:
-#
-# .. variable:: CPACK_OSX_PACKAGE_VERSION
-#
-# The version of Mac OS X that the resulting PackageMaker archive should be
-# compatible with. Different versions of Mac OS X support different
-# features. For example, CPack can only build component-based installers for
-# Mac OS X 10.4 or newer, and can only build installers that download
-# component son-the-fly for Mac OS X 10.5 or newer. If left blank, this value
-# will be set to the minimum version of Mac OS X that supports the requested
-# features. Set this variable to some value (e.g., 10.4) only if you want to
-# guarantee that your installer will work on that version of Mac OS X, and
-# don't mind missing extra features available in the installer shipping with
-# later versions of Mac OS X.
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#.rst:
-# CPackProductBuild
-# -----------------
-#
-# productbuild CPack generator (Mac OS X).
-#
-# Variables specific to CPack productbuild generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The following variable is specific to installers built on Mac
-# OS X using productbuild:
-#
-# .. variable:: CPACK_COMMAND_PRODUCTBUILD
-#
-# Path to the productbuild(1) command used to generate a product archive for
-# the OS X Installer or Mac App Store. This variable can be used to override
-# the automatically detected command (or specify its location if the
-# auto-detection fails to find it.)
-#
-# .. variable:: CPACK_PRODUCTBUILD_IDENTITY_NAME
-#
-# Adds a digital signature to the resulting package.
-#
-#
-# .. variable:: CPACK_PRODUCTBUILD_KEYCHAIN_PATH
-#
-# Specify a specific keychain to search for the signing identity.
-#
-#
-# .. variable:: CPACK_COMMAND_PKGBUILD
-#
-# Path to the pkgbuild(1) command used to generate an OS X component package
-# on OS X. This variable can be used to override the automatically detected
-# command (or specify its location if the auto-detection fails to find it.)
-#
-#
-# .. variable:: CPACK_PKGBUILD_IDENTITY_NAME
-#
-# Adds a digital signature to the resulting package.
-#
-#
-# .. variable:: CPACK_PKGBUILD_KEYCHAIN_PATH
-#
-# Specify a specific keychain to search for the signing identity.
-#
-#
-# .. variable:: CPACK_PREFLIGHT_<COMP>_SCRIPT
-#
-# Full path to a file that will be used as the ``preinstall`` script for the
-# named ``<COMP>`` component's package, where ``<COMP>`` is the uppercased
-# component name. No ``preinstall`` script is added if this variable is not
-# defined for a given component.
-#
-#
-# .. variable:: CPACK_POSTFLIGHT_<COMP>_SCRIPT
-#
-# Full path to a file that will be used as the ``postinstall`` script for the
-# named ``<COMP>`` component's package, where ``<COMP>`` is the uppercased
-# component name. No ``postinstall`` script is added if this variable is not
-# defined for a given component.
-#
-#
-# .. 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.
+++ /dev/null
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#.rst:
-# CPackWIX
-# --------
-#
-# CPack WiX generator specific options
-#
-# Variables specific to CPack WiX generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The following variables are specific to the installers built on
-# Windows using WiX.
-#
-# .. variable:: CPACK_WIX_UPGRADE_GUID
-#
-# Upgrade GUID (``Product/@UpgradeCode``)
-#
-# Will be automatically generated unless explicitly provided.
-#
-# It should be explicitly set to a constant generated globally unique
-# identifier (GUID) to allow your installers to replace existing
-# installations that use the same GUID.
-#
-# You may for example explicitly set this variable in your
-# CMakeLists.txt to the value that has been generated per default. You
-# should not use GUIDs that you did not generate yourself or which may
-# belong to other projects.
-#
-# A GUID shall have the following fixed length syntax::
-#
-# XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
-#
-# (each X represents an uppercase hexadecimal digit)
-#
-# .. variable:: CPACK_WIX_PRODUCT_GUID
-#
-# Product GUID (``Product/@Id``)
-#
-# Will be automatically generated unless explicitly provided.
-#
-# If explicitly provided this will set the Product Id of your installer.
-#
-# The installer will abort if it detects a pre-existing installation that
-# uses the same GUID.
-#
-# The GUID shall use the syntax described for CPACK_WIX_UPGRADE_GUID.
-#
-# .. variable:: CPACK_WIX_LICENSE_RTF
-#
-# RTF License File
-#
-# If CPACK_RESOURCE_FILE_LICENSE has an .rtf extension it is used as-is.
-#
-# If CPACK_RESOURCE_FILE_LICENSE has an .txt extension it is implicitly
-# converted to RTF by the WiX Generator.
-# The expected encoding of the .txt file is UTF-8.
-#
-# With CPACK_WIX_LICENSE_RTF you can override the license file used by the
-# WiX Generator in case CPACK_RESOURCE_FILE_LICENSE is in an unsupported
-# format or the .txt -> .rtf conversion does not work as expected.
-#
-# .. variable:: CPACK_WIX_PRODUCT_ICON
-#
-# The Icon shown next to the program name in Add/Remove programs.
-#
-# If set, this icon is used in place of the default icon.
-#
-# .. variable:: CPACK_WIX_UI_REF
-#
-# This variable allows you to override the Id of the ``<UIRef>`` element
-# in the WiX template.
-#
-# The default is ``WixUI_InstallDir`` in case no CPack components have
-# been defined and ``WixUI_FeatureTree`` otherwise.
-#
-# .. variable:: CPACK_WIX_UI_BANNER
-#
-# The bitmap will appear at the top of all installer pages other than the
-# welcome and completion dialogs.
-#
-# If set, this image will replace the default banner image.
-#
-# This image must be 493 by 58 pixels.
-#
-# .. variable:: CPACK_WIX_UI_DIALOG
-#
-# Background bitmap used on the welcome and completion dialogs.
-#
-# If this variable is set, the installer will replace the default dialog
-# image.
-#
-# This image must be 493 by 312 pixels.
-#
-# .. variable:: CPACK_WIX_PROGRAM_MENU_FOLDER
-#
-# Start menu folder name for launcher.
-#
-# If this variable is not set, it will be initialized with CPACK_PACKAGE_NAME
-#
-# .. variable:: CPACK_WIX_CULTURES
-#
-# Language(s) of the installer
-#
-# Languages are compiled into the WixUI extension library. To use them,
-# simply provide the name of the culture. If you specify more than one
-# culture identifier in a comma or semicolon delimited list, the first one
-# that is found will be used. You can find a list of supported languages at:
-# http://wix.sourceforge.net/manual-wix3/WixUI_localization.htm
-#
-# .. variable:: CPACK_WIX_TEMPLATE
-#
-# Template file for WiX generation
-#
-# If this variable is set, the specified template will be used to generate
-# the WiX wxs file. This should be used if further customization of the
-# output is required.
-#
-# If this variable is not set, the default MSI template included with CMake
-# will be used.
-#
-# .. variable:: CPACK_WIX_PATCH_FILE
-#
-# Optional list of XML files with fragments to be inserted into
-# generated WiX sources
-#
-# This optional variable can be used to specify an XML file that the
-# WiX generator will use to inject fragments into its generated
-# source files.
-#
-# Patch files understood by the CPack WiX generator
-# roughly follow this RELAX NG compact schema:
-#
-# .. code-block:: none
-#
-# start = CPackWiXPatch
-#
-# CPackWiXPatch = element CPackWiXPatch { CPackWiXFragment* }
-#
-# CPackWiXFragment = element CPackWiXFragment
-# {
-# attribute Id { string },
-# fragmentContent*
-# }
-#
-# fragmentContent = element * - CPackWiXFragment
-# {
-# (attribute * { text } | text | fragmentContent)*
-# }
-#
-# Currently fragments can be injected into most
-# Component, File, Directory and Feature elements.
-#
-# The following additional special Ids can be used:
-#
-# * ``#PRODUCT`` for the ``<Product>`` element.
-# * ``#PRODUCTFEATURE`` for the root ``<Feature>`` element.
-#
-# The following example illustrates how this works.
-#
-# Given that the WiX generator creates the following XML element:
-#
-# .. code-block:: xml
-#
-# <Component Id="CM_CP_applications.bin.my_libapp.exe" Guid="*"/>
-#
-# The following XML patch file may be used to inject an Environment element
-# into it:
-#
-# .. code-block:: xml
-#
-# <CPackWiXPatch>
-# <CPackWiXFragment Id="CM_CP_applications.bin.my_libapp.exe">
-# <Environment Id="MyEnvironment" Action="set"
-# Name="MyVariableName" Value="MyVariableValue"/>
-# </CPackWiXFragment>
-# </CPackWiXPatch>
-#
-# .. variable:: CPACK_WIX_EXTRA_SOURCES
-#
-# Extra WiX source files
-#
-# This variable provides an optional list of extra WiX source files (.wxs)
-# that should be compiled and linked. The full path to source files is
-# required.
-#
-# .. variable:: CPACK_WIX_EXTRA_OBJECTS
-#
-# Extra WiX object files or libraries
-#
-# This variable provides an optional list of extra WiX object (.wixobj)
-# and/or WiX library (.wixlib) files. The full path to objects and libraries
-# is required.
-#
-# .. variable:: CPACK_WIX_EXTENSIONS
-#
-# This variable provides a list of additional extensions for the WiX
-# tools light and candle.
-#
-# .. variable:: CPACK_WIX_<TOOL>_EXTENSIONS
-#
-# This is the tool specific version of CPACK_WIX_EXTENSIONS.
-# ``<TOOL>`` can be either LIGHT or CANDLE.
-#
-# .. variable:: CPACK_WIX_<TOOL>_EXTRA_FLAGS
-#
-# This list variable allows you to pass additional
-# flags to the WiX tool ``<TOOL>``.
-#
-# Use it at your own risk.
-# Future versions of CPack may generate flags which may be in conflict
-# with your own flags.
-#
-# ``<TOOL>`` can be either LIGHT or CANDLE.
-#
-# .. variable:: CPACK_WIX_CMAKE_PACKAGE_REGISTRY
-#
-# If this variable is set the generated installer will create
-# an entry in the windows registry key
-# ``HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\<package>``
-# The value for ``<package>`` is provided by this variable.
-#
-# Assuming you also install a CMake configuration file this will
-# allow other CMake projects to find your package with
-# the :command:`find_package` command.
-#
-# .. variable:: CPACK_WIX_PROPERTY_<PROPERTY>
-#
-# This variable can be used to provide a value for
-# the Windows Installer property ``<PROPERTY>``
-#
-# The following list contains some example properties that can be used to
-# customize information under
-# "Programs and Features" (also known as "Add or Remove Programs")
-#
-# * ARPCOMMENTS - Comments
-# * ARPHELPLINK - Help and support information URL
-# * ARPURLINFOABOUT - General information URL
-# * ARPURLUPDATEINFO - Update information URL
-# * ARPHELPTELEPHONE - Help and support telephone number
-# * ARPSIZE - Size (in kilobytes) of the application
-#
-# .. variable:: CPACK_WIX_ROOT_FEATURE_TITLE
-#
-# Sets the name of the root install feature in the WIX installer. Same as
-# CPACK_COMPONENT_<compName>_DISPLAY_NAME for components.
-#
-# .. variable:: CPACK_WIX_ROOT_FEATURE_DESCRIPTION
-#
-# Sets the description of the root install feature in the WIX installer. Same as
-# CPACK_COMPONENT_<compName>_DESCRIPTION for components.
-#
-# .. variable:: CPACK_WIX_SKIP_PROGRAM_FOLDER
-#
-# 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
-# between the system on which the installer is created
-# and the system on which the installer might be used into account.
-#
-# It is therefore possible that the installer e.g. might try to install
-# onto a drive that is unavailable or unintended or a path that does not
-# 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)
- string(REPLACE "\\" "/" CPACK_WIX_ROOT "$ENV{WIX}")
-endif()
-
-find_program(CPACK_WIX_CANDLE_EXECUTABLE candle
- PATHS "${CPACK_WIX_ROOT}" PATH_SUFFIXES "bin")
-
-if(NOT CPACK_WIX_CANDLE_EXECUTABLE)
- message(FATAL_ERROR "Could not find the WiX candle executable.")
-endif()
-
-find_program(CPACK_WIX_LIGHT_EXECUTABLE light
- PATHS "${CPACK_WIX_ROOT}" PATH_SUFFIXES "bin")
-
-if(NOT CPACK_WIX_LIGHT_EXECUTABLE)
- message(FATAL_ERROR "Could not find the WiX light executable.")
-endif()
#]=======================================================================]
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
function(csharp_get_filename_keys OUT)
set(${OUT} "")
foreach(f ${ARGN})
endif()
endforeach()
endfunction()
+
+cmake_policy(POP)
endif()
endforeach()
- if(CMAKE_GENERATOR MATCHES "^Visual Studio ")
+ if(CMAKE_GENERATOR MATCHES "^Visual Studio 9 ")
_ipo_not_supported("CMake doesn't support IPO for current generator")
return()
endif()
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> --create -cr <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_DEPFILE_FLAGS_${lang} "--depend=<DEPFILE> --depend_single_line --no_depend_system_headers")
+
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ")
endmacro()
set(CMAKE_Fortran_VERBOSE_FLAG "-v")
set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed")
set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree")
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-X")
string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -g -DNDEBUG")
+
+set(CMAKE_C_LINKER_WRAPPER_FLAG "-X")
set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "--target=")
set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=")
endif()
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP)
+
+ if(CMAKE_${lang}_COMPILER_TARGET)
+ if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.4.0)
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-target" "${CMAKE_${lang}_COMPILER_TARGET}")
+ else()
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}")
+ endif()
+ endif()
set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
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()
+ if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.6)
+ set(CMAKE_CXX14_STANDARD_COMPILE_OPTION -h std=c++14)
+ set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION -h std=c++14,gnu)
endif ()
endif ()
__compiler_clang(Fortran)
set(CMAKE_Fortran_PREPROCESS_SOURCE
- "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> -o <PREPROCESSED_SOURCE>")
+ "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
set(CMAKE_Fortran_VERBOSE_FLAG "-v")
set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
set(CMAKE_${lang}_COMPILE_OPTIONS_SYSROOT "--sysroot=")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
# Older versions of gcc (< 4.5) contain a bug causing them to report a missing
# header file as a warning if depfiles are enabled, causing check_header_file
# tests to always succeed. Work around this by disabling dependency tracking
)
endif()
- set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
+ set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}")
+ if(CMAKE_${lang}_COMPILER_ARG1)
+ separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}")
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS})
+ unset(_COMPILER_ARGS)
+ endif()
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
endmacro()
set(CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
set(CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+
+set(CMAKE_C_LINKER_WRAPPER_FLAG "-Wl,")
+set(CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",")
set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+set(CMAKE_CXX_LINKER_WRAPPER_FLAG "-Wl,")
+set(CMAKE_CXX_LINKER_WRAPPER_FLAG_SEP ",")
+
# HP aCC since version 3.80 supports the flag +hpxstd98 to get ANSI C++98
# template support. It is known that version 6.25 doesn't need that flag.
# Current assumption: the flag is needed for every version from 3.80 to 4
set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG ",")
__compiler_iar_AVR(ASM)
set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;asm;msa)
+else()
+ message(FATAL_ERROR "CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID not detected as \"AVR\" or \"ARM\". This should be automatic.")
endif()
# The toolchains for ARM and AVR are quite different:
if("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM")
+ if(NOT CMAKE_C_COMPILER_VERSION)
+ message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION not detected. This should be automatic.")
+ endif()
set(CMAKE_C_EXTENSION_COMPILE_OPTION -e)
get_filename_component(_compilerDir "${CMAKE_C_COMPILER}" PATH)
get_filename_component(_compilerDir "${_compilerDir}" PATH)
include_directories("${_compilerDir}/inc" )
+
+else()
+ message(FATAL_ERROR "CMAKE_C_COMPILER_ARCHITECTURE_ID not detected as \"AVR\" or \"ARM\". This should be automatic.")
endif()
#
# --c++ is full C++ and supported since 6.10
if(NOT CMAKE_IAR_CXX_FLAG)
+ if(NOT CMAKE_CXX_COMPILER_VERSION)
+ message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION not detected. This should be automatic.")
+ endif()
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.10)
set(CMAKE_IAR_CXX_FLAG --c++)
else()
get_filename_component(_compilerDir "${CMAKE_C_COMPILER}" PATH)
get_filename_component(_compilerDir "${_compilerDir}" PATH)
include_directories("${_compilerDir}/inc")
+
+else()
+ message(FATAL_ERROR "CMAKE_CXX_COMPILER_ARCHITECTURE_ID not detected as \"AVR\" or \"ARM\". This should be automatic." )
endif()
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")
+ set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}")
+ if(CMAKE_${lang}_COMPILER_ARG1)
+ separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}")
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS})
+ unset(_COMPILER_ARGS)
+ endif()
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-QdM" "-P" "-Za" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
endmacro()
endif()
set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free")
set(CMAKE_Fortran_COMPILE_OPTIONS_PIC "-PIC")
set(CMAKE_Fortran_COMPILE_OPTIONS_PIE "-PIC")
+set(CMAKE_Fortran_RESPONSE_FILE_LINK_FLAG "-Wl,@")
string(APPEND CMAKE_${lang}_FLAGS_INIT " -Bdynamic")
endif()
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG ",")
+
set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL ppc64le AND (NOT CMAKE_HOST_WIN32 OR CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 16.3))
set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "-V")
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-Wp,-isystem,")
- set(CMAKE_DEPFILE_FLAGS_${lang} "-Wc,-MD,<DEPFILE>,-MT,<OBJECT>,-MF,<DEPFILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-Wp,-MD,<DEPFILE> -Wp,-MT,<OBJECT> -Wp,-MF,<DEPFILE>")
+
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE NO)
set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
- set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-Wp,-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
+ set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}")
+ if(CMAKE_${lang}_COMPILER_ARG1)
+ separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}")
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS})
+ unset(_COMPILER_ARGS)
+ endif()
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-Wp,-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO)
unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO)
set(CMAKE_${lang}_COMPILE_OPTIONS_DLL -belf)
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-Kpic -belf")
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-belf -Wl,-Bexport")
+
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
endmacro()
set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Bdynamic")
endforeach()
+set(CMAKE_C_LINKER_WRAPPER_FLAG "-Qoption" "ld" " ")
+set(CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",")
+
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_${type}_LINK_DYNAMIC_CXX_FLAGS "-Bdynamic")
endforeach()
+set(CMAKE_CXX_LINKER_WRAPPER_FLAG "-Qoption" "ld" " ")
+set(CMAKE_CXX_LINKER_WRAPPER_FLAG_SEP ",")
+
set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE "<CMAKE_CXX_COMPILER> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
set(CMAKE_Fortran_MODDIR_FLAG "-moddir=")
set(CMAKE_Fortran_MODPATH_FLAG "-M")
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Qoption" "ld" " ")
+set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
+
set(CMAKE_Fortran_PREPROCESS_SOURCE
"<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -F -fpp <SOURCE> -o <PREPROCESSED_SOURCE>")
string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -g -DNDEBUG")
+
+set(CMAKE_C_LINKER_WRAPPER_FLAG "-Wl,")
+set(CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",")
# Feature flags.
set(CMAKE_${lang}_VERBOSE_FLAG "-V")
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-qpic")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-qpic")
set(CMAKE_${lang}_RESPONSE_FILE_FLAG "-qoptfile=")
set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-qoptfile=")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g")
string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O")
string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O")
isa = XCBuildConfiguration;
buildSettings = {
@id_development_team@
+ @id_code_sign_identity@
PRODUCT_NAME = CompilerId@id_lang@;
};
name = Debug;
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# DeployQt4
-# ---------
-#
-# Functions to help assemble a standalone Qt4 executable.
-#
-# A collection of CMake utility functions useful for deploying Qt4
-# executables.
-#
-# The following functions are provided by this module:
-#
-# ::
-#
-# write_qt4_conf
-# resolve_qt4_paths
-# fixup_qt4_executable
-# install_qt4_plugin_path
-# install_qt4_plugin
-# install_qt4_executable
-#
-# Requires CMake 2.6 or greater because it uses function and
-# PARENT_SCOPE. Also depends on BundleUtilities.cmake.
-#
-# ::
-#
-# WRITE_QT4_CONF(<qt_conf_dir> <qt_conf_contents>)
-#
-# Writes a qt.conf file with the <qt_conf_contents> into <qt_conf_dir>.
-#
-# ::
-#
-# RESOLVE_QT4_PATHS(<paths_var> [<executable_path>])
-#
-# Loop through <paths_var> list and if any don't exist resolve them
-# relative to the <executable_path> (if supplied) or the
-# CMAKE_INSTALL_PREFIX.
-#
-# ::
-#
-# FIXUP_QT4_EXECUTABLE(<executable>
-# [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf>])
-#
-# Copies Qt plugins, writes a Qt configuration file (if needed) and
-# fixes up a Qt4 executable using BundleUtilities so it is standalone
-# and can be drag-and-drop copied to another machine as long as all of
-# the system libraries are compatible.
-#
-# <executable> should point to the executable to be fixed-up.
-#
-# <qtplugins> should contain a list of the names or paths of any Qt
-# plugins to be installed.
-#
-# <libs> will be passed to BundleUtilities and should be a list of any
-# already installed plugins, libraries or executables to also be
-# fixed-up.
-#
-# <dirs> will be passed to BundleUtilities and should contain and
-# directories to be searched to find library dependencies.
-#
-# <plugins_dir> allows an custom plugins directory to be used.
-#
-# <request_qt_conf> will force a qt.conf file to be written even if not
-# needed.
-#
-# ::
-#
-# INSTALL_QT4_PLUGIN_PATH(plugin executable copy installed_plugin_path_var
-# <plugins_dir> <component> <configurations>)
-#
-# Install (or copy) a resolved <plugin> to the default plugins directory
-# (or <plugins_dir>) relative to <executable> and store the result in
-# <installed_plugin_path_var>.
-#
-# If <copy> is set to TRUE then the plugins will be copied rather than
-# installed. This is to allow this module to be used at CMake time
-# rather than install time.
-#
-# If <component> is set then anything installed will use this COMPONENT.
-#
-# ::
-#
-# INSTALL_QT4_PLUGIN(plugin executable copy installed_plugin_path_var
-# <plugins_dir> <component>)
-#
-# Install (or copy) an unresolved <plugin> to the default plugins
-# directory (or <plugins_dir>) relative to <executable> and store the
-# result in <installed_plugin_path_var>. See documentation of
-# INSTALL_QT4_PLUGIN_PATH.
-#
-# ::
-#
-# INSTALL_QT4_EXECUTABLE(<executable>
-# [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf> <component>])
-#
-# Installs Qt plugins, writes a Qt configuration file (if needed) and
-# fixes up a Qt4 executable using BundleUtilities so it is standalone
-# and can be drag-and-drop copied to another machine as long as all of
-# the system libraries are compatible. The executable will be fixed-up
-# at install time. <component> is the COMPONENT used for bundle fixup
-# and plugin installation. See documentation of FIXUP_QT4_BUNDLE.
+#[=======================================================================[.rst:
+DeployQt4
+---------
+
+Functions to help assemble a standalone Qt4 executable.
+
+A collection of CMake utility functions useful for deploying Qt4
+executables.
+
+The following functions are provided by this module:
+
+::
+
+ write_qt4_conf
+ resolve_qt4_paths
+ fixup_qt4_executable
+ install_qt4_plugin_path
+ install_qt4_plugin
+ install_qt4_executable
+
+Requires CMake 2.6 or greater because it uses function and
+PARENT_SCOPE. Also depends on BundleUtilities.cmake.
+
+::
+
+ WRITE_QT4_CONF(<qt_conf_dir> <qt_conf_contents>)
+
+Writes a qt.conf file with the <qt_conf_contents> into <qt_conf_dir>.
+
+::
+
+ RESOLVE_QT4_PATHS(<paths_var> [<executable_path>])
+
+Loop through <paths_var> list and if any don't exist resolve them
+relative to the <executable_path> (if supplied) or the
+CMAKE_INSTALL_PREFIX.
+
+::
+
+ FIXUP_QT4_EXECUTABLE(<executable>
+ [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf>])
+
+Copies Qt plugins, writes a Qt configuration file (if needed) and
+fixes up a Qt4 executable using BundleUtilities so it is standalone
+and can be drag-and-drop copied to another machine as long as all of
+the system libraries are compatible.
+
+<executable> should point to the executable to be fixed-up.
+
+<qtplugins> should contain a list of the names or paths of any Qt
+plugins to be installed.
+
+<libs> will be passed to BundleUtilities and should be a list of any
+already installed plugins, libraries or executables to also be
+fixed-up.
+
+<dirs> will be passed to BundleUtilities and should contain and
+directories to be searched to find library dependencies.
+
+<plugins_dir> allows an custom plugins directory to be used.
+
+<request_qt_conf> will force a qt.conf file to be written even if not
+needed.
+
+::
+
+ INSTALL_QT4_PLUGIN_PATH(plugin executable copy installed_plugin_path_var
+ <plugins_dir> <component> <configurations>)
+
+Install (or copy) a resolved <plugin> to the default plugins directory
+(or <plugins_dir>) relative to <executable> and store the result in
+<installed_plugin_path_var>.
+
+If <copy> is set to TRUE then the plugins will be copied rather than
+installed. This is to allow this module to be used at CMake time
+rather than install time.
+
+If <component> is set then anything installed will use this COMPONENT.
+
+::
+
+ INSTALL_QT4_PLUGIN(plugin executable copy installed_plugin_path_var
+ <plugins_dir> <component>)
+
+Install (or copy) an unresolved <plugin> to the default plugins
+directory (or <plugins_dir>) relative to <executable> and store the
+result in <installed_plugin_path_var>. See documentation of
+INSTALL_QT4_PLUGIN_PATH.
+
+::
+
+ INSTALL_QT4_EXECUTABLE(<executable>
+ [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf> <component>])
+
+Installs Qt plugins, writes a Qt configuration file (if needed) and
+fixes up a Qt4 executable using BundleUtilities so it is standalone
+and can be drag-and-drop copied to another machine as long as all of
+the system libraries are compatible. The executable will be fixed-up
+at install time. <component> is the COMPONENT used for bundle fixup
+and plugin installation. See documentation of FIXUP_QT4_BUNDLE.
+#]=======================================================================]
# The functions defined in this file depend on the fixup_bundle function
# (and others) found in BundleUtilities.cmake
-include("${CMAKE_CURRENT_LIST_DIR}/BundleUtilities.cmake")
set(DeployQt4_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
set(DeployQt4_apple_plugins_dir "PlugIns")
function(write_qt4_conf qt_conf_dir qt_conf_contents)
- set(qt_conf_path "${qt_conf_dir}/qt.conf")
- message(STATUS "Writing ${qt_conf_path}")
- file(WRITE "${qt_conf_path}" "${qt_conf_contents}")
+ set(qt_conf_path "${qt_conf_dir}/qt.conf")
+ message(STATUS "Writing ${qt_conf_path}")
+ file(WRITE "${qt_conf_path}" "${qt_conf_contents}")
endfunction()
function(resolve_qt4_paths paths_var)
- unset(executable_path)
- if(ARGC GREATER 1)
- set(executable_path ${ARGV1})
- endif()
-
- set(paths_resolved)
- foreach(path ${${paths_var}})
- if(EXISTS "${path}")
- list(APPEND paths_resolved "${path}")
- else()
- if(${executable_path})
- list(APPEND paths_resolved "${executable_path}/${path}")
- else()
- list(APPEND paths_resolved "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${path}")
- endif()
- endif()
- endforeach()
- set(${paths_var} ${paths_resolved} PARENT_SCOPE)
-endfunction()
+ unset(executable_path)
+ if(ARGC GREATER 1)
+ set(executable_path ${ARGV1})
+ endif()
-function(fixup_qt4_executable executable)
- unset(qtplugins)
- if(ARGC GREATER 1)
- set(qtplugins ${ARGV1})
- endif()
- unset(libs)
- if(ARGC GREATER 2)
- set(libs ${ARGV2})
- endif()
- unset(dirs)
- if(ARGC GREATER 3)
- set(dirs ${ARGV3})
- endif()
- unset(plugins_dir)
- if(ARGC GREATER 4)
- set(plugins_dir ${ARGV4})
- endif()
- unset(request_qt_conf)
- if(ARGC GREATER 5)
- set(request_qt_conf ${ARGV5})
- endif()
-
- message(STATUS "fixup_qt4_executable")
- message(STATUS " executable='${executable}'")
- message(STATUS " qtplugins='${qtplugins}'")
- message(STATUS " libs='${libs}'")
- message(STATUS " dirs='${dirs}'")
- message(STATUS " plugins_dir='${plugins_dir}'")
- message(STATUS " request_qt_conf='${request_qt_conf}'")
-
- if(QT_LIBRARY_DIR)
- list(APPEND dirs "${QT_LIBRARY_DIR}")
- endif()
- if(QT_BINARY_DIR)
- list(APPEND dirs "${QT_BINARY_DIR}")
- endif()
-
- if(APPLE)
- set(qt_conf_dir "${executable}/Contents/Resources")
- set(executable_path "${executable}")
- set(write_qt_conf TRUE)
- if(NOT DEFINED plugins_dir)
- set(plugins_dir "${DeployQt4_apple_plugins_dir}")
- endif()
- else()
- get_filename_component(executable_path "${executable}" PATH)
- if(NOT executable_path)
- set(executable_path ".")
- endif()
- set(qt_conf_dir "${executable_path}")
- set(write_qt_conf ${request_qt_conf})
- endif()
-
- foreach(plugin ${qtplugins})
- set(installed_plugin_path "")
- install_qt4_plugin("${plugin}" "${executable}" 1 installed_plugin_path)
- list(APPEND libs ${installed_plugin_path})
- endforeach()
-
- foreach(lib ${libs})
- if(NOT EXISTS "${lib}")
- message(FATAL_ERROR "Library does not exist: ${lib}")
- endif()
- endforeach()
-
- resolve_qt4_paths(libs "${executable_path}")
-
- if(write_qt_conf)
- set(qt_conf_contents "[Paths]\nPlugins = ${plugins_dir}")
- write_qt4_conf("${qt_conf_dir}" "${qt_conf_contents}")
- endif()
-
- fixup_bundle("${executable}" "${libs}" "${dirs}")
+ set(paths_resolved)
+ foreach(path ${${paths_var}})
+ if(EXISTS "${path}")
+ list(APPEND paths_resolved "${path}")
+ else()
+ if(${executable_path})
+ list(APPEND paths_resolved "${executable_path}/${path}")
+ else()
+ list(APPEND paths_resolved "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${path}")
+ endif()
+ endif()
+ endforeach()
+ set(${paths_var} ${paths_resolved} PARENT_SCOPE)
endfunction()
+cmake_policy(GET CMP0080 _cmp0080_value)
+if(NOT DEFINED CMAKE_GENERATOR OR NOT _cmp0080_value STREQUAL "NEW")
+ set(_CMP0080_SUPPRESS_WARNING TRUE)
+ include("${CMAKE_CURRENT_LIST_DIR}/BundleUtilities.cmake")
+ unset(_CMP0080_SUPPRESS_WARNING)
+
+ function(fixup_qt4_executable executable)
+ cmake_policy(GET CMP0080 _cmp0080_value)
+ if(_cmp0080_value STREQUAL "" AND DEFINED CMAKE_GENERATOR)
+ _warn_cmp0080()
+ endif()
+
+ unset(qtplugins)
+ if(ARGC GREATER 1)
+ set(qtplugins ${ARGV1})
+ endif()
+ unset(libs)
+ if(ARGC GREATER 2)
+ set(libs ${ARGV2})
+ endif()
+ unset(dirs)
+ if(ARGC GREATER 3)
+ set(dirs ${ARGV3})
+ endif()
+ unset(plugins_dir)
+ if(ARGC GREATER 4)
+ set(plugins_dir ${ARGV4})
+ endif()
+ unset(request_qt_conf)
+ if(ARGC GREATER 5)
+ set(request_qt_conf ${ARGV5})
+ endif()
+
+ message(STATUS "fixup_qt4_executable")
+ message(STATUS " executable='${executable}'")
+ message(STATUS " qtplugins='${qtplugins}'")
+ message(STATUS " libs='${libs}'")
+ message(STATUS " dirs='${dirs}'")
+ message(STATUS " plugins_dir='${plugins_dir}'")
+ message(STATUS " request_qt_conf='${request_qt_conf}'")
+
+ if(QT_LIBRARY_DIR)
+ list(APPEND dirs "${QT_LIBRARY_DIR}")
+ endif()
+ if(QT_BINARY_DIR)
+ list(APPEND dirs "${QT_BINARY_DIR}")
+ endif()
+
+ if(APPLE)
+ set(qt_conf_dir "${executable}/Contents/Resources")
+ set(executable_path "${executable}")
+ set(write_qt_conf TRUE)
+ if(NOT DEFINED plugins_dir)
+ set(plugins_dir "${DeployQt4_apple_plugins_dir}")
+ endif()
+ else()
+ get_filename_component(executable_path "${executable}" PATH)
+ if(NOT executable_path)
+ set(executable_path ".")
+ endif()
+ set(qt_conf_dir "${executable_path}")
+ set(write_qt_conf ${request_qt_conf})
+ endif()
+
+ foreach(plugin ${qtplugins})
+ set(installed_plugin_path "")
+ install_qt4_plugin("${plugin}" "${executable}" 1 installed_plugin_path)
+ list(APPEND libs ${installed_plugin_path})
+ endforeach()
+
+ foreach(lib ${libs})
+ if(NOT EXISTS "${lib}")
+ message(FATAL_ERROR "Library does not exist: ${lib}")
+ endif()
+ endforeach()
+
+ resolve_qt4_paths(libs "${executable_path}")
+
+ if(write_qt_conf)
+ set(qt_conf_contents "[Paths]\nPlugins = ${plugins_dir}")
+ write_qt4_conf("${qt_conf_dir}" "${qt_conf_contents}")
+ endif()
+
+ fixup_bundle("${executable}" "${libs}" "${dirs}")
+ endfunction()
+endif()
+
function(install_qt4_plugin_path plugin executable copy installed_plugin_path_var)
- unset(plugins_dir)
- if(ARGC GREATER 4)
- set(plugins_dir ${ARGV4})
- endif()
- unset(component)
- if(ARGC GREATER 5)
- set(component ${ARGV5})
- endif()
+ unset(plugins_dir)
+ if(ARGC GREATER 4)
+ set(plugins_dir ${ARGV4})
+ endif()
+ unset(component)
+ if(ARGC GREATER 5)
+ set(component ${ARGV5})
+ endif()
+ unset(configurations)
+ if(ARGC GREATER 6)
+ set(configurations ${ARGV6})
+ endif()
+
+ if(EXISTS "${plugin}")
+ if(APPLE)
+ if(NOT plugins_dir)
+ set(plugins_dir "${DeployQt4_apple_plugins_dir}")
+ endif()
+ set(plugins_path "${executable}/Contents/${plugins_dir}")
+ else()
+ get_filename_component(plugins_path "${executable}" PATH)
+ if(NOT plugins_path)
+ set(plugins_path ".")
+ endif()
+ if(plugins_dir)
+ string(APPEND plugins_path "/${plugins_dir}")
+ endif()
+ endif()
+
+ set(plugin_group "")
+
+ get_filename_component(plugin_path "${plugin}" PATH)
+ get_filename_component(plugin_parent_path "${plugin_path}" PATH)
+ get_filename_component(plugin_parent_dir_name "${plugin_parent_path}" NAME)
+ get_filename_component(plugin_name "${plugin}" NAME)
+ string(TOLOWER "${plugin_parent_dir_name}" plugin_parent_dir_name)
+
+ if("${plugin_parent_dir_name}" STREQUAL "plugins")
+ get_filename_component(plugin_group "${plugin_path}" NAME)
+ set(${plugin_group_var} "${plugin_group}")
+ endif()
+ string(APPEND plugins_path "/${plugin_group}")
+
+ if(${copy})
+ file(MAKE_DIRECTORY "${plugins_path}")
+ file(COPY "${plugin}" DESTINATION "${plugins_path}")
+ else()
+ get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(configurations AND (_isMultiConfig OR CMAKE_BUILD_TYPE))
+ set(configurations CONFIGURATIONS ${configurations})
+ else()
unset(configurations)
- if(ARGC GREATER 6)
- set(configurations ${ARGV6})
- endif()
-
- if(EXISTS "${plugin}")
- if(APPLE)
- if(NOT plugins_dir)
- set(plugins_dir "${DeployQt4_apple_plugins_dir}")
- endif()
- set(plugins_path "${executable}/Contents/${plugins_dir}")
- else()
- get_filename_component(plugins_path "${executable}" PATH)
- if(NOT plugins_path)
- set(plugins_path ".")
- endif()
- if(plugins_dir)
- string(APPEND plugins_path "/${plugins_dir}")
- endif()
- endif()
-
- set(plugin_group "")
-
- get_filename_component(plugin_path "${plugin}" PATH)
- get_filename_component(plugin_parent_path "${plugin_path}" PATH)
- get_filename_component(plugin_parent_dir_name "${plugin_parent_path}" NAME)
- get_filename_component(plugin_name "${plugin}" NAME)
- string(TOLOWER "${plugin_parent_dir_name}" plugin_parent_dir_name)
-
- if("${plugin_parent_dir_name}" STREQUAL "plugins")
- get_filename_component(plugin_group "${plugin_path}" NAME)
- set(${plugin_group_var} "${plugin_group}")
- endif()
- string(APPEND plugins_path "/${plugin_group}")
-
- if(${copy})
- file(MAKE_DIRECTORY "${plugins_path}")
- file(COPY "${plugin}" DESTINATION "${plugins_path}")
- else()
- get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
- if(configurations AND (_isMultiConfig OR CMAKE_BUILD_TYPE))
- set(configurations CONFIGURATIONS ${configurations})
- else()
- unset(configurations)
- endif()
- install(FILES "${plugin}" DESTINATION "${plugins_path}" ${configurations} ${component})
- endif()
- set(${installed_plugin_path_var} "${plugins_path}/${plugin_name}" PARENT_SCOPE)
- endif()
+ endif()
+ install(FILES "${plugin}" DESTINATION "${plugins_path}" ${configurations} ${component})
+ endif()
+ set(${installed_plugin_path_var} "${plugins_path}/${plugin_name}" PARENT_SCOPE)
+ endif()
endfunction()
function(install_qt4_plugin plugin executable copy installed_plugin_path_var)
- unset(plugins_dir)
- if(ARGC GREATER 4)
- set(plugins_dir ${ARGV4})
- endif()
- unset(component)
- if(ARGC GREATER 5)
- set(component ${ARGV5})
- endif()
-
- if(EXISTS "${plugin}")
- install_qt4_plugin_path("${plugin}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
- else()
- string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var)
- set(plugin_release_var "${plugin_var}_RELEASE")
- set(plugin_debug_var "${plugin_var}_DEBUG")
- set(plugin_release "${${plugin_release_var}}")
- set(plugin_debug "${${plugin_debug_var}}")
- if(DEFINED "${plugin_release_var}" AND DEFINED "${plugin_debug_var}" AND NOT EXISTS "${plugin_release}" AND NOT EXISTS "${plugin_debug}")
- message(WARNING "Qt plugin \"${plugin}\" not recognized or found.")
- endif()
- if(NOT EXISTS "${${plugin_debug_var}}")
- set(plugin_debug "${plugin_release}")
- endif()
-
- get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
- if(_isMultiConfig OR CMAKE_BUILD_TYPE)
- set(_RELEASE_CONFIGS ${CMAKE_CONFIGURATION_TYPES} "${CMAKE_BUILD_TYPE}")
- if (_RELEASE_CONFIGS)
- list(FILTER _RELEASE_CONFIGS EXCLUDE REGEX "[Dd][Ee][Bb][Uu][Gg]")
- endif()
- string(REPLACE ";" "|" _RELEASE_CONFIGS "${_RELEASE_CONFIGS}")
- install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}_release" "${plugins_dir}" "${component}" "${_RELEASE_CONFIGS}")
- install_qt4_plugin_path("${plugin_debug}" "${executable}" "${copy}" "${installed_plugin_path_var}_debug" "${plugins_dir}" "${component}" "Debug")
- unset(_RELEASE_CONFIGS)
-
- if(CMAKE_BUILD_TYPE MATCHES "^Debug$")
- set(${installed_plugin_path_var} ${${installed_plugin_path_var}_debug})
- else()
- set(${installed_plugin_path_var} ${${installed_plugin_path_var}_release})
- endif()
- else()
- install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
- endif()
- endif()
- set(${installed_plugin_path_var} ${${installed_plugin_path_var}} PARENT_SCOPE)
+ unset(plugins_dir)
+ if(ARGC GREATER 4)
+ set(plugins_dir ${ARGV4})
+ endif()
+ unset(component)
+ if(ARGC GREATER 5)
+ set(component ${ARGV5})
+ endif()
+
+ if(EXISTS "${plugin}")
+ install_qt4_plugin_path("${plugin}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
+ else()
+ string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var)
+ set(plugin_release_var "${plugin_var}_RELEASE")
+ set(plugin_debug_var "${plugin_var}_DEBUG")
+ set(plugin_release "${${plugin_release_var}}")
+ set(plugin_debug "${${plugin_debug_var}}")
+ if(DEFINED "${plugin_release_var}" AND DEFINED "${plugin_debug_var}" AND NOT EXISTS "${plugin_release}" AND NOT EXISTS "${plugin_debug}")
+ message(WARNING "Qt plugin \"${plugin}\" not recognized or found.")
+ endif()
+ if(NOT EXISTS "${${plugin_debug_var}}")
+ set(plugin_debug "${plugin_release}")
+ endif()
+
+ get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(_isMultiConfig OR CMAKE_BUILD_TYPE)
+ set(_RELEASE_CONFIGS ${CMAKE_CONFIGURATION_TYPES} "${CMAKE_BUILD_TYPE}")
+ if (_RELEASE_CONFIGS)
+ list(FILTER _RELEASE_CONFIGS EXCLUDE REGEX "[Dd][Ee][Bb][Uu][Gg]")
+ endif()
+ string(REPLACE ";" "|" _RELEASE_CONFIGS "${_RELEASE_CONFIGS}")
+ install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}_release" "${plugins_dir}" "${component}" "${_RELEASE_CONFIGS}")
+ install_qt4_plugin_path("${plugin_debug}" "${executable}" "${copy}" "${installed_plugin_path_var}_debug" "${plugins_dir}" "${component}" "Debug")
+ unset(_RELEASE_CONFIGS)
+
+ if(CMAKE_BUILD_TYPE MATCHES "^Debug$")
+ set(${installed_plugin_path_var} ${${installed_plugin_path_var}_debug})
+ else()
+ set(${installed_plugin_path_var} ${${installed_plugin_path_var}_release})
+ endif()
+ else()
+ install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
+ endif()
+ endif()
+ set(${installed_plugin_path_var} ${${installed_plugin_path_var}} PARENT_SCOPE)
endfunction()
function(install_qt4_executable executable)
- unset(qtplugins)
- if(ARGC GREATER 1)
- set(qtplugins ${ARGV1})
- endif()
- unset(libs)
- if(ARGC GREATER 2)
- set(libs ${ARGV2})
- endif()
- unset(dirs)
- if(ARGC GREATER 3)
- set(dirs ${ARGV3})
- endif()
- unset(plugins_dir)
- if(ARGC GREATER 4)
- set(plugins_dir ${ARGV4})
- endif()
- unset(request_qt_conf)
- if(ARGC GREATER 5)
- set(request_qt_conf ${ARGV5})
- endif()
- unset(component)
- if(ARGC GREATER 6)
- set(component ${ARGV6})
- endif()
-
- if(QT_LIBRARY_DIR)
- list(APPEND dirs "${QT_LIBRARY_DIR}")
- endif()
- if(QT_BINARY_DIR)
- list(APPEND dirs "${QT_BINARY_DIR}")
- endif()
- if(component)
- set(component COMPONENT ${component})
- else()
- unset(component)
- endif()
-
- get_filename_component(executable_absolute "${executable}" ABSOLUTE)
- if(EXISTS "${QT_QTCORE_LIBRARY_RELEASE}")
- gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_RELEASE}" qtcore_type)
- elseif(EXISTS "${QT_QTCORE_LIBRARY_DEBUG}")
- gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_DEBUG}" qtcore_type)
- endif()
- if(qtcore_type STREQUAL "system")
- set(qt_plugins_dir "")
- endif()
-
- if(QT_IS_STATIC)
- message(WARNING "Qt built statically: not installing plugins.")
- else()
- foreach(plugin ${qtplugins})
- set(installed_plugin_paths "")
- install_qt4_plugin("${plugin}" "${executable}" 0 installed_plugin_paths "${plugins_dir}" "${component}")
- list(APPEND libs ${installed_plugin_paths})
- endforeach()
- endif()
-
- resolve_qt4_paths(libs "")
-
- install(CODE
- "include(\"${DeployQt4_cmake_dir}/DeployQt4.cmake\")
- set(BU_CHMOD_BUNDLE_ITEMS TRUE)
- FIXUP_QT4_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")"
- ${component}
- )
+ unset(qtplugins)
+ if(ARGC GREATER 1)
+ set(qtplugins ${ARGV1})
+ endif()
+ unset(libs)
+ if(ARGC GREATER 2)
+ set(libs ${ARGV2})
+ endif()
+ unset(dirs)
+ if(ARGC GREATER 3)
+ set(dirs ${ARGV3})
+ endif()
+ unset(plugins_dir)
+ if(ARGC GREATER 4)
+ set(plugins_dir ${ARGV4})
+ endif()
+ unset(request_qt_conf)
+ if(ARGC GREATER 5)
+ set(request_qt_conf ${ARGV5})
+ endif()
+ unset(component)
+ if(ARGC GREATER 6)
+ set(component ${ARGV6})
+ endif()
+
+ if(QT_LIBRARY_DIR)
+ list(APPEND dirs "${QT_LIBRARY_DIR}")
+ endif()
+ if(QT_BINARY_DIR)
+ list(APPEND dirs "${QT_BINARY_DIR}")
+ endif()
+ if(component)
+ set(component COMPONENT ${component})
+ else()
+ unset(component)
+ endif()
+
+ get_filename_component(executable_absolute "${executable}" ABSOLUTE)
+ if(EXISTS "${QT_QTCORE_LIBRARY_RELEASE}")
+ gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_RELEASE}" qtcore_type)
+ elseif(EXISTS "${QT_QTCORE_LIBRARY_DEBUG}")
+ gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_DEBUG}" qtcore_type)
+ endif()
+ if(qtcore_type STREQUAL "system")
+ set(qt_plugins_dir "")
+ endif()
+
+ if(QT_IS_STATIC)
+ message(WARNING "Qt built statically: not installing plugins.")
+ else()
+ foreach(plugin ${qtplugins})
+ set(installed_plugin_paths "")
+ install_qt4_plugin("${plugin}" "${executable}" 0 installed_plugin_paths "${plugins_dir}" "${component}")
+ list(APPEND libs ${installed_plugin_paths})
+ endforeach()
+ endif()
+
+ resolve_qt4_paths(libs "")
+
+ install(CODE
+"include(\"${DeployQt4_cmake_dir}/DeployQt4.cmake\")
+set(BU_CHMOD_BUNDLE_ITEMS TRUE)
+FIXUP_QT4_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")"
+ ${component}
+ )
endfunction()
# We loop through ARGN and consider the namespace starting with an
# upper-case letter followed by at least two more upper-case letters,
# numbers or underscores to be keywords.
+
+ if(NOT DEFINED _ExternalProject_SELF)
+ message(FATAL_ERROR "error: ExternalProject module must be explicitly included before using ${f} function")
+ endif()
+
set(key)
foreach(arg IN LISTS args)
set(BISON_TARGET_verbose_file "${ReportFile}")
list(APPEND BISON_TARGET_cmdopt "--report-file=${BISON_TARGET_verbose_file}")
endif()
+ if(NOT IS_ABSOLUTE "${BISON_TARGET_verbose_file}")
+ set(BISON_TARGET_verbose_file "${CMAKE_CURRENT_SOURCE_DIR}/${BISON_TARGET_verbose_file}")
+ endif()
endmacro()
# internal macro
# adds a custom command and sets
- # BISON_TARGET_cmdopt, BISON_TARGET_verbose_file, BISON_TARGET_extraoutputs
+ # BISON_TARGET_cmdopt, BISON_TARGET_extraoutputs
macro(BISON_TARGET_option_verbose Name BisonOutput filename)
list(APPEND BISON_TARGET_cmdopt "--verbose")
- list(APPEND BISON_TARGET_extraoutputs
+ list(APPEND BISON_TARGET_outputs
"${BISON_TARGET_verbose_file}")
if (NOT "${filename}" STREQUAL "")
- add_custom_command(OUTPUT ${filename}
+ if(IS_ABSOLUTE "${filename}")
+ set(BISON_TARGET_verbose_extra_file "${filename}")
+ else()
+ set(BISON_TARGET_verbose_extra_file "${CMAKE_CURRENT_SOURCE_DIR}/${filename}")
+ endif()
+ add_custom_command(OUTPUT ${BISON_TARGET_verbose_extra_file}
COMMAND ${CMAKE_COMMAND} -E copy
"${BISON_TARGET_verbose_file}"
"${filename}"
DEPENDS
"${BISON_TARGET_verbose_file}"
COMMENT "[BISON][${Name}] Copying bison verbose table to ${filename}"
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
- set(BISON_${Name}_VERBOSE_FILE ${filename})
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
list(APPEND BISON_TARGET_extraoutputs
- "${filename}")
+ "${BISON_TARGET_verbose_extra_file}")
+ unset(BISON_TARGET_verbose_extra_file)
endif()
endmacro()
list(APPEND BISON_TARGET_outputs "${BISON_TARGET_output_header}")
add_custom_command(OUTPUT ${BISON_TARGET_outputs}
- ${BISON_TARGET_extraoutputs}
COMMAND ${BISON_EXECUTABLE} ${BISON_TARGET_cmdopt} -o ${BisonOutput} ${BisonInput}
VERBATIM
DEPENDS ${BisonInput}
# BLAS_LINKER_FLAGS - uncached list of required linker flags (excluding -l
# and -L).
# BLAS_LIBRARIES - uncached list of libraries (using full path name) to
-# link against to use BLAS
+# link against to use BLAS (may be empty if compiler implicitly links
+# BLAS)
# BLAS95_LIBRARIES - uncached list of libraries (using full path name)
# to link against to use BLAS95 interface
# BLAS95_FOUND - set to true if a library implementing the BLAS f95 interface
# * SGIMATH
# * IBMESSL
# * Intel10_32 (intel mkl v10 32 bit)
-# * Intel10_64lp (intel mkl v10 64 bit, lp thread model, lp64 model)
-# * Intel10_64lp_seq (intel mkl v10 64 bit, sequential code, lp64 model)
+# * Intel10_64lp (intel mkl v10+ 64 bit, threaded code, lp64 model)
+# * Intel10_64lp_seq (intel mkl v10+ 64 bit, sequential code, lp64 model)
+# * Intel10_64ilp (intel mkl v10+ 64 bit, threaded code, ilp64 model)
+# * Intel10_64ilp_seq (intel mkl v10+ 64 bit, sequential code, ilp64 model)
# * Intel (older versions of mkl 32 and 64 bit)
# * ACML
# * ACML_MP
find_package(PkgConfig)
pkg_check_modules(PKGC_BLAS blas)
if(PKGC_BLAS_FOUND)
+ set(BLAS_FOUND ${PKGC_BLAS_FOUND})
set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}")
return()
endif()
endif()
macro(Check_Fortran_Libraries LIBRARIES _prefix _name _flags _list _thread)
-# This macro checks for the existence of the combination of fortran libraries
-# given by _list. If the combination is found, this macro checks (using the
-# Check_Fortran_Function_Exists macro) whether can link against that library
-# combination using the name of a routine given by _name using the linker
-# flags given by _flags. If the combination of libraries is found and passes
-# the link test, LIBRARIES is set to the list of complete library paths that
-# have been found. Otherwise, LIBRARIES is set to FALSE.
-
-# N.B. _prefix is the prefix applied to the names of all cached variables that
-# are generated internally and marked advanced by this macro.
-
-set(_libdir ${ARGN})
-
-set(_libraries_work TRUE)
-set(${LIBRARIES})
-set(_combined_name)
-if (NOT _libdir)
- if (WIN32)
- set(_libdir ENV LIB)
- elseif (APPLE)
- set(_libdir ENV DYLD_LIBRARY_PATH)
- else ()
- set(_libdir ENV LD_LIBRARY_PATH)
+ # This macro checks for the existence of the combination of fortran libraries
+ # given by _list. If the combination is found, this macro checks (using the
+ # Check_Fortran_Function_Exists macro) whether can link against that library
+ # combination using the name of a routine given by _name using the linker
+ # flags given by _flags. If the combination of libraries is found and passes
+ # the link test, LIBRARIES is set to the list of complete library paths that
+ # have been found. Otherwise, LIBRARIES is set to FALSE.
+
+ # N.B. _prefix is the prefix applied to the names of all cached variables that
+ # are generated internally and marked advanced by this macro.
+
+ set(_libdir ${ARGN})
+
+ set(_libraries_work TRUE)
+ set(${LIBRARIES})
+ set(_combined_name)
+ if (NOT _libdir)
+ if (WIN32)
+ set(_libdir ENV LIB)
+ elseif (APPLE)
+ set(_libdir ENV DYLD_LIBRARY_PATH)
+ else ()
+ set(_libdir ENV LD_LIBRARY_PATH)
+ endif ()
endif ()
-endif ()
-foreach(_library ${_list})
- set(_combined_name ${_combined_name}_${_library})
+ foreach(_library ${_list})
+ set(_combined_name ${_combined_name}_${_library})
- if(_libraries_work)
- if (BLA_STATIC)
- if (WIN32)
- set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
- endif ()
- if (APPLE)
- set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ if(_libraries_work)
+ if (BLA_STATIC)
+ if (WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ endif ()
+ if (APPLE)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ else ()
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ endif ()
else ()
- set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
- endif ()
- else ()
- if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
- # for ubuntu's libblas3gf and liblapack3gf packages
- set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf)
+ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ # for ubuntu's libblas3gf and liblapack3gf packages
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES} .so.3gf)
+ endif ()
endif ()
- endif ()
- find_library(${_prefix}_${_library}_LIBRARY
- NAMES ${_library}
- PATHS ${_libdir}
- )
- mark_as_advanced(${_prefix}_${_library}_LIBRARY)
- set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
- set(_libraries_work ${${_prefix}_${_library}_LIBRARY})
+ find_library(${_prefix}_${_library}_LIBRARY
+ NAMES ${_library}
+ PATHS ${_libdir}
+ )
+ mark_as_advanced(${_prefix}_${_library}_LIBRARY)
+ set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
+ set(_libraries_work ${${_prefix}_${_library}_LIBRARY})
+ endif()
+ endforeach()
+ if(_libraries_work)
+ # Test this combination of libraries.
+ set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_thread})
+ # message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}")
+ if (CMAKE_Fortran_COMPILER_LOADED)
+ check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS)
+ else()
+ check_function_exists("${_name}_" ${_prefix}${_combined_name}_WORKS)
+ endif()
+ set(CMAKE_REQUIRED_LIBRARIES)
+ mark_as_advanced(${_prefix}${_combined_name}_WORKS)
+ set(_libraries_work ${${_prefix}${_combined_name}_WORKS})
endif()
-endforeach()
-if(_libraries_work)
- # Test this combination of libraries.
- set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_thread})
-# message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}")
- if (CMAKE_Fortran_COMPILER_LOADED)
- check_fortran_function_exists("${_name}" ${_prefix}${_combined_name}_WORKS)
+ if(_libraries_work)
+ if("${_list}" STREQUAL "")
+ set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
+ endif()
else()
- check_function_exists("${_name}_" ${_prefix}${_combined_name}_WORKS)
+ set(${LIBRARIES} FALSE)
endif()
- set(CMAKE_REQUIRED_LIBRARIES)
- mark_as_advanced(${_prefix}${_combined_name}_WORKS)
- set(_libraries_work ${${_prefix}${_combined_name}_WORKS})
-endif()
-if(NOT _libraries_work)
- set(${LIBRARIES} FALSE)
-endif()
-#message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}")
+ #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}")
endmacro()
set(BLAS_LINKER_FLAGS)
endif()
endif ()
+if (BLA_VENDOR STREQUAL "All")
+ if(NOT BLAS_LIBRARIES)
+ # Implicitly linked BLAS libraries
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ ""
+ ""
+ )
+ endif()
+endif ()
+
+#BLAS in intel mkl 10+ library? (em64t 64bit)
+if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
+ if (NOT BLAS_LIBRARIES)
+ if (BLA_VENDOR MATCHES "_64ilp")
+ set(BLAS_mkl_ILP_MODE "ilp64")
+ else ()
+ set(BLAS_mkl_ILP_MODE "lp64")
+ endif ()
+ if (NOT WIN32)
+ set(LM "-lm")
+ endif ()
+ if (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED)
+ if(BLAS_FIND_QUIETLY OR NOT BLAS_FIND_REQUIRED)
+ find_package(Threads)
+ else()
+ find_package(Threads REQUIRED)
+ endif()
+
+ set(BLAS_SEARCH_LIBS "")
+
+ if(BLA_F95)
+ set(BLAS_mkl_SEARCH_SYMBOL sgemm_f95)
+ set(_LIBRARIES BLAS95_LIBRARIES)
+ if (WIN32)
+ if (BLA_STATIC)
+ set(BLAS_mkl_DLL_SUFFIX "")
+ else()
+ set(BLAS_mkl_DLL_SUFFIX "_dll")
+ endif()
+
+ # Find the main file (32-bit or 64-bit)
+ set(BLAS_SEARCH_LIBS_WIN_MAIN "")
+ if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
+ "mkl_blas95${BLAS_mkl_DLL_SUFFIX} mkl_intel_c${BLAS_mkl_DLL_SUFFIX}")
+ endif()
+ if (BLA_VENDOR MATCHES "^Intel10_64i?lp" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
+ "mkl_blas95_${BLAS_mkl_ILP_MODE}${BLAS_mkl_DLL_SUFFIX} mkl_intel_${BLAS_mkl_ILP_MODE}${BLAS_mkl_DLL_SUFFIX}")
+ endif ()
+
+ # Add threading/sequential libs
+ set(BLAS_SEARCH_LIBS_WIN_THREAD "")
+ if (BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
+ "mkl_sequential${BLAS_mkl_DLL_SUFFIX}")
+ endif()
+ if (NOT BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
+ # old version
+ list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
+ "libguide40 mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
+ # mkl >= 10.3
+ list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
+ "libiomp5md mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
+ endif()
+
+ # Cartesian product of the above
+ foreach (MAIN ${BLAS_SEARCH_LIBS_WIN_MAIN})
+ foreach (THREAD ${BLAS_SEARCH_LIBS_WIN_THREAD})
+ list(APPEND BLAS_SEARCH_LIBS
+ "${MAIN} ${THREAD} mkl_core${BLAS_mkl_DLL_SUFFIX}")
+ endforeach()
+ endforeach()
+ else ()
+ if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_blas95 mkl_intel mkl_intel_thread mkl_core guide")
+ endif ()
+ if (BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
+ # old version
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_blas95 mkl_intel_${BLAS_mkl_ILP_MODE} mkl_intel_thread mkl_core guide")
+
+ # mkl >= 10.3
+ if (CMAKE_C_COMPILER MATCHES ".+gcc")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_intel_${BLAS_mkl_ILP_MODE} mkl_gnu_thread mkl_core gomp")
+ else ()
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_intel_${BLAS_mkl_ILP_MODE} mkl_intel_thread mkl_core iomp5")
+ endif ()
+ endif ()
+ if (BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_blas95_${BLAS_mkl_ILP_MODE} mkl_intel_${BLAS_mkl_ILP_MODE} mkl_sequential mkl_core")
+ endif ()
+ endif ()
+ else ()
+ set(BLAS_mkl_SEARCH_SYMBOL sgemm)
+ set(_LIBRARIES BLAS_LIBRARIES)
+ if (WIN32)
+ if (BLA_STATIC)
+ set(BLAS_mkl_DLL_SUFFIX "")
+ else()
+ set(BLAS_mkl_DLL_SUFFIX "_dll")
+ endif()
+
+ # Find the main file (32-bit or 64-bit)
+ set(BLAS_SEARCH_LIBS_WIN_MAIN "")
+ if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
+ "mkl_intel_c${BLAS_mkl_DLL_SUFFIX}")
+ endif()
+ if (BLA_VENDOR MATCHES "^Intel10_64i?lp" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
+ "mkl_intel_${BLAS_mkl_ILP_MODE}${BLAS_mkl_DLL_SUFFIX}")
+ endif ()
+
+ # Add threading/sequential libs
+ set(BLAS_SEARCH_LIBS_WIN_THREAD "")
+ if (NOT BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
+ # old version
+ list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
+ "libguide40 mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
+ # mkl >= 10.3
+ list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
+ "libiomp5md mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
+ endif()
+ if (BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
+ "mkl_sequential${BLAS_mkl_DLL_SUFFIX}")
+ endif()
+
+ # Cartesian product of the above
+ foreach (MAIN ${BLAS_SEARCH_LIBS_WIN_MAIN})
+ foreach (THREAD ${BLAS_SEARCH_LIBS_WIN_THREAD})
+ list(APPEND BLAS_SEARCH_LIBS
+ "${MAIN} ${THREAD} mkl_core${BLAS_mkl_DLL_SUFFIX}")
+ endforeach()
+ endforeach()
+ else ()
+ if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_intel mkl_intel_thread mkl_core guide")
+ endif ()
+ if (BLA_VENDOR MATCHES "^Intel10_64i?lp$" OR BLA_VENDOR STREQUAL "All")
+
+ # old version
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_intel_${BLAS_mkl_ILP_MODE} mkl_intel_thread mkl_core guide")
+
+ # mkl >= 10.3
+ if (CMAKE_C_COMPILER MATCHES ".+gcc")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_intel_${BLAS_mkl_ILP_MODE} mkl_gnu_thread mkl_core gomp")
+ else ()
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_intel_${BLAS_mkl_ILP_MODE} mkl_intel_thread mkl_core iomp5")
+ endif ()
+ endif ()
+ if (BLA_VENDOR MATCHES "^Intel10_64i?lp_seq$" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_intel_${BLAS_mkl_ILP_MODE} mkl_sequential mkl_core")
+ endif ()
+
+ #older vesions of intel mkl libs
+ if (BLA_VENDOR STREQUAL "Intel" OR BLA_VENDOR STREQUAL "All")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_ia32")
+ list(APPEND BLAS_SEARCH_LIBS
+ "mkl_em64t")
+ endif ()
+ endif ()
+ endif ()
+
+ foreach (IT ${BLAS_SEARCH_LIBS})
+ string(REPLACE " " ";" SEARCH_LIBS ${IT})
+ if (NOT ${_LIBRARIES})
+ check_fortran_libraries(
+ ${_LIBRARIES}
+ BLAS
+ ${BLAS_mkl_SEARCH_SYMBOL}
+ ""
+ "${SEARCH_LIBS}"
+ "${CMAKE_THREAD_LIBS_INIT};${LM}"
+ )
+ endif ()
+ endforeach ()
+
+ endif ()
+ unset(BLAS_mkl_ILP_MODE)
+ endif ()
+endif ()
+
if (BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- # gotoblas (http://www.tacc.utexas.edu/tacc-projects/gotoblas2)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "goto2"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ # gotoblas (http://www.tacc.utexas.edu/tacc-projects/gotoblas2)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "goto2"
+ ""
+ )
+ endif()
endif ()
if (BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- # OpenBLAS (http://www.openblas.net)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "openblas"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ # OpenBLAS (http://www.openblas.net)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "openblas"
+ ""
+ )
+ endif()
endif ()
if (BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- # FLAME's blis library (https://github.com/flame/blis)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "blis"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ # FLAME's blis library (https://github.com/flame/blis)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "blis"
+ ""
+ )
+ endif()
endif ()
if (BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- dgemm
- ""
- "f77blas;atlas"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ dgemm
+ ""
+ "f77blas;atlas"
+ ""
+ )
+ endif()
endif ()
# BLAS in PhiPACK libraries? (requires generic BLAS lib, too)
if (BLA_VENDOR STREQUAL "PhiPACK" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "sgemm;dgemm;blas"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "sgemm;dgemm;blas"
+ ""
+ )
+ endif()
endif ()
# BLAS in Alpha CXML library?
if (BLA_VENDOR STREQUAL "CXML" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "cxml"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "cxml"
+ ""
+ )
+ endif()
endif ()
# BLAS in Alpha DXML library? (now called CXML, see above)
if (BLA_VENDOR STREQUAL "DXML" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "dxml"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "dxml"
+ ""
+ )
+ endif()
endif ()
# BLAS in Sun Performance library?
if (BLA_VENDOR STREQUAL "SunPerf" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- "-xlic_lib=sunperf"
- "sunperf;sunmath"
- ""
- )
- if(BLAS_LIBRARIES)
- set(BLAS_LINKER_FLAGS "-xlic_lib=sunperf")
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ "-xlic_lib=sunperf"
+ "sunperf;sunmath"
+ ""
+ )
+ if(BLAS_LIBRARIES)
+ set(BLAS_LINKER_FLAGS "-xlic_lib=sunperf")
+ endif()
endif()
- endif()
endif ()
# BLAS in SCSL library? (SGI/Cray Scientific Library)
if (BLA_VENDOR STREQUAL "SCSL" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "scsl"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "scsl"
+ ""
+ )
+ endif()
endif ()
# BLAS in SGIMATH library?
if (BLA_VENDOR STREQUAL "SGIMATH" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "complib.sgimath"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "complib.sgimath"
+ ""
+ )
+ endif()
endif ()
# BLAS in IBM ESSL library? (requires generic BLAS lib, too)
if (BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "essl;blas"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "essl;blas"
+ ""
+ )
+ endif()
endif ()
#BLAS in acml library?
if (BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All")
- if( ((BLA_VENDOR STREQUAL "ACML") AND (NOT BLAS_ACML_LIB_DIRS)) OR
- ((BLA_VENDOR STREQUAL "ACML_MP") AND (NOT BLAS_ACML_MP_LIB_DIRS)) OR
- ((BLA_VENDOR STREQUAL "ACML_GPU") AND (NOT BLAS_ACML_GPU_LIB_DIRS))
- )
- # try to find acml in "standard" paths
- if( WIN32 )
+ if( ((BLA_VENDOR STREQUAL "ACML") AND (NOT BLAS_ACML_LIB_DIRS)) OR
+ ((BLA_VENDOR STREQUAL "ACML_MP") AND (NOT BLAS_ACML_MP_LIB_DIRS)) OR
+ ((BLA_VENDOR STREQUAL "ACML_GPU") AND (NOT BLAS_ACML_GPU_LIB_DIRS))
+ )
+ # try to find acml in "standard" paths
+ if( WIN32 )
file( GLOB _ACML_ROOT "C:/AMD/acml*/ACML-EULA.txt" )
- else()
+ else()
file( GLOB _ACML_ROOT "/opt/acml*/ACML-EULA.txt" )
- endif()
- if( WIN32 )
+ endif()
+ if( WIN32 )
file( GLOB _ACML_GPU_ROOT "C:/AMD/acml*/GPGPUexamples" )
- else()
+ else()
file( GLOB _ACML_GPU_ROOT "/opt/acml*/GPGPUexamples" )
- endif()
- list(GET _ACML_ROOT 0 _ACML_ROOT)
- list(GET _ACML_GPU_ROOT 0 _ACML_GPU_ROOT)
- if( _ACML_ROOT )
+ endif()
+ list(GET _ACML_ROOT 0 _ACML_ROOT)
+ list(GET _ACML_GPU_ROOT 0 _ACML_GPU_ROOT)
+ if( _ACML_ROOT )
get_filename_component( _ACML_ROOT ${_ACML_ROOT} PATH )
if( SIZEOF_INTEGER EQUAL 8 )
- set( _ACML_PATH_SUFFIX "_int64" )
+ set( _ACML_PATH_SUFFIX "_int64" )
+ else()
+ set( _ACML_PATH_SUFFIX "" )
+ endif()
+ if( CMAKE_Fortran_COMPILER_ID STREQUAL "Intel" )
+ set( _ACML_COMPILER32 "ifort32" )
+ set( _ACML_COMPILER64 "ifort64" )
+ elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "SunPro" )
+ set( _ACML_COMPILER32 "sun32" )
+ set( _ACML_COMPILER64 "sun64" )
+ elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "PGI" )
+ set( _ACML_COMPILER32 "pgi32" )
+ if( WIN32 )
+ set( _ACML_COMPILER64 "win64" )
+ else()
+ set( _ACML_COMPILER64 "pgi64" )
+ endif()
+ elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "Open64" )
+ # 32 bit builds not supported on Open64 but for code simplicity
+ # We'll just use the same directory twice
+ set( _ACML_COMPILER32 "open64_64" )
+ set( _ACML_COMPILER64 "open64_64" )
+ elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "NAG" )
+ set( _ACML_COMPILER32 "nag32" )
+ set( _ACML_COMPILER64 "nag64" )
else()
- set( _ACML_PATH_SUFFIX "" )
- endif()
- if( CMAKE_Fortran_COMPILER_ID STREQUAL "Intel" )
- set( _ACML_COMPILER32 "ifort32" )
- set( _ACML_COMPILER64 "ifort64" )
- elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "SunPro" )
- set( _ACML_COMPILER32 "sun32" )
- set( _ACML_COMPILER64 "sun64" )
- elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "PGI" )
- set( _ACML_COMPILER32 "pgi32" )
- if( WIN32 )
- set( _ACML_COMPILER64 "win64" )
+ set( _ACML_COMPILER32 "gfortran32" )
+ set( _ACML_COMPILER64 "gfortran64" )
+ endif()
+
+ if( BLA_VENDOR STREQUAL "ACML_MP" )
+ set(_ACML_MP_LIB_DIRS
+ "${_ACML_ROOT}/${_ACML_COMPILER32}_mp${_ACML_PATH_SUFFIX}/lib"
+ "${_ACML_ROOT}/${_ACML_COMPILER64}_mp${_ACML_PATH_SUFFIX}/lib" )
else()
- set( _ACML_COMPILER64 "pgi64" )
+ set(_ACML_LIB_DIRS
+ "${_ACML_ROOT}/${_ACML_COMPILER32}${_ACML_PATH_SUFFIX}/lib"
+ "${_ACML_ROOT}/${_ACML_COMPILER64}${_ACML_PATH_SUFFIX}/lib" )
endif()
- elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "Open64" )
- # 32 bit builds not supported on Open64 but for code simplicity
- # We'll just use the same directory twice
- set( _ACML_COMPILER32 "open64_64" )
- set( _ACML_COMPILER64 "open64_64" )
- elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "NAG" )
- set( _ACML_COMPILER32 "nag32" )
- set( _ACML_COMPILER64 "nag64" )
- else()
- set( _ACML_COMPILER32 "gfortran32" )
- set( _ACML_COMPILER64 "gfortran64" )
- endif()
-
- if( BLA_VENDOR STREQUAL "ACML_MP" )
- set(_ACML_MP_LIB_DIRS
- "${_ACML_ROOT}/${_ACML_COMPILER32}_mp${_ACML_PATH_SUFFIX}/lib"
- "${_ACML_ROOT}/${_ACML_COMPILER64}_mp${_ACML_PATH_SUFFIX}/lib" )
- else()
- set(_ACML_LIB_DIRS
- "${_ACML_ROOT}/${_ACML_COMPILER32}${_ACML_PATH_SUFFIX}/lib"
- "${_ACML_ROOT}/${_ACML_COMPILER64}${_ACML_PATH_SUFFIX}/lib" )
- endif()
endif()
- elseif(BLAS_${BLA_VENDOR}_LIB_DIRS)
- set(_${BLA_VENDOR}_LIB_DIRS ${BLAS_${BLA_VENDOR}_LIB_DIRS})
- endif()
+elseif(BLAS_${BLA_VENDOR}_LIB_DIRS)
+ set(_${BLA_VENDOR}_LIB_DIRS ${BLAS_${BLA_VENDOR}_LIB_DIRS})
+endif()
- if( BLA_VENDOR STREQUAL "ACML_MP" )
+if( BLA_VENDOR STREQUAL "ACML_MP" )
foreach( BLAS_ACML_MP_LIB_DIRS ${_ACML_MP_LIB_DIRS})
- check_fortran_libraries (
- BLAS_LIBRARIES
- BLAS
- sgemm
- "" "acml_mp;acml_mv" "" ${BLAS_ACML_MP_LIB_DIRS}
- )
- if( BLAS_LIBRARIES )
- break()
- endif()
+ check_fortran_libraries (
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ "" "acml_mp;acml_mv" "" ${BLAS_ACML_MP_LIB_DIRS}
+ )
+ if( BLAS_LIBRARIES )
+ break()
+ endif()
endforeach()
- elseif( BLA_VENDOR STREQUAL "ACML_GPU" )
+elseif( BLA_VENDOR STREQUAL "ACML_GPU" )
foreach( BLAS_ACML_GPU_LIB_DIRS ${_ACML_GPU_LIB_DIRS})
- check_fortran_libraries (
- BLAS_LIBRARIES
- BLAS
- sgemm
- "" "acml;acml_mv;CALBLAS" "" ${BLAS_ACML_GPU_LIB_DIRS}
- )
- if( BLAS_LIBRARIES )
- break()
- endif()
+ check_fortran_libraries (
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ "" "acml;acml_mv;CALBLAS" "" ${BLAS_ACML_GPU_LIB_DIRS}
+ )
+ if( BLAS_LIBRARIES )
+ break()
+ endif()
endforeach()
- else()
+else()
foreach( BLAS_ACML_LIB_DIRS ${_ACML_LIB_DIRS} )
- check_fortran_libraries (
- BLAS_LIBRARIES
- BLAS
- sgemm
- "" "acml;acml_mv" "" ${BLAS_ACML_LIB_DIRS}
- )
- if( BLAS_LIBRARIES )
- break()
- endif()
+ check_fortran_libraries (
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ "" "acml;acml_mv" "" ${BLAS_ACML_LIB_DIRS}
+ )
+ if( BLAS_LIBRARIES )
+ break()
+ endif()
endforeach()
- endif()
+endif()
- # Either acml or acml_mp should be in LD_LIBRARY_PATH but not both
- if(NOT BLAS_LIBRARIES)
+# Either acml or acml_mp should be in LD_LIBRARY_PATH but not both
+if(NOT BLAS_LIBRARIES)
check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "acml;acml_mv"
- ""
- )
- endif()
- if(NOT BLAS_LIBRARIES)
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "acml;acml_mv"
+ ""
+ )
+endif()
+if(NOT BLAS_LIBRARIES)
check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "acml_mp;acml_mv"
- ""
- )
- endif()
- if(NOT BLAS_LIBRARIES)
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "acml_mp;acml_mv"
+ ""
+ )
+endif()
+if(NOT BLAS_LIBRARIES)
check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "acml;acml_mv;CALBLAS"
- ""
- )
- endif()
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "acml;acml_mv;CALBLAS"
+ ""
+ )
+endif()
endif () # ACML
# Apple BLAS library?
if (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All")
-if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- dgemm
- ""
- "Accelerate"
- ""
- )
- endif()
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ dgemm
+ ""
+ "Accelerate"
+ ""
+ )
+ endif()
endif ()
if (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All")
- if ( NOT BLAS_LIBRARIES )
+ if ( NOT BLAS_LIBRARIES )
check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- dgemm
- ""
- "vecLib"
- ""
- )
- endif ()
+ BLAS_LIBRARIES
+ BLAS
+ dgemm
+ ""
+ "vecLib"
+ ""
+ )
+ endif ()
endif ()
+
# Generic BLAS library?
if (BLA_VENDOR STREQUAL "Generic" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_fortran_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "blas"
- ""
- )
- endif()
-endif ()
-
-#BLAS in intel mkl 10 library? (em64t 64bit)
-if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
- if (NOT WIN32)
- set(LM "-lm")
- endif ()
- if (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED)
- if(BLAS_FIND_QUIETLY OR NOT BLAS_FIND_REQUIRED)
- find_package(Threads)
- else()
- find_package(Threads REQUIRED)
+ if(NOT BLAS_LIBRARIES)
+ check_fortran_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "blas"
+ ""
+ )
endif()
-
- set(BLAS_SEARCH_LIBS "")
-
- if(BLA_F95)
- set(BLAS_mkl_SEARCH_SYMBOL SGEMM)
- set(_LIBRARIES BLAS95_LIBRARIES)
- if (WIN32)
- if (BLA_STATIC)
- set(BLAS_mkl_DLL_SUFFIX "")
- else()
- set(BLAS_mkl_DLL_SUFFIX "_dll")
- endif()
-
- # Find the main file (32-bit or 64-bit)
- set(BLAS_SEARCH_LIBS_WIN_MAIN "")
- if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
- "mkl_blas95${BLAS_mkl_DLL_SUFFIX} mkl_intel_c${BLAS_mkl_DLL_SUFFIX}")
- endif()
- if (BLA_VENDOR MATCHES "^Intel10_64lp" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
- "mkl_blas95_lp64${BLAS_mkl_DLL_SUFFIX} mkl_intel_lp64${BLAS_mkl_DLL_SUFFIX}")
- endif ()
-
- # Add threading/sequential libs
- set(BLAS_SEARCH_LIBS_WIN_THREAD "")
- if (BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
- "mkl_sequential${BLAS_mkl_DLL_SUFFIX}")
- endif()
- if (NOT BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
- # old version
- list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
- "libguide40 mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
- # mkl >= 10.3
- list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
- "libiomp5md mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
- endif()
-
- # Cartesian product of the above
- foreach (MAIN ${BLAS_SEARCH_LIBS_WIN_MAIN})
- foreach (THREAD ${BLAS_SEARCH_LIBS_WIN_THREAD})
- list(APPEND BLAS_SEARCH_LIBS
- "${MAIN} ${THREAD} mkl_core${BLAS_mkl_DLL_SUFFIX}")
- endforeach()
- endforeach()
- else ()
- if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_blas95 mkl_intel mkl_intel_thread mkl_core guide")
- endif ()
- if (BLA_VENDOR STREQUAL "Intel10_64lp" OR BLA_VENDOR STREQUAL "All")
- # old version
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_blas95 mkl_intel_lp64 mkl_intel_thread mkl_core guide")
-
- # mkl >= 10.3
- if (CMAKE_C_COMPILER MATCHES ".+gcc")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_blas95_lp64 mkl_intel_lp64 mkl_gnu_thread mkl_core gomp")
- else ()
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_blas95_lp64 mkl_intel_lp64 mkl_intel_thread mkl_core iomp5")
- endif ()
- endif ()
- if (BLA_VENDOR STREQUAL "Intel10_64lp_seq" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_intel_lp64 mkl_sequential mkl_core")
- endif ()
- endif ()
- else ()
- set(BLAS_mkl_SEARCH_SYMBOL sgemm)
- set(_LIBRARIES BLAS_LIBRARIES)
- if (WIN32)
- if (BLA_STATIC)
- set(BLAS_mkl_DLL_SUFFIX "")
- else()
- set(BLAS_mkl_DLL_SUFFIX "_dll")
- endif()
-
- # Find the main file (32-bit or 64-bit)
- set(BLAS_SEARCH_LIBS_WIN_MAIN "")
- if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
- "mkl_intel_c${BLAS_mkl_DLL_SUFFIX}")
- endif()
- if (BLA_VENDOR MATCHES "^Intel10_64lp" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS_WIN_MAIN
- "mkl_intel_lp64${BLAS_mkl_DLL_SUFFIX}")
- endif ()
-
- # Add threading/sequential libs
- set(BLAS_SEARCH_LIBS_WIN_THREAD "")
- if (NOT BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
- # old version
- list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
- "libguide40 mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
- # mkl >= 10.3
- list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
- "libiomp5md mkl_intel_thread${BLAS_mkl_DLL_SUFFIX}")
- endif()
- if (BLA_VENDOR MATCHES "_seq$" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS_WIN_THREAD
- "mkl_sequential${BLAS_mkl_DLL_SUFFIX}")
- endif()
-
- # Cartesian product of the above
- foreach (MAIN ${BLAS_SEARCH_LIBS_WIN_MAIN})
- foreach (THREAD ${BLAS_SEARCH_LIBS_WIN_THREAD})
- list(APPEND BLAS_SEARCH_LIBS
- "${MAIN} ${THREAD} mkl_core${BLAS_mkl_DLL_SUFFIX}")
- endforeach()
- endforeach()
- else ()
- if (BLA_VENDOR STREQUAL "Intel10_32" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_intel mkl_intel_thread mkl_core guide")
- endif ()
- if (BLA_VENDOR STREQUAL "Intel10_64lp" OR BLA_VENDOR STREQUAL "All")
-
- # old version
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_intel_lp64 mkl_intel_thread mkl_core guide")
-
- # mkl >= 10.3
- if (CMAKE_C_COMPILER MATCHES ".+gcc")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_intel_lp64 mkl_gnu_thread mkl_core gomp")
- else ()
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_intel_lp64 mkl_intel_thread mkl_core iomp5")
- endif ()
- endif ()
- if (BLA_VENDOR STREQUAL "Intel10_64lp_seq" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_intel_lp64 mkl_sequential mkl_core")
- endif ()
-
- #older vesions of intel mkl libs
- if (BLA_VENDOR STREQUAL "Intel" OR BLA_VENDOR STREQUAL "All")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_ia32")
- list(APPEND BLAS_SEARCH_LIBS
- "mkl_em64t")
- endif ()
- endif ()
- endif ()
-
- foreach (IT ${BLAS_SEARCH_LIBS})
- string(REPLACE " " ";" SEARCH_LIBS ${IT})
- if (NOT ${_LIBRARIES})
- check_fortran_libraries(
- ${_LIBRARIES}
- BLAS
- ${BLAS_mkl_SEARCH_SYMBOL}
- ""
- "${SEARCH_LIBS}"
- "${CMAKE_THREAD_LIBS_INIT};${LM}"
- )
- endif ()
- endforeach ()
-
- endif ()
endif ()
if(BLA_F95)
find_package_handle_standard_args(BLAS REQUIRED_VARS BLAS_LIBRARIES)
endif()
+# On compilers that implicitly link BLAS (such as ftn, cc, and CC on Cray HPC machines)
+# we used a placeholder for empty BLAS_LIBRARIES to get through our logic above.
+if (BLAS_LIBRARIES STREQUAL "BLAS_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
+ set(BLAS_LIBRARIES "")
+endif()
+
cmake_pop_check_state()
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_blas_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
# used if multiple compatible suffixes should
# be tested for, in decreasing order of
# preference.
+# Boost_ARCHITECTURE - Set to the architecture-specific library suffix
+# (e.g. "-x64"). Default is auto-computed for the
+# C++ compiler in use.
# Boost_THREADAPI - Suffix for "thread" component library name,
# such as "pthread" or "win32". Names with
# and without this suffix will both be tried.
# Runs compiler with "-dumpversion" and parses major/minor
# version with a regex.
#
-function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION)
- string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\1\\2"
- _boost_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
+function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION _OUTPUT_VERSION_MAJOR _OUTPUT_VERSION_MINOR)
+ string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\1"
+ _boost_COMPILER_VERSION_MAJOR ${CMAKE_CXX_COMPILER_VERSION})
+ string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\2"
+ _boost_COMPILER_VERSION_MINOR ${CMAKE_CXX_COMPILER_VERSION})
+
+ set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}${_boost_COMPILER_VERSION_MINOR}")
set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE)
+ set(${_OUTPUT_VERSION_MAJOR} ${_boost_COMPILER_VERSION_MAJOR} PARENT_SCOPE)
+ set(${_OUTPUT_VERSION_MINOR} ${_boost_COMPILER_VERSION_MINOR} PARENT_SCOPE)
endfunction()
#
if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34)
set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34
else()
- _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION)
+ _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR)
set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}")
endif()
elseif (UNIX)
- if (CMAKE_COMPILER_IS_GNUCXX)
+ _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR)
+ if(NOT Boost_VERSION VERSION_LESS 106900)
+ # From GCC 5 and clang 4, versioning changes and minor becomes patch.
+ # For those compilers, patch is exclude from compiler tag in Boost 1.69+ library naming.
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 4)
+ set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}")
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 3)
+ set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}")
+ endif()
+ endif()
+
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34)
set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34
else()
- _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION)
# Determine which version of GCC we have.
if(APPLE)
if(Boost_MINOR_VERSION)
if(${Boost_MINOR_VERSION} GREATER 35)
# In Boost 1.36.0 and newer, the mangled compiler name used
- # on Mac OS X/Darwin is "xgcc".
+ # on macOS/Darwin is "xgcc".
set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}")
else()
# In Boost <= 1.35.0, there is no mangled compiler name for
- # the Mac OS X/Darwin version of GCC.
+ # the macOS/Darwin version of GCC.
set(_boost_COMPILER "")
endif()
else()
set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}")
endif()
endif()
- endif ()
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ # TODO: Find out any Boost version constraints vs clang support.
+ set(_boost_COMPILER "-clang${_boost_COMPILER_VERSION}")
+ endif()
else()
# TODO at least Boost_DEBUG here?
set(_boost_COMPILER "")
endif()
set(_Boost_IMPORTED_TARGETS TRUE)
- if(Boost_VERSION VERSION_LESS 103300)
+ if(Boost_VERSION AND Boost_VERSION VERSION_LESS 103300)
message(WARNING "Imported targets and dependency information not available for Boost version ${Boost_VERSION} (all versions older than 1.33)")
set(_Boost_IMPORTED_TARGETS FALSE)
elseif(NOT Boost_VERSION VERSION_LESS 103300 AND Boost_VERSION VERSION_LESS 103500)
set(_Boost_TIMER_DEPENDENCIES chrono system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
+ elseif(NOT Boost_VERSION VERSION_LESS 106800 AND Boost_VERSION VERSION_LESS 106900)
+ set(_Boost_CHRONO_DEPENDENCIES system)
+ set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time)
+ set(_Boost_CONTRACT_DEPENDENCIES thread chrono system date_time)
+ set(_Boost_COROUTINE_DEPENDENCIES context system)
+ set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time)
+ set(_Boost_FILESYSTEM_DEPENDENCIES system)
+ set(_Boost_IOSTREAMS_DEPENDENCIES regex)
+ set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
+ set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
+ set(_Boost_MPI_DEPENDENCIES serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
+ set(_Boost_NUMPY_DEPENDENCIES python${component_python_version})
+ set(_Boost_RANDOM_DEPENDENCIES system)
+ set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
+ set(_Boost_TIMER_DEPENDENCIES chrono system)
+ set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
+ set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
else()
- if(NOT Boost_VERSION VERSION_LESS 106800)
- set(_Boost_CHRONO_DEPENDENCIES system)
- set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time)
- set(_Boost_CONTRACT_DEPENDENCIES thread chrono system date_time)
- set(_Boost_COROUTINE_DEPENDENCIES context system)
- set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time)
- set(_Boost_FILESYSTEM_DEPENDENCIES system)
+ if(NOT Boost_VERSION VERSION_LESS 106900)
+ set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time)
+ set(_Boost_COROUTINE_DEPENDENCIES context)
+ set(_Boost_FIBER_DEPENDENCIES context)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
- set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
+ set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
set(_Boost_MPI_DEPENDENCIES serialization)
set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_NUMPY_DEPENDENCIES python${component_python_version})
- set(_Boost_RANDOM_DEPENDENCIES system)
- set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
+ set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic)
set(_Boost_TIMER_DEPENDENCIES chrono system)
- set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
+ set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
endif()
- if(NOT Boost_VERSION VERSION_LESS 106900)
+ if(NOT Boost_VERSION VERSION_LESS 107000)
message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
endif()
endif()
set(_Boost_REGEX_HEADERS "boost/regex.hpp")
set(_Boost_SERIALIZATION_HEADERS "boost/serialization/serialization.hpp")
set(_Boost_SIGNALS_HEADERS "boost/signals.hpp")
+ set(_Boost_STACKTRACE_ADDR2LINE_HEADERS "boost/stacktrace.hpp")
+ set(_Boost_STACKTRACE_BACKTRACE_HEADERS "boost/stacktrace.hpp")
+ set(_Boost_STACKTRACE_BASIC_HEADERS "boost/stacktrace.hpp")
+ set(_Boost_STACKTRACE_NOOP_HEADERS "boost/stacktrace.hpp")
+ set(_Boost_STACKTRACE_WINDBG_CACHED_HEADERS "boost/stacktrace.hpp")
+ set(_Boost_STACKTRACE_WINDBG_HEADERS "boost/stacktrace.hpp")
set(_Boost_SYSTEM_HEADERS "boost/system/config.hpp")
set(_Boost_TEST_EXEC_MONITOR_HEADERS "boost/test/test_exec_monitor.hpp")
set(_Boost_THREAD_HEADERS "boost/thread.hpp")
# _Boost_COMPONENT_HEADERS. See the instructions at the top of
# _Boost_COMPONENT_DEPENDENCIES.
set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
+ "1.69.0" "1.69"
"1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65"
"1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60"
"1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55"
# -x86 Architecture and address model tag
# First character is the architecture, then word-size, either 32 or 64
# Only used in 'versioned' layout, added in Boost 1.66.0
-set(_boost_ARCHITECTURE_TAG "")
-# {CMAKE_CXX_COMPILER_ARCHITECTURE_ID} is not currently set for all compilers
-if(NOT "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "x" AND NOT Boost_VERSION VERSION_LESS 106600)
- string(APPEND _boost_ARCHITECTURE_TAG "-")
- # This needs to be kept in-sync with the section of CMakePlatformId.h.in
- # inside 'defined(_WIN32) && defined(_MSC_VER)'
- if(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "IA64")
- string(APPEND _boost_ARCHITECTURE_TAG "i")
- elseif(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "X86"
- OR ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "x64")
- string(APPEND _boost_ARCHITECTURE_TAG "x")
- elseif(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} MATCHES "^ARM")
- string(APPEND _boost_ARCHITECTURE_TAG "a")
- elseif(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "MIPS")
- string(APPEND _boost_ARCHITECTURE_TAG "m")
+if(DEFINED Boost_ARCHITECTURE)
+ set(_boost_ARCHITECTURE_TAG "${Boost_ARCHITECTURE}")
+ if(Boost_DEBUG)
+ message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+ "using user-specified Boost_ARCHITECTURE = ${_boost_ARCHITECTURE_TAG}")
endif()
+else()
+ set(_boost_ARCHITECTURE_TAG "")
+ # {CMAKE_CXX_COMPILER_ARCHITECTURE_ID} is not currently set for all compilers
+ if(NOT "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "x" AND NOT Boost_VERSION VERSION_LESS 106600)
+ string(APPEND _boost_ARCHITECTURE_TAG "-")
+ # This needs to be kept in-sync with the section of CMakePlatformId.h.in
+ # inside 'defined(_WIN32) && defined(_MSC_VER)'
+ if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "IA64")
+ string(APPEND _boost_ARCHITECTURE_TAG "i")
+ elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "X86"
+ OR CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "x64")
+ string(APPEND _boost_ARCHITECTURE_TAG "x")
+ elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID MATCHES "^ARM")
+ string(APPEND _boost_ARCHITECTURE_TAG "a")
+ elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "MIPS")
+ string(APPEND _boost_ARCHITECTURE_TAG "m")
+ endif()
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- string(APPEND _boost_ARCHITECTURE_TAG "64")
- else()
- string(APPEND _boost_ARCHITECTURE_TAG "32")
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ string(APPEND _boost_ARCHITECTURE_TAG "64")
+ else()
+ string(APPEND _boost_ARCHITECTURE_TAG "32")
+ endif()
endif()
endif()
list(APPEND _boost_RELEASE_NAMES
${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION}
${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}
+ ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}
${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component} )
if(_boost_STATIC_RUNTIME_WORKAROUND)
set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}")
message (STATUS " ${COMPONENT}")
endif()
list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY})
+ if(COMPONENT STREQUAL "thread")
+ list(APPEND Boost_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+ endif()
endif()
endforeach()
else()
# matches what is needed by the CUDA runtime version.
#
# The following variables affect the behavior of the macros in the
-# script (in alphebetical order). Note that any of these flags can be
+# script (in alphabetical order). Note that any of these flags can be
# changed multiple times in the same directory before calling
# ``CUDA_ADD_EXECUTABLE``, ``CUDA_ADD_LIBRARY``, ``CUDA_COMPILE``,
# ``CUDA_COMPILE_PTX``, ``CUDA_COMPILE_FATBIN``, ``CUDA_COMPILE_CUBIN``
# the host compiler is constructed with one or more visual studio macros
# such as $(VCInstallDir), that expands out to the path when
# the command is run from within VS.
+# If the CUDAHOSTCXX environment variable is set it will
+# be used as the default.
#
# CUDA_NVCC_FLAGS
# CUDA_NVCC_FLAGS_<CONFIG>
# VERBOSE=1 to see output), although setting CUDA_VERBOSE_BUILD to ON will
# always print the output.
#
-# The script creates the following macros (in alphebetical order)::
+# The script creates the following macros (in alphabetical order)::
#
# CUDA_ADD_CUFFT_TO_TARGET( cuda_target )
# -- Adds the cufft library to the target (can be any target). Handles whether
# Extra user settable flags
cmake_initialize_per_config_variable(CUDA_NVCC_FLAGS "Semi-colon delimit multiple arguments.")
-if(CMAKE_GENERATOR MATCHES "Visual Studio")
+if(DEFINED ENV{CUDAHOSTCXX})
+ set(CUDA_HOST_COMPILER "$ENV{CUDAHOSTCXX}" CACHE FILEPATH "Host side compiler used by NVCC")
+elseif(CMAKE_GENERATOR MATCHES "Visual Studio")
set(_CUDA_MSVC_HOST_COMPILER "$(VCInstallDir)Tools/MSVC/$(VCToolsVersion)/bin/Host$(Platform)/$(PlatformTarget)")
if(MSVC_VERSION LESS 1910)
set(_CUDA_MSVC_HOST_COMPILER "$(VCInstallDir)bin")
RUN_OUTPUT_VARIABLE compute_capabilities)
endif()
+ # Filter unrelated content out of the output.
+ string(REGEX MATCHALL "[0-9]+\\.[0-9]+" compute_capabilities "${compute_capabilities}")
+
if(run_result EQUAL 0)
string(REPLACE "2.1" "2.1(2.0)" compute_capabilities "${compute_capabilities}")
set(CUDA_GPU_DETECT_OUTPUT ${compute_capabilities}
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
mark_as_advanced(CURL_INCLUDE_DIR)
-# Look for the library (sorted from most current/relevant entry to least).
-find_library(CURL_LIBRARY NAMES
- curl
- # Windows MSVC prebuilts:
- curllib
- libcurl_imp
- curllib_static
- # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
- libcurl
-)
-mark_as_advanced(CURL_LIBRARY)
+if(NOT CURL_LIBRARY)
+ # Look for the library (sorted from most current/relevant entry to least).
+ find_library(CURL_LIBRARY_RELEASE NAMES
+ curl
+ # Windows MSVC prebuilts:
+ curllib
+ libcurl_imp
+ curllib_static
+ # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
+ libcurl
+ )
+ mark_as_advanced(CURL_LIBRARY_RELEASE)
+
+ find_library(CURL_LIBRARY_DEBUG NAMES
+ # Windows MSVC CMake builds in debug configuration on vcpkg:
+ libcurl-d_imp
+ libcurl-d
+ )
+ mark_as_advanced(CURL_LIBRARY_DEBUG)
+
+ include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+ select_library_configurations(CURL)
+endif()
if(CURL_INCLUDE_DIR)
foreach(_curl_version_header curlver.h curl.h)
if(NOT TARGET CURL::libcurl)
add_library(CURL::libcurl UNKNOWN IMPORTED)
- set_target_properties(CURL::libcurl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}")
- set_property(TARGET CURL::libcurl APPEND PROPERTY IMPORTED_LOCATION "${CURL_LIBRARY}")
+ set_target_properties(CURL::libcurl PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}")
+
+ if(EXISTS "${CURL_LIBRARY}")
+ set_target_properties(CURL::libcurl PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION "${CURL_LIBRARY}")
+ endif()
+ if(CURL_LIBRARY_RELEASE)
+ set_property(TARGET CURL::libcurl APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS RELEASE)
+ set_target_properties(CURL::libcurl PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}")
+ endif()
+ if(CURL_LIBRARY_DEBUG)
+ set_property(TARGET CURL::libcurl APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS DEBUG)
+ set_target_properties(CURL::libcurl PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}")
+ endif()
endif()
endif()
# GLUT_Xmu_LIBRARY = the full path to the Xmu library.
# GLUT_Xi_LIBRARY = the full path to the Xi Library.
+include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+
if (WIN32)
find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h
PATHS ${GLUT_ROOT_PATH}/include )
- find_library( GLUT_glut_LIBRARY NAMES glut glut32 freeglut
+ find_library( GLUT_glut_LIBRARY_RELEASE NAMES glut glut32 freeglut
PATHS
${OPENGL_LIBRARY_DIR}
${GLUT_ROOT_PATH}/Release
)
+ find_library( GLUT_glut_LIBRARY_DEBUG NAMES freeglutd
+ PATHS
+ ${OPENGL_LIBRARY_DIR}
+ ${GLUT_ROOT_PATH}/Debug
+ )
+ mark_as_advanced(GLUT_glut_LIBRARY_RELEASE GLUT_glut_LIBRARY_DEBUG)
+ select_library_configurations(GLUT_glut)
else ()
if (APPLE)
find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR})
find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX")
find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX")
+ mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY)
if(GLUT_cocoa_LIBRARY AND NOT TARGET GLUT::Cocoa)
add_library(GLUT::Cocoa UNKNOWN IMPORTED)
find_library( GLUT_Xi_LIBRARY Xi
/usr/openwin/lib
)
+ mark_as_advanced(GLUT_Xi_LIBRARY)
find_library( GLUT_Xmu_LIBRARY Xmu
/usr/openwin/lib
)
+ mark_as_advanced(GLUT_Xmu_LIBRARY)
if(GLUT_Xi_LIBRARY AND NOT TARGET GLUT::Xi)
add_library(GLUT::Xi UNKNOWN IMPORTED)
/usr/openwin/lib
${_GLUT_glut_LIB_DIR}
)
+ mark_as_advanced(GLUT_glut_LIBRARY)
unset(_GLUT_INC_DIR)
unset(_GLUT_glut_LIB_DIR)
set_target_properties(GLUT::GLUT PROPERTIES
IMPORTED_LOCATION "${GLUT_glut_LIBRARY}/${CMAKE_MATCH_1}")
else()
- set_target_properties(GLUT::GLUT PROPERTIES
- IMPORTED_LOCATION "${GLUT_glut_LIBRARY}")
+ if(GLUT_glut_LIBRARY_RELEASE)
+ set_property(TARGET GLUT::GLUT APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS RELEASE)
+ set_target_properties(GLUT::GLUT PROPERTIES
+ IMPORTED_LOCATION_RELEASE "${GLUT_glut_LIBRARY_RELEASE}")
+ endif()
+
+ if(GLUT_glut_LIBRARY_DEBUG)
+ set_property(TARGET GLUT::GLUT APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS DEBUG)
+ set_target_properties(GLUT::GLUT PROPERTIES
+ IMPORTED_LOCATION_DEBUG "${GLUT_glut_LIBRARY_DEBUG}")
+ endif()
+
+ if(NOT GLUT_glut_LIBRARY_RELEASE AND NOT GLUT_glut_LIBRARY_DEBUG)
+ set_property(TARGET GLUT::GLUT APPEND PROPERTY
+ IMPORTED_LOCATION "${GLUT_glut_LIBRARY}")
+ endif()
endif()
if(TARGET GLUT::Xmu)
set (GLUT_INCLUDE_PATH ${GLUT_INCLUDE_DIR})
endif()
-mark_as_advanced(
- GLUT_INCLUDE_DIR
- GLUT_glut_LIBRARY
- GLUT_Xmu_LIBRARY
- GLUT_Xi_LIBRARY
- )
+mark_as_advanced(GLUT_INCLUDE_DIR)
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# FindJNI
-# -------
-#
-# Find JNI java libraries.
-#
-# This module finds if Java is installed and determines where the
-# include files and libraries are. It also determines what the name of
-# the library is. The caller may set variable JAVA_HOME to specify a
-# Java installation prefix explicitly.
-#
-# This module sets the following result variables:
-#
-# ::
-#
-# JNI_INCLUDE_DIRS = the include dirs to use
-# JNI_LIBRARIES = the libraries to use
-# JNI_FOUND = TRUE if JNI headers and libraries were found.
-# JAVA_AWT_LIBRARY = the path to the jawt library
-# JAVA_JVM_LIBRARY = the path to the jvm library
-# JAVA_INCLUDE_PATH = the include path to jni.h
-# JAVA_INCLUDE_PATH2 = the include path to jni_md.h
-# JAVA_AWT_INCLUDE_PATH = the include path to jawt.h
+#[=======================================================================[.rst:
+FindJNI
+-------
+
+Find Java Native Interface (JNI) libraries.
+
+JNI enables Java code running in a Java Virtual Machine (JVM) to call
+and be called by native applications and libraries written in other
+languages such as C, C++.
+
+This module finds if Java is installed and determines where the
+include files and libraries are. It also determines what the name of
+the library is. The caller may set variable ``JAVA_HOME`` to specify a
+Java installation prefix explicitly.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module sets the following result variables:
+
+``JNI_INCLUDE_DIRS``
+ the include dirs to use
+``JNI_LIBRARIES``
+ the libraries to use (JAWT and JVM)
+``JNI_FOUND``
+ TRUE if JNI headers and libraries were found.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+The following cache variables are also available to set or use:
+
+``JAVA_AWT_LIBRARY``
+ the path to the Java AWT Native Interface (JAWT) library
+``JAVA_JVM_LIBRARY``
+ the path to the Java Virtual Machine (JVM) library
+``JAVA_INCLUDE_PATH``
+ the include path to jni.h
+``JAVA_INCLUDE_PATH2``
+ the include path to jni_md.h and jniport.h
+``JAVA_AWT_INCLUDE_PATH``
+ the include path to jawt.h
+#]=======================================================================]
# Expand {libarch} occurrences to java_libarch subdirectory(-ies) and set ${_var}
macro(java_append_library_directories _var)
/usr/lib/jvm/default/jre/lib/{libarch}
/usr/lib/jvm/default/lib/{libarch}
# Ubuntu specific paths for default JVM
+ /usr/lib/jvm/java-11-openjdk-{libarch}/jre/lib/{libarch} # Ubuntu 18.04 LTS
/usr/lib/jvm/java-8-openjdk-{libarch}/jre/lib/{libarch} # Ubuntu 15.10
/usr/lib/jvm/java-7-openjdk-{libarch}/jre/lib/{libarch} # Ubuntu 15.10
/usr/lib/jvm/java-6-openjdk-{libarch}/jre/lib/{libarch} # Ubuntu 15.10
# Find Java
#
# This module finds if Java is installed and determines where the
-# include files and libraries are. The caller may set variable JAVA_HOME
+# include files and libraries are. The caller may set variable ``JAVA_HOME``
# to specify a Java installation prefix explicitly.
#
-# See also the :module:`FindJNI` module to find Java development tools.
+# See also the :module:`FindJNI` module to find Java Native Interface (JNI).
#
# Specify one or more of the following components as you call this find module. See example below.
#
# ::
#
-# Runtime = User just want to execute some Java byte-compiled
+# Runtime = Java Runtime Environment used to execute Java byte-compiled applications
# Development = Development tools (java, javac, javah, jar and javadoc), includes Runtime component
-# IdlJ = idl compiler for Java
-# JarSigner = signer tool for jar
+# IdlJ = Interface Description Language (IDL) to Java compiler
+# JarSigner = Signer and verifier tool for Java Archive (JAR) files
#
#
# This module sets the following result variables:
#
#
# The minimum required version of Java can be specified using the
-# standard CMake syntax, e.g. find_package(Java 1.5)
+# :command:`find_package` syntax, e.g.
#
-# NOTE: ${Java_VERSION} and ${Java_VERSION_STRING} are not guaranteed to
+# .. code-block:: cmake
+#
+# find_package(Java 1.8)
+#
+# NOTE: ``${Java_VERSION}`` and ``${Java_VERSION_STRING}`` are not guaranteed to
# be identical. For example some java version may return:
-# Java_VERSION_STRING = 1.5.0_17 and Java_VERSION = 1.5.0.17
+# ``Java_VERSION_STRING = 1.8.0_17`` and ``Java_VERSION = 1.8.0.17``
#
-# another example is the Java OEM, with: Java_VERSION_STRING = 1.6.0-oem
-# and Java_VERSION = 1.6.0
+# another example is the Java OEM, with: ``Java_VERSION_STRING = 1.8.0-oem``
+# and ``Java_VERSION = 1.8.0``
#
# For these components the following variables are set:
#
# ::
#
# find_package(Java)
+# find_package(Java 1.8 REQUIRED)
# find_package(Java COMPONENTS Runtime)
# find_package(Java COMPONENTS Development)
find_package(Threads REQUIRED)
endif()
+ if (BLA_VENDOR MATCHES "_64ilp")
+ set(BLAS_mkl_ILP_MODE "ilp64")
+ else ()
+ set(BLAS_mkl_ILP_MODE "lp64")
+ endif ()
+
set(LAPACK_SEARCH_LIBS "")
if (BLA_F95)
- set(LAPACK_mkl_SEARCH_SYMBOL "CHEEV")
+ set(LAPACK_mkl_SEARCH_SYMBOL "cheev_f95")
set(_LIBRARIES LAPACK95_LIBRARIES)
set(_BLAS_LIBRARIES ${BLAS95_LIBRARIES})
list(APPEND LAPACK_SEARCH_LIBS
"mkl_intel_c")
list(APPEND LAPACK_SEARCH_LIBS
- "mkl_intel_lp64")
+ "mkl_lapack95_${BLAS_mkl_ILP_MODE}")
else()
set(LAPACK_mkl_SEARCH_SYMBOL "cheev")
set(_LIBRARIES LAPACK_LIBRARIES)
"mkl_lapack")
# new >= 10.3
list(APPEND LAPACK_SEARCH_LIBS
- "mkl_gf_lp64")
+ "mkl_gf_${BLAS_mkl_ILP_MODE}")
endif()
# First try empty lapack libs
)
endif ()
endforeach ()
+
+ unset(BLAS_mkl_ILP_MODE)
endif ()
endif()
else()
unset(_lua_include_subdirs)
unset(_lua_library_names)
unset(_lua_append_versions)
-set(_lua_additional_paths
- ~/Library/Frameworks
- /Library/Frameworks
- /sw # Fink
- /opt/local # DarwinPorts
- /opt/csw # Blastwave
- /opt)
# this is a function only to have all the variables inside go away automatically
function(_lua_get_versions)
HINTS
ENV LUA_DIR
PATH_SUFFIXES ${subdir}
- PATHS ${_lua_additional_paths}
)
if (LUA_INCLUDE_DIR)
break()
find_library(LUA_LIBRARY
NAMES ${_lua_library_names} lua
+ NAMES_PER_DIR
HINTS
ENV LUA_DIR
PATH_SUFFIXES lib
- PATHS ${_lua_additional_paths}
)
unset(_lua_library_names)
add_library(MPI::MPI_${LANG} INTERFACE IMPORTED)
endif()
- set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}")
+ # When this is consumed for compiling CUDA, use '-Xcompiler' to wrap '-pthread'.
+ string(REPLACE "-pthread" "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:-Xcompiler >-pthread"
+ _MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}")
+ set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "${_MPI_${LANG}_COMPILE_OPTIONS}")
+ unset(_MPI_${LANG}_COMPILE_OPTIONS)
+
set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_DEFINITIONS "${MPI_${LANG}_COMPILE_DEFINITIONS}")
set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_LINK_LIBRARIES "")
#
# * ``MX_LIBRARY``, ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the ``MX``,
# ``ENG`` and ``MAT`` libraries of Matlab
+# * ``ENGINE_LIBRARY``, ``DATAARRAY_LIBRARY``: respectively the ``MatlabEngine``
+# and ``MatlabDataArray`` libraries of Matlab (Matlab 2018a and later)
# * ``MAIN_PROGRAM`` the Matlab binary program. Note that this component is not
# available on the MCR version, and will yield an error if the MCR is found
# instead of the regular Matlab installation.
# * ``MEX_COMPILER`` the MEX compiler.
+# * ``MCC_COMPILER`` the MCC compiler, included with the Matlab Compiler add-on.
# * ``SIMULINK`` the Simulink environment.
#
# .. note::
# ``Matlab_MAT_LIBRARY``
# Matlab matrix library. Available only if the component ``MAT_LIBRARY``
# is requested.
+# ``Matlab_ENGINE_LIBRARY``
+# Matlab C++ engine library. Available only if the component ``ENGINE_LIBRARY``
+# is requested.
+# ``Matlab_DATAARRAY_LIBRARY``
+# Matlab C++ data array library. Available only if the component ``DATAARRAY_LIBRARY``
+# is requested.
# ``Matlab_LIBRARIES``
# the whole set of libraries of Matlab
# ``Matlab_MEX_COMPILER``
# the mex compiler of Matlab. Currently not used.
-# Available only if the component ``MEX_COMPILER`` is asked
+# Available only if the component ``MEX_COMPILER`` is requested.
+# ``Matlab_MCC_COMPILER``
+# the mcc compiler of Matlab. Included with the Matlab Compiler add-on.
+# Available only if the component ``MCC_COMPILER`` is requested.
#
# Cached variables
# """"""""""""""""
endif()
set(MATLAB_VERSIONS_MAPPING
+ "R2018b=9.5"
+ "R2018a=9.4"
"R2017b=9.3"
"R2017a=9.2"
"R2016b=9.1"
target_link_libraries(${${prefix}_NAME} ${Matlab_MX_LIBRARY})
endif()
+ if(DEFINED Matlab_ENGINE_LIBRARY)
+ target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY})
+ endif()
+
+ if(DEFINED Matlab_DATAARRAY_LIBRARY)
+ target_link_libraries(${${prefix}_NAME} ${Matlab_DATAARRAY_LIBRARY})
+ endif()
+
target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${${prefix}_LINK_TO})
set_target_properties(${${prefix}_NAME}
PROPERTIES
endif() # documentation
# entry point in the mex file + taking care of visibility and symbol clashes.
+ if (MSVC)
+ get_target_property(
+ _previous_link_flags
+ ${${prefix}_NAME}
+ LINK_FLAGS)
+ if(NOT _previous_link_flags)
+ set(_previous_link_flags)
+ endif()
+
+ set_target_properties(${${prefix}_NAME}
+ PROPERTIES
+ LINK_FLAGS "${_previous_link_flags} /EXPORT:mexFunction")
+ endif()
+
if(WIN32)
set_target_properties(${${prefix}_NAME}
PROPERTIES
# if the user does not specify the possible installation root, we look for
# one installation using the appropriate heuristics.
# There is apparently no standard way on Linux.
- if(WIN32)
+ if(CMAKE_HOST_WIN32)
_Matlab_find_instances_win32(_matlab_possible_roots_win32)
list(APPEND _matlab_possible_roots ${_matlab_possible_roots_win32})
elseif(APPLE)
Matlab_INCLUDE_DIRS
Matlab_MEX_LIBRARY
Matlab_MEX_COMPILER
+ Matlab_MCC_COMPILER
Matlab_MAIN_PROGRAM
Matlab_MX_LIBRARY
Matlab_ENG_LIBRARY
Matlab_MAT_LIBRARY
+ Matlab_ENGINE_LIBRARY
+ Matlab_DATAARRAY_LIBRARY
Matlab_MEX_EXTENSION
Matlab_SIMULINK_INCLUDE_DIR
endif()
unset(_matlab_find_simulink)
+# component MCC Compiler
+list(FIND Matlab_FIND_COMPONENTS MCC_COMPILER _matlab_find_mcc_compiler)
+if(_matlab_find_mcc_compiler GREATER -1)
+ find_program(
+ Matlab_MCC_COMPILER
+ "mcc"
+ PATHS ${Matlab_BINARIES_DIR}
+ DOC "Matlab MCC compiler"
+ NO_DEFAULT_PATH
+ )
+ if(Matlab_MCC_COMPILER)
+ set(Matlab_MCC_COMPILER_FOUND TRUE)
+ endif()
+endif()
+unset(_matlab_find_mcc_compiler)
+
+# component MatlabEngine
+list(FIND Matlab_FIND_COMPONENTS ENGINE_LIBRARY _matlab_find_matlab_engine)
+if(_matlab_find_matlab_engine GREATER -1)
+ _Matlab_find_library(
+ ${_matlab_lib_prefix_for_search}
+ Matlab_ENGINE_LIBRARY
+ MatlabEngine
+ PATHS ${_matlab_lib_dir_for_search}
+ DOC "MatlabEngine Library"
+ NO_DEFAULT_PATH
+ )
+ if(Matlab_ENGINE_LIBRARY)
+ set(Matlab_ENGINE_LIBRARY_FOUND TRUE)
+ endif()
+endif()
+unset(_matlab_find_matlab_engine)
+
+# component MatlabDataArray
+list(FIND Matlab_FIND_COMPONENTS DATAARRAY_LIBRARY _matlab_find_matlab_dataarray)
+if(_matlab_find_matlab_dataarray GREATER -1)
+ _Matlab_find_library(
+ ${_matlab_lib_prefix_for_search}
+ Matlab_DATAARRAY_LIBRARY
+ MatlabDataArray
+ PATHS ${_matlab_lib_dir_for_search}
+ DOC "MatlabDataArray Library"
+ NO_DEFAULT_PATH
+ )
+ if(Matlab_DATAARRAY_LIBRARY)
+ set(Matlab_DATAARRAY_LIBRARY_FOUND TRUE)
+ endif()
+endif()
+unset(_matlab_find_matlab_dataarray)
+
unset(_matlab_lib_dir_for_search)
set(Matlab_LIBRARIES ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY})
+if(Matlab_DATAARRAY_LIBRARY_FOUND)
+ set(Matlab_LIBRARIES ${Matlab_LIBRARIES} ${Matlab_DATAARRAY_LIBRARY})
+endif()
+
+if(Matlab_ENGINE_LIBRARY_FOUND)
+ set(Matlab_LIBRARIES ${Matlab_LIBRARIES} ${Matlab_ENGINE_LIBRARY})
+endif()
+
find_package_handle_standard_args(
Matlab
FOUND_VAR Matlab_FOUND
Matlab_MEX_LIBRARY
Matlab_MX_LIBRARY
Matlab_ENG_LIBRARY
+ Matlab_ENGINE_LIBRARY
+ Matlab_DATAARRAY_LIBRARY
Matlab_MAT_LIBRARY
Matlab_INCLUDE_DIRS
Matlab_FOUND
OpenCL/common/lib/x64)
endif()
else()
- find_library(OpenCL_LIBRARY
- NAMES OpenCL
- PATHS
- ENV AMDAPPSDKROOT
- ENV CUDA_PATH
- PATH_SUFFIXES
- lib/x86_64
- lib/x64
- lib
- lib64)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ find_library(OpenCL_LIBRARY
+ NAMES OpenCL
+ PATHS
+ ENV AMDAPPSDKROOT
+ ENV CUDA_PATH
+ PATH_SUFFIXES
+ lib/x86
+ lib)
+ elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ find_library(OpenCL_LIBRARY
+ NAMES OpenCL
+ PATHS
+ ENV AMDAPPSDKROOT
+ ENV CUDA_PATH
+ PATH_SUFFIXES
+ lib/x86_64
+ lib/x64
+ lib
+ lib64)
+ endif()
endif()
set(OpenCL_LIBRARIES ${OpenCL_LIBRARY})
set(OpenMP_C_CXX_TEST_SOURCE
"
#include <omp.h>
-int main() {
+int main(void) {
#ifdef _OPENMP
omp_get_max_threads();
return 0;
break()
endif()
endif()
+ else()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Detecting ${LANG} OpenMP failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
endif()
set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
('0' + ((_OPENMP/10)%10)),
('0' + ((_OPENMP/1)%10)),
']', '\\0' };
-int main()
+int main(void)
{
puts(ompver_str);
return 0;
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})
+ COPY_FILE ${BIN_FILE}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT)
if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
if("${specstr}" MATCHES "${regex_spec_date}")
set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
endif()
+ else()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Detecting ${LANG} OpenMP version failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
endif()
endfunction()
# standard install paths.
# Explicit -DVAR=value arguments should still be able to override everything.
+include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+
find_path(OPENTHREADS_INCLUDE_DIR OpenThreads/Thread
HINTS
ENV OPENTHREADS_INCLUDE_DIR
)
-find_library(OPENTHREADS_LIBRARY
+find_library(OPENTHREADS_LIBRARY_RELEASE
NAMES OpenThreads OpenThreadsWin32
HINTS
ENV OPENTHREADS_LIBRARY_DIR
PATH_SUFFIXES lib
)
-if(OPENTHREADS_LIBRARY_DEBUG)
- set(OPENTHREADS_LIBRARIES
- optimized ${OPENTHREADS_LIBRARY}
- debug ${OPENTHREADS_LIBRARY_DEBUG})
-else()
- set(OPENTHREADS_LIBRARIES ${OPENTHREADS_LIBRARY})
-endif()
+select_library_configurations(OPENTHREADS)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenThreads DEFAULT_MSG
# internal helper macro to generate the failure message when used in CONFIG_MODE:
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
- # <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
+ # <PackageName>_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})")
else()
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
endif()
- # In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
+ # In config-mode, we rely on the variable <PackageName>_CONFIG, which is set by find_package()
# when it successfully found the config-file, including version checking:
if(FPHSA_CONFIG_MODE)
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
endmacro()
# Splits given arguments into options and a package list
-macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cmake_environment_path _imp_target)
+macro(_pkgconfig_parse_options _result _is_req _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global)
set(${_is_req} 0)
set(${_is_silent} 0)
set(${_no_cmake_path} 0)
set(${_no_cmake_environment_path} 0)
set(${_imp_target} 0)
+ set(${_imp_target_global} 0)
if(DEFINED PKG_CONFIG_USE_CMAKE_PREFIX_PATH)
if(NOT PKG_CONFIG_USE_CMAKE_PREFIX_PATH)
set(${_no_cmake_path} 1)
if (_pkg STREQUAL "IMPORTED_TARGET")
set(${_imp_target} 1)
endif()
+ if (_pkg STREQUAL "GLOBAL")
+ set(${_imp_target_global} 1)
+ endif()
endforeach()
+ if (${_imp_target_global} AND NOT ${_imp_target})
+ message(SEND_ERROR "the argument GLOBAL may only be used together with IMPORTED_TARGET")
+ endif()
+
set(${_result} ${ARGN})
list(REMOVE_ITEM ${_result} "REQUIRED")
list(REMOVE_ITEM ${_result} "QUIET")
list(REMOVE_ITEM ${_result} "NO_CMAKE_PATH")
list(REMOVE_ITEM ${_result} "NO_CMAKE_ENVIRONMENT_PATH")
list(REMOVE_ITEM ${_result} "IMPORTED_TARGET")
+ list(REMOVE_ITEM ${_result} "GLOBAL")
endmacro()
# Add the content of a variable or an environment variable to a list of
endfunction()
# create an imported target from all the information returned by pkg-config
-function(_pkg_create_imp_target _prefix)
+function(_pkg_create_imp_target _prefix _imp_target_global)
# only create the target if it is linkable, i.e. no executables
if (NOT TARGET PkgConfig::${_prefix}
AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_CFLAGS_OTHER ))
- add_library(PkgConfig::${_prefix} INTERFACE IMPORTED)
+ if(${_imp_target_global})
+ set(_global_opt "GLOBAL")
+ else()
+ unset(_global_opt)
+ endif()
+ add_library(PkgConfig::${_prefix} INTERFACE IMPORTED ${_global_opt})
if(${_prefix}_INCLUDE_DIRS)
set_property(TARGET PkgConfig::${_prefix} PROPERTY
# recalculate the dynamic output
# this is a macro and not a function so the result of _pkg_find_libs is automatically propagated
-macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target)
+macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global)
_pkg_find_libs(${_prefix} ${_no_cmake_path} ${_no_cmake_environment_path})
if(${_imp_target})
- _pkg_create_imp_target(${_prefix})
+ _pkg_create_imp_target(${_prefix} ${_imp_target_global})
endif()
endmacro()
###
-macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _prefix)
+macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global _prefix)
_pkgconfig_unset(${_prefix}_FOUND)
_pkgconfig_unset(${_prefix}_VERSION)
_pkgconfig_unset(${_prefix}_PREFIX)
set(_pkg_check_modules_exist_query)
# check whether version is given
- if (_pkg_check_modules_pkg MATCHES "(.*[^><])(>=|=|<=)(.*)")
+ if (_pkg_check_modules_pkg MATCHES "(.*[^><])(=|[><]=?)(.*)")
set(_pkg_check_modules_pkg_name "${CMAKE_MATCH_1}")
set(_pkg_check_modules_pkg_op "${CMAKE_MATCH_2}")
set(_pkg_check_modules_pkg_ver "${CMAKE_MATCH_3}")
list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}")
# create the final query which is of the format:
+ # * <pkg-name> > <version>
# * <pkg-name> >= <version>
# * <pkg-name> = <version>
# * <pkg-name> <= <version>
+ # * <pkg-name> < <version>
# * --exists <pkg-name>
list(APPEND _pkg_check_modules_exist_query --print-errors --short-errors)
if (_pkg_check_modules_pkg_op)
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other )
- _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global})
endif()
if(NOT "${_extra_paths}" STREQUAL "")
[REQUIRED] [QUIET]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
- [IMPORTED_TARGET]
+ [IMPORTED_TARGET [GLOBAL]]
<moduleSpec> [<moduleSpec>...])
When the ``REQUIRED`` argument is given, the command will fail with an error
The ``IMPORTED_TARGET`` argument will create an imported target named
``PkgConfig::<prefix>`` that can be passed directly as an argument to
- :command:`target_link_libraries`.
+ :command:`target_link_libraries`. The ``GLOBAL`` argument will make the
+ imported target available in global scope.
- Each ``<moduleSpec>`` must be in one of the following formats::
+ Each ``<moduleSpec>`` can be either a bare module name or it can be a
+ module name with a version constraint (operators ``=``, ``<``, ``>``,
+ ``<=`` and ``>=`` are supported). The following are examples for a module
+ named ``foo`` with various constraints::
- {moduleName} ... matches any version
- {moduleName}>={version} ... at least version <version> is required
- {moduleName}={version} ... exactly version <version> is required
- {moduleName}<={version} ... modules must not be newer than <version>
+ foo # Any version matches
+ foo<2 # Only match versions before 2
+ foo>=3.1 # Match any version from 3.1 or later
+ foo=1.2.3 # Foo must be exactly version 1.2.3
The following variables may be set upon return. Two sets of values exist,
one for the common case (``<XXX> = <prefix>``) and another for the
XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp
#]========================================]
macro(pkg_check_modules _prefix _module0)
- _pkgconfig_parse_options(_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target "${_module0}" ${ARGN})
+ _pkgconfig_parse_options(_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN})
# check cached value
if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND OR
(NOT "${ARGN}" STREQUAL "" AND NOT "${__pkg_config_arguments_${_prefix}}" STREQUAL "${_module0};${ARGN}") OR
( "${ARGN}" STREQUAL "" AND NOT "${__pkg_config_arguments_${_prefix}}" STREQUAL "${_module0}"))
- _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} "${_prefix}" ${_pkg_modules})
+ _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} "${_prefix}" ${_pkg_modules})
_pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
if (${_prefix}_FOUND)
endif()
else()
if (${_prefix}_FOUND)
- _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global})
endif()
endif()
endmacro()
[REQUIRED] [QUIET]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
- [IMPORTED_TARGET]
+ [IMPORTED_TARGET [GLOBAL]]
<moduleSpec> [<moduleSpec>...])
Examples
pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2)
#]========================================]
macro(pkg_search_module _prefix _module0)
- _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target "${_module0}" ${ARGN})
+ _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path _imp_target _imp_target_global "${_module0}" ${ARGN})
# check cached value
if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND)
set(_pkg_modules_found 0)
# iterate through all modules and stop at the first working one.
foreach(_pkg_alt ${_pkg_modules_alt})
if(NOT _pkg_modules_found)
- _pkg_check_modules_internal(0 1 ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} "${_prefix}" "${_pkg_alt}")
+ _pkg_check_modules_internal(0 1 ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global} "${_prefix}" "${_pkg_alt}")
endif()
if (${_prefix}_FOUND)
_pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
elseif (${_prefix}_FOUND)
- _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target} ${_imp_target_global})
endif()
endmacro()
# In Windows the default installation of PostgreSQL uses that as part of the path.
# E.g C:\Program Files\PostgreSQL\8.4.
# Currently, the following version numbers are known to this module:
-# "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0"
+# "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0"
#
# To use this variable just do something like this:
# set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4")
set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS}
- "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0")
+ "11" "10" "9.6" "9.5" "9.4" "9.3" "9.2" "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0")
# Define additional search paths for root directories.
set( PostgreSQL_ROOT_DIRECTORIES
# ``ARGN``
# ``.proto`` filess
-function(PROTOBUF_GENERATE_CPP SRCS HDRS)
- cmake_parse_arguments(protobuf "" "EXPORT_MACRO;DESCRIPTORS" "" ${ARGN})
+function(protobuf_generate)
+ include(CMakeParseArguments)
- set(PROTO_FILES "${protobuf_UNPARSED_ARGUMENTS}")
- if(NOT PROTO_FILES)
- message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
+ set(_options APPEND_PATH DESCRIPTORS)
+ set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR)
+ if(COMMAND target_sources)
+ list(APPEND _singleargs TARGET)
+ endif()
+ set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS)
+
+ cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
+
+ if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
+ message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
return()
endif()
- if(protobuf_EXPORT_MACRO)
- set(DLL_EXPORT_DECL "dllexport_decl=${protobuf_EXPORT_MACRO}:")
+ if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET)
+ message(SEND_ERROR "Error: protobuf_generate called without a target or output variable")
+ return()
endif()
- if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
- # Create an include path for each file specified
- 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)
- if(${_contains_already} EQUAL -1)
- list(APPEND _protobuf_include_path -I ${ABS_PATH})
- endif()
- endforeach()
- else()
- set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+ if(NOT protobuf_generate_LANGUAGE)
+ set(protobuf_generate_LANGUAGE cpp)
endif()
+ string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE)
- if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
- set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
+ if(NOT protobuf_generate_PROTOC_OUT_DIR)
+ set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
endif()
- if(DEFINED Protobuf_IMPORT_DIRS)
- foreach(DIR ${Protobuf_IMPORT_DIRS})
- get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
- list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
- if(${_contains_already} EQUAL -1)
- list(APPEND _protobuf_include_path -I ${ABS_PATH})
+ if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp)
+ set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}:")
+ endif()
+
+ if(NOT protobuf_generate_GENERATE_EXTENSIONS)
+ if(protobuf_generate_LANGUAGE STREQUAL cpp)
+ set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc)
+ elseif(protobuf_generate_LANGUAGE STREQUAL python)
+ set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py)
+ else()
+ message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS")
+ return()
+ endif()
+ endif()
+
+ if(protobuf_generate_TARGET)
+ get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES)
+ foreach(_file ${_source_list})
+ if(_file MATCHES "proto$")
+ list(APPEND protobuf_generate_PROTOS ${_file})
endif()
endforeach()
endif()
- set(${SRCS})
- set(${HDRS})
- if (protobuf_DESCRIPTORS)
- set(${protobuf_DESCRIPTORS})
+ if(NOT protobuf_generate_PROTOS)
+ message(SEND_ERROR "Error: protobuf_generate could not find any .proto files")
+ return()
endif()
- 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)
- get_filename_component(FIL_DIR ${FIL} DIRECTORY)
- if(FIL_DIR)
- set(FIL_WE "${FIL_DIR}/${FIL_WE}")
+ if(protobuf_generate_APPEND_PATH)
+ # Create an include path for each file specified
+ foreach(_file ${protobuf_generate_PROTOS})
+ get_filename_component(_abs_file ${_file} ABSOLUTE)
+ get_filename_component(_abs_path ${_abs_file} PATH)
+ list(FIND _protobuf_include_path ${_abs_path} _contains_already)
+ if(${_contains_already} EQUAL -1)
+ list(APPEND _protobuf_include_path -I ${_abs_path})
endif()
+ endforeach()
+ else()
+ set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+ endif()
+
+ foreach(DIR ${protobuf_generate_IMPORT_DIRS})
+ get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
+ list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+ if(${_contains_already} EQUAL -1)
+ list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
+ endforeach()
- set(_protobuf_protoc_src "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
- set(_protobuf_protoc_hdr "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
- list(APPEND ${SRCS} "${_protobuf_protoc_src}")
- list(APPEND ${HDRS} "${_protobuf_protoc_hdr}")
+ set(_generated_srcs_all)
+ foreach(_proto ${protobuf_generate_PROTOS})
+ get_filename_component(_abs_file ${_proto} ABSOLUTE)
+ get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
+ get_filename_component(_basename ${_proto} NAME_WE)
+ file(RELATIVE_PATH _rel_dir ${CMAKE_CURRENT_SOURCE_DIR} ${_abs_dir})
- if(protobuf_DESCRIPTORS)
- set(_protobuf_protoc_desc "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.desc")
- set(_protobuf_protoc_flags "--descriptor_set_out=${_protobuf_protoc_desc}")
- list(APPEND ${protobuf_DESCRIPTORS} "${_protobuf_protoc_desc}")
- else()
- set(_protobuf_protoc_desc "")
- set(_protobuf_protoc_flags "")
+ set(_generated_srcs)
+ foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS})
+ list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_basename}${_ext}")
+ endforeach()
+
+ if(protobuf_generate_DESCRIPTORS AND protobuf_generate_LANGUAGE STREQUAL cpp)
+ set(_descriptor_file "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.desc")
+ set(_dll_desc_out "--descriptor_set_out=${_descriptor_file}")
+ list(APPEND _generated_srcs ${_descriptor_file})
endif()
+ list(APPEND _generated_srcs_all ${_generated_srcs})
add_custom_command(
- OUTPUT "${_protobuf_protoc_src}"
- "${_protobuf_protoc_hdr}"
- ${_protobuf_protoc_desc}
+ OUTPUT ${_generated_srcs}
COMMAND protobuf::protoc
- "--cpp_out=${DLL_EXPORT_DECL}${CMAKE_CURRENT_BINARY_DIR}"
- ${_protobuf_protoc_flags}
- ${_protobuf_include_path} ${ABS_FIL}
- DEPENDS ${ABS_FIL} protobuf::protoc
- COMMENT "Running C++ protocol buffer compiler on ${FIL}"
+ ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_dll_desc_out} ${_protobuf_include_path} ${_abs_file}
+ DEPENDS ${_abs_file} protobuf::protoc
+ COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}"
VERBATIM )
endforeach()
- set(${SRCS} "${${SRCS}}" PARENT_SCOPE)
- set(${HDRS} "${${HDRS}}" PARENT_SCOPE)
- if(protobuf_DESCRIPTORS)
- set(${protobuf_DESCRIPTORS} "${${protobuf_DESCRIPTORS}}" PARENT_SCOPE)
+ set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE)
+ if(protobuf_generate_OUT_VAR)
+ set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE)
+ endif()
+ if(protobuf_generate_TARGET)
+ target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all})
endif()
endfunction()
-function(PROTOBUF_GENERATE_PYTHON SRCS)
- if(NOT ARGN)
- message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
+function(PROTOBUF_GENERATE_CPP SRCS HDRS)
+ cmake_parse_arguments(protobuf_generate_cpp "" "EXPORT_MACRO;DESCRIPTORS" "" ${ARGN})
+
+ set(_proto_files "${protobuf_generate_cpp_UNPARSED_ARGUMENTS}")
+ if(NOT _proto_files)
+ message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
return()
endif()
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
- # Create an include path for each file specified
- foreach(FIL ${ARGN})
- get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
- get_filename_component(ABS_PATH ${ABS_FIL} PATH)
- list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
- if(${_contains_already} EQUAL -1)
- list(APPEND _protobuf_include_path -I ${ABS_PATH})
- endif()
- endforeach()
- else()
- set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+ set(_append_arg APPEND_PATH)
+ endif()
+
+ if(protobuf_generate_cpp_DESCRIPTORS)
+ set(_descriptors DESCRIPTORS)
endif()
if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
endif()
if(DEFINED Protobuf_IMPORT_DIRS)
- foreach(DIR ${Protobuf_IMPORT_DIRS})
- get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
- list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
- if(${_contains_already} EQUAL -1)
- list(APPEND _protobuf_include_path -I ${ABS_PATH})
- endif()
- endforeach()
+ set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
endif()
+ set(_outvar)
+ protobuf_generate(${_append_arg} ${_descriptors} LANGUAGE cpp EXPORT_MACRO ${protobuf_generate_cpp_EXPORT_MACRO} OUT_VAR _outvar ${_import_arg} PROTOS ${_proto_files})
+
set(${SRCS})
- foreach(FIL ${ARGN})
- get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
- get_filename_component(FIL_WE ${FIL} NAME_WE)
- if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)
- get_filename_component(FIL_DIR ${FIL} DIRECTORY)
- if(FIL_DIR)
- set(FIL_WE "${FIL_DIR}/${FIL_WE}")
- endif()
- endif()
+ set(${HDRS})
+ if(protobuf_generate_cpp_DESCRIPTORS)
+ set(${protobuf_generate_cpp_DESCRIPTORS})
+ endif()
- list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py")
- add_custom_command(
- OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py"
- COMMAND protobuf::protoc --python_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
- DEPENDS ${ABS_FIL} protobuf::protoc
- COMMENT "Running Python protocol buffer compiler on ${FIL}"
- VERBATIM )
+ foreach(_file ${_outvar})
+ if(_file MATCHES "cc$")
+ list(APPEND ${SRCS} ${_file})
+ elseif(_file MATCHES "desc$")
+ list(APPEND ${protobuf_generate_cpp_DESCRIPTORS} ${_file})
+ else()
+ list(APPEND ${HDRS} ${_file})
+ endif()
endforeach()
-
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+ set(${HDRS} ${${HDRS}} PARENT_SCOPE)
+ if(protobuf_generate_cpp_DESCRIPTORS)
+ set(${protobuf_generate_cpp_DESCRIPTORS} "${${protobuf_generate_cpp_DESCRIPTORS}}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(PROTOBUF_GENERATE_PYTHON SRCS)
+ if(NOT ARGN)
+ message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
+ return()
+ endif()
+
+ if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
+ set(_append_arg APPEND_PATH)
+ endif()
+
+ if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
+ set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
+ endif()
+
+ if(DEFINED Protobuf_IMPORT_DIRS)
+ set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
+ endif()
+
+ set(_outvar)
+ protobuf_generate(${_append_arg} LANGUAGE python OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN})
+ set(${SRCS} ${_outvar} PARENT_SCOPE)
endfunction()
mark_as_advanced(${name}_LIBRARY_DEBUG)
select_library_configurations(${name})
+
+ if(UNIX AND Threads_FOUND)
+ list(APPEND ${name}_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+
set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE)
set(${name}_LIBRARIES "${${name}_LIBRARIES}" PARENT_SCOPE)
endif()
endfunction()
-# Internal function: find threads library
-function(_protobuf_find_threads)
- set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
- find_package(Threads)
- if(Threads_FOUND)
- list(APPEND Protobuf_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
- set(Protobuf_LIBRARIES "${Protobuf_LIBRARIES}" PARENT_SCOPE)
- endif()
-endfunction()
-
#
# Main.
#
find_path(Protobuf_SRC_ROOT_FOLDER protobuf.pc.in)
endif()
+if(UNIX)
+ # Protobuf headers may depend on threading.
+ find_package(Threads QUIET)
+endif()
+
# The Protobuf library
_protobuf_find_libraries(Protobuf protobuf)
#DOC "The Google Protocol Buffers RELEASE Library"
set(CMAKE_FIND_LIBRARY_PREFIXES "${Protobuf_ORIG_FIND_LIBRARY_PREFIXES}")
endif()
-if(UNIX)
- _protobuf_find_threads()
-endif()
-
# Find the include directory
find_path(Protobuf_INCLUDE_DIR
google/protobuf/service.h
set_target_properties(protobuf::libprotobuf PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}")
endif()
+ if(UNIX AND TARGET Threads::Threads)
+ set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
+ INTERFACE_LINK_LIBRARIES Threads::Threads)
+ endif()
endif()
endif()
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}")
endif()
+ if(UNIX AND TARGET Threads::Threads)
+ set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
+ INTERFACE_LINK_LIBRARIES Threads::Threads)
+ endif()
endif()
endif()
set_target_properties(protobuf::libprotoc PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}")
endif()
+ if(UNIX AND TARGET Threads::Threads)
+ set_property(TARGET protobuf::libprotoc APPEND PROPERTY
+ INTERFACE_LINK_LIBRARIES Threads::Threads)
+ endif()
endif()
endif()
* If set to TRUE, search **only** for static libraries.
* If set to FALSE, search **only** for shared libraries.
+``Python_FIND_REGISTRY``
+ On Windows the ``Python_FIND_REGISTRY`` variable determine the order
+ of preference between registry and environment variables.
+ the ``Python_FIND_REGISTRY`` variable can be set to empty or one of the
+ following:
+
+ * ``FIRST``: Try to use registry before environment variables.
+ This is the default.
+ * ``LAST``: Try to use registry after environment variables.
+ * ``NEVER``: Never try to use registry.
+
+``CMAKE_FIND_FRAMEWORK``
+ On OS X the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of
+ preference between Apple-style and unix-style package components.
+
+ .. note::
+
+ Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
+
+.. note::
+
+ If a Python virtual environment is configured, set variable
+ ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
+ value ``LAST`` or ``NEVER`` to select it preferably.
+
Commands
^^^^^^^^
endmacro()
+macro (_PYTHON_FIND_FRAMEWORKS)
+ set (${_PYTHON_PREFIX}_FRAMEWORKS)
+ if (APPLE)
+ set (_pff_frameworks ${CMAKE_FRAMEWORK_PATH}
+ $ENV{CMAKE_FRAMEWORK_PATH}
+ ~/Library/Frameworks
+ /usr/local/Frameworks
+ ${CMAKE_SYSTEM_FRAMEWORK_PATH})
+ list (REMOVE_DUPLICATES _pff_frameworks)
+ foreach (_pff_framework IN LISTS _pff_frameworks)
+ if (EXISTS ${_pff_framework}/Python.framework)
+ list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python.framework)
+ endif()
+ endforeach()
+ unset (_pff_frameworks)
+ unset (_pff_framework)
+ endif()
+endmacro()
+
function (_PYTHON_GET_FRAMEWORKS _PYTHON_PGF_FRAMEWORK_PATHS _PYTHON_VERSION)
set (_PYTHON_FRAMEWORK_PATHS)
- foreach (_PYTHON_FRAMEWORK IN LISTS Python_FRAMEWORKS)
+ foreach (_PYTHON_FRAMEWORK IN LISTS ${_PYTHON_PREFIX}_FRAMEWORKS)
list (APPEND _PYTHON_FRAMEWORK_PATHS
"${_PYTHON_FRAMEWORK}/Versions/${_PYTHON_VERSION}")
endforeach()
return()
endif()
- if (${_PYTHON_PREFIX}_EXECUTABLE MATCHES "python${CMAKE_EXECUTABLE_SUFFIX}$")
- # executable found do not have version in name
- # ensure major version is OK
+ if (ARGC EQUAL 1)
+ set (expected_version ${ARGV0})
+ else()
+ unset (expected_version)
+ endif()
+
+ get_filename_component (python_name "${${_PYTHON_PREFIX}_EXECUTABLE}" NAME)
+
+ if (expected_version AND NOT python_name STREQUAL "python${expected_version}${CMAKE_EXECUTABLE_SUFFIX}")
+ # executable found must have a specific version
execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
- "import sys; sys.stdout.write(str(sys.version_info[0]))"
+ "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))"
RESULT_VARIABLE result
OUTPUT_VARIABLE version
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ if (result OR NOT version EQUAL expected_version)
# interpreter not usable or has wrong major version
set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
return()
endif()
+ else()
+ if (NOT python_name STREQUAL "python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}${CMAKE_EXECUTABLE_SUFFIX}")
+ # executable found do not have version in name
+ # ensure major version is OK
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+ "import sys; sys.stdout.write(str(sys.version_info[0]))"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE version
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+ # interpreter not usable or has wrong major version
+ set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+ return()
+ endif()
+ endif()
endif()
if (CMAKE_SIZEOF_VOID_P AND "Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
endfunction()
+function (_PYTHON_VALIDATE_COMPILER expected_version)
+ if (NOT ${_PYTHON_PREFIX}_COMPILER)
+ return()
+ endif()
+
+ # retrieve python environment version from compiler
+ set (working_dir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir")
+ file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))\n")
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${working_dir}/version.py"
+ WORKING_DIRECTORY "${working_dir}"
+ OUTPUT_QUIET
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process (COMMAND "${working_dir}/version"
+ WORKING_DIRECTORY "${working_dir}"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE version
+ ERROR_QUIET)
+ file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
+
+ if (result OR NOT version EQUAL expected_version)
+ # Compiler not usable or has wrong major version
+ set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE)
+ endif()
+endfunction()
+
+
function (_PYTHON_FIND_RUNTIME_LIBRARY _PYTHON_LIB)
string (REPLACE "_RUNTIME" "" _PYTHON_LIB "${_PYTHON_LIB}")
# look at runtime part on systems supporting it
endif()
endif()
-# Anaconda distribution: define which architectures can be used
+# Python and Anaconda distributions: define which architectures can be used
if (CMAKE_SIZEOF_VOID_P)
# In this case, search only for 64bit or 32bit
math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
# architecture unknown, search for natural interpreter
set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy)
endif()
+set (_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES net45 net40)
# Apple frameworks handling
-include (${CMAKE_CURRENT_LIST_DIR}/../CMakeFindFrameworks.cmake)
-cmake_find_frameworks (Python)
+_python_find_frameworks ()
+
+# Save CMAKE_FIND_APPBUNDLE
+if (DEFINED CMAKE_FIND_APPBUNDLE)
+ set (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE})
+else()
+ unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE)
+endif()
+# To avoid app bundle lookup
+set (CMAKE_FIND_APPBUNDLE "NEVER")
# Save CMAKE_FIND_FRAMEWORK
if (DEFINED CMAKE_FIND_FRAMEWORK)
set (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
+ if (CMAKE_FIND_FRAMEWORK STREQUAL "ONLY")
+ message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: CMAKE_FIND_FRAMEWORK: 'ONLY' value is not supported. 'FIRST' will be used instead.")
+ set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK "FIRST")
+ else()
+ set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
+ endif()
else()
unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
+ set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK "FIRST")
+endif()
+# To avoid framework lookup
+set (CMAKE_FIND_FRAMEWORK "NEVER")
+
+# Windows Registry handling
+if (DEFINED ${_PYTHON_PREFIX}_FIND_REGISTRY)
+ if (NOT ${_PYTHON_PREFIX}_FIND_REGISTRY MATCHES "^(FIRST|LAST|NEVER)$")
+ message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_REGISTRY}: invalid value for '${_PYTHON_PREFIX}_FIND_REGISTRY'. 'FIRST', 'LAST' or 'NEVER' expected.")
+ set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
+ else()
+ set (_${_PYTHON_PREFIX}_FIND_REGISTRY ${${_PYTHON_PREFIX}_FIND_REGISTRY})
+ endif()
+else()
+ set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
endif()
-# To avoid picking up the system elements pre-maturely.
-set (CMAKE_FIND_FRAMEWORK LAST)
unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
_python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
+ # Apple frameworks handling
+ if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ NAMES_PER_DIR
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ PATH_SUFFIXES bin
+ NO_CMAKE_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
+ # Windows registry
+ if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ python
+ ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
# try using HINTS
find_program (${_PYTHON_PREFIX}_EXECUTABLE
NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ python
+ ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
NAMES_PER_DIR
HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- PATH_SUFFIXES bin
+ PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH)
- # try using registry
+ # try using standard paths.
if (WIN32)
find_program (${_PYTHON_PREFIX}_EXECUTABLE
- NAMES python${_${_PYTHON_PREFIX}_VERSION} python
+ NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ python
+ ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+ NAMES_PER_DIR)
+ else()
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ NAMES_PER_DIR)
+ endif()
+
+ # Apple frameworks handling
+ if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ NAMES_PER_DIR
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ PATH_SUFFIXES bin
+ NO_DEFAULT_PATH)
+ endif()
+
+ # Windows registry
+ if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION}
+ python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ python
${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- PATH_SUFFIXES bin
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
+ PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
+ NO_DEFAULT_PATH)
endif()
- # try in standard paths
- find_program (${_PYTHON_PREFIX}_EXECUTABLE
- NAMES python${_${_PYTHON_PREFIX}_VERSION})
- _python_validate_interpreter ()
+ _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION})
if (${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
endforeach()
- # try more generic names
if (NOT ${_PYTHON_PREFIX}_EXECUTABLE)
+ # No specific version found. Retry with generic names
+ # try using HINTS
find_program (${_PYTHON_PREFIX}_EXECUTABLE
- NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python
+ NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ python
${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+ NAMES_PER_DIR
HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES bin)
+ PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ # try using standard paths.
+ # NAMES_PER_DIR is not defined on purpose to have a chance to find
+ # expected version.
+ # For example, typical systems have 'python' for version 2.* and 'python3'
+ # for version 3.*. So looking for names per dir will find, potentially,
+ # systematically 'python' (i.e. version 2) even if version 3 is searched.
+ find_program (${_PYTHON_PREFIX}_EXECUTABLE
+ NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
+ python
+ ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES})
_python_validate_interpreter ()
endif()
endif()
if (${_PYTHON_PREFIX}_Interpreter_FOUND)
+ if (NOT CMAKE_SIZEOF_VOID_P)
+ # determine interpreter architecture
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)"
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE ${_PYTHON_PREFIX}_IS64BIT
+ ERROR_VARIABLE ${_PYTHON_PREFIX}_IS64BIT)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ if (${_PYTHON_PREFIX}_IS64BIT)
+ set (_${_PYTHON_PREFIX}_ARCH 64)
+ set (_${_PYTHON_PREFIX}_ARCH2 64)
+ else()
+ set (_${_PYTHON_PREFIX}_ARCH 32)
+ set (_${_PYTHON_PREFIX}_ARCH2 32)
+ endif()
+ endif()
+ endif()
+
# retrieve interpreter identity
execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -V
RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
# try using root dir and registry
foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+ if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
+ find_program (${_PYTHON_PREFIX}_COMPILER
+ NAMES ipyc
+ HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
find_program (${_PYTHON_PREFIX}_COMPILER
NAMES ipyc
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH)
+
+ if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
+ find_program (${_PYTHON_PREFIX}_COMPILER
+ NAMES ipyc
+ PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}
+ NO_DEFAULT_PATH)
+ endif()
+
+ _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION})
if (${_PYTHON_PREFIX}_COMPILER)
break()
endif()
endforeach()
- # try in standard paths
+
+ # no specific version found, re-try in standard paths
find_program (${_PYTHON_PREFIX}_COMPILER
- NAMES ipyc)
+ NAMES ipyc
+ HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES})
if (${_PYTHON_PREFIX}_COMPILER)
# retrieve python environment version from compiler
list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "python${_${_PYTHON_PREFIX}_VERSION}-config")
find_program (_${_PYTHON_PREFIX}_CONFIG
NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES}
+ NAMES_PER_DIR
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES bin)
unset (_${_PYTHON_PREFIX}_CONFIG_NAMES)
if (NOT _${_PYTHON_PREFIX}_CONFIG)
continue()
endif()
+ if (DEFINED CMAKE_LIBRARY_ARCHITECTURE)
+ # check that config tool match library architecture
+ execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (_${_PYTHON_PREFIX}_RESULT)
+ unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
+ continue()
+ endif()
+ string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT)
+ if (_${_PYTHON_PREFIX}_RESULT EQUAL -1)
+ unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
+ continue()
+ endif()
+ endif()
# retrieve root install directory
execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --prefix
_python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
- # search first in known locations
+ set (_${_PYTHON_PREFIX}_REGISTRY_PATHS
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath])
+
+ if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
+ find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
+ python${_${_PYTHON_PREFIX}_VERSION}mu
+ python${_${_PYTHON_PREFIX}_VERSION}m
+ python${_${_PYTHON_PREFIX}_VERSION}u
+ python${_${_PYTHON_PREFIX}_VERSION}
+ NAMES_PER_DIR
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config
+ NO_CMAKE_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
+ if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
+ find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
+ python${_${_PYTHON_PREFIX}_VERSION}mu
+ python${_${_PYTHON_PREFIX}_VERSION}m
+ python${_${_PYTHON_PREFIX}_VERSION}u
+ python${_${_PYTHON_PREFIX}_VERSION}
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
+ PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}
+ lib/python${_${_PYTHON_PREFIX}_VERSION}/config
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
+ # search in HINTS locations
find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
python${_${_PYTHON_PREFIX}_VERSION}mu
python${_${_PYTHON_PREFIX}_VERSION}
NAMES_PER_DIR
HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs
lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu
lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m
lib/python${_${_PYTHON_PREFIX}_VERSION}/config
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH)
+
+ if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST")
+ set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS})
+ else()
+ unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
+ endif()
+
+ if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
+ set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS})
+ else()
+ unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS)
+ endif()
+
# search in all default paths
find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
python${_${_PYTHON_PREFIX}_VERSION}u
python${_${_PYTHON_PREFIX}_VERSION}
NAMES_PER_DIR
+ PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ ${__${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs
lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu
lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m
python${_${_PYTHON_PREFIX}_VERSION}
NAMES_PER_DIR
HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
PATH_SUFFIXES bin)
endif()
# use library location as a hint
get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
- NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
- NAMES_PER_DIR
- HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
- NO_DEFAULT_PATH)
- else()
- # search first in known locations
- find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
NAMES_PER_DIR
- HINTS ${_${_PYTHON_PREFIX}_HINTS}
- PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- PATH_SUFFIXES lib libs
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
+ HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
+ NO_DEFAULT_PATH)
+ else()
+ # search first in known locations
+ if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
+ find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
+ NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+ NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
+ PATH_SUFFIXES lib libs
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
# search in all default paths
find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
NAMES_PER_DIR
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${__${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES lib libs)
endif()
if (${_PYTHON_PREFIX}_LIBRARY_DEBUG)
NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
NAMES_PER_DIR
HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
- PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
PATH_SUFFIXES bin)
endif()
endif()
# Don't search for include dir until library location is known
if (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS)
+
+ if (${_PYTHON_PREFIX}_EXECUTABLE)
+ # pick up include directory from configuration
+ execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+ "import sys; import sysconfig; sys.stdout.write(sysconfig.get_path('include'))"
+ RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+ OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PATH
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (NOT _${_PYTHON_PREFIX}_RESULT)
+ file (TO_CMAKE_PATH "${_${_PYTHON_PREFIX}_PATH}" _${_PYTHON_PREFIX}_PATH)
+ list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PATH}")
+ endif()
+ endif()
+
foreach (_${_PYTHON_PREFIX}_LIB IN ITEMS ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
if (${_${_PYTHON_PREFIX}_LIB})
# Use the library's install prefix as a hint
endforeach()
list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_HINTS)
+ if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
+ find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+ NAMES Python.h
+ HINTS ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu
+ include/python${_${_PYTHON_PREFIX}_VERSION}m
+ include/python${_${_PYTHON_PREFIX}_VERSION}u
+ include/python${_${_PYTHON_PREFIX}_VERSION}
+ include
+ NO_CMAKE_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
+ if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST")
+ find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+ NAMES Python.h
+ HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS}
+ PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
+ PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu
+ include/python${_${_PYTHON_PREFIX}_VERSION}m
+ include/python${_${_PYTHON_PREFIX}_VERSION}u
+ include/python${_${_PYTHON_PREFIX}_VERSION}
+ include
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH)
+ endif()
+
find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
NAMES Python.h
HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS}
- PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+ PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+ ${__${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu
include/python${_${_PYTHON_PREFIX}_VERSION}m
include/python${_${_PYTHON_PREFIX}_VERSION}u
# final clean-up
+# Restore CMAKE_FIND_APPBUNDLE
+if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE)
+ set (CMAKE_FIND_APPBUNDLE ${_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE})
+ unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE)
+else()
+ unset (CMAKE_FIND_APPBUNDLE)
+endif()
# Restore CMAKE_FIND_FRAMEWORK
if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
set (CMAKE_FIND_FRAMEWORK ${_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK})
* If set to TRUE, search **only** for static libraries.
* If set to FALSE, search **only** for shared libraries.
+``Python2_FIND_REGISTRY``
+ On Windows the ``Python2_FIND_REGISTRY`` variable determine the order
+ of preference between registry and environment variables.
+ the ``Python2_FIND_REGISTRY`` variable can be set to empty or one of the
+ following:
+
+ * ``FIRST``: Try to use registry before environment variables.
+ This is the default.
+ * ``LAST``: Try to use registry after environment variables.
+ * ``NEVER``: Never try to use registry.
+
+``CMAKE_FIND_FRAMEWORK``
+ On macOS the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of
+ preference between Apple-style and unix-style package components.
+
+ .. note::
+
+ Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
+
+.. note::
+
+ If a Python virtual environment is configured, set variable
+ ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
+ value ``LAST`` or ``NEVER`` to select it preferably.
+
Commands
^^^^^^^^
* If set to TRUE, search **only** for static libraries.
* If set to FALSE, search **only** for shared libraries.
+``Python3_FIND_REGISTRY``
+ On Windows the ``Python3_FIND_REGISTRY`` variable determine the order
+ of preference between registry and environment variables.
+ the ``Python3_FIND_REGISTRY`` variable can be set to empty or one of the
+ following:
+
+ * ``FIRST``: Try to use registry before environment variables.
+ This is the default.
+ * ``LAST``: Try to use registry after environment variables.
+ * ``NEVER``: Never try to use registry.
+
+``CMAKE_FIND_FRAMEWORK``
+ On OS X the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of
+ preference between Apple-style and unix-style package components.
+
+ .. note::
+
+ Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
+
+.. note::
+
+ If a Python virtual environment is configured, set variable
+ ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
+ value ``LAST`` or ``NEVER`` to select it preferably.
+
Commands
^^^^^^^^
unset(_PYTHON2_VERSIONS)
unset(_PYTHON3_VERSIONS)
+# Python distribution: define which architectures can be used
+if (CMAKE_SIZEOF_VOID_P)
+ # In this case, search only for 64bit or 32bit
+ math (EXPR _PYTHON_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
+ set (_PYTHON_ARCH2 _PYTHON_PREFIX_ARCH})
+else()
+ if (PYTHON_EXECUTABLE)
+ # determine interpreter architecture
+ execute_process (COMMAND "${PYTHON_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)"
+ RESULT_VARIABLE _PYTHON_RESULT
+ OUTPUT_VARIABLE _PYTHON_IS64BIT
+ ERROR_VARIABLE _PYTHON_IS64BIT)
+ if (NOT _PYTHON_RESULT)
+ if (_PYTHON_IS64BIT)
+ set (_PYTHON_ARCH 64)
+ set (_PYTHON_ARCH2 64)
+ else()
+ set (_PYTHON_ARCH 32)
+ set (_PYTHON_ARCH2 32)
+ endif()
+ endif()
+ else()
+ # architecture unknown, search for both 64bit and 32bit
+ set (_PYTHON_ARCH 64)
+ set (_PYTHON_ARCH2 32)
+ endif()
+endif()
+
foreach(_CURRENT_VERSION ${_Python_VERSIONS})
string(REPLACE "." "" _CURRENT_VERSION_NO_DOTS ${_CURRENT_VERSION})
if(WIN32)
HINTS ${_Python_LIBRARY_PATH_HINT}
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs/Debug
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs/Debug
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs/Debug
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs/Debug
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
)
endif()
PATHS
${PYTHON_FRAMEWORK_LIBRARIES}
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/libs
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/libs
)
# Look for the static library in the Python config directory
find_library(PYTHON_LIBRARY
PATHS
${PYTHON_FRAMEWORK_INCLUDES}
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/include
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/include
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH}\\InstallPath]/include
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-${_PYTHON_ARCH2}\\InstallPath]/include
PATH_SUFFIXES
python${_CURRENT_VERSION}mu
python${_CURRENT_VERSION}m
#
#
# The minimum required version of Subversion can be specified using the
-# standard syntax, e.g. find_package(Subversion 1.4)
+# standard syntax, e.g. ``find_package(Subversion 1.4)``.
#
# If the command line client executable is found two macros are defined:
#
# ::
#
-# Subversion_WC_INFO(<dir> <var-prefix>)
+# Subversion_WC_INFO(<dir> <var-prefix> [IGNORE_SVN_FAILURE])
# Subversion_WC_LOG(<dir> <var-prefix>)
#
-# Subversion_WC_INFO extracts information of a subversion working copy
-# at a given location. This macro defines the following variables:
+# ``Subversion_WC_INFO`` extracts information of a subversion working copy at a
+# given location. This macro defines the following variables if running
+# Subversion's ``info`` command on ``<dir>`` succeeds; otherwise a
+# ``SEND_ERROR`` message is generated. The error can be ignored by providing the
+# ``IGNORE_SVN_FAILURE`` option, which causes these variables to remain
+# undefined.
#
# ::
#
# <var-prefix>_WC_LAST_CHANGED_REV - revision of last commit
# <var-prefix>_WC_INFO - output of command `svn info <dir>'
#
-# Subversion_WC_LOG retrieves the log message of the base revision of a
-# subversion working copy at a given location. This macro defines the
-# variable:
+# ``Subversion_WC_LOG`` retrieves the log message of the base revision of a
+# subversion working copy at a given location. This macro defines the variable:
#
# ::
#
"\\2" Subversion_VERSION_SVN "${Subversion_VERSION_SVN}")
macro(Subversion_WC_INFO dir prefix)
+
+ cmake_parse_arguments(
+ "Subversion_WC_INFO"
+ "IGNORE_SVN_FAILURE"
+ "" ""
+ ${ARGN}
+ )
+
# the subversion commands should be executed with the C locale, otherwise
# the message (which are parsed) may be translated, Alex
set(_Subversion_SAVED_LC_ALL "$ENV{LC_ALL}")
RESULT_VARIABLE Subversion_svn_info_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
- if(NOT ${Subversion_svn_info_result} EQUAL 0)
- message(SEND_ERROR "Command \"${Subversion_SVN_EXECUTABLE} info ${dir}\" failed with output:\n${Subversion_svn_info_error}")
- else()
-
+ if(${Subversion_svn_info_result} EQUAL 0)
string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
"\\2" ${prefix}_WC_URL "${${prefix}_WC_INFO}")
string(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*"
"\\2" ${prefix}_WC_LAST_CHANGED_REV "${${prefix}_WC_INFO}")
string(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*"
"\\2" ${prefix}_WC_LAST_CHANGED_DATE "${${prefix}_WC_INFO}")
-
+ elseif(NOT Subversion_WC_INFO_IGNORE_SVN_FAILURE)
+ message(SEND_ERROR "Command \"${Subversion_SVN_EXECUTABLE} info ${dir}\" failed with output:\n${Subversion_svn_info_error}")
endif()
# restore the previous LC_ALL
add_library(Threads::Threads INTERFACE IMPORTED)
if(THREADS_HAVE_PTHREAD_ARG)
- set_property(TARGET Threads::Threads PROPERTY INTERFACE_COMPILE_OPTIONS "-pthread")
+ set_property(TARGET Threads::Threads
+ PROPERTY INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:-Xcompiler -pthread>"
+ "$<$<NOT:$<COMPILE_LANGUAGE:CUDA>>:-pthread>")
endif()
if(CMAKE_THREAD_LIBS_INIT)
endif()
set(XercesC_VERSION "${XercesC_MAJOR}.${XercesC_MINOR}.${XercesC_PATCH}" PARENT_SCOPE)
+ set(XercesC_VERSION_MAJOR "${XercesC_MAJOR}" PARENT_SCOPE)
+ set(XercesC_VERSION_MINOR "${XercesC_MINOR}" PARENT_SCOPE)
+ set(XercesC_VERSION_PATCH "${XercesC_PATCH}" PARENT_SCOPE)
else()
message(FATAL_ERROR "Include file ${version_hdr} does not exist or does not contain expected version information")
endif()
DOC "Xerces-C++ include directory")
mark_as_advanced(XercesC_INCLUDE_DIR)
+if(XercesC_INCLUDE_DIR)
+ _XercesC_GET_VERSION("${XercesC_INCLUDE_DIR}/xercesc/util/XercesVersion.hpp")
+endif()
+
if(NOT XercesC_LIBRARY)
# Find all XercesC libraries
find_library(XercesC_LIBRARY_RELEASE
- NAMES "xerces-c" "xerces-c_3"
+ NAMES "xerces-c" "xerces-c_${XercesC_VERSION_MAJOR}"
DOC "Xerces-C++ libraries (release)")
find_library(XercesC_LIBRARY_DEBUG
- NAMES "xerces-cd" "xerces-c_3D" "xerces-c_3_1D"
+ NAMES "xerces-cd" "xerces-c_${XercesC_VERSION_MAJOR}D" "xerces-c_${XercesC_VERSION_MAJOR}_${XercesC_VERSION_MINOR}D"
DOC "Xerces-C++ libraries (debug)")
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
select_library_configurations(XercesC)
mark_as_advanced(XercesC_LIBRARY_RELEASE XercesC_LIBRARY_DEBUG)
endif()
-if(XercesC_INCLUDE_DIR)
- _XercesC_GET_VERSION("${XercesC_INCLUDE_DIR}/xercesc/util/XercesVersion.hpp")
-endif()
+unset(XercesC_VERSION_MAJOR)
+unset(XercesC_VERSION_MINOR)
+unset(XercesC_VERSION_PATCH)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(XercesC
endif()
# Normal search.
+set(_ZLIB_x86 "(x86)")
set(_ZLIB_SEARCH_NORMAL
- PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]"
- "$ENV{PROGRAMFILES}/zlib"
- )
+ PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]"
+ "$ENV{ProgramFiles}/zlib"
+ "$ENV{ProgramFiles${_ZLIB_x86}}/zlib")
+unset(_ZLIB_x86)
list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL)
set(ZLIB_NAMES z zlib zdll zlib1)
# libraries and nodekits. Please see FindOpenSceneGraph.cmake for full
# documentation.
+include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+
#
# OSG_FIND_PATH
#
function(OSG_FIND_LIBRARY module library)
string(TOUPPER ${module} module_uc)
- find_library(${module_uc}_LIBRARY
+ find_library(${module_uc}_LIBRARY_RELEASE
NAMES ${library}
HINTS
ENV ${module_uc}_DIR
PATH_SUFFIXES lib
)
- if(NOT ${module_uc}_LIBRARY_DEBUG)
- # They don't have a debug library
- set(${module_uc}_LIBRARY_DEBUG ${${module_uc}_LIBRARY} PARENT_SCOPE)
- set(${module_uc}_LIBRARIES ${${module_uc}_LIBRARY} PARENT_SCOPE)
- else()
- # They really have a FOO_LIBRARY_DEBUG
- set(${module_uc}_LIBRARIES
- optimized ${${module_uc}_LIBRARY}
- debug ${${module_uc}_LIBRARY_DEBUG}
- PARENT_SCOPE
- )
- endif()
+ select_library_configurations(${module_uc})
+
+ # the variables set by select_library_configurations go out of scope
+ # here, so we need to set them again
+ set(${module_uc}_LIBRARY ${${module_uc}_LIBRARY} PARENT_SCOPE)
+ set(${module_uc}_LIBRARIES ${${module_uc}_LIBRARIES} PARENT_SCOPE)
endfunction()
#
_GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}"
"Read-only architecture-independent data (DATAROOTDIR)")
-if(CMAKE_SYSTEM_NAME MATCHES "^(.*BSD|DragonFly)$")
+if(CMAKE_SYSTEM_NAME MATCHES "^(([^k].*)?BSD|DragonFly)$")
_GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_INFODIR "info"
"Info documentation (info)")
_GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_MANDIR "man"
# as the executable by default:
#
set(path "@executable_path")
- set(overridden 0)
# On the Mac, relative to the executable depending on the type
# of the thing we are embedding:
#
set(path "@executable_path/../../Contents/MacOS")
- # Embed .dylibs right next to the main bundle executable:
+ # Embed frameworks and .dylibs in the embedded "Frameworks" directory
+ # (sibling of MacOS):
#
- if(item MATCHES "\\.dylib$")
- set(path "@executable_path/../MacOS")
- set(overridden 1)
- endif()
-
- # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
- #
- if(NOT overridden)
- if(item MATCHES "[^/]+\\.framework/")
- set(path "@executable_path/../Frameworks")
- set(overridden 1)
- endif()
+ if(item MATCHES "[^/]+\\.framework/" OR item MATCHES "\\.dylib$")
+ set(path "@executable_path/../Frameworks")
endif()
endif()
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})
+ 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})
get_filename_component(windows_kits_dir
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]" ABSOLUTE)
set(programfilesx86 "ProgramFiles(x86)")
- find_path(WINDOWS_KITS_DIR NAMES Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll
+ if(";${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION};$ENV{UCRTVersion};$ENV{WindowsSDKVersion};" MATCHES [=[;(10\.[0-9.]+)[;\]]=])
+ set(__ucrt_version "${CMAKE_MATCH_1}/")
+ else()
+ set(__ucrt_version "")
+ endif()
+ find_path(WINDOWS_KITS_DIR
+ NAMES
+ Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll
+ Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll
PATHS
$ENV{CMAKE_WINDOWS_KITS_10_DIR}
"${windows_kits_dir}"
# Glob the list of UCRT DLLs.
if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY)
- file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll")
+ if(EXISTS "${WINDOWS_KITS_DIR}/Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll")
+ file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll")
+ else()
+ file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll")
+ endif()
list(APPEND __install__libs ${__ucrt_dlls})
endif()
if(CMAKE_INSTALL_DEBUG_LIBRARIES)
- file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${CMAKE_MSVC_ARCH}/ucrt/*.dll")
+ if(EXISTS "${WINDOWS_KITS_DIR}/bin/${__ucrt_version}${CMAKE_MSVC_ARCH}/ucrt/ucrtbased.dll")
+ file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${__ucrt_version}${CMAKE_MSVC_ARCH}/ucrt/*.dll")
+ else()
+ file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${CMAKE_MSVC_ARCH}/ucrt/*.dll")
+ endif()
list(APPEND __install__libs ${__ucrt_dlls})
endif()
endif()
)
endif()
- # include the language dll's for vs8 as well as the actuall dll's
+ # include the language dll's for vs8 as well as the actual dll's
set(MSVC_MFCLOC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC80.MFCLOC")
# Install the manifest that allows DLLs to be loaded from the
# directory containing the executable.
)
endif()
- # include the language dll's for vs9 as well as the actuall dll's
+ # include the language dll's for vs9 as well as the actual dll's
set(MSVC_MFCLOC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC90.MFCLOC")
# Install the manifest that allows DLLs to be loaded from the
# directory containing the executable.
endif()
endif()
- # include the language dll's as well as the actuall dll's
+ # include the language dll's as well as the actual dll's
set(MSVC_MFCLOC_DIR "${MSVC_REDIST_MFC_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.MFCLOC")
set(__install__libs ${__install__libs}
"${MSVC_MFCLOC_DIR}/mfc${v}chs.dll"
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# CPackDeb
-# --------
-#
-# The built in (binary) CPack Deb generator (Unix only)
-#
-# Variables specific to CPack Debian (DEB) generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# CPackDeb may be used to create Deb package using :module:`CPack`.
-# CPackDeb is a :module:`CPack` generator thus it uses the ``CPACK_XXX``
-# variables used by :module:`CPack`.
-#
-# CPackDeb generator should work on any Linux host but it will produce
-# better deb package when Debian specific tools ``dpkg-xxx`` are usable on
-# the build system.
-#
-# CPackDeb has specific features which are controlled by the specifics
-# :code:`CPACK_DEBIAN_XXX` variables.
-#
-# :code:`CPACK_DEBIAN_<COMPONENT>_XXXX` variables may be used in order to have
-# **component** specific values. Note however that ``<COMPONENT>`` refers to
-# the **grouping name** written in upper case. It may be either a component name
-# or a component GROUP name.
-#
-# Here are some CPackDeb wiki resources that are here for historic reasons and
-# are no longer maintained but may still prove useful:
-#
-# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/Configuration
-# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/PackageGenerators#deb-unix-only
-#
-# List of CPackDEB specific variables:
-#
-# .. variable:: CPACK_DEB_COMPONENT_INSTALL
-#
-# Enable component packaging for CPackDEB
-#
-# * Mandatory : NO
-# * Default : OFF
-#
-# If enabled (ON) multiple packages are generated. By default a single package
-# containing files of all components is generated.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_NAME
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_NAME
-#
-# Set Package control field (variable is automatically transformed to lower
-# case).
-#
-# * Mandatory : YES
-# * Default :
-#
-# - :variable:`CPACK_PACKAGE_NAME` for non-component based
-# installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_NAME` suffixed with -<COMPONENT>
-# for component-based installations.
-#
-# See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
-#
-# .. variable:: CPACK_DEBIAN_FILE_NAME
-# CPACK_DEBIAN_<COMPONENT>_FILE_NAME
-#
-# Package file name.
-#
-# * Mandatory : YES
-# * Default : ``<CPACK_PACKAGE_FILE_NAME>[-<component>].deb``
-#
-# This may be set to ``DEB-DEFAULT`` to allow CPackDeb to generate package file
-# name by itself in deb format::
-#
-# <PackageName>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
-#
-# Alternatively provided package file name must end
-# with either ``.deb`` or ``.ipk`` suffix.
-#
-# .. note::
-#
-# Preferred setting of this variable is ``DEB-DEFAULT`` but for backward
-# compatibility with CPackDeb in CMake prior to version 3.6 this feature
-# is disabled by default.
-#
-# .. note::
-#
-# By using non default filenames duplicate names may occur. Duplicate files
-# get overwritten and it is up to the packager to set the variables in a
-# manner that will prevent such errors.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_EPOCH
-#
-# The Debian package epoch
-#
-# * Mandatory : No
-# * Default : -
-#
-# Optional number that should be incremented when changing versioning schemas
-# or fixing mistakes in the version numbers of older packages.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_VERSION
-#
-# The Debian package version
-#
-# * Mandatory : YES
-# * Default : :variable:`CPACK_PACKAGE_VERSION`
-#
-# This variable may contain only alphanumerics (A-Za-z0-9) and the characters
-# . + - ~ (full stop, plus, hyphen, tilde) and should start with a digit. If
-# :variable:`CPACK_DEBIAN_PACKAGE_RELEASE` is not set then hyphens are not
-# allowed.
-#
-# .. note::
-#
-# For backward compatibility with CMake 3.9 and lower a failed test of this
-# variable's content is not a hard error when both
-# :variable:`CPACK_DEBIAN_PACKAGE_RELEASE` and
-# :variable:`CPACK_DEBIAN_PACKAGE_EPOCH` variables are not set. An author
-# warning is reported instead.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_RELEASE
-#
-# The Debian package release - Debian revision number.
-#
-# * Mandatory : No
-# * Default : -
-#
-# This is the numbering of the DEB package itself, i.e. the version of the
-# packaging and not the version of the content (see
-# :variable:`CPACK_DEBIAN_PACKAGE_VERSION`). One may change the default value
-# if the previous packaging was buggy and/or you want to put here a fancy Linux
-# distro specific numbering.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_ARCHITECTURE
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_ARCHITECTURE
-#
-# The Debian package architecture
-#
-# * Mandatory : YES
-# * Default : Output of :code:`dpkg --print-architecture` (or :code:`i386`
-# if :code:`dpkg` is not found)
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_DEPENDS
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS
-#
-# Sets the Debian dependencies of this package.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_DEPENDS` for component-based
-# installations.
-#
-# .. note::
-#
-# If :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS` or
-# more specifically :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS`
-# is set for this component, the discovered dependencies will be appended
-# to :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS` instead of
-# :variable:`CPACK_DEBIAN_PACKAGE_DEPENDS`. If
-# :variable:`CPACK_DEBIAN_<COMPONENT>_PACKAGE_DEPENDS` is an empty string,
-# only the automatically discovered dependencies will be set for this
-# component.
-#
-# Example::
-#
-# set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libc6 (< 2.4)")
-#
-# .. variable:: CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS
-#
-# Sets inter component dependencies if listed with
-# :variable:`CPACK_COMPONENT_<compName>_DEPENDS` variables.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_MAINTAINER
-#
-# The Debian package maintainer
-#
-# * Mandatory : YES
-# * Default : :code:`CPACK_PACKAGE_CONTACT`
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_DESCRIPTION
-# CPACK_COMPONENT_<COMPONENT>_DESCRIPTION
-#
-# The Debian package description
-#
-# * Mandatory : YES
-# * Default :
-#
-# - :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` if set or
-# - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
-#
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_SECTION
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_SECTION
-#
-# Set Section control field e.g. admin, devel, doc, ...
-#
-# * Mandatory : YES
-# * Default : "devel"
-#
-# See https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
-#
-# .. variable:: CPACK_DEBIAN_ARCHIVE_TYPE
-#
-# The archive format used for creating the Debian package.
-#
-# * Mandatory : YES
-# * Default : "paxr"
-#
-# Possible values are:
-#
-# - paxr
-# - gnutar
-#
-# .. note::
-#
-# Default pax archive format is the most portable format and generates
-# packages that do not treat sparse files specially.
-# GNU tar format on the other hand supports longer filenames.
-#
-# .. variable:: CPACK_DEBIAN_COMPRESSION_TYPE
-#
-# The compression used for creating the Debian package.
-#
-# * Mandatory : YES
-# * Default : "gzip"
-#
-# Possible values are:
-#
-# - lzma
-# - xz
-# - bzip2
-# - gzip
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_PRIORITY
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY
-#
-# Set Priority control field e.g. required, important, standard, optional,
-# extra
-#
-# * Mandatory : YES
-# * Default : "optional"
-#
-# See https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_HOMEPAGE
-#
-# The URL of the web site for this package, preferably (when applicable) the
-# site from which the original source can be obtained and any additional
-# upstream documentation or information may be found.
-#
-# * Mandatory : NO
-# * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
-#
-# .. note::
-#
-# The content of this field is a simple URL without any surrounding
-# characters such as <>.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_SHLIBDEPS
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_SHLIBDEPS
-#
-# May be set to ON in order to use :code:`dpkg-shlibdeps` to generate
-# better package dependency list.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - :variable:`CPACK_DEBIAN_PACKAGE_SHLIBDEPS` if set or
-# - OFF
-#
-# .. note::
-#
-# You may need set :variable:`CMAKE_INSTALL_RPATH` to an appropriate value
-# if you use this feature, because if you don't :code:`dpkg-shlibdeps`
-# may fail to find your own shared libs.
-# See https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_DEBUG
-#
-# May be set when invoking cpack in order to trace debug information
-# during CPackDeb run.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_PREDEPENDS
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_PREDEPENDS
-#
-# Sets the `Pre-Depends` field of the Debian package.
-# Like :variable:`Depends <CPACK_DEBIAN_PACKAGE_DEPENDS>`, except that it
-# also forces :code:`dpkg` to complete installation of the packages named
-# before even starting the installation of the package which declares the
-# pre-dependency.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_PREDEPENDS` for component-based
-# installations.
-#
-# See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_ENHANCES
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_ENHANCES
-#
-# Sets the `Enhances` field of the Debian package.
-# Similar to :variable:`Suggests <CPACK_DEBIAN_PACKAGE_SUGGESTS>` but works
-# in the opposite direction: declares that a package can enhance the
-# functionality of another package.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_ENHANCES` for component-based
-# installations.
-#
-# See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_BREAKS
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_BREAKS
-#
-# Sets the `Breaks` field of the Debian package.
-# When a binary package (P) declares that it breaks other packages (B),
-# :code:`dpkg` will not allow the package (P) which declares `Breaks` be
-# **unpacked** unless the packages that will be broken (B) are deconfigured
-# first.
-# As long as the package (P) is configured, the previously deconfigured
-# packages (B) cannot be reconfigured again.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_BREAKS` for component-based
-# installations.
-#
-# See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-breaks
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_CONFLICTS
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONFLICTS
-#
-# Sets the `Conflicts` field of the Debian package.
-# When one binary package declares a conflict with another using a `Conflicts`
-# field, :code:`dpkg` will not allow them to be unpacked on the system at
-# the same time.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_CONFLICTS` for component-based
-# installations.
-#
-# See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-conflicts
-#
-# .. note::
-#
-# This is a stronger restriction than
-# :variable:`Breaks <CPACK_DEBIAN_PACKAGE_BREAKS>`, which prevents the
-# broken package from being configured while the breaking package is in
-# the "Unpacked" state but allows both packages to be unpacked at the same
-# time.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_PROVIDES
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_PROVIDES
-#
-# Sets the `Provides` field of the Debian package.
-# A virtual package is one which appears in the `Provides` control field of
-# another package.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_PROVIDES` for component-based
-# installations.
-#
-# See https://www.debian.org/doc/debian-policy/ch-relationships.html#s-virtual
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_REPLACES
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_REPLACES
-#
-# Sets the `Replaces` field of the Debian package.
-# Packages can declare in their control file that they should overwrite
-# files in certain other packages, or completely replace other packages.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_REPLACES` for component-based
-# installations.
-#
-# See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_RECOMMENDS
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_RECOMMENDS
-#
-# Sets the `Recommends` field of the Debian package.
-# Allows packages to declare a strong, but not absolute, dependency on other
-# packages.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_RECOMMENDS` for component-based
-# installations.
-#
-# See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_SUGGESTS
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_SUGGESTS
-#
-# Sets the `Suggests` field of the Debian package.
-# Allows packages to declare a suggested package install grouping.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_SUGGESTS` for component-based
-# installations.
-#
-# See http://www.debian.org/doc/debian-policy/ch-relationships.html#s-binarydeps
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS
-#
-# * Mandatory : NO
-# * Default : OFF
-#
-# Allows to generate shlibs control file automatically. Compatibility is defined by
-# :variable:`CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY` variable value.
-#
-# .. note::
-#
-# Libraries are only considered if they have both library name and version
-# set. This can be done by setting SOVERSION property with
-# :command:`set_target_properties` command.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY
-#
-# Compatibility policy for auto-generated shlibs control file.
-#
-# * Mandatory : NO
-# * Default : "="
-#
-# Defines compatibility policy for auto-generated shlibs control file.
-# Possible values: "=", ">="
-#
-# See https://www.debian.org/doc/debian-policy/ch-sharedlibs.html#s-sharedlibs-shlibdeps
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONTROL_EXTRA
-#
-# This variable allow advanced user to add custom script to the
-# control.tar.gz.
-# Typical usage is for conffiles, postinst, postrm, prerm.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# Usage::
-#
-# set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
-# "${CMAKE_CURRENT_SOURCE_DIR}/prerm;${CMAKE_CURRENT_SOURCE_DIR}/postrm")
-#
-# .. note::
-#
-# The original permissions of the files will be used in the final
-# package unless the variable
-# :variable:`CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION` is set.
-# In particular, the scripts should have the proper executable
-# flag prior to the generation of the package.
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_CONTROL_STRICT_PERMISSION
-#
-# This variable indicates if the Debian policy on control files should be
-# strictly followed.
-#
-# * Mandatory : NO
-# * Default : FALSE
-#
-# Usage::
-#
-# set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
-#
-# .. note::
-#
-# This overrides the permissions on the original files, following the rules
-# set by Debian policy
-# https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
-#
-# .. variable:: CPACK_DEBIAN_PACKAGE_SOURCE
-# CPACK_DEBIAN_<COMPONENT>_PACKAGE_SOURCE
-#
-# Sets the ``Source`` field of the binary Debian package.
-# When the binary package name is not the same as the source package name
-# (in particular when several components/binaries are generated from one
-# source) the source from which the binary has been generated should be
-# indicated with the field ``Source``.
-#
-# * Mandatory : NO
-# * Default :
-#
-# - An empty string for non-component based installations
-# - :variable:`CPACK_DEBIAN_PACKAGE_SOURCE` for component-based
-# installations.
-#
-# See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
-#
-# .. note::
-#
-# This value is not interpreted. It is possible to pass an optional
-# revision number of the referenced source package as well.
-#
-# Building Debian packages on Windows
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# To communicate UNIX file permissions from the install stage
-# to the CPack DEB generator the "cmake_mode_t" NTFS
-# alternate data stream (ADT) is used.
-#
-# When a filesystem without ADT support is used only owner read/write
-# permissions can be preserved.
-
# CPack script for creating Debian package
# Author: Mathieu Malaterre
#
message(FATAL_ERROR "CPackDeb.cmake may only be used by CPack internally.")
endif()
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
function(cpack_deb_variable_fallback OUTPUT_VAR_NAME)
set(FALLBACK_VAR_NAMES ${ARGN})
endif()
set(WDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}")
+ set(DBGSYMDIR "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_DEB_PACKAGE_COMPONENT_PART_PATH}-dbgsym")
+ file(REMOVE_RECURSE "${DBGSYMDIR}")
# per component automatic discover: some of the component might not have
# binaries.
endif()
endif()
- if(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OR CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS)
+ cpack_deb_variable_fallback("CPACK_DEBIAN_DEBUGINFO_PACKAGE"
+ "CPACK_DEBIAN_${_local_component_name}_DEBUGINFO_PACKAGE"
+ "CPACK_DEBIAN_DEBUGINFO_PACKAGE")
+ if(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OR CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS OR CPACK_DEBIAN_DEBUGINFO_PACKAGE)
# Generating binary list - Get type of all install files
file(GLOB_RECURSE FILE_PATHS_ LIST_DIRECTORIES false RELATIVE "${WDIR}" "${WDIR}/*")
# get file info so that we can determine if file is executable or not
unset(CPACK_DEB_INSTALL_FILES)
foreach(FILE_ IN LISTS FILE_PATHS_)
- execute_process(COMMAND env LC_ALL=C ${FILE_EXECUTABLE} "./${FILE_}"
+ execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${FILE_EXECUTABLE} "./${FILE_}"
WORKING_DIRECTORY "${WDIR}"
RESULT_VARIABLE FILE_RESULT_
OUTPUT_VARIABLE INSTALL_FILE_)
string(REGEX MATCH "(^.*):" _FILE_NAME "${_FILE}")
list(APPEND CPACK_DEB_SHARED_OBJECT_FILES "${CMAKE_MATCH_1}")
endif()
+ if(_FILE MATCHES "ELF.*not stripped")
+ string(REGEX MATCH "(^.*):" _FILE_NAME "${_FILE}")
+ list(APPEND CPACK_DEB_UNSTRIPPED_FILES "${CMAKE_MATCH_1}")
+ endif()
+ endforeach()
+ endif()
+
+ find_program(READELF_EXECUTABLE NAMES readelf)
+
+ if(CPACK_DEBIAN_DEBUGINFO_PACKAGE AND CPACK_DEB_UNSTRIPPED_FILES)
+ find_program(OBJCOPY_EXECUTABLE NAMES objcopy)
+
+ if(NOT OBJCOPY_EXECUTABLE)
+ message(FATAL_ERROR "debuginfo packages require the objcopy tool")
+ endif()
+ if(NOT READELF_EXECUTABLE)
+ message(FATAL_ERROR "debuginfo packages require the readelf tool")
+ endif()
+
+ file(RELATIVE_PATH _DBGSYM_ROOT "${CPACK_TEMPORARY_DIRECTORY}" "${DBGSYMDIR}")
+ foreach(_FILE IN LISTS CPACK_DEB_UNSTRIPPED_FILES)
+
+ # Get the file's Build ID
+ execute_process(COMMAND env LC_ALL=C ${READELF_EXECUTABLE} -n "${_FILE}"
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ OUTPUT_VARIABLE READELF_OUTPUT
+ RESULT_VARIABLE READELF_RESULT
+ ERROR_VARIABLE READELF_ERROR
+ OUTPUT_STRIP_TRAILING_WHITESPACE )
+ if(NOT READELF_RESULT EQUAL 0)
+ message(FATAL_ERROR "CPackDeb: readelf: '${READELF_ERROR}';\n"
+ "executed command: '${READELF_EXECUTABLE} -n ${_FILE}'")
+ endif()
+ if(READELF_OUTPUT MATCHES "Build ID: ([0-9a-zA-Z][0-9a-zA-Z])([0-9a-zA-Z]*)")
+ set(_BUILD_ID_START ${CMAKE_MATCH_1})
+ set(_BUILD_ID_REMAINING ${CMAKE_MATCH_2})
+ list(APPEND BUILD_IDS ${_BUILD_ID_START}${_BUILD_ID_REMAINING})
+ else()
+ message(FATAL_ERROR "Unable to determine Build ID for ${_FILE}")
+ endif()
+
+ # Split out the debug symbols from the binaries
+ set(_FILE_DBGSYM ${_DBGSYM_ROOT}/usr/lib/debug/.build-id/${_BUILD_ID_START}/${_BUILD_ID_REMAINING}.debug)
+ get_filename_component(_OUT_DIR "${_FILE_DBGSYM}" DIRECTORY)
+ file(MAKE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/${_OUT_DIR}")
+ execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}"
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ OUTPUT_VARIABLE OBJCOPY_OUTPUT
+ RESULT_VARIABLE OBJCOPY_RESULT
+ ERROR_VARIABLE OBJCOPY_ERROR
+ OUTPUT_STRIP_TRAILING_WHITESPACE )
+ if(NOT OBJCOPY_RESULT EQUAL 0)
+ message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
+ "executed command: '${OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'")
+ endif()
+ execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --strip-unneeded ${_FILE}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ OUTPUT_VARIABLE OBJCOPY_OUTPUT
+ RESULT_VARIABLE OBJCOPY_RESULT
+ ERROR_VARIABLE OBJCOPY_ERROR
+ OUTPUT_STRIP_TRAILING_WHITESPACE )
+ if(NOT OBJCOPY_RESULT EQUAL 0)
+ message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
+ "executed command: '${OBJCOPY_EXECUTABLE} --strip-debug ${_FILE}'")
+ endif()
+ execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ OUTPUT_VARIABLE OBJCOPY_OUTPUT
+ RESULT_VARIABLE OBJCOPY_RESULT
+ ERROR_VARIABLE OBJCOPY_ERROR
+ OUTPUT_STRIP_TRAILING_WHITESPACE )
+ if(NOT OBJCOPY_RESULT EQUAL 0)
+ message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n"
+ "executed command: '${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'")
+ endif()
endforeach()
endif()
if(SHLIBDEPS_EXECUTABLE)
# Check version of the dpkg-shlibdeps tool using CPackDEB method
- execute_process(COMMAND env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --version
+ execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --version
OUTPUT_VARIABLE _TMP_VERSION
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
file(MAKE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/DEBIAN")
# Add --ignore-missing-info if the tool supports it
- execute_process(COMMAND env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --help
+ execute_process(COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${SHLIBDEPS_EXECUTABLE} --help
OUTPUT_VARIABLE _TMP_HELP
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY "=")
endif()
- find_program(READELF_EXECUTABLE NAMES readelf)
-
if(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS)
if(READELF_EXECUTABLE)
foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
# <foo>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
set(CPACK_OUTPUT_FILE_NAME
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
+ set(CPACK_DBGSYM_OUTPUT_FILE_NAME
+ "${CPACK_DEBIAN_PACKAGE_NAME}-dbgsym_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.ddeb")
else()
if(NOT CPACK_DEBIAN_FILE_NAME MATCHES ".*\\.(deb|ipk)")
message(FATAL_ERROR "'${CPACK_DEBIAN_FILE_NAME}' is not a valid DEB package file name as it must end with '.deb' or '.ipk'!")
endif()
set(CPACK_OUTPUT_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}")
+ string(REGEX REPLACE "\.deb$" "-dbgsym.ddeb" CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}")
endif()
set(CPACK_TEMPORARY_PACKAGE_FILE_NAME "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_OUTPUT_FILE_NAME}")
get_filename_component(BINARY_DIR "${CPACK_OUTPUT_FILE_PATH}" DIRECTORY)
set(CPACK_OUTPUT_FILE_PATH "${BINARY_DIR}/${CPACK_OUTPUT_FILE_NAME}")
- endif() # else() back compatibility - don't change the name
+ else()
+ # back compatibility - don't change the name
+ string(REGEX REPLACE "\.deb$" "-dbgsym.ddeb" CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_OUTPUT_FILE_NAME}")
+ endif()
# Print out some debug information if we were asked for that
if(CPACK_DEBIAN_PACKAGE_DEBUG)
set(GEN_CPACK_DEBIAN_GENERATE_POSTINST "${CPACK_DEBIAN_GENERATE_POSTINST}" PARENT_SCOPE)
set(GEN_CPACK_DEBIAN_GENERATE_POSTRM "${CPACK_DEBIAN_GENERATE_POSTRM}" PARENT_SCOPE)
set(GEN_WDIR "${WDIR}" PARENT_SCOPE)
+
+ set(GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE "${CPACK_DEBIAN_DEBUGINFO_PACKAGE}" PARENT_SCOPE)
+ if(BUILD_IDS)
+ set(GEN_DBGSYMDIR "${DBGSYMDIR}" PARENT_SCOPE)
+ set(GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME "${CPACK_DBGSYM_OUTPUT_FILE_NAME}" PARENT_SCOPE)
+ string(REPLACE ";" " " BUILD_IDS "${BUILD_IDS}")
+ set(GEN_BUILD_IDS "${BUILD_IDS}" PARENT_SCOPE)
+ endif()
endfunction()
cpack_deb_prepare_package_vars()
+
+cmake_policy(POP)
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+if(NOT "${CPACK_EXTERNAL_REQUESTED_VERSIONS}" STREQUAL "")
+ unset(_found_major)
+
+ foreach(_req_version IN LISTS CPACK_EXTERNAL_REQUESTED_VERSIONS)
+ if(_req_version MATCHES "^([0-9]+)\\.([0-9]+)$")
+ set(_req_major "${CMAKE_MATCH_1}")
+ set(_req_minor "${CMAKE_MATCH_2}")
+
+ foreach(_known_version IN LISTS CPACK_EXTERNAL_KNOWN_VERSIONS)
+ string(REGEX MATCH
+ "^([0-9]+)\\.([0-9]+)$"
+ _known_version_dummy
+ "${_known_version}"
+ )
+
+ set(_known_major "${CMAKE_MATCH_1}")
+ set(_known_minor "${CMAKE_MATCH_2}")
+
+ if(_req_major EQUAL _known_major AND NOT _known_minor LESS _req_minor)
+ set(_found_major "${_known_major}")
+ set(_found_minor "${_known_minor}")
+ break()
+ endif()
+ endforeach()
+
+ if(DEFINED _found_major)
+ break()
+ endif()
+ endif()
+ endforeach()
+
+ if(DEFINED _found_major)
+ set(CPACK_EXTERNAL_SELECTED_MAJOR "${_found_major}")
+ set(CPACK_EXTERNAL_SELECTED_MINOR "${_found_minor}")
+ set(CPACK_EXTERNAL_SELECTED_VERSION "${_found_major}.${_found_minor}")
+ else()
+ message(FATAL_ERROR
+ "Could not find a suitable version in CPACK_EXTERNAL_REQUESTED_VERSIONS"
+ )
+ endif()
+else()
+ list(GET CPACK_EXTERNAL_KNOWN_VERSIONS 0 CPACK_EXTERNAL_SELECTED_VERSION)
+ string(REGEX MATCH
+ "^([0-9]+)\\.([0-9]+)$"
+ _dummy
+ "${CPACK_EXTERNAL_SELECTED_VERSION}"
+ )
+ set(CPACK_EXTERNAL_SELECTED_MAJOR "${CMAKE_MATCH_1}")
+ set(CPACK_EXTERNAL_SELECTED_MINOR "${CMAKE_MATCH_2}")
+endif()
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+if(CMAKE_BINARY_DIR)
+ message(FATAL_ERROR "CPackFreeBSD.cmake may only be used by CPack internally.")
+endif()
+
+if(NOT UNIX)
+ message(FATAL_ERROR "CPackFreeBSD.cmake may only be used under UNIX.")
+endif()
+
+
+###
+#
+# These bits are copied from the Debian packaging file; slightly modified.
+# They are used for filling in FreeBSD-packaging variables that can take
+# on values from elsewhere -- e.g. the package description may as well be
+# copied from Debian.
+#
+function(_cpack_freebsd_fallback_var OUTPUT_VAR_NAME)
+ set(FALLBACK_VAR_NAMES ${ARGN})
+
+ set(VALUE "${${OUTPUT_VAR_NAME}}")
+ if(VALUE)
+ return()
+ endif()
+
+ foreach(variable_name IN LISTS FALLBACK_VAR_NAMES)
+ if(${variable_name})
+ set(${OUTPUT_VAR_NAME} "${${variable_name}}" PARENT_SCOPE)
+ set(VALUE "${${variable_name}}")
+ break()
+ endif()
+ endforeach()
+ if(NOT VALUE)
+ message(WARNING "Variable ${OUTPUT_VAR_NAME} could not be given a fallback value from any variable ${FALLBACK_VAR_NAMES}.")
+ endif()
+endfunction()
+
+function(check_required_var VAR_NAME)
+ if(NOT ${VAR_NAME})
+ message(FATAL_ERROR "Variable ${VAR_NAME} is not set.")
+ endif()
+endfunction()
+
+set(_cpack_freebsd_fallback_origin "misc/bogus")
+
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_NAME"
+ "CPACK_PACKAGE_NAME"
+ "CMAKE_PROJECT_NAME"
+ )
+
+set(_cpack_freebsd_fallback_www "http://example.com/?pkg=${CPACK_FREEBSD_PACKAGE_NAME}")
+
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_COMMENT"
+ "CPACK_PACKAGE_DESCRIPTION_SUMMARY"
+ )
+
+# TODO: maybe read the PACKAGE_DESCRIPTION file for the longer
+# FreeBSD pkg-descr?
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_DESCRIPTION"
+ "CPACK_DEBIAN_PACKAGE_DESCRIPTION"
+ "CPACK_PACKAGE_DESCRIPTION_SUMMARY"
+ "PACKAGE_DESCRIPTION"
+ )
+
+# There's really only one homepage for a project, so
+# re-use the Debian setting if it's there.
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_WWW"
+ "CMAKE_PROJECT_HOMEPAGE_URL"
+ "CPACK_DEBIAN_PACKAGE_HOMEPAGE"
+ "_cpack_freebsd_fallback_www"
+ )
+
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_VERSION"
+ "CMAKE_PROJECT_VERSION"
+ "${CMAKE_PROJECT_NAME}_VERSION"
+ "PROJECT_VERSION"
+ "CPACK_PACKAGE_VERSION"
+ "CPACK_PACKAGE_VERSION"
+ )
+
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_MAINTAINER"
+ "CPACK_PACKAGE_CONTACT"
+ )
+
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_LICENSE"
+ "CPACK_RPM_PACKAGE_LICENSE"
+ )
+
+_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_ORIGIN"
+ "_cpack_freebsd_fallback_origin"
+ )
+
+if(NOT CPACK_FREEBSD_PACKAGE_CATEGORIES)
+ string(REGEX REPLACE "/.*" "" CPACK_FREEBSD_PACKAGE_CATEGORIES ${CPACK_FREEBSD_PACKAGE_ORIGIN})
+endif()
+
+check_required_var("CPACK_FREEBSD_PACKAGE_NAME")
+check_required_var("CPACK_FREEBSD_PACKAGE_ORIGIN")
+check_required_var("CPACK_FREEBSD_PACKAGE_VERSION")
+check_required_var("CPACK_FREEBSD_PACKAGE_MAINTAINER")
+check_required_var("CPACK_FREEBSD_PACKAGE_COMMENT")
+check_required_var("CPACK_FREEBSD_PACKAGE_DESCRIPTION")
+check_required_var("CPACK_FREEBSD_PACKAGE_WWW")
+check_required_var("CPACK_FREEBSD_PACKAGE_LICENSE")
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#[=======================================================================[.rst:
-CPackNuGet
-----------
-
-When build a NuGet package there is no direct way to control an output
-filename due a lack of the corresponding CLI option of NuGet, so there
-is no ``CPACK_NUGET_PACKAGE_FILENAME`` variable. To form the output filename
-NuGet uses the package name and the version according to its built-in rules.
-
-Also, be aware that including a top level directory
-(``CPACK_INCLUDE_TOPLEVEL_DIRECTORY``) is ignored by this generator.
-
-
-Variables specific to CPack NuGet generator
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-CPackNuGet may be used to create NuGet packages using :module:`CPack`.
-CPackNuGet is a :module:`CPack` generator thus it uses the ``CPACK_XXX``
-variables used by :module:`CPack`.
-
-CPackNuGet has specific features which are controlled by the specifics
-:code:`CPACK_NUGET_XXX` variables. In the "one per group" mode
-(see :variable:`CPACK_COMPONENTS_GROUPING`), ``<compName>`` placeholder
-in the variables below would contain a group name (uppercased and turned into
-a "C" identifier).
-
-List of CPackNuGet specific variables:
-
-.. variable:: CPACK_NUGET_COMPONENT_INSTALL
-
- Enable component packaging for CPackNuGet
-
- * Mandatory : NO
- * Default : OFF
-
-.. variable:: CPACK_NUGET_PACKAGE_NAME
- CPACK_NUGET_<compName>_PACKAGE_NAME
-
- The NUGET package name.
-
- * Mandatory : YES
- * Default : :variable:`CPACK_PACKAGE_NAME`
-
-.. variable:: CPACK_NUGET_PACKAGE_VERSION
- CPACK_NUGET_<compName>_PACKAGE_VERSION
-
- The NuGet package version.
-
- * Mandatory : YES
- * Default : :variable:`CPACK_PACKAGE_VERSION`
-
-.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION
- CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION
-
- A long description of the package for UI display.
-
- * Mandatory : YES
- * Default :
- - :variable:`CPACK_COMPONENT_<compName>_DESCRIPTION`,
- - ``CPACK_COMPONENT_GROUP_<groupName>_DESCRIPTION``,
- - :variable:`CPACK_PACKAGE_DESCRIPTION`
-
-.. variable:: CPACK_NUGET_PACKAGE_AUTHORS
- CPACK_NUGET_<compName>_PACKAGE_AUTHORS
-
- A comma-separated list of packages authors, matching the profile names
- on nuget.org_. These are displayed in the NuGet Gallery on
- nuget.org_ and are used to cross-reference packages by the same
- authors.
-
- * Mandatory : YES
- * Default : :variable:`CPACK_PACKAGE_VENDOR`
-
-.. variable:: CPACK_NUGET_PACKAGE_TITLE
- CPACK_NUGET_<compName>_PACKAGE_TITLE
-
- A human-friendly title of the package, typically used in UI displays
- as on nuget.org_ and the Package Manager in Visual Studio. If not
- specified, the package ID is used.
-
- * Mandatory : NO
- * Default :
- - :variable:`CPACK_COMPONENT_<compName>_DISPLAY_NAME`,
- - ``CPACK_COMPONENT_GROUP_<groupName>_DISPLAY_NAME``
-
-.. variable:: CPACK_NUGET_PACKAGE_OWNERS
- CPACK_NUGET_<compName>_PACKAGE_OWNERS
-
- A comma-separated list of the package creators using profile names
- on nuget.org_. This is often the same list as in authors,
- and is ignored when uploading the package to nuget.org_.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_HOMEPAGE_URL
- CPACK_NUGET_<compName>_PACKAGE_HOMEPAGE_URL
-
- A URL for the package's home page, often shown in UI displays as well
- as nuget.org_.
-
- * Mandatory : NO
- * Default : :variable:`CPACK_PACKAGE_HOMEPAGE_URL`
-
-.. variable:: CPACK_NUGET_PACKAGE_LICENSEURL
- CPACK_NUGET_<compName>_PACKAGE_LICENSEURL
-
- A URL for the package's license, often shown in UI displays as well
- as nuget.org_.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_ICONURL
- CPACK_NUGET_<compName>_PACKAGE_ICONURL
-
- A URL for a 64x64 image with transparency background to use as the
- icon for the package in UI display.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION_SUMMARY
- CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION_SUMMARY
-
- A short description of the package for UI display. If omitted, a
- truncated version of description is used.
-
- * Mandatory : NO
- * Default : :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
-
-.. variable:: CPACK_NUGET_PACKAGE_RELEASE_NOTES
- CPACK_NUGET_<compName>_PACKAGE_RELEASE_NOTES
-
- A description of the changes made in this release of the package,
- often used in UI like the Updates tab of the Visual Studio Package
- Manager in place of the package description.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_COPYRIGHT
- CPACK_NUGET_<compName>_PACKAGE_COPYRIGHT
-
- Copyright details for the package.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_TAGS
- CPACK_NUGET_<compName>_PACKAGE_TAGS
-
- A space-delimited list of tags and keywords that describe the
- package and aid discoverability of packages through search and
- filtering.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES
- CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES
-
- A list of package dependencies.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES_<dependency>_VERSION
- CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES_<dependency>_VERSION
-
- A `version specification`_ for the particular dependency, where
- ``<dependency>`` is an item of the dependency list (see above)
- transformed with ``MAKE_C_IDENTIFIER`` function of :command:`string`
- command.
-
- * Mandatory : NO
- * Default : -
-
-.. variable:: CPACK_NUGET_PACKAGE_DEBUG
-
- Enable debug messages while executing ``CPackNuGet.cmake``.
-
- * Mandatory : NO
- * Default : OFF
-
-
-.. _nuget.org: http://nuget.org
-.. _version specification: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
-
-.. NuGet spec docs https://docs.microsoft.com/en-us/nuget/reference/nuspec
-
-#]=======================================================================]
-
# Author: Alex Turbov
if(CMAKE_BINARY_DIR)
# NuGet will name it properly.
_cpack_nuget_debug("Rendering `${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec` file...")
configure_file(
- "${CMAKE_CURRENT_LIST_DIR}/CPack.NuGet.nuspec.in"
+ "${CMAKE_ROOT}/Modules/CPack.NuGet.nuspec.in"
"${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec"
@ONLY
)
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# CPackRPM
-# --------
-#
-# The built in (binary) CPack RPM generator (Unix only)
-#
-# Variables specific to CPack RPM generator
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# CPackRPM may be used to create RPM packages using :module:`CPack`.
-# CPackRPM is a :module:`CPack` generator thus it uses the ``CPACK_XXX``
-# variables used by :module:`CPack`.
-#
-# CPackRPM has specific features which are controlled by the specifics
-# :code:`CPACK_RPM_XXX` variables.
-#
-# :code:`CPACK_RPM_<COMPONENT>_XXXX` variables may be used in order to have
-# **component** specific values. Note however that ``<COMPONENT>`` refers to the
-# **grouping name** written in upper case. It may be either a component name or
-# a component GROUP name. Usually those variables correspond to RPM spec file
-# entities. One may find information about spec files here
-# http://www.rpm.org/wiki/Docs
-#
-# .. note::
-#
-# `<COMPONENT>` part of variables is preferred to be in upper case (for e.g. if
-# component is named `foo` then use `CPACK_RPM_FOO_XXXX` variable name format)
-# as is with other `CPACK_<COMPONENT>_XXXX` variables.
-# For the purposes of back compatibility (CMake/CPack version 3.5 and lower)
-# support for same cased component (e.g. `fOo` would be used as
-# `CPACK_RPM_fOo_XXXX`) is still supported for variables defined in older
-# versions of CMake/CPack but is not guaranteed for variables that
-# will be added in the future. For the sake of back compatibility same cased
-# component variables also override upper cased versions where both are
-# present.
-#
-# Here are some CPackRPM wiki resources that are here for historic reasons and
-# are no longer maintained but may still prove useful:
-#
-# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/Configuration
-# - https://gitlab.kitware.com/cmake/community/wikis/doc/cpack/PackageGenerators#rpm-unix-only
-#
-# List of CPackRPM specific variables:
-#
-# .. variable:: CPACK_RPM_COMPONENT_INSTALL
-#
-# Enable component packaging for CPackRPM
-#
-# * Mandatory : NO
-# * Default : OFF
-#
-# If enabled (ON) multiple packages are generated. By default a single package
-# containing files of all components is generated.
-#
-# .. variable:: CPACK_RPM_PACKAGE_SUMMARY
-# CPACK_RPM_<component>_PACKAGE_SUMMARY
-#
-# The RPM package summary.
-#
-# * Mandatory : YES
-# * Default : :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
-#
-# .. variable:: CPACK_RPM_PACKAGE_NAME
-# CPACK_RPM_<component>_PACKAGE_NAME
-#
-# The RPM package name.
-#
-# * Mandatory : YES
-# * Default : :variable:`CPACK_PACKAGE_NAME`
-#
-# .. variable:: CPACK_RPM_FILE_NAME
-# CPACK_RPM_<component>_FILE_NAME
-#
-# Package file name.
-#
-# * Mandatory : YES
-# * Default : ``<CPACK_PACKAGE_FILE_NAME>[-<component>].rpm`` with spaces
-# replaced by '-'
-#
-# This may be set to ``RPM-DEFAULT`` to allow rpmbuild tool to generate package
-# file name by itself.
-# Alternatively provided package file name must end with ``.rpm`` suffix.
-#
-# .. note::
-#
-# By using user provided spec file, rpm macro extensions such as for
-# generating debuginfo packages or by simply using multiple components more
-# than one rpm file may be generated, either from a single spec file or from
-# multiple spec files (each component execution produces it's own spec file).
-# In such cases duplicate file names may occur as a result of this variable
-# setting or spec file content structure. Duplicate files get overwritten
-# and it is up to the packager to set the variables in a manner that will
-# prevent such errors.
-#
-# .. variable:: CPACK_RPM_MAIN_COMPONENT
-#
-# Main component that is packaged without component suffix.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# This variable can be set to any component or group name so that component or
-# group rpm package is generated without component suffix in filename and
-# package name.
-#
-# .. variable:: CPACK_RPM_PACKAGE_EPOCH
-#
-# The RPM package epoch
-#
-# * Mandatory : No
-# * Default : -
-#
-# Optional number that should be incremented when changing versioning schemas
-# or fixing mistakes in the version numbers of older packages.
-#
-# .. variable:: CPACK_RPM_PACKAGE_VERSION
-#
-# The RPM package version.
-#
-# * Mandatory : YES
-# * Default : :variable:`CPACK_PACKAGE_VERSION`
-#
-# .. variable:: CPACK_RPM_PACKAGE_ARCHITECTURE
-# CPACK_RPM_<component>_PACKAGE_ARCHITECTURE
-#
-# The RPM package architecture.
-#
-# * Mandatory : YES
-# * Default : Native architecture output by ``uname -m``
-#
-# This may be set to ``noarch`` if you know you are building a noarch package.
-#
-# .. variable:: CPACK_RPM_PACKAGE_RELEASE
-#
-# The RPM package release.
-#
-# * Mandatory : YES
-# * Default : 1
-#
-# This is the numbering of the RPM package itself, i.e. the version of the
-# packaging and not the version of the content (see
-# :variable:`CPACK_RPM_PACKAGE_VERSION`). One may change the default value if
-# the previous packaging was buggy and/or you want to put here a fancy Linux
-# distro specific numbering.
-#
-# .. note::
-#
-# This is the string that goes into the RPM ``Release:`` field. Some distros
-# (e.g. Fedora, CentOS) require ``1%{?dist}`` format and not just a number.
-# ``%{?dist}`` part can be added by setting :variable:`CPACK_RPM_PACKAGE_RELEASE_DIST`.
-#
-# .. variable:: CPACK_RPM_PACKAGE_RELEASE_DIST
-#
-# The dist tag that is added RPM ``Release:`` field.
-#
-# * Mandatory : NO
-# * Default : OFF
-#
-# This is the reported ``%{dist}`` tag from the current distribution or empty
-# ``%{dist}`` if RPM macro is not set. If this variable is set then RPM
-# ``Release:`` field value is set to ``${CPACK_RPM_PACKAGE_RELEASE}%{?dist}``.
-#
-# .. variable:: CPACK_RPM_PACKAGE_LICENSE
-#
-# The RPM package license policy.
-#
-# * Mandatory : YES
-# * Default : "unknown"
-#
-# .. variable:: CPACK_RPM_PACKAGE_GROUP
-# CPACK_RPM_<component>_PACKAGE_GROUP
-#
-# The RPM package group.
-#
-# * Mandatory : YES
-# * Default : "unknown"
-#
-# .. variable:: CPACK_RPM_PACKAGE_VENDOR
-#
-# The RPM package vendor.
-#
-# * Mandatory : YES
-# * Default : CPACK_PACKAGE_VENDOR if set or "unknown"
-#
-# .. variable:: CPACK_RPM_PACKAGE_URL
-# CPACK_RPM_<component>_PACKAGE_URL
-#
-# The projects URL.
-#
-# * Mandatory : NO
-# * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
-#
-# .. variable:: CPACK_RPM_PACKAGE_DESCRIPTION
-# CPACK_RPM_<component>_PACKAGE_DESCRIPTION
-#
-# RPM package description.
-#
-# * Mandatory : YES
-# * Default : :variable:`CPACK_COMPONENT_<compName>_DESCRIPTION` (component
-# based installers only) if set, :variable:`CPACK_PACKAGE_DESCRIPTION_FILE`
-# if set or "no package description available"
-#
-# .. variable:: CPACK_RPM_COMPRESSION_TYPE
-#
-# RPM compression type.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to override RPM compression type to be used to build the
-# RPM. For example some Linux distribution now default to lzma or xz
-# compression whereas older cannot use such RPM. Using this one can enforce
-# compression type to be used.
-#
-# Possible values are:
-#
-# - lzma
-# - xz
-# - bzip2
-# - gzip
-#
-# .. variable:: CPACK_RPM_PACKAGE_AUTOREQ
-# CPACK_RPM_<component>_PACKAGE_AUTOREQ
-#
-# RPM spec autoreq field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to enable (1, yes) or disable (0, no) automatic shared libraries
-# dependency detection. Dependencies are added to requires list.
-#
-# .. note::
-#
-# By default automatic dependency detection is enabled by rpm generator.
-#
-# .. variable:: CPACK_RPM_PACKAGE_AUTOPROV
-# CPACK_RPM_<component>_PACKAGE_AUTOPROV
-#
-# RPM spec autoprov field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to enable (1, yes) or disable (0, no) automatic listing of shared
-# libraries that are provided by the package. Shared libraries are added to
-# provides list.
-#
-# .. note::
-#
-# By default automatic provides detection is enabled by rpm generator.
-#
-# .. variable:: CPACK_RPM_PACKAGE_AUTOREQPROV
-# CPACK_RPM_<component>_PACKAGE_AUTOREQPROV
-#
-# RPM spec autoreqprov field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# Variable enables/disables autoreq and autoprov at the same time.
-# See :variable:`CPACK_RPM_PACKAGE_AUTOREQ` and :variable:`CPACK_RPM_PACKAGE_AUTOPROV`
-# for more details.
-#
-# .. note::
-#
-# By default automatic detection feature is enabled by rpm.
-#
-# .. variable:: CPACK_RPM_PACKAGE_REQUIRES
-# CPACK_RPM_<component>_PACKAGE_REQUIRES
-#
-# RPM spec requires field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set RPM dependencies (requires). Note that you must enclose
-# the complete requires string between quotes, for example::
-#
-# set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.5.0, cmake >= 2.8")
-#
-# The required package list of an RPM file could be printed with::
-#
-# rpm -qp --requires file.rpm
-#
-# .. variable:: CPACK_RPM_PACKAGE_CONFLICTS
-# CPACK_RPM_<component>_PACKAGE_CONFLICTS
-#
-# RPM spec conflicts field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set negative RPM dependencies (conflicts). Note that you must
-# enclose the complete requires string between quotes, for example::
-#
-# set(CPACK_RPM_PACKAGE_CONFLICTS "libxml2")
-#
-# The conflicting package list of an RPM file could be printed with::
-#
-# rpm -qp --conflicts file.rpm
-#
-# .. variable:: CPACK_RPM_PACKAGE_REQUIRES_PRE
-# CPACK_RPM_<component>_PACKAGE_REQUIRES_PRE
-#
-# RPM spec requires(pre) field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set RPM preinstall dependencies (requires(pre)). Note that
-# you must enclose the complete requires string between quotes, for example::
-#
-# set(CPACK_RPM_PACKAGE_REQUIRES_PRE "shadow-utils, initscripts")
-#
-# .. variable:: CPACK_RPM_PACKAGE_REQUIRES_POST
-# CPACK_RPM_<component>_PACKAGE_REQUIRES_POST
-#
-# RPM spec requires(post) field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set RPM postinstall dependencies (requires(post)). Note that
-# you must enclose the complete requires string between quotes, for example::
-#
-# set(CPACK_RPM_PACKAGE_REQUIRES_POST "shadow-utils, initscripts")
-#
-# .. variable:: CPACK_RPM_PACKAGE_REQUIRES_POSTUN
-# CPACK_RPM_<component>_PACKAGE_REQUIRES_POSTUN
-#
-# RPM spec requires(postun) field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set RPM postuninstall dependencies (requires(postun)). Note
-# that you must enclose the complete requires string between quotes, for
-# example::
-#
-# set(CPACK_RPM_PACKAGE_REQUIRES_POSTUN "shadow-utils, initscripts")
-#
-# .. variable:: CPACK_RPM_PACKAGE_REQUIRES_PREUN
-# CPACK_RPM_<component>_PACKAGE_REQUIRES_PREUN
-#
-# RPM spec requires(preun) field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set RPM preuninstall dependencies (requires(preun)). Note that
-# you must enclose the complete requires string between quotes, for example::
-#
-# set(CPACK_RPM_PACKAGE_REQUIRES_PREUN "shadow-utils, initscripts")
-#
-# .. variable:: CPACK_RPM_PACKAGE_SUGGESTS
-# CPACK_RPM_<component>_PACKAGE_SUGGESTS
-#
-# RPM spec suggest field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set weak RPM dependencies (suggests). Note that you must
-# enclose the complete requires string between quotes.
-#
-# .. variable:: CPACK_RPM_PACKAGE_PROVIDES
-# CPACK_RPM_<component>_PACKAGE_PROVIDES
-#
-# RPM spec provides field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set RPM dependencies (provides). The provided package list
-# of an RPM file could be printed with::
-#
-# rpm -qp --provides file.rpm
-#
-# .. variable:: CPACK_RPM_PACKAGE_OBSOLETES
-# CPACK_RPM_<component>_PACKAGE_OBSOLETES
-#
-# RPM spec obsoletes field.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set RPM packages that are obsoleted by this one.
-#
-# .. variable:: CPACK_RPM_PACKAGE_RELOCATABLE
-#
-# build a relocatable RPM.
-#
-# * Mandatory : NO
-# * Default : CPACK_PACKAGE_RELOCATABLE
-#
-# If this variable is set to TRUE or ON CPackRPM will try
-# to build a relocatable RPM package. A relocatable RPM may
-# be installed using::
-#
-# rpm --prefix or --relocate
-#
-# in order to install it at an alternate place see rpm(8). Note that
-# currently this may fail if :variable:`CPACK_SET_DESTDIR` is set to ``ON``. If
-# :variable:`CPACK_SET_DESTDIR` is set then you will get a warning message but
-# if there is file installed with absolute path you'll get unexpected behavior.
-#
-# .. variable:: CPACK_RPM_SPEC_INSTALL_POST
-#
-# Deprecated - use :variable:`CPACK_RPM_SPEC_MORE_DEFINE` instead.
-#
-# * Mandatory : NO
-# * Default : -
-# * Deprecated: YES
-#
-# May be used to override the ``__spec_install_post`` section within the
-# generated spec file. This affects the install step during package creation,
-# not during package installation. For adding operations to be performed
-# during package installation, use
-# :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE` instead.
-#
-# .. variable:: CPACK_RPM_SPEC_MORE_DEFINE
-#
-# RPM extended spec definitions lines.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to add any ``%define`` lines to the generated spec file. An
-# example of its use is to prevent stripping of executables (but note that
-# this may also disable other default post install processing)::
-#
-# set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true")
-#
-# .. variable:: CPACK_RPM_PACKAGE_DEBUG
-#
-# Toggle CPackRPM debug output.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be set when invoking cpack in order to trace debug information
-# during CPack RPM run. For example you may launch CPack like this::
-#
-# cpack -D CPACK_RPM_PACKAGE_DEBUG=1 -G RPM
-#
-# .. variable:: CPACK_RPM_USER_BINARY_SPECFILE
-# CPACK_RPM_<componentName>_USER_BINARY_SPECFILE
-#
-# A user provided spec file.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be set by the user in order to specify a USER binary spec file
-# to be used by CPackRPM instead of generating the file.
-# The specified file will be processed by configure_file( @ONLY).
-#
-# .. variable:: CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE
-#
-# Spec file template.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# If set CPack will generate a template for USER specified binary
-# spec file and stop with an error. For example launch CPack like this::
-#
-# cpack -D CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE=1 -G RPM
-#
-# The user may then use this file in order to hand-craft is own
-# binary spec file which may be used with
-# :variable:`CPACK_RPM_USER_BINARY_SPECFILE`.
-#
-# .. variable:: CPACK_RPM_PRE_INSTALL_SCRIPT_FILE
-# CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE
-#
-# Path to file containing pre (un)install script.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to embed a pre (un)installation script in the spec file.
-# The referred script file (or both) will be read and directly
-# put after the ``%pre`` or ``%preun`` section
-# If :variable:`CPACK_RPM_COMPONENT_INSTALL` is set to ON the (un)install
-# script for each component can be overridden with
-# ``CPACK_RPM_<COMPONENT>_PRE_INSTALL_SCRIPT_FILE`` and
-# ``CPACK_RPM_<COMPONENT>_PRE_UNINSTALL_SCRIPT_FILE``.
-# One may verify which scriptlet has been included with::
-#
-# rpm -qp --scripts package.rpm
-#
-# .. variable:: CPACK_RPM_POST_INSTALL_SCRIPT_FILE
-# CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE
-#
-# Path to file containing post (un)install script.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to embed a post (un)installation script in the spec file.
-# The referred script file (or both) will be read and directly
-# put after the ``%post`` or ``%postun`` section.
-# If :variable:`CPACK_RPM_COMPONENT_INSTALL` is set to ON the (un)install
-# script for each component can be overridden with
-# ``CPACK_RPM_<COMPONENT>_POST_INSTALL_SCRIPT_FILE`` and
-# ``CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE``.
-# One may verify which scriptlet has been included with::
-#
-# rpm -qp --scripts package.rpm
-#
-# .. variable:: CPACK_RPM_USER_FILELIST
-# CPACK_RPM_<COMPONENT>_USER_FILELIST
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to explicitly specify ``%(<directive>)`` file line
-# in the spec file. Like ``%config(noreplace)`` or any other directive
-# that be found in the ``%files`` section. You can have multiple directives
-# per line, as in ``%attr(600,root,root) %config(noreplace)``. Since
-# CPackRPM is generating the list of files (and directories) the user
-# specified files of the ``CPACK_RPM_<COMPONENT>_USER_FILELIST`` list will
-# be removed from the generated list. If referring to directories do
-# not add a trailing slash.
-#
-# .. variable:: CPACK_RPM_CHANGELOG_FILE
-#
-# RPM changelog file.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to embed a changelog in the spec file.
-# The referred file will be read and directly put after the ``%changelog``
-# section.
-#
-# .. variable:: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST
-#
-# list of path to be excluded.
-#
-# * Mandatory : NO
-# * Default : /etc /etc/init.d /usr /usr/bin /usr/include /usr/lib
-# /usr/libx32 /usr/lib64 /usr/share /usr/share/aclocal
-# /usr/share/doc
-#
-# May be used to exclude path (directories or files) from the auto-generated
-# list of paths discovered by CPack RPM. The default value contains a
-# reasonable set of values if the variable is not defined by the user. If the
-# variable is defined by the user then CPackRPM will NOT any of the default
-# path. If you want to add some path to the default list then you can use
-# :variable:`CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION` variable.
-#
-# .. variable:: CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
-#
-# additional list of path to be excluded.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to add more exclude path (directories or files) from the initial
-# default list of excluded paths. See
-# :variable:`CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST`.
-#
-# .. variable:: CPACK_RPM_RELOCATION_PATHS
-#
-# Packages relocation paths list.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to specify more than one relocation path per relocatable RPM.
-# Variable contains a list of relocation paths that if relative are prefixed
-# by the value of :variable:`CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX` or by the
-# value of :variable:`CPACK_PACKAGING_INSTALL_PREFIX` if the component version
-# is not provided.
-# Variable is not component based as its content can be used to set a different
-# path prefix for e.g. binary dir and documentation dir at the same time.
-# Only prefixes that are required by a certain component are added to that
-# component - component must contain at least one file/directory/symbolic link
-# with :variable:`CPACK_RPM_RELOCATION_PATHS` prefix for a certain relocation
-# path to be added. Package will not contain any relocation paths if there are
-# no files/directories/symbolic links on any of the provided prefix locations.
-# Packages that either do not contain any relocation paths or contain
-# files/directories/symbolic links that are outside relocation paths print
-# out an ``AUTHOR_WARNING`` that RPM will be partially relocatable.
-#
-# .. variable:: CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
-#
-# Per component relocation path install prefix.
-#
-# * Mandatory : NO
-# * Default : CPACK_PACKAGING_INSTALL_PREFIX
-#
-# May be used to set per component :variable:`CPACK_PACKAGING_INSTALL_PREFIX`
-# for relocatable RPM packages.
-#
-# .. variable:: CPACK_RPM_NO_INSTALL_PREFIX_RELOCATION
-# CPACK_RPM_NO_<COMPONENT>_INSTALL_PREFIX_RELOCATION
-#
-# Removal of default install prefix from relocation paths list.
-#
-# * Mandatory : NO
-# * Default : CPACK_PACKAGING_INSTALL_PREFIX or CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
-# are treated as one of relocation paths
-#
-# May be used to remove CPACK_PACKAGING_INSTALL_PREFIX and CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
-# from relocatable RPM prefix paths.
-#
-# .. variable:: CPACK_RPM_ADDITIONAL_MAN_DIRS
-#
-# * Mandatory : NO
-# * Default : -
-#
-# May be used to set additional man dirs that could potentially be compressed
-# by brp-compress RPM macro. Variable content must be a list of regular
-# expressions that point to directories containing man files or to man files
-# directly. Note that in order to compress man pages a path must also be
-# present in brp-compress RPM script and that brp-compress script must be
-# added to RPM configuration by the operating system.
-#
-# Regular expressions that are added by default were taken from brp-compress
-# RPM macro:
-#
-# - /usr/man/man.*
-# - /usr/man/.*/man.*
-# - /usr/info.*
-# - /usr/share/man/man.*
-# - /usr/share/man/.*/man.*
-# - /usr/share/info.*
-# - /usr/kerberos/man.*
-# - /usr/X11R6/man/man.*
-# - /usr/lib/perl5/man/man.*
-# - /usr/share/doc/.*/man/man.*
-# - /usr/lib/.*/man/man.*
-#
-# .. variable:: CPACK_RPM_DEFAULT_USER
-# CPACK_RPM_<compName>_DEFAULT_USER
-#
-# default user ownership of RPM content
-#
-# * Mandatory : NO
-# * Default : root
-#
-# Value should be user name and not UID.
-# Note that <compName> must be in upper-case.
-#
-# .. variable:: CPACK_RPM_DEFAULT_GROUP
-# CPACK_RPM_<compName>_DEFAULT_GROUP
-#
-# default group ownership of RPM content
-#
-# * Mandatory : NO
-# * Default : root
-#
-# Value should be group name and not GID.
-# Note that <compName> must be in upper-case.
-#
-# .. variable:: CPACK_RPM_DEFAULT_FILE_PERMISSIONS
-# CPACK_RPM_<compName>_DEFAULT_FILE_PERMISSIONS
-#
-# default permissions used for packaged files
-#
-# * Mandatory : NO
-# * Default : - (system default)
-#
-# Accepted values are lists with ``PERMISSIONS``. Valid permissions
-# are:
-#
-# - OWNER_READ
-# - OWNER_WRITE
-# - OWNER_EXECUTE
-# - GROUP_READ
-# - GROUP_WRITE
-# - GROUP_EXECUTE
-# - WORLD_READ
-# - WORLD_WRITE
-# - WORLD_EXECUTE
-#
-# Note that <compName> must be in upper-case.
-#
-# .. variable:: CPACK_RPM_DEFAULT_DIR_PERMISSIONS
-# CPACK_RPM_<compName>_DEFAULT_DIR_PERMISSIONS
-#
-# default permissions used for packaged directories
-#
-# * Mandatory : NO
-# * Default : - (system default)
-#
-# Accepted values are lists with PERMISSIONS. Valid permissions
-# are the same as for :variable:`CPACK_RPM_DEFAULT_FILE_PERMISSIONS`.
-# Note that <compName> must be in upper-case.
-#
-# .. variable:: CPACK_RPM_INSTALL_WITH_EXEC
-#
-# force execute permissions on programs and shared libraries
-#
-# * Mandatory : NO
-# * Default : - (system default)
-#
-# Force set owner, group and world execute permissions on programs and shared
-# libraries. This can be used for creating valid rpm packages on systems such
-# as Debian where shared libraries do not have execute permissions set.
-#
-# .. note::
-#
-# Programs and shared libraries without execute permissions are ignored during
-# separation of debug symbols from the binary for debuginfo packages.
-#
-# Packaging of Symbolic Links
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# CPackRPM supports packaging of symbolic links::
-#
-# execute_process(COMMAND ${CMAKE_COMMAND}
-# -E create_symlink <relative_path_location> <symlink_name>)
-# install(FILES ${CMAKE_CURRENT_BINARY_DIR}/<symlink_name>
-# DESTINATION <symlink_location> COMPONENT libraries)
-#
-# Symbolic links will be optimized (paths will be shortened if possible)
-# before being added to the package or if multiple relocation paths are
-# detected, a post install symlink relocation script will be generated.
-#
-# Symbolic links may point to locations that are not packaged by the same
-# package (either a different component or even not packaged at all) but
-# those locations will be treated as if they were a part of the package
-# while determining if symlink should be either created or present in a
-# post install script - depending on relocation paths.
-#
-# Symbolic links that point to locations outside packaging path produce a
-# warning and are treated as non relocatable permanent symbolic links.
-#
-# Currently there are a few limitations though:
-#
-# * For component based packaging component interdependency is not checked
-# when processing symbolic links. Symbolic links pointing to content of
-# a different component are treated the same way as if pointing to location
-# that will not be packaged.
-#
-# * Symbolic links pointing to a location through one or more intermediate
-# symbolic links will not be handled differently - if the intermediate
-# symbolic link(s) is also on a relocatable path, relocating it during
-# package installation may cause initial symbolic link to point to an
-# invalid location.
-#
-# Packaging of debug information
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# Debuginfo packages contain debug symbols and sources for debugging packaged
-# binaries.
-#
-# Debuginfo RPM packaging has it's own set of variables:
-#
-# .. variable:: CPACK_RPM_DEBUGINFO_PACKAGE
-# CPACK_RPM_<component>_DEBUGINFO_PACKAGE
-#
-# Enable generation of debuginfo RPM package(s).
-#
-# * Mandatory : NO
-# * Default : OFF
-#
-# .. note::
-#
-# Binaries must contain debug symbols before packaging so use either ``Debug``
-# or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value.
-#
-# .. note::
-#
-# Packages generated from packages without binary files, with binary files but
-# without execute permissions or without debug symbols will cause packaging
-# termination.
-#
-# .. variable:: CPACK_BUILD_SOURCE_DIRS
-#
-# Provides locations of root directories of source files from which binaries
-# were built.
-#
-# * Mandatory : YES if :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is set
-# * Default : -
-#
-# .. note::
-#
-# For CMake project :variable:`CPACK_BUILD_SOURCE_DIRS` is set by default to
-# point to :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR` paths.
-#
-# .. note::
-#
-# Sources with path prefixes that do not fall under any location provided with
-# :variable:`CPACK_BUILD_SOURCE_DIRS` will not be present in debuginfo package.
-#
-# .. variable:: CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX
-# CPACK_RPM_<component>_BUILD_SOURCE_DIRS_PREFIX
-#
-# Prefix of location where sources will be placed during package installation.
-#
-# * Mandatory : YES if :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is set
-# * Default : "/usr/src/debug/<CPACK_PACKAGE_FILE_NAME>" and
-# for component packaging "/usr/src/debug/<CPACK_PACKAGE_FILE_NAME>-<component>"
-#
-# .. note::
-#
-# Each source path prefix is additionally suffixed by ``src_<index>`` where
-# index is index of the path used from :variable:`CPACK_BUILD_SOURCE_DIRS`
-# variable. This produces ``<CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX>/src_<index>``
-# replacement path.
-# Limitation is that replaced path part must be shorter or of equal
-# length than the length of its replacement. If that is not the case either
-# :variable:`CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX` variable has to be set to
-# a shorter path or source directories must be placed on a longer path.
-#
-# .. variable:: CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS
-#
-# Directories containing sources that should be excluded from debuginfo packages.
-#
-# * Mandatory : NO
-# * Default : "/usr /usr/src /usr/src/debug"
-#
-# Listed paths are owned by other RPM packages and should therefore not be
-# deleted on debuginfo package uninstallation.
-#
-# .. variable:: CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS_ADDITION
-#
-# Paths that should be appended to :variable:`CPACK_RPM_DEBUGINFO_EXCLUDE_DIRS`
-# for exclusion.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# .. variable:: CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE
-#
-# Create a single debuginfo package even if components packaging is set.
-#
-# * Mandatory : NO
-# * Default : OFF
-#
-# When this variable is enabled it produces a single debuginfo package even if
-# component packaging is enabled.
-#
-# When using this feature in combination with components packaging and there is
-# more than one component this variable requires :variable:`CPACK_RPM_MAIN_COMPONENT`
-# to be set.
-#
-# .. note::
-#
-# If none of the :variable:`CPACK_RPM_<component>_DEBUGINFO_PACKAGE` variables
-# 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_<component>_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)
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# SRPM packaging is enabled by setting :variable:`CPACK_RPM_PACKAGE_SOURCES`
-# variable while usually using :variable:`CPACK_INSTALLED_DIRECTORIES` variable
-# to provide directory containing CMakeLists.txt and source files.
-#
-# For CMake projects SRPM package would be produced by executing::
-#
-# cpack -G RPM --config ./CPackSourceConfig.cmake
-#
-# .. note::
-#
-# Produced SRPM package is expected to be built with :manual:`cmake(1)` executable
-# and packaged with :manual:`cpack(1)` executable so CMakeLists.txt has to be
-# located in root source directory and must be able to generate binary rpm
-# packages by executing ``cpack -G`` command. The two executables as well as
-# rpmbuild must also be present when generating binary rpm packages from the
-# produced SRPM package.
-#
-# Once the SRPM package is generated it can be used to generate binary packages
-# by creating a directory structure for rpm generation and executing rpmbuild
-# tool::
-#
-# mkdir -p build_dir/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
-# rpmbuild --define "_topdir <path_to_build_dir>" --rebuild <SRPM_file_name>
-#
-# Generated packages will be located in build_dir/RPMS directory or its sub
-# directories.
-#
-# .. note::
-#
-# SRPM package internally uses CPack/RPM generator to generate binary packages
-# so CMakeScripts.txt can decide during the SRPM to binary rpm generation step
-# what content the package(s) should have as well as how they should be packaged
-# (monolithic or components). CMake can decide this for e.g. by reading environment
-# variables set by the package manager before starting the process of generating
-# binary rpm packages. This way a single SRPM package can be used to produce
-# different binary rpm packages on different platforms depending on the platform's
-# packaging rules.
-#
-# Source RPM packaging has it's own set of variables:
-#
-# .. variable:: CPACK_RPM_PACKAGE_SOURCES
-#
-# Should the content be packaged as a source rpm (default is binary rpm).
-#
-# * Mandatory : NO
-# * Default : OFF
-#
-# .. note::
-#
-# For cmake projects :variable:`CPACK_RPM_PACKAGE_SOURCES` variable is set
-# to ``OFF`` in CPackConfig.cmake and ``ON`` in CPackSourceConfig.cmake
-# generated files.
-#
-# .. variable:: CPACK_RPM_SOURCE_PKG_BUILD_PARAMS
-#
-# Additional command-line parameters provided to :manual:`cmake(1)` executable.
-#
-# * Mandatory : NO
-# * Default : -
-#
-# .. variable:: CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX
-#
-# Packaging install prefix that would be provided in :variable:`CPACK_PACKAGING_INSTALL_PREFIX`
-# variable for producing binary RPM packages.
-#
-# * 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.
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
function(get_file_permissions FILE RETURN_VAR)
execute_process(COMMAND ls -l ${FILE}
OUTPUT_VARIABLE permissions_
list(LENGTH SYMLINK_RELOCATIONS SYMLINK_RELOCATIONS_COUNT)
list(LENGTH POINT_RELOCATIONS POINT_RELOCATIONS_COUNT)
else()
- # location pointed to is ouside WDR so it should be treated as a permanent symlink
+ # location pointed to is outside WDR so it should be treated as a permanent symlink
set(SYMLINK_POINT_WD_ "${SYMLINK_POINT_}")
unset(SYMLINK_RELOCATIONS)
%build
mkdir cpack_rpm_build_dir
cd cpack_rpm_build_dir
-cmake ${CPACK_RPM_SOURCE_PKG_BUILD_PARAMS} -DCPACK_PACKAGING_INSTALL_PREFIX=${CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX} ../${CPACK_PACKAGE_FILE_NAME}
+'${CMAKE_COMMAND}' ${CPACK_RPM_SOURCE_PKG_BUILD_PARAMS} -DCPACK_PACKAGING_INSTALL_PREFIX=${CPACK_RPM_SOURCE_PKG_PACKAGING_INSTALL_PREFIX} ../${CPACK_PACKAGE_FILE_NAME}
make %{?_smp_mflags}" # %{?_smp_mflags} -> -j option
)
set(TMP_RPM_INSTALL
endfunction()
cpack_rpm_generate_package()
+
+cmake_policy(POP)
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+if(NOT CPACK_WIX_ROOT)
+ string(REPLACE "\\" "/" CPACK_WIX_ROOT "$ENV{WIX}")
+endif()
+
+find_program(CPACK_WIX_CANDLE_EXECUTABLE candle
+ PATHS "${CPACK_WIX_ROOT}" PATH_SUFFIXES "bin")
+
+if(NOT CPACK_WIX_CANDLE_EXECUTABLE)
+ message(FATAL_ERROR "Could not find the WiX candle executable.")
+endif()
+
+find_program(CPACK_WIX_LIGHT_EXECUTABLE light
+ PATHS "${CPACK_WIX_ROOT}" PATH_SUFFIXES "bin")
+
+if(NOT CPACK_WIX_LIGHT_EXECUTABLE)
+ message(FATAL_ERROR "Could not find the WiX light executable.")
+endif()
set(CPACK_ZIP_NEED_QUOTES FALSE)
endif()
endif()
-
@CPACK_NSIS_DELETE_ICONS@
@CPACK_NSIS_DELETE_ICONS_EXTRA@
- ;Delete empty start menu parent diretories
+ ;Delete empty start menu parent directories
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
startMenuDeleteLoop:
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
@CPACK_NSIS_DELETE_ICONS_EXTRA@
- ;Delete empty start menu parent diretories
+ ;Delete empty start menu parent directories
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
secondStartMenuDeleteLoop:
endif()
if(NOT CMAKE_${lang}_COMPILER_TARGET)
set(CMAKE_${lang}_COMPILER_TARGET "${_ANDROID_ABI_CLANG_TARGET}")
+ list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}")
endif()
endmacro()
return()
endif()
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
# If the user provided CMAKE_SYSROOT for us, extract information from it.
set(_ANDROID_SYSROOT_NDK "")
set(_ANDROID_SYSROOT_API "")
# Report the chosen architecture.
message(STATUS "Android: Targeting API '${CMAKE_SYSTEM_VERSION}' with architecture '${CMAKE_ANDROID_ARCH}', ABI '${CMAKE_ANDROID_ARCH_ABI}', and processor '${CMAKE_SYSTEM_PROCESSOR}'")
+
+cmake_policy(POP)
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names")
set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "-bundle -Wl,-headerpad_max_install_names")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 12.0)
set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
endif()
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+#Setup Green Hills MULTI specific compilation information
-#Setup Greenhills MULTI specific compilation information
-
-if (NOT GHS_INT_DIRECTORY)
- #Assume the C:/ghs/int#### directory that is latest is preferred
- set(GHS_EXPECTED_ROOT "C:/ghs")
- if (EXISTS ${GHS_EXPECTED_ROOT})
- FILE(GLOB GHS_CANDIDATE_INT_DIRS RELATIVE
- ${GHS_EXPECTED_ROOT} ${GHS_EXPECTED_ROOT}/*)
- string(REGEX MATCHALL "int[0-9][0-9][0-9][0-9a-z]" GHS_CANDIDATE_INT_DIRS
- ${GHS_CANDIDATE_INT_DIRS})
- if (GHS_CANDIDATE_INT_DIRS)
- list(SORT GHS_CANDIDATE_INT_DIRS)
- list(GET GHS_CANDIDATE_INT_DIRS -1 GHS_INT_DIRECTORY)
- string(CONCAT GHS_INT_DIRECTORY ${GHS_EXPECTED_ROOT} "/"
- ${GHS_INT_DIRECTORY})
+set(GHS_OS_ROOT "C:/ghs" CACHE PATH "GHS platform OS search root directory")
+mark_as_advanced(GHS_OS_ROOT)
+
+set(GHS_OS_DIR "NOTFOUND" CACHE PATH "GHS platform OS directory")
+mark_as_advanced(GHS_OS_DIR)
+
+#set GHS_OS_DIR if not set by user
+if ( NOT GHS_OS_DIR )
+ if (EXISTS ${GHS_OS_ROOT})
+
+ #get all directories in root directory
+ FILE(GLOB GHS_CANDIDATE_OS_DIRS
+ LIST_DIRECTORIES true RELATIVE ${GHS_OS_ROOT} ${GHS_OS_ROOT}/*)
+ FILE(GLOB GHS_CANDIDATE_OS_FILES
+ LIST_DIRECTORIES false RELATIVE ${GHS_OS_ROOT} ${GHS_OS_ROOT}/*)
+ if ( GHS_CANDIDATE_OS_FILES )
+ list(REMOVE_ITEM GHS_CANDIDATE_OS_DIRS ${GHS_CANDIDATE_OS_FILES})
endif ()
- endif ()
- #Try to look for known registry values
- if (NOT GHS_INT_DIRECTORY)
- find_path(GHS_INT_DIRECTORY INTEGRITY.ld PATHS
- "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\GreenHillsSoftware6433c345;InstallLocation]" #int1122
- "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\GreenHillsSoftware289b6625;InstallLocation]" #int1104
- )
- endif ()
+ #filter based on platform name
+ if (GHS_TARGET_PLATFORM STREQUAL "integrity")
+ list(FILTER GHS_CANDIDATE_OS_DIRS INCLUDE REGEX "int[0-9][0-9][0-9][0-9a-z].*")
+ endif ()
+
+ if (GHS_CANDIDATE_OS_DIRS)
+ list(SORT GHS_CANDIDATE_OS_DIRS)
+ list(GET GHS_CANDIDATE_OS_DIRS -1 GHS_OS_DIR)
+ string(CONCAT GHS_OS_DIR ${GHS_OS_ROOT} "/" ${GHS_OS_DIR})
+ endif()
- set(GHS_INT_DIRECTORY ${GHS_INT_DIRECTORY} CACHE PATH
- "Path to integrity directory")
+ set(GHS_OS_DIR "${GHS_OS_DIR}" CACHE PATH "GHS platform OS directory" FORCE)
+ endif ()
endif ()
-set(GHS_OS_DIR ${GHS_INT_DIRECTORY} CACHE PATH "OS directory")
-set(GHS_PRIMARY_TARGET "arm_integrity.tgt" CACHE STRING "target for compilation")
-set(GHS_BSP_NAME "simarm" CACHE STRING "BSP name")
+set(GHS_BSP_NAME "IGNORE" CACHE STRING "BSP name")
+
set(GHS_CUSTOMIZATION "" CACHE FILEPATH "optional GHS customization")
mark_as_advanced(GHS_CUSTOMIZATION)
set(GHS_GPJ_MACROS "" CACHE STRING "optional GHS macros generated in the .gpjs for legacy reasons")
set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,")
set(CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic")
+# Debian policy requires that shared libraries be installed without
+# executable permission. Fedora policy requires that shared libraries
+# be installed with the executable permission. Since the native tools
+# create shared libraries with execute permission in the first place a
+# reasonable policy seems to be to install with execute permission by
+# default. In order to support debian packages we provide an option
+# here. The option default is based on the current distribution, but
+# packagers can set it explicitly on the command line.
+if(DEFINED CMAKE_INSTALL_SO_NO_EXE)
+ # Store the decision variable in the cache. This preserves any
+ # setting the user provides on the command line.
+ set(CMAKE_INSTALL_SO_NO_EXE "${CMAKE_INSTALL_SO_NO_EXE}" CACHE INTERNAL
+ "Install .so files without execute permission.")
+else()
+ # Store the decision variable as an internal cache entry to avoid
+ # checking the platform every time. This option is advanced enough
+ # that only package maintainers should need to adjust it. They are
+ # capable of providing a setting on the command line.
+ if(EXISTS "/etc/debian_version")
+ set(CMAKE_INSTALL_SO_NO_EXE 1 CACHE INTERNAL
+ "Install .so files without execute permission.")
+ else()
+ set(CMAKE_INSTALL_SO_NO_EXE 0 CACHE INTERNAL
+ "Install .so files without execute permission.")
+ endif()
+endif()
+
set(CMAKE_LIBRARY_ARCHITECTURE_REGEX "[a-z0-9_]+(-[a-z0-9_]+)?-gnu[a-z0-9_]*")
include(Platform/UnixPaths)
string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " ")
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " ")
+set(CMAKE_C_LINKER_WRAPPER_FLAG "-flags-link" " ")
+set(CMAKE_C_LINKER_WRAPPER_FLAG_SEP ",")
+
set(CMAKE_C_CREATE_STATIC_LIBRARY
"<CMAKE_C_COMPILER> -build-lib -proc ${ADSP_PROCESSOR} -si-revision ${ADSP_PROCESSOR_SILICIUM_REVISION} -o <TARGET> <CMAKE_C_LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_CREATE_SHARED_LIBRARY)
set(CMAKE_C_CREATE_MODULE_LIBRARY)
-
string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " ")
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " ")
+set(CMAKE_CXX_LINKER_WRAPPER_FLAG "-flags-link" " ")
+set(CMAKE_CXX_LINKER_WRAPPER_FLAG_SEP ",")
+
set(CMAKE_CXX_CREATE_STATIC_LIBRARY
"<CMAKE_CXX_COMPILER> -build-lib -proc ${ADSP_PROCESSOR} -si-revision ${ADSP_PROCESSOR_SILICIUM_REVISION} -o <TARGET> <CMAKE_CXX_LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_CREATE_SHARED_LIBRARY)
set(CMAKE_CXX_CREATE_MODULE_LIBRARY)
-
set (CMAKE_EXE_LINKER_FLAGS_INIT --model-small)
endif()
+set(CMAKE_C_LINKER_WRAPPER_FLAG "-Wl" ",")
+
# compile a C file into an object file
set(CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
# not supported by sdcc
set(CMAKE_C_CREATE_SHARED_LIBRARY "")
set(CMAKE_C_CREATE_MODULE_LIBRARY "")
-
# executables that use dlopen but do not set ENABLE_EXPORTS.
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
+
set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
if(XIAR)
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "${_tD}") # ... while this is a space separated string.
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+ set (CMAKE_${lang}_LINKER_WRAPPER_FLAG "-l")
+
# compile a source file into an object file
# place <DEFINES> outside the response file because Borland refuses
# to parse quotes from the response file.
include(Platform/Windows-MSVC)
macro(__windows_compiler_intel lang)
__windows_compiler_msvc(${lang})
- string(REPLACE "<CMAKE_LINKER> /lib" "lib" CMAKE_${lang}_CREATE_STATIC_LIBRARY "${CMAKE_${lang}_CREATE_STATIC_LIBRARY}")
+ string(REPLACE "<CMAKE_LINKER> /lib" "xilib" CMAKE_${lang}_CREATE_STATIC_LIBRARY "${CMAKE_${lang}_CREATE_STATIC_LIBRARY}")
foreach(rule CREATE_SHARED_LIBRARY CREATE_SHARED_MODULE LINK_EXECUTABLE)
string(REPLACE "<CMAKE_LINKER>" "xilink" CMAKE_${lang}_${rule} "${CMAKE_${lang}_${rule}}")
endforeach()
--- /dev/null
+include(Platform/Windows-Clang-C)
--- /dev/null
+include(Platform/Windows-Clang-CXX)
--- /dev/null
+include(Platform/Windows-GNU-C)
--- /dev/null
+include(Platform/Windows-GNU-CXX)
--- /dev/null
+include(Platform/Windows-Clang-C)
--- /dev/null
+include(Platform/Windows-Clang-CXX)
--- /dev/null
+include(Platform/Windows-GNU-C)
--- /dev/null
+include(Platform/Windows-GNU-CXX)
# Sets the variable named ${var} to the number of physical cores
# available on the machine if the information can be determined.
# Otherwise it is set to 0. Currently this functionality is implemented
-# for AIX, cygwin, FreeBSD, HPUX, IRIX, Linux, Mac OS X, QNX, Sun and
+# for AIX, cygwin, FreeBSD, HPUX, IRIX, Linux, macOS, QNX, Sun and
# Windows.
#
# This function is guaranteed to return a positive integer (>=1) if it
.. note::
- The variable ``SWIG_MODULE_<name>_REAL_NAME`` will be set to the name
- of the swig module target library. This variable is useless if variable
- ``UseSWIG_TARGET_NAME_PREFERENCE`` is set to ``STANDARD``.
+ This command creates a target with the specified ``<name>`` when
+ policy :policy:`CMP0078` is set to ``NEW``. Otherwise, the legacy
+ behavior will choose a different target name and store it in the
+ ``SWIG_MODULE_<name>_REAL_NAME`` variable.
.. note::
:prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
:prop_sf:`COMPILE_OPTIONS`.
+``USE_TARGET_INCLUDE_DIRECTORIES``
+ If set to ``TRUE``, contents of target property
+ :prop_tgt:`INCLUDE_DIRECTORIES` will be forwarded to ``SWIG`` compiler.
+ If set to ``FALSE`` target property :prop_tgt:`INCLUDE_DIRECTORIES` will be
+ ignored. If not set, target property ``SWIG_USE_TARGET_INCLUDE_DIRECTORIES``
+ will be considered.
+
``GENERATED_INCLUDE_DIRECTORIES``, ``GENERATED_COMPILE_DEFINITIONS`` and ``GENERATED_COMPILE_OPTIONS``
Add custom flags to the C/C++ generated source. They will fill, respectively,
properties :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
set_property(TARGET mymod PROPERTY SWIG_COMPILE_DEFINITIONS MY_DEF1 MY_DEF2)
set_property(TARGET mymod PROPERTY SWIG_COMPILE_OPTIONS -bla -blb)
+``SWIG_USE_TARGET_INCLUDE_DIRECTORIES``
+ If set to ``TRUE``, contents of target property
+ :prop_tgt:`INCLUDE_DIRECTORIES` will be forwarded to ``SWIG`` compiler.
+ If set to ``FALSE`` or not defined, target property
+ :prop_tgt:`INCLUDE_DIRECTORIES` will be ignored. This behavior can be
+ overridden by specifying source property ``USE_TARGET_INCLUDE_DIRECTORIES``.
+
``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS``
These properties will populate, respectively, properties
:prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
Some variables can be set to customize the behavior of ``swig_add_library``
as well as ``SWIG``:
-``UseSWIG_TARGET_NAME_PREFERENCE``
- Specify target name strategy.
-
- * Set to ``LEGACY`` or undefined: legacy strategy is applied. Variable
- ``SWIG_MODULE_<name>_REAL_NAME`` must be used to get real target name.
- * Set to ``STANDARD``: target name matches specified name.
-
``UseSWIG_MODULE_VERSION``
Specify different behaviors for ``UseSWIG`` module.
Specify extra dependencies for the generated module for ``<name>``.
#]=======================================================================]
-
+cmake_policy(GET CMP0078 target_name_policy)
cmake_policy (VERSION 3.12)
+if (target_name_policy)
+ # respect user choice regarding CMP0078 policy
+ cmake_policy(SET CMP0078 ${target_name_policy})
+endif()
+unset(target_name_policy)
set(SWIG_CXX_EXTENSION "cxx")
set(SWIG_EXTRA_LIBRARIES "")
set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
set(SWIG_CSHARP_EXTRA_FILE_EXTENSIONS ".cs" "PINVOKE.cs")
+set(SWIG_MANAGE_SUPPORT_FILES_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/UseSWIG/ManageSupportFiles.cmake")
+
##
## PRIVATE functions
##
endif()
set (property "$<TARGET_PROPERTY:${target_name},SWIG_INCLUDE_DIRECTORIES>")
list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:$<TARGET_GENEX_EVAL:${target_name},${property}>,$<SEMICOLON>-I>>")
+ set (property "$<TARGET_PROPERTY:${target_name},INCLUDE_DIRECTORIES>")
+ get_source_file_property(use_target_include_dirs "${infile}" USE_TARGET_INCLUDE_DIRECTORIES)
+ if (use_target_include_dirs)
+ list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
+ elseif(use_target_include_dirs STREQUAL "NOTFOUND")
+ # not defined at source level, rely on target level
+ list (APPEND swig_source_file_flags "$<$<AND:$<BOOL:$<TARGET_PROPERTY:${target_name},SWIG_USE_TARGET_INCLUDE_DIRECTORIES>>,$<BOOL:${property}>>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
+ endif()
set (property "$<TARGET_PROPERTY:${target_name},SWIG_COMPILE_DEFINITIONS>")
list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:$<TARGET_GENEX_EVAL:${target_name},${property}>,$<SEMICOLON>-D>>")
if (UseSWIG_MODULE_VERSION VERSION_GREATER 1)
# as part of custom command, start by removing old generated files
# to ensure obsolete files do not stay
- set (swig_cleanup_command COMMAND "${CMAKE_COMMAND}" -E remove_directory "${outdir}")
+ set (swig_file_outdir "${workingdir}/${swig_source_file_name_we}.files")
+ set (swig_cleanup_command COMMAND "${CMAKE_COMMAND}" "-DSUPPORT_FILES_WORKING_DIRECTORY=${swig_file_outdir}" "-DSUPPORT_FILES_OUTPUT_DIRECTORY=${outdir}" -DACTION=CLEAN -P "${SWIG_MANAGE_SUPPORT_FILES_SCRIPT}")
+ set (swig_copy_command COMMAND "${CMAKE_COMMAND}" "-DSUPPORT_FILES_WORKING_DIRECTORY=${swig_file_outdir}" "-DSUPPORT_FILES_OUTPUT_DIRECTORY=${outdir}" -DACTION=COPY -P "${SWIG_MANAGE_SUPPORT_FILES_SCRIPT}")
else()
+ set (swig_file_outdir "${outdir}")
unset (swig_cleanup_command)
+ unset (swig_copy_command)
endif()
# IMPLICIT_DEPENDS below can not handle situations where a dependent file is
COMMAND "${CMAKE_COMMAND}" -E env "SWIG_LIB=${SWIG_DIR}" "${SWIG_EXECUTABLE}"
"-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
"${swig_source_file_flags}"
- -outdir "${outdir}"
+ -outdir "${swig_file_outdir}"
${swig_special_flags}
${swig_extra_flags}
"${swig_include_dirs}"
-o "${swig_generated_file_fullname}"
"${swig_source_file_fullname}"
+ ${swig_copy_command}
MAIN_DEPENDENCY "${swig_source_file_fullname}"
DEPENDS ${swig_dependencies}
IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
- COMMENT "Swig source"
+ COMMENT "Swig compile ${infile} for ${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
COMMAND_EXPAND_LISTS)
set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
PROPERTIES GENERATED 1)
unset(_SAM_TYPE)
endif()
- if (NOT DEFINED UseSWIG_TARGET_NAME_PREFERENCE)
- set (UseSWIG_TARGET_NAME_PREFERENCE LEGACY)
- elseif (NOT UseSWIG_TARGET_NAME_PREFERENCE MATCHES "^(LEGACY|STANDARD)$")
- message (FATAL_ERROR "UseSWIG_TARGET_NAME_PREFERENCE: ${UseSWIG_TARGET_NAME_PREFERENCE}: invalid value. 'LEGACY' or 'STANDARD' is expected.")
+ cmake_policy(GET CMP0078 target_name_policy)
+ if (target_name_policy STREQUAL "NEW")
+ set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
+ else()
+ if (NOT target_name_policy)
+ message(AUTHOR_WARNING
+ "Policy CMP0078 is not set. "
+ "Run \"cmake --help-policy CMP0078\" for policy details. "
+ "Use the cmake_policy command to set the policy and suppress this warning."
+ )
+ endif()
+ if (NOT DEFINED UseSWIG_TARGET_NAME_PREFERENCE)
+ set (UseSWIG_TARGET_NAME_PREFERENCE LEGACY)
+ elseif (NOT UseSWIG_TARGET_NAME_PREFERENCE MATCHES "^(LEGACY|STANDARD)$")
+ message (FATAL_ERROR "UseSWIG_TARGET_NAME_PREFERENCE: ${UseSWIG_TARGET_NAME_PREFERENCE}: invalid value. 'LEGACY' or 'STANDARD' is expected.")
+ endif()
endif()
if (NOT DEFINED UseSWIG_MODULE_VERSION)
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+if (ACTION STREQUAL "CLEAN")
+ # Collect current list of generated files
+ file (GLOB files LIST_DIRECTORIES FALSE RELATIVE "${SUPPORT_FILES_WORKING_DIRECTORY}" "${SUPPORT_FILES_WORKING_DIRECTORY}/*")
+
+ if (files)
+ # clean-up the output directory
+ ## compute full paths
+ list (TRANSFORM files PREPEND "${SUPPORT_FILES_OUTPUT_DIRECTORY}/")
+ ## remove generated files from the output directory
+ file (REMOVE ${files})
+
+ # clean-up working directory
+ file (REMOVE_RECURSE "${SUPPORT_FILES_WORKING_DIRECTORY}")
+ endif()
+
+ file (MAKE_DIRECTORY "${SUPPORT_FILES_WORKING_DIRECTORY}")
+endif()
+
+if (ACTION STREQUAL "COPY")
+ # Collect current list of generated files
+ file (GLOB files LIST_DIRECTORIES FALSE "${SUPPORT_FILES_WORKING_DIRECTORY}/*")
+
+ if (files)
+ # copy files to the output directory
+ file (COPY ${files} DESTINATION "${SUPPORT_FILES_OUTPUT_DIRECTORY}")
+ endif()
+endif()
CMake is a cross-platform, open-source build system generator.
For full documentation visit the `CMake Home Page`_ and the
-`CMake Documentation Page`_.
+`CMake Documentation Page`_. The `CMake Community Wiki`_ also
+references useful guides and recipes.
.. _`CMake Home Page`: https://cmake.org
.. _`CMake Documentation Page`: https://cmake.org/cmake/help/documentation.html
+.. _`CMake Community Wiki`: https://gitlab.kitware.com/cmake/community/wikis/home
CMake is maintained and supported by `Kitware`_ and developed in
collaboration with a productive community of contributors.
cmInstallDirectoryGenerator.h
cmInstallDirectoryGenerator.cxx
cmLinkedTree.h
+ cmLinkItem.cxx
cmLinkItem.h
cmLinkLineComputer.cxx
cmLinkLineComputer.h
cmAddCompileDefinitionsCommand.h
cmAddCompileOptionsCommand.cxx
cmAddCompileOptionsCommand.h
+ cmAddLinkOptionsCommand.cxx
+ cmAddLinkOptionsCommand.h
cmAddCustomCommandCommand.cxx
cmAddCustomCommandCommand.h
cmAddCustomTargetCommand.cxx
cmTargetCompileOptionsCommand.h
cmTargetIncludeDirectoriesCommand.cxx
cmTargetIncludeDirectoriesCommand.h
+ cmTargetLinkOptionsCommand.cxx
+ cmTargetLinkOptionsCommand.h
+ cmTargetLinkDirectoriesCommand.cxx
+ cmTargetLinkDirectoriesCommand.h
cmTargetLinkLibrariesCommand.cxx
cmTargetLinkLibrariesCommand.h
cmTargetPropCommandBase.cxx
set(CPACK_SRCS
CPack/cmCPackArchiveGenerator.cxx
CPack/cmCPackComponentGroup.cxx
+ CPack/cmCPackDebGenerator.cxx
+ CPack/cmCPackExternalGenerator.cxx
CPack/cmCPackGeneratorFactory.cxx
CPack/cmCPackGenerator.cxx
CPack/cmCPackLog.cxx
CPack/cmCPackTarCompressGenerator.cxx
CPack/cmCPackZIPGenerator.cxx
CPack/cmCPack7zGenerator.cxx
- CPack/cmCPackDebGenerator.cxx
)
# CPack IFW generator
set(CPACK_SRCS ${CPACK_SRCS}
add_library(CMakeServerLib
cmConnection.h cmConnection.cxx
cmFileMonitor.cxx cmFileMonitor.h
+ cmJsonObjectDictionary.h
+ cmJsonObjects.h
+ cmJsonObjects.cxx
cmPipeConnection.cxx cmPipeConnection.h
cmServer.cxx cmServer.h
cmServerConnection.cxx cmServerConnection.h
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
-set(CMake_VERSION_MINOR 12)
-set(CMake_VERSION_PATCH 4)
+set(CMake_VERSION_MINOR 13)
+set(CMake_VERSION_PATCH 0)
#set(CMake_VERSION_RC 0)
ifwCmd.c_str(), &output, &output, &retVal, nullptr,
this->GeneratorVerbose, cmDuration::zero());
if (!res || retVal) {
- cmGeneratedFileStream ofs(ifwTmpFile.c_str());
+ cmGeneratedFileStream ofs(ifwTmpFile);
ofs << "# Run command: " << ifwCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
ifwCmd.c_str(), &output, &output, &retVal, nullptr,
this->GeneratorVerbose, cmDuration::zero());
if (!res || retVal) {
- cmGeneratedFileStream ofs(ifwTmpFile.c_str());
+ cmGeneratedFileStream ofs(ifwTmpFile);
ofs << "# Run command: " << ifwCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
}
// Output stream
- cmGeneratedFileStream fout((this->Directory + "/config/config.xml").data());
+ cmGeneratedFileStream fout(this->Directory + "/config/config.xml");
cmXMLWriter xout(fout);
xout.StartDocument();
}
// Output stream
- cmGeneratedFileStream fout((this->Directory + "/meta/package.xml").data());
+ cmGeneratedFileStream fout(this->Directory + "/meta/package.xml");
cmXMLWriter xout(fout);
xout.StartDocument();
this->Directory + "/repository/UpdatesPatch.xml";
// Output stream
- cmGeneratedFileStream fout(updatesPatchXml.data());
+ cmGeneratedFileStream fout(updatesPatchXml);
cmXMLWriter xout(fout);
xout.StartDocument();
command << " -ext " << QuotePath(ext);
}
+ if (sourceFile.rfind(this->CPackTopLevel, 0) != 0) {
+ command << " " << QuotePath("-I" + this->CPackTopLevel);
+ }
+
AddCustomFlags("CPACK_WIX_CANDLE_EXTRA_FLAGS", command);
command << " " << QuotePath(sourceFile);
bool cmCPackWIXGenerator::InitializeWiXConfiguration()
{
- if (!ReadListFile("CPackWIX.cmake")) {
+ if (!ReadListFile("Internal/CPack/CPackWIX.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while executing CPackWIX.cmake" << std::endl);
return false;
*/
#define DECLARE_AND_OPEN_ARCHIVE(filename, archive) \
cmGeneratedFileStream gf; \
- gf.Open((filename).c_str(), false, true); \
+ gf.Open((filename), false, true); \
if (!GenerateHeader(&gf)) { \
cmCPackLogger(cmCPackLog::LOG_ERROR, \
- "Problem to generate Header for archive < " \
+ "Problem to generate Header for archive <" \
<< (filename) << ">." << std::endl); \
return 0; \
} \
cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \
if (!(archive)) { \
cmCPackLogger(cmCPackLog::LOG_ERROR, \
- "Problem to create archive < " \
- << (filename) << ">. ERROR =" << (archive).GetError() \
+ "Problem to create archive <" \
+ << (filename) << ">, ERROR = " << (archive).GetError() \
<< std::endl); \
return 0; \
}
archive.Add(rp, 0, nullptr, false);
if (!archive) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem while adding file< "
+ "Problem while adding file <"
<< file << "> to archive <" << packageFileNames[0]
- << "> .ERROR =" << archive.GetError() << std::endl);
+ << ">, ERROR = " << archive.GetError() << std::endl);
return 0;
}
}
std::vector<cmCPackComponentGroup*> Subgroups;
};
+/** \class cmCPackInstallCMakeProject
+ * \brief A single quadruplet from the CPACK_INSTALL_CMAKE_PROJECTS variable.
+ */
+class cmCPackInstallCMakeProject
+{
+public:
+ /// The directory of the CMake project.
+ std::string Directory;
+
+ /// The name of the CMake project.
+ std::string ProjectName;
+
+ /// The name of the component (or component set) to install.
+ std::string Component;
+
+ /// The subdirectory to install into.
+ std::string SubDirectory;
+
+ /// The list of installation types.
+ std::vector<cmCPackInstallationType*> InstallationTypes;
+
+ /// The list of components.
+ std::vector<cmCPackComponent*> Components;
+};
+
#endif
#include "cm_sys_stat.h"
#include "cmsys/Glob.hxx"
+#include <map>
#include <ostream>
#include <set>
#include <string.h>
#include <utility>
+namespace {
+
+class DebGenerator
+{
+public:
+ DebGenerator(cmCPackLog* logger, std::string const& outputName,
+ std::string const& workDir, std::string const& topLevelDir,
+ std::string const& temporaryDir,
+ const char* debianCompressionType,
+ const char* debianArchiveType,
+ std::map<std::string, std::string> const& controlValues,
+ bool genShLibs, std::string const& shLibsFilename,
+ bool genPostInst, std::string const& postInst, bool genPostRm,
+ std::string const& postRm, const char* controlExtra,
+ bool permissionStrctPolicy,
+ std::vector<std::string> const& packageFiles);
+
+ bool generate() const;
+
+private:
+ void generateDebianBinaryFile() const;
+ void generateControlFile() const;
+ bool generateDataTar() const;
+ std::string generateMD5File() const;
+ bool generateControlTar(std::string const& md5Filename) const;
+ bool generateDeb() const;
+
+ cmCPackLog* Logger;
+ const std::string OutputName;
+ const std::string WorkDir;
+ std::string CompressionSuffix;
+ const std::string TopLevelDir;
+ const std::string TemporaryDir;
+ const char* DebianArchiveType;
+ const std::map<std::string, std::string> ControlValues;
+ const bool GenShLibs;
+ const std::string ShLibsFilename;
+ const bool GenPostInst;
+ const std::string PostInst;
+ const bool GenPostRm;
+ const std::string PostRm;
+ const char* ControlExtra;
+ const bool PermissionStrictPolicy;
+ const std::vector<std::string> PackageFiles;
+ cmArchiveWrite::Compress TarCompressionType;
+};
+
+DebGenerator::DebGenerator(
+ cmCPackLog* logger, std::string const& outputName,
+ std::string const& workDir, std::string const& topLevelDir,
+ std::string const& temporaryDir, const char* debianCompressionType,
+ const char* debianArchiveType,
+ std::map<std::string, std::string> const& controlValues, bool genShLibs,
+ std::string const& shLibsFilename, bool genPostInst,
+ std::string const& postInst, bool genPostRm, std::string const& postRm,
+ const char* controlExtra, bool permissionStrictPolicy,
+ std::vector<std::string> const& packageFiles)
+ : Logger(logger)
+ , OutputName(outputName)
+ , WorkDir(workDir)
+ , TopLevelDir(topLevelDir)
+ , TemporaryDir(temporaryDir)
+ , DebianArchiveType(debianArchiveType ? debianArchiveType : "paxr")
+ , ControlValues(controlValues)
+ , GenShLibs(genShLibs)
+ , ShLibsFilename(shLibsFilename)
+ , GenPostInst(genPostInst)
+ , PostInst(postInst)
+ , GenPostRm(genPostRm)
+ , PostRm(postRm)
+ , ControlExtra(controlExtra)
+ , PermissionStrictPolicy(permissionStrictPolicy)
+ , PackageFiles(packageFiles)
+{
+ if (!debianCompressionType) {
+ debianCompressionType = "gzip";
+ }
+
+ if (!strcmp(debianCompressionType, "lzma")) {
+ CompressionSuffix = ".lzma";
+ TarCompressionType = cmArchiveWrite::CompressLZMA;
+ } else if (!strcmp(debianCompressionType, "xz")) {
+ CompressionSuffix = ".xz";
+ TarCompressionType = cmArchiveWrite::CompressXZ;
+ } else if (!strcmp(debianCompressionType, "bzip2")) {
+ CompressionSuffix = ".bz2";
+ TarCompressionType = cmArchiveWrite::CompressBZip2;
+ } else if (!strcmp(debianCompressionType, "gzip")) {
+ CompressionSuffix = ".gz";
+ TarCompressionType = cmArchiveWrite::CompressGZip;
+ } else if (!strcmp(debianCompressionType, "none")) {
+ CompressionSuffix.clear();
+ TarCompressionType = cmArchiveWrite::CompressNone;
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error unrecognized compression type: "
+ << debianCompressionType << std::endl);
+ }
+}
+
+bool DebGenerator::generate() const
+{
+ generateDebianBinaryFile();
+ generateControlFile();
+ if (!generateDataTar()) {
+ return false;
+ }
+ std::string md5Filename = generateMD5File();
+ if (!generateControlTar(md5Filename)) {
+ return false;
+ }
+ return generateDeb();
+}
+
+void DebGenerator::generateDebianBinaryFile() const
+{
+ // debian-binary file
+ const std::string dbfilename = WorkDir + "/debian-binary";
+ cmGeneratedFileStream out(dbfilename);
+ out << "2.0";
+ out << std::endl; // required for valid debian package
+}
+
+void DebGenerator::generateControlFile() const
+{
+ std::string ctlfilename = WorkDir + "/control";
+
+ cmGeneratedFileStream out(ctlfilename);
+ for (auto const& kv : ControlValues) {
+ out << kv.first << ": " << kv.second << "\n";
+ }
+
+ unsigned long totalSize = 0;
+ {
+ std::string dirName = TemporaryDir;
+ dirName += '/';
+ for (std::string const& file : PackageFiles) {
+ totalSize += cmSystemTools::FileLength(file);
+ }
+ }
+ out << "Installed-Size: " << (totalSize + 1023) / 1024 << "\n";
+ out << std::endl;
+}
+
+bool DebGenerator::generateDataTar() const
+{
+ std::string filename_data_tar = WorkDir + "/data.tar" + CompressionSuffix;
+ cmGeneratedFileStream fileStream_data_tar;
+ fileStream_data_tar.Open(filename_data_tar, false, true);
+ if (!fileStream_data_tar) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the file \""
+ << filename_data_tar << "\" for writing" << std::endl);
+ return false;
+ }
+ cmArchiveWrite data_tar(fileStream_data_tar, TarCompressionType,
+ DebianArchiveType);
+
+ // uid/gid should be the one of the root user, and this root user has
+ // always uid/gid equal to 0.
+ data_tar.SetUIDAndGID(0u, 0u);
+ data_tar.SetUNAMEAndGNAME("root", "root");
+
+ // now add all directories which have to be compressed
+ // collect all top level install dirs for that
+ // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would
+ // give /usr and /opt
+ size_t topLevelLength = WorkDir.length();
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "WDIR: \"" << WorkDir << "\", length = " << topLevelLength
+ << std::endl);
+ std::set<std::string> orderedFiles;
+
+ // we have to reconstruct the parent folders as well
+
+ for (std::string currentPath : PackageFiles) {
+ while (currentPath != WorkDir) {
+ // the last one IS WorkDir, but we do not want this one:
+ // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application
+ // should not add XXX/application
+ orderedFiles.insert(currentPath);
+ currentPath = cmSystemTools::CollapseCombinedPath(currentPath, "..");
+ }
+ }
+
+ for (std::string const& file : orderedFiles) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "FILEIT: \"" << file << "\"" << std::endl);
+ std::string::size_type slashPos = file.find('/', topLevelLength + 1);
+ std::string relativeDir =
+ file.substr(topLevelLength, slashPos - topLevelLength);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl);
+
+#ifdef WIN32
+ std::string mode_t_adt_filename = file + ":cmake_mode_t";
+ cmsys::ifstream permissionStream(mode_t_adt_filename.c_str());
+
+ mode_t permissions = 0;
+
+ if (permissionStream) {
+ permissionStream >> std::oct >> permissions;
+ }
+
+ if (permissions != 0) {
+ data_tar.SetPermissions(permissions);
+ } else if (cmSystemTools::FileIsDirectory(file)) {
+ data_tar.SetPermissions(0755);
+ } else {
+ data_tar.ClearPermissions();
+ }
+#endif
+
+ // do not recurse because the loop will do it
+ if (!data_tar.Add(file, topLevelLength, ".", false)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: " << file << std::endl
+ << "#error:" << data_tar.GetError() << std::endl);
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string DebGenerator::generateMD5File() const
+{
+ std::string md5filename = WorkDir + "/md5sums";
+
+ cmGeneratedFileStream out(md5filename);
+
+ std::string topLevelWithTrailingSlash = TemporaryDir;
+ topLevelWithTrailingSlash += '/';
+ for (std::string const& file : PackageFiles) {
+ // hash only regular files
+ if (cmSystemTools::FileIsDirectory(file) ||
+ cmSystemTools::FileIsSymlink(file)) {
+ continue;
+ }
+
+ std::string output =
+ cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5);
+ if (output.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem computing the md5 of " << file << std::endl);
+ }
+
+ output += " " + file + "\n";
+ // debian md5sums entries are like this:
+ // 014f3604694729f3bf19263bac599765 usr/bin/ccmake
+ // thus strip the full path (with the trailing slash)
+ cmSystemTools::ReplaceString(output, topLevelWithTrailingSlash.c_str(),
+ "");
+ out << output;
+ }
+ // each line contains a eol.
+ // Do not end the md5sum file with yet another (invalid)
+ return md5filename;
+}
+
+bool DebGenerator::generateControlTar(std::string const& md5Filename) const
+{
+ std::string filename_control_tar = WorkDir + "/control.tar.gz";
+
+ cmGeneratedFileStream fileStream_control_tar;
+ fileStream_control_tar.Open(filename_control_tar, false, true);
+ if (!fileStream_control_tar) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the file \""
+ << filename_control_tar << "\" for writing" << std::endl);
+ return false;
+ }
+ cmArchiveWrite control_tar(fileStream_control_tar,
+ cmArchiveWrite::CompressGZip, DebianArchiveType);
+
+ // sets permissions and uid/gid for the files
+ control_tar.SetUIDAndGID(0u, 0u);
+ control_tar.SetUNAMEAndGNAME("root", "root");
+
+ /* permissions are set according to
+ https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
+ and
+ https://lintian.debian.org/tags/control-file-has-bad-permissions.html
+ */
+ const mode_t permission644 = 0644;
+ const mode_t permissionExecute = 0111;
+ const mode_t permission755 = permission644 | permissionExecute;
+
+ // for md5sum and control (that we have generated here), we use 644
+ // (RW-R--R--)
+ // so that deb lintian doesn't warn about it
+ control_tar.SetPermissions(permission644);
+
+ // adds control and md5sums
+ if (!control_tar.Add(md5Filename, WorkDir.length(), ".") ||
+ !control_tar.Add(WorkDir + "/control", WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"control\" or \"md5sums\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+
+ // adds generated shlibs file
+ if (GenShLibs) {
+ if (!control_tar.Add(ShLibsFilename, WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"shlibs\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+ }
+
+ // adds LDCONFIG related files
+ if (GenPostInst) {
+ control_tar.SetPermissions(permission755);
+ if (!control_tar.Add(PostInst, WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"postinst\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+ control_tar.SetPermissions(permission644);
+ }
+
+ if (GenPostRm) {
+ control_tar.SetPermissions(permission755);
+ if (!control_tar.Add(PostRm, WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"postinst\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+ control_tar.SetPermissions(permission644);
+ }
+
+ // for the other files, we use
+ // -either the original permission on the files
+ // -either a permission strictly defined by the Debian policies
+ if (ControlExtra) {
+ // permissions are now controlled by the original file permissions
+
+ static const char* strictFiles[] = { "config", "postinst", "postrm",
+ "preinst", "prerm" };
+ std::set<std::string> setStrictFiles(
+ strictFiles, strictFiles + sizeof(strictFiles) / sizeof(strictFiles[0]));
+
+ // default
+ control_tar.ClearPermissions();
+
+ std::vector<std::string> controlExtraList;
+ cmSystemTools::ExpandListArgument(ControlExtra, controlExtraList);
+ for (std::string const& i : controlExtraList) {
+ std::string filenamename = cmsys::SystemTools::GetFilenameName(i);
+ std::string localcopy = WorkDir + "/" + filenamename;
+
+ if (PermissionStrictPolicy) {
+ control_tar.SetPermissions(
+ setStrictFiles.count(filenamename) ? permission755 : permission644);
+ }
+
+ // if we can copy the file, it means it does exist, let's add it:
+ if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) {
+ control_tar.Add(localcopy, WorkDir.length(), ".");
+ }
+ }
+ }
+
+ return true;
+}
+
+bool DebGenerator::generateDeb() const
+{
+ // ar -r your-package-name.deb debian-binary control.tar.* data.tar.*
+ // A debian package .deb is simply an 'ar' archive. The only subtle
+ // difference is that debian uses the BSD ar style archive whereas most
+ // Linux distro have a GNU ar.
+ // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info
+ std::string const outputPath = TopLevelDir + "/" + OutputName;
+ std::string const tlDir = WorkDir + "/";
+ cmGeneratedFileStream debStream;
+ debStream.Open(outputPath, false, true);
+ cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd");
+
+ // uid/gid should be the one of the root user, and this root user has
+ // always uid/gid equal to 0.
+ deb.SetUIDAndGID(0u, 0u);
+ deb.SetUNAMEAndGNAME("root", "root");
+
+ if (!deb.Add(tlDir + "debian-binary", tlDir.length()) ||
+ !deb.Add(tlDir + "control.tar.gz", tlDir.length()) ||
+ !deb.Add(tlDir + "data.tar" + CompressionSuffix, tlDir.length())) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error creating debian package:"
+ << std::endl
+ << "#top level directory: " << TopLevelDir << std::endl
+ << "#file: " << OutputName << std::endl
+ << "#error:" << deb.GetError() << std::endl);
+ return false;
+ }
+ return true;
+}
+
+} // end anonymous namespace
+
cmCPackDebGenerator::cmCPackDebGenerator()
{
}
component_path += packageName;
this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
- if (!this->ReadListFile("CPackDeb.cmake")) {
+ if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackDeb.cmake" << std::endl);
retval = 0;
return retval;
}
- cmsys::Glob gl;
- std::string findExpr(this->GetOption("GEN_WDIR"));
- findExpr += "/*";
- gl.RecurseOn();
- gl.SetRecurseListDirs(true);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
- return 0;
+ { // Isolate globbing of binaries vs. dbgsyms
+ cmsys::Glob gl;
+ std::string findExpr(this->GetOption("GEN_WDIR"));
+ findExpr += "/*";
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find any files in the installed directory"
+ << std::endl);
+ return 0;
+ }
+ packageFiles = gl.GetFiles();
}
- packageFiles = gl.GetFiles();
int res = createDeb();
if (res != 1) {
packageFileName += "/";
packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
packageFileNames.push_back(std::move(packageFileName));
+
+ if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE")) {
+ cmsys::Glob gl;
+ std::string findExpr(this->GetOption("GEN_DBGSYMDIR"));
+ findExpr += "/*";
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find any files in the installed directory"
+ << std::endl);
+ return 0;
+ }
+ packageFiles = gl.GetFiles();
+
+ res = createDbgsymDDeb();
+ if (res != 1) {
+ retval = 0;
+ }
+ // add the generated package to package file names list
+ packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ packageFileName += "/";
+ packageFileName += this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME");
+ packageFileNames.push_back(std::move(packageFileName));
+ }
+
return retval;
}
this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
}
- if (!this->ReadListFile("CPackDeb.cmake")) {
+ if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackDeb.cmake" << std::endl);
retval = 0;
int cmCPackDebGenerator::createDeb()
{
- // debian-binary file
- const std::string strGenWDIR(this->GetOption("GEN_WDIR"));
- const std::string dbfilename = strGenWDIR + "/debian-binary";
- { // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(dbfilename.c_str());
- out << "2.0";
- out << std::endl; // required for valid debian package
- }
-
- // control file
- std::string ctlfilename = strGenWDIR + "/control";
+ std::map<std::string, std::string> controlValues;
// debian policy enforce lower case for package name
- // mandatory entries:
- std::string debian_pkg_name = cmsys::SystemTools::LowerCase(
+ controlValues["Package"] = cmsys::SystemTools::LowerCase(
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME"));
- const char* debian_pkg_version =
+ controlValues["Version"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
- const char* debian_pkg_section =
+ controlValues["Section"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION");
- const char* debian_pkg_priority =
+ controlValues["Priority"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY");
- const char* debian_pkg_arch =
+ controlValues["Architecture"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
- const char* maintainer =
+ controlValues["Maintainer"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
- const char* desc = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION");
+ controlValues["Description"] =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION");
- // optional entries
+ const char* debian_pkg_source =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
+ if (debian_pkg_source && *debian_pkg_source) {
+ controlValues["Source"] = debian_pkg_source;
+ }
const char* debian_pkg_dep =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS");
+ if (debian_pkg_dep && *debian_pkg_dep) {
+ controlValues["Depends"] = debian_pkg_dep;
+ }
const char* debian_pkg_rec =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS");
+ if (debian_pkg_rec && *debian_pkg_rec) {
+ controlValues["Recommends"] = debian_pkg_rec;
+ }
const char* debian_pkg_sug =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS");
+ if (debian_pkg_sug && *debian_pkg_sug) {
+ controlValues["Suggests"] = debian_pkg_sug;
+ }
const char* debian_pkg_url =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE");
+ if (debian_pkg_url && *debian_pkg_url) {
+ controlValues["Homepage"] = debian_pkg_url;
+ }
const char* debian_pkg_predep =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS");
+ if (debian_pkg_predep && *debian_pkg_predep) {
+ controlValues["Pre-Depends"] = debian_pkg_predep;
+ }
const char* debian_pkg_enhances =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES");
+ if (debian_pkg_enhances && *debian_pkg_enhances) {
+ controlValues["Enhances"] = debian_pkg_enhances;
+ }
const char* debian_pkg_breaks =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS");
+ if (debian_pkg_breaks && *debian_pkg_breaks) {
+ controlValues["Breaks"] = debian_pkg_breaks;
+ }
const char* debian_pkg_conflicts =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS");
+ if (debian_pkg_conflicts && *debian_pkg_conflicts) {
+ controlValues["Conflicts"] = debian_pkg_conflicts;
+ }
const char* debian_pkg_provides =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES");
+ if (debian_pkg_provides && *debian_pkg_provides) {
+ controlValues["Provides"] = debian_pkg_provides;
+ }
const char* debian_pkg_replaces =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES");
- const char* debian_pkg_source =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
-
- { // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(ctlfilename.c_str());
- out << "Package: " << debian_pkg_name << "\n";
- out << "Version: " << debian_pkg_version << "\n";
- out << "Section: " << debian_pkg_section << "\n";
- out << "Priority: " << debian_pkg_priority << "\n";
- out << "Architecture: " << debian_pkg_arch << "\n";
- if (debian_pkg_source && *debian_pkg_source) {
- out << "Source: " << debian_pkg_source << "\n";
- }
- if (debian_pkg_dep && *debian_pkg_dep) {
- out << "Depends: " << debian_pkg_dep << "\n";
- }
- if (debian_pkg_rec && *debian_pkg_rec) {
- out << "Recommends: " << debian_pkg_rec << "\n";
- }
- if (debian_pkg_sug && *debian_pkg_sug) {
- out << "Suggests: " << debian_pkg_sug << "\n";
- }
- if (debian_pkg_url && *debian_pkg_url) {
- out << "Homepage: " << debian_pkg_url << "\n";
- }
- if (debian_pkg_predep && *debian_pkg_predep) {
- out << "Pre-Depends: " << debian_pkg_predep << "\n";
- }
- if (debian_pkg_enhances && *debian_pkg_enhances) {
- out << "Enhances: " << debian_pkg_enhances << "\n";
- }
- if (debian_pkg_breaks && *debian_pkg_breaks) {
- out << "Breaks: " << debian_pkg_breaks << "\n";
- }
- if (debian_pkg_conflicts && *debian_pkg_conflicts) {
- out << "Conflicts: " << debian_pkg_conflicts << "\n";
- }
- if (debian_pkg_provides && *debian_pkg_provides) {
- out << "Provides: " << debian_pkg_provides << "\n";
- }
- if (debian_pkg_replaces && *debian_pkg_replaces) {
- out << "Replaces: " << debian_pkg_replaces << "\n";
- }
- unsigned long totalSize = 0;
- {
- std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- dirName += '/';
- for (std::string const& file : packageFiles) {
- totalSize += cmSystemTools::FileLength(file);
- }
- }
- out << "Installed-Size: " << (totalSize + 1023) / 1024 << "\n";
- out << "Maintainer: " << maintainer << "\n";
- out << "Description: " << desc << "\n";
- out << std::endl;
+ if (debian_pkg_replaces && *debian_pkg_replaces) {
+ controlValues["Replaces"] = debian_pkg_replaces;
}
+ const std::string strGenWDIR(this->GetOption("GEN_WDIR"));
const std::string shlibsfilename = strGenWDIR + "/shlibs";
const char* debian_pkg_shlibs =
const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") &&
debian_pkg_shlibs && *debian_pkg_shlibs;
if (gen_shibs) {
- cmGeneratedFileStream out(shlibsfilename.c_str());
+ cmGeneratedFileStream out(shlibsfilename);
out << debian_pkg_shlibs;
out << std::endl;
}
const std::string postinst = strGenWDIR + "/postinst";
const std::string postrm = strGenWDIR + "/postrm";
if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) {
- cmGeneratedFileStream out(postinst.c_str());
+ cmGeneratedFileStream out(postinst);
out << "#!/bin/sh\n\n"
"set -e\n\n"
"if [ \"$1\" = \"configure\" ]; then\n"
"fi\n";
}
if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) {
- cmGeneratedFileStream out(postrm.c_str());
+ cmGeneratedFileStream out(postrm);
out << "#!/bin/sh\n\n"
"set -e\n\n"
"if [ \"$1\" = \"remove\" ]; then\n"
"fi\n";
}
- cmArchiveWrite::Compress tar_compression_type = cmArchiveWrite::CompressGZip;
- const char* debian_compression_type =
- this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE");
- if (!debian_compression_type) {
- debian_compression_type = "gzip";
- }
-
- std::string compression_suffix;
- if (!strcmp(debian_compression_type, "lzma")) {
- compression_suffix = ".lzma";
- tar_compression_type = cmArchiveWrite::CompressLZMA;
- } else if (!strcmp(debian_compression_type, "xz")) {
- compression_suffix = ".xz";
- tar_compression_type = cmArchiveWrite::CompressXZ;
- } else if (!strcmp(debian_compression_type, "bzip2")) {
- compression_suffix = ".bz2";
- tar_compression_type = cmArchiveWrite::CompressBZip2;
- } else if (!strcmp(debian_compression_type, "gzip")) {
- compression_suffix = ".gz";
- tar_compression_type = cmArchiveWrite::CompressGZip;
- } else if (!strcmp(debian_compression_type, "none")) {
- compression_suffix.clear();
- tar_compression_type = cmArchiveWrite::CompressNone;
- } else {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error unrecognized compression type: "
- << debian_compression_type << std::endl);
- }
-
- const char* debian_archive_type =
- this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE");
- if (!debian_archive_type) {
- debian_archive_type = "paxr";
+ DebGenerator gen(
+ Logger, this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"), strGenWDIR,
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
+ this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
+ this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, gen_shibs,
+ shlibsfilename, this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST"), postinst,
+ this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM"), postrm,
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA"),
+ this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
+ packageFiles);
+
+ if (!gen.generate()) {
+ return 0;
}
+ return 1;
+}
- std::string filename_data_tar =
- strGenWDIR + "/data.tar" + compression_suffix;
-
- // atomic file generation for data.tar
- {
- cmGeneratedFileStream fileStream_data_tar;
- fileStream_data_tar.Open(filename_data_tar.c_str(), false, true);
- if (!fileStream_data_tar) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error opening the file \""
- << filename_data_tar << "\" for writing" << std::endl);
- return 0;
- }
- cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type,
- debian_archive_type);
-
- // uid/gid should be the one of the root user, and this root user has
- // always uid/gid equal to 0.
- data_tar.SetUIDAndGID(0u, 0u);
- data_tar.SetUNAMEAndGNAME("root", "root");
-
- // now add all directories which have to be compressed
- // collect all top level install dirs for that
- // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would
- // give /usr and /opt
- size_t topLevelLength = strGenWDIR.length();
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "WDIR: \"" << strGenWDIR << "\", length = " << topLevelLength
- << std::endl);
- std::set<std::string> orderedFiles;
-
- // we have to reconstruct the parent folders as well
-
- for (std::string currentPath : packageFiles) {
- while (currentPath != strGenWDIR) {
- // the last one IS strGenWDIR, but we do not want this one:
- // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application
- // should not add XXX/application
- orderedFiles.insert(currentPath);
- currentPath = cmSystemTools::CollapseCombinedPath(currentPath, "..");
- }
- }
-
- for (std::string const& file : orderedFiles) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "FILEIT: \"" << file << "\"" << std::endl);
- std::string::size_type slashPos = file.find('/', topLevelLength + 1);
- std::string relativeDir =
- file.substr(topLevelLength, slashPos - topLevelLength);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl);
-
-#ifdef WIN32
- std::string mode_t_adt_filename = file + ":cmake_mode_t";
- cmsys::ifstream permissionStream(mode_t_adt_filename.c_str());
-
- mode_t permissions = 0;
-
- if (permissionStream) {
- permissionStream >> std::oct >> permissions;
- }
-
- if (permissions != 0) {
- data_tar.SetPermissions(permissions);
- } else if (cmSystemTools::FileIsDirectory(file)) {
- data_tar.SetPermissions(0755);
- } else {
- data_tar.ClearPermissions();
- }
-#endif
-
- // do not recurse because the loop will do it
- if (!data_tar.Add(file, topLevelLength, ".", false)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: " << file << std::endl
- << "#error:" << data_tar.GetError() << std::endl);
- return 0;
- }
- }
- } // scope for file generation
+int cmCPackDebGenerator::createDbgsymDDeb()
+{
+ // Packages containing debug symbols follow the same structure as .debs
+ // but have different metadata and content.
- std::string md5filename = strGenWDIR + "/md5sums";
- {
- // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(md5filename.c_str());
-
- std::string topLevelWithTrailingSlash =
- this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- topLevelWithTrailingSlash += '/';
- for (std::string const& file : packageFiles) {
- // hash only regular files
- if (cmSystemTools::FileIsDirectory(file) ||
- cmSystemTools::FileIsSymlink(file)) {
- continue;
- }
+ std::map<std::string, std::string> controlValues;
+ // debian policy enforce lower case for package name
+ std::string packageNameLower = cmsys::SystemTools::LowerCase(
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME"));
+ const char* debian_pkg_version =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
- std::string output =
- cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5);
- if (output.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem computing the md5 of " << file << std::endl);
- }
+ controlValues["Package"] = packageNameLower + "-dbgsym";
+ controlValues["Package-Type"] = "ddeb";
+ controlValues["Version"] = debian_pkg_version;
+ controlValues["Auto-Built-Package"] = "debug-symbols";
+ controlValues["Depends"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") +
+ std::string(" (= ") + debian_pkg_version + ")";
+ controlValues["Section"] = "debug";
+ controlValues["Priority"] = "optional";
+ controlValues["Architecture"] =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
+ controlValues["Maintainer"] =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
+ controlValues["Description"] =
+ std::string("debug symbols for ") + packageNameLower;
- output += " " + file + "\n";
- // debian md5sums entries are like this:
- // 014f3604694729f3bf19263bac599765 usr/bin/ccmake
- // thus strip the full path (with the trailing slash)
- cmSystemTools::ReplaceString(output, topLevelWithTrailingSlash.c_str(),
- "");
- out << output;
- }
- // each line contains a eol.
- // Do not end the md5sum file with yet another (invalid)
+ const char* debian_pkg_source =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
+ if (debian_pkg_source && *debian_pkg_source) {
+ controlValues["Source"] = debian_pkg_source;
}
-
- std::string filename_control_tar = strGenWDIR + "/control.tar.gz";
- // atomic file generation for control.tar
- {
- cmGeneratedFileStream fileStream_control_tar;
- fileStream_control_tar.Open(filename_control_tar.c_str(), false, true);
- if (!fileStream_control_tar) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error opening the file \"" << filename_control_tar
- << "\" for writing"
- << std::endl);
- return 0;
- }
- cmArchiveWrite control_tar(fileStream_control_tar,
- cmArchiveWrite::CompressGZip,
- debian_archive_type);
-
- // sets permissions and uid/gid for the files
- control_tar.SetUIDAndGID(0u, 0u);
- control_tar.SetUNAMEAndGNAME("root", "root");
-
- /* permissions are set according to
- https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
- and
- https://lintian.debian.org/tags/control-file-has-bad-permissions.html
- */
- const mode_t permission644 = 0644;
- const mode_t permissionExecute = 0111;
- const mode_t permission755 = permission644 | permissionExecute;
-
- // for md5sum and control (that we have generated here), we use 644
- // (RW-R--R--)
- // so that deb lintian doesn't warn about it
- control_tar.SetPermissions(permission644);
-
- // adds control and md5sums
- if (!control_tar.Add(md5filename, strGenWDIR.length(), ".") ||
- !control_tar.Add(strGenWDIR + "/control", strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"control\" or \"md5sums\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
-
- // adds generated shlibs file
- if (gen_shibs) {
- if (!control_tar.Add(shlibsfilename, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"shlibs\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
- }
-
- // adds LDCONFIG related files
- if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) {
- control_tar.SetPermissions(permission755);
- if (!control_tar.Add(postinst, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
- control_tar.SetPermissions(permission644);
- }
-
- if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) {
- control_tar.SetPermissions(permission755);
- if (!control_tar.Add(postrm, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
- control_tar.SetPermissions(permission644);
- }
-
- // for the other files, we use
- // -either the original permission on the files
- // -either a permission strictly defined by the Debian policies
- const char* controlExtra =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA");
- if (controlExtra) {
- // permissions are now controlled by the original file permissions
-
- const bool permissionStrictPolicy =
- this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION");
-
- static const char* strictFiles[] = { "config", "postinst", "postrm",
- "preinst", "prerm" };
- std::set<std::string> setStrictFiles(
- strictFiles,
- strictFiles + sizeof(strictFiles) / sizeof(strictFiles[0]));
-
- // default
- control_tar.ClearPermissions();
-
- std::vector<std::string> controlExtraList;
- cmSystemTools::ExpandListArgument(controlExtra, controlExtraList);
- for (std::string const& i : controlExtraList) {
- std::string filenamename = cmsys::SystemTools::GetFilenameName(i);
- std::string localcopy = strGenWDIR + "/" + filenamename;
-
- if (permissionStrictPolicy) {
- control_tar.SetPermissions(setStrictFiles.count(filenamename)
- ? permission755
- : permission644);
- }
-
- // if we can copy the file, it means it does exist, let's add it:
- if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) {
- control_tar.Add(localcopy, strGenWDIR.length(), ".");
- }
- }
- }
+ const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS");
+ if (debian_build_ids && *debian_build_ids) {
+ controlValues["Build-Ids"] = debian_build_ids;
}
- // ar -r your-package-name.deb debian-binary control.tar.* data.tar.*
- // A debian package .deb is simply an 'ar' archive. The only subtle
- // difference is that debian uses the BSD ar style archive whereas most
- // Linux distro have a GNU ar.
- // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info
- std::string const outputDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- std::string const outputName = this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
- std::string const outputPath = outputDir + "/" + outputName;
- std::string const tlDir = strGenWDIR + "/";
- cmGeneratedFileStream debStream;
- debStream.Open(outputPath.c_str(), false, true);
- cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd");
+ DebGenerator gen(
+ Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"),
+ this->GetOption("GEN_DBGSYMDIR"),
- // uid/gid should be the one of the root user, and this root user has
- // always uid/gid equal to 0.
- deb.SetUIDAndGID(0u, 0u);
- deb.SetUNAMEAndGNAME("root", "root");
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
+ this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
+ this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, false, "",
+ false, "", false, "", nullptr,
+ this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
+ packageFiles);
- if (!deb.Add(tlDir + "debian-binary", tlDir.length()) ||
- !deb.Add(tlDir + "control.tar.gz", tlDir.length()) ||
- !deb.Add(tlDir + "data.tar" + compression_suffix, tlDir.length())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error creating debian package:"
- << std::endl
- << "#top level directory: " << outputDir << std::endl
- << "#file: " << outputName << std::endl
- << "#error:" << deb.GetError() << std::endl);
+ if (!gen.generate()) {
return 0;
}
return 1;
private:
int createDeb();
+ int createDbgsymDDeb();
+
std::vector<std::string> packageFiles;
};
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackExternalGenerator.h"
+
+#include "cmAlgorithms.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+
+#include "cmsys/FStream.hxx"
+
+#include <utility>
+#include <vector>
+
+int cmCPackExternalGenerator::InitializeInternal()
+{
+ this->SetOption("CPACK_EXTERNAL_KNOWN_VERSIONS", "1.0");
+
+ if (!this->ReadListFile("Internal/CPack/CPackExternal.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while executing CPackExternal.cmake" << std::endl);
+ return 0;
+ }
+
+ std::string major = this->GetOption("CPACK_EXTERNAL_SELECTED_MAJOR");
+ if (major == "1") {
+ this->Generator = cm::make_unique<cmCPackExternalVersion1Generator>(this);
+ }
+
+ return this->Superclass::InitializeInternal();
+}
+
+int cmCPackExternalGenerator::PackageFiles()
+{
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = " ";
+
+ std::string filename = "package.json";
+ if (!this->packageFileNames.empty()) {
+ filename = this->packageFileNames[0];
+ }
+
+ cmsys::ofstream fout(filename.c_str());
+ std::unique_ptr<Json::StreamWriter> jout(builder.newStreamWriter());
+
+ Json::Value root(Json::objectValue);
+
+ if (!this->Generator->WriteToJSON(root)) {
+ return 0;
+ }
+
+ if (jout->write(root, &fout)) {
+ return 0;
+ }
+
+ const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT");
+ if (packageScript && *packageScript) {
+ if (!cmSystemTools::FileIsFullPath(packageScript)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "CPACK_EXTERNAL_PACKAGE_SCRIPT does not contain a full file path"
+ << std::endl);
+ return 0;
+ }
+
+ int res = this->MakefileMap->ReadListFile(packageScript);
+
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+bool cmCPackExternalGenerator::SupportsComponentInstallation() const
+{
+ return true;
+}
+
+int cmCPackExternalGenerator::InstallProjectViaInstallCommands(
+ bool setDestDir, const std::string& tempInstallDirectory)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallProjectViaInstallCommands(
+ setDestDir, tempInstallDirectory);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::InstallProjectViaInstallScript(
+ bool setDestDir, const std::string& tempInstallDirectory)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallProjectViaInstallScript(
+ setDestDir, tempInstallDirectory);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::InstallProjectViaInstalledDirectories(
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallProjectViaInstalledDirectories(
+ setDestDir, tempInstallDirectory, default_dir_mode);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::RunPreinstallTarget(
+ const std::string& installProjectName, const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::RunPreinstallTarget(
+ installProjectName, installDirectory, globalGenerator, buildConfig);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::InstallCMakeProject(
+ bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode,
+ const std::string& component, bool componentInstall,
+ const std::string& installSubDirectory, const std::string& buildConfig,
+ std::string& absoluteDestFiles)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallCMakeProject(
+ setDestDir, installDirectory, baseTempInstallDirectory, default_dir_mode,
+ component, componentInstall, installSubDirectory, buildConfig,
+ absoluteDestFiles);
+ }
+
+ return 1;
+}
+
+bool cmCPackExternalGenerator::StagingEnabled() const
+{
+ return !cmSystemTools::IsOff(
+ this->GetOption("CPACK_EXTERNAL_ENABLE_STAGING"));
+}
+
+cmCPackExternalGenerator::cmCPackExternalVersionGenerator::
+ cmCPackExternalVersionGenerator(cmCPackExternalGenerator* parent)
+ : Parent(parent)
+{
+}
+
+int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteVersion(
+ Json::Value& root)
+{
+ root["formatVersionMajor"] = this->GetVersionMajor();
+ root["formatVersionMinor"] = this->GetVersionMinor();
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON(
+ Json::Value& root)
+{
+ if (!this->WriteVersion(root)) {
+ return 0;
+ }
+
+ const char* packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME");
+ if (packageName) {
+ root["packageName"] = packageName;
+ }
+
+ const char* packageVersion =
+ this->Parent->GetOption("CPACK_PACKAGE_VERSION");
+ if (packageVersion) {
+ root["packageVersion"] = packageVersion;
+ }
+
+ const char* packageDescriptionFile =
+ this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
+ if (packageDescriptionFile) {
+ root["packageDescriptionFile"] = packageDescriptionFile;
+ }
+
+ const char* packageDescriptionSummary =
+ this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY");
+ if (packageDescriptionSummary) {
+ root["packageDescriptionSummary"] = packageDescriptionSummary;
+ }
+
+ const char* buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG");
+ if (buildConfigCstr) {
+ root["buildConfig"] = buildConfigCstr;
+ }
+
+ const char* defaultDirectoryPermissions =
+ this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (defaultDirectoryPermissions && *defaultDirectoryPermissions) {
+ root["defaultDirectoryPermissions"] = defaultDirectoryPermissions;
+ }
+ if (cmSystemTools::IsInternallyOn(
+ this->Parent->GetOption("CPACK_SET_DESTDIR"))) {
+ root["setDestdir"] = true;
+ root["packagingInstallPrefix"] =
+ this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+ } else {
+ root["setDestdir"] = false;
+ }
+
+ root["stripFiles"] =
+ !cmSystemTools::IsOff(this->Parent->GetOption("CPACK_STRIP_FILES"));
+ root["warnOnAbsoluteInstallDestination"] =
+ this->Parent->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION");
+ root["errorOnAbsoluteInstallDestination"] =
+ this->Parent->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION");
+
+ Json::Value& projects = root["projects"] = Json::Value(Json::arrayValue);
+ for (auto& project : this->Parent->CMakeProjects) {
+ Json::Value jsonProject(Json::objectValue);
+
+ jsonProject["projectName"] = project.ProjectName;
+ jsonProject["component"] = project.Component;
+ jsonProject["directory"] = project.Directory;
+ jsonProject["subDirectory"] = project.SubDirectory;
+
+ Json::Value& installationTypes = jsonProject["installationTypes"] =
+ Json::Value(Json::arrayValue);
+ for (auto& installationType : project.InstallationTypes) {
+ installationTypes.append(installationType->Name);
+ }
+
+ Json::Value& components = jsonProject["components"] =
+ Json::Value(Json::arrayValue);
+ for (auto& component : project.Components) {
+ components.append(component->Name);
+ }
+
+ projects.append(jsonProject);
+ }
+
+ Json::Value& installationTypes = root["installationTypes"] =
+ Json::Value(Json::objectValue);
+ for (auto& installationType : this->Parent->InstallationTypes) {
+ Json::Value& jsonInstallationType =
+ installationTypes[installationType.first] =
+ Json::Value(Json::objectValue);
+
+ jsonInstallationType["name"] = installationType.second.Name;
+ jsonInstallationType["displayName"] = installationType.second.DisplayName;
+ jsonInstallationType["index"] = installationType.second.Index;
+ }
+
+ Json::Value& components = root["components"] =
+ Json::Value(Json::objectValue);
+ for (auto& component : this->Parent->Components) {
+ Json::Value& jsonComponent = components[component.first] =
+ Json::Value(Json::objectValue);
+
+ jsonComponent["name"] = component.second.Name;
+ jsonComponent["displayName"] = component.second.DisplayName;
+ if (component.second.Group) {
+ jsonComponent["group"] = component.second.Group->Name;
+ }
+ jsonComponent["isRequired"] = component.second.IsRequired;
+ jsonComponent["isHidden"] = component.second.IsHidden;
+ jsonComponent["isDisabledByDefault"] =
+ component.second.IsDisabledByDefault;
+ jsonComponent["isDownloaded"] = component.second.IsDownloaded;
+ jsonComponent["description"] = component.second.Description;
+ jsonComponent["archiveFile"] = component.second.ArchiveFile;
+
+ Json::Value& cmpInstallationTypes = jsonComponent["installationTypes"] =
+ Json::Value(Json::arrayValue);
+ for (auto& installationType : component.second.InstallationTypes) {
+ cmpInstallationTypes.append(installationType->Name);
+ }
+
+ Json::Value& dependencies = jsonComponent["dependencies"] =
+ Json::Value(Json::arrayValue);
+ for (auto& dep : component.second.Dependencies) {
+ dependencies.append(dep->Name);
+ }
+ }
+
+ Json::Value& groups = root["componentGroups"] =
+ Json::Value(Json::objectValue);
+ for (auto& group : this->Parent->ComponentGroups) {
+ Json::Value& jsonGroup = groups[group.first] =
+ Json::Value(Json::objectValue);
+
+ jsonGroup["name"] = group.second.Name;
+ jsonGroup["displayName"] = group.second.DisplayName;
+ jsonGroup["description"] = group.second.Description;
+ jsonGroup["isBold"] = group.second.IsBold;
+ jsonGroup["isExpandedByDefault"] = group.second.IsExpandedByDefault;
+ if (group.second.ParentGroup) {
+ jsonGroup["parentGroup"] = group.second.ParentGroup->Name;
+ }
+
+ Json::Value& subgroups = jsonGroup["subgroups"] =
+ Json::Value(Json::arrayValue);
+ for (auto& subgroup : group.second.Subgroups) {
+ subgroups.append(subgroup->Name);
+ }
+
+ Json::Value& groupComponents = jsonGroup["components"] =
+ Json::Value(Json::arrayValue);
+ for (auto& component : group.second.Components) {
+ groupComponents.append(component->Name);
+ }
+ }
+
+ return 1;
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackExternalGenerator_h
+#define cmCPackExternalGenerator_h
+
+#include "cmCPackGenerator.h"
+#include "cm_sys_stat.h"
+
+#include <memory>
+#include <string>
+
+class cmGlobalGenerator;
+namespace Json {
+class Value;
+}
+
+/** \class cmCPackExternalGenerator
+ * \brief A generator for CPack External packaging tools
+ */
+class cmCPackExternalGenerator : public cmCPackGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackExternalGenerator, cmCPackGenerator);
+
+ const char* GetOutputExtension() override { return ".json"; }
+
+protected:
+ int InitializeInternal() override;
+
+ int PackageFiles() override;
+
+ bool SupportsComponentInstallation() const override;
+
+ int InstallProjectViaInstallCommands(
+ bool setDestDir, const std::string& tempInstallDirectory) override;
+ int InstallProjectViaInstallScript(
+ bool setDestDir, const std::string& tempInstallDirectory) override;
+ int InstallProjectViaInstalledDirectories(
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode) override;
+
+ int RunPreinstallTarget(const std::string& installProjectName,
+ const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator,
+ const std::string& buildConfig) override;
+ int InstallCMakeProject(bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory,
+ const mode_t* default_dir_mode,
+ const std::string& component, bool componentInstall,
+ const std::string& installSubDirectory,
+ const std::string& buildConfig,
+ std::string& absoluteDestFiles) override;
+
+private:
+ bool StagingEnabled() const;
+
+ class cmCPackExternalVersionGenerator
+ {
+ public:
+ cmCPackExternalVersionGenerator(cmCPackExternalGenerator* parent);
+
+ virtual ~cmCPackExternalVersionGenerator() = default;
+
+ virtual int WriteToJSON(Json::Value& root);
+
+ protected:
+ virtual int GetVersionMajor() = 0;
+ virtual int GetVersionMinor() = 0;
+
+ int WriteVersion(Json::Value& root);
+
+ cmCPackExternalGenerator* Parent;
+ };
+
+ class cmCPackExternalVersion1Generator
+ : public cmCPackExternalVersionGenerator
+ {
+ public:
+ using cmCPackExternalVersionGenerator::cmCPackExternalVersionGenerator;
+
+ protected:
+ int GetVersionMajor() override { return 1; }
+ int GetVersionMinor() override { return 0; }
+ };
+
+ std::unique_ptr<cmCPackExternalVersionGenerator> Generator;
+};
+
+#endif
int cmCPackFreeBSDGenerator::PackageFiles()
{
- if (!this->ReadListFile("CPackFreeBSD.cmake")) {
+ if (!this->ReadListFile("Internal/CPack/CPackFreeBSD.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackFreeBSD.cmake" << std::endl);
return 0;
if (!resB || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/InstallOutput.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << ic << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
return 0;
}
files = gl.GetFiles();
- std::vector<std::string>::iterator gfit;
- std::vector<cmsys::RegularExpression>::iterator regIt;
for (std::string const& gf : files) {
bool skip = false;
std::string inFile = gf;
inFile += '/';
}
for (cmsys::RegularExpression& reg : ignoreFilesRegex) {
- if (reg.find(inFile.c_str())) {
+ if (reg.find(inFile)) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Ignore file: " << inFile << std::endl);
skip = true;
++it;
std::string installProjectName = *it;
++it;
- std::string installComponent = *it;
+ cmCPackInstallCMakeProject project;
+
+ project.Directory = installDirectory;
+ project.ProjectName = installProjectName;
+ project.Component = *it;
++it;
- std::string installSubDirectory = *it;
- std::string installFile = installDirectory + "/cmake_install.cmake";
+ project.SubDirectory = *it;
std::vector<std::string> componentsVector;
* - the user did not request Monolithic install
* (this works at CPack time too)
*/
- if (this->SupportsComponentInstallation() &
+ if (this->SupportsComponentInstallation() &&
!(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) {
// Determine the installation types for this project (if provided).
std::string installTypesVar = "CPACK_" +
- cmSystemTools::UpperCase(installComponent) + "_INSTALL_TYPES";
+ cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES";
const char* installTypes = this->GetOption(installTypesVar);
if (installTypes && *installTypes) {
std::vector<std::string> installTypesVector;
cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
for (std::string const& installType : installTypesVector) {
- this->GetInstallationType(installProjectName, installType);
+ project.InstallationTypes.push_back(
+ this->GetInstallationType(project.ProjectName, installType));
}
}
// Determine the set of components that will be used in this project
std::string componentsVar =
- "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(installComponent);
+ "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component);
const char* components = this->GetOption(componentsVar);
if (components && *components) {
cmSystemTools::ExpandListArgument(components, componentsVector);
for (std::string const& comp : componentsVector) {
- GetComponent(installProjectName, comp);
+ project.Components.push_back(
+ this->GetComponent(project.ProjectName, comp));
}
componentInstall = true;
}
}
if (componentsVector.empty()) {
- componentsVector.push_back(installComponent);
+ componentsVector.push_back(project.Component);
}
const char* buildConfigCstr = this->GetOption("CPACK_BUILD_CONFIG");
// on windows.
cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());
- // Does this generator require pre-install?
- if (const char* preinstall =
- globalGenerator->GetPreinstallTargetName()) {
- std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand(
- preinstall, buildConfig, "", false);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Install command: " << buildCommand << std::endl);
- cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Run preinstall target for: " << installProjectName
- << std::endl);
- std::string output;
- int retVal = 1;
- bool resB = cmSystemTools::RunSingleCommand(
- buildCommand.c_str(), &output, &output, &retVal,
- installDirectory.c_str(), this->GeneratorVerbose,
- cmDuration::zero());
- if (!resB || retVal) {
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/PreinstallOutput.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << buildCommand << std::endl
- << "# Directory: " << installDirectory << std::endl
- << "# Output:" << std::endl
- << output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem running install command: "
- << buildCommand << std::endl
- << "Please check " << tmpFile << " for errors"
- << std::endl);
- return 0;
- }
+ if (!this->RunPreinstallTarget(project.ProjectName, project.Directory,
+ globalGenerator, buildConfig)) {
+ return 0;
}
+
delete globalGenerator;
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install project: " << installProjectName << std::endl);
+ "- Install project: " << project.ProjectName << std::endl);
// Run the installation for each component
for (std::string const& component : componentsVector) {
- std::string tempInstallDirectory = baseTempInstallDirectory;
- installComponent = component;
- if (componentInstall) {
- cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install component: " << installComponent
- << std::endl);
+ if (!this->InstallCMakeProject(
+ setDestDir, project.Directory, baseTempInstallDirectory,
+ default_dir_mode, component, componentInstall,
+ project.SubDirectory, buildConfig, absoluteDestFiles)) {
+ return 0;
}
+ }
- cmake cm(cmake::RoleScript);
- cm.SetHomeDirectory("");
- cm.SetHomeOutputDirectory("");
- cm.GetCurrentSnapshot().SetDefaultDefinitions();
- cm.AddCMakePaths();
- cm.SetProgressCallback(cmCPackGeneratorProgress, this);
- cm.SetTrace(this->Trace);
- cm.SetTraceExpand(this->TraceExpand);
- cmGlobalGenerator gg(&cm);
- cmMakefile mf(&gg, cm.GetCurrentSnapshot());
- if (!installSubDirectory.empty() && installSubDirectory != "/" &&
- installSubDirectory != ".") {
- tempInstallDirectory += installSubDirectory;
- }
- if (componentInstall) {
- tempInstallDirectory += "/";
- // Some CPack generators would rather chose
- // the local installation directory suffix.
- // Some (e.g. RPM) use
- // one install directory for each component **GROUP**
- // instead of the default
- // one install directory for each component.
- tempInstallDirectory +=
- GetComponentInstallDirNameSuffix(installComponent);
- if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
- tempInstallDirectory += "/";
- tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
- }
- }
+ this->CMakeProjects.push_back(project);
+ }
+ }
+ this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
+ absoluteDestFiles.c_str());
+ return 1;
+}
- const char* default_dir_inst_permissions =
- this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
- if (default_dir_inst_permissions && *default_dir_inst_permissions) {
- mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
- default_dir_inst_permissions);
- }
+int cmCPackGenerator::RunPreinstallTarget(
+ const std::string& installProjectName, const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
+{
+ // Does this generator require pre-install?
+ if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) {
+ std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand(
+ preinstall, buildConfig, "", false);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Install command: " << buildCommand << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Run preinstall target for: " << installProjectName
+ << std::endl);
+ std::string output;
+ int retVal = 1;
+ bool resB = cmSystemTools::RunSingleCommand(
+ buildCommand.c_str(), &output, &output, &retVal,
+ installDirectory.c_str(), this->GeneratorVerbose, cmDuration::zero());
+ if (!resB || retVal) {
+ std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ tmpFile += "/PreinstallOutput.log";
+ cmGeneratedFileStream ofs(tmpFile);
+ ofs << "# Run command: " << buildCommand << std::endl
+ << "# Directory: " << installDirectory << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running install command: "
+ << buildCommand << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
+ return 0;
+ }
+ }
- if (!setDestDir) {
- tempInstallDirectory += this->GetPackagingInstallPrefix();
- }
+ return 1;
+}
- if (setDestDir) {
- // For DESTDIR based packaging, use the *project*
- // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
- // value of the project's CMAKE_INSTALL_PREFIX is sent in here as
- // the value of the CPACK_INSTALL_PREFIX variable.
- //
- // If DESTDIR has been 'internally set ON' this means that
- // the underlying CPack specific generator did ask for that
- // In this case we may override CPACK_INSTALL_PREFIX with
- // CPACK_PACKAGING_INSTALL_PREFIX
- // I know this is tricky and awkward but it's the price for
- // CPACK_SET_DESTDIR backward compatibility.
- if (cmSystemTools::IsInternallyOn(
- this->GetOption("CPACK_SET_DESTDIR"))) {
- this->SetOption("CPACK_INSTALL_PREFIX",
- this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
- }
- std::string dir;
- if (this->GetOption("CPACK_INSTALL_PREFIX")) {
- dir += this->GetOption("CPACK_INSTALL_PREFIX");
- }
- mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str());
+int cmCPackGenerator::InstallCMakeProject(
+ bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode,
+ const std::string& component, bool componentInstall,
+ const std::string& installSubDirectory, const std::string& buildConfig,
+ std::string& absoluteDestFiles)
+{
+ std::string tempInstallDirectory = baseTempInstallDirectory;
+ std::string installFile = installDirectory + "/cmake_install.cmake";
- cmCPackLogger(
- cmCPackLog::LOG_DEBUG,
- "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf.AddDefinition)"
- << std::endl);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
- << std::endl);
-
- // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
- // exists:
- //
- if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) {
- dir = tempInstallDirectory + dir;
- } else {
- dir = tempInstallDirectory + "/" + dir;
- }
- /*
- * We must re-set DESTDIR for each component
- * We must not add the CPACK_INSTALL_PREFIX part because
- * it will be added using the override of CMAKE_INSTALL_PREFIX
- * The main reason for this awkward trick is that
- * are using DESTDIR for 2 different reasons:
- * - Because it was asked by the CPack Generator or the user
- * using CPACK_SET_DESTDIR
- * - Because it was already used for component install
- * in order to put things in subdirs...
- */
- cmSystemTools::PutEnv(std::string("DESTDIR=") +
- tempInstallDirectory);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Creating directory: '" << dir << "'" << std::endl);
+ if (componentInstall) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install component: " << component << std::endl);
+ }
- if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
- cmCPackLogger(
- cmCPackLog::LOG_ERROR,
- "Problem creating temporary directory: " << dir << std::endl);
- return 0;
- }
- } else {
- mf.AddDefinition("CMAKE_INSTALL_PREFIX",
- tempInstallDirectory.c_str());
+ cmake cm(cmake::RoleScript);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
+ cm.AddCMakePaths();
+ cm.SetProgressCallback(cmCPackGeneratorProgress, this);
+ cm.SetTrace(this->Trace);
+ cm.SetTraceExpand(this->TraceExpand);
+ cmGlobalGenerator gg(&cm);
+ cmMakefile mf(&gg, cm.GetCurrentSnapshot());
+ if (!installSubDirectory.empty() && installSubDirectory != "/" &&
+ installSubDirectory != ".") {
+ tempInstallDirectory += installSubDirectory;
+ }
+ if (componentInstall) {
+ tempInstallDirectory += "/";
+ // Some CPack generators would rather chose
+ // the local installation directory suffix.
+ // Some (e.g. RPM) use
+ // one install directory for each component **GROUP**
+ // instead of the default
+ // one install directory for each component.
+ tempInstallDirectory += GetComponentInstallDirNameSuffix(component);
+ if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
+ tempInstallDirectory += "/";
+ tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ }
+ }
- if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
- default_dir_mode)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem creating temporary directory: "
- << tempInstallDirectory << std::endl);
- return 0;
- }
+ const char* default_dir_inst_permissions =
+ this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (default_dir_inst_permissions && *default_dir_inst_permissions) {
+ mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
+ default_dir_inst_permissions);
+ }
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Using non-DESTDIR install... (mf.AddDefinition)"
- << std::endl);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Setting CMAKE_INSTALL_PREFIX to '"
- << tempInstallDirectory << "'" << std::endl);
- }
+ if (!setDestDir) {
+ tempInstallDirectory += this->GetPackagingInstallPrefix();
+ }
- if (!buildConfig.empty()) {
- mf.AddDefinition("BUILD_TYPE", buildConfig.c_str());
- }
- std::string installComponentLowerCase =
- cmSystemTools::LowerCase(installComponent);
- if (installComponentLowerCase != "all") {
- mf.AddDefinition("CMAKE_INSTALL_COMPONENT",
- installComponent.c_str());
- }
+ if (setDestDir) {
+ // For DESTDIR based packaging, use the *project*
+ // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
+ // value of the project's CMAKE_INSTALL_PREFIX is sent in here as
+ // the value of the CPACK_INSTALL_PREFIX variable.
+ //
+ // If DESTDIR has been 'internally set ON' this means that
+ // the underlying CPack specific generator did ask for that
+ // In this case we may override CPACK_INSTALL_PREFIX with
+ // CPACK_PACKAGING_INSTALL_PREFIX
+ // I know this is tricky and awkward but it's the price for
+ // CPACK_SET_DESTDIR backward compatibility.
+ if (cmSystemTools::IsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) {
+ this->SetOption("CPACK_INSTALL_PREFIX",
+ this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
+ }
+ std::string dir;
+ if (this->GetOption("CPACK_INSTALL_PREFIX")) {
+ dir += this->GetOption("CPACK_INSTALL_PREFIX");
+ }
+ mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str());
- // strip on TRUE, ON, 1, one or several file names, but not on
- // FALSE, OFF, 0 and an empty string
- if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES"))) {
- mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1");
- }
- // Remember the list of files before installation
- // of the current component (if we are in component install)
- std::string const& InstallPrefix = tempInstallDirectory;
- std::vector<std::string> filesBefore;
- std::string findExpr = tempInstallDirectory;
- if (componentInstall) {
- cmsys::Glob glB;
- findExpr += "/*";
- glB.RecurseOn();
- glB.SetRecurseListDirs(true);
- glB.FindFiles(findExpr);
- filesBefore = glB.GetFiles();
- std::sort(filesBefore.begin(), filesBefore.end());
- }
+ cmCPackLogger(
+ cmCPackLog::LOG_DEBUG,
+ "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf.AddDefinition)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
+ << std::endl);
+
+ // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
+ // exists:
+ //
+ if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) {
+ dir = tempInstallDirectory + dir;
+ } else {
+ dir = tempInstallDirectory + "/" + dir;
+ }
+ /*
+ * We must re-set DESTDIR for each component
+ * We must not add the CPACK_INSTALL_PREFIX part because
+ * it will be added using the override of CMAKE_INSTALL_PREFIX
+ * The main reason for this awkward trick is that
+ * are using DESTDIR for 2 different reasons:
+ * - Because it was asked by the CPack Generator or the user
+ * using CPACK_SET_DESTDIR
+ * - Because it was already used for component install
+ * in order to put things in subdirs...
+ */
+ cmSystemTools::PutEnv(std::string("DESTDIR=") + tempInstallDirectory);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Creating directory: '" << dir << "'" << std::endl);
- // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION
- // then forward request to cmake_install.cmake script
- if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) {
- mf.AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
- }
- // If current CPack generator does support
- // ABSOLUTE INSTALL DESTINATION or CPack has been asked for
- // then ask cmake_install.cmake script to error out
- // as soon as it occurs (before installing file)
- if (!SupportsAbsoluteDestination() ||
- this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
- mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
- }
- // do installation
- int res = mf.ReadListFile(installFile.c_str());
- // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
- // to CPack (may be used by generators like CPack RPM or DEB)
- // in order to transparently handle ABSOLUTE PATH
- if (mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
- mf.AddDefinition(
- "CPACK_ABSOLUTE_DESTINATION_FILES",
- mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES"));
- }
+ if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating temporary directory: " << dir
+ << std::endl);
+ return 0;
+ }
+ } else {
+ mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());
- // Now rebuild the list of files after installation
- // of the current component (if we are in component install)
- if (componentInstall) {
- cmsys::Glob glA;
- glA.RecurseOn();
- glA.SetRecurseListDirs(true);
- glA.SetRecurseThroughSymlinks(false);
- glA.FindFiles(findExpr);
- std::vector<std::string> filesAfter = glA.GetFiles();
- std::sort(filesAfter.begin(), filesAfter.end());
- std::vector<std::string>::iterator diff;
- std::vector<std::string> result(filesAfter.size());
- diff = std::set_difference(filesAfter.begin(), filesAfter.end(),
- filesBefore.begin(), filesBefore.end(),
- result.begin());
-
- std::vector<std::string>::iterator fit;
- std::string localFileName;
- // Populate the File field of each component
- for (fit = result.begin(); fit != diff; ++fit) {
- localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit);
- localFileName =
- localFileName.substr(localFileName.find_first_not_of('/'));
- Components[installComponent].Files.push_back(localFileName);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Adding file <"
- << localFileName << "> to component <"
- << installComponent << ">" << std::endl);
- }
- }
+ if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
+ default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating temporary directory: "
+ << tempInstallDirectory << std::endl);
+ return 0;
+ }
- if (nullptr != mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
- if (!absoluteDestFiles.empty()) {
- absoluteDestFiles += ";";
- }
- absoluteDestFiles +=
- mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Got some ABSOLUTE DESTINATION FILES: "
- << absoluteDestFiles << std::endl);
- // define component specific var
- if (componentInstall) {
- std::string absoluteDestFileComponent =
- std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" +
- GetComponentInstallDirNameSuffix(installComponent);
- if (nullptr != this->GetOption(absoluteDestFileComponent)) {
- std::string absoluteDestFilesListComponent =
- this->GetOption(absoluteDestFileComponent);
- absoluteDestFilesListComponent += ";";
- absoluteDestFilesListComponent +=
- mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
- this->SetOption(absoluteDestFileComponent,
- absoluteDestFilesListComponent.c_str());
- } else {
- this->SetOption(
- absoluteDestFileComponent,
- mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
- }
- }
- }
- if (cmSystemTools::GetErrorOccuredFlag() || !res) {
- return 0;
- }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Using non-DESTDIR install... (mf.AddDefinition)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory
+ << "'" << std::endl);
+ }
+
+ if (!buildConfig.empty()) {
+ mf.AddDefinition("BUILD_TYPE", buildConfig.c_str());
+ }
+ std::string installComponentLowerCase = cmSystemTools::LowerCase(component);
+ if (installComponentLowerCase != "all") {
+ mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component.c_str());
+ }
+
+ // strip on TRUE, ON, 1, one or several file names, but not on
+ // FALSE, OFF, 0 and an empty string
+ if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES"))) {
+ mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1");
+ }
+ // Remember the list of files before installation
+ // of the current component (if we are in component install)
+ std::string const& InstallPrefix = tempInstallDirectory;
+ std::vector<std::string> filesBefore;
+ std::string findExpr = tempInstallDirectory;
+ if (componentInstall) {
+ cmsys::Glob glB;
+ findExpr += "/*";
+ glB.RecurseOn();
+ glB.SetRecurseListDirs(true);
+ glB.FindFiles(findExpr);
+ filesBefore = glB.GetFiles();
+ std::sort(filesBefore.begin(), filesBefore.end());
+ }
+
+ // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION
+ // then forward request to cmake_install.cmake script
+ if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) {
+ mf.AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
+ }
+ // If current CPack generator does support
+ // ABSOLUTE INSTALL DESTINATION or CPack has been asked for
+ // then ask cmake_install.cmake script to error out
+ // as soon as it occurs (before installing file)
+ if (!SupportsAbsoluteDestination() ||
+ this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
+ mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
+ }
+ // do installation
+ int res = mf.ReadListFile(installFile.c_str());
+ // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
+ // to CPack (may be used by generators like CPack RPM or DEB)
+ // in order to transparently handle ABSOLUTE PATH
+ if (mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
+ mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES",
+ mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES"));
+ }
+
+ // Now rebuild the list of files after installation
+ // of the current component (if we are in component install)
+ if (componentInstall) {
+ cmsys::Glob glA;
+ glA.RecurseOn();
+ glA.SetRecurseListDirs(true);
+ glA.SetRecurseThroughSymlinks(false);
+ glA.FindFiles(findExpr);
+ std::vector<std::string> filesAfter = glA.GetFiles();
+ std::sort(filesAfter.begin(), filesAfter.end());
+ std::vector<std::string>::iterator diff;
+ std::vector<std::string> result(filesAfter.size());
+ diff = std::set_difference(filesAfter.begin(), filesAfter.end(),
+ filesBefore.begin(), filesBefore.end(),
+ result.begin());
+
+ std::vector<std::string>::iterator fit;
+ std::string localFileName;
+ // Populate the File field of each component
+ for (fit = result.begin(); fit != diff; ++fit) {
+ localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit);
+ localFileName =
+ localFileName.substr(localFileName.find_first_not_of('/'));
+ Components[component].Files.push_back(localFileName);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Adding file <" << localFileName << "> to component <"
+ << component << ">" << std::endl);
+ }
+ }
+
+ if (nullptr != mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
+ if (!absoluteDestFiles.empty()) {
+ absoluteDestFiles += ";";
+ }
+ absoluteDestFiles += mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Got some ABSOLUTE DESTINATION FILES: " << absoluteDestFiles
+ << std::endl);
+ // define component specific var
+ if (componentInstall) {
+ std::string absoluteDestFileComponent =
+ std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" +
+ GetComponentInstallDirNameSuffix(component);
+ if (nullptr != this->GetOption(absoluteDestFileComponent)) {
+ std::string absoluteDestFilesListComponent =
+ this->GetOption(absoluteDestFileComponent);
+ absoluteDestFilesListComponent += ";";
+ absoluteDestFilesListComponent +=
+ mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
+ this->SetOption(absoluteDestFileComponent,
+ absoluteDestFilesListComponent.c_str());
+ } else {
+ this->SetOption(absoluteDestFileComponent,
+ mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
}
}
}
- this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
- absoluteDestFiles.c_str());
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
+ return 0;
+ }
return 1;
}
if (installTypes && *installTypes) {
std::vector<std::string> installTypesVector;
cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
- std::vector<std::string>::iterator installTypesIt;
for (std::string const& installType : installTypesVector) {
component->InstallationTypes.push_back(
this->GetInstallationType(projectName, installType));
if (depends && *depends) {
std::vector<std::string> dependsVector;
cmSystemTools::ExpandListArgument(depends, dependsVector);
- std::vector<std::string>::iterator dependIt;
for (std::string const& depend : dependsVector) {
cmCPackComponent* child = GetComponent(projectName, depend);
component->Dependencies.push_back(child);
#include "cm_sys_stat.h"
class cmCPackLog;
+class cmGlobalGenerator;
class cmInstalledFile;
class cmMakefile;
bool setDestDir, const std::string& tempInstallDirectory,
const mode_t* default_dir_mode);
+ virtual int RunPreinstallTarget(const std::string& installProjectName,
+ const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator,
+ const std::string& buildConfig);
+ virtual int InstallCMakeProject(
+ bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory,
+ const mode_t* default_dir_mode, const std::string& component,
+ bool componentInstall, const std::string& installSubDirectory,
+ const std::string& buildConfig, std::string& absoluteDestFiles);
+
/**
* The various level of support of
* CPACK_SET_DESTDIR used by the generator.
*/
std::vector<std::string> files;
+ std::vector<cmCPackInstallCMakeProject> CMakeProjects;
std::map<std::string, cmCPackInstallationType> InstallationTypes;
/**
* The set of components.
bool Trace;
bool TraceExpand;
-private:
cmMakefile* MakefileMap;
};
# include "cmCPackFreeBSDGenerator.h"
#endif
#include "cmCPackDebGenerator.h"
+#include "cmCPackExternalGenerator.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmCPackNSISGenerator.h"
this->RegisterGenerator("NuGet", "NuGet packages",
cmCPackNuGetGenerator::CreateGenerator);
}
+ if (cmCPackExternalGenerator::CanGenerate()) {
+ this->RegisterGenerator("External", "CPack External packages",
+ cmCPackExternalGenerator::CreateGenerator);
+ }
#ifdef __APPLE__
if (cmCPackDragNDropGenerator::CanGenerate()) {
this->RegisterGenerator("DragNDrop", "Mac OSX Drag And Drop",
nsisCmd.c_str(), &output, &output, &retVal, nullptr,
this->GeneratorVerbose, cmDuration::zero());
if (!res || retVal) {
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << nsisCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
std::string tmpFile = topDir ? topDir : ".";
tmpFile += "/NSISOutput.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << nsisCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
// Find a ZIP program
if (!this->IsSet("ZIP_EXECUTABLE")) {
- this->ReadListFile("CPackZIP.cmake");
+ this->ReadListFile("Internal/CPack/CPackZIP.cmake");
if (!this->IsSet("ZIP_EXECUTABLE")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
cmSystemTools::IsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES"));
unsigned long totalSize = 0;
{ // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(zipListFileName.c_str());
+ cmGeneratedFileStream out(zipListFileName);
for (std::string const& file : component->Files) {
if (needQuotesInFile) {
out << "\"";
if (!res || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/CompressZip.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << cmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
this->SetOption("CPACK_NUGET_ORDINAL_MONOLITIC", "TRUE");
}
- auto retval = this->ReadListFile("CPackNuGet.cmake");
+ auto retval = this->ReadListFile("Internal/CPack/CPackNuGet.cmake");
if (retval) {
AddGeneratedPackageNames();
} else {
tmpFile += "/ProductBuildOutput.log";
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
- std::string output, error_output;
+ std::string output;
int retVal = 1;
bool res = cmSystemTools::RunSingleCommand(
- command.c_str(), &output, &error_output, &retVal, nullptr,
+ command.c_str(), &output, &output, &retVal, nullptr,
this->GeneratorVerbose, cmDuration::zero());
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl);
if (!res || retVal) {
component_path += packageName;
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
- if (!this->ReadListFile("CPackRPM.cmake")) {
+ if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackRPM.cmake" << std::endl);
retval = 0;
component_path.c_str());
}
- if (this->ReadListFile("CPackRPM.cmake")) {
+ if (this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
AddGeneratedPackageNames();
} else {
cmCPackLogger(cmCPackLog::LOG_ERROR,
#include "cmCTest.h"
#include "cmCTestTestHandler.h"
#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
#include "cmake.h"
if (this->BuildNoCMake) {
// Make the generator available for the Build call below.
- cm.SetGlobalGenerator(cm.CreateGlobalGenerator(this->BuildGenerator));
- cm.SetGeneratorPlatform(this->BuildGeneratorPlatform);
- cm.SetGeneratorToolset(this->BuildGeneratorToolset);
+ cmGlobalGenerator* gen = cm.CreateGlobalGenerator(this->BuildGenerator);
+ cm.SetGlobalGenerator(gen);
+ if (!this->BuildGeneratorPlatform.empty()) {
+ cmMakefile mf(gen, cm.GetCurrentSnapshot());
+ if (!gen->SetGeneratorPlatform(this->BuildGeneratorPlatform, &mf)) {
+ return 1;
+ }
+ }
// Load the cache to make CMAKE_MAKE_PROGRAM available.
cm.LoadCache(this->BinaryDir);
"instantiated from ",
"candidates are:",
": warning",
+ ": WARNING",
": \\(Warning\\)",
": note",
"Note:",
std::string const& useLaunchers =
this->CTest->GetCTestConfiguration("UseLaunchers");
- this->UseCTestLaunch = cmSystemTools::IsOn(useLaunchers.c_str());
+ this->UseCTestLaunch = cmSystemTools::IsOn(useLaunchers);
// Create a last build log
cmGeneratedFileStream ofs;
for (cmCTestCompileErrorWarningRex& rit :
this->ErrorWarningFileLineRegex) {
cmsys::RegularExpression* re = &rit.RegularExpression;
- if (re->find(cm->Text.c_str())) {
+ if (re->find(cm->Text)) {
cm->SourceFile = re->match(rit.FileIndex);
// At this point we need to make this->SourceFile relative to
// the source root of the project, so cvs links will work
// Give some testing configuration information to the launcher.
std::string fname = this->Handler->CTestLaunchDir;
fname += "/CTestLaunchConfig.cmake";
- cmGeneratedFileStream fout(fname.c_str());
+ cmGeneratedFileStream fout(fname);
std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory");
fout << "set(CTEST_SOURCE_DIRECTORY \"" << srcdir << "\")\n";
}
fname += "/Custom";
fname += purpose;
fname += ".txt";
- cmGeneratedFileStream fout(fname.c_str());
+ cmGeneratedFileStream fout(fname);
for (std::string const& m : matchers) {
fout << m << "\n";
}
if (line.empty()) {
// Ignore empty line; probably style 2
- } else if (st1re1.find(line.c_str())) {
+ } else if (st1re1.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 1;
}
actualSourceFile.clear();
sourceFile = st1re1.match(2);
- } else if (st1re2.find(line.c_str())) {
+ } else if (st1re2.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 1;
}
}
gcovFile = st1re2.match(1);
- } else if (st2re1.find(line.c_str())) {
+ } else if (st2re1.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
actualSourceFile.clear();
sourceFile = st2re1.match(1);
- } else if (st2re2.find(line.c_str())) {
+ } else if (st2re2.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
cont->Error++;
break;
}
- } else if (st2re3.find(line.c_str())) {
+ } else if (st2re3.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
}
gcovFile = st2re3.match(2);
- } else if (st2re4.find(line.c_str())) {
+ } else if (st2re4.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
"Warning: " << st2re4.match(1)
<< " had unexpected EOF" << std::endl,
this->Quiet);
- } else if (st2re5.find(line.c_str())) {
+ } else if (st2re5.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
"Warning: Cannot open file: " << st2re5.match(1)
<< std::endl,
this->Quiet);
- } else if (st2re6.find(line.c_str())) {
+ } else if (st2re6.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
std::string init_submodules =
this->CTest->GetCTestConfiguration("GITInitSubmodules");
- if (cmSystemTools::IsOn(init_submodules.c_str())) {
+ if (cmSystemTools::IsOn(init_submodules)) {
char const* git_submodule_init[] = { git, "submodule", "init", nullptr };
ret = this->RunChild(git_submodule_init, &submodule_out, &submodule_err,
top_dir.c_str());
cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(),
this->Quiet);
} else {
- const char* bdir =
+ std::string const& bdir =
this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
- if (bdir) {
+ if (!bdir.empty()) {
this->CTest->SetCTestConfiguration(
"BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(),
this->Quiet);
logXML += ".xml";
// Use cmGeneratedFileStream to atomically create the report file.
- cmGeneratedFileStream fxml(logXML.c_str());
+ cmGeneratedFileStream fxml(logXML);
cmXMLWriter xml(fxml, 2);
cmXMLElement e2(xml, "Failure");
e2.Attribute("type", this->IsError() ? "Error" : "Warning");
std::vector<cmsys::RegularExpression>& regexps)
{
for (cmsys::RegularExpression& r : regexps) {
- if (r.find(line.c_str())) {
+ if (r.find(line)) {
return true;
}
}
g.FindFiles(ofile);
if (g.GetFiles().empty()) {
std::string log = "Cannot find memory tester output file: " + ofile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl);
+ cmCTestLog(this->CTest, WARNING, log << std::endl);
ofile.clear();
} else {
files = g.GetFiles();
}
} else if (!cmSystemTools::FileExists(ofile)) {
std::string log = "Cannot find memory tester output file: " + ofile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl);
+ cmCTestLog(this->CTest, WARNING, log << std::endl);
ofile.clear();
}
files.push_back(std::move(ofile));
#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
#include "cmsys/FStream.hxx"
-#include "cmsys/String.hxx"
#include "cmsys/SystemInformation.hxx"
#include <algorithm>
this->RunningCount = 0;
this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable();
this->HaveAffinity = this->ProcessorsAvailable.size();
- this->StopTimePassed = false;
this->HasCycles = false;
this->SerialTestRunning = false;
}
bool cmCTestMultiProcessHandler::StartTestProcess(int test)
{
- std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime();
- if (stop_time != std::chrono::system_clock::time_point() &&
- stop_time <= std::chrono::system_clock::now()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "The stop time has been passed. "
- "Stopping all tests."
- << std::endl);
- this->StopTimePassed = true;
- return false;
- }
-
if (this->HaveAffinity && this->Properties[test]->WantAffinity) {
size_t needProcessors = this->GetProcessorsUsed(test);
if (needProcessors > this->ProcessorsAvailable.size()) {
this->Properties[test]->Directory + " : " +
std::strerror(workdir.GetLastResult()));
} else {
- if (testRun->StartTest(this->Total)) {
+ if (testRun->StartTest(this->Completed, this->Total)) {
return true;
}
}
return false;
}
+bool cmCTestMultiProcessHandler::CheckStopTimePassed()
+{
+ if (!this->StopTimePassed) {
+ std::chrono::system_clock::time_point stop_time =
+ this->CTest->GetStopTime();
+ if (stop_time != std::chrono::system_clock::time_point() &&
+ stop_time <= std::chrono::system_clock::now()) {
+ this->SetStopTimePassed();
+ }
+ }
+ return this->StopTimePassed;
+}
+
+void cmCTestMultiProcessHandler::SetStopTimePassed()
+{
+ if (!this->StopTimePassed) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "The stop time has been passed. "
+ "Stopping all tests."
+ << std::endl);
+ this->StopTimePassed = true;
+ }
+}
+
void cmCTestMultiProcessHandler::LockResources(int index)
{
this->LockedResources.insert(
return;
}
+ if (this->CheckStopTimePassed()) {
+ return;
+ }
+
size_t numToStart = 0;
if (this->RunningCount < this->ParallelLevel) {
}
if (testLoadOk && processors <= numToStart && this->StartTest(test)) {
- if (this->StopTimePassed) {
- return;
- }
-
numToStart -= processors;
} else if (numToStart == 0) {
break;
auto properties = runner->GetTestProperties();
bool testResult = runner->EndTest(this->Completed, this->Total, started);
+ if (runner->TimedOutForStopTime()) {
+ this->SetStopTimePassed();
+ }
if (started) {
- if (runner->StartAgain()) {
+ if (!this->StopTimePassed && runner->StartAgain(this->Completed)) {
this->Completed--; // remove the completed test because run again
return;
}
if (line == "---") {
break;
}
- std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' ');
+ std::vector<std::string> parts = cmSystemTools::SplitString(line, ' ');
// Format: <name> <previous_runs> <avg_cost>
if (parts.size() < 3) {
break;
break;
}
- std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' ');
+ std::vector<std::string> parts = cmSystemTools::SplitString(line, ' ');
// Probably an older version of the file, will be fixed next run
if (parts.size() < 3) {
inline size_t GetProcessorsUsed(int index);
std::string GetName(int index);
+ bool CheckStopTimePassed();
+ void SetStopTimePassed();
+
void LockResources(int index);
void UnlockResources(int index);
// map from test number to set of depend tests
size_t RunningCount;
std::set<size_t> ProcessorsAvailable;
size_t HaveAffinity;
- bool StopTimePassed;
+ bool StopTimePassed = false;
// list of test properties (indices concurrent to the test map)
PropertiesMap Properties;
std::map<int, bool> TestRunningMap;
// Check for TIMEOUT_AFTER_MATCH property.
if (!this->TestProperties->TimeoutRegularExpressions.empty()) {
for (auto& reg : this->TestProperties->TimeoutRegularExpressions) {
- if (reg.first.find(this->ProcessOutput.c_str())) {
+ if (reg.first.find(this->ProcessOutput)) {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
this->GetIndex()
<< ": "
bool passed = true;
cmProcess::State res =
started ? this->TestProcess->GetProcessStatus() : cmProcess::State::Error;
+ if (res != cmProcess::State::Expired) {
+ this->TimeoutIsForStopTime = false;
+ }
int retVal = this->TestProcess->GetExitValue();
bool forceFail = false;
bool skipped = false;
this->FailedDependencies.empty()) {
bool found = false;
for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
- if (pass.first.find(this->ProcessOutput.c_str())) {
+ if (pass.first.find(this->ProcessOutput)) {
found = true;
reason = "Required regular expression found.";
break;
if (!this->TestProperties->ErrorRegularExpressions.empty() &&
this->FailedDependencies.empty()) {
for (auto& pass : this->TestProperties->ErrorRegularExpressions) {
- if (pass.first.find(this->ProcessOutput.c_str())) {
+ if (pass.first.find(this->ProcessOutput)) {
reason = "Error regular expression found in output.";
reason += " Regex=[";
reason += pass.second;
}
}
}
+ std::ostringstream outputStream;
if (res == cmProcess::State::Exited) {
bool success = !forceFail &&
(retVal == 0 ||
} else if ((success && !this->TestProperties->WillFail) ||
(!success && this->TestProperties->WillFail)) {
this->TestResult.Status = cmCTestTestHandler::COMPLETED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed ");
+ outputStream << " Passed ";
} else {
this->TestResult.Status = cmCTestTestHandler::FAILED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason);
+ outputStream << "***Failed " << reason;
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
}
} else if (res == cmProcess::State::Expired) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout ");
+ outputStream << "***Timeout ";
this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
} else if (res == cmProcess::State::Exception) {
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
+ outputStream << "***Exception: ";
this->TestResult.ExceptionStatus =
this->TestProcess->GetExitExceptionString();
switch (this->TestProcess->GetExitException()) {
case cmProcess::Exception::Fault:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
+ outputStream << "SegFault";
this->TestResult.Status = cmCTestTestHandler::SEGFAULT;
break;
case cmProcess::Exception::Illegal:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Illegal");
+ outputStream << "Illegal";
this->TestResult.Status = cmCTestTestHandler::ILLEGAL;
break;
case cmProcess::Exception::Interrupt:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Interrupt");
+ outputStream << "Interrupt";
this->TestResult.Status = cmCTestTestHandler::INTERRUPT;
break;
case cmProcess::Exception::Numerical:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Numerical");
+ outputStream << "Numerical";
this->TestResult.Status = cmCTestTestHandler::NUMERICAL;
break;
default:
this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
}
} else if ("Disabled" == this->TestResult.CompletionStatus) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run (Disabled) ");
+ outputStream << "***Not Run (Disabled) ";
} else // cmProcess::State::Error
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run ");
+ outputStream << "***Not Run ";
}
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
char buf[1024];
sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n");
+ outputStream << buf << "\n";
+
+ if (this->CTest->GetTestProgressOutput()) {
+ if (!passed) {
+ // If the test did not pass, reprint test name and error
+ std::string output = GetTestPrefix(completed, total);
+ std::string testName = this->TestProperties->Name;
+ const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
+ testName.resize(maxTestNameWidth + 4, '.');
+
+ output += testName;
+ output += outputStream.str();
+ outputStream.str("");
+ outputStream.clear();
+ outputStream << output;
+ cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, "\n"); // flush
+ }
+ if (completed == total) {
+ std::string testName =
+ GetTestPrefix(completed, total) + this->TestProperties->Name + "\n";
+ cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName);
+ }
+ }
+ if (!this->CTest->GetTestProgressOutput() || !passed) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str());
+ }
if (outputTestErrorsToConsole) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, this->ProcessOutput << std::endl);
return passed || skipped;
}
-bool cmCTestRunTest::StartAgain()
+bool cmCTestRunTest::StartAgain(size_t completed)
{
if (!this->RunAgain) {
return false;
return true;
}
- this->StartTest(this->TotalNumberOfTests);
+ this->StartTest(completed, this->TotalNumberOfTests);
return true;
}
{
// Still need to log the Start message so the test summary records our
// attempt to start this test
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8)
- << "Start "
- << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
- << this->TestProperties->Index << ": "
- << this->TestProperties->Name << std::endl);
+ if (!this->CTest->GetTestProgressOutput()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8)
+ << "Start "
+ << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
+ << this->TestProperties->Index << ": "
+ << this->TestProperties->Name << std::endl);
+ }
this->ProcessOutput.clear();
if (!output.empty()) {
this->TestProcess = cm::make_unique<cmProcess>(*this);
}
+std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const
+{
+ std::ostringstream outputStream;
+ outputStream << std::setw(getNumWidth(total)) << completed << "/";
+ outputStream << std::setw(getNumWidth(total)) << total << " ";
+
+ if (this->TestHandler->MemCheck) {
+ outputStream << "MemCheck";
+ } else {
+ outputStream << "Test";
+ }
+
+ std::ostringstream indexStr;
+ indexStr << " #" << this->Index << ":";
+ outputStream << std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
+ << indexStr.str();
+ outputStream << " ";
+
+ return outputStream.str();
+}
+
// Starts the execution of a test. Returns once it has started
-bool cmCTestRunTest::StartTest(size_t total)
+bool cmCTestRunTest::StartTest(size_t completed, size_t total)
{
this->TotalNumberOfTests = total; // save for rerun case
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(2 * getNumWidth(total) + 8)
- << "Start "
- << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
- << this->TestProperties->Index << ": "
- << this->TestProperties->Name << std::endl);
+ if (!this->CTest->GetTestProgressOutput()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(total) + 8)
+ << "Start "
+ << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
+ << this->TestProperties->Index << ": "
+ << this->TestProperties->Name << std::endl);
+ } else {
+ std::string testName =
+ GetTestPrefix(completed, total) + this->TestProperties->Name + "\n";
+ cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName);
+ }
+
this->ProcessOutput.clear();
// Return immediately if test is disabled
auto timeout = this->TestProperties->Timeout;
+ this->TimeoutIsForStopTime = false;
std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime();
if (stop_time != std::chrono::system_clock::time_point()) {
std::chrono::duration<double> stop_timeout =
}
if (timeout == std::chrono::duration<double>::zero() ||
stop_timeout < timeout) {
+ this->TimeoutIsForStopTime = true;
timeout = stop_timeout;
}
}
{
if (!this->ProcessOutput.empty() &&
this->ProcessOutput.find("<DartMeasurement") != std::string::npos) {
- if (this->TestHandler->DartStuff.find(this->ProcessOutput.c_str())) {
+ if (this->TestHandler->DartStuff.find(this->ProcessOutput)) {
this->TestResult.DartString = this->TestHandler->DartStuff.match(1);
// keep searching and replacing until none are left
- while (this->TestHandler->DartStuff1.find(this->ProcessOutput.c_str())) {
+ while (this->TestHandler->DartStuff1.find(this->ProcessOutput)) {
// replace the exact match for the string
cmSystemTools::ReplaceString(
this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(),
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
{
- // if this is the last or only run of this test
- // then print out completed / total
+ std::ostringstream outputStream;
+
+ // If this is the last or only run of this test, or progress output is
+ // requested, then print out completed / total.
// Only issue is if a test fails and we are running until fail
// then it will never print out the completed / total, same would
// got for run until pass. Trick is when this is called we don't
// yet know if we are passing or failing.
- if (this->NumberOfRunsLeft == 1) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(getNumWidth(total)) << completed << "/");
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(getNumWidth(total)) << total << " ");
+ if (this->NumberOfRunsLeft == 1 || this->CTest->GetTestProgressOutput()) {
+ outputStream << std::setw(getNumWidth(total)) << completed << "/";
+ outputStream << std::setw(getNumWidth(total)) << total << " ";
}
// if this is one of several runs of a test just print blank space
// to keep things neat
else {
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(getNumWidth(total)) << " "
- << " ");
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(getNumWidth(total)) << " "
- << " ");
+ outputStream << std::setw(getNumWidth(total)) << " ";
+ outputStream << std::setw(getNumWidth(total)) << " ";
}
if (this->TestHandler->MemCheck) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "MemCheck");
+ outputStream << "MemCheck";
} else {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Test");
+ outputStream << "Test";
}
std::ostringstream indexStr;
indexStr << " #" << this->Index << ":";
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
- << indexStr.str());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
+ outputStream << std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
+ << indexStr.str();
+ outputStream << " ";
+
const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
std::string outname = this->TestProperties->Name + " ";
outname.resize(maxTestNameWidth + 4, '.');
+ outputStream << outname;
*this->TestHandler->LogFile << this->TestProperties->Index << "/"
<< this->TestHandler->TotalNumberOfTests
*this->TestHandler->LogFile << this->ProcessOutput << "<end of output>"
<< std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str());
+ if (!this->CTest->GetTestProgressOutput()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str());
+ }
+
cmCTestLog(this->CTest, DEBUG,
"Testing " << this->TestProperties->Name << " ... ");
}
void CompressOutput();
// launch the test process, return whether it started correctly
- bool StartTest(size_t total);
+ bool StartTest(size_t completed, size_t total);
// capture and report the test results
bool EndTest(size_t completed, size_t total, bool started);
// Called by ctest -N to log the command string
void ComputeWeightedCost();
- bool StartAgain();
+ bool StartAgain(size_t completed);
void StartFailure(std::string const& output);
void FinalizeTest();
+ bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; }
+
private:
bool NeedsToRerun();
void DartProcessing();
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
+ // Returns "completed/total Test #Index: "
+ std::string GetTestPrefix(size_t completed, size_t total) const;
+
cmCTestTestHandler::cmCTestTestProperties* TestProperties;
+ bool TimeoutIsForStopTime = false;
// Pointer back to the "parent"; the handler that invoked this test run
cmCTestTestHandler* TestHandler;
cmCTest* CTest;
inline int getNumWidth(size_t n)
{
- int numWidth = 1;
- if (n >= 10) {
- numWidth = 2;
- }
- if (n >= 100) {
- numWidth = 3;
+ int w = 1;
+ while (n >= 10) {
+ n /= 10;
+ ++w;
}
- return numWidth;
+ return w;
}
#endif
// now that we have done most of the error checking finally run the
// dashboard, we may be asked to repeatedly run this dashboard, such as
- // for a continuous, do we ned to run it more than once?
+ // for a continuous, do we need to run it more than once?
if (this->ContinuousDuration >= 0) {
this->UpdateElapsedTime();
auto ending_time =
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Write CMake output to file: " << cmakeOutputFile
<< std::endl);
- cmGeneratedFileStream fout(cmakeOutputFile.c_str());
+ cmGeneratedFileStream fout(cmakeOutputFile);
if (fout) {
fout << output.c_str();
} else {
{
std::string cacheFile = directory;
cacheFile += "/CMakeCache.txt";
- cmGeneratedFileStream fout(cacheFile.c_str());
+ cmGeneratedFileStream fout(cacheFile);
if (!fout) {
return false;
}
// Log startup actions.
std::string startLogFile = binaryDir + "/Testing/Temporary/LastStart.log";
- cmGeneratedFileStream ofs(startLogFile.c_str());
+ cmGeneratedFileStream ofs(startLogFile);
if (!ofs) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot create log file: LastStart.log" << std::endl);
::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
std::string local_file = file;
+ bool initialize_cdash_buildid = false;
if (!cmSystemTools::FileExists(local_file)) {
local_file = localprefix + "/" + file;
+ // If this file exists within the local Testing directory we assume
+ // that it will be associated with the current build in CDash.
+ initialize_cdash_buildid = true;
}
std::string remote_file =
remoteprefix + cmSystemTools::GetFilenameName(file);
((url.find('?') == std::string::npos) ? '?' : '&') +
"FileName=" + ofile;
+ if (initialize_cdash_buildid) {
+ // Provide extra arguments to CDash so that it can initialize and
+ // return a buildid.
+ cmCTestCurl ctest_curl(this->CTest);
+ upload_as += "&build=";
+ upload_as +=
+ ctest_curl.Escape(this->CTest->GetCTestConfiguration("BuildName"));
+ upload_as += "&site=";
+ upload_as +=
+ ctest_curl.Escape(this->CTest->GetCTestConfiguration("Site"));
+ upload_as += "&stamp=";
+ upload_as += ctest_curl.Escape(this->CTest->GetCurrentTag());
+ upload_as += "-";
+ upload_as += ctest_curl.Escape(this->CTest->GetTestModelString());
+ cmCTestScriptHandler* ch = static_cast<cmCTestScriptHandler*>(
+ this->CTest->GetHandler("script"));
+ cmake* cm = ch->GetCMake();
+ if (cm) {
+ const char* subproject =
+ cm->GetState()->GetGlobalProperty("SubProject");
+ if (subproject) {
+ upload_as += "&subproject=";
+ upload_as += ctest_curl.Escape(subproject);
+ }
+ }
+ }
+
upload_as += "&MD5=";
if (cmSystemTools::IsOn(this->GetOption("InternalTest"))) {
// specify target
::curl_easy_setopt(curl, CURLOPT_URL, upload_as.c_str());
+ // CURLAUTH_BASIC is default, and here we allow additional methods,
+ // including more secure ones
+ ::curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+
// now specify which file to upload
::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
for (cmCTestTestProperties& rt : this->TestList) {
if (t == rt.Name) {
if (key == "WILL_FAIL") {
- rt.WillFail = cmSystemTools::IsOn(val.c_str());
+ rt.WillFail = cmSystemTools::IsOn(val);
}
if (key == "DISABLED") {
- rt.Disabled = cmSystemTools::IsOn(val.c_str());
+ rt.Disabled = cmSystemTools::IsOn(val);
}
if (key == "ATTACHED_FILES") {
cmSystemTools::ExpandListArgument(val, rt.AttachedFiles);
cmSystemTools::ExpandListArgument(val, rt.RequiredFiles);
}
if (key == "RUN_SERIAL") {
- rt.RunSerial = cmSystemTools::IsOn(val.c_str());
+ rt.RunSerial = cmSystemTools::IsOn(val);
}
if (key == "FAIL_REGULAR_EXPRESSION") {
std::vector<std::string> lval;
}
}
if (key == "PROCESSOR_AFFINITY") {
- rt.WantAffinity = cmSystemTools::IsOn(val.c_str());
+ rt.WantAffinity = cmSystemTools::IsOn(val);
}
if (key == "SKIP_RETURN_CODE") {
rt.SkipReturnCode = atoi(val.c_str());
this->Quiet);
if (this->UseExcludeRegExpFlag && this->UseExcludeRegExpFirst &&
- this->ExcludeTestsRegularExpression.find(testname.c_str())) {
+ this->ExcludeTestsRegularExpression.find(testname)) {
return true;
}
if (this->MemCheck) {
test.SkipReturnCode = -1;
test.PreviousRuns = 0;
if (this->UseIncludeRegExpFlag &&
- !this->IncludeTestsRegularExpression.find(testname.c_str())) {
+ !this->IncludeTestsRegularExpression.find(testname)) {
test.IsInBasedOnREOptions = false;
} else if (this->UseExcludeRegExpFlag && !this->UseExcludeRegExpFirst &&
- this->ExcludeTestsRegularExpression.find(testname.c_str())) {
+ this->ExcludeTestsRegularExpression.find(testname)) {
test.IsInBasedOnREOptions = false;
}
this->TestList.push_back(test);
// if update version only is on then do not actually update,
// just note the current version and finish
if (!cmSystemTools::IsOn(
- this->CTest->GetCTestConfiguration("UpdateVersionOnly").c_str())) {
+ this->CTest->GetCTestConfiguration("UpdateVersionOnly"))) {
result = this->NoteOldRevision() && result;
this->Log << "--- Begin Update ---\n";
result = this->UpdateImpl() && result;
{
// this method parses lines from the .mcov file
// each line has ^COVERAGE(...) in it, and there
- // are several varients of coverage lines:
+ // are several variants of coverage lines:
//
// ^COVERAGE("DIC11","PR1",0)="2:0:0:0"
// ( file , entry, line ) = "number_executed:timing_info"
uv_pipe_open(pipe_writer, fds[1]);
uv_stdio_container_t stdio[3];
- stdio[0].flags = UV_IGNORE;
+ stdio[0].flags = UV_INHERIT_FD;
+ stdio[0].data.fd = 0;
stdio[1].flags = UV_INHERIT_STREAM;
stdio[1].data.stream = pipe_writer;
stdio[2] = stdio[1];
set(CMake_CXX14_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION)
set(CMake_CXX14_WORKS 0)
endif()
#include <cstdio>
+#include <memory>
+
int main()
{
- return 0;
+ std::unique_ptr<int> u(new int(0));
+ return *u;
}
set(CMake_CXX17_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|PGI")
if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION)
set(CMake_CXX17_WORKS 0)
endif()
#include <cstdio>
+#include <memory>
#include <unordered_map>
int main()
{
- return 0;
+ std::unique_ptr<int> u(new int(0));
+ return *u;
}
getmaxyx(stdscr, y, x);
char bar[cmCursesMainForm::MAX_WIDTH];
- size_t size = strlen(this->Title.c_str());
+ size_t size = this->Title.size();
if (size >= cmCursesMainForm::MAX_WIDTH) {
size = cmCursesMainForm::MAX_WIDTH - 1;
}
cmSystemTools::ConvertToUnixSlashes(out);
}
if (type == cmStateEnums::BOOL) {
- if (cmSystemTools::IsOff(out.c_str())) {
+ if (cmSystemTools::IsOff(out)) {
out = "OFF";
} else {
out = "ON";
# pragma warning (disable: 4244) /* loss of precision */
# pragma warning (disable: 4702) /* unreachable code */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339 */
+#line 134 "cmCommandArgumentParser.cxx" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
/* Copy the second part of user declarations. */
-#line 204 "cmCommandArgumentParser.cxx" /* yacc.c:358 */
+#line 207 "cmCommandArgumentParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 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
+ 0, 99, 99, 105, 108, 113, 116, 121, 124, 129,
+ 132, 135, 138, 141, 144, 149, 152, 155, 158, 163,
+ 166, 171, 174, 179, 182
};
#endif
switch (yyn)
{
case 2:
-#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 99 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = 0;
yyGetParser->SetResult((yyvsp[0].str));
}
-#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1309 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 3:
-#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1317 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 4:
-#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 108 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1325 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 5:
-#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = 0;
}
-#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1333 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 6:
-#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 116 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1341 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 7:
-#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1349 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 8:
-#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 124 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1357 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 9:
-#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1365 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 10:
-#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1373 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 11:
-#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1381 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 12:
-#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1389 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 13:
-#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1397 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 14:
-#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1405 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 15:
-#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1413 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 16:
-#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1421 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 17:
-#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
}
-#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1429 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 18:
-#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 158 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
}
-#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1437 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 19:
-#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1445 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 20:
-#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 166 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[-1].str);
}
-#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1453 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 21:
-#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = 0;
}
-#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1461 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 22:
-#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 174 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1469 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 23:
-#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1477 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
case 24:
-#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 182 "cmCommandArgumentParser.y" /* yacc.c:1646 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1485 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
break;
-#line 1486 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1489 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
#endif
return yyresult;
}
-#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906 */
+#line 187 "cmCommandArgumentParser.y" /* yacc.c:1906 */
/* End of grammar */
# pragma warning (disable: 4244) /* loss of precision */
# pragma warning (disable: 4702) /* unreachable code */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 120 "cmDependsJavaParser.cxx" /* yacc.c:339 */
+#line 123 "cmDependsJavaParser.cxx" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
/* Copy the second part of user declarations. */
-#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358 */
+#line 378 "cmDependsJavaParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 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
+ 0, 182, 182, 191, 199, 207, 215, 223, 231, 240,
+ 248, 257, 265, 274, 279, 284, 289, 294, 299, 304,
+ 309, 315, 323, 332, 342, 351, 360, 368, 378, 384,
+ 391, 398, 404, 411, 420, 430, 440, 449, 457, 466,
+ 475, 481, 490, 496, 505, 511, 520, 532, 540, 549,
+ 561, 574, 582, 590, 599, 607, 616, 616, 616, 617,
+ 618, 618, 618, 618, 618, 618, 619, 622, 632, 641,
+ 650, 659, 669, 675, 684, 693, 702, 710, 719, 728,
+ 734, 743, 751, 759, 767, 776, 784, 793, 799, 807,
+ 816, 824, 833, 842, 851, 859, 868, 876, 884, 893,
+ 902, 912, 919, 929, 939, 946, 953, 956, 962, 972,
+ 982, 992, 998, 1008, 1018, 1028, 1037, 1047, 1058, 1068,
+ 1075, 1085, 1094, 1104, 1113, 1123, 1129, 1139, 1148, 1158,
+ 1168, 1175, 1184, 1193, 1202, 1211, 1219, 1228, 1237, 1247,
+ 1257, 1266, 1276, 1286, 1293, 1302, 1312, 1321, 1331, 1340,
+ 1347, 1357, 1366, 1376, 1385, 1394, 1404, 1414, 1423, 1433,
+ 1442, 1451, 1460, 1469, 1478, 1488, 1497, 1506, 1515, 1524,
+ 1534, 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, 1615,
+ 1624, 1633, 1643, 1653, 1664, 1674, 1684, 1693, 1702, 1711,
+ 1720, 1729, 1738, 1748, 1758, 1768, 1778, 1785, 1792, 1799,
+ 1809, 1816, 1826, 1836, 1845, 1855, 1864, 1874, 1881, 1888,
+ 1895, 1903, 1910, 1920, 1927, 1937, 1947, 1954, 1964, 1973,
+ 1983, 1993, 2002, 2012, 2021, 2031, 2042, 2049, 2056, 2067,
+ 2077, 2087, 2097, 2106, 2116, 2123, 2133, 2142, 2152, 2159,
+ 2169, 2178, 2188, 2197, 2203, 2212, 2221, 2230, 2239, 2249,
+ 2259, 2266, 2276, 2283, 2293, 2302, 2312, 2321, 2330, 2339,
+ 2349, 2356, 2366, 2375, 2385, 2395, 2401, 2408, 2418, 2428,
+ 2438, 2449, 2459, 2470, 2480, 2491, 2501, 2511, 2520, 2529,
+ 2538, 2547, 2557, 2567, 2577, 2586, 2595, 2604, 2613, 2623,
+ 2633, 2643, 2652, 2661, 2670, 2680, 2689, 2698, 2705, 2714,
+ 2723, 2732, 2742, 2751, 2760, 2770, 2779, 2788, 2797, 2807,
+ 2816, 2825, 2834, 2843, 2852, 2862, 2871, 2880, 2890, 2899,
+ 2909, 2918, 2928, 2937, 2947, 2956, 2966, 2975, 2985, 2994,
+ 3004, 3013, 3023, 3033, 3043, 3052, 3062, 3071, 3080, 3089,
+ 3098, 3107, 3116, 3125, 3134, 3143, 3152, 3161, 3171, 3181,
+ 3191, 3200
};
#endif
switch (yyn)
{
case 2:
-#line 180 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 183 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 3:
-#line 189 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 192 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2307 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 4:
-#line 197 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 200 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2318 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 5:
-#line 205 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 208 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 6:
-#line 213 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 216 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2340 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 7:
-#line 221 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 224 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2351 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 8:
-#line 229 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 232 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2362 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 9:
-#line 238 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 241 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2373 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 10:
-#line 246 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 249 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2384 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 11:
-#line 255 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 258 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2395 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 12:
-#line 263 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 266 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2406 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 13:
-#line 272 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 275 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2414 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 14:
-#line 277 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 280 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2422 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 15:
-#line 282 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 285 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2430 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 16:
-#line 287 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 290 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 17:
-#line 292 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 295 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2446 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 18:
-#line 297 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 300 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2454 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 19:
-#line 302 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 305 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 20:
-#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 310 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
}
-#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2470 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 21:
-#line 313 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 316 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2481 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 22:
-#line 321 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 324 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 23:
-#line 330 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 333 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpStoreClass((yyvsp[0].str));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2504 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 24:
-#line 340 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 343 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 25:
-#line 349 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 352 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2526 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 26:
-#line 358 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 361 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2537 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 27:
-#line 366 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 369 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpStoreClass((yyvsp[-1].str));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2549 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 28:
-#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 379 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 29:
-#line 382 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 385 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2567 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 30:
-#line 389 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 392 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2576 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 31:
-#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 399 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2585 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 32:
-#line 402 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 405 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
(yyval.str) = (yyvsp[0].str);
}
-#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2594 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 33:
-#line 409 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 412 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->AddClassFound((yyvsp[-2].str));
yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
(yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine());
}
-#line 2603 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2606 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 34:
-#line 418 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 421 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2619 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 35:
-#line 428 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 431 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 36:
-#line 438 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 441 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2643 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 37:
-#line 447 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 450 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2654 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 38:
-#line 455 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 458 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 39:
-#line 464 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 467 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2676 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 40:
-#line 472 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 475 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 41:
-#line 479 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 482 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2697 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 42:
-#line 487 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 490 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 43:
-#line 494 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 497 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 44:
-#line 502 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 505 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2728 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 45:
-#line 509 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 512 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2739 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 46:
-#line 518 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 521 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->SetCurrentPackage((yyvsp[-1].str));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2753 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 47:
-#line 530 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 533 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2764 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 48:
-#line 538 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 541 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2775 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 49:
-#line 547 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 550 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->AddPackagesImport((yyvsp[-1].str));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2789 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 50:
-#line 559 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 562 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
std::string str = (yyvsp[-3].str);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2804 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 51:
-#line 572 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 575 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2815 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 52:
-#line 580 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 583 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2826 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 53:
-#line 588 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 591 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2837 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 54:
-#line 597 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 600 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 55:
-#line 605 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 608 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2859 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 67:
-#line 620 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 623 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2870 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 68:
-#line 630 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 633 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2882 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 69:
-#line 639 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 642 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2894 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 70:
-#line 648 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 651 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2906 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 71:
-#line 657 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 660 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2918 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 72:
-#line 666 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 669 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2928 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 73:
-#line 673 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 676 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2939 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 74:
-#line 682 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 685 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 75:
-#line 691 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 694 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2961 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 76:
-#line 700 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 703 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2972 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 77:
-#line 708 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 711 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2983 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 78:
-#line 717 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 720 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2994 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 79:
-#line 725 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 728 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 80:
-#line 732 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 735 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3015 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 81:
-#line 741 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 744 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 82:
-#line 749 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 752 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3037 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 83:
-#line 757 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 760 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3048 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 84:
-#line 765 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 768 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 85:
-#line 774 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 777 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3070 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 86:
-#line 782 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 785 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3081 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 87:
-#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 794 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
}
-#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3089 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 88:
-#line 797 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 800 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 89:
-#line 805 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 808 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3111 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 90:
-#line 814 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 817 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3122 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 91:
-#line 822 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 825 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 92:
-#line 831 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 834 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 93:
-#line 840 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 843 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3156 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 94:
-#line 849 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 852 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 95:
-#line 857 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 860 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3178 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 96:
-#line 866 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 869 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3189 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 97:
-#line 874 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 877 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3200 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 98:
-#line 882 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 885 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3211 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 99:
-#line 891 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 894 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3223 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 100:
-#line 900 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 903 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3235 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 101:
-#line 909 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 912 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3246 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 102:
-#line 917 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 920 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3258 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 103:
-#line 927 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 930 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3271 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 104:
-#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 940 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
}
-#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3280 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 105:
-#line 943 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 946 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3291 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 107:
-#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 957 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
-#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3300 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 108:
-#line 960 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 963 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3312 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 109:
-#line 970 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 973 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3324 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 110:
-#line 980 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 983 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3336 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 111:
-#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 993 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
-#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3345 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 112:
-#line 996 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 999 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3357 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 113:
-#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1009 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3369 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 114:
-#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1019 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 115:
-#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1029 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 116:
-#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1038 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 117:
-#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1048 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3418 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 118:
-#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1059 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3430 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 119:
-#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1068 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 120:
-#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1076 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 121:
-#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1086 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 122:
-#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1095 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 123:
-#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1105 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3488 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 124:
-#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1114 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3500 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 125:
-#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1123 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3510 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 126:
-#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1130 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3522 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 127:
-#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1140 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 128:
-#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1149 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 129:
-#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1159 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 130:
-#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1168 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 131:
-#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1176 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3580 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 132:
-#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1185 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3592 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 133:
-#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1194 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3604 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 134:
-#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1203 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 135:
-#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1212 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3627 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 136:
-#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1220 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3639 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 137:
-#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1229 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 138:
-#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1238 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 139:
-#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1248 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 140:
-#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1258 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 141:
-#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1267 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 142:
-#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1277 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 143:
-#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1286 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3721 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 144:
-#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1294 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3733 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 145:
-#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1303 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3745 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 146:
-#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1313 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3757 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 147:
-#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1322 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3769 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 148:
-#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1332 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3780 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 149:
-#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1340 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3791 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 150:
-#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1348 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3803 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 151:
-#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1358 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3815 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 152:
-#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1367 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 153:
-#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1377 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 154:
-#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1386 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 155:
-#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1395 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 156:
-#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1405 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 157:
-#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1415 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3887 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 158:
-#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1424 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3899 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 159:
-#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1434 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3911 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 160:
-#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1443 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3923 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 161:
-#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1452 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3935 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 162:
-#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1461 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 163:
-#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1470 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3959 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 164:
-#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1479 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3971 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 165:
-#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1489 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3983 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 166:
-#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1498 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3995 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 167:
-#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1507 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4007 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 168:
-#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1516 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4019 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 169:
-#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1525 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4031 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 170:
-#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1535 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4043 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 171:
-#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1544 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4055 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 172:
-#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1553 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 173:
-#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1562 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4079 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 174:
-#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1571 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4091 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 175:
-#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1580 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4103 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 176:
-#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1589 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4115 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 177:
-#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1598 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4127 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 178:
-#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1607 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4139 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 179:
-#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1616 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 180:
-#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1625 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4163 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 181:
-#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1634 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 182:
-#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1644 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4187 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 183:
-#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1654 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4200 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 184:
-#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1665 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4212 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 185:
-#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1675 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4224 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 186:
-#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1685 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4236 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 187:
-#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1694 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4248 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 188:
-#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1703 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4260 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 189:
-#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1712 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4272 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 190:
-#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1721 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4284 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 191:
-#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1730 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 192:
-#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1739 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4308 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 193:
-#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1749 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 194:
-#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1759 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(7);
jpCheckEmpty(7);
yyGetParser->SetCurrentCombine("");
}
-#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4332 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 195:
-#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1769 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(7);
jpCheckEmpty(7);
yyGetParser->SetCurrentCombine("");
}
-#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 196:
-#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1779 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
-#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 197:
-#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1786 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
}
-#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4362 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 198:
-#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1792 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4373 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 199:
-#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1800 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4385 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 200:
-#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1809 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4396 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 201:
-#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1817 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4408 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 202:
-#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1827 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4420 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 203:
-#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1837 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4432 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 204:
-#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1846 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4444 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 205:
-#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1856 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4456 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 206:
-#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1865 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4468 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 207:
-#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1875 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
-#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 208:
-#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1882 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
-#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4486 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 209:
-#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1889 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(7);
}
-#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4495 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 210:
-#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1897 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(9);
}
-#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4504 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 211:
-#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1903 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 212:
-#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1911 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4527 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 213:
-#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1920 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4538 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 214:
-#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1928 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4550 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 215:
-#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1939 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(9);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4561 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 216:
-#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1947 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4572 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 217:
-#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1955 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4584 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 218:
-#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1965 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4596 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 219:
-#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1974 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4608 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 220:
-#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1984 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4620 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 221:
-#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1994 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 222:
-#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2003 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4644 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 223:
-#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2013 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4656 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 224:
-#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2022 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4668 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 225:
-#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2032 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4681 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 226:
-#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2042 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4692 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 227:
-#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2050 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
-#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 228:
-#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2057 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4714 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 229:
-#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2068 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4726 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 230:
-#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2078 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4738 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 231:
-#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2088 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 232:
-#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2098 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4762 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 233:
-#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2107 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4774 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 234:
-#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2116 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4785 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 235:
-#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2124 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4797 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 236:
-#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2134 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4809 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 237:
-#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2143 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 238:
-#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2153 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
-#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 239:
-#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2160 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 240:
-#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2170 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 241:
-#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2179 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 242:
-#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2189 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 243:
-#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2198 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
}
-#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4887 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 244:
-#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2204 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4899 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 245:
-#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2213 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4911 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 246:
-#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2222 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4923 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 247:
-#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2231 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4935 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 248:
-#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2240 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 249:
-#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2250 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
jpCheckEmpty(6);
yyGetParser->SetCurrentCombine("");
}
-#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4959 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 250:
-#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2259 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4970 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 251:
-#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2267 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4982 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 252:
-#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2276 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4993 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 253:
-#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2284 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5005 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 254:
-#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2294 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5017 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 255:
-#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2303 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5029 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 256:
-#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2313 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5041 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 257:
-#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2322 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5053 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 258:
-#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2331 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5065 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 259:
-#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2340 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5077 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 260:
-#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2349 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 261:
-#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2357 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 262:
-#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2367 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 263:
-#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2376 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 264:
-#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2386 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 265:
-#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2396 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
}
-#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 266:
-#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2402 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
}
-#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5154 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 267:
-#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2409 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 268:
-#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2419 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 269:
-#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2429 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5193 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 270:
-#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2439 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5206 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 271:
-#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2450 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5219 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 272:
-#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2460 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-5].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 273:
-#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2471 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5246 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 274:
-#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2481 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5259 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 275:
-#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2492 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5272 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 276:
-#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2502 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5284 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 277:
-#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2512 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 278:
-#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2521 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5308 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 279:
-#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2530 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 280:
-#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2539 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5332 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 281:
-#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2548 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 282:
-#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2558 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5356 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 283:
-#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2568 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5368 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 284:
-#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2578 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5380 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 285:
-#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2587 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 286:
-#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2596 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5404 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 287:
-#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2605 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5416 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 288:
-#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2614 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5428 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 289:
-#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2624 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5440 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 290:
-#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2634 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5452 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 291:
-#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2644 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5464 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 292:
-#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2653 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5476 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 293:
-#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2662 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(2);
jpCheckEmpty(2);
yyGetParser->SetCurrentCombine("");
}
-#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5488 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 294:
-#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2671 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5500 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 295:
-#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2681 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 296:
-#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2690 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(4);
jpCheckEmpty(4);
yyGetParser->SetCurrentCombine("");
}
-#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 297:
-#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2699 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
}
-#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5533 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 298:
-#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2706 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5545 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 299:
-#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2715 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5557 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 300:
-#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2724 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 301:
-#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2733 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 302:
-#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2743 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 303:
-#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2752 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 304:
-#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2761 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 305:
-#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2771 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 306:
-#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2780 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 307:
-#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2789 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 308:
-#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2798 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 309:
-#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2808 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5677 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 310:
-#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2817 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 311:
-#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2826 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 312:
-#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2835 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5713 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 313:
-#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2844 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 314:
-#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2853 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5737 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 315:
-#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2863 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5749 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 316:
-#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2872 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 317:
-#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2881 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5773 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 318:
-#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2891 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5785 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 319:
-#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2900 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5797 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 320:
-#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2910 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5809 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 321:
-#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2919 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 322:
-#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2929 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5833 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 323:
-#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2938 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 324:
-#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2948 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5857 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 325:
-#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2957 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5869 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 326:
-#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2967 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5881 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 327:
-#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2976 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5893 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 328:
-#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2986 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5905 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 329:
-#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2995 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(5);
jpCheckEmpty(5);
yyGetParser->SetCurrentCombine("");
}
-#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5917 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 330:
-#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3005 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5929 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 331:
-#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3014 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5941 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 332:
-#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3024 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpCheckEmpty(3);
yyGetParser->SetCurrentCombine("");
}
-#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5953 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 333:
-#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3034 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
yyGetParser->SetCurrentCombine("");
}
-#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5966 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 334:
-#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3044 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5978 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 335:
-#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3053 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 336:
-#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3063 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 337:
-#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3072 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 338:
-#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3081 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 339:
-#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3090 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 340:
-#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3099 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 341:
-#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3108 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 342:
-#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3117 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 343:
-#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3126 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 344:
-#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3135 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6098 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 345:
-#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3144 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6110 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 346:
-#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3153 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6122 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 347:
-#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3162 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6134 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 348:
-#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3172 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6146 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 349:
-#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3182 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6158 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 350:
-#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3192 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(1);
jpCheckEmpty(1);
yyGetParser->SetCurrentCombine("");
}
-#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6170 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
case 351:
-#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3201 "cmDependsJavaParser.y" /* yacc.c:1646 */
{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
yyGetParser->SetCurrentCombine("");
}
-#line 6180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6183 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
break;
-#line 6184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6187 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
#endif
return yyresult;
}
-#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906 */
+#line 3210 "cmDependsJavaParser.y" /* yacc.c:1906 */
/* End of grammar */
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 15
-#define YY_END_OF_BUFFER 16
+#define YY_NUM_RULES 18
+#define YY_END_OF_BUFFER 19
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static const flex_int16_t yy_accept[23] =
+static const flex_int16_t yy_accept[29] =
{ 0,
- 0, 0, 16, 15, 6, 8, 13, 14, 4, 2,
- 3, 5, 1, 15, 15, 9, 7, 10, 1, 11,
- 12, 0
+ 0, 0, 19, 17, 1, 18, 8, 10, 15, 16,
+ 6, 4, 5, 7, 2, 2, 17, 17, 11, 9,
+ 12, 2, 0, 13, 14, 3, 3, 0
} ;
static const YY_CHAR yy_ec[256] =
{ 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 1, 1, 1, 4, 5, 1, 6,
+ 7, 8, 9, 1, 10, 1, 11, 12, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 1, 1, 14,
+ 1, 15, 1, 1, 16, 16, 16, 16, 16, 16,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 2, 3, 1, 4,
- 5, 6, 7, 1, 8, 1, 9, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 1, 1, 11,
- 1, 12, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 13, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 17, 1, 1,
+ 1, 1, 1, 18, 1, 1, 16, 16, 16, 16,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 14, 1, 15, 1, 1, 1, 1,
+ 16, 16, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 17,
+ 1, 1, 1, 19, 1, 20, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1
} ;
-static const YY_CHAR yy_meta[16] =
+static const YY_CHAR yy_meta[21] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1
+ 1, 2, 2, 1, 1, 3, 4, 1, 1, 1
} ;
-static const flex_int16_t yy_base[23] =
+static const flex_int16_t yy_base[32] =
{ 0,
- 0, 0, 20, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 9, 7, 5, 21, 21, 21, 6, 21,
- 21, 21
+ 0, 0, 34, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 16, 9, 18, 11, 35, 35,
+ 35, 11, 0, 35, 35, 0, 0, 35, 23, 26,
+ 28
} ;
-static const flex_int16_t yy_def[23] =
+static const flex_int16_t yy_def[32] =
{ 0,
- 22, 1, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 0
+ 28, 1, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 29, 28, 28, 28, 28, 28,
+ 28, 28, 30, 28, 28, 31, 31, 0, 28, 28,
+ 28
} ;
-static const flex_int16_t yy_nxt[37] =
+static const flex_int16_t yy_nxt[56] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 21, 20, 19, 22,
- 3, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22
+ 14, 15, 16, 17, 18, 4, 4, 19, 20, 21,
+ 22, 22, 22, 22, 22, 25, 22, 26, 26, 27,
+ 27, 24, 23, 28, 3, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28
} ;
-static const flex_int16_t yy_chk[37] =
+static const flex_int16_t yy_chk[56] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 19, 15, 14, 13, 3,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 16, 16, 22, 22, 29, 18, 29, 30, 30, 31,
+ 31, 17, 15, 3, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28
} ;
/* The intent behind this definition is that it'll catch
/* Include the set of tokens from the parser. */
#include "cmExprParserTokens.h"
+#include <string>
+
/*--------------------------------------------------------------------------*/
#define INITIAL 0
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 23 )
+ if ( yy_current_state >= 29 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 21 );
+ while ( yy_base[yy_current_state] != 35 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
case 1:
YY_RULE_SETUP
-{ yylvalp->Number = atoi(yytext); return exp_NUMBER; }
+{}
YY_BREAK
case 2:
YY_RULE_SETUP
-{ return exp_PLUS; }
+{ yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; }
YY_BREAK
case 3:
YY_RULE_SETUP
-{ return exp_MINUS; }
+{ yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; }
YY_BREAK
case 4:
YY_RULE_SETUP
-{ return exp_TIMES; }
+{ return exp_PLUS; }
YY_BREAK
case 5:
YY_RULE_SETUP
-{ return exp_DIVIDE; }
+{ return exp_MINUS; }
YY_BREAK
case 6:
YY_RULE_SETUP
-{ return exp_MOD; }
+{ return exp_TIMES; }
YY_BREAK
case 7:
YY_RULE_SETUP
-{ return exp_OR; }
+{ return exp_DIVIDE; }
YY_BREAK
case 8:
YY_RULE_SETUP
-{ return exp_AND; }
+{ return exp_MOD; }
YY_BREAK
case 9:
YY_RULE_SETUP
-{ return exp_XOR; }
+{ return exp_OR; }
YY_BREAK
case 10:
YY_RULE_SETUP
-{ return exp_NOT; }
+{ return exp_AND; }
YY_BREAK
case 11:
YY_RULE_SETUP
-{ return exp_SHIFTLEFT; }
+{ return exp_XOR; }
YY_BREAK
case 12:
YY_RULE_SETUP
-{ return exp_SHIFTRIGHT; }
+{ return exp_NOT; }
YY_BREAK
case 13:
YY_RULE_SETUP
-{ return exp_OPENPARENT; }
+{ return exp_SHIFTLEFT; }
YY_BREAK
case 14:
YY_RULE_SETUP
-{ return exp_CLOSEPARENT; }
+{ return exp_SHIFTRIGHT; }
YY_BREAK
case 15:
YY_RULE_SETUP
+{ return exp_OPENPARENT; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+{ return exp_CLOSEPARENT; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+{ yyextra->UnexpectedChar(yytext[0]); }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
ECHO;
YY_BREAK
case YY_STATE_EOF(INITIAL):
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 23 )
+ if ( yy_current_state >= 29 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 23 )
+ if ( yy_current_state >= 29 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
- yy_is_jam = (yy_current_state == 22);
+ yy_is_jam = (yy_current_state == 28);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
/* Include the set of tokens from the parser. */
#include "cmExprParserTokens.h"
+#include <string>
+
/*--------------------------------------------------------------------------*/
%}
%pointer
%%
+[ \t] {}
-[0-9][0-9]* { yylvalp->Number = atoi(yytext); return exp_NUMBER; }
+[0-9][0-9]* { yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; }
+0[xX][0-9a-fA-F][0-9a-fA-F]* { yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; }
"+" { return exp_PLUS; }
"-" { return exp_MINUS; }
">>" { return exp_SHIFTRIGHT; }
"(" { return exp_OPENPARENT; }
")" { return exp_CLOSEPARENT; }
+. { yyextra->UnexpectedChar(yytext[0]); }
%%
#include <stdlib.h>
#include <string.h>
+#include <stdexcept>
/*-------------------------------------------------------------------------*/
#define YYDEBUG 1
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 112 "cmExprParser.cxx" /* yacc.c:339 */
+#line 116 "cmExprParser.cxx" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
/* Copy the second part of user declarations. */
-#line 189 "cmExprParser.cxx" /* yacc.c:358 */
+#line 193 "cmExprParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 73, 73, 78, 81, 86, 89, 94, 97, 102,
- 105, 108, 113, 116, 119, 124, 127, 130, 133, 138,
- 141, 144, 149, 152
+ 0, 77, 77, 82, 85, 90, 93, 98, 101, 106,
+ 109, 112, 117, 120, 123, 128, 131, 134, 140, 145,
+ 148, 151, 156, 159
};
#endif
switch (yyn)
{
case 2:
-#line 73 "cmExprParser.y" /* yacc.c:1646 */
+#line 77 "cmExprParser.y" /* yacc.c:1646 */
{
cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
}
-#line 1289 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1293 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 3:
-#line 78 "cmExprParser.y" /* yacc.c:1646 */
+#line 82 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1297 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1301 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 4:
-#line 81 "cmExprParser.y" /* yacc.c:1646 */
+#line 85 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
}
-#line 1305 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1309 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 5:
-#line 86 "cmExprParser.y" /* yacc.c:1646 */
+#line 90 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1313 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1317 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 6:
-#line 89 "cmExprParser.y" /* yacc.c:1646 */
+#line 93 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
}
-#line 1321 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1325 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 7:
-#line 94 "cmExprParser.y" /* yacc.c:1646 */
+#line 98 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1329 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1333 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 8:
-#line 97 "cmExprParser.y" /* yacc.c:1646 */
+#line 101 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
}
-#line 1337 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1341 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 9:
-#line 102 "cmExprParser.y" /* yacc.c:1646 */
+#line 106 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1345 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1349 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 10:
-#line 105 "cmExprParser.y" /* yacc.c:1646 */
+#line 109 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
}
-#line 1353 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1357 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 11:
-#line 108 "cmExprParser.y" /* yacc.c:1646 */
+#line 112 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
}
-#line 1361 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1365 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 12:
-#line 113 "cmExprParser.y" /* yacc.c:1646 */
+#line 117 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1369 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1373 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 13:
-#line 116 "cmExprParser.y" /* yacc.c:1646 */
+#line 120 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
}
-#line 1377 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1381 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 14:
-#line 119 "cmExprParser.y" /* yacc.c:1646 */
+#line 123 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
}
-#line 1385 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1389 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 15:
-#line 124 "cmExprParser.y" /* yacc.c:1646 */
+#line 128 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1393 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1397 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 16:
-#line 127 "cmExprParser.y" /* yacc.c:1646 */
+#line 131 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
}
-#line 1401 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1405 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 17:
-#line 130 "cmExprParser.y" /* yacc.c:1646 */
+#line 134 "cmExprParser.y" /* yacc.c:1646 */
{
+ if (yyvsp[0].Number == 0) {
+ throw std::overflow_error("divide by zero");
+ }
(yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
}
-#line 1409 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1416 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 18:
-#line 133 "cmExprParser.y" /* yacc.c:1646 */
+#line 140 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
}
-#line 1417 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1424 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 19:
-#line 138 "cmExprParser.y" /* yacc.c:1646 */
+#line 145 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1425 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1432 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 20:
-#line 141 "cmExprParser.y" /* yacc.c:1646 */
+#line 148 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = + (yyvsp[0].Number);
}
-#line 1433 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1440 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 21:
-#line 144 "cmExprParser.y" /* yacc.c:1646 */
+#line 151 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = - (yyvsp[0].Number);
}
-#line 1441 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1448 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 22:
-#line 149 "cmExprParser.y" /* yacc.c:1646 */
+#line 156 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1449 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1456 "cmExprParser.cxx" /* yacc.c:1646 */
break;
case 23:
-#line 152 "cmExprParser.y" /* yacc.c:1646 */
+#line 159 "cmExprParser.y" /* yacc.c:1646 */
{
(yyval.Number) = (yyvsp[-1].Number);
}
-#line 1457 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1464 "cmExprParser.cxx" /* yacc.c:1646 */
break;
-#line 1461 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1468 "cmExprParser.cxx" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
#endif
return yyresult;
}
-#line 157 "cmExprParser.y" /* yacc.c:1906 */
+#line 164 "cmExprParser.y" /* yacc.c:1906 */
/* End of grammar */
#include <stdlib.h>
#include <string.h>
+#include <stdexcept>
/*-------------------------------------------------------------------------*/
#define YYDEBUG 1
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
$<Number>$ = $<Number>1 * $<Number>3;
}
| term exp_DIVIDE unary {
+ if (yyvsp[0].Number == 0) {
+ throw std::overflow_error("divide by zero");
+ }
$<Number>$ = $<Number>1 / $<Number>3;
}
| term exp_MOD unary {
# pragma warning (disable: 4127) /* Conditional expression is constant. */
# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 132 "cmFortranParser.cxx" /* yacc.c:339 */
+#line 135 "cmFortranParser.cxx" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
union YYSTYPE
{
-#line 70 "cmFortranParser.y" /* yacc.c:355 */
+#line 73 "cmFortranParser.y" /* yacc.c:355 */
char* string;
-#line 256 "cmFortranParser.cxx" /* yacc.c:355 */
+#line 259 "cmFortranParser.cxx" /* yacc.c:355 */
};
typedef union YYSTYPE YYSTYPE;
/* Copy the second part of user declarations. */
-#line 272 "cmFortranParser.cxx" /* yacc.c:358 */
+#line 275 "cmFortranParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 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
+ 0, 101, 101, 101, 104, 108, 113, 122, 128, 135,
+ 140, 144, 149, 157, 162, 167, 172, 177, 182, 187,
+ 192, 197, 201, 205, 209, 213, 214, 219, 219, 219,
+ 220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
+ 225, 225, 226, 226, 227, 227, 228, 228, 231, 232,
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+ 243, 244, 245, 246
};
#endif
switch (yyn)
{
case 4:
-#line 101 "cmFortranParser.y" /* yacc.c:1646 */
+#line 104 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
}
-#line 1536 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1539 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 5:
-#line 105 "cmFortranParser.y" /* yacc.c:1646 */
+#line 108 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1546 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1549 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 6:
-#line 110 "cmFortranParser.y" /* yacc.c:1646 */
+#line 113 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
}
free((yyvsp[-2].string));
}
-#line 1560 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1563 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 7:
-#line 119 "cmFortranParser.y" /* yacc.c:1646 */
+#line 122 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string));
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1571 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1574 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 8:
-#line 125 "cmFortranParser.y" /* yacc.c:1646 */
+#line 128 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1583 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1586 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 9:
-#line 132 "cmFortranParser.y" /* yacc.c:1646 */
+#line 135 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
free((yyvsp[-2].string));
}
-#line 1593 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1596 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 10:
-#line 137 "cmFortranParser.y" /* yacc.c:1646 */
+#line 140 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, false);
}
-#line 1602 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1605 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 11:
-#line 141 "cmFortranParser.y" /* yacc.c:1646 */
+#line 144 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1612 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1615 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 12:
-#line 146 "cmFortranParser.y" /* yacc.c:1646 */
+#line 149 "cmFortranParser.y" /* yacc.c:1646 */
{
if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1625 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1628 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 13:
-#line 154 "cmFortranParser.y" /* yacc.c:1646 */
+#line 157 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1635 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1638 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 14:
-#line 159 "cmFortranParser.y" /* yacc.c:1646 */
+#line 162 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1645 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1648 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 15:
-#line 164 "cmFortranParser.y" /* yacc.c:1646 */
+#line 167 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1655 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1658 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 16:
-#line 169 "cmFortranParser.y" /* yacc.c:1646 */
+#line 172 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1665 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1668 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 17:
-#line 174 "cmFortranParser.y" /* yacc.c:1646 */
+#line 177 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1675 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1678 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 18:
-#line 179 "cmFortranParser.y" /* yacc.c:1646 */
+#line 182 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1685 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1688 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 19:
-#line 184 "cmFortranParser.y" /* yacc.c:1646 */
+#line 187 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1695 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1698 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 20:
-#line 189 "cmFortranParser.y" /* yacc.c:1646 */
+#line 192 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1705 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1708 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 21:
-#line 194 "cmFortranParser.y" /* yacc.c:1646 */
+#line 197 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
-#line 1714 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1717 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 22:
-#line 198 "cmFortranParser.y" /* yacc.c:1646 */
+#line 201 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
-#line 1723 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1726 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 23:
-#line 202 "cmFortranParser.y" /* yacc.c:1646 */
+#line 205 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
-#line 1732 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1735 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 24:
-#line 206 "cmFortranParser.y" /* yacc.c:1646 */
+#line 209 "cmFortranParser.y" /* yacc.c:1646 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
-#line 1741 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1744 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 48:
-#line 228 "cmFortranParser.y" /* yacc.c:1646 */
+#line 231 "cmFortranParser.y" /* yacc.c:1646 */
{ free ((yyvsp[0].string)); }
-#line 1747 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1750 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
case 55:
-#line 235 "cmFortranParser.y" /* yacc.c:1646 */
+#line 238 "cmFortranParser.y" /* yacc.c:1646 */
{ free ((yyvsp[0].string)); }
-#line 1753 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1756 "cmFortranParser.cxx" /* yacc.c:1646 */
break;
-#line 1757 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1760 "cmFortranParser.cxx" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
#endif
return yyresult;
}
-#line 246 "cmFortranParser.y" /* yacc.c:1906 */
+#line 249 "cmFortranParser.y" /* yacc.c:1906 */
/* End of grammar */
# pragma warning (disable: 4127) /* Conditional expression is constant. */
# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
union YYSTYPE
{
-#line 70 "cmFortranParser.y" /* yacc.c:1909 */
+#line 73 "cmFortranParser.y" /* yacc.c:1909 */
char* string;
typedef cmsys::CommandLineArguments argT;
arg.AddArgument("-B", argT::CONCAT_ARGUMENT, &binaryDirectory,
"Binary Directory");
- arg.AddArgument("-H", argT::CONCAT_ARGUMENT, &sourceDirectory,
+ arg.AddArgument("-S", argT::CONCAT_ARGUMENT, &sourceDirectory,
"Source Directory");
// do not complain about unknown options
arg.StoreUnusedArguments(true);
QMenu* ToolsMenu = this->menuBar()->addMenu(tr("&Tools"));
this->ConfigureAction = ToolsMenu->addAction(tr("&Configure"));
- // prevent merging with Preferences menu item on Mac OS X
+ // prevent merging with Preferences menu item on macOS
this->ConfigureAction->setMenuRole(QAction::NoRole);
QObject::connect(this->ConfigureAction, SIGNAL(triggered(bool)), this,
SLOT(doConfigure()));
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="styleSheet">
+ <string notr="true">padding-left: 0</string>
+ </property>
<property name="editable">
<bool>true</bool>
</property>
}
const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
if (gen) {
- const char* extraGen =
+ const std::string* extraGen =
state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
std::string curGen =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- gen, extraGen ? extraGen : "");
+ gen, extraGen ? *extraGen : "");
this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
}
// Can remove this function and FileDialogFlag when minimum Qt version is 4.5
bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt)
{
- // workaround for what looks like a bug in Qt on Mac OS X
+ // workaround for what looks like a bug in Qt on macOS
// where it doesn't create a QWidget wrapper for the native file dialog
// so the Qt library ends up assuming the focus was lost to something else
return false;
}
- // Convert working directory to a full path.
- if (!working.empty()) {
- const char* build_dir = this->Makefile->GetCurrentBinaryDirectory();
- working = cmSystemTools::CollapseFullPath(working, build_dir);
- }
-
// Choose which mode of the command to use.
bool escapeOldStyle = !verbatim;
if (source.empty() && output.empty()) {
}
}
- // Convert working directory to a full path.
- if (!working_directory.empty()) {
- const char* build_dir = this->Makefile->GetCurrentBinaryDirectory();
- working_directory =
- cmSystemTools::CollapseFullPath(working_directory, build_dir);
- }
-
if (commandLines.empty() && !byproducts.empty()) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddLinkOptionsCommand.h"
+
+#include "cmMakefile.h"
+
+class cmExecutionStatus;
+
+bool cmAddLinkOptionsCommand::InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus&)
+{
+ if (args.empty()) {
+ return true;
+ }
+
+ for (std::string const& i : args) {
+ this->Makefile->AddLinkOption(i);
+ }
+ return true;
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmAddLinkOptionsCommand_h
+#define cmAddLinkOptionsCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmCommand.h"
+
+class cmExecutionStatus;
+
+class cmAddLinkOptionsCommand : public cmCommand
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ cmCommand* Clone() override { return new cmAddLinkOptionsCommand; }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) override;
+};
+
+#endif
// Remove the CurrentDirectory from the srcPath and replace it
// with the CurrentOutputDirectory.
- const char* src = this->Makefile->GetCurrentSourceDirectory();
- const char* bin = this->Makefile->GetCurrentBinaryDirectory();
- size_t srcLen = strlen(src);
- size_t binLen = strlen(bin);
+ const std::string& src = this->Makefile->GetCurrentSourceDirectory();
+ const std::string& bin = this->Makefile->GetCurrentBinaryDirectory();
+ size_t srcLen = src.length();
+ size_t binLen = bin.length();
if (srcLen > 0 && src[srcLen - 1] == '/') {
--srcLen;
}
if (binLen > 0 && bin[binLen - 1] == '/') {
--binLen;
}
- binPath = std::string(bin, binLen) + srcPath.substr(srcLen);
+ binPath = bin.substr(0, binLen) + srcPath.substr(srcLen);
} else {
// Use the binary directory specified.
// Interpret a relative path with respect to the current binary directory.
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"
#include <iostream>
+#include <sstream>
#include <string.h>
#include <time.h>
return;
}
break;
- case CompressGZip:
+ case CompressGZip: {
if (archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) {
this->Error = "archive_write_add_filter_gzip: ";
this->Error += cm_archive_error_string(this->Archive);
return;
}
- break;
+ std::string source_date_epoch;
+ cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
+ if (!source_date_epoch.empty()) {
+ // We're not able to specify an arbitrary timestamp for gzip.
+ // The next best thing is to omit the timestamp entirely.
+ if (archive_write_set_filter_option(this->Archive, "gzip", "timestamp",
+ nullptr) != ARCHIVE_OK) {
+ this->Error = "archive_write_set_filter_option: ";
+ this->Error += cm_archive_error_string(this->Archive);
+ return;
+ }
+ }
+ } break;
case CompressBZip2:
if (archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) {
this->Error = "archive_write_add_filter_bzip2: ";
return false;
}
archive_entry_set_mtime(e, t, 0);
+ } else {
+ std::string source_date_epoch;
+ cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
+ if (!source_date_epoch.empty()) {
+ std::istringstream iss(source_date_epoch);
+ time_t epochTime;
+ iss >> epochTime;
+ if (iss.eof() && !iss.fail()) {
+ archive_entry_set_mtime(e, epochTime, 0);
+ }
+ }
}
// manages the uid/guid of the entry (if any)
cmSystemTools::RunSingleCommand("uname -a", &buildname, &buildname);
if (!buildname.empty()) {
std::string RegExp = "([^ ]*) [^ ]* ([^ ]*) ";
- cmsys::RegularExpression reg(RegExp.c_str());
- if (reg.find(buildname.c_str())) {
+ cmsys::RegularExpression reg(RegExp);
+ if (reg.find(buildname)) {
buildname = reg.match(1) + "-" + reg.match(2);
}
}
const char* CCONV cmGetStartDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentSourceDirectory();
+ return mf->GetCurrentSourceDirectory().c_str();
}
const char* CCONV cmGetStartOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentBinaryDirectory();
+ return mf->GetCurrentBinaryDirectory().c_str();
}
const char* CCONV cmGetCurrentDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentSourceDirectory();
+ return mf->GetCurrentSourceDirectory().c_str();
}
const char* CCONV cmGetCurrentOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentBinaryDirectory();
+ return mf->GetCurrentBinaryDirectory().c_str();
}
const char* CCONV cmGetDefinition(void* arg, const char* def)
{
" for directory ", d);
return;
}
- t->AddLinkDirectory(d);
+ t->InsertLinkDirectory(d, mf->GetBacktrace());
}
void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/Process.h"
-#include "cmsys/String.hxx"
#include "cmsys/SystemInformation.hxx"
#include <algorithm>
#include <chrono>
#include <time.h>
#include <utility>
#include <vector>
+#if defined(_WIN32)
+# include <windows.h> // IWYU pragma: keep
+#else
+# include <unistd.h> // IWYU pragma: keep
+#endif
#include "cmAlgorithms.h"
#include "cmCTestBuildAndTestHandler.h"
this->Failover = false;
this->ForceNewCTestProcess = false;
this->TomorrowTag = false;
+ this->TestProgressOutput = false;
+ this->FlushTestProgressLine = false;
this->Verbose = false;
this->Debug = false;
this->OutputTestOutputOnTestFailure = false;
this->RepeatTests = 1; // default to run each test once
this->RepeatUntilFail = false;
- std::string outOnFail;
- if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", outOnFail)) {
- this->OutputTestOutputOnTestFailure =
- !cmSystemTools::IsOff(outOnFail.c_str());
+
+ std::string envValue;
+ if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", envValue)) {
+ this->OutputTestOutputOnTestFailure = !cmSystemTools::IsOff(envValue);
+ }
+ envValue.clear();
+ if (cmSystemTools::GetEnv("CTEST_PROGRESS_OUTPUT", envValue)) {
+ this->TestProgressOutput = !cmSystemTools::IsOff(envValue);
}
+
this->InitStreams();
this->Parts[PartStart].SetName("Start");
}
}
if (this->ProduceXML) {
- this->CompressXMLFiles = cmSystemTools::IsOn(
- this->GetCTestConfiguration("CompressSubmission").c_str());
+ this->CompressXMLFiles =
+ cmSystemTools::IsOn(this->GetCTestConfiguration("CompressSubmission"));
}
return true;
}
}
}
std::string filename = testingDir + "/" + name;
- stream.Open(filename.c_str());
+ stream.Open(filename);
if (!stream) {
cmCTestLog(this, ERROR_MESSAGE,
"Problem opening file: " << filename << std::endl);
this->AddSiteProperties(xml);
xml.StartElement("Notes");
- for (cmsys::String const& file : files) {
+ for (std::string const& file : files) {
cmCTestLog(this, OUTPUT, "\tAdd file: " << file << std::endl);
std::string note_time = this->CurrentTime();
xml.StartElement("Note");
bool cmCTest::SubmitExtraFiles(const VectorOfStrings& files)
{
- for (cmsys::String const& file : files) {
+ for (std::string const& file : files) {
if (!cmSystemTools::FileExists(file)) {
cmCTestLog(this, ERROR_MESSAGE,
"Cannot find extra file: " << file << " to submit."
if (this->CheckArgument(arg, "-Q", "--quiet")) {
this->Quiet = true;
}
+ if (this->CheckArgument(arg, "--progress")) {
+ this->TestProgressOutput = true;
+ }
if (this->CheckArgument(arg, "-V", "--verbose")) {
this->Verbose = true;
}
if (this->CheckArgument(arg, "--interactive-debug-mode") &&
i < args.size() - 1) {
i++;
- this->InteractiveDebugMode = cmSystemTools::IsOn(args[i].c_str());
+ this->InteractiveDebugMode = cmSystemTools::IsOn(args[i]);
}
if (this->CheckArgument(arg, "--submit-index") && i < args.size() - 1) {
i++;
return true;
}
+bool cmCTest::ProgressOutputSupportedByConsole() const
+{
+#if defined(_WIN32)
+ // On Windows we need a console buffer.
+ void* console = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ return GetConsoleScreenBufferInfo(console, &csbi);
+#else
+ // On UNIX we need a non-dumb tty.
+ std::string term_env_variable;
+ if (cmSystemTools::GetEnv("TERM", term_env_variable)) {
+ return isatty(1) && term_env_variable != "dumb";
+ }
+#endif
+ return false;
+}
+
// handle the -S -SR and -SP arguments
void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
bool& SRArgumentSpecified)
}
}
+ // TestProgressOutput only supported if console supports it and not logging
+ // to a file
+ this->TestProgressOutput = this->TestProgressOutput &&
+ !this->OutputLogFile && this->ProgressOutputSupportedByConsole();
+#ifdef _WIN32
+ if (this->TestProgressOutput) {
+ // Disable output line buffering so we can print content without
+ // a newline.
+ std::setvbuf(stdout, nullptr, _IONBF, 0);
+ }
+#endif
+
// now what should cmake do? if --build-and-test was specified then
// we run the build and test handler and return
if (cmakeAndTest) {
"OUTPUT",
"HANDLER_OUTPUT",
"HANDLER_PROGRESS_OUTPUT",
+ "HANDLER_TEST_PROGRESS_OUTPUT",
"HANDLER_VERBOSE_OUTPUT",
"WARNING",
"ERROR_MESSAGE",
if (!this->Quiet) {
std::ostream& out = *this->StreamOut;
std::ostream& err = *this->StreamErr;
+
+ if (logType == HANDLER_TEST_PROGRESS_OUTPUT) {
+ if (this->TestProgressOutput) {
+ cmCTestLogOutputFileLine(out);
+ if (this->FlushTestProgressLine) {
+ printf("\r");
+ this->FlushTestProgressLine = false;
+ out.flush();
+ }
+
+ std::string msg_str{ msg };
+ auto const lineBreakIt = msg_str.find('\n');
+ if (lineBreakIt != std::string::npos) {
+ this->FlushTestProgressLine = true;
+ msg_str.erase(std::remove(msg_str.begin(), msg_str.end(), '\n'),
+ msg_str.end());
+ }
+
+ out << msg_str;
+#ifndef _WIN32
+ printf("\x1B[K"); // move caret to end
+#endif
+ out.flush();
+ return;
+ }
+ logType = HANDLER_OUTPUT;
+ }
+
switch (logType) {
case DEBUG:
if (this->Debug) {
#include "cmDuration.h"
#include "cmProcessOutput.h"
-#include "cmsys/String.hxx"
+
#include <chrono>
#include <map>
#include <set>
if the string does not name a valid part. */
Part GetPartFromName(const char* name);
- typedef std::vector<cmsys::String> VectorOfStrings;
+ typedef std::vector<std::string> VectorOfStrings;
typedef std::set<std::string> SetOfStrings;
/** Process Command line arguments */
OUTPUT,
HANDLER_OUTPUT,
HANDLER_PROGRESS_OUTPUT,
+ HANDLER_TEST_PROGRESS_OUTPUT,
HANDLER_VERBOSE_OUTPUT,
WARNING,
ERROR_MESSAGE,
void SetFailover(bool failover) { this->Failover = failover; }
bool GetFailover() { return this->Failover; }
+ bool GetTestProgressOutput() const { return this->TestProgressOutput; }
+
bool GetVerbose() { return this->Verbose; }
bool GetExtraVerbose() { return this->ExtraVerbose; }
std::string ConfigType;
std::string ScheduleType;
std::chrono::system_clock::time_point StopTime;
+ bool TestProgressOutput;
bool Verbose;
bool ExtraVerbose;
bool ProduceXML;
bool PrintLabels;
bool Failover;
+ bool FlushTestProgressLine;
+
bool ForceNewCTestProcess;
bool RunConfigurationScript;
bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args,
std::string& errormsg);
+ /** returns true iff the console supports progress output */
+ bool ProgressOutputSupportedByConsole() const;
+
/** handle the -S -SP and -SR arguments */
void HandleScriptArguments(size_t& i, std::vector<std::string>& args,
bool& SRArgumentSpecified);
}
this->CacheMajorVersion = 0;
this->CacheMinorVersion = 0;
- if (const char* cmajor =
+ if (const std::string* cmajor =
this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) {
unsigned int v = 0;
- if (sscanf(cmajor, "%u", &v) == 1) {
+ if (sscanf(cmajor->c_str(), "%u", &v) == 1) {
this->CacheMajorVersion = v;
}
- if (const char* cminor =
+ if (const std::string* cminor =
this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) {
- if (sscanf(cminor, "%u", &v) == 1) {
+ if (sscanf(cminor->c_str(), "%u", &v) == 1) {
this->CacheMinorVersion = v;
}
}
}
// check to make sure the cache directory has not
// been moved
- const char* oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ const std::string* oldDir =
+ this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
if (internal && oldDir) {
std::string currentcwd = path;
- std::string oldcwd = oldDir;
+ std::string oldcwd = *oldDir;
cmSystemTools::ConvertToUnixSlashes(currentcwd);
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
+ const std::string* dir =
+ this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
std::ostringstream message;
message << "The current CMakeCache.txt directory " << currentcwd
- << " is different than the directory "
- << this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")
+ << " is different than the directory " << (dir ? *dir : "")
<< " where CMakeCache.txt was created. This may result "
"in binaries being created in the wrong place. If you "
"are not sure, reedit the CMakeCache.txt";
{
std::string cacheFile = path;
cacheFile += "/CMakeCache.txt";
- cmGeneratedFileStream fout(cacheFile.c_str());
+ cmGeneratedFileStream fout(cacheFile);
fout.SetCopyIfDifferent(true);
if (!fout) {
cmSystemTools::Error("Unable to open cache file for save. ",
return CacheIterator(*this, key);
}
-const char* cmCacheManager::GetInitializedCacheValue(
+const std::string* cmCacheManager::GetInitializedCacheValue(
const std::string& key) const
{
CacheEntryMap::const_iterator i = this->Cache.find(key);
if (i != this->Cache.end() && i->second.Initialized) {
- return i->second.Value.c_str();
+ return &i->second.Value;
}
return nullptr;
}
bool cmCacheManager::CacheIterator::GetValueAsBool() const
{
- return cmSystemTools::IsOn(this->GetEntry().Value.c_str());
+ return cmSystemTools::IsOn(this->GetEntry().Value);
}
std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
int GetSize() { return static_cast<int>(this->Cache.size()); }
///! Get a value from the cache given a key
- const char* GetInitializedCacheValue(const std::string& key) const;
+ const std::string* GetInitializedCacheValue(const std::string& key) const;
const char* GetCacheEntryValue(const std::string& key)
{
return "";
}
if (strcmp(key, "CACHE") == 0) {
- if (const char* c =
+ if (const std::string* c =
this->Makefile->GetState()->GetInitializedCacheValue(var)) {
if (this->EscapeQuotes) {
- return this->AddString(cmSystemTools::EscapeQuotes(c));
+ return this->AddString(cmSystemTools::EscapeQuotes(*c));
}
- return this->AddString(c);
+ return this->AddString(*c);
}
return "";
}
return;
}
char* out = new char[len + 1];
- strncpy(out, str, len);
+ memcpy(out, str, len);
out[len] = 0;
pt->str = out;
this->Variables.push_back(out);
void cmCommandArgumentParserHelper::CleanupParser()
{
- std::vector<char*>::iterator sit;
for (char* var : this->Variables) {
delete[] var;
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmAddCompileOptionsCommand.h"
+# include "cmAddLinkOptionsCommand.h"
# include "cmAuxSourceDirectoryCommand.h"
# include "cmBuildNameCommand.h"
# include "cmCMakeHostSystemInformationCommand.h"
# include "cmRemoveDefinitionsCommand.h"
# include "cmSourceGroupCommand.h"
# include "cmSubdirDependsCommand.h"
+# include "cmTargetLinkDirectoriesCommand.h"
+# include "cmTargetLinkOptionsCommand.h"
# include "cmUseMangledMesaCommand.h"
# include "cmUtilitySourceCommand.h"
# include "cmVariableRequiresCommand.h"
state->AddBuiltinCommand("include_external_msproject",
new cmIncludeExternalMSProjectCommand);
state->AddBuiltinCommand("install_programs", new cmInstallProgramsCommand);
+ state->AddBuiltinCommand("add_link_options", new cmAddLinkOptionsCommand);
state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand);
+ state->AddBuiltinCommand("target_link_options",
+ new cmTargetLinkOptionsCommand);
+ state->AddBuiltinCommand("target_link_directories",
+ new cmTargetLinkDirectoriesCommand);
state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand);
state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand);
state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand);
return this->FinalLinkEntries;
}
-std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
- std::string const& item)
+std::map<cmLinkItem, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
+ cmLinkItem const& item)
{
- std::map<std::string, int>::value_type index_entry(
+ std::map<cmLinkItem, int>::value_type index_entry(
item, static_cast<int>(this->EntryList.size()));
- std::map<std::string, int>::iterator lei =
+ std::map<cmLinkItem, int>::iterator lei =
this->LinkEntryIndex.insert(index_entry).first;
this->EntryList.emplace_back();
this->InferredDependSets.push_back(nullptr);
int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
{
// Check if the item entry has already been added.
- std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item);
+ std::map<cmLinkItem, int>::iterator lei = this->LinkEntryIndex.find(item);
if (lei != this->LinkEntryIndex.end()) {
// Yes. We do not need to follow the item's dependencies again.
return lei->second;
// Initialize the item entry.
int index = lei->second;
LinkEntry& entry = this->EntryList[index];
- entry.Item = item;
+ entry.Item = item.AsStr();
entry.Target = item.Target;
- entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
- item.substr(0, 10) != "-framework");
+ entry.IsFlag =
+ (!entry.Target && entry.Item[0] == '-' && entry.Item[1] != 'l' &&
+ entry.Item.substr(0, 10) != "-framework");
// If the item has dependencies queue it to follow them.
if (entry.Target) {
void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
{
// Check if the target already has an entry.
- std::map<std::string, int>::iterator lei =
+ std::map<cmLinkItem, int>::iterator lei =
this->LinkEntryIndex.find(dep.Item);
if (lei == this->LinkEntryIndex.end()) {
// Allocate a spot for the item entry.
// Initialize the item entry.
LinkEntry& entry = this->EntryList[lei->second];
- entry.Item = dep.Item;
+ entry.Item = dep.Item.AsStr();
entry.Target = dep.Item.Target;
// This item was added specifically because it is a dependent
// If the library is meant for this link type then use it.
if (llt == GENERAL_LibraryType || llt == this->LinkType) {
- actual_libs.emplace_back(d, this->FindTargetToLink(depender_index, d));
+ actual_libs.emplace_back(this->ResolveLinkItem(depender_index, d));
} else if (this->OldLinkDirMode) {
- cmLinkItem item(d, this->FindTargetToLink(depender_index, d));
+ cmLinkItem item = this->ResolveLinkItem(depender_index, d);
this->CheckWrongConfigItem(item);
}
// Skip entries that will resolve to the target getting linked or
// are empty.
cmLinkItem const& item = l;
- if (item == this->Target->GetName() || item.empty()) {
+ if (item.AsStr() == this->Target->GetName() || item.AsStr().empty()) {
continue;
}
}
}
-cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink(
- int depender_index, const std::string& name)
+cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index,
+ const std::string& name)
{
// Look for a target in the scope of the depender.
cmGeneratorTarget const* from = this->Target;
from = depender;
}
}
- return from->FindTargetToLink(name);
+ return from->ResolveLinkItem(name);
}
void cmComputeLinkDepends::InferDependencies()
std::string Config;
EntryVector FinalLinkEntries;
- std::map<std::string, int>::iterator AllocateLinkEntry(
- std::string const& item);
+ std::map<cmLinkItem, int>::iterator AllocateLinkEntry(
+ cmLinkItem const& item);
int AddLinkEntry(cmLinkItem const& item);
void AddVarLinkEntries(int depender_index, const char* value);
void AddDirectLinkEntries();
template <typename T>
void AddLinkEntries(int depender_index, std::vector<T> const& libs);
- cmGeneratorTarget const* FindTargetToLink(int depender_index,
- const std::string& name);
+ cmLinkItem ResolveLinkItem(int depender_index, const std::string& name);
// One entry for each unique item.
std::vector<LinkEntry> EntryList;
- std::map<std::string, int> LinkEntryIndex;
+ std::map<cmLinkItem, int> LinkEntryIndex;
// BFS of initial dependencies.
struct BFSEntry
------------------------------------------------------------------------------
-Linux, FreeBSD, Mac OS X, IRIX, Sun, Windows:
+Linux, FreeBSD, macOS, IRIX, Sun, Windows:
Linking to libraries using the full path works fine.
}
// Add the search path entries requested by the user to path ordering.
- this->OrderLinkerSearchPath->AddUserDirectories(
- this->Target->GetLinkDirectories());
- this->OrderRuntimeSearchPath->AddUserDirectories(
- this->Target->GetLinkDirectories());
+ std::vector<std::string> directories;
+ this->Target->GetLinkDirectories(directories, config, this->LinkLanguage);
+ this->OrderLinkerSearchPath->AddUserDirectories(directories);
+ this->OrderRuntimeSearchPath->AddUserDirectories(directories);
// Set up the implicit link directories.
this->LoadImplicitLinkInfo();
if (this->OldLinkDirMode) {
// Construct a mask to not bother with this behavior for link
// directories already specified by the user.
- std::vector<std::string> const& dirs = this->Target->GetLinkDirectories();
- this->OldLinkDirMask.insert(dirs.begin(), dirs.end());
+ this->OldLinkDirMask.insert(directories.begin(), directories.end());
}
this->CMP0060Warn = this->Makefile->PolicyOptionalWarningEnabled(
}
const char* stagePath =
this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
- const char* installPrefix =
+ std::string const& installPrefix =
this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
cmSystemTools::ConvertToUnixSlashes(rootPath);
std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath();
// dependencies in all targets, because the generated build-systems can't
// deal with config-specific dependencies.
{
- std::set<std::string> emitted;
+ std::set<cmLinkItem> emitted;
std::vector<std::string> configs;
depender->Makefile->GetConfigurations(configs);
std::vector<cmSourceFile const*> objectFiles;
depender->GetExternalObjects(objectFiles, it);
for (cmSourceFile const* o : objectFiles) {
- std::string objLib = o->GetObjectLibrary();
- if (!objLib.empty() && emitted.insert(objLib).second) {
- if (depender->GetType() != cmStateEnums::EXECUTABLE &&
- depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
- depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
- depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
- depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR,
- "Only executables and libraries may reference target objects.",
- depender->GetBacktrace());
- return;
+ std::string const& objLib = o->GetObjectLibrary();
+ if (!objLib.empty()) {
+ cmLinkItem const& objItem = depender->ResolveLinkItem(objLib);
+ if (emitted.insert(objItem).second) {
+ if (depender->GetType() != cmStateEnums::EXECUTABLE &&
+ depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR,
+ "Only executables and libraries may reference target objects.",
+ depender->GetBacktrace());
+ return;
+ }
+ const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(
+ objLib);
}
- const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib);
}
}
cmLinkImplementation const* impl = depender->GetLinkImplementation(it);
// A target should not depend on itself.
- emitted.insert(depender->GetName());
+ emitted.insert(cmLinkItem(depender));
for (cmLinkImplItem const& lib : impl->Libraries) {
// Don't emit the same library twice for this target.
if (emitted.insert(lib).second) {
// Loop over all utility dependencies.
{
std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
- std::set<std::string> emitted;
+ std::set<cmLinkItem> emitted;
// A target should not depend on itself.
- emitted.insert(depender->GetName());
+ emitted.insert(cmLinkItem(depender));
for (cmLinkItem const& litem : tutils) {
// Don't emit the same utility twice for this target.
if (emitted.insert(litem).second) {
void cmComputeTargetDepends::AddInterfaceDepends(
int depender_index, const cmGeneratorTarget* dependee,
- const std::string& config, std::set<std::string>& emitted)
+ const std::string& config, std::set<cmLinkItem>& emitted)
{
cmGeneratorTarget const* depender = this->Targets[depender_index];
if (cmLinkInterface const* iface =
void cmComputeTargetDepends::AddInterfaceDepends(
int depender_index, cmLinkItem const& dependee_name,
- const std::string& config, std::set<std::string>& emitted)
+ const std::string& config, std::set<cmLinkItem>& emitted)
{
cmGeneratorTarget const* depender = this->Targets[depender_index];
cmGeneratorTarget const* dependee = dependee_name.Target;
if (dependee) {
// A target should not depend on itself.
- emitted.insert(depender->GetName());
+ emitted.insert(cmLinkItem(depender));
this->AddInterfaceDepends(depender_index, dependee, config, emitted);
}
}
<< depender->GetName() << "\" does not exist.";
cmListFileBacktrace const* backtrace =
- depender->GetUtilityBacktrace(dependee_name);
+ depender->GetUtilityBacktrace(dependee_name.AsStr());
if (backtrace) {
cm->IssueMessage(messageType, e.str(), *backtrace);
} else {
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
const std::string& config,
- std::set<std::string>& emitted);
+ std::set<cmLinkItem>& emitted);
void AddInterfaceDepends(int depender_index,
cmGeneratorTarget const* dependee,
const std::string& config,
- std::set<std::string>& emitted);
+ std::set<cmLinkItem>& emitted);
cmGlobalGenerator* GlobalGenerator;
bool DebugMode;
bool NoCycles;
}
std::string const& inFile = args[0];
- if (!cmSystemTools::FileIsFullPath(inFile)) {
- this->InputFile = this->Makefile->GetCurrentSourceDirectory();
- this->InputFile += "/";
- }
- this->InputFile += inFile;
+ this->InputFile = cmSystemTools::CollapseFullPath(
+ inFile, this->Makefile->GetCurrentSourceDirectory());
// If the input location is a directory, error out.
if (cmSystemTools::FileIsDirectory(this->InputFile)) {
}
std::string const& outFile = args[1];
- if (!cmSystemTools::FileIsFullPath(outFile)) {
- this->OutputFile = this->Makefile->GetCurrentBinaryDirectory();
- this->OutputFile += "/";
- }
- this->OutputFile += outFile;
+ this->OutputFile = cmSystemTools::CollapseFullPath(
+ outFile, this->Makefile->GetCurrentBinaryDirectory());
// If the output location is already a directory put the file in it.
if (cmSystemTools::FileIsDirectory(this->OutputFile)) {
}
this->Depends.insert(this->Depends.end(), result.begin(), result.end());
}
+
+ const std::string& workingdirectory = this->CC.GetWorkingDirectory();
+ if (!workingdirectory.empty()) {
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ this->GE->Parse(workingdirectory);
+ this->WorkingDirectory = cge->Evaluate(this->LG, this->Config);
+ // Convert working directory to a full path.
+ if (!this->WorkingDirectory.empty()) {
+ std::string const& build_dir = this->LG->GetCurrentBinaryDirectory();
+ this->WorkingDirectory =
+ cmSystemTools::CollapseFullPath(this->WorkingDirectory, build_dir);
+ }
+ }
}
cmCustomCommandGenerator::~cmCustomCommandGenerator()
std::string cmCustomCommandGenerator::GetWorkingDirectory() const
{
- return this->CC.GetWorkingDirectory();
+ return this->WorkingDirectory;
}
std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
cmGeneratorExpression* GE;
cmCustomCommandLines CommandLines;
std::vector<std::string> Depends;
+ std::string WorkingDirectory;
const char* GetCrossCompilingEmulator(unsigned int c) const;
const char* GetArgv0Location(unsigned int c) const;
return begin->Map.insert(MapType::value_type(key, def)).first->second;
}
-const char* cmDefinitions::Get(const std::string& key, StackIter begin,
- StackIter end)
+const std::string* cmDefinitions::Get(const std::string& key, StackIter begin,
+ StackIter end)
{
Def const& def = cmDefinitions::GetInternal(key, begin, end, false);
- return def.Exists ? def.c_str() : nullptr;
+ return def.Exists ? &def : nullptr;
}
void cmDefinitions::Raise(const std::string& key, StackIter begin,
typedef cmLinkedTree<cmDefinitions>::iterator StackIter;
public:
- static const char* Get(const std::string& key, StackIter begin,
- StackIter end);
+ static const std::string* Get(const std::string& key, StackIter begin,
+ StackIter end);
static void Raise(const std::string& key, StackIter begin, StackIter end);
std::string srcLang = "CMAKE_DEPENDS_CHECK_";
srcLang += this->Language;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- const char* srcStr = mf->GetSafeDefinition(srcLang);
+ std::string const& srcStr = mf->GetSafeDefinition(srcLang);
std::vector<std::string> pairs;
cmSystemTools::ExpandListArgument(srcStr, pairs);
// Complain if the file cannot be found and matches the complain
// regex.
if (fullName.empty() &&
- this->IncludeRegexComplain.find(current.FileName.c_str())) {
+ this->IncludeRegexComplain.find(current.FileName)) {
cmSystemTools::Error("Cannot find file \"", current.FileName.c_str(),
"\".");
return false;
}
// Match include directives.
- if (this->IncludeRegexLine.find(line.c_str())) {
+ if (this->IncludeRegexLine.find(line)) {
// Get the file being included.
UnscannedEntry entry;
entry.FileName = this->IncludeRegexLine.match(2);
// file their own directory by simply using "filename.h" (#12619)
// This kind of problem will be fixed when a more
// preprocessor-like implementation of this scanner is created.
- if (this->IncludeRegexScan.find(entry.FileName.c_str())) {
+ if (this->IncludeRegexScan.find(entry.FileName)) {
newCacheEntry->UnscannedEntries.push_back(entry);
if (this->Encountered.find(entry.FileName) ==
this->Encountered.end()) {
void cmDependsC::TransformLine(std::string& line)
{
// Check for a transform rule match. Return if none.
- if (!this->IncludeRegexTransform.find(line.c_str())) {
+ if (!this->IncludeRegexTransform.find(line)) {
return;
}
TransformRulesType::const_iterator tri =
// Store the list of modules provided by this target.
std::string fiName = this->TargetDirectory;
fiName += "/fortran.internal";
- cmGeneratedFileStream fiStream(fiName.c_str());
+ cmGeneratedFileStream fiStream(fiName);
fiStream << "# The fortran modules provided by this target.\n";
fiStream << "provides\n";
std::set<std::string> const& provides = this->Internal->TargetProvides;
if (!provides.empty()) {
std::string fcName = this->TargetDirectory;
fcName += "/cmake_clean_Fortran.cmake";
- cmGeneratedFileStream fcStream(fcName.c_str());
+ cmGeneratedFileStream fcStream(fcName);
fcStream << "# Remove fortran modules provided by this target.\n";
fcStream << "FILE(REMOVE";
std::string currentBinDir =
void cmDocumentationFormatter::PrintColumn(std::ostream& os, const char* text)
{
- // Print text arranged in an indented column of fixed witdh.
+ // Print text arranged in an indented column of fixed width.
const char* l = text;
long column = 0;
bool newSentence = false;
#include <sstream>
#include <utility>
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmAlgorithms.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
-#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
os << "LOCAL_CPP_FEATURES += ";
os << (property.second) << "\n";
} else if (property.first == "INTERFACE_LINK_LIBRARIES") {
- // evaluate any generator expressions with the current
- // build type of the makefile
- cmGeneratorExpression ge;
- cmGeneratorExpressionDAGChecker dagChecker(
- target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
- std::unique_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(property.second);
- std::string evaluated = cge->Evaluate(
- target->GetLocalGenerator(), config, false, target, &dagChecker);
- // need to look at list in pi->second and see if static or shared
- // FindTargetToLink
- // target->GetLocalGenerator()->FindGeneratorTargetToUse()
- // then add to LOCAL_CPPFLAGS
- std::vector<std::string> libraries;
- cmSystemTools::ExpandListArgument(evaluated, libraries);
std::string staticLibs;
std::string sharedLibs;
std::string ldlibs;
- for (std::string const& lib : libraries) {
- cmGeneratorTarget* gt =
- target->GetLocalGenerator()->FindGeneratorTargetToUse(lib);
+ cmLinkInterfaceLibraries const* linkIFace =
+ target->GetLinkInterfaceLibraries(config, target, false);
+ for (cmLinkItem const& item : linkIFace->Libraries) {
+ cmGeneratorTarget const* gt = item.Target;
+ std::string const& lib = item.AsStr();
if (gt) {
if (gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
end = "\\\n";
}
os << "\n";
+ } else if (property.first == "INTERFACE_LINK_OPTIONS") {
+ os << "LOCAL_EXPORT_LDFLAGS := ";
+ std::vector<std::string> linkFlagsList;
+ cmSystemTools::ExpandListArgument(property.second, linkFlagsList);
+ os << cmJoin(linkFlagsList, " ") << "\n";
} else {
os << "# " << property.first << " " << (property.second) << "\n";
}
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
properties);
}
const char* packageExpr = "^[A-Za-z0-9_.-]+$";
cmsys::RegularExpression packageRegex(packageExpr);
- if (!packageRegex.find(package.c_str())) {
+ if (!packageRegex.find(package)) {
std::ostringstream e;
e << "PACKAGE given invalid package name \"" << package << "\". "
<< "Package names must match \"" << packageExpr << "\".";
// We store the current build directory in the registry as a value
// named by a hash of its own content. This is deterministic and is
// unique with high probability.
- const char* outDir = this->Makefile->GetCurrentBinaryDirectory();
+ const std::string& outDir = this->Makefile->GetCurrentBinaryDirectory();
std::string hash = cmSystemTools::ComputeStringMD5(outDir);
#if defined(_WIN32) && !defined(__CYGWIN__)
- this->StorePackageRegistryWin(package, outDir, hash.c_str());
+ this->StorePackageRegistryWin(package, outDir.c_str(), hash.c_str());
#else
- this->StorePackageRegistryDir(package, outDir, hash.c_str());
+ this->StorePackageRegistryDir(package, outDir.c_str(), hash.c_str());
#endif
return true;
fname += "/";
fname += hash;
if (!cmSystemTools::FileExists(fname)) {
- cmGeneratedFileStream entry(fname.c_str(), true);
+ cmGeneratedFileStream entry(fname, true);
if (entry) {
entry << content << "\n";
} else {
} else {
// Generate atomically and with copy-if-different.
std::unique_ptr<cmGeneratedFileStream> ap(
- new cmGeneratedFileStream(this->MainImportFile.c_str(), true));
+ new cmGeneratedFileStream(this->MainImportFile, true));
ap->SetCopyIfDifferent(true);
foutPtr = std::move(ap);
}
cmGeneratorTarget* target,
const std::string& prop)
{
- const char* installDir =
+ std::string const& installDir =
target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
std::string const& topSourceDir =
target->GetLocalGenerator()->GetSourceDirectory();
}
}
+void cmExportFileGenerator::PopulateLinkDependsInterface(
+ cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
+{
+ cmGeneratorTarget* gt = tei->Target;
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ const char* propName = "INTERFACE_LINK_DEPENDS";
+ const char* input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
+ }
+
+ if (!*input) {
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets);
+
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
+}
+
+void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
+ cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
+{
+ cmGeneratorTarget* gt = tei->Target;
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ const char* propName = "INTERFACE_LINK_DIRECTORIES";
+ const char* input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
+ }
+
+ if (!*input) {
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets);
+
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
+}
+
void cmExportFileGenerator::PopulateInterfaceProperty(
const std::string& propName, cmGeneratorTarget* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
std::string& input, cmGeneratorTarget* target,
std::vector<std::string>& missingTargets)
{
- cmLocalGenerator* lg = target->GetLocalGenerator();
+ cmGeneratorTarget::TargetOrString resolved =
+ target->ResolveTargetReference(input);
- cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(input);
+ cmGeneratorTarget* tgt = resolved.Target;
if (!tgt) {
+ input = resolved.String;
return false;
}
if (tgt->IsImported()) {
+ input = tgt->GetName();
return true;
}
if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) {
this->HandleMissingTarget(namespacedTarget, missingTargets, target, tgt);
if (!namespacedTarget.empty()) {
input = namespacedTarget;
+ } else {
+ input = tgt->GetName();
}
}
return true;
}
}
+static std::string const& asString(std::string const& l)
+{
+ return l;
+}
+
+static std::string const& asString(cmLinkItem const& l)
+{
+ return l.AsStr();
+}
+
template <typename T>
void cmExportFileGenerator::SetImportLinkProperty(
std::string const& suffix, cmGeneratorTarget* target,
link_entries += sep;
sep = ";";
- std::string temp = l;
+ std::string temp = asString(l);
this->AddTargetNamespace(temp, target, missingTargets);
link_entries += temp;
}
cmTargetExport* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+ void PopulateLinkDirectoriesInterface(
+ cmTargetExport* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+ void PopulateLinkDependsInterface(
+ cmTargetExport* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void SetImportLinkInterface(
const std::string& config, std::string const& suffix,
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateLinkDirectoriesInterface(
+ te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ this->PopulateLinkDependsInterface(
+ te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
std::string errorMessage;
if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
fileName += this->FileExt;
// Open the output file to generate it.
- cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
+ cmGeneratedFileStream exportFileStream(fileName, true);
if (!exportFileStream) {
std::string se = cmSystemTools::GetLastSystemError();
std::ostringstream e;
cm::make_unique<cmsys::ofstream>(this->Filename.c_str(), std::ios::app);
} else {
std::unique_ptr<cmGeneratedFileStream> ap(
- new cmGeneratedFileStream(this->Filename.c_str(), true));
+ new cmGeneratedFileStream(this->Filename, true));
ap->SetCopyIfDifferent(true);
foutPtr = std::move(ap);
}
cmGeneratorExpression ge;
- cmGeneratorExpressionDAGChecker dagChecker(tgt->GetName(), propName, nullptr,
- nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, nullptr);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
#include <iostream>
#include <sstream>
+#include <stdexcept>
+#include <utility>
int cmExpr_yyparse(yyscan_t yyscanner);
//
{
this->FileLine = -1;
this->FileName = nullptr;
+ this->Result = 0;
}
cmExprParserHelper::~cmExprParserHelper()
{
- this->CleanupParser();
}
int cmExprParserHelper::ParseString(const char* str, int verb)
yyscan_t yyscanner;
cmExpr_yylex_init(&yyscanner);
cmExpr_yyset_extra(this, yyscanner);
- int res = cmExpr_yyparse(yyscanner);
+
+ try {
+ int res = cmExpr_yyparse(yyscanner);
+ if (res != 0) {
+ std::string e = "cannot parse the expression: \"" + InputBuffer + "\": ";
+ e += ErrorString;
+ e += ".";
+ this->SetError(std::move(e));
+ }
+ } catch (std::runtime_error const& fail) {
+ std::string e =
+ "cannot evaluate the expression: \"" + InputBuffer + "\": ";
+ e += fail.what();
+ e += ".";
+ this->SetError(std::move(e));
+ } catch (std::out_of_range const&) {
+ std::string e = "cannot evaluate the expression: \"" + InputBuffer +
+ "\": a numeric value is out of range.";
+ this->SetError(std::move(e));
+ } catch (...) {
+ std::string e = "cannot parse the expression: \"" + InputBuffer + "\".";
+ this->SetError(std::move(e));
+ }
cmExpr_yylex_destroy(yyscanner);
- if (res != 0) {
- // str << "CAL_Parser returned: " << res << std::endl;
- // std::cerr << "When parsing: [" << str << "]" << std::endl;
+ if (!this->ErrorString.empty()) {
return 0;
}
- this->CleanupParser();
-
if (Verbose) {
std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
<< std::endl;
return 1;
}
-void cmExprParserHelper::CleanupParser()
-{
-}
-
int cmExprParserHelper::LexInput(char* buf, int maxlen)
{
// std::cout << "JPLexInput ";
this->ErrorString = ostr.str();
}
-void cmExprParserHelper::SetResult(int value)
+void cmExprParserHelper::UnexpectedChar(char c)
+{
+ unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
+ std::ostringstream ostr;
+ ostr << "Unexpected character in expression at position " << pos << ": " << c
+ << "\n";
+ this->WarningString += ostr.str();
+}
+
+void cmExprParserHelper::SetResult(KWIML_INT_int64_t value)
{
this->Result = value;
}
+
+void cmExprParserHelper::SetError(std::string errorString)
+{
+ this->ErrorString = std::move(errorString);
+}
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cm_kwiml.h"
+
#include <string>
#include <vector>
public:
struct ParserType
{
- int Number;
+ KWIML_INT_int64_t Number;
};
cmExprParserHelper();
int LexInput(char* buf, int maxlen);
void Error(const char* str);
- void SetResult(int value);
+ void SetResult(KWIML_INT_int64_t value);
- int GetResult() { return this->Result; }
+ KWIML_INT_int64_t GetResult() { return this->Result; }
const char* GetError() { return this->ErrorString.c_str(); }
+ void UnexpectedChar(char c);
+
+ std::string const& GetWarning() const { return this->WarningString; }
+
private:
std::string::size_type InputBufferPos;
std::string InputBuffer;
void Print(const char* place, const char* str);
- void CleanupParser();
+ void SetError(std::string errorString);
- int Result;
+ KWIML_INT_int64_t Result;
const char* FileName;
long FileLine;
std::string ErrorString;
+ std::string WarningString;
};
#define YYSTYPE cmExprParserHelper::ParserType
const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
const cmMakefile* mf = lgs[0]->GetMakefile();
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
filename += "/";
filename += target->GetName();
filename += ".objlib";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (fout) {
/* clang-format off */
fout << "# This is a dummy file for the OBJECT library "
pureFortran = true;
}
- std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
+ std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar);
std::string compiler = "gcc"; // default to gcc
if (compilerId == "MSVC") {
if (mf->IsDefinitionSet("MSVC10")) {
}
}
- cmGeneratedFileStream fout(workspaceFileName.c_str());
+ cmGeneratedFileStream fout(workspaceFileName);
cmXMLWriter xml(fout);
xml.StartDocument("utf-8");
for (cmLocalGenerator* lg : lgs) {
for (cmGeneratorTarget* lt : lg->GetGeneratorTargets()) {
cmStateEnums::TargetType type = lt->GetType();
- std::string outputDir = lg->GetCurrentBinaryDirectory();
+ std::string const& outputDir = lg->GetCurrentBinaryDirectory();
std::string targetName = lt->GetName();
std::string filename = outputDir + "/" + targetName + ".project";
retval.push_back(targetName);
// for each sub project in the workspace create a codelite project
for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
- std::string outputDir = it.second[0]->GetCurrentBinaryDirectory();
+ std::string const& outputDir = it.second[0]->GetCurrentBinaryDirectory();
std::string projectName = it.second[0]->GetProjectName();
retval.push_back(projectName);
std::string filename = outputDir + "/" + projectName + ".project";
void cmExtraCodeLiteGenerator::CreateProjectFile(
const std::vector<cmLocalGenerator*>& lgs)
{
- std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
+ std::string const& outputDir = lgs[0]->GetCurrentBinaryDirectory();
std::string projectName = lgs[0]->GetProjectName();
std::string filename = outputDir + "/";
const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
const cmMakefile* mf = lgs[0]->GetMakefile();
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
const cmGeneratorTarget* gt, const std::string& filename)
{
const cmMakefile* mf = gt->Makefile;
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
compilerIdVar = "CMAKE_C_COMPILER_ID";
}
- std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
+ std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar);
std::string compiler = "gnu g++"; // default to g++
// Since we need the compiler for parsing purposes only
std::string eclipseVersion = mf->GetSafeDefinition("CMAKE_ECLIPSE_VERSION");
cmsys::RegularExpression regex(".*([0-9]+\\.[0-9]+).*");
- if (regex.find(eclipseVersion.c_str())) {
+ if (regex.find(eclipseVersion)) {
unsigned int majorVersion = 0;
unsigned int minorVersion = 0;
int res =
this->GetPathBasename(this->HomeDirectory));
const std::string filename = this->HomeDirectory + "/.project";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_";
cacheEntryName += envVar;
- const char* cacheValue =
+ const std::string* cacheValue =
lg->GetState()->GetInitializedCacheValue(cacheEntryName);
// now we have both, decide which one to use
mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory());
} else if (!envVarSet && cacheValue != nullptr) {
// It is already in the cache, but not in the env, so use it from the cache
- valueToUse = cacheValue;
+ valueToUse = *cacheValue;
} else {
// It is both in the cache and in the env.
// Use the version from the env. except if the value from the env is
// completely contained in the value from the cache (for the case that we
// now have a PATH without MSVC dirs in the env. but had the full PATH with
// all MSVC dirs during the cmake run which stored the var in the cache:
- valueToUse = cacheValue;
+ valueToUse = *cacheValue;
if (valueToUse.find(envVarValue) == std::string::npos) {
valueToUse = envVarValue;
mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
const std::string filename = this->HomeOutputDirectory + "/.project";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
// Frameworks/ part has to be stripped
// /System/Library/Frameworks/GLUT.framework/Headers
cmsys::RegularExpression frameworkRx("(.+/Frameworks)/.+\\.framework/");
- if (frameworkRx.find(dir.c_str())) {
+ if (frameworkRx.find(dir)) {
dir = frameworkRx.match(1);
}
const std::string filename = this->HomeOutputDirectory + "/.cproject";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
{
std::string filename = lg->GetBinaryDirectory();
filename += "/.kateproject";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
filename += "/";
filename += this->ProjectName;
filename += ".kateproject";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
{
const cmMakefile* mf = lgs[0]->GetMakefile();
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
lg->GetTargetCompileFlags(gtgt, config, language, flags);
// Add source file specific flags.
- cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config,
- gtgt->GetName(), language);
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, gtgt,
+ language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
cmMakefile* makefile = lg->GetMakefile();
const std::string& language = source->GetLanguage();
const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- cmGeneratorExpressionInterpreter genexInterpreter(
- lg, target, config, target->GetName(), language);
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+ language);
// Add the export symbol definition for shared library objects.
if (const char* exportMacro = target->GetExportMacro()) {
cmMakefile* makefile = lg->GetMakefile();
const std::string& language = source->GetLanguage();
const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- cmGeneratorExpressionInterpreter genexInterpreter(
- lg, target, config, target->GetName(), language);
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+ language);
// Add include directories for this source file
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
// what is the current source dir
std::string cdir = this->Makefile->GetCurrentSourceDirectory();
- const char* fluid_exe =
+ std::string const& fluid_exe =
this->Makefile->GetRequiredDefinition("FLTK_FLUID_EXECUTABLE");
// get parameter for the command
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
-#include "cmsys/String.hxx"
+
#include <algorithm>
#include <assert.h>
+#include <ctype.h>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
cmSystemTools::MakeDirectory(dir);
mode_t mode = 0;
+ bool writable = false;
// Set permissions to writable
if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) {
- cmSystemTools::SetPermissions(fileName.c_str(),
#if defined(_MSC_VER) || defined(__MINGW32__)
- mode | S_IWRITE
+ writable = mode & S_IWRITE;
+ mode_t newMode = mode | S_IWRITE;
#else
- mode | S_IWUSR | S_IWGRP
+ writable = mode & S_IWUSR;
+ mode_t newMode = mode | S_IWUSR | S_IWGRP;
#endif
- );
+ if (!writable) {
+ cmSystemTools::SetPermissions(fileName.c_str(), newMode);
+ }
}
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
return false;
}
file.close();
- if (mode) {
+ if (mode && !writable) {
cmSystemTools::SetPermissions(fileName.c_str(), mode);
}
return true;
continue;
}
- if ((c >= 0x20 && c < 0x7F) || c == '\t' ||
- (c == '\n' && newline_consume)) {
+ if (c >= 0 && c <= 0xFF &&
+ (isprint(c) || 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...
// The current line has been terminated. Check if the current
// string matches the requirements. The length may now be as
// low as zero since blank lines are allowed.
- if (s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) {
+ if (s.length() >= minlen && (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
s.clear();
// string matches the requirements. We require that the length
// be at least one no matter what the user specified.
if (s.length() >= minlen && !s.empty() &&
- (!have_regex || regex.find(s.c_str()))) {
+ (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
s.clear();
if (maxlen > 0 && s.size() == maxlen) {
// Terminate a string if the maximum length is reached.
- if (s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) {
+ if (s.length() >= minlen && (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
s.clear();
// input file or the input size limit. Check if the current string
// matches the requirements.
if ((!limit_count || strings.size() < limit_count) && !s.empty() &&
- s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) {
+ s.length() >= minlen && (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output < 0 || output_size < limit_output) {
strings.push_back(s);
if (*i == "LIST_DIRECTORIES") {
++i; // skip LIST_DIRECTORIES
if (i != args.end()) {
- if (cmSystemTools::IsOn(i->c_str())) {
+ if (cmSystemTools::IsOn(*i)) {
g.SetListDirs(true);
g.SetRecurseListDirs(true);
- } else if (cmSystemTools::IsOff(i->c_str())) {
+ } else if (cmSystemTools::IsOff(*i)) {
g.SetListDirs(false);
g.SetRecurseListDirs(false);
} else {
this->DirPermissions |= mode_world_read;
this->DirPermissions |= mode_world_execute;
}
+
+ bool GetDefaultDirectoryPermissions(mode_t** mode)
+ {
+ // check if default dir creation permissions were set
+ const char* default_dir_install_permissions =
+ this->Makefile->GetDefinition(
+ "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (default_dir_install_permissions && *default_dir_install_permissions) {
+ std::vector<std::string> items;
+ cmSystemTools::ExpandListArgument(default_dir_install_permissions,
+ items);
+ for (const auto& arg : items) {
+ if (!this->CheckPermissions(arg, **mode)) {
+ std::ostringstream e;
+ e << this->FileCommand->GetError()
+ << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
+ "variable.";
+ this->FileCommand->SetError(e.str());
+ return false;
+ }
+ }
+ } else {
+ *mode = nullptr;
+ }
+
+ return true;
+ }
};
bool cmFileCopier::Parse(std::vector<std::string> const& args)
this->ReportCopy(destination, TypeDir,
!cmSystemTools::FileIsDirectory(destination));
+ // check if default dir creation permissions were set
+ mode_t default_dir_mode_v = 0;
+ mode_t* default_dir_mode = &default_dir_mode_v;
+ if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) {
+ return false;
+ }
+
// Make sure the destination directory exists.
- if (!cmSystemTools::MakeDirectory(destination)) {
+ if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
std::ostringstream e;
e << this->Name << " cannot make directory \"" << destination
<< "\": " << cmSystemTools::GetLastSystemError();
// Check whether to copy files always or only if they have changed.
std::string install_always;
if (cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS", install_always)) {
- this->Always = cmSystemTools::IsOn(install_always.c_str());
+ this->Always = cmSystemTools::IsOn(install_always);
}
// Get the current manifest.
this->Manifest =
// check if default dir creation permissions were set
mode_t default_dir_mode_v = 0;
- mode_t* default_dir_mode = nullptr;
- const char* default_dir_install_permissions = this->Makefile->GetDefinition(
- "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
- if (default_dir_install_permissions && *default_dir_install_permissions) {
- std::vector<std::string> items;
- cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
- for (const auto& arg : items) {
- if (!this->CheckPermissions(arg, default_dir_mode_v)) {
- std::ostringstream e;
- e << this->FileCommand->GetError()
- << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.";
- this->FileCommand->SetError(e.str());
- return false;
- }
- }
-
- default_dir_mode = &default_dir_mode_v;
+ mode_t* default_dir_mode = &default_dir_mode_v;
+ if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) {
+ return false;
}
if (this->InstallType != cmInstallType_DIRECTORY) {
#else
char pathSep = ':';
#endif
- std::vector<cmsys::String> path = cmSystemTools::SplitString(*i, pathSep);
+ std::vector<std::string> path = cmSystemTools::SplitString(*i, pathSep);
i++;
const char* var = i->c_str();
std::string value;
- for (std::vector<cmsys::String>::iterator j = path.begin(); j != path.end();
+ for (std::vector<std::string>::iterator j = path.begin(); j != path.end();
++j) {
if (j != path.begin()) {
value += ";";
} else {
*j = cmSystemTools::ConvertToOutputPath(*j);
// remove double quotes in the path
- cmsys::String& s = *j;
+ std::string& s = *j;
if (s.size() > 1 && s[0] == '\"' && s[s.size() - 1] == '\"') {
s = s.substr(1, s.size() - 2);
} else if (*i == "TLS_VERIFY") {
++i;
if (i != args.end()) {
- tls_verify = cmSystemTools::IsOn(i->c_str());
+ tls_verify = cmSystemTools::IsOn(*i);
} else {
this->SetError("TLS_VERIFY missing bool value.");
return false;
::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
check_curl_result(res, "DOWNLOAD cannot set url: ");
+ // enable auth
+ res = ::curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ check_curl_result(res, "DOWNLOAD cannot set httpauth: ");
+
// enable HTTP ERROR parsing
res = ::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
check_curl_result(res, "DOWNLOAD cannot set http failure option: ");
res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
check_curl_result(res, "UPLOAD cannot set url: ");
+ // enable auth
+ res = ::curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ check_curl_result(res, "UPLOAD cannot set httpauth: ");
+
res =
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cmWriteToMemoryCallback);
check_curl_result(res, "UPLOAD cannot set write function: ");
}
if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = this->Makefile->GetCurrentSourceDirectory() + ("/" + path);
+ path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
}
// Unify path (remove '//', '/../', ...)
this->GG = this->Makefile->GetGlobalGenerator();
// Collect the list of library name prefixes/suffixes to try.
- const char* prefixes_list =
+ std::string const& prefixes_list =
this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_PREFIXES");
- const char* suffixes_list =
+ std::string const& suffixes_list =
this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_SUFFIXES");
cmSystemTools::ExpandListArgument(prefixes_list, this->Prefixes, true);
cmSystemTools::ExpandListArgument(suffixes_list, this->Suffixes, true);
return false;
}
this->Configs.push_back(args[i]);
- } else if (!haveVersion && version.find(args[i].c_str())) {
+ } else if (!haveVersion && version.find(args[i])) {
haveVersion = true;
this->Version = args[i];
} else {
this->SetModuleVariables(components);
- // See if there is a Find<package>.cmake module.
+ // See if there is a Find<PackageName>.cmake module.
if (this->UseFindModules) {
bool foundModule = false;
if (!this->FindModule(foundModule)) {
}
// No find module. Assume the project has a CMake config file. Use
- // a <package>_DIR cache variable to locate it.
+ // a <PackageName>_DIR cache variable to locate it.
this->Variable = this->Name;
this->Variable += "_DIR";
#include "cm_kwiml.h"
#include <cstddef>
+#include <functional>
#include <map>
#include <set>
#include <string>
// IWYU insists we should forward-declare instead of including <functional>,
// but we cannot forward-declare reliably because some C++ standard libraries
// put the template in an inline namespace.
-#ifdef CMAKE_IWYU
+#ifdef CMAKE_IWYU_FORWARD_STD_HASH
/* clang-format off */
namespace std {
template <class T> struct hash;
}
/* clang-format on */
-#else
-# include <functional>
#endif
#include "cmFindCommon.h"
// Current names under consideration.
std::vector<std::string> Names;
+ // Current name with extension under consideration.
+ std::string TestNameExt;
+
// Current full path under consideration.
std::string TestPath;
this->Names.clear();
this->AddName(name);
}
+ bool CheckCompoundNames()
+ {
+ for (std::string const& n : this->Names) {
+ // Only perform search relative to current directory if the file name
+ // contains a directory separator.
+ if (n.find('/') != std::string::npos) {
+ if (this->CheckDirectoryForName("", n)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
bool CheckDirectory(std::string const& path)
{
for (std::string const& n : this->Names) {
bool CheckDirectoryForName(std::string const& path, std::string const& name)
{
for (std::string const& ext : this->Extensions) {
- this->TestPath = path;
- this->TestPath += name;
if (!ext.empty() && cmSystemTools::StringEndsWith(name, ext.c_str())) {
continue;
}
- this->TestPath += ext;
+ this->TestNameExt = name;
+ this->TestNameExt += ext;
+ this->TestPath =
+ cmSystemTools::CollapseCombinedPath(path, this->TestNameExt);
+
if (cmSystemTools::FileExists(this->TestPath, true)) {
- this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
+ this->BestPath = this->TestPath;
return true;
}
}
helper.AddName(n);
}
- // Check for the names themselves (e.g. absolute paths).
- if (helper.CheckDirectory(std::string())) {
+ // Check for the names themselves if they contain a directory separator.
+ if (helper.CheckCompoundNames()) {
return helper.BestPath;
}
// Switch to searching for this name.
helper.SetName(n);
- // Check for the name by itself (e.g. an absolute path).
- if (helper.CheckDirectory(std::string())) {
+ // Check for the names themselves if they contain a directory separator.
+ if (helper.CheckCompoundNames()) {
return helper.BestPath;
}
#endif
}
-cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet,
- Encoding encoding)
+cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,
+ bool quiet, Encoding encoding)
: cmGeneratedFileStreamBase(name)
, Stream(TempName.c_str())
{
this->Okay = !this->fail();
}
-cmGeneratedFileStream& cmGeneratedFileStream::Open(const char* name,
+cmGeneratedFileStream& cmGeneratedFileStream::Open(std::string const& name,
bool quiet, bool binaryFlag)
{
// Store the file name and construct the temporary file name.
{
}
-cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(const char* name)
+cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(std::string const& name)
: Name()
, TempName()
, CopyIfDifferent(false)
this->Close();
}
-void cmGeneratedFileStreamBase::Open(const char* name)
+void cmGeneratedFileStreamBase::Open(std::string const& name)
{
// Save the original name of the file.
this->Name = name;
// destination atomically.
if (this->Compress) {
std::string gzname = this->TempName + ".temp.gz";
- if (this->CompressFile(this->TempName.c_str(), gzname.c_str())) {
- this->RenameFile(gzname.c_str(), resname.c_str());
+ if (this->CompressFile(this->TempName, gzname)) {
+ this->RenameFile(gzname, resname);
}
cmSystemTools::RemoveFile(gzname);
} else {
- this->RenameFile(this->TempName.c_str(), resname.c_str());
+ this->RenameFile(this->TempName, resname);
}
replaced = true;
}
#ifdef CMAKE_BUILD_WITH_CMAKE
-int cmGeneratedFileStreamBase::CompressFile(const char* oldname,
- const char* newname)
+int cmGeneratedFileStreamBase::CompressFile(std::string const& oldname,
+ std::string const& newname)
{
- gzFile gf = gzopen(newname, "w");
+ gzFile gf = gzopen(newname.c_str(), "w");
if (!gf) {
return 0;
}
return 1;
}
#else
-int cmGeneratedFileStreamBase::CompressFile(const char*, const char*)
+int cmGeneratedFileStreamBase::CompressFile(std::string const&,
+ std::string const&)
{
return 0;
}
#endif
-int cmGeneratedFileStreamBase::RenameFile(const char* oldname,
- const char* newname)
+int cmGeneratedFileStreamBase::RenameFile(std::string const& oldname,
+ std::string const& newname)
{
- return cmSystemTools::RenameFile(oldname, newname);
+ return cmSystemTools::RenameFile(oldname.c_str(), newname.c_str());
}
void cmGeneratedFileStream::SetName(const std::string& fname)
cmGeneratedFileStreamBase();
// This constructor prepares the temporary output file.
- cmGeneratedFileStreamBase(const char* name);
+ cmGeneratedFileStreamBase(std::string const& name);
// The destructor renames the temporary output file to the real name.
~cmGeneratedFileStreamBase();
// called before the real stream is opened. Close is always called
// after the real stream is closed and Okay is set to whether the
// real stream was still valid for writing when it was closed.
- void Open(const char* name);
+ void Open(std::string const& name);
bool Close();
// Internal file replacement implementation.
- int RenameFile(const char* oldname, const char* newname);
+ int RenameFile(std::string const& oldname, std::string const& newname);
// Internal file compression implementation.
- int CompressFile(const char* oldname, const char* newname);
+ int CompressFile(std::string const& oldname, std::string const& newname);
// The name of the final destination file for the output.
std::string Name;
* file cannot be opened an error message is produced unless the
* second argument is set to true.
*/
- cmGeneratedFileStream(const char* name, bool quiet = false,
+ cmGeneratedFileStream(std::string const& name, bool quiet = false,
Encoding encoding = codecvt::None);
/**
* temporary file. If the file cannot be opened an error message is
* produced unless the second argument is set to true.
*/
- cmGeneratedFileStream& Open(const char* name, bool quiet = false,
+ cmGeneratedFileStream& Open(std::string const& name, bool quiet = false,
bool binaryFlag = false);
/**
{
}
-const char* cmCompiledGeneratorExpression::Evaluate(
+const std::string& cmCompiledGeneratorExpression::Evaluate(
cmLocalGenerator* lg, const std::string& config, bool quiet,
const cmGeneratorTarget* headTarget,
cmGeneratorExpressionDAGChecker* dagChecker,
language);
}
-const char* cmCompiledGeneratorExpression::Evaluate(
+const std::string& cmCompiledGeneratorExpression::Evaluate(
cmLocalGenerator* lg, const std::string& config, bool quiet,
const cmGeneratorTarget* headTarget, const cmGeneratorTarget* currentTarget,
cmGeneratorExpressionDAGChecker* dagChecker,
return this->EvaluateWithContext(context, dagChecker);
}
-const char* cmCompiledGeneratorExpression::EvaluateWithContext(
+const std::string& cmCompiledGeneratorExpression::EvaluateWithContext(
cmGeneratorExpressionContext& context,
cmGeneratorExpressionDAGChecker* dagChecker) const
{
if (!this->NeedsEvaluation) {
- return this->Input.c_str();
+ return this->Input;
}
this->Output.clear();
this->DependTargets = context.DependTargets;
this->AllTargetsSeen = context.AllTargets;
- // TODO: Return a std::string from here instead?
- return this->Output.c_str();
+ return this->Output;
}
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
}
}
-const char* cmGeneratorExpressionInterpreter::Evaluate(
+const std::string& cmGeneratorExpressionInterpreter::Evaluate(
const char* expression, const std::string& property)
{
- if (this->Target.empty()) {
- return this->EvaluateExpression(expression);
- }
+ this->CompiledGeneratorExpression =
+ this->GeneratorExpression.Parse(expression);
// Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS
cmGeneratorExpressionDAGChecker dagChecker(
- this->Target, property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property,
- nullptr, nullptr);
+ this->HeadTarget,
+ property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr,
+ nullptr);
- return this->EvaluateExpression(expression, &dagChecker);
+ return this->CompiledGeneratorExpression->Evaluate(
+ this->LocalGenerator, this->Config, false, this->HeadTarget, &dagChecker,
+ this->Language);
}
static std::string StripEmptyListElements(const std::string& input);
+ static inline bool StartsWithGeneratorExpression(const std::string& input)
+ {
+ return input.length() >= 2 && input[0] == '$' && input[1] == '<';
+ }
+ static inline bool StartsWithGeneratorExpression(const char* input)
+ {
+ return input != nullptr && input[0] == '$' && input[1] == '<';
+ }
+
private:
cmListFileBacktrace Backtrace;
};
CM_DISABLE_COPY(cmCompiledGeneratorExpression)
public:
- const char* Evaluate(cmLocalGenerator* lg, const std::string& config,
- bool quiet = false,
- cmGeneratorTarget const* headTarget = nullptr,
- cmGeneratorTarget const* currentTarget = nullptr,
- cmGeneratorExpressionDAGChecker* dagChecker = nullptr,
- std::string const& language = std::string()) const;
- const char* Evaluate(cmLocalGenerator* lg, const std::string& config,
- bool quiet, cmGeneratorTarget const* headTarget,
- cmGeneratorExpressionDAGChecker* dagChecker,
- std::string const& language = std::string()) const;
+ const std::string& Evaluate(
+ cmLocalGenerator* lg, const std::string& config, bool quiet = false,
+ cmGeneratorTarget const* headTarget = nullptr,
+ cmGeneratorTarget const* currentTarget = nullptr,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr,
+ std::string const& language = std::string()) const;
+ const std::string& Evaluate(
+ cmLocalGenerator* lg, const std::string& config, bool quiet,
+ cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::string const& language = std::string()) const;
/** Get set of targets found during evaluations. */
std::set<cmGeneratorTarget*> const& GetTargets() const
std::map<std::string, std::string>& mapping);
private:
- const char* EvaluateWithContext(
+ const std::string& EvaluateWithContext(
cmGeneratorExpressionContext& context,
cmGeneratorExpressionDAGChecker* dagChecker) const;
public:
cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
- cmGeneratorTarget* generatorTarget,
- const std::string& config,
- const std::string& target,
- const std::string& lang)
+ std::string const& config,
+ cmGeneratorTarget const* headTarget,
+ std::string const& lang = std::string())
: LocalGenerator(localGenerator)
- , GeneratorTarget(generatorTarget)
, Config(config)
- , Target(target)
+ , HeadTarget(headTarget)
, Language(lang)
{
}
- cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
- cmGeneratorTarget* generatorTarget,
- const std::string& config)
- : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget, config,
- std::string(), std::string())
- {
- }
- const char* Evaluate(const char* expression)
- {
- return this->EvaluateExpression(expression);
- }
- const char* Evaluate(const std::string& expression)
- {
- return this->Evaluate(expression.c_str());
- }
- const char* Evaluate(const char* expression, const std::string& property);
- const char* Evaluate(const std::string& expression,
- const std::string& property)
+ const std::string& Evaluate(const char* expression,
+ const std::string& property);
+ const std::string& Evaluate(const std::string& expression,
+ const std::string& property)
{
return this->Evaluate(expression.c_str(), property);
}
protected:
- cmGeneratorExpression& GetGeneratorExpression()
- {
- return this->GeneratorExpression;
- }
-
- cmCompiledGeneratorExpression& GetCompiledGeneratorExpression()
- {
- return *(this->CompiledGeneratorExpression);
- }
-
- cmLocalGenerator* GetLocalGenerator() { return this->LocalGenerator; }
-
- cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
-
- const std::string& GetTargetName() const { return this->Target; }
- const std::string& GetLanguage() const { return this->Language; }
-
- const char* EvaluateExpression(
- const char* expression,
- cmGeneratorExpressionDAGChecker* dagChecker = nullptr)
- {
- this->CompiledGeneratorExpression =
- this->GeneratorExpression.Parse(expression);
-
- if (dagChecker == nullptr) {
- return this->CompiledGeneratorExpression->Evaluate(
- this->LocalGenerator, this->Config, false, this->GeneratorTarget);
- }
-
- return this->CompiledGeneratorExpression->Evaluate(
- this->LocalGenerator, this->Config, false, this->GeneratorTarget,
- dagChecker, this->Language);
- }
-
-private:
cmGeneratorExpression GeneratorExpression;
std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression;
cmLocalGenerator* LocalGenerator = nullptr;
- cmGeneratorTarget* GeneratorTarget = nullptr;
std::string Config;
- std::string Target;
+ cmGeneratorTarget const* HeadTarget = nullptr;
std::string Language;
};
#include <utility>
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
- const cmListFileBacktrace& backtrace, const std::string& target,
+ const cmListFileBacktrace& backtrace, cmGeneratorTarget const* target,
const std::string& property, const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent)
: Parent(parent)
}
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
- const std::string& target, const std::string& property,
+ cmGeneratorTarget const* target, const std::string& property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent)
: Parent(parent)
TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy)
#undef TEST_TRANSITIVE_PROPERTY_METHOD
{
- std::map<std::string, std::set<std::string>>::const_iterator it =
- top->Seen.find(this->Target);
+ std::map<cmGeneratorTarget const*, std::set<std::string>>::const_iterator
+ it = top->Seen.find(this->Target);
if (it != top->Seen.end()) {
const std::set<std::string>& propSet = it->second;
if (propSet.find(this->Property) != propSet.end()) {
return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
}
-bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
+bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
+ cmGeneratorTarget const* tgt)
{
const cmGeneratorExpressionDAGChecker* top = this;
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
}
-std::string cmGeneratorExpressionDAGChecker::TopTarget() const
+cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
{
const cmGeneratorExpressionDAGChecker* top = this;
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
struct GeneratorExpressionContent;
struct cmGeneratorExpressionContext;
+class cmGeneratorTarget;
#define CM_SELECT_BOTH(F, A1, A2) F(A1, A2)
#define CM_SELECT_FIRST(F, A1, A2) F(A1)
SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \
SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \
SELECT(F, EvaluatingSources, SOURCES) \
- SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES)
+ SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) \
+ SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) \
+ SELECT(F, EvaluatingLinkDirectories, LINK_DIRECTORIES) \
+ SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS)
#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
struct cmGeneratorExpressionDAGChecker
{
cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace,
- const std::string& target,
+ cmGeneratorTarget const* target,
const std::string& property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent);
- cmGeneratorExpressionDAGChecker(const std::string& target,
+ cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target,
const std::string& property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent);
const std::string& expr);
bool EvaluatingGenexExpression();
- bool EvaluatingLinkLibraries(const char* tgt = nullptr);
+ bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
bool GetTransitivePropertiesOnly();
void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; }
- std::string TopTarget() const;
+ cmGeneratorTarget const* TopTarget() const;
private:
Result CheckGraph() const;
private:
const cmGeneratorExpressionDAGChecker* const Parent;
- const std::string Target;
+ cmGeneratorTarget const* Target;
const std::string Property;
- std::map<std::string, std::set<std::string>> Seen;
+ std::map<cmGeneratorTarget const*, std::set<std::string>> Seen;
const GeneratorExpressionContent* const Content;
const cmListFileBacktrace Backtrace;
Result CheckResult;
std::string outputFileName = this->OutputFileExpr->Evaluate(
lg, config, false, nullptr, nullptr, nullptr, lang);
- const std::string outputContent = inputExpression->Evaluate(
+ const std::string& outputContent = inputExpression->Evaluate(
lg, config, false, nullptr, nullptr, nullptr, lang);
if (cmSystemTools::FileIsFullPath(outputFileName)) {
this->Files.push_back(outputFileName);
outputFiles[outputFileName] = outputContent;
- cmGeneratedFileStream fout(outputFileName.c_str());
+ cmGeneratedFileStream fout(outputFileName);
fout.SetCopyIfDifferent(true);
fout << outputContent;
if (fout.Close() && perm) {
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
+ return !cmSystemTools::IsOff(*parameters.begin()) ? "1" : "0";
}
} boolNode;
{
if (context->HeadTarget) {
cmGeneratorExpressionDAGChecker dagChecker(
- context->Backtrace, context->HeadTarget->GetName(), genexOperator,
- content, dagCheckerParent);
+ context->Backtrace, context->HeadTarget, genexOperator, content,
+ dagCheckerParent);
switch (dagChecker.Check()) {
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
cmGeneratorExpressionDAGChecker* /*unused*/,
const std::string& lang) const
{
- const char* compilerId = context->LG->GetMakefile()->GetSafeDefinition(
- "CMAKE_" + lang + "_COMPILER_ID");
+ std::string const& compilerId =
+ context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
+ "_COMPILER_ID");
if (parameters.empty()) {
- return compilerId ? compilerId : "";
+ return compilerId;
}
static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
if (!compilerIdValidator.find(*parameters.begin())) {
"Expression syntax not recognized.");
return std::string();
}
- if (!compilerId) {
+ if (compilerId.empty()) {
return parameters.front().empty() ? "1" : "0";
}
- if (strcmp(parameters.begin()->c_str(), compilerId) == 0) {
+ if (strcmp(parameters.begin()->c_str(), compilerId.c_str()) == 0) {
return "1";
}
- if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) {
+ if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+ compilerId.c_str()) == 0) {
switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
case cmPolicies::WARN: {
std::ostringstream e;
cmGeneratorExpressionDAGChecker* /*unused*/,
const std::string& lang) const
{
- const char* compilerVersion =
+ std::string const& compilerVersion =
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
"_COMPILER_VERSION");
if (parameters.empty()) {
- return compilerVersion ? compilerVersion : "";
+ return compilerVersion;
}
static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
"Expression syntax not recognized.");
return std::string();
}
- if (!compilerVersion) {
+ if (compilerVersion.empty()) {
return parameters.front().empty() ? "1" : "0";
}
return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
parameters.begin()->c_str(),
- compilerVersion)
+ compilerVersion.c_str())
? "1"
: "0";
}
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- const char* platformId =
+ std::string const& platformId =
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME");
if (parameters.empty()) {
- return platformId ? platformId : "";
+ return platformId;
}
- if (!platformId) {
+ if (platformId.empty()) {
return parameters.front().empty() ? "1" : "0";
}
- if (strcmp(parameters.begin()->c_str(), platformId) == 0) {
+ if (*parameters.begin() == platformId) {
return "1";
}
return "0";
// Don't follow such link interface entries so as not to create a
// self-referencing loop.
if (l.Target && l.Target != target) {
- depString += sep + "$<TARGET_PROPERTY:" + l.Target->GetName() + "," +
+ std::string uniqueName =
+ target->GetGlobalGenerator()->IndexGeneratorTargetUniquely(l.Target);
+ depString += sep + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," +
interfacePropertyName + ">";
sep = ";";
}
std::string targetName = parameters.front();
propertyName = parameters[1];
if (!cmGeneratorExpression::IsValidTargetName(targetName)) {
- if (!propertyNameValidator.find(propertyName.c_str())) {
+ if (!propertyNameValidator.find(propertyName)) {
::reportError(context, content->GetOriginalExpression(),
"Target name and property name not supported.");
return std::string();
return target->GetLinkerLanguage(context->Config);
}
- cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
- target->GetName(), propertyName,
- content, dagCheckerParent);
+ cmGeneratorExpressionDAGChecker dagChecker(
+ context->Backtrace, target, propertyName, content, dagCheckerParent);
switch (dagChecker.Check()) {
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
return std::string();
}
if (dagChecker &&
- (dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
+ (dagChecker->EvaluatingLinkLibraries(target) ||
(dagChecker->EvaluatingSources() &&
- name == dagChecker->TopTarget()))) {
+ target == dagChecker->TopTarget()))) {
::reportError(context, content->GetOriginalExpression(),
"Expressions which require the linker language may not "
"be used while evaluating link libraries");
, DebugCompileOptionsDone(false)
, DebugCompileFeaturesDone(false)
, DebugCompileDefinitionsDone(false)
+ , DebugLinkOptionsDone(false)
+ , DebugLinkDirectoriesDone(false)
, DebugSourcesDone(false)
, LinkImplementationLanguageIsContextDependent(true)
, UtilityItemsDone(false)
t->GetCompileDefinitionsBacktraces(),
this->CompileDefinitionsEntries);
+ CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(),
+ t->GetLinkOptionsBacktraces(),
+ this->LinkOptionsEntries);
+
+ CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(),
+ t->GetLinkDirectoriesBacktraces(),
+ this->LinkDirectoriesEntries);
+
CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
t->GetSourceBacktraces(),
this->SourceEntries, true);
this->DLLPlatform =
- strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
- "") != 0;
+ !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
this->PolicyMap = t->PolicyMap;
}
cmDeleteAll(this->CompileOptionsEntries);
cmDeleteAll(this->CompileFeaturesEntries);
cmDeleteAll(this->CompileDefinitionsEntries);
+ cmDeleteAll(this->LinkOptionsEntries);
+ cmDeleteAll(this->LinkDirectoriesEntries);
cmDeleteAll(this->SourceEntries);
cmDeleteAll(this->LinkInformation);
}
return this->Target->GetProperty(prop);
}
+const char* cmGeneratorTarget::GetSafeProperty(const std::string& prop) const
+{
+ const char* ret = this->GetProperty(prop);
+ if (!ret) {
+ return "";
+ }
+ return ret;
+}
+
const char* cmGeneratorTarget::GetOutputTargetType(
cmStateEnums::ArtifactType artifact) const
{
this->UtilityItemsDone = true;
std::set<std::string> const& utilities = this->GetUtilities();
for (std::string const& i : utilities) {
- cmGeneratorTarget* gt =
- this->LocalGenerator->FindGeneratorTargetToUse(i);
- this->UtilityItems.insert(cmLinkItem(i, gt));
+ if (cmGeneratorTarget* gt =
+ this->LocalGenerator->FindGeneratorTargetToUse(i)) {
+ this->UtilityItems.insert(cmLinkItem(gt));
+ } else {
+ this->UtilityItems.insert(cmLinkItem(i));
+ }
}
}
return this->UtilityItems;
if (iter == this->SystemIncludesCache.end()) {
cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
+ this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
thisTarget->GetLinkImplementationLibraries(config)) {
for (cmLinkImplItem const& lib : impl->Libraries) {
if (lib.Target) {
- std::string genex = "$<TARGET_PROPERTY:" + lib + "," + prop + ">";
+ std::string uniqueName =
+ thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
+ lib.Target);
+ std::string genex =
+ "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">";
cmGeneratorExpression ge(lib.Backtrace);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
cge->SetEvaluateForBuildsystem(true);
for (cmLinkImplItem const& lib : impl->Libraries) {
if (lib.Target &&
lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string genex = "$<TARGET_OBJECTS:" + lib + ">";
+ std::string uniqueName =
+ thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
+ lib.Target);
+ std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">";
cmGeneratorExpression ge(lib.Backtrace);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
cge->SetEvaluateForBuildsystem(true);
for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
cmLinkImplItem const& item = entry->LinkImplItem;
- std::string const& targetName = item;
+ std::string const& targetName = item.AsStr();
std::vector<std::string> entrySources;
cmSystemTools::ExpandListArgument(
entry->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt, tgt,
this->DebugSourcesDone = true;
}
- cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "SOURCES",
- nullptr, nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr,
+ nullptr);
std::unordered_set<std::string> uniqueSrcs;
bool contextDependentDirectSources =
std::string cppFileName = xaml + ".cpp";
files.ExpectedXamlHeaders.insert(hFileName);
files.ExpectedXamlSources.insert(cppFileName);
- } else if (header_regex.find(sf->GetFullPath().c_str())) {
+ } else if (header_regex.find(sf->GetFullPath())) {
kind = SourceKindHeader;
} else {
kind = SourceKindExtra;
return this->Target->GetBacktrace();
}
-const std::vector<std::string>& cmGeneratorTarget::GetLinkDirectories() const
-{
- return this->Target->GetLinkDirectories();
-}
-
const std::set<std::string>& cmGeneratorTarget::GetUtilities() const
{
return this->Target->GetUtilities();
void Visit(cmLinkItem const& item)
{
if (!item.Target) {
- if (item.find("::") != std::string::npos) {
+ if (item.AsStr().find("::") != std::string::npos) {
bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR;
std::ostringstream e;
if (!noMessage) {
e << "Target \"" << this->Target->GetName()
- << "\" links to target \"" << item
+ << "\" links to target \"" << item.AsStr()
<< "\" but the target was not found. Perhaps a find_package() "
"call is missing for an IMPORTED target, or an ALIAS target is "
"missing?";
}
cmGeneratorExpression ge;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "AUTOUIC_OPTIONS", nullptr, nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr,
+ nullptr);
cmSystemTools::ExpandListArgument(
ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this,
&dagChecker),
{
for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
cmLinkImplItem const& item = entry->LinkImplItem;
- std::string const& targetName = item;
+ std::string const& targetName = item.AsStr();
bool const fromImported = item.Target && item.Target->IsImported();
bool const checkCMP0027 = item.FromGenex;
std::vector<std::string> entryIncludes;
}
}
- if (!cmSystemTools::IsOff(entryInclude.c_str())) {
+ if (!cmSystemTools::IsOff(entryInclude)) {
cmSystemTools::ConvertToUnixSlashes(entryInclude);
}
std::string inc = entryInclude;
std::vector<std::string> includes;
std::unordered_set<std::string> uniqueIncludes;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "INCLUDE_DIRECTORIES", nullptr, nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
+ nullptr, nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
cmLinkImplementationLibraries const* impl =
this->GetLinkImplementationLibraries(config);
for (cmLinkImplItem const& lib : impl->Libraries) {
- std::string libDir = cmSystemTools::CollapseFullPath(lib);
+ std::string libDir = cmSystemTools::CollapseFullPath(lib.AsStr());
static cmsys::RegularExpression frameworkCheck(
"(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
Shell
};
-static void processCompileOptionsInternal(
+static void processOptionsInternal(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
std::vector<std::string>& options,
if (!usedOptions.empty()) {
tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
cmake::LOG,
- std::string("Used compile ") + logName + std::string(" for target ") +
+ std::string("Used ") + logName + std::string(" for target ") +
tgt->GetName() + ":\n" + usedOptions,
entry->ge->GetBacktrace());
}
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions, std::string const& language)
{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions, "options",
- language, OptionsParse::Shell);
+ processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
+ config, debugOptions, "compile options", language,
+ OptionsParse::Shell);
}
void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
{
std::unordered_set<std::string> uniqueOptions;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "COMPILE_OPTIONS", nullptr, nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
+ nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions)
{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions, "features",
- std::string(), OptionsParse::None);
+ processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
+ config, debugOptions, "compile features",
+ std::string(), OptionsParse::None);
}
void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
{
std::unordered_set<std::string> uniqueFeatures;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "COMPILE_FEATURES", nullptr, nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
+ nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
bool debugOptions, std::string const& language)
{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions,
- "definitions", language, OptionsParse::None);
+ processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
+ config, debugOptions, "compile definitions", language,
+ OptionsParse::None);
}
void cmGeneratorTarget::GetCompileDefinitions(
{
std::unordered_set<std::string> uniqueOptions;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "COMPILE_DEFINITIONS", nullptr, nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
+ nullptr, nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
}
+namespace {
+void processLinkOptions(
+ cmGeneratorTarget const* tgt,
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
+ std::vector<std::string>& options,
+ std::unordered_set<std::string>& uniqueOptions,
+ cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
+ bool debugOptions, std::string const& language)
+{
+ processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
+ config, debugOptions, "link options", language,
+ OptionsParse::Shell);
+}
+}
+
+void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const
+{
+ std::unordered_set<std::string> uniqueOptions;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
+ nullptr);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugOptions = !this->DebugLinkOptionsDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "LINK_OPTIONS") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugLinkOptionsDone = true;
+ }
+
+ processLinkOptions(this, this->LinkOptionsEntries, result, uniqueOptions,
+ &dagChecker, config, debugOptions, language);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceLinkOptionsEntries;
+
+ AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS",
+ linkInterfaceLinkOptionsEntries);
+
+ processLinkOptions(this, linkInterfaceLinkOptionsEntries, result,
+ uniqueOptions, &dagChecker, config, debugOptions,
+ language);
+
+ cmDeleteAll(linkInterfaceLinkOptionsEntries);
+
+ // Last step: replace "LINKER:" prefixed elements by
+ // actual linker wrapper
+ const std::string wrapper(this->Makefile->GetSafeDefinition(
+ "CMAKE_" + language + "_LINKER_WRAPPER_FLAG"));
+ std::vector<std::string> wrapperFlag;
+ cmSystemTools::ExpandListArgument(wrapper, wrapperFlag);
+ const std::string wrapperSep(this->Makefile->GetSafeDefinition(
+ "CMAKE_" + language + "_LINKER_WRAPPER_FLAG_SEP"));
+ bool concatFlagAndArgs = true;
+ if (!wrapperFlag.empty() && wrapperFlag.back() == " ") {
+ concatFlagAndArgs = false;
+ wrapperFlag.pop_back();
+ }
+
+ const std::string LINKER{ "LINKER:" };
+ const std::string SHELL{ "SHELL:" };
+ const std::string LINKER_SHELL = LINKER + SHELL;
+
+ std::vector<std::string>::iterator entry;
+ while ((entry = std::find_if(result.begin(), result.end(),
+ [&LINKER](const std::string& item) -> bool {
+ return item.compare(0, LINKER.length(),
+ LINKER) == 0;
+ })) != result.end()) {
+ std::vector<std::string> linkerOptions;
+ if (entry->compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) {
+ cmSystemTools::ParseUnixCommandLine(
+ entry->c_str() + LINKER_SHELL.length(), linkerOptions);
+ } else {
+ linkerOptions =
+ cmSystemTools::tokenize(entry->substr(LINKER.length()), ",");
+ }
+ entry = result.erase(entry);
+
+ if (linkerOptions.empty() ||
+ (linkerOptions.size() == 1 && linkerOptions.front().empty())) {
+ continue;
+ }
+
+ // for now, raise an error if prefix SHELL: is part of arguments
+ if (std::find_if(linkerOptions.begin(), linkerOptions.end(),
+ [&SHELL](const std::string& item) -> bool {
+ return item.find(SHELL) != std::string::npos;
+ }) != linkerOptions.end()) {
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR,
+ "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.",
+ this->GetBacktrace());
+ return;
+ }
+
+ if (wrapperFlag.empty()) {
+ // nothing specified, insert elements as is
+ result.insert(entry, linkerOptions.begin(), linkerOptions.end());
+ } else {
+ std::vector<std::string> options;
+
+ if (!wrapperSep.empty()) {
+ if (concatFlagAndArgs) {
+ // insert flag elements except last one
+ options.insert(options.end(), wrapperFlag.begin(),
+ wrapperFlag.end() - 1);
+ // concatenate last flag element and all LINKER list values
+ // in one option
+ options.push_back(wrapperFlag.back() +
+ cmJoin(linkerOptions, wrapperSep));
+ } else {
+ options.insert(options.end(), wrapperFlag.begin(),
+ wrapperFlag.end());
+ // concatenate all LINKER list values in one option
+ options.push_back(cmJoin(linkerOptions, wrapperSep));
+ }
+ } else {
+ // prefix each element of LINKER list with wrapper
+ if (concatFlagAndArgs) {
+ std::transform(
+ linkerOptions.begin(), linkerOptions.end(), linkerOptions.begin(),
+ [&wrapperFlag](const std::string& value) -> std::string {
+ return wrapperFlag.back() + value;
+ });
+ }
+ for (const auto& value : linkerOptions) {
+ options.insert(options.end(), wrapperFlag.begin(),
+ concatFlagAndArgs ? wrapperFlag.end() - 1
+ : wrapperFlag.end());
+ options.push_back(value);
+ }
+ }
+ result.insert(entry, options.begin(), options.end());
+ }
+ }
+}
+
+namespace {
+void processStaticLibraryLinkOptions(
+ cmGeneratorTarget const* tgt,
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
+ std::vector<std::string>& options,
+ std::unordered_set<std::string>& uniqueOptions,
+ cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
+ std::string const& language)
+{
+ processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
+ config, false, "static library link options",
+ language, OptionsParse::Shell);
+}
+}
+
+void cmGeneratorTarget::GetStaticLibraryLinkOptions(
+ std::vector<std::string>& result, const std::string& config,
+ const std::string& language) const
+{
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
+ std::unordered_set<std::string> uniqueOptions;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS",
+ nullptr, nullptr);
+
+ if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
+ std::vector<std::string> options;
+ cmGeneratorExpression ge;
+ cmSystemTools::ExpandListArgument(linkOptions, options);
+ for (const auto& option : options) {
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(option);
+ entries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(std::move(cge)));
+ }
+ }
+ processStaticLibraryLinkOptions(this, entries, result, uniqueOptions,
+ &dagChecker, config, language);
+
+ cmDeleteAll(entries);
+}
+
+namespace {
+void processLinkDirectories(
+ cmGeneratorTarget const* tgt,
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
+ std::vector<std::string>& directories,
+ std::unordered_set<std::string>& uniqueDirectories,
+ cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
+ bool debugDirectories, std::string const& language)
+{
+ for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
+ cmLinkImplItem const& item = entry->LinkImplItem;
+ std::string const& targetName = item.AsStr();
+
+ std::vector<std::string> entryDirectories;
+ cmSystemTools::ExpandListArgument(
+ entry->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt,
+ dagChecker, language),
+ entryDirectories);
+
+ std::string usedDirectories;
+ for (std::string& entryDirectory : entryDirectories) {
+ if (!cmSystemTools::FileIsFullPath(entryDirectory)) {
+ std::ostringstream e;
+ bool noMessage = false;
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
+ if (!targetName.empty()) {
+ /* clang-format off */
+ e << "Target \"" << targetName << "\" contains relative "
+ "path in its INTERFACE_LINK_DIRECTORIES:\n"
+ " \"" << entryDirectory << "\"";
+ /* clang-format on */
+ } else {
+ switch (tgt->GetPolicyStatusCMP0081()) {
+ case cmPolicies::WARN: {
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0081) << "\n";
+ messageType = cmake::AUTHOR_WARNING;
+ } break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+ e << "Found relative path while evaluating link directories of "
+ "\""
+ << tgt->GetName() << "\":\n \"" << entryDirectory << "\"\n";
+ }
+ if (!noMessage) {
+ tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ if (messageType == cmake::FATAL_ERROR) {
+ return;
+ }
+ }
+ }
+
+ // Sanitize the path the same way the link_directories command does
+ // in case projects set the LINK_DIRECTORIES property directly.
+ cmSystemTools::ConvertToUnixSlashes(entryDirectory);
+ if (uniqueDirectories.insert(entryDirectory).second) {
+ directories.push_back(entryDirectory);
+ if (debugDirectories) {
+ usedDirectories += " * " + entryDirectory + "\n";
+ }
+ }
+ }
+ if (!usedDirectories.empty()) {
+ tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::LOG,
+ std::string("Used link directories for target ") + tgt->GetName() +
+ ":\n" + usedDirectories,
+ entry->ge->GetBacktrace());
+ }
+ }
+}
+}
+
+void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const
+{
+ std::unordered_set<std::string> uniqueDirectories;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
+ nullptr);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugDirectories = !this->DebugLinkDirectoriesDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "LINK_DIRECTORIES") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugLinkDirectoriesDone = true;
+ }
+
+ processLinkDirectories(this, this->LinkDirectoriesEntries, result,
+ uniqueDirectories, &dagChecker, config,
+ debugDirectories, language);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceLinkDirectoriesEntries;
+
+ AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES",
+ linkInterfaceLinkDirectoriesEntries);
+
+ processLinkDirectories(this, linkInterfaceLinkDirectoriesEntries, result,
+ uniqueDirectories, &dagChecker, config,
+ debugDirectories, language);
+
+ cmDeleteAll(linkInterfaceLinkDirectoriesEntries);
+}
+
+namespace {
+void processLinkDepends(
+ cmGeneratorTarget const* tgt,
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
+ std::vector<std::string>& options,
+ std::unordered_set<std::string>& uniqueOptions,
+ cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
+ std::string const& language)
+{
+ processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker,
+ config, false, "link depends", language,
+ OptionsParse::None);
+}
+}
+
+void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const
+{
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries;
+ std::unordered_set<std::string> uniqueOptions;
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
+ nullptr);
+
+ if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) {
+ std::vector<std::string> depends;
+ cmGeneratorExpression ge;
+ cmSystemTools::ExpandListArgument(linkDepends, depends);
+ for (const auto& depend : depends) {
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depend);
+ linkDependsEntries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(std::move(cge)));
+ }
+ }
+ AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS",
+ linkDependsEntries);
+ processLinkDepends(this, linkDependsEntries, result, uniqueOptions,
+ &dagChecker, config, language);
+
+ cmDeleteAll(linkDependsEntries);
+}
+
void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
{
if (this->IsImported()) {
return prefix + base + suffix;
}
-const char* cmGeneratorTarget::ImportedGetLocation(
+std::string cmGeneratorTarget::ImportedGetLocation(
const std::string& config) const
{
- static std::string location;
assert(this->IsImported());
- location = this->Target->ImportedGetFullPath(
+ return this->Target->ImportedGetFullPath(
config, cmStateEnums::RuntimeBinaryArtifact);
- return location.c_str();
}
std::string cmGeneratorTarget::GetFullNameImported(
// if there is no prefix on the target use the cmake definition
if (!targetPrefix && prefixVar) {
- targetPrefix = this->Makefile->GetSafeDefinition(prefixVar);
+ targetPrefix = this->Makefile->GetSafeDefinition(prefixVar).c_str();
}
// if there is no suffix on the target use the cmake definition
if (!targetSuffix && suffixVar) {
- targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
+ targetSuffix = this->Makefile->GetSafeDefinition(suffixVar).c_str();
}
// frameworks have directory prefix but no suffix
{
int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
if (nameResult == 0) {
- return strcmp(t1->GetLocalGenerator()->GetCurrentBinaryDirectory(),
- t2->GetLocalGenerator()->GetCurrentBinaryDirectory()) < 0;
+ return strcmp(
+ t1->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str(),
+ t2->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str()) < 0;
}
return nameResult < 0;
}
if (name == this->GetName() || name.empty()) {
continue;
}
- items.emplace_back(name, this->FindTargetToLink(name));
+ items.push_back(this->ResolveLinkItem(name));
}
}
std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const
{
cmGeneratorExpression ge;
- cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, nullptr,
- nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr);
// The $<LINK_ONLY> expression may be in a link interface to specify private
// link dependencies that are otherwise excluded from usage requirements.
if (usage_requirements_only) {
this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
// Shared libraries may have runtime implementation dependencies
// on other shared libraries that are not in the interface.
- std::unordered_set<std::string> emitted;
+ std::set<cmLinkItem> emitted;
for (cmLinkItem const& lib : iface.Libraries) {
emitted.insert(lib);
}
end = entryRange.end();
le != end; ++le, ++btIt) {
std::vector<std::string> llibs;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "LINK_LIBRARIES", nullptr, nullptr);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
+ nullptr);
cmGeneratorExpression ge(*btIt);
std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
- std::string const evaluated =
+ std::string const& evaluated =
cge->Evaluate(this->LocalGenerator, config, false, head, &dagChecker);
cmSystemTools::ExpandListArgument(evaluated, llibs);
if (cge->GetHadHeadSensitiveCondition()) {
}
// The entry is meant for this configuration.
- impl.Libraries.emplace_back(name, this->FindTargetToLink(name), *btIt,
+ impl.Libraries.emplace_back(this->ResolveLinkItem(name), *btIt,
evaluated != *le);
}
continue;
}
// Support OLD behavior for CMP0003.
- impl.WrongConfigLibraries.emplace_back(name,
- this->FindTargetToLink(name));
+ impl.WrongConfigLibraries.push_back(this->ResolveLinkItem(name));
}
}
}
-cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
+cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
std::string const& name) const
{
- cmGeneratorTarget* tgt =
- this->LocalGenerator->FindGeneratorTargetToUse(name);
+ cmLocalGenerator const* lg = this->LocalGenerator;
+ std::string const* lookupName = &name;
+
+ // When target_link_libraries() is called with a LHS target that is
+ // not created in the calling directory it adds a directory id suffix
+ // that we can use to look up the calling directory. It is that scope
+ // in which the item name is meaningful. This case is relatively rare
+ // so we allocate a separate string only when the directory id is present.
+ std::string::size_type pos = name.find(CMAKE_DIRECTORY_ID_SEP);
+ std::string plainName;
+ if (pos != std::string::npos) {
+ // We will look up the plain name without the directory id suffix.
+ plainName = name.substr(0, pos);
+
+ // We will look up in the scope of the directory id.
+ // If we do not recognize the id then leave the original
+ // syntax in place to produce an indicative error later.
+ cmDirectoryId const dirId =
+ name.substr(pos + sizeof(CMAKE_DIRECTORY_ID_SEP) - 1);
+ if (cmLocalGenerator const* otherLG =
+ this->GlobalGenerator->FindLocalGenerator(dirId)) {
+ lg = otherLG;
+ lookupName = &plainName;
+ }
+ }
+
+ TargetOrString resolved;
+
+ if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(*lookupName)) {
+ resolved.Target = tgt;
+ } else if (lookupName == &plainName) {
+ resolved.String = std::move(plainName);
+ } else {
+ resolved.String = name;
+ }
+
+ return resolved;
+}
+
+cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const
+{
+ TargetOrString resolved = this->ResolveTargetReference(name);
+
+ if (!resolved.Target) {
+ return cmLinkItem(resolved.String);
+ }
// Skip targets that will not really be linked. This is probably a
// name conflict between an external library and an executable
// within the project.
- if (tgt && tgt->GetType() == cmStateEnums::EXECUTABLE &&
- !tgt->IsExecutableWithExports()) {
- tgt = nullptr;
+ if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE &&
+ !resolved.Target->IsExecutableWithExports()) {
+ return cmLinkItem(resolved.Target->GetName());
}
- return tgt;
+ return cmLinkItem(resolved.Target);
}
std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
std::string GetExportName() const;
std::vector<std::string> GetPropertyKeys() const;
+ ///! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
+ ///! Always returns a valid pointer
+ const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void GetSourceFiles(std::vector<cmSourceFile*>& files,
const std::string& config) const;
cmListFileBacktrace GetBacktrace() const;
- const std::vector<std::string>& GetLinkDirectories() const;
-
std::set<std::string> const& GetUtilities() const;
cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
cmOptionalLinkImplementation& impl,
const cmGeneratorTarget* head) const;
- cmGeneratorTarget* FindTargetToLink(std::string const& name) const;
+ struct TargetOrString
+ {
+ std::string String;
+ cmGeneratorTarget* Target = nullptr;
+ };
+ TargetOrString ResolveTargetReference(std::string const& name) const;
+
+ cmLinkItem ResolveLinkItem(std::string const& name) const;
// Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change
const std::string& config,
const std::string& language) const;
+ void GetLinkOptions(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+ void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+
+ void GetLinkDirectories(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+
+ void GetLinkDepends(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+
bool IsSystemIncludeDirectory(const std::string& dir,
const std::string& config,
const std::string& language) const;
no soname at all. */
bool IsImportedSharedLibWithoutSOName(const std::string& config) const;
- const char* ImportedGetLocation(const std::string& config) const;
+ std::string ImportedGetLocation(const std::string& config) const;
/** Get the target major and minor version numbers interpreted from
the VERSION property. Version 0 is returned if the property is
std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
+ std::vector<TargetPropertyEntry*> LinkOptionsEntries;
+ std::vector<TargetPropertyEntry*> LinkDirectoriesEntries;
std::vector<TargetPropertyEntry*> SourceEntries;
mutable std::set<std::string> LinkImplicitNullProperties;
mutable bool DebugCompileOptionsDone;
mutable bool DebugCompileFeaturesDone;
mutable bool DebugCompileDefinitionsDone;
+ mutable bool DebugLinkOptionsDone;
+ mutable bool DebugLinkDirectoriesDone;
mutable bool DebugSourcesDone;
mutable bool LinkImplementationLanguageIsContextDependent;
mutable bool UtilityItemsDone;
"providing the name of the variable to get.");
return false;
}
- std::string output = dir->GetSafeDefinition(*i);
+ std::string const& output = dir->GetSafeDefinition(*i);
this->Makefile->AddDefinition(variable, output.c_str());
return true;
}
cmSystemTools::MakeDirectory(scriptFile);
scriptFile += "/VerifyGlobs.cmake";
stampFile += "/cmake.verify_globs";
- cmGeneratedFileStream verifyScriptFile(scriptFile.c_str());
+ cmGeneratedFileStream verifyScriptFile(scriptFile);
verifyScriptFile.SetCopyIfDifferent(true);
if (!verifyScriptFile) {
cmSystemTools::Error("Unable to open verification script file for save. ",
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmQtAutoGen.h"
#include "cmQtAutoGenInitializer.h"
#include "cmSourceFile.h"
#include "cmState.h"
{
int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
if (nameResult == 0) {
- return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory(),
- t2->GetMakefile()->GetCurrentBinaryDirectory()) < 0;
+ return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory().c_str(),
+ t2->GetMakefile()->GetCurrentBinaryDirectory().c_str()) < 0;
}
return nameResult < 0;
}
const std::string& inMakeProgram, const std::string& makeDefault) const
{
std::string makeProgram = inMakeProgram;
- if (cmSystemTools::IsOff(makeProgram.c_str())) {
+ if (cmSystemTools::IsOff(makeProgram)) {
const char* makeProgramCSTR =
this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
if (cmSystemTools::IsOff(makeProgramCSTR)) {
} else {
makeProgram = makeProgramCSTR;
}
- if (cmSystemTools::IsOff(makeProgram.c_str()) && !makeProgram.empty()) {
+ if (cmSystemTools::IsOff(makeProgram) && !makeProgram.empty()) {
makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND";
}
}
}
return;
}
- const char* name = mf->GetRequiredDefinition(langComp);
+ std::string const& name = mf->GetRequiredDefinition(langComp);
std::string path;
if (!cmSystemTools::FileIsFullPath(name)) {
path = cmSystemTools::FindProgram(name);
if (!optional && (path.empty() || !cmSystemTools::FileExists(path))) {
return;
}
- const char* cname =
+ const std::string* cname =
this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp);
std::string changeVars;
if (cname && !optional) {
std::string cnameString;
- if (!cmSystemTools::FileIsFullPath(cname)) {
- cnameString = cmSystemTools::FindProgram(cname);
+ if (!cmSystemTools::FileIsFullPath(*cname)) {
+ cnameString = cmSystemTools::FindProgram(*cname);
} else {
- cnameString = cname;
+ cnameString = *cname;
}
std::string pathString = path;
// get rid of potentially multiple slashes:
}
changeVars += langComp;
changeVars += ";";
- changeVars += cname;
+ changeVars += *cname;
this->GetCMakeInstance()->GetState()->SetGlobalProperty(
"__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars.c_str());
}
std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_";
sharedLibFlagsVar += lang;
sharedLibFlagsVar += "_FLAGS";
- const char* sharedLibFlags = mf->GetSafeDefinition(sharedLibFlagsVar);
- if (sharedLibFlags) {
- this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags;
- }
+ this->LanguageToOriginalSharedLibFlags[lang] =
+ mf->GetSafeDefinition(sharedLibFlagsVar);
// Translate compiler ids for compatibility.
this->CheckCompilerIdCompatibility(mf, lang);
{
std::string extensionsVar = std::string("CMAKE_") + std::string(l) +
std::string("_SOURCE_FILE_EXTENSIONS");
- std::string exts = mf->GetSafeDefinition(extensionsVar);
+ const std::string& exts = mf->GetSafeDefinition(extensionsVar);
std::vector<std::string> extensionList;
cmSystemTools::ExpandListArgument(exts, extensionList);
for (std::string const& i : extensionList) {
return this->Makefiles[0]->IsOn(name);
}
-const char* cmGlobalGenerator::GetSafeGlobalSetting(
+std::string cmGlobalGenerator::GetSafeGlobalSetting(
std::string const& name) const
{
assert(!this->Makefiles.empty());
void cmGlobalGenerator::CreateLocalGenerators()
{
+ this->LocalGeneratorSearchIndex.clear();
cmDeleteAll(this->LocalGenerators);
this->LocalGenerators.clear();
this->LocalGenerators.reserve(this->Makefiles.size());
for (cmMakefile* m : this->Makefiles) {
- this->LocalGenerators.push_back(this->CreateLocalGenerator(m));
+ cmLocalGenerator* lg = this->CreateLocalGenerator(m);
+ this->LocalGenerators.push_back(lg);
+ this->IndexLocalGenerator(lg);
}
}
// so create the map from project name to vector of local generators
this->FillProjectMap();
-#ifdef CMAKE_BUILD_WITH_CMAKE
- // Iterate through all targets and set up automoc for those which have
- // the AUTOMOC, AUTOUIC or AUTORCC property set
- auto autogenInits = this->CreateQtAutoGenInitializers();
- for (auto& autoGen : autogenInits) {
- autoGen->InitCustomTargets();
+ // Iterate through all targets and set up AUTOMOC, AUTOUIC and AUTORCC
+ if (!this->QtAutoGen()) {
+ return false;
}
-#endif
// Add generator specific helper commands
for (cmLocalGenerator* localGen : this->LocalGenerators) {
}
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
- for (auto& autoGen : autogenInits) {
- autoGen->SetupCustomTargets();
- autoGen.reset(nullptr);
- }
- autogenInits.clear();
-#endif
-
for (cmLocalGenerator* localGen : this->LocalGenerators) {
cmMakefile* mf = localGen->GetMakefile();
for (cmInstallGenerator* g : mf->GetInstallGenerators()) {
return true;
}
-std::vector<std::unique_ptr<cmQtAutoGenInitializer>>
-cmGlobalGenerator::CreateQtAutoGenInitializers()
+bool cmGlobalGenerator::QtAutoGen()
{
+#ifdef CMAKE_BUILD_WITH_CMAKE
std::vector<std::unique_ptr<cmQtAutoGenInitializer>> autogenInits;
-#ifdef CMAKE_BUILD_WITH_CMAKE
for (cmLocalGenerator* localGen : this->LocalGenerators) {
const std::vector<cmGeneratorTarget*>& targets =
localGen->GetGeneratorTargets();
continue;
}
- std::string qtVersionMajor =
- cmQtAutoGenInitializer::GetQtMajorVersion(target);
+ auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target);
// don't do anything if there is no Qt4 or Qt5Core (which contains moc)
- if (qtVersionMajor != "4" && qtVersionMajor != "5") {
+ if (qtVersion.Major != 4 && qtVersion.Major != 5) {
continue;
}
- autogenInits.emplace_back(new cmQtAutoGenInitializer(
- target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor));
+ autogenInits.emplace_back(cm::make_unique<cmQtAutoGenInitializer>(
+ target, mocEnabled, uicEnabled, rccEnabled, qtVersion));
+ }
+ }
+
+ if (!autogenInits.empty()) {
+ // Initialize custom targets
+ for (auto& autoGen : autogenInits) {
+ if (!autoGen->InitCustomTargets()) {
+ return false;
+ }
+ }
+
+ // Setup custom targets
+ for (auto& autoGen : autogenInits) {
+ if (!autoGen->SetupCustomTargets()) {
+ return false;
+ }
+ autoGen.reset(nullptr);
}
}
#endif
- return autogenInits;
+
+ return true;
}
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
for (std::string const& li : langs) {
std::string const standardIncludesVar =
"CMAKE_" + li + "_STANDARD_INCLUDE_DIRECTORIES";
- std::string const standardIncludesStr =
+ std::string const& standardIncludesStr =
mf->GetSafeDefinition(standardIncludesVar);
std::vector<std::string> standardIncludesVec;
cmSystemTools::ExpandListArgument(standardIncludesStr,
this->TargetSearchIndex.clear();
this->GeneratorTargetSearchIndex.clear();
this->MakefileSearchIndex.clear();
+ this->LocalGeneratorSearchIndex.clear();
this->ProjectMap.clear();
this->RuleHashes.clear();
this->DirectoryContentMap.clear();
// update progress
// estimate how many lg there will be
- const char* numGenC =
+ const std::string* numGenC =
this->CMakeInstance->GetState()->GetInitializedCacheValue(
"CMAKE_NUMBER_OF_MAKEFILES");
return;
}
- int numGen = atoi(numGenC);
+ int numGen = atoi(numGenC->c_str());
float prog = 0.9f * static_cast<float>(this->Makefiles.size()) /
static_cast<float>(numGen);
if (prog > 0.9f) {
this->CMakeInstance->UpdateProgress("Configuring", prog);
}
-void cmGlobalGenerator::AddInstallComponent(const char* component)
+void cmGlobalGenerator::AddInstallComponent(const std::string& component)
{
- if (component && *component) {
+ if (!component.empty()) {
this->InstallComponents.insert(component);
}
}
return nullptr;
}
-///! Find a local generator by its startdirectory
cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(
- const std::string& start_dir) const
+ cmDirectoryId const& id) const
{
- for (cmLocalGenerator* lg : this->LocalGenerators) {
- std::string sd = lg->GetCurrentSourceDirectory();
- if (sd == start_dir) {
- return lg;
- }
+ LocalGeneratorMap::const_iterator i =
+ this->LocalGeneratorSearchIndex.find(id.String);
+ if (i != this->LocalGeneratorSearchIndex.end()) {
+ return i->second;
}
return nullptr;
}
}
}
+std::string cmGlobalGenerator::IndexGeneratorTargetUniquely(
+ cmGeneratorTarget const* gt)
+{
+ // Use the pointer value to uniquely identify the target instance.
+ // Use a "T" prefix to indicate that this identifier is for a target.
+ // We must satisfy cmGeneratorExpression::IsValidTargetName so use no
+ // other special characters.
+ char buf[64];
+ sprintf(buf, "::T%p",
+ static_cast<void const*>(gt)); // cast avoids format warning
+ std::string id = gt->GetName() + buf;
+ // We internally index pointers to non-const generator targets
+ // but our callers only have pointers to const generator targets.
+ // They will give up non-const privileges when looking up anyway.
+ this->GeneratorTargetSearchIndex[id] = const_cast<cmGeneratorTarget*>(gt);
+ return id;
+}
+
void cmGlobalGenerator::IndexMakefile(cmMakefile* mf)
{
// FIXME: add_subdirectory supports multiple build directories
MakefileMap::value_type(mf->GetCurrentSourceDirectory(), mf));
}
+void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg)
+{
+ cmDirectoryId id = lg->GetMakefile()->GetDirectoryId();
+ this->LocalGeneratorSearchIndex[id.String] = lg;
+}
+
cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const
{
TargetMap::const_iterator i = this->TargetSearchIndex.find(name);
std::string edit_cmd = this->GetEditCacheCommand();
if (!edit_cmd.empty()) {
singleLine.push_back(std::move(edit_cmd));
- singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
+ singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
gti.Message = "Running CMake cache editor...";
gti.UsesTerminal = true;
gti.UsesTerminal = true;
cmCustomCommandLine singleLine;
singleLine.push_back(cmSystemTools::GetCMakeCommand());
- singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
+ singleLine.push_back("-S$(CMAKE_SOURCE_DIR)");
singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
gti.CommandLines.push_back(std::move(singleLine));
targets.push_back(std::move(gti));
std::string fpath = cmSystemTools::CollapseFullPath(fname, home.c_str());
if (cmSystemTools::FileExists(fpath)) {
RuleHash hash;
- strncpy(hash.Data, line.c_str(), 32);
+ memcpy(hash.Data, line.c_str(), 32);
this->RuleHashes[fname] = hash;
}
}
if (this->RuleHashes.empty()) {
cmSystemTools::RemoveFile(pfile);
} else {
- cmGeneratedFileStream fout(pfile.c_str());
+ cmGeneratedFileStream fout(pfile);
fout << "# Hashes of file build rules.\n";
for (auto const& rh : this->RuleHashes) {
fout.write(rh.second.Data, 32);
std::string fname = this->CMakeInstance->GetHomeOutputDirectory();
fname += cmake::GetCMakeFilesDirectory();
fname += "/TargetDirectories.txt";
- cmGeneratedFileStream fout(fname.c_str());
+ cmGeneratedFileStream fout(fname);
for (cmLocalGenerator* lg : this->LocalGenerators) {
const std::vector<cmGeneratorTarget*>& tgts = lg->GetGeneratorTargets();
Json::Value& lj_sources = lj_root["sources"] = Json::arrayValue;
cmSystemTools::MakeDirectory(dir);
- cmGeneratedFileStream fout(file.c_str());
+ cmGeneratedFileStream fout(file);
std::vector<std::string> labels;
}
}
}
- cmGeneratedFileStream json_fout(json_file.c_str());
+ cmGeneratedFileStream json_fout(json_file);
json_fout << lj_root;
} else
#endif
return true;
}
- cmGeneratedFileStream file(path.c_str());
+ cmGeneratedFileStream file(path);
file << "# CPack properties\n";
for (auto const& i : installedFiles) {
# include "cmFileLockPool.h"
#endif
+#define CMAKE_DIRECTORY_ID_SEP "::@"
+
+class cmDirectoryId;
class cmExportBuildFileGenerator;
class cmExternalMakefileProjectGenerator;
class cmGeneratorTarget;
class cmLocalGenerator;
class cmMakefile;
class cmOutputConverter;
-class cmQtAutoGenInitializer;
class cmSourceFile;
class cmStateDirectory;
class cmake;
std::string GetExtraGeneratorName() const;
- void AddInstallComponent(const char* component);
+ void AddInstallComponent(const std::string& component);
const std::set<std::string>* GetInstallComponents() const
{
const char* GetGlobalSetting(std::string const& name) const;
bool GlobalSettingIsOn(std::string const& name) const;
- const char* GetSafeGlobalSetting(std::string const& name) const;
+ std::string GetSafeGlobalSetting(std::string const& name) const;
/** Add a file to the manifest of generated targets for a configuration. */
void AddToManifest(std::string const& f);
bool NameResolvesToFramework(const std::string& libname) const;
cmMakefile* FindMakefile(const std::string& start_dir) const;
- ///! Find a local generator by its startdirectory
- cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const;
+ cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
/** Append the subdirectory for the given configuration. If anything is
appended the given prefix and suffix will be appended around it, which
void IndexTarget(cmTarget* t);
void IndexGeneratorTarget(cmGeneratorTarget* gt);
+ // Index the target using a name that is unique to that target
+ // even if other targets have the same name.
+ std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt);
+
static bool IsReservedTarget(std::string const& name);
virtual const char* GetAllTargetName() const { return "ALL_BUILD"; }
i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig() const { return false; }
+ virtual bool IsXcode() 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 CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
- // Qt auto generators
- std::vector<std::unique_ptr<cmQtAutoGenInitializer>>
- CreateQtAutoGenInitializers();
+ /// @brief Qt AUTOMOC/UIC/RCC target generation
+ /// @return true on success
+ bool QtAutoGen();
std::string SelectMakeProgram(const std::string& makeProgram,
const std::string& makeDefault = "") const;
typedef std::unordered_map<std::string, cmGeneratorTarget*>
GeneratorTargetMap;
typedef std::unordered_map<std::string, cmMakefile*> MakefileMap;
+ typedef std::unordered_map<std::string, cmLocalGenerator*> LocalGeneratorMap;
// Map efficiently from target name to cmTarget instance.
// Do not use this structure for looping over all targets.
// It contains both normal and globally visible imported targets.
// It may not contain all of them (see note in IndexMakefile method).
MakefileMap MakefileSearchIndex;
+ // Map efficiently from source directory path to cmLocalGenerator instance.
+ // Do not use this structure for looping over all directories.
+ // Its order is not deterministic.
+ LocalGeneratorMap LocalGeneratorSearchIndex;
+
cmMakefile* TryCompileOuterMakefile;
// If you add a new map here, make sure it is copied
// in EnableLanguagesFromGenerator
std::string const& reason) const;
void IndexMakefile(cmMakefile* mf);
+ void IndexLocalGenerator(cmLocalGenerator* lg);
virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; }
#include "cmVersion.h"
const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
-const char* cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild";
+const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe";
+const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "C:/ghs";
cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm)
: cmGlobalGenerator(cm)
, OSDirRelative(false)
{
- this->GhsBuildCommandInitialized = false;
}
cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator()
"Generates Green Hills MULTI files (experimental, work-in-progress).";
}
-void cmGlobalGhsMultiGenerator::EnableLanguage(
- std::vector<std::string> const& l, cmMakefile* mf, bool optional)
+bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
+ cmMakefile* mf)
{
- mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
- mf->AddDefinition("CMAKE_SYSTEM_PROCESSOR", "ARM");
-
- const std::string ghsCompRoot(GetCompRoot());
- mf->AddDefinition("GHS_COMP_ROOT", ghsCompRoot.c_str());
- std::string ghsCompRootStart =
- 0 == ghsCompRootStart.size() ? "" : ghsCompRoot + "/";
- mf->AddDefinition("CMAKE_C_COMPILER",
- std::string(ghsCompRootStart + "ccarm.exe").c_str());
+ std::string tsp; /* toolset path */
+ std::string tsn = ts; /* toolset name */
+
+ GetToolset(mf, tsp, tsn);
+
+ /* no toolset was found */
+ if (tsn.empty()) {
+ return false;
+ } else if (ts.empty()) {
+ std::string message;
+ message =
+ "Green Hills MULTI: -T <toolset> not specified; defaulting to \"";
+ message += tsn;
+ message += "\"";
+ cmSystemTools::Message(message.c_str());
+
+ /* store the toolset for later use
+ * -- already done if -T<toolset> was specified
+ */
+ mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsn.c_str(),
+ "Name of generator toolset.",
+ cmStateEnums::INTERNAL);
+ }
+
+ /* set the build tool to use */
+ const char* prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM");
+ std::string gbuild(tsp + "/" + tsn + "/" + DEFAULT_BUILD_PROGRAM);
+
+ /* check if the toolset changed from last generate */
+ if (prevTool != NULL && (gbuild != prevTool)) {
+ std::string message = "generator toolset: ";
+ message += gbuild;
+ message += "\nDoes not match the toolset used previously: ";
+ message += prevTool;
+ message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.";
+ cmSystemTools::Error(message.c_str());
+ } else {
+ /* store the toolset that is being used for this build */
+ mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(),
+ "build program to use", cmStateEnums::INTERNAL,
+ true);
+ }
+
+ mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsn.c_str());
+
+ // FIXME: compiler detection not implemented
+ // gbuild uses the primaryTarget setting in the top-level project
+ // file to determine which compiler to use. Because compiler
+ // detection is not implemented these variables must be
+ // set to skip past these tests. However cmake will verify that
+ // the executable pointed to by CMAKE_<LANG>_COMPILER exists.
+ // To pass this additional check gbuild is used as a place holder for the
+ // actual compiler.
+ mf->AddDefinition("CMAKE_C_COMPILER", gbuild.c_str());
mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE");
- mf->AddDefinition("CMAKE_CXX_COMPILER",
- std::string(ghsCompRootStart + "cxarm.exe").c_str());
+ mf->AddDefinition("CMAKE_CXX_COMPILER", gbuild.c_str());
mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE");
mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS");
mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE");
- if (!ghsCompRoot.empty()) {
- static const char* compPreFix = "comp_";
- std::string compFilename =
- cmsys::SystemTools::FindLastString(ghsCompRoot.c_str(), compPreFix);
- cmsys::SystemTools::ReplaceString(compFilename, compPreFix, "");
- mf->AddDefinition("CMAKE_SYSTEM_VERSION", compFilename.c_str());
- }
-
- mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
- this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
+ return true;
}
-bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* mf)
+bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
+ cmMakefile* mf)
{
- // The GHS generator knows how to lookup its build tool
- // directly instead of needing a helper module to do it, so we
- // do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
- if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
- mf->AddDefinition("CMAKE_MAKE_PROGRAM",
- this->GetGhsBuildCommand().c_str());
+ if (p == "") {
+ cmSystemTools::Message(
+ "Green Hills MULTI: -A <arch> not specified; defaulting to \"arm\"");
+ std::string arch = "arm";
+
+ /* store the platform name for later use
+ * -- already done if -A<arch> was specified
+ */
+ mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch.c_str(),
+ "Name of generator platform.",
+ cmStateEnums::INTERNAL);
}
- return true;
-}
-std::string const& cmGlobalGhsMultiGenerator::GetGhsBuildCommand()
-{
- if (!this->GhsBuildCommandInitialized) {
- this->GhsBuildCommandInitialized = true;
- this->GhsBuildCommand = this->FindGhsBuildCommand();
+ const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM");
+ if (tgtPlatform == nullptr) {
+ tgtPlatform = "integrity";
}
- return this->GhsBuildCommand;
+
+ /* store the platform name for later use */
+ mf->AddCacheDefinition("GHS_TARGET_PLATFORM", tgtPlatform,
+ "Name of GHS target platform.",
+ cmStateEnums::INTERNAL);
+
+ return true;
}
-std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand()
+void cmGlobalGhsMultiGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
- std::vector<std::string> userPaths;
- userPaths.push_back(this->GetCompRoot());
- std::string makeProgram =
- cmSystemTools::FindProgram(DEFAULT_MAKE_PROGRAM, userPaths);
- if (makeProgram.empty()) {
- makeProgram = DEFAULT_MAKE_PROGRAM;
- }
- return makeProgram;
+ mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
+
+ mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
+ this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
}
-std::string cmGlobalGhsMultiGenerator::GetCompRoot()
+bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/)
{
- std::string output;
-
- const std::vector<std::string> potentialDirsHardPaths(
- GetCompRootHardPaths());
- const std::vector<std::string> potentialDirsRegistry(GetCompRootRegistry());
-
- std::vector<std::string> potentialDirsComplete;
- potentialDirsComplete.insert(potentialDirsComplete.end(),
- potentialDirsHardPaths.begin(),
- potentialDirsHardPaths.end());
- potentialDirsComplete.insert(potentialDirsComplete.end(),
- potentialDirsRegistry.begin(),
- potentialDirsRegistry.end());
-
- // Use latest version
- std::string outputDirName;
- for (std::vector<std::string>::const_iterator potentialDirsCompleteIt =
- potentialDirsComplete.begin();
- potentialDirsCompleteIt != potentialDirsComplete.end();
- ++potentialDirsCompleteIt) {
- const std::string dirName(
- cmsys::SystemTools::GetFilenameName(*potentialDirsCompleteIt));
- if (dirName.compare(outputDirName) > 0) {
- output = *potentialDirsCompleteIt;
- outputDirName = dirName;
- }
- }
+ // The GHS generator only knows how to lookup its build tool
+ // during generation of the project files, but this
+ // can only be done after the toolset is specified.
- return output;
+ return true;
}
-std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootHardPaths()
+void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd,
+ std::string& ts)
{
- std::vector<std::string> output;
- cmSystemTools::Glob("C:/ghs", "comp_[^;]+", output);
- for (std::vector<std::string>::iterator outputIt = output.begin();
- outputIt != output.end(); ++outputIt) {
- *outputIt = "C:/ghs/" + *outputIt;
+ const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT");
+
+ if (!ghsRoot) {
+ ghsRoot = DEFAULT_TOOLSET_ROOT;
}
- return output;
-}
+ tsd = ghsRoot;
-std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry()
-{
- std::vector<std::string> output(2);
- cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_"
- "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
- "Windows\\CurrentVersion\\Uninstall\\"
- "GreenHillsSoftwared771f1b4;InstallLocation",
- output[0]);
- cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_"
- "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
- "Windows\\CurrentVersion\\Uninstall\\"
- "GreenHillsSoftware9881cef6;InstallLocation",
- output[1]);
- return output;
+ if (ts.empty()) {
+ std::vector<std::string> output;
+
+ // Use latest? version
+ cmSystemTools::Glob(tsd, "comp_[^;]+", output);
+
+ if (output.empty()) {
+ cmSystemTools::Error("GHS toolset not found in ", tsd.c_str());
+ ts = "";
+ } else {
+ ts = output.back();
+ }
+ } else {
+ std::string tryPath = tsd + std::string("/") + ts;
+ if (!cmSystemTools::FileExists(tryPath)) {
+ cmSystemTools::Error("GHS toolset \"", ts.c_str(), "\" not found in ",
+ tsd.c_str());
+ ts = "";
+ }
+ }
}
void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
this->OSDirRelative = true;
}
- char const* bspName =
+ std::string bspName;
+ char const* bspCache =
this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
- if (NULL == bspName) {
- bspName = "";
- cmSystemTools::Error("GHS_BSP_NAME cache variable must be set");
- } else {
+ if (bspCache) {
+ bspName = bspCache;
this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME");
}
- std::string fBspName(this->trimQuotes(bspName));
- std::replace(fBspName.begin(), fBspName.end(), '\\', '/');
+ if (bspName.empty() || bspName.compare("IGNORE") == 0) {
+ const char* a =
+ this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
+ bspName = "sim";
+ bspName += (a ? a : "");
+ }
+
this->WriteMacros();
this->WriteHighLevelDirectives();
GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream());
this->WriteDisclaimer(this->GetBuildFileStream());
*this->GetBuildFileStream() << "# Top Level Project File" << std::endl;
- if (!fBspName.empty()) {
- *this->GetBuildFileStream() << " -bsp " << fBspName << std::endl;
- }
+ *this->GetBuildFileStream() << " -bsp " << bspName << std::endl;
+
this->WriteCompilerOptions(fOSDir);
}
const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
{
+ const char* gbuild =
+ this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
makeCommand.push_back(
- this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand()));
+ this->SelectMakeProgram(makeProgram, (std::string)gbuild));
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
makeCommand.push_back("-parallel");
void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives()
{
- *this->GetBuildFileStream()
- << "primaryTarget=arm_integrity.tgt" << std::endl;
+ /* set primary target */
+ std::string tgt;
+ const char* t =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET");
+ if (t) {
+ tgt = t;
+ this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET");
+ } else {
+ const char* a =
+ this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
+ const char* p =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM");
+ tgt = (a ? a : "");
+ tgt += "_";
+ tgt += (p ? p : "");
+ tgt += ".tgt";
+ }
+
+ *this->GetBuildFileStream() << "primaryTarget=" << tgt << std::endl;
+
char const* const customization =
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
if (NULL != customization && strlen(customization) > 0) {
{
std::string workingPath(path);
cmSystemTools::ConvertToUnixSlashes(workingPath);
- std::vector<cmsys::String> splitPath =
- cmSystemTools::SplitString(workingPath);
+ std::vector<std::string> splitPath = cmSystemTools::SplitString(workingPath);
std::string workingRelPath(relPath);
cmSystemTools::ConvertToUnixSlashes(workingRelPath);
if (!workingRelPath.empty()) {
workingRelPath += "/";
}
std::string pathUpTo;
- for (std::vector<cmsys::String>::const_iterator splitPathI =
- splitPath.begin();
+ for (std::vector<std::string>::const_iterator splitPathI = splitPath.begin();
splitPath.end() != splitPathI; ++splitPathI) {
pathUpTo += *splitPathI;
if (targetFolderBuildStreams->end() ==
void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile(
std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
std::string const& pathUpTo,
- std::vector<cmsys::String>::const_iterator splitPathI,
- std::vector<cmsys::String>::const_iterator end,
+ std::vector<std::string>::const_iterator splitPathI,
+ std::vector<std::string>::const_iterator end,
GhsMultiGpj::Types const projType)
{
- std::vector<cmsys::String>::const_iterator splitPathNextI = splitPathI + 1;
+ std::vector<std::string>::const_iterator splitPathNextI = splitPathI + 1;
if (end != splitPathNextI &&
targetFolderBuildStreams->end() ==
targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI)) {
std::string output(path);
if (!path.empty()) {
cmSystemTools::ConvertToUnixSlashes(output);
- std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output);
+ std::vector<std::string> splitPath = cmSystemTools::SplitString(output);
output += "/" + splitPath.back() + FILE_EXTENSION;
}
return output;
this->GetCMakeInstance()->GetHomeOutputDirectory().c_str(),
folderName, GhsMultiGpj::PROJECT);
}
- std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(
+ std::vector<std::string> splitPath = cmSystemTools::SplitString(
cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt));
std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" +
splitPath.back());
* Utilized by the generator factory to determine if this generator
* supports toolsets.
*/
- static bool SupportsToolset() { return false; }
+ static bool SupportsToolset() { return true; }
/**
* Utilized by the generator factory to determine if this generator
* supports platforms.
*/
- static bool SupportsPlatform() { return false; }
+ static bool SupportsPlatform() { return true; }
+
+ // Toolset / Platform Support
+ virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
+ virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
/**
* Try to determine system information such as shared library
std::vector<std::string> const& makeOptions = std::vector<std::string>());
private:
- std::string const& GetGhsBuildCommand();
- std::string FindGhsBuildCommand();
- std::string GetCompRoot();
- std::vector<std::string> GetCompRootHardPaths();
- std::vector<std::string> GetCompRootRegistry();
+ void GetToolset(cmMakefile* mf, std::string& tsd, std::string& ts);
void OpenBuildFileStream();
void WriteMacros();
static void AddFilesUpToPathAppendNextFile(
std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
std::string const& pathUpTo,
- std::vector<cmsys::String>::const_iterator splitPathI,
- std::vector<cmsys::String>::const_iterator end,
- GhsMultiGpj::Types projType);
+ std::vector<std::string>::const_iterator splitPathI,
+ std::vector<std::string>::const_iterator end, GhsMultiGpj::Types projType);
static std::string GetFileNameFromPath(std::string const& path);
void UpdateBuildFiles(const std::vector<cmGeneratorTarget*>& tgts);
bool IsTgtForBuild(const cmGeneratorTarget* tgt);
std::vector<std::string> LibDirs;
bool OSDirRelative;
- bool GhsBuildCommandInitialized;
- std::string GhsBuildCommand;
- static const char* DEFAULT_MAKE_PROGRAM;
+ static const char* DEFAULT_BUILD_PROGRAM;
+ static const char* DEFAULT_TOOLSET_ROOT;
};
#endif
this->ResolveLanguageCompiler(l, mf, optional);
}
#ifdef _WIN32
- if (strcmp(mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID"), "MSVC") != 0 &&
- strcmp(mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID"), "MSVC") != 0 &&
+ if ((mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID") != "MSVC") &&
+ (mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") != "MSVC") &&
(mf->IsOn("CMAKE_COMPILER_IS_MINGW") ||
- strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "GNU") == 0 ||
- strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "GNU") == 0 ||
- strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "Clang") == 0 ||
- strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "Clang") == 0)) {
+ (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") ||
+ (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") ||
+ (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") ||
+ (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang"))) {
this->UsingGCCOnWindows = true;
}
#endif
// Get a stream where to generate things.
if (!this->BuildFileStream) {
this->BuildFileStream = new cmGeneratedFileStream(
- buildFilePath.c_str(), false, this->GetMakefileEncoding());
+ buildFilePath, false, this->GetMakefileEncoding());
if (!this->BuildFileStream) {
// An error message is generated by the constructor if it cannot
// open the file.
// Get a stream where to generate things.
if (!this->RulesFileStream) {
this->RulesFileStream = new cmGeneratedFileStream(
- rulesFilePath.c_str(), false, this->GetMakefileEncoding());
+ rulesFilePath, false, this->GetMakefileEncoding());
if (!this->RulesFileStream) {
// An error message is generated by the constructor if it cannot
// open the file.
}
// Get a stream where to generate things.
- this->CompileCommandsStream =
- new cmGeneratedFileStream(buildFilePath.c_str());
+ this->CompileCommandsStream = new cmGeneratedFileStream(buildFilePath);
*this->CompileCommandsStream << "[";
} else {
*this->CompileCommandsStream << "," << std::endl;
std::set<std::string> const& utils = target->GetUtilities();
for (std::string const& util : utils) {
std::string d =
- target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
- std::string("/") + util;
+ target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util;
outputs.push_back(this->ConvertToNinjaPath(d));
}
} else {
continue;
}
+ // Don't write alias if there is a already a custom command with
+ // matching output
+ if (this->HasCustomCommandOutput(ta.first)) {
+ continue;
+ }
+
cmNinjaDeps deps;
this->AppendTargetOutputs(ta.second, deps);
std::ostringstream cmd;
cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
cmOutputConverter::SHELL)
- << " -H"
+ << " -S"
<< lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
cmOutputConverter::SHELL)
<< " -B"
}
{
- cmGeneratedFileStream depfile(arg_dep.c_str());
+ cmGeneratedFileStream depfile(arg_dep);
depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":";
for (std::string const& include : info.Includes) {
depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(include);
}
}
- cmGeneratedFileStream ddif(arg_ddi.c_str());
+ cmGeneratedFileStream ddif(arg_ddi);
ddif << ddi;
if (!ddif) {
cmSystemTools::Error("-E cmake_ninja_depends failed to write ",
}
}
- cmGeneratedFileStream ddf(arg_dd.c_str());
+ cmGeneratedFileStream ddf(arg_dd);
ddf << "ninja_dyndep_version = 1.0\n";
for (cmFortranObjectInfo const& object : objects) {
// use by dependents that reference this target in linked-target-dirs.
std::string const target_mods_file =
cmSystemTools::GetFilenamePath(arg_dd) + "/FortranModules.json";
- cmGeneratedFileStream tmf(target_mods_file.c_str());
+ cmGeneratedFileStream tmf(target_mods_file);
tmf << tm;
return true;
markFileName += "/";
markFileName += cmake::GetCMakeFilesDirectory();
markFileName += "/progress.marks";
- cmGeneratedFileStream markFile(markFileName.c_str());
+ cmGeneratedFileStream markFile(markFileName);
markFile << this->CountProgressMarksInAll(lg) << "\n";
}
std::string commandDatabaseName =
std::string(this->GetCMakeInstance()->GetHomeOutputDirectory()) +
"/compile_commands.json";
- this->CommandDatabase =
- new cmGeneratedFileStream(commandDatabaseName.c_str());
+ this->CommandDatabase = new cmGeneratedFileStream(commandDatabaseName);
*this->CommandDatabase << "[" << std::endl;
} else {
*this->CommandDatabase << "," << std::endl;
this->GetCMakeInstance()->GetHomeOutputDirectory();
makefileName += cmake::GetCMakeFilesDirectory();
makefileName += "/Makefile2";
- cmGeneratedFileStream makefileStream(makefileName.c_str(), false,
+ cmGeneratedFileStream makefileStream(makefileName, false,
this->GetMakefileEncoding());
if (!makefileStream) {
return;
this->GetCMakeInstance()->GetHomeOutputDirectory();
cmakefileName += cmake::GetCMakeFilesDirectory();
cmakefileName += "/Makefile.cmake";
- cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
+ cmGeneratedFileStream cmakefileStream(cmakefileName);
if (!cmakefileStream) {
return;
}
void cmGlobalUnixMakefileGenerator3::TargetProgress::WriteProgressVariables(
unsigned long total, unsigned long& current)
{
- cmGeneratedFileStream fout(this->VariableFile.c_str());
+ cmGeneratedFileStream fout(this->VariableFile);
for (unsigned long i = 1; i <= this->NumberOfActions; ++i) {
fout << "CMAKE_PROGRESS_" << i << " = ";
if (total <= 100) {
configArg += "Debug";
}
makeCommand.push_back(configArg);
+ makeCommand.push_back("/p:Platform=" + this->GetPlatformName());
makeCommand.push_back(std::string("/p:VisualStudioVersion=") +
this->GetIDEVersion());
std::string const& sfRel)
{
size_t len =
- (strlen(target->GetLocalGenerator()->GetCurrentBinaryDirectory()) + 1 +
+ (target->GetLocalGenerator()->GetCurrentBinaryDirectory().length() + 1 +
sfRel.length());
if (len > this->LongestSource.Length) {
this->LongestSource.Length = len;
bool FindMakeProgram(cmMakefile* mf) override;
+ bool IsIPOSupported() const override { return true; }
+
static std::string GetInstalledNsightTegraVersion();
cmIDEFlagTable const* GetClFlagTable() const;
cmSystemTools::KeyWOW64_32);
}
+std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion() const
+{
+ // The last Windows 10 SDK version that VS 2015 can target is 10.0.14393.0.
+ return "10.0.14393.0";
+}
+
#if defined(_WIN32) && !defined(__CYGWIN__)
struct NoWindowsH
{
return !cmSystemTools::FileExists(p + "/um/windows.h", true);
}
};
+class WindowsSDKTooRecent
+{
+ std::string const& MaxVersion;
+
+public:
+ WindowsSDKTooRecent(std::string const& maxVersion)
+ : MaxVersion(maxVersion)
+ {
+ }
+ bool operator()(std::string const& v)
+ {
+ return cmSystemTools::VersionCompareGreater(v, MaxVersion);
+ }
+};
#endif
std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
// Sort the results to make sure we select the most recent one.
std::sort(sdks.begin(), sdks.end(), cmSystemTools::VersionCompareGreater);
+ // Skip SDKs that cannot be used with our toolset.
+ std::string maxVersion = this->GetWindows10SDKMaxVersion();
+ if (!maxVersion.empty()) {
+ cmEraseIf(sdks, WindowsSDKTooRecent(maxVersion));
+ }
+
// Look for a SDK exactly matching the requested target version.
for (std::string const& i : sdks) {
if (cmSystemTools::VersionCompareEqual(i, this->SystemVersion)) {
// of the toolset is installed
bool IsWindowsStoreToolsetInstalled() const;
+ // Used to make sure that the Windows 10 SDK selected can work with the
+ // version of the toolset.
+ virtual std::string GetWindows10SDKMaxVersion() const;
+
const char* GetIDEVersion() override { return "14.0"; }
virtual bool SelectWindows10SDK(cmMakefile* mf, bool required);
return false;
}
+std::string cmGlobalVisualStudio15Generator::GetWindows10SDKMaxVersion() const
+{
+ return std::string();
+}
+
std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand()
{
std::string msbuild;
// Check for a Win 8 SDK known to the registry or VS installer tool.
bool IsWin81SDKInstalled() const;
+ std::string GetWindows10SDKMaxVersion() const override;
+
std::string FindMSBuildCommand() override;
std::string FindDevEnvCommand() override;
if (written && this->UseFolderProperty()) {
const std::string targetFolder = target->GetEffectiveFolderName();
if (!targetFolder.empty()) {
- std::vector<cmsys::String> tokens =
+ std::vector<std::string> tokens =
cmSystemTools::SplitString(targetFolder, '/', false);
std::string cumulativePath;
- for (cmsys::String const& iter : tokens) {
+ for (std::string const& iter : tokens) {
if (!iter.size()) {
continue;
}
// Create a rule to re-run CMake.
cmCustomCommandLine commandLine;
commandLine.push_back(cmSystemTools::GetCMakeCommand());
- std::string argH = "-H";
- argH += lg->GetSourceDirectory();
- commandLine.push_back(argH);
+ std::string argS = "-S";
+ argS += lg->GetSourceDirectory();
+ commandLine.push_back(argS);
std::string argB = "-B";
argB += lg->GetBinaryDirectory();
commandLine.push_back(argB);
const std::string& projectName,
bool dryRun)
{
- std::string buildDir = cmSystemTools::ConvertToOutputPath(bindir);
- std::string sln = buildDir + "\\" + projectName + ".sln";
+ std::string sln = bindir + "/" + projectName + ".sln";
if (dryRun) {
return cmSystemTools::FileExists(sln, true);
}
+ sln = cmSystemTools::ConvertToOutputPath(sln);
+
return std::async(std::launch::async, OpenSolution, sln).get();
}
}
}
+void cmGlobalXCodeGenerator::ComputeTargetOrder()
+{
+ size_t index = 0;
+ auto const& lgens = this->GetLocalGenerators();
+ for (cmLocalGenerator* lgen : lgens) {
+ auto const& targets = lgen->GetGeneratorTargets();
+ for (cmGeneratorTarget const* gt : targets) {
+ this->ComputeTargetOrder(gt, index);
+ }
+ }
+ assert(index == this->TargetOrderIndex.size());
+}
+
+void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
+ size_t& index)
+{
+ std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0);
+ auto insertion = this->TargetOrderIndex.insert(value);
+ if (!insertion.second) {
+ return;
+ }
+ auto entry = insertion.first;
+
+ auto& deps = this->GetTargetDirectDepends(gt);
+ for (auto& d : deps) {
+ this->ComputeTargetOrder(d, index);
+ }
+
+ entry->second = index++;
+}
+
void cmGlobalXCodeGenerator::Generate()
{
this->cmGlobalGenerator::Generate();
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
+
+ this->ComputeTargetOrder();
+
for (auto keyVal : this->ProjectMap) {
cmLocalGenerator* root = keyVal.second[0];
public:
XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile,
cmLocalGenerator* localGenerator,
- cmGeneratorTarget* generatorTarget,
+ cmGeneratorTarget* headTarget,
const std::string& lang)
- : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget,
- "NO-PER-CONFIG-SUPPORT-IN-XCODE",
- generatorTarget->GetName(), lang)
+ : cmGeneratorExpressionInterpreter(
+ localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget, lang)
, SourceFile(sourceFile)
{
}
using cmGeneratorExpressionInterpreter::Evaluate;
- const char* Evaluate(const char* expression, const std::string& property)
+ const std::string& Evaluate(const char* expression,
+ const std::string& property)
{
- const char* processed =
+ const std::string& processed =
this->cmGeneratorExpressionInterpreter::Evaluate(expression, property);
- if (this->GetCompiledGeneratorExpression()
- .GetHadContextSensitiveCondition()) {
+ if (this->CompiledGeneratorExpression->GetHadContextSensitiveCondition()) {
std::ostringstream e;
/* clang-format off */
e <<
"specified for source:\n"
" " << this->SourceFile->GetFullPath() << "\n";
/* clang-format on */
- this->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
}
return processed;
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
if (const char* compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) {
this->AppendDefines(
- flagsBuild, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS),
+ flagsBuild,
+ genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS).c_str(),
true);
}
if (!flagsBuild.IsEmpty()) {
struct cmCompareTargets
{
- bool operator()(std::string const& a, std::string const& b) const
+ bool operator()(cmXCodeObject* l, cmXCodeObject* r) const
{
+ std::string const& a = l->GetTarget()->GetName();
+ std::string const& b = r->GetTarget()->GetName();
if (a == "ALL_BUILD") {
return true;
}
if (b == "ALL_BUILD") {
return false;
}
- return strcmp(a.c_str(), b.c_str()) < 0;
+ return a < b;
}
};
cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets)
{
this->SetCurrentLocalGenerator(gen);
- typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets>
- cmSortedTargets;
- cmSortedTargets sortedTargets;
- for (auto tgt : this->CurrentLocalGenerator->GetGeneratorTargets()) {
- sortedTargets[tgt->GetName()] = tgt;
+ std::vector<cmGeneratorTarget*> gts =
+ this->CurrentLocalGenerator->GetGeneratorTargets();
+ std::sort(gts.begin(), gts.end(),
+ [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) {
+ return this->TargetOrderIndex[l] < this->TargetOrderIndex[r];
+ });
+ for (auto gtgt : gts) {
+ if (!this->CreateXCodeTarget(gtgt, targets)) {
+ return false;
+ }
}
- for (auto& sortedTarget : sortedTargets) {
- cmGeneratorTarget* gtgt = sortedTarget.second;
-
- std::string targetName = gtgt->GetName();
+ std::sort(targets.begin(), targets.end(), cmCompareTargets());
+ return true;
+}
- // make sure ALL_BUILD, INSTALL, etc are only done once
- if (this->SpecialTargetEmitted(targetName)) {
- continue;
- }
+bool cmGlobalXCodeGenerator::CreateXCodeTarget(
+ cmGeneratorTarget* gtgt, std::vector<cmXCodeObject*>& targets)
+{
+ std::string targetName = gtgt->GetName();
- if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
+ // make sure ALL_BUILD, INSTALL, etc are only done once
+ if (this->SpecialTargetEmitted(targetName)) {
+ return true;
+ }
- if (gtgt->GetType() == cmStateEnums::UTILITY ||
- gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
- cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
- if (!t) {
- return false;
- }
- targets.push_back(t);
- continue;
- }
+ if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return true;
+ }
- // organize the sources
- std::vector<cmSourceFile*> classes;
- if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ if (gtgt->GetType() == cmStateEnums::UTILITY ||
+ gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
+ if (!t) {
return false;
}
+ targets.push_back(t);
+ return true;
+ }
- // Add CMakeLists.txt file for user convenience.
- this->AddXCodeProjBuildRule(gtgt, classes);
+ // organize the sources
+ std::vector<cmSourceFile*> classes;
+ if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ return false;
+ }
- std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
+ // Add CMakeLists.txt file for user convenience.
+ this->AddXCodeProjBuildRule(gtgt, classes);
- gtgt->ComputeObjectMapping();
+ std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
- std::vector<cmXCodeObject*> externalObjFiles;
- std::vector<cmXCodeObject*> headerFiles;
- std::vector<cmXCodeObject*> resourceFiles;
- std::vector<cmXCodeObject*> sourceFiles;
- for (auto sourceFile : classes) {
- cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, sourceFile, gtgt);
- cmXCodeObject* fr = xsf->GetObject("fileRef");
- cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
+ gtgt->ComputeObjectMapping();
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(sourceFile);
+ std::vector<cmXCodeObject*> externalObjFiles;
+ std::vector<cmXCodeObject*> headerFiles;
+ std::vector<cmXCodeObject*> resourceFiles;
+ std::vector<cmXCodeObject*> sourceFiles;
+ for (auto sourceFile : classes) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
+ cmXCodeObject* fr = xsf->GetObject("fileRef");
+ cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
- if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
- if (sourceFile->GetObjectLibrary().empty()) {
- externalObjFiles.push_back(xsf);
- }
- } else if (this->IsHeaderFile(sourceFile) ||
- (tsFlags.Type ==
- cmGeneratorTarget::SourceFileTypePrivateHeader) ||
- (tsFlags.Type ==
- cmGeneratorTarget::SourceFileTypePublicHeader)) {
- headerFiles.push_back(xsf);
- } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
- resourceFiles.push_back(xsf);
- } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) {
- // Include this file in the build if it has a known language
- // and has not been listed as an ignored extension for this
- // generator.
- if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile)
- .empty() &&
- !this->IgnoreFile(sourceFile->GetExtension().c_str())) {
- sourceFiles.push_back(xsf);
- }
- }
- }
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
- if (this->XcodeVersion < 50) {
- // Add object library contents as external objects. (Equivalent to
- // the externalObjFiles above, except each one is not a cmSourceFile
- // within the target.)
- std::vector<cmSourceFile const*> objs;
- gtgt->GetExternalObjects(objs, "");
- for (auto sourceFile : objs) {
- if (sourceFile->GetObjectLibrary().empty()) {
- continue;
- }
- std::string const& obj = sourceFile->GetFullPath();
- cmXCodeObject* xsf =
- this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr);
+ if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
+ if (sourceFile->GetObjectLibrary().empty()) {
externalObjFiles.push_back(xsf);
}
- }
-
- // some build phases only apply to bundles and/or frameworks
- bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
- bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
- bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
-
- cmXCodeObject* buildFiles = nullptr;
-
- // create source build phase
- cmXCodeObject* sourceBuildPhase = nullptr;
- if (!sourceFiles.empty()) {
- sourceBuildPhase =
- this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
- sourceBuildPhase->SetComment("Sources");
- sourceBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (auto& sourceFile : sourceFiles) {
- buildFiles->AddObject(sourceFile);
+ } else if (this->IsHeaderFile(sourceFile) ||
+ (tsFlags.Type ==
+ cmGeneratorTarget::SourceFileTypePrivateHeader) ||
+ (tsFlags.Type ==
+ cmGeneratorTarget::SourceFileTypePublicHeader)) {
+ headerFiles.push_back(xsf);
+ } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
+ resourceFiles.push_back(xsf);
+ } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) {
+ // Include this file in the build if it has a known language
+ // and has not been listed as an ignored extension for this
+ // generator.
+ if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile)
+ .empty() &&
+ !this->IgnoreFile(sourceFile->GetExtension().c_str())) {
+ sourceFiles.push_back(xsf);
}
- sourceBuildPhase->AddAttribute("files", buildFiles);
- sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
}
+ }
- // create header build phase - only for framework targets
- cmXCodeObject* headerBuildPhase = nullptr;
- if (!headerFiles.empty() && isFrameworkTarget) {
- headerBuildPhase =
- this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
- headerBuildPhase->SetComment("Headers");
- headerBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (auto& headerFile : headerFiles) {
- buildFiles->AddObject(headerFile);
+ if (this->XcodeVersion < 50) {
+ // Add object library contents as external objects. (Equivalent to
+ // the externalObjFiles above, except each one is not a cmSourceFile
+ // within the target.)
+ std::vector<cmSourceFile const*> objs;
+ gtgt->GetExternalObjects(objs, "");
+ for (auto sourceFile : objs) {
+ if (sourceFile->GetObjectLibrary().empty()) {
+ continue;
}
- headerBuildPhase->AddAttribute("files", buildFiles);
- headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
+ std::string const& obj = sourceFile->GetFullPath();
+ cmXCodeObject* xsf =
+ this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr);
+ externalObjFiles.push_back(xsf);
+ }
+ }
+
+ // some build phases only apply to bundles and/or frameworks
+ bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
+ bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
+ bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
+
+ cmXCodeObject* buildFiles = nullptr;
+
+ // create source build phase
+ cmXCodeObject* sourceBuildPhase = nullptr;
+ if (!sourceFiles.empty()) {
+ sourceBuildPhase = this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
+ sourceBuildPhase->SetComment("Sources");
+ sourceBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for (auto& sourceFile : sourceFiles) {
+ buildFiles->AddObject(sourceFile);
+ }
+ sourceBuildPhase->AddAttribute("files", buildFiles);
+ sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
+
+ // create header build phase - only for framework targets
+ cmXCodeObject* headerBuildPhase = nullptr;
+ if (!headerFiles.empty() && isFrameworkTarget) {
+ headerBuildPhase = this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
+ headerBuildPhase->SetComment("Headers");
+ headerBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for (auto& headerFile : headerFiles) {
+ buildFiles->AddObject(headerFile);
+ }
+ headerBuildPhase->AddAttribute("files", buildFiles);
+ headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
+
+ // create resource build phase - only for framework or bundle targets
+ cmXCodeObject* resourceBuildPhase = nullptr;
+ if (!resourceFiles.empty() &&
+ (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
+ resourceBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
+ resourceBuildPhase->SetComment("Resources");
+ resourceBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for (auto& resourceFile : resourceFiles) {
+ buildFiles->AddObject(resourceFile);
}
+ resourceBuildPhase->AddAttribute("files", buildFiles);
+ resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
- // create resource build phase - only for framework or bundle targets
- cmXCodeObject* resourceBuildPhase = nullptr;
- if (!resourceFiles.empty() &&
- (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
- resourceBuildPhase =
- this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
- resourceBuildPhase->SetComment("Resources");
- resourceBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (auto& resourceFile : resourceFiles) {
- buildFiles->AddObject(resourceFile);
- }
- resourceBuildPhase->AddAttribute("files", buildFiles);
- resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- }
-
- // create vector of "non-resource content file" build phases - only for
- // framework or bundle targets
- std::vector<cmXCodeObject*> contentBuildPhases;
- if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
- typedef std::map<std::string, std::vector<cmSourceFile*>>
- mapOfVectorOfSourceFiles;
- mapOfVectorOfSourceFiles bundleFiles;
- for (auto sourceFile : classes) {
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(sourceFile);
- if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
- bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
- }
+ // create vector of "non-resource content file" build phases - only for
+ // framework or bundle targets
+ std::vector<cmXCodeObject*> contentBuildPhases;
+ if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
+ typedef std::map<std::string, std::vector<cmSourceFile*>>
+ mapOfVectorOfSourceFiles;
+ mapOfVectorOfSourceFiles bundleFiles;
+ for (auto sourceFile : classes) {
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
+ if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
- for (auto keySources : bundleFiles) {
- cmXCodeObject* copyFilesBuildPhase =
- this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
- copyFilesBuildPhase->SetComment("Copy files");
- copyFilesBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
- this->CreateString("6"));
- std::ostringstream ostr;
- if (gtgt->IsFrameworkOnApple()) {
- // dstPath in frameworks is relative to Versions/<version>
+ }
+ for (auto keySources : bundleFiles) {
+ cmXCodeObject* copyFilesBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
+ copyFilesBuildPhase->SetComment("Copy files");
+ copyFilesBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
+ this->CreateString("6"));
+ std::ostringstream ostr;
+ if (gtgt->IsFrameworkOnApple()) {
+ // dstPath in frameworks is relative to Versions/<version>
+ ostr << keySources.first;
+ } else if (keySources.first != "MacOS") {
+ if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) {
ostr << keySources.first;
- } else if (keySources.first != "MacOS") {
- if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) {
- ostr << keySources.first;
- } else {
- // dstPath in bundles is relative to Contents/MacOS
- ostr << "../" << keySources.first;
- }
- }
- copyFilesBuildPhase->AddAttribute("dstPath",
- this->CreateString(ostr.str()));
- copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- copyFilesBuildPhase->AddAttribute("files", buildFiles);
- for (auto sourceFile : keySources.second) {
- cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, sourceFile, gtgt);
- buildFiles->AddObject(xsf);
+ } else {
+ // dstPath in bundles is relative to Contents/MacOS
+ ostr << "../" << keySources.first;
}
- contentBuildPhases.push_back(copyFilesBuildPhase);
}
+ copyFilesBuildPhase->AddAttribute("dstPath",
+ this->CreateString(ostr.str()));
+ copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ copyFilesBuildPhase->AddAttribute("files", buildFiles);
+ for (auto sourceFile : keySources.second) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
+ buildFiles->AddObject(xsf);
+ }
+ contentBuildPhases.push_back(copyFilesBuildPhase);
}
+ }
- // create vector of "resource content file" build phases - only for
- // framework or bundle targets
- if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
- typedef std::map<std::string, std::vector<cmSourceFile*>>
- mapOfVectorOfSourceFiles;
- mapOfVectorOfSourceFiles bundleFiles;
- for (auto sourceFile : classes) {
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(sourceFile);
- if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
- bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
- }
- }
- for (auto keySources : bundleFiles) {
- 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(keySources.first));
- copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- copyFilesBuildPhase->AddAttribute("files", buildFiles);
- for (auto sourceFile : keySources.second) {
- cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, sourceFile, gtgt);
- buildFiles->AddObject(xsf);
- }
- contentBuildPhases.push_back(copyFilesBuildPhase);
+ // create vector of "resource content file" build phases - only for
+ // framework or bundle targets
+ if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
+ typedef std::map<std::string, std::vector<cmSourceFile*>>
+ mapOfVectorOfSourceFiles;
+ mapOfVectorOfSourceFiles bundleFiles;
+ for (auto sourceFile : classes) {
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
+ if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
}
-
- // create framework build phase
- cmXCodeObject* frameworkBuildPhase = nullptr;
- if (!externalObjFiles.empty()) {
- frameworkBuildPhase =
- this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
- frameworkBuildPhase->SetComment("Frameworks");
- frameworkBuildPhase->AddAttribute("buildActionMask",
+ for (auto keySources : bundleFiles) {
+ 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(keySources.first));
+ copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- frameworkBuildPhase->AddAttribute("files", buildFiles);
- for (auto& externalObjFile : externalObjFiles) {
- buildFiles->AddObject(externalObjFile);
+ copyFilesBuildPhase->AddAttribute("files", buildFiles);
+ for (auto sourceFile : keySources.second) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
+ buildFiles->AddObject(xsf);
}
- frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
+ contentBuildPhases.push_back(copyFilesBuildPhase);
+ }
+ }
+
+ // create framework build phase
+ cmXCodeObject* frameworkBuildPhase = nullptr;
+ if (!externalObjFiles.empty()) {
+ frameworkBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
+ frameworkBuildPhase->SetComment("Frameworks");
+ frameworkBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ frameworkBuildPhase->AddAttribute("files", buildFiles);
+ for (auto& externalObjFile : externalObjFiles) {
+ buildFiles->AddObject(externalObjFile);
}
+ frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
- // create list of build phases and create the Xcode target
- cmXCodeObject* buildPhases =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ // create list of build phases and create the Xcode target
+ cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
- resourceBuildPhase, contentBuildPhases,
- frameworkBuildPhase, gtgt);
+ this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
+ resourceBuildPhase, contentBuildPhases,
+ frameworkBuildPhase, gtgt);
- targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
- }
+ targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
return true;
}
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) {
this->CurrentLocalGenerator->GetStaticLibraryFlags(
- extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt);
+ extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt);
} else {
const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags);
}
}
+ std::vector<std::string> opts;
+ gtgt->GetLinkOptions(opts, configName, llang);
+ // LINK_OPTIONS are escaped.
+ this->CurrentLocalGenerator->AppendCompileOptions(extraLinkOptions, opts);
}
// Set target-specific architectures.
// Point Xcode at the top of the source tree.
{
std::string pdir =
- this->RelativeToBinary(root->GetCurrentSourceDirectory());
+ this->RelativeToBinary(root->GetCurrentSourceDirectory().c_str());
this->RootObject->AddAttribute("projectDirPath", this->CreateString(pdir));
this->RootObject->AddAttribute("projectRoot", this->CreateString(""));
}
if (generators.empty()) {
return;
}
- // Skip local generators that are excluded from this project.
- for (auto generator : generators) {
- if (this->IsExcluded(root, generator)) {
- continue;
- }
- }
-
if (!this->CreateXCodeObjects(root, generators)) {
return;
}
i.e. "Can I build Debug and Release in the same tree?" */
bool IsMultiConfig() const override;
+ bool IsXcode() const override { return true; }
+
bool HasKnownObjectFileLocation(std::string* reason) const override;
bool IsIPOSupported() const override { return true; }
protected:
void AddExtraIDETargets() override;
+ void ComputeTargetOrder();
+ void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index);
void Generate() override;
private:
void AddXCodeProjBuildRule(cmGeneratorTarget* target,
std::vector<cmSourceFile*>& sources) const;
bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
+ bool CreateXCodeTarget(cmGeneratorTarget* gtgt,
+ std::vector<cmXCodeObject*>&);
bool IsHeaderFile(cmSourceFile*);
void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);
void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets);
std::string ObjectDirArchDefault;
std::string ObjectDirArch;
std::string GeneratorToolset;
+ std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;
};
#endif
currentFilename += ptr.first;
currentFilename += ".dependers";
- cmGeneratedFileStream str(currentFilename.c_str());
+ cmGeneratedFileStream str(currentFilename);
if (!str) {
return;
}
std::string currentFilename = fileName;
currentFilename += ".";
currentFilename += ptr.first;
- cmGeneratedFileStream str(currentFilename.c_str());
+ cmGeneratedFileStream str(currentFilename);
if (!str) {
return;
}
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmHexFileConverter.h"
+#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define MOTOROLA_SREC_MIN_LINE_LENGTH (2 + 2 + 4 + 2)
#define MOTOROLA_SREC_MAX_LINE_LENGTH (2 + 2 + 8 + (256 * 2) + 2)
-// might go to SystemTools ?
-static bool cm_IsHexChar(char c)
-{
- return (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) ||
- ((c >= 'A') && (c <= 'F')));
-}
-
static unsigned int ChompStrlen(const char* line)
{
if (line == nullptr) {
}
for (unsigned int i = 1; i < slen; i++) {
- if (!cm_IsHexChar(buf[i])) {
+ if (!isxdigit(buf[i])) {
return Binary;
}
}
#include <algorithm>
#include <set>
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
return true;
}
-static bool StartsWithGeneratorExpression(const std::string& input)
-{
- return input[0] == '$' && input[1] == '<';
-}
-
// do a lot of cleanup on the arguments because this is one place where folks
// sometimes take the output of a program and pass it directly into this
// command not thinking that a single argument could be filled with spaces
return;
}
- if (!cmSystemTools::IsOff(inc.c_str())) {
+ if (!cmSystemTools::IsOff(inc)) {
cmSystemTools::ConvertToUnixSlashes(inc);
if (!cmSystemTools::FileIsFullPath(inc)) {
- if (!StartsWithGeneratorExpression(inc)) {
+ if (!cmGeneratorExpression::StartsWithGeneratorExpression(inc)) {
std::string tmp = this->Makefile->GetCurrentSourceDirectory();
tmp += "/";
tmp += inc;
#include "cmsys/Glob.hxx"
#include <sstream>
#include <stddef.h>
-#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
// Tell the global generator about any installation component names
// specified.
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str());
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(component);
return true;
}
// Check whether this is a DLL platform.
bool dll_platform =
- strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
- "") != 0;
+ !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
for (std::string const& tgt : targetList.GetVector()) {
return false;
}
// Lookup this target in the current directory.
- if (cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt)) {
+ cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt);
+ if (!target) {
+ // If no local target has been found, find it in the global scope.
+ target = this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
+ }
+ if (target) {
// Found the target. Check its type.
if (target->GetType() != cmStateEnums::EXECUTABLE &&
target->GetType() != cmStateEnums::STATIC_LIBRARY &&
} else {
// Did not find the target.
std::ostringstream e;
- e << "TARGETS given target \"" << tgt
- << "\" which does not exist in this directory.";
+ e << "TARGETS given target \"" << tgt << "\" which does not exist.";
this->SetError(e.str());
return false;
}
// specified
if (installsArchive) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- archiveArgs.GetComponent().c_str());
+ archiveArgs.GetComponent());
}
if (installsLibrary) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- libraryArgs.GetComponent().c_str());
+ libraryArgs.GetComponent());
}
if (installsNamelink) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- libraryArgs.GetNamelinkComponent().c_str());
+ libraryArgs.GetNamelinkComponent());
}
if (installsRuntime) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- runtimeArgs.GetComponent().c_str());
+ runtimeArgs.GetComponent());
}
if (installsObject) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- objectArgs.GetComponent().c_str());
+ objectArgs.GetComponent());
}
if (installsFramework) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- frameworkArgs.GetComponent().c_str());
+ frameworkArgs.GetComponent());
}
if (installsBundle) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- bundleArgs.GetComponent().c_str());
+ bundleArgs.GetComponent());
}
if (installsPrivateHeader) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- privateHeaderArgs.GetComponent().c_str());
+ privateHeaderArgs.GetComponent());
}
if (installsPublicHeader) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- publicHeaderArgs.GetComponent().c_str());
+ publicHeaderArgs.GetComponent());
}
if (installsResource) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- resourceArgs.GetComponent().c_str());
+ resourceArgs.GetComponent());
}
return true;
// Tell the global generator about any installation component names
// specified.
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- ica.GetComponent().c_str());
+ ica.GetComponent());
return true;
}
// Tell the global generator about any installation component names
// specified.
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str());
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(component);
return true;
}
cmMakefile const& mf = *this->LocalGenerator->GetMakefile();
for (std::string& d : dirs) {
if (!cmSystemTools::FileIsFullPath(d)) {
- d = std::string(mf.GetCurrentSourceDirectory()) + "/" + d;
+ d = mf.GetCurrentSourceDirectory() + "/" + d;
}
}
void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
{
+ // Lookup this target in the current directory.
this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
+ if (!this->Target) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
}
void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
{
std::string value;
bool isSet = this->GetProperty(prop, value);
- return isSet && cmSystemTools::IsOn(value.c_str());
+ return isSet && cmSystemTools::IsOn(value);
}
void cmInstalledFile::GetPropertyAsList(const std::string& prop,
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <string>
+
+// Vocabulary:
+
+static const std::string kARTIFACTS_KEY = "artifacts";
+static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
+static const std::string kCOMPILE_FLAGS_KEY = "compileFlags";
+static const std::string kCONFIGURATIONS_KEY = "configurations";
+static const std::string kDEFINES_KEY = "defines";
+static const std::string kFILE_GROUPS_KEY = "fileGroups";
+static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath";
+static const std::string kFULL_NAME_KEY = "fullName";
+static const std::string kINCLUDE_PATH_KEY = "includePath";
+static const std::string kIS_CMAKE_KEY = "isCMake";
+static const std::string kIS_GENERATED_KEY = "isGenerated";
+static const std::string kIS_SYSTEM_KEY = "isSystem";
+static const std::string kIS_TEMPORARY_KEY = "isTemporary";
+static const std::string kKEY_KEY = "key";
+static const std::string kLANGUAGE_KEY = "language";
+static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage";
+static const std::string kLINK_FLAGS_KEY = "linkFlags";
+static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags";
+static const std::string kLINK_LIBRARIES_KEY = "linkLibraries";
+static const std::string kLINK_PATH_KEY = "linkPath";
+static const std::string kNAME_KEY = "name";
+static const std::string kPATH_KEY = "path";
+static const std::string kPROJECTS_KEY = "projects";
+static const std::string kPROPERTIES_KEY = "properties";
+static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
+static const std::string kSOURCES_KEY = "sources";
+static const std::string kSYSROOT_KEY = "sysroot";
+static const std::string kTARGETS_KEY = "targets";
+static const std::string kTYPE_KEY = "type";
+static const std::string kVALUE_KEY = "value";
+static const std::string kHAS_INSTALL_RULE = "hasInstallRule";
+static const std::string kINSTALL_PATHS = "installPaths";
+static const std::string kCTEST_NAME = "ctestName";
+static const std::string kCTEST_COMMAND = "ctestCommand";
+static const std::string kCTEST_INFO = "ctestInfo";
+static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion";
+static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided";
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmJsonObjects.h" // IWYU pragma: keep
+
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmJsonObjectDictionary.h"
+#include "cmJsonObjects.h"
+#include "cmLinkLineComputer.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmProperty.h"
+#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTest.h"
+#include "cmake.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <functional>
+#include <limits>
+#include <map>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+namespace {
+
+std::vector<std::string> getConfigurations(const cmake* cm)
+{
+ std::vector<std::string> configurations;
+ auto makefiles = cm->GetGlobalGenerator()->GetMakefiles();
+ if (makefiles.empty()) {
+ return configurations;
+ }
+
+ makefiles[0]->GetConfigurations(configurations);
+ if (configurations.empty()) {
+ configurations.push_back("");
+ }
+ return configurations;
+}
+
+bool hasString(const Json::Value& v, const std::string& s)
+{
+ return !v.isNull() &&
+ std::any_of(v.begin(), v.end(),
+ [s](const Json::Value& i) { return i.asString() == s; });
+}
+
+template <class T>
+Json::Value fromStringList(const T& in)
+{
+ Json::Value result = Json::arrayValue;
+ for (std::string const& i : in) {
+ result.append(i);
+ }
+ return result;
+}
+
+} // namespace
+
+void cmGetCMakeInputs(const cmGlobalGenerator* gg,
+ const std::string& sourceDir,
+ const std::string& buildDir,
+ std::vector<std::string>* internalFiles,
+ std::vector<std::string>* explicitFiles,
+ std::vector<std::string>* tmpFiles)
+{
+ const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/';
+ std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles();
+ for (cmMakefile const* mf : makefiles) {
+ for (std::string const& lf : mf->GetListFiles()) {
+
+ const std::string startOfFile = lf.substr(0, cmakeRootDir.size());
+ const bool isInternal = (startOfFile == cmakeRootDir);
+ const bool isTemporary = !isInternal && (lf.find(buildDir + '/') == 0);
+
+ std::string toAdd = lf;
+ if (!sourceDir.empty()) {
+ const std::string& relative =
+ cmSystemTools::RelativePath(sourceDir, lf);
+ if (toAdd.size() > relative.size()) {
+ toAdd = relative;
+ }
+ }
+
+ if (isInternal) {
+ if (internalFiles) {
+ internalFiles->push_back(std::move(toAdd));
+ }
+ } else {
+ if (isTemporary) {
+ if (tmpFiles) {
+ tmpFiles->push_back(std::move(toAdd));
+ }
+ } else {
+ if (explicitFiles) {
+ explicitFiles->push_back(std::move(toAdd));
+ }
+ }
+ }
+ }
+ }
+}
+
+Json::Value cmDumpCMakeInputs(const cmake* cm)
+{
+ const cmGlobalGenerator* gg = cm->GetGlobalGenerator();
+ const std::string& buildDir = cm->GetHomeOutputDirectory();
+ const std::string& sourceDir = cm->GetHomeDirectory();
+
+ std::vector<std::string> internalFiles;
+ std::vector<std::string> explicitFiles;
+ std::vector<std::string> tmpFiles;
+ cmGetCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles,
+ &tmpFiles);
+
+ Json::Value array = Json::arrayValue;
+
+ Json::Value tmp = Json::objectValue;
+ tmp[kIS_CMAKE_KEY] = true;
+ tmp[kIS_TEMPORARY_KEY] = false;
+ tmp[kSOURCES_KEY] = fromStringList(internalFiles);
+ array.append(tmp);
+
+ tmp = Json::objectValue;
+ tmp[kIS_CMAKE_KEY] = false;
+ tmp[kIS_TEMPORARY_KEY] = false;
+ tmp[kSOURCES_KEY] = fromStringList(explicitFiles);
+ array.append(tmp);
+
+ tmp = Json::objectValue;
+ tmp[kIS_CMAKE_KEY] = false;
+ tmp[kIS_TEMPORARY_KEY] = true;
+ tmp[kSOURCES_KEY] = fromStringList(tmpFiles);
+ array.append(tmp);
+
+ return array;
+}
+
+class LanguageData
+{
+public:
+ bool operator==(const LanguageData& other) const;
+
+ void SetDefines(const std::set<std::string>& defines);
+
+ bool IsGenerated = false;
+ std::string Language;
+ std::string Flags;
+ std::vector<std::string> Defines;
+ std::vector<std::pair<std::string, bool>> IncludePathList;
+};
+
+bool LanguageData::operator==(const LanguageData& other) const
+{
+ return Language == other.Language && Defines == other.Defines &&
+ Flags == other.Flags && IncludePathList == other.IncludePathList &&
+ IsGenerated == other.IsGenerated;
+}
+
+void LanguageData::SetDefines(const std::set<std::string>& defines)
+{
+ std::vector<std::string> result;
+ result.reserve(defines.size());
+ for (std::string const& i : defines) {
+ result.push_back(i);
+ }
+ std::sort(result.begin(), result.end());
+ Defines = std::move(result);
+}
+
+namespace std {
+
+template <>
+struct hash<LanguageData>
+{
+ std::size_t operator()(const LanguageData& in) const
+ {
+ using std::hash;
+ size_t result =
+ hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
+ for (auto const& i : in.IncludePathList) {
+ result = result ^
+ (hash<std::string>()(i.first) ^
+ (i.second ? std::numeric_limits<size_t>::max() : 0));
+ }
+ for (auto const& i : in.Defines) {
+ result = result ^ hash<std::string>()(i);
+ }
+ result =
+ result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0);
+ return result;
+ }
+};
+
+} // namespace std
+
+static Json::Value DumpSourceFileGroup(const LanguageData& data,
+ const std::vector<std::string>& files,
+ const std::string& baseDir)
+{
+ Json::Value result = Json::objectValue;
+
+ if (!data.Language.empty()) {
+ result[kLANGUAGE_KEY] = data.Language;
+ if (!data.Flags.empty()) {
+ result[kCOMPILE_FLAGS_KEY] = data.Flags;
+ }
+ if (!data.IncludePathList.empty()) {
+ Json::Value includes = Json::arrayValue;
+ for (auto const& i : data.IncludePathList) {
+ Json::Value tmp = Json::objectValue;
+ tmp[kPATH_KEY] = i.first;
+ if (i.second) {
+ tmp[kIS_SYSTEM_KEY] = i.second;
+ }
+ includes.append(tmp);
+ }
+ result[kINCLUDE_PATH_KEY] = includes;
+ }
+ if (!data.Defines.empty()) {
+ result[kDEFINES_KEY] = fromStringList(data.Defines);
+ }
+ }
+
+ result[kIS_GENERATED_KEY] = data.IsGenerated;
+
+ Json::Value sourcesValue = Json::arrayValue;
+ for (auto const& i : files) {
+ const std::string relPath = cmSystemTools::RelativePath(baseDir, i);
+ sourcesValue.append(relPath.size() < i.size() ? relPath : i);
+ }
+
+ result[kSOURCES_KEY] = sourcesValue;
+ return result;
+}
+
+static Json::Value DumpSourceFilesList(
+ cmGeneratorTarget* target, const std::string& config,
+ const std::map<std::string, LanguageData>& languageDataMap)
+{
+ // Collect sourcefile groups:
+
+ std::vector<cmSourceFile*> files;
+ target->GetSourceFiles(files, config);
+
+ std::unordered_map<LanguageData, std::vector<std::string>> fileGroups;
+ for (cmSourceFile* file : files) {
+ LanguageData fileData;
+ fileData.Language = file->GetLanguage();
+ if (!fileData.Language.empty()) {
+ const LanguageData& ld = languageDataMap.at(fileData.Language);
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+ fileData.Language);
+
+ std::string compileFlags = ld.Flags;
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = file->GetProperty(COMPILE_FLAGS)) {
+ lg->AppendFlags(compileFlags,
+ genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
+ }
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = file->GetProperty(COMPILE_OPTIONS)) {
+ lg->AppendCompileOptions(
+ compileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
+ }
+ fileData.Flags = compileFlags;
+
+ // Add include directories from source file properties.
+ std::vector<std::string> includes;
+
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) {
+ const std::string& evaluatedIncludes =
+ genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
+ lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file);
+
+ for (const auto& include : includes) {
+ fileData.IncludePathList.push_back(
+ std::make_pair(include,
+ target->IsSystemIncludeDirectory(
+ include, config, fileData.Language)));
+ }
+ }
+
+ fileData.IncludePathList.insert(fileData.IncludePathList.end(),
+ ld.IncludePathList.begin(),
+ ld.IncludePathList.end());
+
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ std::set<std::string> defines;
+ if (const char* defs = file->GetProperty(COMPILE_DEFINITIONS)) {
+ lg->AppendDefines(
+ defines, genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS));
+ }
+
+ const std::string defPropName =
+ "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
+ if (const char* config_defs = file->GetProperty(defPropName)) {
+ lg->AppendDefines(
+ defines,
+ genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS));
+ }
+
+ defines.insert(ld.Defines.begin(), ld.Defines.end());
+
+ fileData.SetDefines(defines);
+ }
+
+ fileData.IsGenerated = file->GetPropertyAsBool("GENERATED");
+ std::vector<std::string>& groupFileList = fileGroups[fileData];
+ groupFileList.push_back(file->GetFullPath());
+ }
+
+ const std::string& baseDir = target->Makefile->GetCurrentSourceDirectory();
+ Json::Value result = Json::arrayValue;
+ for (auto const& it : fileGroups) {
+ Json::Value group = DumpSourceFileGroup(it.first, it.second, baseDir);
+ if (!group.isNull()) {
+ result.append(group);
+ }
+ }
+
+ return result;
+}
+
+static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo,
+ const std::string& config)
+{
+ Json::Value result = Json::objectValue;
+ result[kCTEST_NAME] = testInfo->GetName();
+
+ // Concat command entries together. After the first should be the arguments
+ // for the command
+ std::string command;
+ for (auto const& cmd : testInfo->GetCommand()) {
+ command.append(cmd);
+ command.append(" ");
+ }
+
+ // Remove any config specific variables from the output.
+ cmGeneratorExpression ge;
+ auto cge = ge.Parse(command);
+ const std::string& processed = cge->Evaluate(lg, config);
+ result[kCTEST_COMMAND] = processed;
+
+ // Build up the list of properties that may have been specified
+ Json::Value properties = Json::arrayValue;
+ for (auto& prop : testInfo->GetProperties()) {
+ Json::Value entry = Json::objectValue;
+ entry[kKEY_KEY] = prop.first;
+
+ // Remove config variables from the value too.
+ auto cge_value = ge.Parse(prop.second.GetValue());
+ const std::string& processed_value = cge_value->Evaluate(lg, config);
+ entry[kVALUE_KEY] = processed_value;
+ properties.append(entry);
+ }
+ result[kPROPERTIES_KEY] = properties;
+
+ return result;
+}
+
+static void DumpMakefileTests(cmLocalGenerator* lg, const std::string& config,
+ Json::Value* result)
+{
+ auto mf = lg->GetMakefile();
+ std::vector<cmTest*> tests;
+ mf->GetTests(config, tests);
+ for (auto test : tests) {
+ Json::Value tmp = DumpCTestInfo(lg, test, config);
+ if (!tmp.isNull()) {
+ result->append(tmp);
+ }
+ }
+}
+
+static Json::Value DumpCTestProjectList(const cmake* cm,
+ std::string const& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ auto globalGen = cm->GetGlobalGenerator();
+
+ for (const auto& projectIt : globalGen->GetProjectMap()) {
+ Json::Value pObj = Json::objectValue;
+ pObj[kNAME_KEY] = projectIt.first;
+
+ Json::Value tests = Json::arrayValue;
+
+ // Gather tests for every generator
+ for (const auto& lg : projectIt.second) {
+ // Make sure they're generated.
+ lg->GenerateTestFiles();
+ DumpMakefileTests(lg, config, &tests);
+ }
+
+ pObj[kCTEST_INFO] = tests;
+
+ result.append(pObj);
+ }
+
+ return result;
+}
+
+static Json::Value DumpCTestConfiguration(const cmake* cm,
+ const std::string& config)
+{
+ Json::Value result = Json::objectValue;
+ result[kNAME_KEY] = config;
+
+ result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config);
+
+ return result;
+}
+
+static Json::Value DumpCTestConfigurationsList(const cmake* cm)
+{
+ Json::Value result = Json::arrayValue;
+
+ for (const std::string& c : getConfigurations(cm)) {
+ result.append(DumpCTestConfiguration(cm, c));
+ }
+
+ return result;
+}
+
+Json::Value cmDumpCTestInfo(const cmake* cm)
+{
+ Json::Value result = Json::objectValue;
+ result[kCONFIGURATIONS_KEY] = DumpCTestConfigurationsList(cm);
+ return result;
+}
+
+static Json::Value DumpTarget(cmGeneratorTarget* target,
+ const std::string& config)
+{
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ const cmState* state = lg->GetState();
+
+ const cmStateEnums::TargetType type = target->GetType();
+ const std::string typeName = state->GetTargetTypeName(type);
+
+ Json::Value ttl = Json::arrayValue;
+ ttl.append("EXECUTABLE");
+ ttl.append("STATIC_LIBRARY");
+ ttl.append("SHARED_LIBRARY");
+ ttl.append("MODULE_LIBRARY");
+ ttl.append("OBJECT_LIBRARY");
+ ttl.append("UTILITY");
+ ttl.append("INTERFACE_LIBRARY");
+
+ if (!hasString(ttl, typeName) || target->IsImported()) {
+ return Json::Value();
+ }
+
+ Json::Value result = Json::objectValue;
+ result[kNAME_KEY] = target->GetName();
+ result[kIS_GENERATOR_PROVIDED_KEY] =
+ target->Target->GetIsGeneratorProvided();
+ result[kTYPE_KEY] = typeName;
+ result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory();
+ result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory();
+
+ if (type == cmStateEnums::INTERFACE_LIBRARY) {
+ return result;
+ }
+
+ result[kFULL_NAME_KEY] = target->GetFullName(config);
+
+ if (target->Target->GetHaveInstallRule()) {
+ result[kHAS_INSTALL_RULE] = true;
+
+ Json::Value installPaths = Json::arrayValue;
+ auto targetGenerators = target->Makefile->GetInstallGenerators();
+ for (auto installGenerator : targetGenerators) {
+ auto installTargetGenerator =
+ dynamic_cast<cmInstallTargetGenerator*>(installGenerator);
+ if (installTargetGenerator != nullptr &&
+ installTargetGenerator->GetTarget()->Target == target->Target) {
+ auto dest = installTargetGenerator->GetDestination(config);
+
+ std::string installPath;
+ if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) {
+ installPath = dest;
+ } else {
+ std::string installPrefix =
+ target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ installPath = installPrefix + '/' + dest;
+ }
+
+ installPaths.append(installPath);
+ }
+ }
+
+ result[kINSTALL_PATHS] = installPaths;
+ }
+
+ if (target->HaveWellDefinedOutputFiles()) {
+ Json::Value artifacts = Json::arrayValue;
+ artifacts.append(
+ target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
+ if (target->IsDLLPlatform()) {
+ artifacts.append(
+ target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
+ const cmGeneratorTarget::OutputInfo* output =
+ target->GetOutputInfo(config);
+ if (output && !output->PdbDir.empty()) {
+ artifacts.append(output->PdbDir + '/' + target->GetPDBName(config));
+ }
+ }
+ result[kARTIFACTS_KEY] = artifacts;
+
+ result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config);
+
+ std::string linkLibs;
+ std::string linkFlags;
+ std::string linkLanguageFlags;
+ std::string frameworkPath;
+ std::string linkPath;
+ cmLinkLineComputer linkLineComputer(lg,
+ lg->GetStateSnapshot().GetDirectory());
+ lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
+ linkFlags, frameworkPath, linkPath, target);
+
+ linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
+ linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
+ linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
+ frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
+ linkPath = cmSystemTools::TrimWhitespace(linkPath);
+
+ if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) {
+ result[kLINK_LIBRARIES_KEY] = linkLibs;
+ }
+ if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) {
+ result[kLINK_FLAGS_KEY] = linkFlags;
+ }
+ if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) {
+ result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
+ }
+ if (!frameworkPath.empty()) {
+ result[kFRAMEWORK_PATH_KEY] = frameworkPath;
+ }
+ if (!linkPath.empty()) {
+ result[kLINK_PATH_KEY] = linkPath;
+ }
+ const std::string sysroot =
+ lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT");
+ if (!sysroot.empty()) {
+ result[kSYSROOT_KEY] = sysroot;
+ }
+ }
+
+ std::set<std::string> languages;
+ target->GetLanguages(languages, config);
+ std::map<std::string, LanguageData> languageDataMap;
+
+ for (std::string const& lang : languages) {
+ LanguageData& ld = languageDataMap[lang];
+ ld.Language = lang;
+ lg->GetTargetCompileFlags(target, config, lang, ld.Flags);
+ std::set<std::string> defines;
+ lg->GetTargetDefines(target, config, lang, defines);
+ ld.SetDefines(defines);
+ std::vector<std::string> includePathList;
+ lg->GetIncludeDirectories(includePathList, target, lang, config, true);
+ for (std::string const& i : includePathList) {
+ ld.IncludePathList.push_back(
+ std::make_pair(i, target->IsSystemIncludeDirectory(i, config, lang)));
+ }
+ }
+
+ Json::Value sourceGroupsValue =
+ DumpSourceFilesList(target, config, languageDataMap);
+ if (!sourceGroupsValue.empty()) {
+ result[kFILE_GROUPS_KEY] = sourceGroupsValue;
+ }
+
+ return result;
+}
+
+static Json::Value DumpTargetsList(
+ const std::vector<cmLocalGenerator*>& generators, const std::string& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ std::vector<cmGeneratorTarget*> targetList;
+ for (auto const& lgIt : generators) {
+ const auto& list = lgIt->GetGeneratorTargets();
+ targetList.insert(targetList.end(), list.begin(), list.end());
+ }
+ std::sort(targetList.begin(), targetList.end());
+
+ for (cmGeneratorTarget* target : targetList) {
+ Json::Value tmp = DumpTarget(target, config);
+ if (!tmp.isNull()) {
+ result.append(tmp);
+ }
+ }
+
+ return result;
+}
+
+static Json::Value DumpProjectList(const cmake* cm, std::string const& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ auto globalGen = cm->GetGlobalGenerator();
+
+ for (auto const& projectIt : globalGen->GetProjectMap()) {
+ Json::Value pObj = Json::objectValue;
+ pObj[kNAME_KEY] = projectIt.first;
+
+ // All Projects must have at least one local generator
+ assert(!projectIt.second.empty());
+ const cmLocalGenerator* lg = projectIt.second.at(0);
+
+ // Project structure information:
+ const cmMakefile* mf = lg->GetMakefile();
+ auto minVersion = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
+ pObj[kMINIMUM_CMAKE_VERSION] = minVersion ? minVersion : "";
+ pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
+ pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
+ pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
+
+ // For a project-level install rule it might be defined in any of its
+ // associated generators.
+ bool hasInstallRule = false;
+ for (const auto generator : projectIt.second) {
+ hasInstallRule =
+ generator->GetMakefile()->GetInstallGenerators().empty() == false;
+
+ if (hasInstallRule) {
+ break;
+ }
+ }
+
+ pObj[kHAS_INSTALL_RULE] = hasInstallRule;
+
+ result.append(pObj);
+ }
+
+ return result;
+}
+
+static Json::Value DumpConfiguration(const cmake* cm,
+ const std::string& config)
+{
+ Json::Value result = Json::objectValue;
+ result[kNAME_KEY] = config;
+
+ result[kPROJECTS_KEY] = DumpProjectList(cm, config);
+
+ return result;
+}
+
+static Json::Value DumpConfigurationsList(const cmake* cm)
+{
+ Json::Value result = Json::arrayValue;
+
+ for (std::string const& c : getConfigurations(cm)) {
+ result.append(DumpConfiguration(cm, c));
+ }
+
+ return result;
+}
+
+Json::Value cmDumpCodeModel(const cmake* cm)
+{
+ Json::Value result = Json::objectValue;
+ result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(cm);
+ return result;
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmJsonObjects_h
+#define cmJsonObjects_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_value.h"
+
+#include <string>
+#include <vector>
+
+class cmake;
+class cmGlobalGenerator;
+
+extern void cmGetCMakeInputs(const cmGlobalGenerator* gg,
+ const std::string& sourceDir,
+ const std::string& buildDir,
+ std::vector<std::string>* internalFiles,
+ std::vector<std::string>* explicitFiles,
+ std::vector<std::string>* tmpFiles);
+
+extern Json::Value cmDumpCodeModel(const cmake* cm);
+extern Json::Value cmDumpCTestInfo(const cmake* cm);
+extern Json::Value cmDumpCMakeInputs(const cmake* cm);
+
+#endif
#include <sstream>
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmSystemTools.h"
return true;
}
- for (std::string const& i : args) {
- this->AddLinkDir(i);
+ bool before = this->Makefile->IsOn("CMAKE_LINK_DIRECTORIES_BEFORE");
+
+ auto i = args.cbegin();
+ if ((*i) == "BEFORE") {
+ before = true;
+ ++i;
+ } else if ((*i) == "AFTER") {
+ before = false;
+ ++i;
+ }
+
+ std::vector<std::string> directories;
+ for (; i != args.cend(); ++i) {
+ this->AddLinkDir(*i, directories);
}
+
+ this->Makefile->AddLinkDirectory(cmJoin(directories, ";"), before);
+
return true;
}
-void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
+void cmLinkDirectoriesCommand::AddLinkDir(
+ std::string const& dir, std::vector<std::string>& directories)
{
std::string unixPath = dir;
cmSystemTools::ConvertToUnixSlashes(unixPath);
- if (!cmSystemTools::FileIsFullPath(unixPath)) {
+ if (!cmSystemTools::FileIsFullPath(unixPath) &&
+ !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) {
bool convertToAbsolute = false;
std::ostringstream e;
/* clang-format off */
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015);
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ break;
case cmPolicies::OLD:
// OLD behavior does not convert
break;
unixPath = tmp;
}
}
- this->Makefile->AppendProperty("LINK_DIRECTORIES", unixPath.c_str());
+ directories.push_back(unixPath);
}
cmExecutionStatus& status) override;
private:
- void AddLinkDir(std::string const& dir);
+ void AddLinkDir(std::string const& dir,
+ std::vector<std::string>& directories);
};
#endif
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLinkItem.h"
+
+#include "cmGeneratorTarget.h"
+
+#include <utility> // IWYU pragma: keep
+
+cmLinkItem::cmLinkItem()
+ : String()
+ , Target(nullptr)
+{
+}
+
+cmLinkItem::cmLinkItem(std::string const& n)
+ : String(n)
+ , Target(nullptr)
+{
+}
+
+cmLinkItem::cmLinkItem(cmGeneratorTarget const* t)
+ : String()
+ , Target(t)
+{
+}
+
+std::string const& cmLinkItem::AsStr() const
+{
+ return this->Target ? this->Target->GetName() : this->String;
+}
+
+bool operator<(cmLinkItem const& l, cmLinkItem const& r)
+{
+ // Order among targets.
+ if (l.Target && r.Target) {
+ return l.Target < r.Target;
+ }
+ // Order targets before strings.
+ if (l.Target) {
+ return true;
+ }
+ if (r.Target) {
+ return false;
+ }
+ // Order among strings.
+ return l.String < r.String;
+}
+
+bool operator==(cmLinkItem const& l, cmLinkItem const& r)
+{
+ return l.Target == r.Target && l.String == r.String;
+}
+
+std::ostream& operator<<(std::ostream& os, cmLinkItem const& item)
+{
+ return os << item.AsStr();
+}
+
+cmLinkImplItem::cmLinkImplItem()
+ : cmLinkItem()
+ , Backtrace()
+ , FromGenex(false)
+{
+}
+
+cmLinkImplItem::cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt,
+ bool fromGenex)
+ : cmLinkItem(std::move(item))
+ , Backtrace(bt)
+ , FromGenex(fromGenex)
+{
+}
#include <algorithm>
#include <map>
+#include <ostream>
#include <string>
#include <vector>
class cmGeneratorTarget;
// Basic information about each link item.
-class cmLinkItem : public std::string
+class cmLinkItem
{
- typedef std::string std_string;
+ std::string String;
public:
- cmLinkItem()
- : std_string()
- , Target(nullptr)
- {
- }
- cmLinkItem(const std_string& n, cmGeneratorTarget const* t)
- : std_string(n)
- , Target(t)
- {
- }
+ cmLinkItem();
+ explicit cmLinkItem(std::string const& s);
+ explicit cmLinkItem(cmGeneratorTarget const* t);
+ std::string const& AsStr() const;
cmGeneratorTarget const* Target;
+ friend bool operator<(cmLinkItem const& l, cmLinkItem const& r);
+ friend bool operator==(cmLinkItem const& l, cmLinkItem const& r);
+ friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item);
};
class cmLinkImplItem : public cmLinkItem
{
public:
- cmLinkImplItem()
- : cmLinkItem()
- , Backtrace()
- , FromGenex(false)
- {
- }
- cmLinkImplItem(std::string const& n, cmGeneratorTarget const* t,
- cmListFileBacktrace const& bt, bool fromGenex)
- : cmLinkItem(n, t)
- , Backtrace(bt)
- , FromGenex(fromGenex)
- {
- }
+ cmLinkImplItem();
+ cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt,
+ bool fromGenex);
cmListFileBacktrace Backtrace;
bool FromGenex;
};
#include "cmLinkLineDeviceComputer.h"
+#include <set>
#include <sstream>
+#include <utility>
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
{
// Write the library flags to the build rule.
std::ostringstream fout;
+
+ // Generate the unique set of link items when device linking.
+ // The nvcc device linker is designed so that each static library
+ // with device symbols only needs to be listed once as it doesn't
+ // care about link order.
+ std::set<std::string> emitted;
typedef cmComputeLinkInformation::ItemVector ItemVector;
ItemVector const& items = cli.GetItems();
std::string config = cli.GetConfig();
}
}
+ std::string out;
if (item.IsPath) {
// nvcc understands absolute paths to libraries ending in '.a' or '.lib'.
// These should be passed to nvlink. Other extensions need to be left
// can tolerate '.so' or '.dylib' it cannot tolerate '.so.1'.
if (cmHasLiteralSuffix(item.Value, ".a") ||
cmHasLiteralSuffix(item.Value, ".lib")) {
- fout << this->ConvertToOutputFormat(
+ out += this->ConvertToOutputFormat(
this->ConvertToLinkReference(item.Value));
}
} else if (cmLinkItemValidForDevice(item.Value)) {
- fout << item.Value;
+ out += item.Value;
+ }
+
+ if (emitted.insert(out).second) {
+ fout << out << " ";
}
- fout << " ";
}
if (!stdLibString.empty()) {
if (item < 0) {
item = static_cast<int>(nitem) + item;
}
- if (item < 0 || nitem <= static_cast<size_t>(item)) {
+ if (item < 0 || nitem < static_cast<size_t>(item)) {
std::ostringstream str;
str << "index: " << item << " out of range (-" << varArgsExpanded.size()
- << ", "
- << (varArgsExpanded.empty() ? 0 : (varArgsExpanded.size() - 1))
- << ")";
+ << ", " << varArgsExpanded.size() << ")";
this->SetError(str.str());
return false;
}
return true;
}
+class cmStringSorter
+{
+public:
+ enum class Order
+ {
+ UNINITIALIZED,
+ ASCENDING,
+ DESCENDING,
+ };
+
+ enum class Compare
+ {
+ UNINITIALIZED,
+ STRING,
+ FILE_BASENAME,
+ };
+ enum class CaseSensitivity
+ {
+ UNINITIALIZED,
+ SENSITIVE,
+ INSENSITIVE,
+ };
+
+protected:
+ typedef std::string (*StringFilter)(const std::string& in);
+ StringFilter GetCompareFilter(Compare compare)
+ {
+ return (compare == Compare::FILE_BASENAME) ? cmSystemTools::GetFilenameName
+ : nullptr;
+ }
+
+ StringFilter GetCaseFilter(CaseSensitivity sensitivity)
+ {
+ return (sensitivity == CaseSensitivity::INSENSITIVE)
+ ? cmSystemTools::LowerCase
+ : nullptr;
+ }
+
+public:
+ cmStringSorter(Compare compare, CaseSensitivity caseSensitivity,
+ Order desc = Order::ASCENDING)
+ : filters{ GetCompareFilter(compare), GetCaseFilter(caseSensitivity) }
+ , descending(desc == Order::DESCENDING)
+ {
+ }
+
+ std::string ApplyFilter(const std::string& argument)
+ {
+ std::string result = argument;
+ for (auto filter : filters) {
+ if (filter != nullptr) {
+ result = filter(result);
+ }
+ }
+ return result;
+ }
+
+ bool operator()(const std::string& a, const std::string& b)
+ {
+ std::string af = ApplyFilter(a);
+ std::string bf = ApplyFilter(b);
+ bool result;
+ if (descending) {
+ result = bf < af;
+ } else {
+ result = af < bf;
+ }
+ return result;
+ }
+
+protected:
+ StringFilter filters[2] = { nullptr, nullptr };
+ bool descending;
+};
+
bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
{
assert(args.size() >= 2);
- if (args.size() > 2) {
- this->SetError("sub-command SORT only takes one argument.");
+ if (args.size() > 8) {
+ this->SetError("sub-command SORT only takes up to six arguments.");
return false;
}
+ auto sortCompare = cmStringSorter::Compare::UNINITIALIZED;
+ auto sortCaseSensitivity = cmStringSorter::CaseSensitivity::UNINITIALIZED;
+ auto sortOrder = cmStringSorter::Order::UNINITIALIZED;
+
+ size_t argumentIndex = 2;
+ const std::string messageHint = "sub-command SORT ";
+
+ while (argumentIndex < args.size()) {
+ const std::string option = args[argumentIndex++];
+ if (option == "COMPARE") {
+ if (sortCompare != cmStringSorter::Compare::UNINITIALIZED) {
+ std::string error = messageHint + "option \"" + option +
+ "\" has been specified multiple times.";
+ this->SetError(error);
+ return false;
+ }
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "STRING") {
+ sortCompare = cmStringSorter::Compare::STRING;
+ } else if (argument == "FILE_BASENAME") {
+ sortCompare = cmStringSorter::Compare::FILE_BASENAME;
+ } else {
+ std::string error = messageHint + "value \"" + argument +
+ "\" for option \"" + option + "\" is invalid.";
+ this->SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "missing argument for option \"" + option + "\".";
+ this->SetError(error);
+ return false;
+ }
+ } else if (option == "CASE") {
+ if (sortCaseSensitivity !=
+ cmStringSorter::CaseSensitivity::UNINITIALIZED) {
+ std::string error = messageHint + "option \"" + option +
+ "\" has been specified multiple times.";
+ this->SetError(error);
+ return false;
+ }
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "SENSITIVE") {
+ sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
+ } else if (argument == "INSENSITIVE") {
+ sortCaseSensitivity = cmStringSorter::CaseSensitivity::INSENSITIVE;
+ } else {
+ std::string error = messageHint + "value \"" + argument +
+ "\" for option \"" + option + "\" is invalid.";
+ this->SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "missing argument for option \"" + option + "\".";
+ this->SetError(error);
+ return false;
+ }
+ } else if (option == "ORDER") {
+
+ if (sortOrder != cmStringSorter::Order::UNINITIALIZED) {
+ std::string error = messageHint + "option \"" + option +
+ "\" has been specified multiple times.";
+ this->SetError(error);
+ return false;
+ }
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "ASCENDING") {
+ sortOrder = cmStringSorter::Order::ASCENDING;
+ } else if (argument == "DESCENDING") {
+ sortOrder = cmStringSorter::Order::DESCENDING;
+ } else {
+ std::string error = messageHint + "value \"" + argument +
+ "\" for option \"" + option + "\" is invalid.";
+ this->SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "missing argument for option \"" + option + "\".";
+ this->SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "option \"" + option + "\" is unknown.";
+ this->SetError(error);
+ return false;
+ }
+ }
+ // set Default Values if Option is not given
+ if (sortCompare == cmStringSorter::Compare::UNINITIALIZED) {
+ sortCompare = cmStringSorter::Compare::STRING;
+ }
+ if (sortCaseSensitivity == cmStringSorter::CaseSensitivity::UNINITIALIZED) {
+ sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
+ }
+ if (sortOrder == cmStringSorter::Order::UNINITIALIZED) {
+ sortOrder = cmStringSorter::Order::ASCENDING;
+ }
+
const std::string& listName = args[1];
// expand the variable
std::vector<std::string> varArgsExpanded;
return false;
}
- std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
+ if ((sortCompare == cmStringSorter::Compare::STRING) &&
+ (sortCaseSensitivity == cmStringSorter::CaseSensitivity::SENSITIVE) &&
+ (sortOrder == cmStringSorter::Order::ASCENDING)) {
+ std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
+ } else {
+ cmStringSorter sorter(sortCompare, sortCaseSensitivity, sortOrder);
+ std::sort(varArgsExpanded.begin(), varArgsExpanded.end(), sorter);
+ }
std::string value = cmJoin(varArgsExpanded, ";");
this->Makefile->AddDefinition(listName, value.c_str());
#include <algorithm>
#include <assert.h>
+#include <memory>
#include <sstream>
cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=(
return true;
}
-struct cmListFileBacktrace::Entry : public cmListFileContext
+// We hold either the bottom scope of a directory or a call/file context.
+// Discriminate these cases via the parent pointer.
+struct cmListFileBacktrace::Entry
{
- Entry(cmListFileContext const& lfc, Entry* up)
- : cmListFileContext(lfc)
- , Up(up)
- , RefCount(0)
+ Entry(cmStateSnapshot bottom)
+ : Bottom(bottom)
{
- if (this->Up) {
- this->Up->Ref();
- }
}
- ~Entry()
+
+ Entry(std::shared_ptr<Entry const> parent, cmListFileContext lfc)
+ : Context(std::move(lfc))
+ , Parent(std::move(parent))
{
- if (this->Up) {
- this->Up->Unref();
- }
}
- void Ref() { ++this->RefCount; }
- void Unref()
+
+ ~Entry()
{
- if (--this->RefCount == 0) {
- delete this;
+ if (this->Parent) {
+ this->Context.~cmListFileContext();
+ } else {
+ this->Bottom.~cmStateSnapshot();
}
}
- Entry* Up;
- unsigned int RefCount;
-};
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom,
- Entry* up,
- cmListFileContext const& lfc)
- : Bottom(bottom)
- , Cur(new Entry(lfc, up))
-{
- assert(this->Bottom.IsValid());
- this->Cur->Ref();
-}
-
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom,
- Entry* cur)
- : Bottom(bottom)
- , Cur(cur)
-{
- if (this->Cur) {
- assert(this->Bottom.IsValid());
- this->Cur->Ref();
- }
-}
+ bool IsBottom() const { return !this->Parent; }
-cmListFileBacktrace::cmListFileBacktrace()
- : Bottom()
- , Cur(nullptr)
-{
-}
+ union
+ {
+ cmStateSnapshot Bottom;
+ cmListFileContext Context;
+ };
+ std::shared_ptr<Entry const> Parent;
+};
cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot)
- : Bottom(snapshot.GetCallStackBottom())
- , Cur(nullptr)
+ : TopEntry(std::make_shared<Entry const>(snapshot.GetCallStackBottom()))
{
}
-cmListFileBacktrace::cmListFileBacktrace(cmListFileBacktrace const& r)
- : Bottom(r.Bottom)
- , Cur(r.Cur)
+cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent,
+ cmListFileContext const& lfc)
+ : TopEntry(std::make_shared<Entry const>(std::move(parent), lfc))
{
- if (this->Cur) {
- assert(this->Bottom.IsValid());
- this->Cur->Ref();
- }
}
-cmListFileBacktrace& cmListFileBacktrace::operator=(
- cmListFileBacktrace const& r)
+cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> top)
+ : TopEntry(std::move(top))
{
- cmListFileBacktrace tmp(r);
- std::swap(this->Cur, tmp.Cur);
- std::swap(this->Bottom, tmp.Bottom);
- return *this;
}
-cmListFileBacktrace::~cmListFileBacktrace()
+cmStateSnapshot cmListFileBacktrace::GetBottom() const
{
- if (this->Cur) {
- this->Cur->Unref();
+ cmStateSnapshot bottom;
+ if (Entry const* cur = this->TopEntry.get()) {
+ while (Entry const* parent = cur->Parent.get()) {
+ cur = parent;
+ }
+ bottom = cur->Bottom;
}
+ return bottom;
}
cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const
// skipped during call stack printing.
cmListFileContext lfc;
lfc.FilePath = file;
- return cmListFileBacktrace(this->Bottom, this->Cur, lfc);
+ return this->Push(lfc);
}
cmListFileBacktrace cmListFileBacktrace::Push(
cmListFileContext const& lfc) const
{
- return cmListFileBacktrace(this->Bottom, this->Cur, lfc);
+ assert(this->TopEntry);
+ assert(!this->TopEntry->IsBottom() || this->TopEntry->Bottom.IsValid());
+ return cmListFileBacktrace(this->TopEntry, lfc);
}
cmListFileBacktrace cmListFileBacktrace::Pop() const
{
- assert(this->Cur);
- return cmListFileBacktrace(this->Bottom, this->Cur->Up);
+ assert(this->TopEntry);
+ assert(!this->TopEntry->IsBottom());
+ return cmListFileBacktrace(this->TopEntry->Parent);
}
cmListFileContext const& cmListFileBacktrace::Top() const
{
- if (this->Cur) {
- return *this->Cur;
- }
- static cmListFileContext const empty;
- return empty;
+ assert(this->TopEntry);
+ assert(!this->TopEntry->IsBottom());
+ return this->TopEntry->Context;
}
void cmListFileBacktrace::PrintTitle(std::ostream& out) const
{
- if (!this->Cur) {
+ // The title exists only if we have a call on top of the bottom.
+ if (!this->TopEntry || this->TopEntry->IsBottom()) {
return;
}
- cmOutputConverter converter(this->Bottom);
- cmListFileContext lfc = *this->Cur;
- if (!this->Bottom.GetState()->GetIsInTryCompile()) {
+ cmListFileContext lfc = this->TopEntry->Context;
+ cmStateSnapshot bottom = this->GetBottom();
+ cmOutputConverter converter(bottom);
+ if (!bottom.GetState()->GetIsInTryCompile()) {
lfc.FilePath = converter.ConvertToRelativePath(
- this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
+ bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
out << (lfc.Line ? " at " : " in ") << lfc;
}
void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
{
- if (!this->Cur || !this->Cur->Up) {
+ // The call stack exists only if we have at least two calls on top
+ // of the bottom.
+ if (!this->TopEntry || this->TopEntry->IsBottom() ||
+ this->TopEntry->Parent->IsBottom()) {
return;
}
bool first = true;
- cmOutputConverter converter(this->Bottom);
- for (Entry* i = this->Cur->Up; i; i = i->Up) {
- if (i->Name.empty()) {
+ cmStateSnapshot bottom = this->GetBottom();
+ cmOutputConverter converter(bottom);
+ for (Entry const* cur = this->TopEntry->Parent.get(); !cur->IsBottom();
+ cur = cur->Parent.get()) {
+ if (cur->Context.Name.empty()) {
// Skip this whole-file scope. When we get here we already will
// have printed a more-specific context within the file.
continue;
first = false;
out << "Call Stack (most recent call first):\n";
}
- cmListFileContext lfc = *i;
- if (!this->Bottom.GetState()->GetIsInTryCompile()) {
+ cmListFileContext lfc = cur->Context;
+ if (!bottom.GetState()->GetIsInTryCompile()) {
lfc.FilePath = converter.ConvertToRelativePath(
- this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
+ bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
out << " " << lfc << "\n";
}
size_t cmListFileBacktrace::Depth() const
{
size_t depth = 0;
- if (this->Cur == nullptr) {
- return 0;
- }
-
- for (Entry* i = this->Cur->Up; i; i = i->Up) {
- depth++;
+ if (Entry const* cur = this->TopEntry.get()) {
+ for (; !cur->IsBottom(); cur = cur->Parent.get()) {
+ ++depth;
+ }
}
return depth;
}
+bool cmListFileBacktrace::Empty() const
+{
+ return !this->TopEntry || this->TopEntry->IsBottom();
+}
+
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{
os << lfc.FilePath;
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <memory> // IWYU pragma: keep
#include <stddef.h>
#include <string>
#include <vector>
// Default-constructed backtrace may not be used until after
// set via assignment from a backtrace constructed with a
// valid snapshot.
- cmListFileBacktrace();
+ cmListFileBacktrace() = default;
// Construct an empty backtrace whose bottom sits in the directory
// indicated by the given valid snapshot.
cmListFileBacktrace(cmStateSnapshot const& snapshot);
- // Backtraces may be copied and assigned as values.
- cmListFileBacktrace(cmListFileBacktrace const& r);
- cmListFileBacktrace& operator=(cmListFileBacktrace const& r);
- ~cmListFileBacktrace();
+ // Backtraces may be copied, moved, and assigned as values.
+ cmListFileBacktrace(cmListFileBacktrace const&) = default;
+ cmListFileBacktrace(cmListFileBacktrace&&) // NOLINT(clang-tidy)
+ noexcept = default;
+ cmListFileBacktrace& operator=(cmListFileBacktrace const&) = default;
+ cmListFileBacktrace& operator=(cmListFileBacktrace&&) // NOLINT(clang-tidy)
+ noexcept = default;
+ ~cmListFileBacktrace() = default;
- cmStateSnapshot GetBottom() const { return this->Bottom; }
+ cmStateSnapshot GetBottom() const;
// Get a backtrace with the given file scope added to the top.
// May not be called until after construction with a valid snapshot.
cmListFileBacktrace Pop() const;
// Get the context at the top of the backtrace.
- // Returns an empty context if the backtrace is empty.
+ // This may be called only if Empty() would return false.
cmListFileContext const& Top() const;
// Print the top of the backtrace.
// Get the number of 'frames' in this backtrace
size_t Depth() const;
+ // Return true if this backtrace is empty.
+ bool Empty() const;
+
private:
struct Entry;
-
- cmStateSnapshot Bottom;
- Entry* Cur;
- cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* up,
+ std::shared_ptr<Entry const> TopEntry;
+ cmListFileBacktrace(std::shared_ptr<Entry const> parent,
cmListFileContext const& lfc);
- cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* cur);
+ cmListFileBacktrace(std::shared_ptr<Entry const> top);
};
struct cmListFile
this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
}
if (!mod_dir.empty()) {
- const char* moddir_flag =
+ std::string modflag =
this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
- std::string modflag = moddir_flag;
modflag += mod_dir;
this->AppendFlags(flags, modflag);
}
file += "/";
file += "CTestTestfile.cmake";
- cmGeneratedFileStream fout(file.c_str());
+ cmGeneratedFileStream fout(file);
fout.SetCopyIfDifferent(true);
fout << "# CMake generated Testfile for " << std::endl
toplevel_install = 1;
}
file += "/cmake_install.cmake";
- cmGeneratedFileStream fout(file.c_str());
+ cmGeneratedFileStream fout(file);
fout.SetCopyIfDifferent(true);
// Write the header.
std::string flagVar = "CMAKE_INCLUDE_FLAG_";
flagVar += lang;
- const char* includeFlag = this->Makefile->GetSafeDefinition(flagVar);
+ std::string const& includeFlag = this->Makefile->GetSafeDefinition(flagVar);
flagVar = "CMAKE_INCLUDE_FLAG_SEP_";
flagVar += lang;
const char* sep = this->Makefile->GetDefinition(flagVar);
cmGeneratorTarget const* target,
const std::string& lang,
const std::string& config,
- bool stripImplicitInclDirs) const
+ bool stripImplicitDirs,
+ bool appendAllImplicitDirs) const
{
- // Need to decide whether to automatically include the source and
- // binary directories at the beginning of the include path.
- bool includeSourceDir = false;
- bool includeBinaryDir = false;
+ // Do not repeat an include path.
+ std::set<std::string> emitted;
// When automatic include directories are requested for a build then
// include the source and binary directories at the beginning of the
// cannot fix this because not all native build tools support
// per-source-file include paths.
if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR")) {
- includeSourceDir = true;
- includeBinaryDir = true;
- }
-
- // Do not repeat an include path.
- std::set<std::string> emitted;
-
- // Store the automatic include paths.
- if (includeBinaryDir) {
- std::string binDir = this->StateSnapshot.GetDirectory().GetCurrentBinary();
- if (emitted.find(binDir) == emitted.end()) {
- dirs.push_back(binDir);
- emitted.insert(binDir);
+ // Current binary directory
+ {
+ std::string binDir =
+ this->StateSnapshot.GetDirectory().GetCurrentBinary();
+ if (emitted.insert(binDir).second) {
+ dirs.push_back(std::move(binDir));
+ }
}
- }
- if (includeSourceDir) {
- std::string srcDir = this->StateSnapshot.GetDirectory().GetCurrentSource();
- if (emitted.find(srcDir) == emitted.end()) {
- dirs.push_back(srcDir);
- emitted.insert(srcDir);
+ // Current source directory
+ {
+ std::string srcDir =
+ this->StateSnapshot.GetDirectory().GetCurrentSource();
+ if (emitted.insert(srcDir).second) {
+ dirs.push_back(std::move(srcDir));
+ }
}
}
return;
}
- std::string rootPath;
- if (const char* sysrootCompile =
- this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
- rootPath = sysrootCompile;
- } else {
- rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
- }
-
+ // Implicit include directories
std::vector<std::string> implicitDirs;
- // Load implicit include directories for this language.
- std::string impDirVar = "CMAKE_";
- impDirVar += lang;
- impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES";
- if (const char* value = this->Makefile->GetDefinition(impDirVar)) {
- std::vector<std::string> impDirVec;
- cmSystemTools::ExpandListArgument(value, impDirVec);
- for (std::string const& i : impDirVec) {
- std::string d = rootPath + i;
- cmSystemTools::ConvertToUnixSlashes(d);
- emitted.insert(std::move(d));
- if (!stripImplicitInclDirs) {
+ {
+ std::string rootPath;
+ if (const char* sysrootCompile =
+ this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
+ rootPath = sysrootCompile;
+ } else {
+ rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+ }
+
+ // Load implicit include directories for this language.
+ std::string key = "CMAKE_";
+ key += lang;
+ key += "_IMPLICIT_INCLUDE_DIRECTORIES";
+ if (const char* value = this->Makefile->GetDefinition(key)) {
+ std::vector<std::string> impDirVec;
+ cmSystemTools::ExpandListArgument(value, impDirVec);
+ for (std::string const& i : impDirVec) {
+ {
+ std::string d = rootPath + i;
+ cmSystemTools::ConvertToUnixSlashes(d);
+ emitted.insert(std::move(d));
+ }
implicitDirs.push_back(i);
}
}
}
// Get the target-specific include directories.
- std::vector<std::string> includes;
-
- includes = target->GetIncludeDirectories(config, lang);
+ std::vector<std::string> userDirs =
+ target->GetIncludeDirectories(config, lang);
// Support putting all the in-project include directories first if
// it is requested by the project.
if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) {
std::string const &topSourceDir = this->GetState()->GetSourceDirectory(),
&topBinaryDir = this->GetState()->GetBinaryDirectory();
- for (std::string const& i : includes) {
+ for (std::string const& i : userDirs) {
// Emit this directory only if it is a subdirectory of the
// top-level source or binary tree.
if (cmSystemTools::ComparePath(i, topSourceDir) ||
}
// Construct the final ordered include directory list.
- for (std::string const& i : includes) {
+ for (std::string const& i : userDirs) {
if (emitted.insert(i).second) {
dirs.push_back(i);
}
this->MoveSystemIncludesToEnd(dirs, config, lang, target);
// 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<std::string>::size_type const before = includes.size();
- cmSystemTools::ExpandListArgument(standardIncludes, includes);
- for (std::vector<std::string>::iterator i = includes.begin() + before;
- i != includes.end(); ++i) {
- cmSystemTools::ConvertToUnixSlashes(*i);
- dirs.push_back(*i);
- }
-
- for (std::string const& i : implicitDirs) {
- if (std::find(includes.begin(), includes.end(), i) != includes.end()) {
- dirs.push_back(i);
+ {
+ std::vector<std::string>::size_type const before = userDirs.size();
+ {
+ std::string key = "CMAKE_";
+ key += lang;
+ key += "_STANDARD_INCLUDE_DIRECTORIES";
+ std::string const value = this->Makefile->GetSafeDefinition(key);
+ cmSystemTools::ExpandListArgument(value, userDirs);
+ }
+ for (std::vector<std::string>::iterator i = userDirs.begin() + before,
+ ie = userDirs.end();
+ i != ie; ++i) {
+ cmSystemTools::ConvertToUnixSlashes(*i);
+ dirs.push_back(*i);
+ }
+ }
+
+ if (!stripImplicitDirs) {
+ // Append only implicit directories that were requested by the user
+ for (std::string const& i : implicitDirs) {
+ if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) {
+ dirs.push_back(i);
+ }
+ }
+ // Append remaining implicit directories on demand
+ if (appendAllImplicitDirs) {
+ for (std::string const& i : implicitDirs) {
+ if (std::find(dirs.begin(), dirs.end(), i) == dirs.end()) {
+ dirs.push_back(i);
+ }
+ }
}
}
}
void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
std::string const& config,
+ std::string const& linkLanguage,
cmGeneratorTarget* target)
{
this->AppendFlags(
std::string name = "STATIC_LIBRARY_FLAGS_" + config;
this->AppendFlags(flags, target->GetProperty(name));
}
+
+ std::vector<std::string> options;
+ target->GetStaticLibraryLinkOptions(options, config, linkLanguage);
+ // STATIC_LIBRARY_OPTIONS are escaped.
+ this->AppendCompileOptions(flags, options);
}
void cmLocalGenerator::GetTargetFlags(
switch (target->GetType()) {
case cmStateEnums::STATIC_LIBRARY:
- this->GetStaticLibraryFlags(linkFlags, buildType, target);
+ this->GetStaticLibraryFlags(linkFlags, buildType, linkLanguage, target);
break;
case cmStateEnums::MODULE_LIBRARY:
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
linkFlags += " ";
}
}
+ std::vector<std::string> opts;
+ target->GetLinkOptions(opts, config, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->AppendCompileOptions(linkFlags, opts);
if (pcli) {
this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
linkFlags += " ";
}
}
+ std::vector<std::string> opts;
+ target->GetLinkOptions(opts, config, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->AppendCompileOptions(linkFlags, opts);
} break;
default:
break;
const std::string& lang,
const std::string& config)
{
- // Only add Mac OS X specific flags on Darwin platforms (OSX and iphone):
+ // Only add macOS specific flags on Darwin platforms (macOS and iOS):
if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) {
std::vector<std::string> archs;
target->GetAppleArchs(config, archs);
std::string option_flag =
"CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION";
- const char* opt =
+ std::string const& opt =
target->Target->GetMakefile()->GetRequiredDefinition(option_flag);
std::vector<std::string> optVec;
cmSystemTools::ExpandListArgument(opt, optVec);
std::string flagsVar = "CMAKE_SHARED_LIBRARY_";
flagsVar += lang;
flagsVar += "_FLAGS";
- const char* flags = this->Makefile->GetSafeDefinition(flagsVar);
+ std::string const& flags = this->Makefile->GetSafeDefinition(flagsVar);
- if (flags && flags != originalFlags) {
+ if (flags != originalFlags) {
switch (this->GetPolicyStatus(cmPolicies::CMP0018)) {
case cmPolicies::WARN: {
std::ostringstream e;
std::string const& lang,
int targetType)
{
- const char* picFlags = nullptr;
+ std::string picFlags;
if (targetType == cmStateEnums::EXECUTABLE) {
std::string flagsVar = "CMAKE_";
flagsVar += "_COMPILE_OPTIONS_PIE";
picFlags = this->Makefile->GetSafeDefinition(flagsVar);
}
- if (!picFlags) {
+ if (picFlags.empty()) {
std::string flagsVar = "CMAKE_";
flagsVar += lang;
flagsVar += "_COMPILE_OPTIONS_PIC";
picFlags = this->Makefile->GetSafeDefinition(flagsVar);
}
- if (picFlags) {
+ if (!picFlags.empty()) {
std::vector<std::string> options;
cmSystemTools::ExpandListArgument(picFlags, options);
for (std::string const& o : options) {
cmsys::RegularExpression r(regex);
for (std::string const& opt : options_vec) {
- if (r.find(opt.c_str())) {
+ if (r.find(opt)) {
this->AppendFlagEscape(options, opt);
}
}
std::string inc = include;
- if (!cmSystemTools::IsOff(inc.c_str())) {
+ if (!cmSystemTools::IsOff(inc)) {
cmSystemTools::ConvertToUnixSlashes(inc);
}
return this->GetCMakeInstance()->GetHomeOutputDirectory();
}
-const char* cmLocalGenerator::GetCurrentBinaryDirectory() const
+std::string const& cmLocalGenerator::GetCurrentBinaryDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentBinary();
}
-const char* cmLocalGenerator::GetCurrentSourceDirectory() const
+std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentSource();
}
return true;
}
- /** Get the include flags for the current makefile and language. */
+ /** @brief Get the include directories for the current makefile and language.
+ * @arg stripImplicitDirs Strip all directories found in
+ * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES from the result.
+ * @arg appendAllImplicitDirs Append all directories found in
+ * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES to the result.
+ */
void GetIncludeDirectories(std::vector<std::string>& dirs,
cmGeneratorTarget const* target,
const std::string& lang = "C",
const std::string& config = "",
- bool stripImplicitInclDirs = true) const;
+ bool stripImplicitDirs = true,
+ bool appendAllImplicitDirs = false) const;
void AddCompileOptions(std::string& flags, cmGeneratorTarget* target,
const std::string& lang, const std::string& config);
void AddCompileDefinitions(std::set<std::string>& defines,
std::string const& GetSourceDirectory() const;
std::string const& GetBinaryDirectory() const;
- const char* GetCurrentBinaryDirectory() const;
- const char* GetCurrentSourceDirectory() const;
+ std::string const& GetCurrentBinaryDirectory() const;
+ std::string const& GetCurrentSourceDirectory() const;
/**
- * Generate a Mac OS X application bundle Info.plist file.
+ * Generate a macOS application bundle Info.plist file.
*/
void GenerateAppleInfoPList(cmGeneratorTarget* target,
const std::string& targetName,
const char* fname);
/**
- * Generate a Mac OS X framework Info.plist file.
+ * Generate a macOS framework Info.plist file.
*/
void GenerateFrameworkInfoPList(cmGeneratorTarget* target,
const std::string& targetName,
/** Fill out the static linker flags for the given target. */
void GetStaticLibraryFlags(std::string& flags, std::string const& config,
+ std::string const& linkLanguage,
cmGeneratorTarget* target);
/** Fill out these strings for the given target. Libraries to link,
return std::string();
}
- // Expand rules in the empty string. It may insert the launcher and
- // perform replacements.
+ // Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
std::string output;
}
vars.Output = output.c_str();
- std::string launcher = property_value;
- launcher += " ";
-
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->CreateRulePlaceholderExpander());
+ std::string launcher = property_value;
rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
if (!launcher.empty()) {
launcher += " ";
// rules may depend on this file itself.
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
cmGeneratedFileStream ruleFileStream(
- ruleFileNameFull.c_str(), false,
- this->GlobalGenerator->GetMakefileEncoding());
+ ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
if (!ruleFileStream) {
return;
}
infoFileName += "/CMakeDirectoryInformation.cmake";
// Open the output file.
- cmGeneratedFileStream infoFileStream(infoFileName.c_str());
+ cmGeneratedFileStream infoFileStream(infoFileName);
if (!infoFileStream) {
return;
}
std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
cmakefileName += "Makefile.cmake";
std::string runRule =
- "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
+ "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
runRule += " --check-build-system ";
runRule +=
this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
// Short-circuit if there is no launcher.
const char* val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
if (val && *val) {
- // Expand rules in the empty string. It may insert the launcher and
- // perform replacements.
+ // Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = target->GetName().c_str();
vars.CMTargetType = cmState::GetTargetTypeName(target->GetType());
vars.Output = output.c_str();
launcher = val;
- launcher += " ";
rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
if (!launcher.empty()) {
launcher += " ";
std::string ruleFileNameFull = dir;
ruleFileNameFull += "/depend.make";
cmGeneratedFileStream ruleFileStream(
- ruleFileNameFull.c_str(), false,
- this->GlobalGenerator->GetMakefileEncoding());
+ ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
ruleFileStream.SetCopyIfDifferent(true);
if (!ruleFileStream) {
return false;
std::string internalRuleFileNameFull = dir;
internalRuleFileNameFull += "/depend.internal";
cmGeneratedFileStream internalRuleFileStream(
- internalRuleFileNameFull.c_str(), false,
+ internalRuleFileNameFull, false,
this->GlobalGenerator->GetMakefileEncoding());
if (!internalRuleFileStream) {
return false;
this->WriteDisclaimer(internalRuleFileStream);
// for each language we need to scan, scan it
- const char* langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
+ std::string const& langStr =
+ mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
std::vector<std::string> langs;
cmSystemTools::ExpandListArgument(langStr, langs);
for (std::string const& lang : langs) {
cmakefileName += "Makefile.cmake";
{
std::string runRule =
- "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
+ "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
runRule += " --check-build-system ";
runRule +=
this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
if (this->GetCurrentBinaryDirectory() != this->GetSourceDirectory()) {
if (!cmSystemTools::MakeDirectory(this->GetCurrentBinaryDirectory())) {
cmSystemTools::Error("Error creating directory ",
- this->GetCurrentBinaryDirectory());
+ this->GetCurrentBinaryDirectory().c_str());
}
}
std::string comment = "Building Custom Rule ";
comment += makefileIn;
std::string args;
- args = "-H";
+ args = "-S";
args += this->GetSourceDirectory();
commandLine.push_back(args);
args = "-B";
std::string baseFlagVar = "CMAKE_";
baseFlagVar += langForClCompile;
baseFlagVar += "_FLAGS";
- flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str());
+ flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
std::string flagVar =
baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
flags += " ";
- flags += this->Makefile->GetRequiredDefinition(flagVar.c_str());
+ flags += this->Makefile->GetRequiredDefinition(flagVar);
}
// set the correct language
if (linkLanguage == "C") {
targetOptions.FixExceptionHandlingDefault();
std::string asmLocation = configName + "/";
targetOptions.AddFlag("AssemblerListingLocation", asmLocation);
- targetOptions.Parse(flags.c_str());
- targetOptions.Parse(defineFlags.c_str());
+ targetOptions.Parse(flags);
+ targetOptions.Parse(defineFlags);
targetOptions.ParseFinish();
if (!langForClCompile.empty()) {
std::vector<std::string> targetDefines;
rootLinkerFlags + "_" + configTypeUpper;
std::string extraLinkOptionsBuildType =
- this->Makefile->GetRequiredDefinition(
- extraLinkOptionsBuildTypeDef.c_str());
+ this->Makefile->GetRequiredDefinition(extraLinkOptionsBuildTypeDef);
return extraLinkOptionsBuildType;
}
extraLinkOptions += " ";
extraLinkOptions += targetLinkFlags;
}
+
+ std::vector<std::string> opts;
+ target->GetLinkOptions(opts, configName,
+ target->GetLinkerLanguage(configName));
+ // LINK_OPTIONS are escaped.
+ this->AppendCompileOptions(extraLinkOptions, opts);
+
Options linkOptions(this, Options::Linker);
if (this->FortranProject) {
linkOptions.AddTable(cmLocalVisualStudio7GeneratorFortranLinkFlagTable);
}
linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable);
- linkOptions.Parse(extraLinkOptions.c_str());
+ linkOptions.Parse(extraLinkOptions);
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
target->GetModuleDefinitionInfo(configName);
if (mdi && !mdi->DefFile.empty()) {
}
}
std::string libflags;
- this->GetStaticLibraryFlags(libflags, configTypeUpper, target);
+ this->GetStaticLibraryFlags(libflags, configTypeUpper,
+ target->GetLinkerLanguage(configName),
+ target);
if (!libflags.empty()) {
fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\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());
+ << this->Makefile->GetSafeDefinition(standardLibsVar);
if (this->FortranProject) {
this->Internal->OutputObjects(fout, target, configName, " ");
}
// 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());
+ << this->Makefile->GetSafeDefinition(standardLibsVar);
if (this->FortranProject) {
this->Internal->OutputObjects(fout, target, configName, " ");
}
}
}
+static std::string cmLocalVisualStudio7GeneratorEscapeForXML(
+ const std::string& s)
+{
+ std::string ret = s;
+ cmSystemTools::ReplaceString(ret, "&", "&");
+ cmSystemTools::ReplaceString(ret, "\"", """);
+ cmSystemTools::ReplaceString(ret, "<", "<");
+ cmSystemTools::ReplaceString(ret, ">", ">");
+ cmSystemTools::ReplaceString(ret, "\n", "
");
+ return ret;
+}
+
+static std::string GetEscapedPropertyIfValueNotNULL(const char* propertyValue)
+{
+ return propertyValue == nullptr
+ ? std::string()
+ : cmLocalVisualStudio7GeneratorEscapeForXML(propertyValue);
+}
+
void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool(
std::ostream& fout, std::string const& config, cmGeneratorTarget* target)
{
if (this->WindowsCEProject) {
- if (const char* dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY")) {
- /* clang-format off */
- fout <<
- "\t\t\t<DeploymentTool\n"
- "\t\t\t\tForceDirty=\"-1\"\n"
- "\t\t\t\tRemoteDirectory=\"" << this->EscapeForXML(dir) << "\"\n"
- "\t\t\t\tRegisterOutput=\"0\"\n"
- "\t\t\t\tAdditionalFiles=\"\"/>\n"
- ;
- /* clang-format on */
+ const char* dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
+ const char* additionalFiles =
+ target->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
+
+ if (dir == nullptr && additionalFiles == nullptr) {
+ return;
+ }
+
+ fout << "\t\t\t<DeploymentTool\n"
+ "\t\t\t\tForceDirty=\"-1\"\n"
+ "\t\t\t\tRemoteDirectory=\""
+ << GetEscapedPropertyIfValueNotNULL(dir)
+ << "\"\n"
+ "\t\t\t\tRegisterOutput=\"0\"\n"
+ "\t\t\t\tAdditionalFiles=\""
+ << GetEscapedPropertyIfValueNotNULL(additionalFiles) << "\"/>\n";
+
+ if (dir != nullptr) {
std::string const exe =
dir + std::string("\\") + target->GetFullName(config);
- /* clang-format off */
- fout <<
- "\t\t\t<DebuggerTool\n"
- "\t\t\t\tRemoteExecutable=\"" << this->EscapeForXML(exe) << "\"\n"
- "\t\t\t\tArguments=\"\"\n"
- "\t\t\t/>\n"
- ;
- /* clang-format on */
+
+ fout << "\t\t\t<DebuggerTool\n"
+ "\t\t\t\tRemoteExecutable=\""
+ << this->EscapeForXML(exe)
+ << "\"\n"
+ "\t\t\t\tArguments=\"\"\n"
+ "\t\t\t/>\n";
}
}
}
lang = sourceLang;
}
- cmGeneratorExpressionInterpreter genexInterpreter(lg, gt, *i,
- gt->GetName(), lang);
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, *i, gt, lang);
bool needfc = false;
if (!objectName.empty()) {
table = cmLocalVisualStudio7GeneratorFortranFlagTable;
}
Options fileOptions(this, tool, table, gg->ExtraFlagTable);
- fileOptions.Parse(fc.CompileFlags.c_str());
+ fileOptions.Parse(fc.CompileFlags);
fileOptions.AddDefines(fc.CompileDefs);
fileOptions.AddDefines(fc.CompileDefsConfig);
// validate source level include directories
<< "</VisualStudioProject>\n";
}
-std::string cmLocalVisualStudio7GeneratorEscapeForXML(const std::string& s)
-{
- std::string ret = s;
- cmSystemTools::ReplaceString(ret, "&", "&");
- cmSystemTools::ReplaceString(ret, "\"", """);
- cmSystemTools::ReplaceString(ret, "<", "<");
- cmSystemTools::ReplaceString(ret, ">", ">");
- cmSystemTools::ReplaceString(ret, "\n", "
");
- return ret;
-}
-
std::string cmLocalVisualStudio7Generator::EscapeForXML(const std::string& s)
{
return cmLocalVisualStudio7GeneratorEscapeForXML(s);
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
+#include <stdio.h>
#include <stdlib.h>
#include <utility>
class cmMessenger;
+cmDirectoryId::cmDirectoryId(std::string s)
+ : String(std::move(s))
+{
+}
+
// default is not to be building executables
cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
cmStateSnapshot const& snapshot)
cmDeleteAll(this->EvaluationFiles);
}
+cmDirectoryId cmMakefile::GetDirectoryId() const
+{
+ // Use the instance pointer value to uniquely identify this directory.
+ // If we ever need to expose this to CMake language code we should
+ // add a read-only property in cmMakefile::GetProperty.
+ char buf[32];
+ sprintf(buf, "<%p>",
+ static_cast<void const*>(this)); // cast avoids format warning
+ return std::string(buf);
+}
+
void cmMakefile::IssueMessage(cmake::MessageType t,
std::string const& text) const
{
.GetCompileDefinitionsEntryBacktraces();
}
+cmStringRange cmMakefile::GetLinkOptionsEntries() const
+{
+ return this->StateSnapshot.GetDirectory().GetLinkOptionsEntries();
+}
+
+cmBacktraceRange cmMakefile::GetLinkOptionsBacktraces() const
+{
+ return this->StateSnapshot.GetDirectory().GetLinkOptionsEntryBacktraces();
+}
+
+cmStringRange cmMakefile::GetLinkDirectoriesEntries() const
+{
+ return this->StateSnapshot.GetDirectory().GetLinkDirectoriesEntries();
+}
+
+cmBacktraceRange cmMakefile::GetLinkDirectoriesBacktraces() const
+{
+ return this->StateSnapshot.GetDirectory()
+ .GetLinkDirectoriesEntryBacktraces();
+}
+
cmListFileBacktrace cmMakefile::GetBacktrace() const
{
return this->Backtrace;
this->AppendProperty("COMPILE_OPTIONS", option.c_str());
}
+void cmMakefile::AddLinkOption(std::string const& option)
+{
+ this->AppendProperty("LINK_OPTIONS", option.c_str());
+}
+
+void cmMakefile::AddLinkDirectory(std::string const& directory, bool before)
+{
+ cmListFileBacktrace lfbt = this->GetBacktrace();
+ if (before) {
+ this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory,
+ lfbt);
+ } else {
+ this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory,
+ lfbt);
+ }
+}
+
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
{
// Create a regular expression to match valid definitions.
// link libraries
this->SetProperty("LINK_LIBRARIES", parent->GetProperty("LINK_LIBRARIES"));
- // link directories
- this->SetProperty("LINK_DIRECTORIES",
- parent->GetProperty("LINK_DIRECTORIES"));
-
// the initial project name
this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName());
}
}
-const char* cmMakefile::GetCurrentSourceDirectory() const
+const std::string& cmMakefile::GetCurrentSourceDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentSource();
}
-const char* cmMakefile::GetCurrentBinaryDirectory() const
+const std::string& cmMakefile::GetCurrentBinaryDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentBinary();
}
cmStateEnums::CacheEntryType type,
bool force)
{
- const char* existingValue = this->GetState()->GetInitializedCacheValue(name);
+ const std::string* existingValue =
+ this->GetState()->GetInitializedCacheValue(name);
// must be outside the following if() to keep it alive long enough
std::string nvalue;
// if this is not a force, then use the value from the cache
// if it is a force, then use the value being passed in
if (!force) {
- value = existingValue;
+ value = existingValue->c_str();
}
if (type == cmStateEnums::PATH || type == cmStateEnums::FILEPATH) {
std::vector<std::string>::size_type cc;
cmSystemTools::ExpandListArgument(nvalue, files);
nvalue.clear();
for (cc = 0; cc < files.size(); cc++) {
- if (!cmSystemTools::IsOff(files[cc].c_str())) {
+ if (!cmSystemTools::IsOff(files[cc])) {
files[cc] = cmSystemTools::CollapseFullPath(files[cc]);
}
if (cc > 0) {
}
this->GetCMakeInstance()->AddCacheEntry(name, nvalue.c_str(), doc, type);
- nvalue = this->GetState()->GetInitializedCacheValue(name);
+ nvalue = *this->GetState()->GetInitializedCacheValue(name);
value = nvalue.c_str();
}
}
return;
default:;
}
- if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) {
- std::vector<std::string> linkDirs;
- cmSystemTools::ExpandListArgument(linkDirsProp, linkDirs);
-
- for (std::string& linkDir : linkDirs) {
- // Sanitize the path the same way the link_directories command does
- // in case projects set the LINK_DIRECTORIES property directly.
- cmSystemTools::ConvertToUnixSlashes(linkDir);
- target.AddLinkDirectory(linkDir);
- }
- }
if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
std::vector<std::string> linkLibs;
cmSystemTools::SameFile(fileName, this->GetHomeOutputDirectory());
}
-const char* cmMakefile::GetRequiredDefinition(const std::string& name) const
+std::string cmMakefile::GetRequiredDefinition(const std::string& name) const
{
const char* ret = this->GetDefinition(name);
if (!ret) {
cmSystemTools::Error("Error required internal CMake variable not "
"set, cmake may not be built correctly.\n",
"Missing variable is:\n", name.c_str());
- return "";
+ return std::string();
}
- return ret;
+ return std::string(ret);
}
bool cmMakefile::IsDefinitionSet(const std::string& name) const
{
- const char* def = this->StateSnapshot.GetDefinition(name);
+ const std::string* def = this->StateSnapshot.GetDefinition(name);
if (!def) {
def = this->GetState()->GetInitializedCacheValue(name);
}
if (cmVariableWatch* vv = this->GetVariableWatch()) {
if (!def) {
vv->VariableAccessed(
- name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, def, this);
+ name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, nullptr, this);
}
}
#endif
return def != nullptr;
}
-const char* cmMakefile::GetDefinition(const std::string& name) const
+const std::string* cmMakefile::GetDef(const std::string& name) const
{
- const char* def = this->StateSnapshot.GetDefinition(name);
+ const std::string* def = this->StateSnapshot.GetDefinition(name);
if (!def) {
def = this->GetState()->GetInitializedCacheValue(name);
}
vv->VariableAccessed(name,
def ? cmVariableWatch::VARIABLE_READ_ACCESS
: cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS,
- def, this);
+ (def ? def->c_str() : nullptr), this);
if (watch_function_executed) {
// A callback was executed and may have caused re-allocation of the
return def;
}
-const char* cmMakefile::GetSafeDefinition(const std::string& def) const
+const char* cmMakefile::GetDefinition(const std::string& name) const
{
- const char* ret = this->GetDefinition(def);
- if (!ret) {
- return "";
+ const std::string* def = GetDef(name);
+ if (!def) {
+ return nullptr;
}
- return ret;
+ return def->c_str();
+}
+
+const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const
+{
+ static std::string const empty;
+ const std::string* def = GetDef(name);
+ if (!def) {
+ return empty;
+ }
+ return *def;
}
std::vector<std::string> cmMakefile::GetDefinitions() const
// Deprecate old policies, especially those that require a lot
// of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0054) {
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0063) {
this->IssueMessage(cmake::DEPRECATION_WARNING,
cmPolicies::GetPolicyDeprecatedWarning(id));
}
class cmTestGenerator;
class cmVariableWatch;
+/** A type-safe wrapper for a string representing a directory id. */
+class cmDirectoryId
+{
+public:
+ cmDirectoryId(std::string s);
+ std::string String;
+};
+
/** \class cmMakefile
* \brief Process the input CMakeLists.txt file.
*
*/
~cmMakefile();
+ cmDirectoryId GetDirectoryId() const;
+
bool ReadListFile(const char* filename);
bool ReadDependentFile(const char* filename, bool noPolicyScope = true);
void RemoveDefineFlag(std::string const& definition);
void AddCompileDefinition(std::string const& definition);
void AddCompileOption(std::string const& option);
+ void AddLinkOption(std::string const& option);
+ void AddLinkDirectory(std::string const& directory, bool before = false);
/** Create a new imported target with the name and type given. */
cmTarget* AddImportedTarget(const std::string& name,
*/
void SetArgcArgv(const std::vector<std::string>& args);
- const char* GetCurrentSourceDirectory() const;
- const char* GetCurrentBinaryDirectory() const;
+ std::string const& GetCurrentSourceDirectory() const;
+ std::string const& GetCurrentBinaryDirectory() const;
//@}
* cache is then queried.
*/
const char* GetDefinition(const std::string&) const;
- const char* GetSafeDefinition(const std::string&) const;
- const char* GetRequiredDefinition(const std::string& name) const;
+ const std::string* GetDef(const std::string&) const;
+ const std::string& GetSafeDefinition(const std::string&) const;
+ std::string GetRequiredDefinition(const std::string& name) const;
bool IsDefinitionSet(const std::string&) const;
/**
* Get the list of all variables in the current space. If argument
cmBacktraceRange GetCompileOptionsBacktraces() const;
cmStringRange GetCompileDefinitionsEntries() const;
cmBacktraceRange GetCompileDefinitionsBacktraces() const;
+ cmStringRange GetLinkOptionsEntries() const;
+ cmBacktraceRange GetLinkOptionsBacktraces() const;
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesBacktraces() const;
std::set<std::string> const& GetSystemIncludeDirectories() const
{
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
-
// Get the language to use for linking this library.
std::string linkLanguage = "CUDA";
std::string const objExt =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+
// Get the name of the device object to generate.
std::string const targetOutputReal =
this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt;
linkLanguage, this->ConfigName);
// Add target-specific linker flags.
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(linkFlags, linkLanguage);
// Construct a list of files associated with this executable that
// may need to be cleaned.
{
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
- if (!this->DeviceLinkObject.empty()) {
- depends.push_back(this->DeviceLinkObject);
- }
-
// Get the name of the executable to generate.
std::string targetName;
std::string targetNameReal;
return;
}
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+ if (!this->DeviceLinkObject.empty()) {
+ depends.push_back(this->DeviceLinkObject);
+ }
+
this->NumberOfProgressActions++;
if (!this->NoRuleMessages) {
cmLocalUnixMakefileGenerator3::EchoProgress progress;
linkLanguage, this->ConfigName);
// Add target-specific linker flags.
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(linkFlags, linkLanguage);
{
std::unique_ptr<cmLinkLineComputer> linkLineComputer(
// clean set just in case.
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(),
- (targetFullPath + ".manifest").c_str()));
+ targetFullPath + ".manifest"));
#endif
if (targetNameReal != targetName) {
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
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);
+ this->WriteDeviceLibraryRules(linkRuleVar, false);
}
std::string linkLanguage =
std::string extraFlags;
this->LocalGenerator->GetStaticLibraryFlags(
- extraFlags, cmSystemTools::UpperCase(this->ConfigName),
+ extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage,
this->GeneratorTarget);
this->WriteLibraryRules(linkRuleVar, extraFlags, false);
}
cuda_lang) != closure->Languages.end());
if (hasCUDA) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink);
+ this->WriteDeviceLibraryRules(linkRuleVar, relink);
}
}
linkRuleVar += "_CREATE_SHARED_LIBRARY";
std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
-
+ this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
cuda_lang) != closure->Languages.end());
if (hasCUDA) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink);
+ this->WriteDeviceLibraryRules(linkRuleVar, relink);
}
}
linkRuleVar += "_CREATE_SHARED_MODULE";
std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
}
void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
- const std::string& linkRuleVar, const std::string& extraFlags, bool relink)
+ const std::string& linkRuleVar, bool relink)
{
#ifdef CMAKE_BUILD_WITH_CMAKE
// TODO: Merge the methods that call this method to avoid
// code duplication.
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
-
// Get the language to use for linking this library.
std::string linkLanguage = "CUDA";
std::string const objExt =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+
// Create set of linking flags.
std::string linkFlags;
- this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
+ this->GetTargetLinkFlags(linkFlags, linkLanguage);
// Get the name of the device object to generate.
std::string const targetOutputReal =
this->WriteTargetDriverRule(targetOutputReal, relink);
#else
static_cast<void>(linkRuleVar);
- static_cast<void>(extraFlags);
static_cast<void>(relink);
#endif
}
// code duplication.
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
- if (!this->DeviceLinkObject.empty()) {
- depends.push_back(this->DeviceLinkObject);
- }
-
// Get the language to use for linking this library.
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
return;
}
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+ if (!this->DeviceLinkObject.empty()) {
+ depends.push_back(this->DeviceLinkObject);
+ }
+
// Create set of linking flags.
std::string linkFlags;
this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(),
- (targetFullPath + ".manifest").c_str()));
+ targetFullPath + ".manifest"));
}
#endif
void WriteSharedLibraryRules(bool relink);
void WriteModuleLibraryRules(bool relink);
- void WriteDeviceLibraryRules(const std::string& linkRule,
- const std::string& extraFlags, bool relink);
+ void WriteDeviceLibraryRules(const std::string& linkRule, bool relink);
void WriteLibraryRules(const std::string& linkRule,
const std::string& extraFlags, bool relink);
// MacOSX Framework support methods
return result;
}
+void cmMakefileTargetGenerator::GetTargetLinkFlags(
+ std::string& flags, const std::string& linkLanguage)
+{
+ this->LocalGenerator->AppendFlags(
+ flags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
+
+ std::string linkFlagsConfig = "LINK_FLAGS_";
+ linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
+ this->LocalGenerator->AppendFlags(
+ flags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+
+ std::vector<std::string> opts;
+ this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->LocalGenerator->AppendCompileOptions(flags, opts);
+}
+
void cmMakefileTargetGenerator::CreateRuleFile()
{
// Create a directory for this target.
// Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself.
this->BuildFileStream =
- new cmGeneratedFileStream(this->BuildFileNameFull.c_str(), false,
+ new cmGeneratedFileStream(this->BuildFileNameFull, false,
this->GlobalGenerator->GetMakefileEncoding());
this->BuildFileStream->SetCopyIfDifferent(true);
if (!this->BuildFileStream) {
this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
output));
}
+ const std::vector<std::string>& byproducts = ccg.GetByproducts();
+ for (std::string const& byproduct : byproducts) {
+ this->CleanFiles.push_back(
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
+ byproduct));
+ }
+ }
+ }
+
+ // Add byproducts from build events to the clean rules
+ if (clean) {
+ std::vector<cmCustomCommand> buildEventCommands =
+ this->GeneratorTarget->GetPreBuildCommands();
+
+ buildEventCommands.insert(
+ buildEventCommands.end(),
+ this->GeneratorTarget->GetPreLinkCommands().begin(),
+ this->GeneratorTarget->GetPreLinkCommands().end());
+ buildEventCommands.insert(
+ buildEventCommands.end(),
+ this->GeneratorTarget->GetPostBuildCommands().begin(),
+ this->GeneratorTarget->GetPostBuildCommands().end());
+
+ for (const auto& be : buildEventCommands) {
+ const std::vector<std::string>& byproducts = be.GetByproducts();
+ for (std::string const& byproduct : byproducts) {
+ this->CleanFiles.push_back(
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
+ byproduct));
+ }
}
}
std::vector<cmSourceFile const*> headerSources;
if (!cmSystemTools::FileExists(dependFileNameFull)) {
// Write an empty dependency file.
cmGeneratedFileStream depFileStream(
- dependFileNameFull.c_str(), false,
- this->GlobalGenerator->GetMakefileEncoding());
+ dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
depFileStream << "# Empty dependencies file for "
<< this->GeneratorTarget->GetName() << ".\n"
<< "# This may be replaced when dependencies are built."
this->FlagFileNameFull = this->TargetBuildDirectoryFull;
this->FlagFileNameFull += "/flags.make";
this->FlagFileStream =
- new cmGeneratedFileStream(this->FlagFileNameFull.c_str(), false,
+ new cmGeneratedFileStream(this->FlagFileNameFull, false,
this->GlobalGenerator->GetMakefileEncoding());
this->FlagFileStream->SetCopyIfDifferent(true);
if (!this->FlagFileStream) {
std::string config = this->LocalGenerator->GetConfigName();
std::string configUpper = cmSystemTools::UpperCase(config);
cmGeneratorExpressionInterpreter genexInterpreter(
- this->LocalGenerator, this->GeneratorTarget, config,
- this->GeneratorTarget->GetName(), lang);
+ this->LocalGenerator, config, this->GeneratorTarget, lang);
// Add Fortran format flags.
if (lang == "Fortran") {
// Add flags from source file properties.
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source.GetProperty(COMPILE_FLAGS)) {
- const char* evaluatedFlags =
+ const std::string& evaluatedFlags =
genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
*this->FlagFileStream << "# Custom flags: " << relativeObj
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = source.GetProperty(COMPILE_OPTIONS)) {
- const char* evaluatedOptions =
+ const std::string& evaluatedOptions =
genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS);
this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions);
*this->FlagFileStream << "# Custom options: " << relativeObj
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
- const char* evaluatedIncludes =
+ const std::string& evaluatedIncludes =
genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
this->LocalGenerator->AppendIncludeDirectories(includes, evaluatedIncludes,
source);
// Add source-specific preprocessor definitions.
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
if (const char* compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) {
- const char* evaluatedDefs =
+ const std::string& evaluatedDefs =
genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS);
this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
*this->FlagFileStream << "# Custom defines: " << relativeObj
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
if (const char* config_compile_defs = source.GetProperty(defPropName)) {
- const char* evaluatedDefs =
+ const std::string& evaluatedDefs =
genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS);
this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
*this->FlagFileStream << "# Custom defines: " << relativeObj << "_DEFINES_"
this->InfoFileNameFull += "/DependInfo.cmake";
this->InfoFileNameFull =
this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
- this->InfoFileStream =
- new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
+ this->InfoFileStream = new cmGeneratedFileStream(this->InfoFileNameFull);
this->InfoFileStream->SetCopyIfDifferent(true);
if (!*this->InfoFileStream) {
return;
}
void cmMakefileTargetGenerator::AppendLinkDepends(
- std::vector<std::string>& depends)
+ std::vector<std::string>& depends, const std::string& linkLanguage)
{
this->AppendObjectDepends(depends);
}
// Add user-specified dependencies.
- if (const char* linkDepends =
- this->GeneratorTarget->GetProperty("LINK_DEPENDS")) {
- cmSystemTools::ExpandListArgument(linkDepends, depends);
- }
+ this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName,
+ linkLanguage);
}
std::string cmMakefileTargetGenerator::GetLinkRule(
std::string linkScriptName = this->TargetBuildDirectoryFull;
linkScriptName += "/";
linkScriptName += name;
- cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
+ cmGeneratedFileStream linkScriptStream(linkScriptName);
linkScriptStream.SetCopyIfDifferent(true);
for (std::string const& link_command : link_commands) {
// Do not write out empty commands or commands beginning in the
std::string responseFileNameFull = this->TargetBuildDirectoryFull;
responseFileNameFull += "/";
responseFileNameFull += name;
- cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
+ cmGeneratedFileStream responseStream(responseFileNameFull);
responseStream.SetCopyIfDifferent(true);
responseStream << options << "\n";
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());
+ cmGeneratedFileStream fout(objlist_file);
if (mdi->WindowsExportAllSymbols) {
for (std::string const& obj : this->Objects) {
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
protected:
+ void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage);
+
// create the file and directory etc
void CreateRuleFile();
// write the depend rules for this target
void WriteTargetDependRules();
- // write rules for Mac OS X Application Bundle content.
+ // write rules for macOS Application Bundle content.
struct MacOSXContentGeneratorType
: cmOSXBundleGenerator::MacOSXContentGeneratorType
{
void AppendObjectDepends(std::vector<std::string>& depends);
// Append link rule dependencies (objects, etc.).
- void AppendLinkDepends(std::vector<std::string>& depends);
+ void AppendLinkDepends(std::vector<std::string>& depends,
+ const std::string& linkLanguage);
// Lookup the link rule for this target.
std::string GetLinkRule(const std::string& linkRuleVar);
std::string TargetNameImport;
std::string TargetNamePDB;
- // Mac OS X content info.
+ // macOS content info.
std::set<std::string> MacContentFolders;
cmOSXBundleGenerator* OSXBundleGenerator;
MacOSXContentGeneratorType* MacOSXContentGenerator;
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMathCommand.h"
-#include <stdio.h>
-
#include "cmExprParserHelper.h"
#include "cmMakefile.h"
+#include "cm_kwiml.h"
+#include "cmake.h"
+
+#include <stdio.h>
class cmExecutionStatus;
bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args)
{
- if (args.size() != 3) {
+ if ((args.size() != 3) && (args.size() != 5)) {
this->SetError("EXPR called with incorrect arguments.");
return false;
}
+ enum class NumericFormat
+ {
+ UNINITIALIZED,
+ DECIMAL,
+ HEXADECIMAL,
+ };
+
const std::string& outputVariable = args[1];
const std::string& expression = args[2];
+ size_t argumentIndex = 3;
+ NumericFormat outputFormat = NumericFormat::UNINITIALIZED;
+
+ this->Makefile->AddDefinition(outputVariable, "ERROR");
+
+ if (argumentIndex < args.size()) {
+ const std::string messageHint = "sub-command EXPR ";
+ const std::string option = args[argumentIndex++];
+ if (option == "OUTPUT_FORMAT") {
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "DECIMAL") {
+ outputFormat = NumericFormat::DECIMAL;
+ } else if (argument == "HEXADECIMAL") {
+ outputFormat = NumericFormat::HEXADECIMAL;
+ } else {
+ std::string error = messageHint + "value \"" + argument +
+ "\" for option \"" + option + "\" is invalid.";
+ this->SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "missing argument for option \"" + option + "\".";
+ this->SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "option \"" + option + "\" is unknown.";
+ this->SetError(error);
+ return false;
+ }
+ }
+
+ if (outputFormat == NumericFormat::UNINITIALIZED) {
+ outputFormat = NumericFormat::DECIMAL;
+ }
cmExprParserHelper helper;
if (!helper.ParseString(expression.c_str(), 0)) {
- std::string e = "cannot parse the expression: \"" + expression + "\": ";
- e += helper.GetError();
- this->SetError(e);
+ this->SetError(helper.GetError());
return false;
}
char buffer[1024];
- sprintf(buffer, "%d", helper.GetResult());
+ const char* fmt;
+ switch (outputFormat) {
+ case NumericFormat::HEXADECIMAL:
+ fmt = "0x%" KWIML_INT_PRIx64;
+ break;
+ case NumericFormat::DECIMAL:
+ CM_FALLTHROUGH;
+ default:
+ fmt = "%" KWIML_INT_PRId64;
+ break;
+ }
+ sprintf(buffer, fmt, helper.GetResult());
+
+ std::string const& w = helper.GetWarning();
+ if (!w.empty()) {
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w);
+ }
this->Makefile->AddDefinition(outputVariable, buffer);
return true;
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
- const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
+ std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar);
cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
}
{
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
- const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
+ std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar);
cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
}
return linkCmds;
outputs.push_back(targetOutputReal);
// Compute specific libraries to link with.
cmNinjaDeps explicitDeps = this->GetObjects();
- cmNinjaDeps implicitDeps = this->ComputeLinkDeps();
+ cmNinjaDeps implicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage);
std::string frameworkPath;
std::string linkPath;
// Compute specific libraries to link with.
cmNinjaDeps explicitDeps = this->GetObjects();
- cmNinjaDeps implicitDeps = this->ComputeLinkDeps();
+ cmNinjaDeps implicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage);
if (!this->DeviceLinkObject.empty()) {
explicitDeps.push_back(this->DeviceLinkObject);
preLinkCmdLines.push_back(std::move(cmd));
// create a list of obj files for the -E __create_def to read
- cmGeneratedFileStream fout(obj_list_file.c_str());
+ cmGeneratedFileStream fout(obj_list_file);
if (mdi->WindowsExportAllSymbols) {
cmNinjaDeps objs = this->GetObjects();
#include <map>
#include <memory> // IWYU pragma: keep
#include <sstream>
-#include <string.h>
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(
- this->LocalGenerator, this->GeneratorTarget,
- this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(),
- language);
+ this->LocalGenerator, this->LocalGenerator->GetConfigName(),
+ this->GeneratorTarget, language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const
{
- return strcmp(this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" +
- lang),
- "msvc") == 0;
+ return (this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" +
+ lang) == "msvc");
}
// TODO: Refactor with
std::set<std::string> defines;
const std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpressionInterpreter genexInterpreter(
- this->LocalGenerator, this->GeneratorTarget, config,
- this->GeneratorTarget->GetName(), language);
+ this->LocalGenerator, config, this->GeneratorTarget, language);
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
std::vector<std::string> includes;
const std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpressionInterpreter genexInterpreter(
- this->LocalGenerator, this->GeneratorTarget, config,
- this->GeneratorTarget->GetName(), language);
+ this->LocalGenerator, config, this->GeneratorTarget, language);
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
return includesString;
}
-cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
+cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps(
+ const std::string& linkLanguage) const
{
// Static libraries never depend on other targets for linking.
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
}
// Add user-specified dependencies.
- if (const char* linkDepends =
- this->GeneratorTarget->GetProperty("LINK_DEPENDS")) {
- std::vector<std::string> linkDeps;
- cmSystemTools::ExpandListArgument(linkDepends, linkDeps);
- std::transform(linkDeps.begin(), linkDeps.end(),
- std::back_inserter(result), MapToNinjaPath());
- }
+ std::vector<std::string> linkDeps;
+ this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName,
+ linkLanguage);
+ std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result),
+ MapToNinjaPath());
return result;
}
}
std::string const tdin = this->GetTargetDependInfoPath(lang);
- cmGeneratedFileStream tdif(tdin.c_str());
+ cmGeneratedFileStream tdif(tdin);
tdif << tdi;
}
}
/// @return the list of link dependency for the given target @a target.
- cmNinjaDeps ComputeLinkDeps() const;
+ cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const;
/// @return the source file path for the given @a source.
std::string GetSourceFilePath(cmSourceFile const* source) const;
void EnsureDirectoryExists(const std::string& dir) const;
void EnsureParentDirectoryExists(const std::string& path) const;
- // write rules for Mac OS X Application Bundle content.
+ // write rules for macOS Application Bundle content.
struct MacOSXContentGeneratorType
: cmOSXBundleGenerator::MacOSXContentGeneratorType
{
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmOptionCommand.h"
+#include <sstream>
+
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmState.h"
+#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
+#include "cmake.h"
class cmExecutionStatus;
bool cmOptionCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
- bool argError = false;
- if (args.size() < 2) {
- argError = true;
- }
- // for VTK 4.0 we have to support the option command with more than 3
- // arguments if CMAKE_MINIMUM_REQUIRED_VERSION is not defined, if
- // CMAKE_MINIMUM_REQUIRED_VERSION is defined, then we can have stricter
- // checking.
- if (this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
- if (args.size() > 3) {
- argError = true;
- }
- }
+ const bool argError = (args.size() < 2) || (args.size() > 3);
if (argError) {
std::string m = "called with incorrect number of arguments: ";
m += cmJoin(args, " ");
return false;
}
- std::string initialValue = "Off";
- // Now check and see if the value has been stored in the cache
- // already, if so use that value and don't look for the program
+ // Determine the state of the option policy
+ bool checkAndWarn = false;
+ {
+ auto status = this->Makefile->GetPolicyStatus(cmPolicies::CMP0077);
+ const auto* existsBeforeSet =
+ this->Makefile->GetStateSnapshot().GetDefinition(args[0]);
+ switch (status) {
+ case cmPolicies::WARN:
+ checkAndWarn = (existsBeforeSet != nullptr);
+ break;
+ case cmPolicies::OLD:
+ // OLD behavior does not warn.
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW: {
+ // See if a local variable with this name already exists.
+ // If so we ignore the option command.
+ if (existsBeforeSet) {
+ return true;
+ }
+ } break;
+ }
+ }
+
+ // See if a cache variable with this name already exists
+ // If so just make sure the doc state is correct
cmState* state = this->Makefile->GetState();
const char* existingValue = state->GetCacheEntryValue(args[0]);
- if (existingValue) {
- if (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED) {
- state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
- return true;
- }
- initialValue = existingValue;
+ if (existingValue &&
+ (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) {
+ state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
+ return true;
}
+
+ // Nothing in the cache so add it
+ std::string initialValue = existingValue ? existingValue : "Off";
if (args.size() == 3) {
initialValue = args[2];
}
- bool init = cmSystemTools::IsOn(initialValue.c_str());
+ bool init = cmSystemTools::IsOn(initialValue);
this->Makefile->AddCacheDefinition(args[0], init ? "ON" : "OFF",
args[1].c_str(), cmStateEnums::BOOL);
+
+ if (checkAndWarn) {
+ const auto* existsAfterSet =
+ this->Makefile->GetStateSnapshot().GetDefinition(args[0]);
+ if (!existsAfterSet) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0077)
+ << "\n"
+ "For compatibility with older versions of CMake, option "
+ "is clearing the normal variable '"
+ << args[0] << "'.";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+ }
return true;
}
std::string const& remote_path,
cmStateDirectory const& directory)
{
- const std::string relativePathTopBinary =
+ const std::string& relativePathTopBinary =
directory.GetRelativePathTopBinary();
- const std::string relativePathTopSource =
+ const std::string& relativePathTopSource =
directory.GetRelativePathTopSource();
const bool bothInBinary =
if (!found) {
// Couldn't find any dependency information.
- if (this->ComplainFileRegularExpression.find(
- info->IncludeName.c_str())) {
+ if (this->ComplainFileRegularExpression.find(info->IncludeName)) {
cmSystemTools::Error("error cannot find dependencies for ", path);
} else {
// Destroy the name of the file so that it won't be output as a
cmPolicies::PolicyStatus* defaultSetting)
{
std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy;
- std::string defaultValue = mf->GetSafeDefinition(defaultVar);
+ std::string const& defaultValue = mf->GetSafeDefinition(defaultVar);
if (defaultValue == "NEW") {
*defaultSetting = cmPolicies::NEW;
} else if (defaultValue == "OLD") {
3, 12, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0075, \
"Include file check macros honor CMAKE_REQUIRED_LIBRARIES.", 3, 12, \
- 0, cmPolicies::WARN)
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0076, \
+ "target_sources() command converts relative paths to absolute.", 3, \
+ 13, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0077, "option() honors normal variables.", 3, 13, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0078, "UseSWIG generates standard target names.", 3, 13, \
+ 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0079, \
+ "target_link_libraries allows use with targets in other directories.", 3, \
+ 13, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0080, \
+ "BundleUtilities cannot be included at configure time", 3, 13, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0081, \
+ "Relative paths not allowed in LINK_DIRECTORIES target property.", \
+ 3, 13, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
F(CMP0065) \
F(CMP0068) \
F(CMP0069) \
- F(CMP0073)
+ F(CMP0073) \
+ F(CMP0076) \
+ F(CMP0081)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
srcdir += "_SOURCE_DIR";
this->Makefile->AddCacheDefinition(
- bindir, this->Makefile->GetCurrentBinaryDirectory(),
+ bindir, this->Makefile->GetCurrentBinaryDirectory().c_str(),
"Value Computed by CMake", cmStateEnums::STATIC);
this->Makefile->AddCacheDefinition(
- srcdir, this->Makefile->GetCurrentSourceDirectory(),
+ srcdir, this->Makefile->GetCurrentSourceDirectory().c_str(),
"Value Computed by CMake", cmStateEnums::STATIC);
bindir = "PROJECT_BINARY_DIR";
srcdir = "PROJECT_SOURCE_DIR";
- this->Makefile->AddDefinition(bindir,
- this->Makefile->GetCurrentBinaryDirectory());
- this->Makefile->AddDefinition(srcdir,
- this->Makefile->GetCurrentSourceDirectory());
+ this->Makefile->AddDefinition(
+ bindir, this->Makefile->GetCurrentBinaryDirectory().c_str());
+ this->Makefile->AddDefinition(
+ srcdir, this->Makefile->GetCurrentSourceDirectory().c_str());
this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str());
}
}
- if (haveDescription) {
- this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
- this->Makefile->AddDefinition(projectName + "_DESCRIPTION",
- description.c_str());
- TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str());
- }
+ this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
+ this->Makefile->AddDefinition(projectName + "_DESCRIPTION",
+ description.c_str());
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str());
- if (haveHomepage) {
- this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str());
- this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL",
- homepage.c_str());
- TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str());
- }
+ this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str());
+ this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL",
+ homepage.c_str());
+ TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str());
if (languages.empty()) {
// if no language is specified do c and c++
}
// Get the moc executable to run in the custom command.
- const char* moc_exe =
+ std::string const& moc_exe =
this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE");
// Get the variable holding the list of sources.
}
// Get the uic and moc executables to run in the custom commands.
- const char* uic_exe =
+ std::string const& uic_exe =
this->Makefile->GetRequiredDefinition("QT_UIC_EXECUTABLE");
- const char* moc_exe =
+ std::string const& moc_exe =
this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE");
// Get the variable holding the list of sources.
RCC
};
+ /// @brief Integer version
+ struct IntegerVersion
+ {
+ unsigned int Major = 0;
+ unsigned int Minor = 0;
+
+ IntegerVersion() = default;
+ IntegerVersion(unsigned int major, unsigned int minor)
+ : Major(major)
+ , Minor(minor)
+ {
+ }
+
+ bool operator>(IntegerVersion const version)
+ {
+ return (this->Major > version.Major) ||
+ ((this->Major == version.Major) && (this->Minor > version.Minor));
+ }
+
+ bool operator>=(IntegerVersion const version)
+ {
+ return (this->Major > version.Major) ||
+ ((this->Major == version.Major) && (this->Minor >= version.Minor));
+ }
+ };
+
public:
/// @brief Returns the generator name
static std::string const& GeneratorName(GeneratorT genType);
#include <utility>
#include <vector>
-inline static const char* SafeString(const char* value)
-{
- return (value != nullptr) ? value : "";
-}
-
-inline static std::string GetSafeProperty(cmGeneratorTarget const* target,
- const char* key)
-{
- return std::string(SafeString(target->GetProperty(key)));
-}
-
-inline static std::string GetSafeProperty(cmSourceFile const* sf,
- const char* key)
-{
- return std::string(SafeString(sf->GetProperty(key)));
-}
-
static std::size_t GetParallelCPUCount()
{
static std::size_t count = 0;
return cycle;
}
-cmQtAutoGenInitializer::cmQtAutoGenInitializer(
- cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
- std::string const& qtVersionMajor)
+cmQtAutoGenInitializer::cmQtAutoGenInitializer(cmGeneratorTarget* target,
+ bool mocEnabled,
+ bool uicEnabled,
+ bool rccEnabled,
+ IntegerVersion const& qtVersion)
: Target(target)
- , MocEnabled(mocEnabled)
- , UicEnabled(uicEnabled)
- , RccEnabled(rccEnabled)
- , MultiConfig(false)
- , QtVersionMajor(qtVersionMajor)
+ , QtVersion(qtVersion)
{
- this->QtVersionMinor =
- cmQtAutoGenInitializer::GetQtMinorVersion(target, this->QtVersionMajor);
+ Moc.Enabled = mocEnabled;
+ Uic.Enabled = uicEnabled;
+ Rcc.Enabled = rccEnabled;
}
-void cmQtAutoGenInitializer::InitCustomTargets()
+bool cmQtAutoGenInitializer::InitCustomTargets()
{
cmMakefile* makefile = this->Target->Target->GetMakefile();
cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
this->ConfigsList.push_back(this->ConfigDefault);
}
- // Autogen target name
- this->AutogenTargetName = this->Target->GetName();
- this->AutogenTargetName += "_autogen";
-
- // Autogen directories
- {
- // Collapsed current binary directory
- std::string const cbd = cmSystemTools::CollapseFullPath(
- "", makefile->GetCurrentBinaryDirectory());
-
- // Autogen info dir
- this->DirInfo = cbd;
- this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
- this->DirInfo += '/';
- this->DirInfo += this->AutogenTargetName;
- this->DirInfo += ".dir";
- cmSystemTools::ConvertToUnixSlashes(this->DirInfo);
-
- // Autogen build dir
- this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR");
- if (this->DirBuild.empty()) {
- this->DirBuild = cbd;
- this->DirBuild += '/';
- this->DirBuild += this->AutogenTargetName;
+ // Verbosity
+ this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
+ if (!this->Verbosity.empty()) {
+ unsigned long iVerb = 0;
+ if (!cmSystemTools::StringToULong(this->Verbosity.c_str(), &iVerb)) {
+ // Non numeric verbosity
+ this->Verbosity = cmSystemTools::IsOn(this->Verbosity) ? "1" : "0";
}
- cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
-
- // Working directory
- this->DirWork = cbd;
- cmSystemTools::ConvertToUnixSlashes(this->DirWork);
- }
-
- // Autogen files
- {
- this->AutogenInfoFile = this->DirInfo;
- this->AutogenInfoFile += "/AutogenInfo.cmake";
-
- this->AutogenSettingsFile = this->DirInfo;
- this->AutogenSettingsFile += "/AutogenOldSettings.txt";
}
- // Autogen target FOLDER property
+ // Targets FOLDER
{
const char* folder =
makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
}
// Inherit FOLDER property from target (#13688)
if (folder == nullptr) {
- folder = SafeString(this->Target->Target->GetProperty("FOLDER"));
+ folder = this->Target->GetProperty("FOLDER");
}
if (folder != nullptr) {
- this->AutogenFolder = folder;
+ this->TargetsFolder = folder;
}
}
- std::set<std::string> autogenDependFiles;
- std::set<cmTarget*> autogenDependTargets;
- std::vector<std::string> autogenProvides;
-
- // Remove build directories on cleanup
- AddCleanFile(makefile, this->DirBuild);
- // Remove old settings on cleanup
+ // Common directories
{
- std::string base = this->DirInfo;
- base += "/AutogenOldSettings";
+ // Collapsed current binary directory
+ std::string const cbd = cmSystemTools::CollapseFullPath(
+ std::string(), makefile->GetCurrentBinaryDirectory());
+
+ // Info directory
+ this->Dir.Info = cbd;
+ this->Dir.Info += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
+ this->Dir.Info += '/';
+ this->Dir.Info += this->Target->GetName();
+ this->Dir.Info += "_autogen";
+ this->Dir.Info += ".dir";
+ cmSystemTools::ConvertToUnixSlashes(this->Dir.Info);
+
+ // Build directory
+ this->Dir.Build = this->Target->GetSafeProperty("AUTOGEN_BUILD_DIR");
+ if (this->Dir.Build.empty()) {
+ this->Dir.Build = cbd;
+ this->Dir.Build += '/';
+ this->Dir.Build += this->Target->GetName();
+ this->Dir.Build += "_autogen";
+ }
+ cmSystemTools::ConvertToUnixSlashes(this->Dir.Build);
+ // Cleanup build directory
+ AddCleanFile(makefile, this->Dir.Build);
+
+ // Working directory
+ this->Dir.Work = cbd;
+ cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
+
+ // Include directory
+ this->Dir.Include = this->Dir.Build;
+ this->Dir.Include += "/include";
+ if (this->MultiConfig) {
+ this->Dir.Include += "_$<CONFIG>";
+ }
+ // Per config include directories
if (this->MultiConfig) {
for (std::string const& cfg : this->ConfigsList) {
- std::string filename = base;
- filename += '_';
- filename += cfg;
- filename += ".cmake";
- AddCleanFile(makefile, filename);
+ std::string& dir = this->Dir.ConfigInclude[cfg];
+ dir = this->Dir.Build;
+ dir += "/include_";
+ dir += cfg;
+ }
+ }
+ }
+
+ // Moc, Uic and _autogen target settings
+ if (this->Moc.Enabled || this->Uic.Enabled) {
+ // Init moc specific settings
+ if (this->Moc.Enabled && !InitMoc()) {
+ return false;
+ }
+
+ // Init uic specific settings
+ if (this->Uic.Enabled && !InitUic()) {
+ return false;
+ }
+
+ // Autogen target name
+ this->AutogenTarget.Name = this->Target->GetName();
+ this->AutogenTarget.Name += "_autogen";
+
+ // Autogen target parallel processing
+ this->AutogenTarget.Parallel =
+ this->Target->GetSafeProperty("AUTOGEN_PARALLEL");
+ if (this->AutogenTarget.Parallel.empty() ||
+ (this->AutogenTarget.Parallel == "AUTO")) {
+ // Autodetect number of CPUs
+ this->AutogenTarget.Parallel = std::to_string(GetParallelCPUCount());
+ }
+
+ // Autogen target info and settings files
+ {
+ this->AutogenTarget.InfoFile = this->Dir.Info;
+ this->AutogenTarget.InfoFile += "/AutogenInfo.cmake";
+
+ this->AutogenTarget.SettingsFile = this->Dir.Info;
+ this->AutogenTarget.SettingsFile += "/AutogenOldSettings.txt";
+
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string& filename = this->AutogenTarget.ConfigSettingsFile[cfg];
+ filename =
+ AppendFilenameSuffix(this->AutogenTarget.SettingsFile, "_" + cfg);
+ AddCleanFile(makefile, filename);
+ }
+ } else {
+ AddCleanFile(makefile, this->AutogenTarget.SettingsFile);
+ }
+ }
+
+ // Autogen target: Compute user defined dependencies
+ {
+ std::string const deps =
+ this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
+ if (!deps.empty()) {
+ std::vector<std::string> extraDeps;
+ cmSystemTools::ExpandListArgument(deps, extraDeps);
+ for (std::string const& depName : extraDeps) {
+ // Allow target and file dependencies
+ auto* depTarget = makefile->FindTargetToUse(depName);
+ if (depTarget != nullptr) {
+ this->AutogenTarget.DependTargets.insert(depTarget);
+ } else {
+ this->AutogenTarget.DependFiles.insert(depName);
+ }
+ }
}
- } else {
- AddCleanFile(makefile, base.append(".cmake"));
}
}
- // Add moc compilation to generated files list
- if (this->MocEnabled) {
- std::string mocsComp = this->DirBuild + "/mocs_compilation.cpp";
- this->AddGeneratedSource(mocsComp, GeneratorT::MOC);
- autogenProvides.push_back(std::move(mocsComp));
+ // Init rcc specific settings
+ if (this->Rcc.Enabled && !InitRcc()) {
+ return false;
+ }
+
+ // Add autogen include directory to the origin target INCLUDE_DIRECTORIES
+ if (this->Moc.Enabled || this->Uic.Enabled ||
+ (this->Rcc.Enabled && this->MultiConfig)) {
+ this->Target->AddIncludeDirectory(this->Dir.Include, true);
+ }
+
+ // Scan files
+ if (!this->InitScanFiles()) {
+ return false;
+ }
+
+ // Create autogen target
+ if ((this->Moc.Enabled || this->Uic.Enabled) && !this->InitAutogenTarget()) {
+ return false;
+ }
+
+ // Create rcc targets
+ if (this->Rcc.Enabled && !this->InitRccTargets()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitMoc()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+
+ // Mocs compilation file
+ this->Moc.MocsCompilation = this->Dir.Build;
+ this->Moc.MocsCompilation += "/mocs_compilation.cpp";
+
+ // Moc predefs command
+ if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
+ (this->QtVersion >= IntegerVersion(5, 8))) {
+ this->Moc.PredefsCmd =
+ makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
}
- // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
- if (this->MocEnabled || this->UicEnabled ||
- (this->RccEnabled && this->MultiConfig)) {
- std::string includeDir = this->DirBuild;
- includeDir += "/include";
+ // Moc includes
+ {
+ bool const appendImplicit = (this->QtVersion.Major == 5);
+ auto GetIncludeDirs =
+ [this, localGen, appendImplicit](std::string const& cfg) -> std::string {
+ // Get the include dirs for this target, without stripping the implicit
+ // include dirs off, see
+ // https://gitlab.kitware.com/cmake/cmake/issues/13667
+ std::vector<std::string> dirs;
+ localGen->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false,
+ appendImplicit);
+ return cmJoin(dirs, ";");
+ };
+
+ // Default configuration include directories
+ this->Moc.Includes = GetIncludeDirs(this->ConfigDefault);
+ // Other configuration settings
if (this->MultiConfig) {
- includeDir += "_$<CONFIG>";
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string dirs = GetIncludeDirs(cfg);
+ if (dirs != this->Moc.Includes) {
+ this->Moc.ConfigIncludes[cfg] = std::move(dirs);
+ }
+ }
}
- this->Target->AddIncludeDirectory(includeDir, true);
}
- // Acquire rcc executable and features
- if (this->RccEnabled) {
- {
- std::string err;
- if (this->QtVersionMajor == "5") {
- cmGeneratorTarget* tgt =
- localGen->FindGeneratorTargetToUse("Qt5::rcc");
- if (tgt != nullptr) {
- this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTORCC: Qt5::rcc target not found";
- }
- } else if (QtVersionMajor == "4") {
- cmGeneratorTarget* tgt =
- localGen->FindGeneratorTargetToUse("Qt4::rcc");
- if (tgt != nullptr) {
- this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTORCC: Qt4::rcc target not found";
+ // Moc compile definitions
+ {
+ auto GetCompileDefinitions =
+ [this, localGen](std::string const& cfg) -> std::string {
+ std::set<std::string> defines;
+ localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
+ return cmJoin(defines, ";");
+ };
+
+ // Default configuration defines
+ this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault);
+ // Other configuration defines
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string defines = GetCompileDefinitions(cfg);
+ if (defines != this->Moc.Defines) {
+ this->Moc.ConfigDefines[cfg] = std::move(defines);
}
- } else {
- err = "The AUTORCC feature supports only Qt 4 and Qt 5";
}
- if (!err.empty()) {
- err += " (";
- err += this->Target->GetName();
- err += ")";
- cmSystemTools::Error(err.c_str());
+ }
+ }
+
+ // Moc executable
+ if (!GetMocExecutable()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitUic()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ // Uic search paths
+ {
+ std::string const usp =
+ this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS");
+ if (!usp.empty()) {
+ cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths);
+ std::string const& srcDir = makefile->GetCurrentSourceDirectory();
+ for (std::string& path : this->Uic.SearchPaths) {
+ path = cmSystemTools::CollapseFullPath(path, srcDir);
+ }
+ }
+ }
+ // Uic target options
+ {
+ auto UicGetOpts = [this](std::string const& cfg) -> std::string {
+ std::vector<std::string> opts;
+ this->Target->GetAutoUicOptions(opts, cfg);
+ return cmJoin(opts, ";");
+ };
+
+ // Default settings
+ this->Uic.Options = UicGetOpts(this->ConfigDefault);
+
+ // Configuration specific settings
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string options = UicGetOpts(cfg);
+ if (options != this->Uic.Options) {
+ this->Uic.ConfigOptions[cfg] = std::move(options);
+ }
}
}
- // Detect if rcc supports (-)-list
- if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) {
- std::vector<std::string> command;
- command.push_back(this->RccExecutable);
- command.push_back("--help");
- std::string rccStdOut;
- std::string rccStdErr;
- int retVal = 0;
- bool result = cmSystemTools::RunSingleCommand(
- command, &rccStdOut, &rccStdErr, &retVal, nullptr,
- cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
- if (result && retVal == 0 &&
- rccStdOut.find("--list") != std::string::npos) {
- this->RccListOptions.push_back("--list");
- } else {
- this->RccListOptions.push_back("-list");
+ }
+ // .ui files skip and options
+ {
+ std::string const uiExt = "ui";
+ std::string pathError;
+ for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+ // sf->GetExtension() is only valid after sf->GetFullPath() ...
+ // Since we're iterating over source files that might be not in the
+ // target we need to check for path errors (not existing files).
+ std::string const& fPath = sf->GetFullPath(&pathError);
+ if (!pathError.empty()) {
+ pathError.clear();
+ continue;
+ }
+ if (sf->GetExtension() == uiExt) {
+ std::string const absFile = cmSystemTools::GetRealPath(fPath);
+ // Check if the .ui file should be skipped
+ if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
+ sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+ this->Uic.Skip.insert(absFile);
+ }
+ // Check if the .ui file has uic options
+ std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS");
+ if (!uicOpts.empty()) {
+ // Check if file isn't skipped
+ if (this->Uic.Skip.count(absFile) == 0) {
+ this->Uic.FileFiles.push_back(absFile);
+ std::vector<std::string> optsVec;
+ cmSystemTools::ExpandListArgument(uicOpts, optsVec);
+ this->Uic.FileOptions.push_back(std::move(optsVec));
+ }
+ }
}
}
}
- // Extract relevant source files
- std::vector<std::string> generatedSources;
- std::vector<std::string> generatedHeaders;
+ // Uic executable
+ if (!GetUicExecutable()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitRcc()
+{
+ if (!GetRccExecutable()) {
+ return false;
+ }
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitScanFiles()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ // Scan through target files
{
std::string const qrcExt = "qrc";
std::vector<cmSourceFile*> srcFiles;
std::string const& fPath = sf->GetFullPath();
std::string const& ext = sf->GetExtension();
// Register generated files that will be scanned by moc or uic
- if (this->MocEnabled || this->UicEnabled) {
+ if (this->Moc.Enabled || this->Uic.Enabled) {
cmSystemTools::FileFormat const fileType =
cmSystemTools::GetFileFormat(ext.c_str());
if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
std::string const absPath = cmSystemTools::GetRealPath(fPath);
- if ((this->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
- (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
+ if ((this->Moc.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
+ (this->Uic.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
// Register source
const bool generated = sf->GetPropertyAsBool("GENERATED");
if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
if (generated) {
- generatedHeaders.push_back(absPath);
+ this->AutogenTarget.HeadersGenerated.push_back(absPath);
} else {
- this->Headers.push_back(absPath);
+ this->AutogenTarget.Headers.push_back(absPath);
}
} else {
if (generated) {
- generatedSources.push_back(absPath);
+ this->AutogenTarget.SourcesGenerated.push_back(absPath);
} else {
- this->Sources.push_back(absPath);
+ this->AutogenTarget.Sources.push_back(absPath);
}
}
}
}
}
// Register rcc enabled files
- if (this->RccEnabled && (ext == qrcExt) &&
+ if (this->Rcc.Enabled && (ext == qrcExt) &&
!sf->GetPropertyAsBool("SKIP_AUTORCC")) {
// Register qrc file
{
qrc.Generated = sf->GetPropertyAsBool("GENERATED");
// RCC options
{
- std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
+ std::string const opts = sf->GetSafeProperty("AUTORCC_OPTIONS");
if (!opts.empty()) {
cmSystemTools::ExpandListArgument(opts, qrc.Options);
}
}
- this->Qrcs.push_back(std::move(qrc));
+ this->Rcc.Qrcs.push_back(std::move(qrc));
}
}
}
- // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
- // sources meta data cache. Clear it so that OBJECT library targets that
- // are AUTOGEN initialized after this target get their added
- // mocs_compilation.cpp source acknowledged by this target.
- this->Target->ClearSourcesCache();
}
- // Read skip files from makefile sources
- if (this->MocEnabled || this->UicEnabled) {
- std::string pathError;
- for (cmSourceFile* sf : makefile->GetSourceFiles()) {
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- // Since we're iterating over source files that might be not in the
- // target we need to check for path errors (not existing files).
- std::string const& fPath = sf->GetFullPath(&pathError);
- if (!pathError.empty()) {
- pathError.clear();
- continue;
- }
- cmSystemTools::FileFormat const fileType =
- cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
- if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
- !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
- continue;
- }
- const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
- const bool mocSkip =
- this->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
- const bool uicSkip =
- this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
- if (mocSkip || uicSkip) {
- std::string const absFile = cmSystemTools::GetRealPath(fPath);
- if (mocSkip) {
- this->MocSkip.insert(absFile);
+ // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
+ // sources meta data cache. Clear it so that OBJECT library targets that
+ // are AUTOGEN initialized after this target get their added
+ // mocs_compilation.cpp source acknowledged by this target.
+ this->Target->ClearSourcesCache();
+
+ if (this->Moc.Enabled || this->Uic.Enabled) {
+ // Read skip files from makefile sources
+ {
+ std::string pathError;
+ for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+ // sf->GetExtension() is only valid after sf->GetFullPath() ...
+ // Since we're iterating over source files that might be not in the
+ // target we need to check for path errors (not existing files).
+ std::string const& fPath = sf->GetFullPath(&pathError);
+ if (!pathError.empty()) {
+ pathError.clear();
+ continue;
+ }
+ cmSystemTools::FileFormat const fileType =
+ cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
+ if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
+ !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
+ continue;
}
- if (uicSkip) {
- this->UicSkip.insert(absFile);
+ const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
+ const bool mocSkip = this->Moc.Enabled &&
+ (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
+ const bool uicSkip = this->Uic.Enabled &&
+ (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
+ if (mocSkip || uicSkip) {
+ std::string const absFile = cmSystemTools::GetRealPath(fPath);
+ if (mocSkip) {
+ this->Moc.Skip.insert(absFile);
+ }
+ if (uicSkip) {
+ this->Uic.Skip.insert(absFile);
+ }
}
}
}
- }
-
- // Process GENERATED sources and headers
- if (!generatedSources.empty() || !generatedHeaders.empty()) {
- // Check status of policy CMP0071
- bool policyAccept = false;
- bool policyWarn = false;
- cmPolicies::PolicyStatus const CMP0071_status =
- makefile->GetPolicyStatus(cmPolicies::CMP0071);
- switch (CMP0071_status) {
- case cmPolicies::WARN:
- policyWarn = true;
- CM_FALLTHROUGH;
- case cmPolicies::OLD:
- // Ignore GENERATED file
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Process GENERATED file
- policyAccept = true;
- break;
- }
- if (policyAccept) {
- // Accept GENERATED sources
- for (std::string const& absFile : generatedHeaders) {
- this->Headers.push_back(absFile);
- autogenDependFiles.insert(absFile);
- }
- for (std::string const& absFile : generatedSources) {
- this->Sources.push_back(absFile);
- autogenDependFiles.insert(absFile);
+ // Process GENERATED sources and headers
+ if (!this->AutogenTarget.SourcesGenerated.empty() ||
+ !this->AutogenTarget.HeadersGenerated.empty()) {
+ // Check status of policy CMP0071
+ bool policyAccept = false;
+ bool policyWarn = false;
+ cmPolicies::PolicyStatus const CMP0071_status =
+ makefile->GetPolicyStatus(cmPolicies::CMP0071);
+ switch (CMP0071_status) {
+ case cmPolicies::WARN:
+ policyWarn = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // Ignore GENERATED file
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Process GENERATED file
+ policyAccept = true;
+ break;
}
- } else {
- if (policyWarn) {
- std::string msg;
- msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
- msg += "\n";
- std::string tools;
- std::string property;
- if (this->MocEnabled && this->UicEnabled) {
- tools = "AUTOMOC and AUTOUIC";
- property = "SKIP_AUTOGEN";
- } else if (this->MocEnabled) {
- tools = "AUTOMOC";
- property = "SKIP_AUTOMOC";
- } else if (this->UicEnabled) {
- tools = "AUTOUIC";
- property = "SKIP_AUTOUIC";
+
+ if (policyAccept) {
+ // Accept GENERATED sources
+ for (std::string const& absFile :
+ this->AutogenTarget.HeadersGenerated) {
+ this->AutogenTarget.Headers.push_back(absFile);
+ this->AutogenTarget.DependFiles.insert(absFile);
}
- msg += "For compatibility, CMake is excluding the GENERATED source "
- "file(s):\n";
- for (const std::string& absFile : generatedHeaders) {
- msg.append(" ").append(Quoted(absFile)).append("\n");
+ for (std::string const& absFile :
+ this->AutogenTarget.SourcesGenerated) {
+ this->AutogenTarget.Sources.push_back(absFile);
+ this->AutogenTarget.DependFiles.insert(absFile);
}
- for (const std::string& absFile : generatedSources) {
- msg.append(" ").append(Quoted(absFile)).append("\n");
+ } else {
+ if (policyWarn) {
+ std::string msg;
+ msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
+ msg += "\n";
+ std::string tools;
+ std::string property;
+ if (this->Moc.Enabled && this->Uic.Enabled) {
+ tools = "AUTOMOC and AUTOUIC";
+ property = "SKIP_AUTOGEN";
+ } else if (this->Moc.Enabled) {
+ tools = "AUTOMOC";
+ property = "SKIP_AUTOMOC";
+ } else if (this->Uic.Enabled) {
+ tools = "AUTOUIC";
+ property = "SKIP_AUTOUIC";
+ }
+ msg += "For compatibility, CMake is excluding the GENERATED source "
+ "file(s):\n";
+ for (const std::string& absFile :
+ this->AutogenTarget.HeadersGenerated) {
+ msg.append(" ").append(Quoted(absFile)).append("\n");
+ }
+ for (const std::string& absFile :
+ this->AutogenTarget.SourcesGenerated) {
+ msg.append(" ").append(Quoted(absFile)).append("\n");
+ }
+ msg += "from processing by ";
+ msg += tools;
+ msg +=
+ ". If any of the files should be processed, set CMP0071 to NEW. "
+ "If any of the files should not be processed, "
+ "explicitly exclude them by setting the source file property ";
+ msg += property;
+ msg += ":\n set_property(SOURCE file.h PROPERTY ";
+ msg += property;
+ msg += " ON)\n";
+ makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
}
- msg += "from processing by ";
- msg += tools;
- msg +=
- ". If any of the files should be processed, set CMP0071 to NEW. "
- "If any of the files should not be processed, "
- "explicitly exclude them by setting the source file property ";
- msg += property;
- msg += ":\n set_property(SOURCE file.h PROPERTY ";
- msg += property;
- msg += " ON)\n";
- makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
}
}
- // Clear lists
- generatedSources.clear();
- generatedHeaders.clear();
- }
- // Sort headers and sources
- if (this->MocEnabled || this->UicEnabled) {
- std::sort(this->Headers.begin(), this->Headers.end());
- std::sort(this->Sources.begin(), this->Sources.end());
+ // Sort headers and sources
+ if (this->Moc.Enabled || this->Uic.Enabled) {
+ std::sort(this->AutogenTarget.Headers.begin(),
+ this->AutogenTarget.Headers.end());
+ std::sort(this->AutogenTarget.Sources.begin(),
+ this->AutogenTarget.Sources.end());
+ }
}
// Process qrc files
- if (!this->Qrcs.empty()) {
- const bool QtV5 = (this->QtVersionMajor == "5");
+ if (!this->Rcc.Qrcs.empty()) {
+ const bool QtV5 = (this->QtVersion.Major == 5);
// Target rcc options
std::vector<std::string> optionsTarget;
cmSystemTools::ExpandListArgument(
- GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget);
+ this->Target->GetSafeProperty("AUTORCC_OPTIONS"), optionsTarget);
// Check if file name is unique
- for (Qrc& qrc : this->Qrcs) {
+ for (Qrc& qrc : this->Rcc.Qrcs) {
qrc.Unique = true;
- for (Qrc const& qrc2 : this->Qrcs) {
+ for (Qrc const& qrc2 : this->Rcc.Qrcs) {
if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) {
qrc.Unique = false;
break;
// Path checksum and file names
{
cmFilePathChecksum const fpathCheckSum(makefile);
- for (Qrc& qrc : this->Qrcs) {
+ for (Qrc& qrc : this->Rcc.Qrcs) {
qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
// RCC output file name
{
- std::string rccFile = this->DirBuild + "/";
+ std::string rccFile = this->Dir.Build + "/";
rccFile += qrc.PathChecksum;
rccFile += "/qrc_";
rccFile += qrc.QrcName;
qrc.RccFile = std::move(rccFile);
}
{
- std::string base = this->DirInfo;
+ std::string base = this->Dir.Info;
base += "/RCC";
base += qrc.QrcName;
if (!qrc.Unique) {
qrc.SettingsFile = base;
qrc.SettingsFile += "Settings.txt";
+
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ qrc.ConfigSettingsFile[cfg] =
+ AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
+ }
+ }
}
}
}
// RCC options
- for (Qrc& qrc : this->Qrcs) {
+ for (Qrc& qrc : this->Rcc.Qrcs) {
// Target options
std::vector<std::string> opts = optionsTarget;
// Merge computed "-name XYZ" option
RccMergeOptions(opts, qrc.Options, QtV5);
qrc.Options = std::move(opts);
}
- for (Qrc& qrc : this->Qrcs) {
- // Register file at target
- this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
-
- std::vector<std::string> ccOutput;
- ccOutput.push_back(qrc.RccFile);
-
- cmCustomCommandLines commandLines;
- if (this->MultiConfig) {
- // Build for all configurations
- for (std::string const& config : this->ConfigsList) {
- cmCustomCommandLine currentLine;
- currentLine.push_back(cmSystemTools::GetCMakeCommand());
- currentLine.push_back("-E");
- currentLine.push_back("cmake_autorcc");
- currentLine.push_back(qrc.InfoFile);
- currentLine.push_back(config);
- commandLines.push_back(std::move(currentLine));
+ // RCC resources
+ for (Qrc& qrc : this->Rcc.Qrcs) {
+ if (!qrc.Generated) {
+ std::string error;
+ if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) {
+ cmSystemTools::Error(error.c_str());
+ return false;
}
- } else {
- cmCustomCommandLine currentLine;
- currentLine.push_back(cmSystemTools::GetCMakeCommand());
- currentLine.push_back("-E");
- currentLine.push_back("cmake_autorcc");
- currentLine.push_back(qrc.InfoFile);
- currentLine.push_back("$<CONFIG>");
- commandLines.push_back(std::move(currentLine));
}
- std::string ccComment = "Automatic RCC for ";
- ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
+ }
+ }
- if (qrc.Generated) {
- // Create custom rcc target
- std::string ccName;
- {
- ccName = this->Target->GetName();
- ccName += "_arcc_";
- ccName += qrc.QrcName;
- if (!qrc.Unique) {
- ccName += "_";
- ccName += qrc.PathChecksum;
- }
- std::vector<std::string> ccDepends;
- // Add the .qrc and info file to the custom target dependencies
- ccDepends.push_back(qrc.QrcFile);
- ccDepends.push_back(qrc.InfoFile);
-
- cmTarget* autoRccTarget = makefile->AddUtilityCommand(
- ccName, cmMakefile::TargetOrigin::Generator, true,
- this->DirWork.c_str(), ccOutput, ccDepends, commandLines, false,
- ccComment.c_str());
- // Create autogen generator target
- localGen->AddGeneratorTarget(
- new cmGeneratorTarget(autoRccTarget, localGen));
-
- // Set FOLDER property in autogen target
- if (!this->AutogenFolder.empty()) {
- autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
- }
- }
- // Add autogen target to the origin target dependencies
- this->Target->Target->AddUtility(ccName, makefile);
- } else {
- // Create custom rcc command
- {
- std::vector<std::string> ccByproducts;
- std::vector<std::string> ccDepends;
- // Add the .qrc and info file to the custom command dependencies
- ccDepends.push_back(qrc.QrcFile);
- ccDepends.push_back(qrc.InfoFile);
+ return true;
+}
- // Add the resource files to the dependencies
- {
- std::string error;
- if (RccListInputs(qrc.QrcFile, qrc.Resources, error)) {
- for (std::string const& fileName : qrc.Resources) {
- // Add resource file to the custom command dependencies
- ccDepends.push_back(fileName);
- }
- } else {
- cmSystemTools::Error(error.c_str());
- }
- }
- makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
- /*main_dependency*/ std::string(),
- commandLines, ccComment.c_str(),
- this->DirWork.c_str());
- }
- // Reconfigure when .qrc file changes
- makefile->AddCMakeDependFile(qrc.QrcFile);
+bool cmQtAutoGenInitializer::InitAutogenTarget()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
+
+ // Register info file as generated by CMake
+ makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);
+
+ // Files provided by the autogen target
+ std::vector<std::string> autogenProvides;
+ if (this->Moc.Enabled) {
+ this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC);
+ autogenProvides.push_back(this->Moc.MocsCompilation);
+ }
+
+ // Compose target comment
+ std::string autogenComment;
+ {
+ std::string tools;
+ if (this->Moc.Enabled) {
+ tools += "MOC";
+ }
+ if (this->Uic.Enabled) {
+ if (!tools.empty()) {
+ tools += " and ";
}
+ tools += "UIC";
}
+ autogenComment = "Automatic ";
+ autogenComment += tools;
+ autogenComment += " for target ";
+ autogenComment += this->Target->GetName();
}
- // Create _autogen target
- if (this->MocEnabled || this->UicEnabled) {
- // Add user defined autogen target dependencies
- {
- std::string const deps =
- GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS");
- if (!deps.empty()) {
- std::vector<std::string> extraDeps;
- cmSystemTools::ExpandListArgument(deps, extraDeps);
- for (std::string const& depName : extraDeps) {
- // Allow target and file dependencies
- auto* depTarget = makefile->FindTargetToUse(depName);
- if (depTarget != nullptr) {
- autogenDependTargets.insert(depTarget);
- } else {
- autogenDependFiles.insert(depName);
- }
- }
- }
+ // Compose command lines
+ cmCustomCommandLines commandLines;
+ {
+ cmCustomCommandLine currentLine;
+ currentLine.push_back(cmSystemTools::GetCMakeCommand());
+ currentLine.push_back("-E");
+ currentLine.push_back("cmake_autogen");
+ currentLine.push_back(this->AutogenTarget.InfoFile);
+ currentLine.push_back("$<CONFIGURATION>");
+ commandLines.push_back(std::move(currentLine));
+ }
+
+ // Use PRE_BUILD on demand
+ bool usePRE_BUILD = false;
+ if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+ // 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 = true;
+ }
+ // Disable PRE_BUILD in some cases
+ if (usePRE_BUILD) {
+ // Cannot use PRE_BUILD with file depends
+ if (!this->AutogenTarget.DependFiles.empty()) {
+ usePRE_BUILD = false;
+ }
+ }
+ // Create the autogen target/command
+ if (usePRE_BUILD) {
+ // Add additional autogen target dependencies to origin target
+ for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
+ this->Target->Target->AddUtility(depTarget->GetName(), makefile);
}
- // Compose target comment
- std::string autogenComment;
+ // 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.
+ //
+ // PRE_BUILD does not support file dependencies!
+ const std::vector<std::string> no_output;
+ const std::vector<std::string> no_deps;
+ cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
+ commandLines, autogenComment.c_str(),
+ this->Dir.Work.c_str());
+ cc.SetEscapeOldStyle(false);
+ cc.SetEscapeAllowMakeVars(true);
+ this->Target->Target->AddPreBuildCommand(cc);
+ } else {
+
+ // Add link library target dependencies to the autogen target
+ // dependencies
{
- std::string tools;
- if (this->MocEnabled) {
- tools += "MOC";
+ // add_dependencies/addUtility do not support generator expressions.
+ // We depend only on the libraries found in all configs therefore.
+ std::map<cmGeneratorTarget const*, std::size_t> commonTargets;
+ for (std::string const& config : this->ConfigsList) {
+ cmLinkImplementationLibraries const* libs =
+ this->Target->GetLinkImplementationLibraries(config);
+ if (libs != nullptr) {
+ for (cmLinkItem const& item : libs->Libraries) {
+ cmGeneratorTarget const* libTarget = item.Target;
+ if ((libTarget != nullptr) &&
+ !StaticLibraryCycle(this->Target, libTarget, config)) {
+ // Increment target config count
+ commonTargets[libTarget]++;
+ }
+ }
+ }
}
- if (this->UicEnabled) {
- if (!tools.empty()) {
- tools += " and ";
+ for (auto const& item : commonTargets) {
+ if (item.second == this->ConfigsList.size()) {
+ this->AutogenTarget.DependTargets.insert(item.first->Target);
}
- tools += "UIC";
}
- autogenComment = "Automatic ";
- autogenComment += tools;
- autogenComment += " for target ";
- autogenComment += this->Target->GetName();
}
- // Compose command lines
+ // Create autogen target
+ cmTarget* autogenTarget = makefile->AddUtilityCommand(
+ this->AutogenTarget.Name, cmMakefile::TargetOrigin::Generator, true,
+ this->Dir.Work.c_str(), /*byproducts=*/autogenProvides,
+ std::vector<std::string>(this->AutogenTarget.DependFiles.begin(),
+ this->AutogenTarget.DependFiles.end()),
+ commandLines, false, autogenComment.c_str());
+ // Create autogen generator target
+ localGen->AddGeneratorTarget(
+ new cmGeneratorTarget(autogenTarget, localGen));
+
+ // Forward origin utilities to autogen target
+ for (std::string const& depName : this->Target->Target->GetUtilities()) {
+ autogenTarget->AddUtility(depName, makefile);
+ }
+ // Add additional autogen target dependencies to autogen target
+ for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
+ autogenTarget->AddUtility(depTarget->GetName(), makefile);
+ }
+
+ // Set FOLDER property in autogen target
+ if (!this->TargetsFolder.empty()) {
+ autogenTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
+ }
+
+ // Add autogen target to the origin target dependencies
+ this->Target->Target->AddUtility(this->AutogenTarget.Name, makefile);
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitRccTargets()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+
+ for (Qrc const& qrc : this->Rcc.Qrcs) {
+ // Register info file as generated by CMake
+ makefile->AddCMakeOutputFile(qrc.InfoFile);
+ // Register file at target
+ this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
+
+ std::vector<std::string> ccOutput;
+ ccOutput.push_back(qrc.RccFile);
+
cmCustomCommandLines commandLines;
- {
+ if (this->MultiConfig) {
+ // Build for all configurations
+ for (std::string const& config : this->ConfigsList) {
+ cmCustomCommandLine currentLine;
+ currentLine.push_back(cmSystemTools::GetCMakeCommand());
+ currentLine.push_back("-E");
+ currentLine.push_back("cmake_autorcc");
+ currentLine.push_back(qrc.InfoFile);
+ currentLine.push_back(config);
+ commandLines.push_back(std::move(currentLine));
+ }
+ } else {
cmCustomCommandLine currentLine;
currentLine.push_back(cmSystemTools::GetCMakeCommand());
currentLine.push_back("-E");
- currentLine.push_back("cmake_autogen");
- currentLine.push_back(this->AutogenInfoFile);
- currentLine.push_back("$<CONFIGURATION>");
+ currentLine.push_back("cmake_autorcc");
+ currentLine.push_back(qrc.InfoFile);
+ currentLine.push_back("$<CONFIG>");
commandLines.push_back(std::move(currentLine));
}
+ std::string ccComment = "Automatic RCC for ";
+ ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
- // Use PRE_BUILD on demand
- bool usePRE_BUILD = false;
- if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
- // 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 = true;
- }
- // Disable PRE_BUILD in some cases
- if (usePRE_BUILD) {
- // Cannot use PRE_BUILD with file depends
- if (!autogenDependFiles.empty()) {
- usePRE_BUILD = false;
- }
- }
- // Create the autogen target/command
- if (usePRE_BUILD) {
- // Add additional autogen target dependencies to origin target
- for (cmTarget* depTarget : autogenDependTargets) {
- this->Target->Target->AddUtility(depTarget->GetName(), makefile);
- }
-
- // 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.
- //
- // PRE_BUILD does not support file dependencies!
- const std::vector<std::string> no_output;
- const std::vector<std::string> no_deps;
- cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
- commandLines, autogenComment.c_str(),
- this->DirWork.c_str());
- cc.SetEscapeOldStyle(false);
- cc.SetEscapeAllowMakeVars(true);
- this->Target->Target->AddPreBuildCommand(cc);
- } else {
-
- // Add link library target dependencies to the autogen target
- // dependencies
+ if (qrc.Generated) {
+ // Create custom rcc target
+ std::string ccName;
{
- // add_dependencies/addUtility do not support generator expressions.
- // We depend only on the libraries found in all configs therefore.
- std::map<cmGeneratorTarget const*, std::size_t> commonTargets;
- for (std::string const& config : this->ConfigsList) {
- cmLinkImplementationLibraries const* libs =
- this->Target->GetLinkImplementationLibraries(config);
- if (libs != nullptr) {
- for (cmLinkItem const& item : libs->Libraries) {
- cmGeneratorTarget const* libTarget = item.Target;
- if ((libTarget != nullptr) &&
- !StaticLibraryCycle(this->Target, libTarget, config)) {
- // Increment target config count
- commonTargets[libTarget]++;
- }
- }
- }
+ ccName = this->Target->GetName();
+ ccName += "_arcc_";
+ ccName += qrc.QrcName;
+ if (!qrc.Unique) {
+ ccName += "_";
+ ccName += qrc.PathChecksum;
}
- for (auto const& item : commonTargets) {
- if (item.second == this->ConfigsList.size()) {
- autogenDependTargets.insert(item.first->Target);
- }
+ std::vector<std::string> ccDepends;
+ // Add the .qrc and info file to the custom target dependencies
+ ccDepends.push_back(qrc.QrcFile);
+ ccDepends.push_back(qrc.InfoFile);
+
+ cmTarget* autoRccTarget = makefile->AddUtilityCommand(
+ ccName, cmMakefile::TargetOrigin::Generator, true,
+ this->Dir.Work.c_str(), ccOutput, ccDepends, commandLines, false,
+ ccComment.c_str());
+ // Create autogen generator target
+ localGen->AddGeneratorTarget(
+ new cmGeneratorTarget(autoRccTarget, localGen));
+
+ // Set FOLDER property in autogen target
+ if (!this->TargetsFolder.empty()) {
+ autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
}
}
-
- // Create autogen target
- cmTarget* autogenTarget = makefile->AddUtilityCommand(
- this->AutogenTargetName, cmMakefile::TargetOrigin::Generator, true,
- this->DirWork.c_str(), /*byproducts=*/autogenProvides,
- std::vector<std::string>(autogenDependFiles.begin(),
- autogenDependFiles.end()),
- commandLines, false, autogenComment.c_str());
- // Create autogen generator target
- localGen->AddGeneratorTarget(
- new cmGeneratorTarget(autogenTarget, localGen));
-
- // Forward origin utilities to autogen target
- for (std::string const& depName : this->Target->Target->GetUtilities()) {
- autogenTarget->AddUtility(depName, makefile);
- }
- // Add additional autogen target dependencies to autogen target
- for (cmTarget* depTarget : autogenDependTargets) {
- autogenTarget->AddUtility(depTarget->GetName(), makefile);
- }
-
- // Set FOLDER property in autogen target
- if (!this->AutogenFolder.empty()) {
- autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
- }
-
// Add autogen target to the origin target dependencies
- this->Target->Target->AddUtility(this->AutogenTargetName, makefile);
+ this->Target->Target->AddUtility(ccName, makefile);
+ } else {
+ // Create custom rcc command
+ {
+ std::vector<std::string> ccByproducts;
+ std::vector<std::string> ccDepends;
+ // Add the .qrc and info file to the custom command dependencies
+ ccDepends.push_back(qrc.QrcFile);
+ ccDepends.push_back(qrc.InfoFile);
+
+ // Add the resource files to the dependencies
+ for (std::string const& fileName : qrc.Resources) {
+ // Add resource file to the custom command dependencies
+ ccDepends.push_back(fileName);
+ }
+ makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
+ /*main_dependency*/ std::string(),
+ commandLines, ccComment.c_str(),
+ this->Dir.Work.c_str());
+ }
+ // Reconfigure when .qrc file changes
+ makefile->AddCMakeDependFile(qrc.QrcFile);
}
}
+
+ return true;
}
-void cmQtAutoGenInitializer::SetupCustomTargets()
+bool cmQtAutoGenInitializer::SetupCustomTargets()
{
- cmMakefile* makefile = this->Target->Target->GetMakefile();
-
// Create info directory on demand
- if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
- std::string emsg = ("Could not create directory: ");
- emsg += Quoted(this->DirInfo);
+ if (!cmSystemTools::MakeDirectory(this->Dir.Info)) {
+ std::string emsg = ("AutoGen: Could not create directory: ");
+ emsg += Quoted(this->Dir.Info);
cmSystemTools::Error(emsg.c_str());
- }
-
- // Configuration include directories
- std::string includeDir = "include";
- std::map<std::string, std::string> includeDirs;
- for (std::string const& cfg : this->ConfigsList) {
- std::string& dir = includeDirs[cfg];
- dir = "include_";
- dir += cfg;
+ return false;
}
// Generate autogen target info file
- if (this->MocEnabled || this->UicEnabled) {
- if (this->MocEnabled) {
- this->SetupCustomTargetsMoc();
+ if (this->Moc.Enabled || this->Uic.Enabled) {
+ // Write autogen target info files
+ if (!this->SetupWriteAutogenInfo()) {
+ return false;
}
- if (this->UicEnabled) {
- this->SetupCustomTargetsUic();
+ }
+
+ // Write AUTORCC info files
+ if (this->Rcc.Enabled && !this->SetupWriteRccInfo()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ cmGeneratedFileStream ofs;
+ ofs.SetCopyIfDifferent(true);
+ ofs.Open(this->AutogenTarget.InfoFile, false, true);
+ if (ofs) {
+ // Utility lambdas
+ auto CWrite = [&ofs](const char* key, std::string const& value) {
+ ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
+ << ")\n";
+ };
+ auto CWriteUInt = [&ofs](const char* key, unsigned int value) {
+ ofs << "set(" << key << " " << value << ")\n";
+ };
+ auto CWriteList = [&CWrite](const char* key,
+ std::vector<std::string> const& list) {
+ CWrite(key, cmJoin(list, ";"));
+ };
+ auto CWriteNestedLists =
+ [&CWrite](const char* key,
+ std::vector<std::vector<std::string>> const& lists) {
+ std::vector<std::string> seplist;
+ for (const std::vector<std::string>& list : lists) {
+ std::string blist = "{";
+ blist += cmJoin(list, ";");
+ blist += "}";
+ seplist.push_back(std::move(blist));
+ }
+ CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
+ };
+ auto CWriteSet = [&CWrite](const char* key,
+ std::set<std::string> const& list) {
+ CWrite(key, cmJoin(list, ";"));
+ };
+ auto CWriteMap = [&ofs](const char* key,
+ std::map<std::string, std::string> const& map) {
+ for (auto const& item : map) {
+ ofs << "set(" << key << "_" << item.first << " "
+ << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
+ }
+ };
+ auto MfDef = [makefile](const char* key) {
+ return makefile->GetSafeDefinition(key);
+ };
+
+ // Write
+ ofs << "# Meta\n";
+ CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+ CWrite("AM_PARALLEL", this->AutogenTarget.Parallel);
+ CWrite("AM_VERBOSITY", this->Verbosity);
+
+ ofs << "# Directories\n";
+ CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+ CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+ CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+ CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+ CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
+ MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
+ CWrite("AM_BUILD_DIR", this->Dir.Build);
+ CWrite("AM_INCLUDE_DIR", this->Dir.Include);
+ CWriteMap("AM_INCLUDE_DIR", this->Dir.ConfigInclude);
+
+ ofs << "# Files\n";
+ CWriteList("AM_SOURCES", this->AutogenTarget.Sources);
+ CWriteList("AM_HEADERS", this->AutogenTarget.Headers);
+ CWrite("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile);
+ CWriteMap("AM_SETTINGS_FILE", this->AutogenTarget.ConfigSettingsFile);
+
+ ofs << "# Qt\n";
+ CWriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major);
+ CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);
+ CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);
+
+ if (this->Moc.Enabled) {
+ ofs << "# MOC settings\n";
+ CWriteSet("AM_MOC_SKIP", this->Moc.Skip);
+ CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines);
+ CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);
+ CWrite("AM_MOC_INCLUDES", this->Moc.Includes);
+ CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);
+ CWrite("AM_MOC_OPTIONS",
+ this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));
+ CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
+ CWrite("AM_MOC_MACRO_NAMES",
+ this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES"));
+ CWrite("AM_MOC_DEPEND_FILTERS",
+ this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
+ CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
}
- // Parallel processing
- this->Parallel = GetSafeProperty(this->Target, "AUTOGEN_PARALLEL");
- if (this->Parallel.empty() || (this->Parallel == "AUTO")) {
- // Autodetect number of CPUs
- this->Parallel = std::to_string(GetParallelCPUCount());
+ if (this->Uic.Enabled) {
+ ofs << "# UIC settings\n";
+ CWriteSet("AM_UIC_SKIP", this->Uic.Skip);
+ CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options);
+ CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);
+ CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);
+ CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);
+ CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);
}
+ } else {
+ std::string err = "AutoGen: Could not write file ";
+ err += this->AutogenTarget.InfoFile;
+ cmSystemTools::Error(err.c_str());
+ return false;
+ }
+
+ return true;
+}
+bool cmQtAutoGenInitializer::SetupWriteRccInfo()
+{
+ for (Qrc const& qrc : this->Rcc.Qrcs) {
cmGeneratedFileStream ofs;
ofs.SetCopyIfDifferent(true);
- ofs.Open(this->AutogenInfoFile.c_str(), false, true);
+ ofs.Open(qrc.InfoFile, false, true);
if (ofs) {
// Utility lambdas
auto CWrite = [&ofs](const char* key, std::string const& value) {
ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
<< ")\n";
};
- auto CWriteList = [&CWrite](const char* key,
- std::vector<std::string> const& list) {
- CWrite(key, cmJoin(list, ";"));
- };
- auto CWriteNestedLists =
- [&CWrite](const char* key,
- std::vector<std::vector<std::string>> const& lists) {
- std::vector<std::string> seplist;
- for (const std::vector<std::string>& list : lists) {
- std::string blist = "{";
- blist += cmJoin(list, ";");
- blist += "}";
- seplist.push_back(std::move(blist));
- }
- CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
- };
- auto CWriteSet = [&CWrite](const char* key,
- std::set<std::string> const& list) {
- CWrite(key, cmJoin(list, ";"));
- };
auto CWriteMap = [&ofs](const char* key,
std::map<std::string, std::string> const& map) {
for (auto const& item : map) {
<< cmOutputConverter::EscapeForCMake(item.second) << ")\n";
}
};
- auto MfDef = [makefile](const char* key) {
- return std::string(makefile->GetSafeDefinition(key));
- };
// Write
- ofs << "# Meta\n";
- CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
- CWrite("AM_PARALLEL", this->Parallel);
+ ofs << "# Configurations\n";
+ CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+ CWrite("ARCC_VERBOSITY", this->Verbosity);
+ ofs << "# Settings file\n";
+ CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
+ CWriteMap("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);
ofs << "# Directories\n";
- CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
- CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
- CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
- CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
- CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
- MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
- CWrite("AM_BUILD_DIR", this->DirBuild);
- if (this->MultiConfig) {
- CWriteMap("AM_INCLUDE_DIR", includeDirs);
- } else {
- CWrite("AM_INCLUDE_DIR", includeDir);
- }
-
- ofs << "# Files\n";
- CWriteList("AM_SOURCES", this->Sources);
- CWriteList("AM_HEADERS", this->Headers);
- if (this->MultiConfig) {
- std::map<std::string, std::string> settingsFiles;
- for (std::string const& cfg : this->ConfigsList) {
- settingsFiles[cfg] =
- AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg);
- }
- CWriteMap("AM_SETTINGS_FILE", settingsFiles);
- } else {
- CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile);
- }
-
- ofs << "# Qt\n";
- CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor);
- CWrite("AM_QT_MOC_EXECUTABLE", this->MocExecutable);
- CWrite("AM_QT_UIC_EXECUTABLE", this->UicExecutable);
-
- if (this->MocEnabled) {
- ofs << "# MOC settings\n";
- CWriteSet("AM_MOC_SKIP", this->MocSkip);
- CWrite("AM_MOC_DEFINITIONS", this->MocDefines);
- CWriteMap("AM_MOC_DEFINITIONS", this->MocDefinesConfig);
- CWrite("AM_MOC_INCLUDES", this->MocIncludes);
- CWriteMap("AM_MOC_INCLUDES", this->MocIncludesConfig);
- CWrite("AM_MOC_OPTIONS",
- GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
- CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
- CWrite("AM_MOC_MACRO_NAMES",
- GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
- CWrite("AM_MOC_DEPEND_FILTERS",
- GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
- CWrite("AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
- }
-
- if (this->UicEnabled) {
- ofs << "# UIC settings\n";
- CWriteSet("AM_UIC_SKIP", this->UicSkip);
- CWrite("AM_UIC_TARGET_OPTIONS", this->UicOptions);
- CWriteMap("AM_UIC_TARGET_OPTIONS", this->UicOptionsConfig);
- CWriteList("AM_UIC_OPTIONS_FILES", this->UicFileFiles);
- CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->UicFileOptions);
- CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
- }
+ CWrite("ARCC_BUILD_DIR", this->Dir.Build);
+ CWrite("ARCC_INCLUDE_DIR", this->Dir.Include);
+ CWriteMap("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude);
+
+ ofs << "# Rcc executable\n";
+ CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
+ CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";"));
+
+ ofs << "# Rcc job\n";
+ CWrite("ARCC_LOCK_FILE", qrc.LockFile);
+ CWrite("ARCC_SOURCE", qrc.QrcFile);
+ CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
+ CWrite("ARCC_OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.RccFile));
+ CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
+ CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
} else {
- return;
+ std::string err = "AutoRcc: Could not write file ";
+ err += qrc.InfoFile;
+ cmSystemTools::Error(err.c_str());
+ return false;
}
}
- // Generate auto RCC info files
- if (this->RccEnabled) {
- for (Qrc const& qrc : this->Qrcs) {
- // Register rcc info file as generated
- makefile->AddCMakeOutputFile(qrc.InfoFile);
-
- cmGeneratedFileStream ofs;
- ofs.SetCopyIfDifferent(true);
- ofs.Open(qrc.InfoFile.c_str(), false, true);
- if (ofs) {
- // Utility lambdas
- auto CWrite = [&ofs](const char* key, std::string const& value) {
- ofs << "set(" << key << " "
- << cmOutputConverter::EscapeForCMake(value) << ")\n";
- };
- auto CWriteMap =
- [&ofs](const char* key,
- std::map<std::string, std::string> const& map) {
- for (auto const& item : map) {
- ofs << "set(" << key << "_" << item.first << " "
- << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
- }
- };
-
- // Write
- ofs << "# Configurations\n";
- CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
-
- ofs << "# Settings file\n";
- if (this->MultiConfig) {
- std::map<std::string, std::string> settingsFiles;
- for (std::string const& cfg : this->ConfigsList) {
- settingsFiles[cfg] =
- AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
- }
- CWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
- } else {
- CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
- }
-
- ofs << "# Directories\n";
- CWrite("ARCC_BUILD_DIR", this->DirBuild);
- if (this->MultiConfig) {
- CWriteMap("ARCC_INCLUDE_DIR", includeDirs);
- } else {
- CWrite("ARCC_INCLUDE_DIR", includeDir);
- }
+ return true;
+}
- ofs << "# Rcc executable\n";
- CWrite("ARCC_RCC_EXECUTABLE", this->RccExecutable);
- CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->RccListOptions, ";"));
-
- ofs << "# Rcc job\n";
- CWrite("ARCC_LOCK_FILE", qrc.LockFile);
- CWrite("ARCC_SOURCE", qrc.QrcFile);
- CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
- CWrite("ARCC_OUTPUT_NAME",
- cmSystemTools::GetFilenameName(qrc.RccFile));
- CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
- CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
- } else {
- return;
- }
- }
+void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
+ GeneratorT genType)
+{
+ // Register source file in makefile
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ {
+ cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
+ gFile->SetProperty("GENERATED", "1");
+ gFile->SetProperty("SKIP_AUTOGEN", "On");
}
+
+ // Add source file to source group
+ AddToSourceGroup(makefile, filename, genType);
+
+ // Add source file to target
+ this->Target->AddSource(filename);
}
-void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
+cmQtAutoGenInitializer::IntegerVersion cmQtAutoGenInitializer::GetQtVersion(
+ cmGeneratorTarget const* target)
{
- cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
- cmMakefile* makefile = this->Target->Target->GetMakefile();
+ cmQtAutoGenInitializer::IntegerVersion res;
+ cmMakefile* makefile = target->Target->GetMakefile();
- // Moc predefs command
- if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
- this->QtVersionGreaterOrEqual(5, 8)) {
- this->MocPredefsCmd =
- makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
+ // -- Major version
+ std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
+ if (qtMajor.empty()) {
+ qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
}
-
- // Moc includes and compile definitions
{
- auto GetIncludeDirs = [this,
- localGen](std::string const& cfg) -> std::string {
- // Get the include dirs for this target, without stripping the implicit
- // include dirs off, see
- // https://gitlab.kitware.com/cmake/cmake/issues/13667
- std::vector<std::string> includeDirs;
- localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg,
- false);
- return cmJoin(includeDirs, ";");
- };
- auto GetCompileDefinitions =
- [this, localGen](std::string const& cfg) -> std::string {
- std::set<std::string> defines;
- localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
- return cmJoin(defines, ";");
- };
-
- // Default configuration settings
- this->MocIncludes = GetIncludeDirs(this->ConfigDefault);
- this->MocDefines = GetCompileDefinitions(this->ConfigDefault);
- // Other configuration settings
- for (std::string const& cfg : this->ConfigsList) {
- {
- std::string const configIncludeDirs = GetIncludeDirs(cfg);
- if (configIncludeDirs != this->MocIncludes) {
- this->MocIncludesConfig[cfg] = configIncludeDirs;
- }
- }
- {
- std::string const configCompileDefs = GetCompileDefinitions(cfg);
- if (configCompileDefs != this->MocDefines) {
- this->MocDefinesConfig[cfg] = configCompileDefs;
- }
- }
+ const char* targetQtVersion =
+ target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
+ if (targetQtVersion != nullptr) {
+ qtMajor = targetQtVersion;
}
}
- // Moc executable
- {
- std::string mocExec;
- std::string err;
-
- if (this->QtVersionMajor == "5") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
- if (tgt != nullptr) {
- mocExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTOMOC: Qt5::moc target not found";
- }
- } else if (this->QtVersionMajor == "4") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
- if (tgt != nullptr) {
- mocExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- err = "AUTOMOC: Qt4::moc target not found";
+ // -- Minor version
+ std::string qtMinor;
+ if (!qtMajor.empty()) {
+ if (qtMajor == "5") {
+ qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
+ }
+ if (qtMinor.empty()) {
+ qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
+ }
+ {
+ const char* targetQtVersion =
+ target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION",
+ "");
+ if (targetQtVersion != nullptr) {
+ qtMinor = targetQtVersion;
}
- } else {
- err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
}
+ }
- if (err.empty()) {
- this->MocExecutable = mocExec;
- } else {
- err += " (";
- err += this->Target->GetName();
- err += ")";
- cmSystemTools::Error(err.c_str());
+ // -- Convert to integer
+ if (!qtMajor.empty() && !qtMinor.empty()) {
+ unsigned long majorUL(0);
+ unsigned long minorUL(0);
+ if (cmSystemTools::StringToULong(qtMajor.c_str(), &majorUL) &&
+ cmSystemTools::StringToULong(qtMinor.c_str(), &minorUL)) {
+ res.Major = static_cast<unsigned int>(majorUL);
+ res.Minor = static_cast<unsigned int>(minorUL);
}
}
+
+ return res;
}
-void cmQtAutoGenInitializer::SetupCustomTargetsUic()
+bool cmQtAutoGenInitializer::GetMocExecutable()
{
- cmMakefile* makefile = this->Target->Target->GetMakefile();
+ std::string err;
- // Uic search paths
+ // Find moc executable
{
- std::string const usp =
- GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
- if (!usp.empty()) {
- cmSystemTools::ExpandListArgument(usp, this->UicSearchPaths);
- std::string const srcDir = makefile->GetCurrentSourceDirectory();
- for (std::string& path : this->UicSearchPaths) {
- path = cmSystemTools::CollapseFullPath(path, srcDir);
+ std::string targetName;
+ if (this->QtVersion.Major == 5) {
+ targetName = "Qt5::moc";
+ } else if (this->QtVersion.Major == 4) {
+ targetName = "Qt4::moc";
+ } else {
+ err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
+ }
+ if (!targetName.empty()) {
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
+ if (tgt != nullptr) {
+ this->Moc.Executable = tgt->ImportedGetLocation("");
+ } else {
+ err = "Could not find target " + targetName;
}
}
}
- // Uic target options
- {
- auto UicGetOpts = [this](std::string const& cfg) -> std::string {
- std::vector<std::string> opts;
- this->Target->GetAutoUicOptions(opts, cfg);
- return cmJoin(opts, ";");
- };
-
- // Default settings
- this->UicOptions = UicGetOpts(this->ConfigDefault);
- // Configuration specific settings
- for (std::string const& cfg : this->ConfigsList) {
- std::string const configUicOpts = UicGetOpts(cfg);
- if (configUicOpts != this->UicOptions) {
- this->UicOptionsConfig[cfg] = configUicOpts;
+ // Test moc command
+ if (err.empty()) {
+ if (cmSystemTools::FileExists(this->Moc.Executable, true)) {
+ std::vector<std::string> command;
+ command.push_back(this->Moc.Executable);
+ command.push_back("-h");
+ std::string stdOut;
+ std::string stdErr;
+ int retVal = 0;
+ bool result = cmSystemTools::RunSingleCommand(
+ command, &stdOut, &stdErr, &retVal, nullptr,
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ if (!result) {
+ err = "The moc test command failed: ";
+ err += QuotedCommand(command);
}
+ } else {
+ err = "The moc executable ";
+ err += Quoted(this->Moc.Executable);
+ err += " does not exist";
}
}
- // .ui files skip and options
- {
- std::string const uiExt = "ui";
- std::string pathError;
- for (cmSourceFile* sf : makefile->GetSourceFiles()) {
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- // Since we're iterating over source files that might be not in the
- // target we need to check for path errors (not existing files).
- std::string const& fPath = sf->GetFullPath(&pathError);
- if (!pathError.empty()) {
- pathError.clear();
- continue;
- }
- if (sf->GetExtension() == uiExt) {
- std::string const absFile = cmSystemTools::GetRealPath(fPath);
- // Check if the .ui file should be skipped
- if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
- sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
- this->UicSkip.insert(absFile);
- }
- // Check if the .ui file has uic options
- std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
- if (!uicOpts.empty()) {
- // Check if file isn't skipped
- if (this->UicSkip.count(absFile) == 0) {
- this->UicFileFiles.push_back(absFile);
- std::vector<std::string> optsVec;
- cmSystemTools::ExpandListArgument(uicOpts, optsVec);
- this->UicFileOptions.push_back(std::move(optsVec));
- }
- }
- }
- }
+
+ // Print error
+ if (!err.empty()) {
+ std::string msg = "AutoMoc (";
+ msg += this->Target->GetName();
+ msg += "): ";
+ msg += err;
+ cmSystemTools::Error(msg.c_str());
+ return false;
}
- // Uic executable
- {
- std::string err;
- std::string uicExec;
+ return true;
+}
- cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
- if (this->QtVersionMajor == "5") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
- if (tgt != nullptr) {
- uicExec = SafeString(tgt->ImportedGetLocation(""));
- } else {
- // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
- }
- } else if (this->QtVersionMajor == "4") {
- cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
+bool cmQtAutoGenInitializer::GetUicExecutable()
+{
+ std::string err;
+
+ // Find uic executable
+ {
+ std::string targetName;
+ if (this->QtVersion.Major == 5) {
+ targetName = "Qt5::uic";
+ } else if (this->QtVersion.Major == 4) {
+ targetName = "Qt4::uic";
+ } else {
+ err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
+ }
+ if (!targetName.empty()) {
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
if (tgt != nullptr) {
- uicExec = SafeString(tgt->ImportedGetLocation(""));
+ this->Uic.Executable = tgt->ImportedGetLocation("");
} else {
- err = "AUTOUIC: Qt4::uic target not found";
+ if (this->QtVersion.Major == 5) {
+ // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+ } else {
+ err = "Could not find target " + targetName;
+ }
}
- } else {
- err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
}
+ }
- if (err.empty()) {
- this->UicExecutable = uicExec;
+ // Test uic command
+ if (err.empty()) {
+ if (cmSystemTools::FileExists(this->Uic.Executable, true)) {
+ std::vector<std::string> command;
+ command.push_back(this->Uic.Executable);
+ command.push_back("-h");
+ std::string stdOut;
+ std::string stdErr;
+ int retVal = 0;
+ bool result = cmSystemTools::RunSingleCommand(
+ command, &stdOut, &stdErr, &retVal, nullptr,
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ if (!result) {
+ err = "The uic test command failed: ";
+ err += QuotedCommand(command);
+ }
} else {
- err += " (";
- err += this->Target->GetName();
- err += ")";
- cmSystemTools::Error(err.c_str());
+ err = "The uic executable ";
+ err += Quoted(this->Uic.Executable);
+ err += " does not exist";
}
}
-}
-void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
- GeneratorT genType)
-{
- // Register source file in makefile
- cmMakefile* makefile = this->Target->Target->GetMakefile();
- {
- cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
- gFile->SetProperty("GENERATED", "1");
- gFile->SetProperty("SKIP_AUTOGEN", "On");
+ // Print error
+ if (!err.empty()) {
+ std::string msg = "AutoUic (";
+ msg += this->Target->GetName();
+ msg += "): ";
+ msg += err;
+ cmSystemTools::Error(msg.c_str());
+ return false;
}
- // Add source file to source group
- AddToSourceGroup(makefile, filename, genType);
-
- // Add source file to target
- this->Target->AddSource(filename);
+ return true;
}
-std::string cmQtAutoGenInitializer::GetQtMajorVersion(
- cmGeneratorTarget const* target)
+bool cmQtAutoGenInitializer::GetRccExecutable()
{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajor.empty()) {
- qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
- }
- const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
- if (targetQtVersion != nullptr) {
- qtMajor = targetQtVersion;
- }
- return qtMajor;
-}
+ std::string err;
-std::string cmQtAutoGenInitializer::GetQtMinorVersion(
- cmGeneratorTarget const* target, std::string const& qtVersionMajor)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMinor;
- if (qtVersionMajor == "5") {
- qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
- }
- if (qtMinor.empty()) {
- qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
+ // Find rcc executable
+ {
+ std::string targetName;
+ if (this->QtVersion.Major == 5) {
+ targetName = "Qt5::rcc";
+ } else if (this->QtVersion.Major == 4) {
+ targetName = "Qt4::rcc";
+ } else {
+ err = "The AUTORCC feature supports only Qt 4 and Qt 5";
+ }
+ if (!targetName.empty()) {
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
+ if (tgt != nullptr) {
+ this->Rcc.Executable = tgt->ImportedGetLocation("");
+ } else {
+ err = "Could not find target " + targetName;
+ }
+ }
}
- const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
- if (targetQtVersion != nullptr) {
- qtMinor = targetQtVersion;
+ // Test rcc command
+ if (err.empty()) {
+ if (cmSystemTools::FileExists(this->Rcc.Executable, true)) {
+ std::vector<std::string> command;
+ command.push_back(this->Rcc.Executable);
+ command.push_back("-h");
+ std::string stdOut;
+ std::string stdErr;
+ int retVal = 0;
+ bool result = cmSystemTools::RunSingleCommand(
+ command, &stdOut, &stdErr, &retVal, nullptr,
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ if (result) {
+ // Detect if rcc supports (-)-list
+ if (this->QtVersion.Major == 5) {
+ if (stdOut.find("--list") != std::string::npos) {
+ this->Rcc.ListOptions.push_back("--list");
+ } else {
+ this->Rcc.ListOptions.push_back("-list");
+ }
+ }
+ } else {
+ err = "The rcc test command failed: ";
+ err += QuotedCommand(command);
+ }
+ } else {
+ err = "The rcc executable ";
+ err += Quoted(this->Rcc.Executable);
+ err += " does not exist";
+ }
}
- return qtMinor;
-}
-bool cmQtAutoGenInitializer::QtVersionGreaterOrEqual(
- unsigned long requestMajor, unsigned long requestMinor) const
-{
- unsigned long majorUL(0);
- unsigned long minorUL(0);
- if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) &&
- cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) {
- return (majorUL > requestMajor) ||
- (majorUL == requestMajor && minorUL >= requestMinor);
+ // Print error
+ if (!err.empty()) {
+ std::string msg = "AutoRcc (";
+ msg += this->Target->GetName();
+ msg += "): ";
+ msg += err;
+ cmSystemTools::Error(msg.c_str());
+ return false;
}
- return false;
+
+ return true;
}
/// @brief Reads the resource files list from from a .qrc file
error += "\n";
return false;
}
- if (!RccListOptions.empty()) {
+ if (!this->Rcc.ListOptions.empty()) {
// Use rcc for file listing
- if (RccExecutable.empty()) {
+ if (this->Rcc.Executable.empty()) {
error = "rcc executable not available";
return false;
}
std::string rccStdErr;
{
std::vector<std::string> cmd;
- cmd.push_back(RccExecutable);
- cmd.insert(cmd.end(), RccListOptions.begin(), RccListOptions.end());
+ cmd.push_back(this->Rcc.Executable);
+ cmd.insert(cmd.end(), this->Rcc.ListOptions.begin(),
+ this->Rcc.ListOptions.end());
cmd.push_back(fileNameName);
result = cmSystemTools::RunSingleCommand(
cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
#include <vector>
class cmGeneratorTarget;
+class cmTarget;
/// @brief Initializes the QtAutoGen generators
class cmQtAutoGenInitializer : public cmQtAutoGen
{
public:
- static std::string GetQtMajorVersion(cmGeneratorTarget const* target);
- static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
- std::string const& qtVersionMajor);
-
/// @brief Rcc job information
class Qrc
{
std::string PathChecksum;
std::string InfoFile;
std::string SettingsFile;
+ std::map<std::string, std::string> ConfigSettingsFile;
std::string RccFile;
bool Generated;
bool Unique;
};
public:
+ static IntegerVersion GetQtVersion(cmGeneratorTarget const* target);
+
cmQtAutoGenInitializer(cmGeneratorTarget* target, bool mocEnabled,
bool uicEnabled, bool rccEnabled,
- std::string const& qtVersionMajor);
+ IntegerVersion const& qtVersion);
- void InitCustomTargets();
- void SetupCustomTargets();
+ bool InitCustomTargets();
+ bool SetupCustomTargets();
private:
- void SetupCustomTargetsMoc();
- void SetupCustomTargetsUic();
+ bool InitMoc();
+ bool InitUic();
+ bool InitRcc();
+
+ bool InitScanFiles();
+ bool InitAutogenTarget();
+ bool InitRccTargets();
+
+ bool SetupWriteAutogenInfo();
+ bool SetupWriteRccInfo();
void AddGeneratedSource(std::string const& filename, GeneratorT genType);
- bool QtVersionGreaterOrEqual(unsigned long requestMajor,
- unsigned long requestMinor) const;
+ bool GetMocExecutable();
+ bool GetUicExecutable();
+ bool GetRccExecutable();
bool RccListInputs(std::string const& fileName,
std::vector<std::string>& files,
private:
cmGeneratorTarget* Target;
- bool MocEnabled;
- bool UicEnabled;
- bool RccEnabled;
- bool MultiConfig;
- // Qt
- std::string QtVersionMajor;
- std::string QtVersionMinor;
- std::string MocExecutable;
- std::string UicExecutable;
- std::string RccExecutable;
- std::vector<std::string> RccListOptions;
- // Configurations
+
+ // Configuration
+ IntegerVersion QtVersion;
+ bool MultiConfig = false;
std::string ConfigDefault;
std::vector<std::string> ConfigsList;
- std::string Parallel;
- // Names
- std::string AutogenTargetName;
- std::string AutogenFolder;
- std::string AutogenInfoFile;
- std::string AutogenSettingsFile;
- // Directories
- std::string DirInfo;
- std::string DirBuild;
- std::string DirWork;
- // Sources
- std::vector<std::string> Headers;
- std::vector<std::string> Sources;
- // Moc
- std::string MocPredefsCmd;
- std::set<std::string> MocSkip;
- std::string MocIncludes;
- std::map<std::string, std::string> MocIncludesConfig;
- std::string MocDefines;
- std::map<std::string, std::string> MocDefinesConfig;
- // Uic
- std::set<std::string> UicSkip;
- std::vector<std::string> UicSearchPaths;
- std::string UicOptions;
- std::map<std::string, std::string> UicOptionsConfig;
- std::vector<std::string> UicFileFiles;
- std::vector<std::vector<std::string>> UicFileOptions;
- // Rcc
- std::vector<Qrc> Qrcs;
+ std::string Verbosity;
+ std::string TargetsFolder;
+
+ /// @brief Common directories
+ struct
+ {
+ std::string Info;
+ std::string Build;
+ std::string Work;
+ std::string Include;
+ std::map<std::string, std::string> ConfigInclude;
+ } Dir;
+
+ /// @brief Autogen target variables
+ struct
+ {
+ std::string Name;
+ // Settings
+ std::string Parallel;
+ // Configuration files
+ std::string InfoFile;
+ std::string SettingsFile;
+ std::map<std::string, std::string> ConfigSettingsFile;
+ // Dependencies
+ std::set<std::string> DependFiles;
+ std::set<cmTarget*> DependTargets;
+ // Sources to process
+ std::vector<std::string> Headers;
+ std::vector<std::string> Sources;
+ std::vector<std::string> HeadersGenerated;
+ std::vector<std::string> SourcesGenerated;
+ } AutogenTarget;
+
+ /// @brief Moc only variables
+ struct
+ {
+ bool Enabled = false;
+ std::string Executable;
+ std::string PredefsCmd;
+ std::set<std::string> Skip;
+ std::string Includes;
+ std::map<std::string, std::string> ConfigIncludes;
+ std::string Defines;
+ std::map<std::string, std::string> ConfigDefines;
+ std::string MocsCompilation;
+ } Moc;
+
+ ///@brief Uic only variables
+ struct
+ {
+ bool Enabled = false;
+ std::string Executable;
+ std::set<std::string> Skip;
+ std::vector<std::string> SearchPaths;
+ std::string Options;
+ std::map<std::string, std::string> ConfigOptions;
+ std::vector<std::string> FileFiles;
+ std::vector<std::vector<std::string>> FileOptions;
+ } Uic;
+
+ /// @brief Rcc only variables
+ struct
+ {
+ bool Enabled = false;
+ std::string Executable;
+ std::vector<std::string> ListOptions;
+ std::vector<Qrc> Qrcs;
+ } Rcc;
};
#endif
// -- Class methods
-void cmQtAutoGenerator::Logger::SetVerbose(bool value)
+void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value)
{
- Verbose_ = value;
+ unsigned long verbosity = 0;
+ if (cmSystemTools::StringToULong(value.c_str(), &verbosity)) {
+ if (this->Verbosity_ < verbosity) {
+ this->Verbosity_ = static_cast<unsigned int>(verbosity);
+ }
+ }
}
void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
: FileSys_(&Logger_)
{
// Initialize logger
- Logger_.SetVerbose(cmSystemTools::HasEnv("VERBOSE"));
+ {
+ std::string verbose;
+ if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
+ unsigned long iVerbose = 0;
+ if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) {
+ Logger_.SetVerbosity(static_cast<unsigned int>(iVerbose));
+ } else {
+ // Non numeric verbosity
+ Logger_.SetVerbose(cmSystemTools::IsOn(verbose));
+ }
+ }
+ }
{
std::string colorEnv;
cmSystemTools::GetEnv("COLOR", colorEnv);
if (!colorEnv.empty()) {
- Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv.c_str()));
+ Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv));
} else {
Logger_.SetColorOutput(true);
}
{
public:
// -- Verbosity
- bool Verbose() const { return this->Verbose_; }
- void SetVerbose(bool value);
+ unsigned int Verbosity() const { return this->Verbosity_; }
+ void SetVerbosity(unsigned int value) { this->Verbosity_ = value; }
+ void RaiseVerbosity(std::string const& value);
+ bool Verbose() const { return (this->Verbosity_ != 0); }
+ void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; }
bool ColorOutput() const { return this->ColorOutput_; }
void SetColorOutput(bool value);
// -- Log info
private:
std::mutex Mutex_;
- bool volatile Verbose_ = false;
- bool volatile ColorOutput_ = false;
+ unsigned int Verbosity_ = 0;
+ bool ColorOutput_ = false;
};
/// @brief Thread safe file system interface
valueConf = makefile->GetDefinition(keyConf);
}
if (valueConf == nullptr) {
- valueConf = makefile->GetSafeDefinition(key);
+ return makefile->GetSafeDefinition(key);
}
return std::string(valueConf);
};
}
// -- Meta
+ Log().RaiseVerbosity(InfoGet("AM_VERBOSITY"));
Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
{
unsigned long num = Base_.NumThreads;
- if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL"), &num)) {
+ if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL").c_str(), &num)) {
num = std::max<unsigned long>(num, 1);
num = std::min<unsigned long>(num, ParallelMax);
Base_.NumThreads = static_cast<unsigned int>(num);
return false;
}
// include directory
- {
- std::string dirRel = InfoGetConfig("AM_INCLUDE_DIR");
- if (dirRel.empty()) {
- Log().ErrorFile(GeneratorT::GEN, InfoFile(),
- "Autogen include directory missing");
- return false;
- }
- Base_.AutogenIncludeDir = Base_.AbsoluteBuildPath(dirRel);
+ Base_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR");
+ if (Base_.AutogenIncludeDir.empty()) {
+ Log().ErrorFile(GeneratorT::GEN, InfoFile(),
+ "Autogen include directory missing");
+ return false;
}
// - Files
// - Qt environment
{
unsigned long qtv = Base_.QtVersionMajor;
- if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"), &qtv)) {
+ if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR").c_str(),
+ &qtv)) {
Base_.QtVersionMajor = static_cast<unsigned int>(qtv);
}
}
valueConf = makefile->GetDefinition(keyConf);
}
if (valueConf == nullptr) {
- valueConf = makefile->GetSafeDefinition(key);
+ return makefile->GetSafeDefinition(key);
}
return std::string(valueConf);
};
}
// - Configurations
+ Log().RaiseVerbosity(InfoGet("ARCC_VERBOSITY"));
MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
// - Directories
// Compute rcc output file name
if (IsMultiConfig()) {
- RccFileOutput_ = AutogenBuildDir_;
- RccFileOutput_ += '/';
- RccFileOutput_ += IncludeDir_;
+ RccFileOutput_ = IncludeDir_;
RccFileOutput_ += '/';
RccFileOutput_ += MultiConfigOutput();
} else {
, NoteDirective("^.. note::[ \t]*(.*)$")
, ModuleRST("^#\\[(=*)\\[\\.rst:$")
, CMakeRole("(:cmake)?:("
- "command|generator|variable|envvar|module|policy|"
+ "command|cpack_gen|generator|variable|envvar|module|policy|"
"prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
"prop_test|prop_tgt|"
"manual"
// Process them all from the current directory
for (std::string const& p : outPaths) {
- this->AddPathInternal(p, this->FC->Makefile->GetCurrentSourceDirectory());
+ this->AddPathInternal(
+ p, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
cmSystemTools::ExpandListArgument(value, expanded);
for (std::string const& p : expanded) {
- this->AddPathInternal(p,
- this->FC->Makefile->GetCurrentSourceDirectory());
+ this->AddPathInternal(
+ p, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
}
std::vector<std::string> expanded;
cmSystemTools::ExpandListArgument(value, expanded);
- this->AddPrefixPaths(expanded,
- this->FC->Makefile->GetCurrentSourceDirectory());
+ this->AddPrefixPaths(
+ expanded, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
#include "cmAlgorithms.h"
#include "cmConnection.h"
#include "cmFileMonitor.h"
+#include "cmJsonObjectDictionary.h"
#include "cmServerDictionary.h"
#include "cmServerProtocol.h"
#include "cmSystemTools.h"
static const std::string kSIGNAL_TYPE = "signal";
static const std::string kCTEST_INFO_TYPE = "ctestInfo";
-static const std::string kARTIFACTS_KEY = "artifacts";
-static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
static const std::string kBUILD_FILES_KEY = "buildFiles";
static const std::string kCACHE_ARGUMENTS_KEY = "cacheArguments";
static const std::string kCACHE_KEY = "cache";
static const std::string kCAPABILITIES_KEY = "capabilities";
static const std::string kCHECK_SYSTEM_VARS_KEY = "checkSystemVars";
static const std::string kCMAKE_ROOT_DIRECTORY_KEY = "cmakeRootDirectory";
-static const std::string kCOMPILE_FLAGS_KEY = "compileFlags";
-static const std::string kCONFIGURATIONS_KEY = "configurations";
static const std::string kCOOKIE_KEY = "cookie";
static const std::string kDEBUG_OUTPUT_KEY = "debugOutput";
-static const std::string kDEFINES_KEY = "defines";
static const std::string kERROR_MESSAGE_KEY = "errorMessage";
static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator";
-static const std::string kFILE_GROUPS_KEY = "fileGroups";
-static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath";
-static const std::string kFULL_NAME_KEY = "fullName";
static const std::string kGENERATOR_KEY = "generator";
-static const std::string kINCLUDE_PATH_KEY = "includePath";
-static const std::string kIS_CMAKE_KEY = "isCMake";
static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental";
-static const std::string kIS_GENERATED_KEY = "isGenerated";
-static const std::string kIS_SYSTEM_KEY = "isSystem";
-static const std::string kIS_TEMPORARY_KEY = "isTemporary";
-static const std::string kKEY_KEY = "key";
static const std::string kKEYS_KEY = "keys";
-static const std::string kLANGUAGE_KEY = "language";
-static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage";
-static const std::string kLINK_FLAGS_KEY = "linkFlags";
-static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags";
-static const std::string kLINK_LIBRARIES_KEY = "linkLibraries";
-static const std::string kLINK_PATH_KEY = "linkPath";
static const std::string kMAJOR_KEY = "major";
static const std::string kMESSAGE_KEY = "message";
static const std::string kMINOR_KEY = "minor";
-static const std::string kNAME_KEY = "name";
-static const std::string kPATH_KEY = "path";
static const std::string kPLATFORM_KEY = "platform";
static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent";
static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum";
static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage";
static const std::string kPROGRESS_MINIMUM_KEY = "progressMinimum";
-static const std::string kPROJECTS_KEY = "projects";
-static const std::string kPROPERTIES_KEY = "properties";
static const std::string kPROTOCOL_VERSION_KEY = "protocolVersion";
static const std::string kREPLY_TO_KEY = "inReplyTo";
-static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
-static const std::string kSOURCES_KEY = "sources";
static const std::string kSUPPORTED_PROTOCOL_VERSIONS =
"supportedProtocolVersions";
-static const std::string kSYSROOT_KEY = "sysroot";
-static const std::string kTARGETS_KEY = "targets";
static const std::string kTITLE_KEY = "title";
static const std::string kTOOLSET_KEY = "toolset";
static const std::string kTRACE_EXPAND_KEY = "traceExpand";
static const std::string kTRACE_KEY = "trace";
-static const std::string kTYPE_KEY = "type";
-static const std::string kVALUE_KEY = "value";
static const std::string kWARN_UNINITIALIZED_KEY = "warnUninitialized";
static const std::string kWARN_UNUSED_CLI_KEY = "warnUnusedCli";
static const std::string kWARN_UNUSED_KEY = "warnUnused";
static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
static const std::string kWATCHED_FILES_KEY = "watchedFiles";
-static const std::string kHAS_INSTALL_RULE = "hasInstallRule";
-static const std::string kINSTALL_PATHS = "installPaths";
-static const std::string kCTEST_NAME = "ctestName";
-static const std::string kCTEST_COMMAND = "ctestCommand";
-static const std::string kCTEST_INFO = "ctestInfo";
-static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion";
-static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided";
static const std::string kSTART_MAGIC = "[== \"CMake Server\" ==[";
static const std::string kEND_MAGIC = "]== \"CMake Server\" ==]";
#include "cmAlgorithms.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmFileMonitor.h"
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
-#include "cmInstallGenerator.h"
-#include "cmInstallTargetGenerator.h"
-#include "cmLinkLineComputer.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmProperty.h"
+#include "cmJsonObjectDictionary.h"
+#include "cmJsonObjects.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 "cmTarget.h"
-#include "cmTest.h"
#include "cm_uv.h"
#include "cmake.h"
#include <algorithm>
#include <cassert>
-#include <cstddef>
#include <functional>
-#include <limits>
-#include <map>
#include <memory>
-#include <set>
#include <string>
-#include <unordered_map>
#include <vector>
// Get rid of some windows macros:
namespace {
-std::vector<std::string> getConfigurations(const cmake* cm)
-{
- std::vector<std::string> configurations;
- auto makefiles = cm->GetGlobalGenerator()->GetMakefiles();
- if (makefiles.empty()) {
- return configurations;
- }
-
- makefiles[0]->GetConfigurations(configurations);
- if (configurations.empty()) {
- configurations.push_back("");
- }
- return configurations;
-}
-
-bool hasString(const Json::Value& v, const std::string& s)
-{
- return !v.isNull() &&
- std::any_of(v.begin(), v.end(),
- [s](const Json::Value& i) { return i.asString() == s; });
-}
-
-template <class T>
-Json::Value fromStringList(const T& in)
-{
- Json::Value result = Json::arrayValue;
- for (std::string const& i : in) {
- result.append(i);
- }
- return result;
-}
-
std::vector<std::string> toStringList(const Json::Value& in)
{
std::vector<std::string> result;
return result;
}
-void getCMakeInputs(const cmGlobalGenerator* gg, const std::string& sourceDir,
- const std::string& buildDir,
- std::vector<std::string>* internalFiles,
- std::vector<std::string>* explicitFiles,
- std::vector<std::string>* tmpFiles)
-{
- const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/';
- std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles();
- for (cmMakefile const* mf : makefiles) {
- for (std::string const& lf : mf->GetListFiles()) {
-
- const std::string startOfFile = lf.substr(0, cmakeRootDir.size());
- const bool isInternal = (startOfFile == cmakeRootDir);
- const bool isTemporary = !isInternal && (lf.find(buildDir + '/') == 0);
-
- std::string toAdd = lf;
- if (!sourceDir.empty()) {
- const std::string& relative =
- cmSystemTools::RelativePath(sourceDir, lf);
- if (toAdd.size() > relative.size()) {
- toAdd = relative;
- }
- }
-
- if (isInternal) {
- if (internalFiles) {
- internalFiles->push_back(std::move(toAdd));
- }
- } else {
- if (isTemporary) {
- if (tmpFiles) {
- tmpFiles->push_back(std::move(toAdd));
- }
- } else {
- if (explicitFiles) {
- explicitFiles->push_back(std::move(toAdd));
- }
- }
- }
- }
- }
-}
-
} // namespace
cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection,
}
const cmake* cm = this->CMakeInstance();
- const cmGlobalGenerator* gg = cm->GetGlobalGenerator();
const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot();
- const std::string& buildDir = cm->GetHomeOutputDirectory();
const std::string& sourceDir = cm->GetHomeDirectory();
Json::Value result = Json::objectValue;
result[kSOURCE_DIRECTORY_KEY] = sourceDir;
result[kCMAKE_ROOT_DIRECTORY_KEY] = cmakeRootDir;
-
- std::vector<std::string> internalFiles;
- std::vector<std::string> explicitFiles;
- std::vector<std::string> tmpFiles;
- getCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles,
- &tmpFiles);
-
- Json::Value array = Json::arrayValue;
-
- Json::Value tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = true;
- tmp[kIS_TEMPORARY_KEY] = false;
- tmp[kSOURCES_KEY] = fromStringList(internalFiles);
- array.append(tmp);
-
- tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = false;
- tmp[kIS_TEMPORARY_KEY] = false;
- tmp[kSOURCES_KEY] = fromStringList(explicitFiles);
- array.append(tmp);
-
- tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = false;
- tmp[kIS_TEMPORARY_KEY] = true;
- tmp[kSOURCES_KEY] = fromStringList(tmpFiles);
- array.append(tmp);
-
- result[kBUILD_FILES_KEY] = array;
-
+ result[kBUILD_FILES_KEY] = cmDumpCMakeInputs(cm);
return request.Reply(result);
}
-class LanguageData
-{
-public:
- bool operator==(const LanguageData& other) const;
-
- void SetDefines(const std::set<std::string>& defines);
-
- bool IsGenerated = false;
- std::string Language;
- std::string Flags;
- std::vector<std::string> Defines;
- std::vector<std::pair<std::string, bool>> IncludePathList;
-};
-
-bool LanguageData::operator==(const LanguageData& other) const
-{
- return Language == other.Language && Defines == other.Defines &&
- Flags == other.Flags && IncludePathList == other.IncludePathList &&
- IsGenerated == other.IsGenerated;
-}
-
-void LanguageData::SetDefines(const std::set<std::string>& defines)
-{
- std::vector<std::string> result;
- result.reserve(defines.size());
- for (std::string const& i : defines) {
- result.push_back(i);
- }
- std::sort(result.begin(), result.end());
- Defines = std::move(result);
-}
-
-namespace std {
-
-template <>
-struct hash<LanguageData>
-{
- std::size_t operator()(const LanguageData& in) const
- {
- using std::hash;
- size_t result =
- hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
- for (auto const& i : in.IncludePathList) {
- result = result ^
- (hash<std::string>()(i.first) ^
- (i.second ? std::numeric_limits<size_t>::max() : 0));
- }
- for (auto const& i : in.Defines) {
- result = result ^ hash<std::string>()(i);
- }
- result =
- result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0);
- return result;
- }
-};
-
-} // namespace std
-
-static Json::Value DumpSourceFileGroup(const LanguageData& data,
- const std::vector<std::string>& files,
- const std::string& baseDir)
-{
- Json::Value result = Json::objectValue;
-
- if (!data.Language.empty()) {
- result[kLANGUAGE_KEY] = data.Language;
- if (!data.Flags.empty()) {
- result[kCOMPILE_FLAGS_KEY] = data.Flags;
- }
- if (!data.IncludePathList.empty()) {
- Json::Value includes = Json::arrayValue;
- for (auto const& i : data.IncludePathList) {
- Json::Value tmp = Json::objectValue;
- tmp[kPATH_KEY] = i.first;
- if (i.second) {
- tmp[kIS_SYSTEM_KEY] = i.second;
- }
- includes.append(tmp);
- }
- result[kINCLUDE_PATH_KEY] = includes;
- }
- if (!data.Defines.empty()) {
- result[kDEFINES_KEY] = fromStringList(data.Defines);
- }
- }
-
- result[kIS_GENERATED_KEY] = data.IsGenerated;
-
- Json::Value sourcesValue = Json::arrayValue;
- for (auto const& i : files) {
- const std::string relPath = cmSystemTools::RelativePath(baseDir, i);
- sourcesValue.append(relPath.size() < i.size() ? relPath : i);
- }
-
- result[kSOURCES_KEY] = sourcesValue;
- return result;
-}
-
-static Json::Value DumpSourceFilesList(
- cmGeneratorTarget* target, const std::string& config,
- const std::map<std::string, LanguageData>& languageDataMap)
-{
- // Collect sourcefile groups:
-
- std::vector<cmSourceFile*> files;
- target->GetSourceFiles(files, config);
-
- std::unordered_map<LanguageData, std::vector<std::string>> fileGroups;
- for (cmSourceFile* file : files) {
- LanguageData fileData;
- fileData.Language = file->GetLanguage();
- if (!fileData.Language.empty()) {
- const LanguageData& ld = languageDataMap.at(fileData.Language);
- cmLocalGenerator* lg = target->GetLocalGenerator();
- cmGeneratorExpressionInterpreter genexInterpreter(
- lg, target, config, target->GetName(), fileData.Language);
-
- std::string compileFlags = ld.Flags;
- const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (const char* cflags = file->GetProperty(COMPILE_FLAGS)) {
- lg->AppendFlags(compileFlags,
- genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
- }
- const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
- if (const char* coptions = file->GetProperty(COMPILE_OPTIONS)) {
- lg->AppendCompileOptions(
- compileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
- }
- fileData.Flags = compileFlags;
-
- // Add include directories from source file properties.
- std::vector<std::string> includes;
-
- const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
- if (const char* cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) {
- const char* evaluatedIncludes =
- genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
- lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file);
-
- for (const auto& include : includes) {
- fileData.IncludePathList.push_back(
- std::make_pair(include,
- target->IsSystemIncludeDirectory(
- include, config, fileData.Language)));
- }
- }
-
- fileData.IncludePathList.insert(fileData.IncludePathList.end(),
- ld.IncludePathList.begin(),
- ld.IncludePathList.end());
-
- const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
- std::set<std::string> defines;
- if (const char* defs = file->GetProperty(COMPILE_DEFINITIONS)) {
- lg->AppendDefines(
- defines, genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS));
- }
-
- const std::string defPropName =
- "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
- if (const char* config_defs = file->GetProperty(defPropName)) {
- lg->AppendDefines(
- defines,
- genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS));
- }
-
- defines.insert(ld.Defines.begin(), ld.Defines.end());
-
- fileData.SetDefines(defines);
- }
-
- fileData.IsGenerated = file->GetPropertyAsBool("GENERATED");
- std::vector<std::string>& groupFileList = fileGroups[fileData];
- groupFileList.push_back(file->GetFullPath());
- }
-
- const std::string baseDir = target->Makefile->GetCurrentSourceDirectory();
- Json::Value result = Json::arrayValue;
- for (auto const& it : fileGroups) {
- Json::Value group = DumpSourceFileGroup(it.first, it.second, baseDir);
- if (!group.isNull()) {
- result.append(group);
- }
- }
-
- return result;
-}
-
-static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo,
- const std::string& config)
-{
- Json::Value result = Json::objectValue;
- result[kCTEST_NAME] = testInfo->GetName();
-
- // Concat command entries together. After the first should be the arguments
- // for the command
- std::string command;
- for (auto const& cmd : testInfo->GetCommand()) {
- command.append(cmd);
- command.append(" ");
- }
-
- // Remove any config specific variables from the output.
- cmGeneratorExpression ge;
- auto cge = ge.Parse(command.c_str());
- const char* processed = cge->Evaluate(lg, config);
-
- result[kCTEST_COMMAND] = processed;
-
- // Build up the list of properties that may have been specified
- Json::Value properties = Json::arrayValue;
- for (auto& prop : testInfo->GetProperties()) {
- Json::Value entry = Json::objectValue;
- entry[kKEY_KEY] = prop.first;
-
- // Remove config variables from the value too.
- auto cge_value = ge.Parse(prop.second.GetValue());
- const char* processed_value = cge_value->Evaluate(lg, config);
- entry[kVALUE_KEY] = processed_value;
- properties.append(entry);
- }
- result[kPROPERTIES_KEY] = properties;
-
- return result;
-}
-
-static void DumpMakefileTests(cmLocalGenerator* lg, const std::string& config,
- Json::Value* result)
-{
- auto mf = lg->GetMakefile();
- std::vector<cmTest*> tests;
- mf->GetTests(config, tests);
- for (auto test : tests) {
- Json::Value tmp = DumpCTestInfo(lg, test, config);
- if (!tmp.isNull()) {
- result->append(tmp);
- }
- }
-}
-
-static Json::Value DumpCTestProjectList(const cmake* cm,
- std::string const& config)
-{
- Json::Value result = Json::arrayValue;
-
- auto globalGen = cm->GetGlobalGenerator();
-
- for (const auto& projectIt : globalGen->GetProjectMap()) {
- Json::Value pObj = Json::objectValue;
- pObj[kNAME_KEY] = projectIt.first;
-
- Json::Value tests = Json::arrayValue;
-
- // Gather tests for every generator
- for (const auto& lg : projectIt.second) {
- // Make sure they're generated.
- lg->GenerateTestFiles();
- DumpMakefileTests(lg, config, &tests);
- }
-
- pObj[kCTEST_INFO] = tests;
-
- result.append(pObj);
- }
-
- return result;
-}
-
-static Json::Value DumpCTestConfiguration(const cmake* cm,
- const std::string& config)
-{
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = config;
-
- result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config);
-
- return result;
-}
-
-static Json::Value DumpCTestConfigurationsList(const cmake* cm)
-{
- Json::Value result = Json::arrayValue;
-
- for (const std::string& c : getConfigurations(cm)) {
- result.append(DumpCTestConfiguration(cm, c));
- }
-
- return result;
-}
-
-static Json::Value DumpTarget(cmGeneratorTarget* target,
- const std::string& config)
-{
- cmLocalGenerator* lg = target->GetLocalGenerator();
- const cmState* state = lg->GetState();
-
- const cmStateEnums::TargetType type = target->GetType();
- const std::string typeName = state->GetTargetTypeName(type);
-
- Json::Value ttl = Json::arrayValue;
- ttl.append("EXECUTABLE");
- ttl.append("STATIC_LIBRARY");
- ttl.append("SHARED_LIBRARY");
- ttl.append("MODULE_LIBRARY");
- ttl.append("OBJECT_LIBRARY");
- ttl.append("UTILITY");
- ttl.append("INTERFACE_LIBRARY");
-
- if (!hasString(ttl, typeName) || target->IsImported()) {
- return Json::Value();
- }
-
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = target->GetName();
- result[kIS_GENERATOR_PROVIDED_KEY] =
- target->Target->GetIsGeneratorProvided();
- result[kTYPE_KEY] = typeName;
- result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory();
- result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory();
-
- if (type == cmStateEnums::INTERFACE_LIBRARY) {
- return result;
- }
-
- result[kFULL_NAME_KEY] = target->GetFullName(config);
-
- if (target->Target->GetHaveInstallRule()) {
- result[kHAS_INSTALL_RULE] = true;
-
- Json::Value installPaths = Json::arrayValue;
- auto targetGenerators = target->Makefile->GetInstallGenerators();
- for (auto installGenerator : targetGenerators) {
- auto installTargetGenerator =
- dynamic_cast<cmInstallTargetGenerator*>(installGenerator);
- if (installTargetGenerator != nullptr &&
- installTargetGenerator->GetTarget()->Target == target->Target) {
- auto dest = installTargetGenerator->GetDestination(config);
-
- std::string installPath;
- if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) {
- installPath = dest;
- } else {
- std::string installPrefix =
- target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
- installPath = installPrefix + '/' + dest;
- }
-
- installPaths.append(installPath);
- }
- }
-
- result[kINSTALL_PATHS] = installPaths;
- }
-
- if (target->HaveWellDefinedOutputFiles()) {
- Json::Value artifacts = Json::arrayValue;
- artifacts.append(
- target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
- if (target->IsDLLPlatform()) {
- artifacts.append(
- target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
- const cmGeneratorTarget::OutputInfo* output =
- target->GetOutputInfo(config);
- if (output && !output->PdbDir.empty()) {
- artifacts.append(output->PdbDir + '/' + target->GetPDBName(config));
- }
- }
- result[kARTIFACTS_KEY] = artifacts;
-
- result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config);
-
- std::string linkLibs;
- std::string linkFlags;
- std::string linkLanguageFlags;
- std::string frameworkPath;
- std::string linkPath;
- cmLinkLineComputer linkLineComputer(lg,
- lg->GetStateSnapshot().GetDirectory());
- lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
- linkFlags, frameworkPath, linkPath, target);
-
- linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
- linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
- linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
- frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
- linkPath = cmSystemTools::TrimWhitespace(linkPath);
-
- if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) {
- result[kLINK_LIBRARIES_KEY] = linkLibs;
- }
- if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) {
- result[kLINK_FLAGS_KEY] = linkFlags;
- }
- if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) {
- result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
- }
- if (!frameworkPath.empty()) {
- result[kFRAMEWORK_PATH_KEY] = frameworkPath;
- }
- if (!linkPath.empty()) {
- result[kLINK_PATH_KEY] = linkPath;
- }
- const std::string sysroot =
- lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT");
- if (!sysroot.empty()) {
- result[kSYSROOT_KEY] = sysroot;
- }
- }
-
- std::set<std::string> languages;
- target->GetLanguages(languages, config);
- std::map<std::string, LanguageData> languageDataMap;
- for (std::string const& lang : languages) {
- LanguageData& ld = languageDataMap[lang];
- ld.Language = lang;
- lg->GetTargetCompileFlags(target, config, lang, ld.Flags);
- std::set<std::string> defines;
- lg->GetTargetDefines(target, config, lang, defines);
- ld.SetDefines(defines);
- std::vector<std::string> includePathList;
- lg->GetIncludeDirectories(includePathList, target, lang, config, true);
- for (std::string const& i : includePathList) {
- ld.IncludePathList.push_back(
- std::make_pair(i, target->IsSystemIncludeDirectory(i, config, lang)));
- }
- }
-
- Json::Value sourceGroupsValue =
- DumpSourceFilesList(target, config, languageDataMap);
- if (!sourceGroupsValue.empty()) {
- result[kFILE_GROUPS_KEY] = sourceGroupsValue;
- }
-
- return result;
-}
-
-static Json::Value DumpTargetsList(
- const std::vector<cmLocalGenerator*>& generators, const std::string& config)
-{
- Json::Value result = Json::arrayValue;
-
- std::vector<cmGeneratorTarget*> targetList;
- for (auto const& lgIt : generators) {
- const auto& list = lgIt->GetGeneratorTargets();
- targetList.insert(targetList.end(), list.begin(), list.end());
- }
- std::sort(targetList.begin(), targetList.end());
-
- for (cmGeneratorTarget* target : targetList) {
- Json::Value tmp = DumpTarget(target, config);
- if (!tmp.isNull()) {
- result.append(tmp);
- }
- }
-
- return result;
-}
-
-static Json::Value DumpProjectList(const cmake* cm, std::string const& config)
-{
- Json::Value result = Json::arrayValue;
-
- auto globalGen = cm->GetGlobalGenerator();
-
- for (auto const& projectIt : globalGen->GetProjectMap()) {
- Json::Value pObj = Json::objectValue;
- pObj[kNAME_KEY] = projectIt.first;
-
- // All Projects must have at least one local generator
- assert(!projectIt.second.empty());
- const cmLocalGenerator* lg = projectIt.second.at(0);
-
- // Project structure information:
- const cmMakefile* mf = lg->GetMakefile();
- auto minVersion = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
- pObj[kMINIMUM_CMAKE_VERSION] = minVersion ? minVersion : "";
- pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
- pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
- pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
-
- // For a project-level install rule it might be defined in any of its
- // associated generators.
- bool hasInstallRule = false;
- for (const auto generator : projectIt.second) {
- hasInstallRule =
- generator->GetMakefile()->GetInstallGenerators().empty() == false;
-
- if (hasInstallRule) {
- break;
- }
- }
-
- pObj[kHAS_INSTALL_RULE] = hasInstallRule;
-
- result.append(pObj);
- }
-
- return result;
-}
-
-static Json::Value DumpConfiguration(const cmake* cm,
- const std::string& config)
-{
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = config;
-
- result[kPROJECTS_KEY] = DumpProjectList(cm, config);
-
- return result;
-}
-
-static Json::Value DumpConfigurationsList(const cmake* cm)
-{
- Json::Value result = Json::arrayValue;
-
- for (std::string const& c : getConfigurations(cm)) {
- result.append(DumpConfiguration(cm, c));
- }
-
- return result;
-}
-
cmServerResponse cmServerProtocol1::ProcessCodeModel(
const cmServerRequest& request)
{
return request.ReportError("No build system was generated yet.");
}
- Json::Value result = Json::objectValue;
- result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(this->CMakeInstance());
- return request.Reply(result);
+ return request.Reply(cmDumpCodeModel(this->CMakeInstance()));
}
cmServerResponse cmServerProtocol1::ProcessCompute(
if (cm->LoadCache(buildDir)) {
// build directory has been set up before
- const char* cachedSourceDir =
+ const std::string* cachedSourceDir =
cm->GetState()->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
if (!cachedSourceDir) {
return request.ReportError("No CMAKE_HOME_DIRECTORY found in cache.");
}
if (sourceDir.empty()) {
- sourceDir = std::string(cachedSourceDir);
+ sourceDir = *cachedSourceDir;
cm->SetHomeDirectory(sourceDir);
}
- const char* cachedGenerator =
+ const std::string* cachedGenerator =
cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR");
if (cachedGenerator) {
- if (gg && gg->GetName() != cachedGenerator) {
+ if (gg && gg->GetName() != *cachedGenerator) {
return request.ReportError("Configured generator does not match with "
"CMAKE_GENERATOR found in cache.");
}
}
std::vector<std::string> toWatchList;
- getCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList, nullptr);
+ cmGetCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList,
+ nullptr);
FileMonitor()->MonitorPaths(toWatchList,
[this](const std::string& p, int e, int s) {
return request.ReportError("This instance was not yet computed.");
}
- Json::Value result = Json::objectValue;
- result[kCONFIGURATIONS_KEY] =
- DumpCTestConfigurationsList(this->CMakeInstance());
- return request.Reply(result);
+ return request.Reply(cmDumpCTestInfo(this->CMakeInstance()));
}
cmServerProtocol1::GeneratorInformation::GeneratorInformation(
bool cmSetPropertyCommand::HandleCacheMode()
{
if (this->PropertyName == "ADVANCED") {
- if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue.c_str()) &&
- !cmSystemTools::IsOff(this->PropertyValue.c_str())) {
+ if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue) &&
+ !cmSystemTools::IsOff(this->PropertyValue)) {
std::ostringstream e;
e << "given non-boolean value \"" << this->PropertyValue
<< "\" for CACHE property \"ADVANCED\". ";
propertyPairs.push_back(*j);
if (*j == "GENERATED") {
++j;
- if (j != propend && cmSystemTools::IsOn(j->c_str())) {
+ if (j != propend && cmSystemTools::IsOn(*j)) {
generated = true;
}
} else {
}
#else
// try to find the hostname for this computer
- if (!cmSystemTools::IsOff(hostname_cmd.c_str())) {
+ if (!cmSystemTools::IsOff(hostname_cmd)) {
std::string host;
cmSystemTools::RunSingleCommand(hostname_cmd.c_str(), &host, nullptr,
nullptr, nullptr,
cmMakefile const* mf = this->Location.GetMakefile();
const char* tryDirs[3] = { nullptr, nullptr, nullptr };
if (this->Location.DirectoryIsAmbiguous()) {
- tryDirs[0] = mf->GetCurrentSourceDirectory();
- tryDirs[1] = mf->GetCurrentBinaryDirectory();
+ tryDirs[0] = mf->GetCurrentSourceDirectory().c_str();
+ tryDirs[1] = mf->GetCurrentBinaryDirectory().c_str();
} else {
tryDirs[0] = "";
}
return retVal;
}
+const char* cmSourceFile::GetSafeProperty(const std::string& prop) const
+{
+ const char* ret = this->GetProperty(prop);
+ if (!ret) {
+ return "";
+ }
+ return ret;
+}
+
bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const
{
return cmSystemTools::IsOn(this->GetProperty(prop));
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
+ ///! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
+ ///! Always returns a valid pointer
+ const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
/** Implement getting a property when called from a CMake language
}
} else if (this->AmbiguousDirectory) {
// Compare possible directory combinations.
- std::string const& srcDir = cmSystemTools::CollapseFullPath(
+ std::string const srcDir = cmSystemTools::CollapseFullPath(
this->Directory, this->Makefile->GetCurrentSourceDirectory());
- std::string const& binDir = cmSystemTools::CollapseFullPath(
+ std::string const binDir = cmSystemTools::CollapseFullPath(
this->Directory, this->Makefile->GetCurrentBinaryDirectory());
if (srcDir != loc.Directory && binDir != loc.Directory) {
return false;
}
} else if (loc.AmbiguousDirectory) {
// Compare possible directory combinations.
- std::string const& srcDir = cmSystemTools::CollapseFullPath(
+ std::string const srcDir = cmSystemTools::CollapseFullPath(
loc.Directory, loc.Makefile->GetCurrentSourceDirectory());
- std::string const& binDir = cmSystemTools::CollapseFullPath(
+ std::string const binDir = cmSystemTools::CollapseFullPath(
loc.Directory, loc.Makefile->GetCurrentBinaryDirectory());
if (srcDir != this->Directory && binDir != this->Directory) {
return false;
return e->Value.c_str();
}
-const char* cmState::GetInitializedCacheValue(std::string const& key) const
+const std::string* cmState::GetInitializedCacheValue(
+ std::string const& key) const
{
return this->CacheManager->GetInitializedCacheValue(key);
}
it->CompileDefinitionsBacktraces.clear();
it->CompileOptions.clear();
it->CompileOptionsBacktraces.clear();
+ it->LinkOptions.clear();
+ it->LinkOptionsBacktraces.clear();
+ it->LinkDirectories.clear();
+ it->LinkDirectoriesBacktraces.clear();
it->DirectoryEnd = pos;
it->NormalTargetNames.clear();
it->Properties.clear();
{
std::string srcDir =
- cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
+ *cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
std::string binDir =
- cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
+ *cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
this->VarTree.Clear();
pos->Vars = this->VarTree.Push(this->VarTree.Root());
pos->Parent = this->VarTree.Root();
pos->IncludeDirectoryPosition = 0;
pos->CompileDefinitionsPosition = 0;
pos->CompileOptionsPosition = 0;
+ pos->LinkOptionsPosition = 0;
+ pos->LinkDirectoriesPosition = 0;
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->Policies = this->PolicyStack.Root();
pos->PolicyRoot = this->PolicyStack.Root();
prevPos->BuildSystemDirectory->CompileDefinitions.size();
prevPos->CompileOptionsPosition =
prevPos->BuildSystemDirectory->CompileOptions.size();
+ prevPos->LinkOptionsPosition =
+ prevPos->BuildSystemDirectory->LinkOptions.size();
+ prevPos->LinkDirectoriesPosition =
+ prevPos->BuildSystemDirectory->LinkDirectories.size();
prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
std::vector<std::string> GetCacheEntryKeys() const;
const char* GetCacheEntryValue(std::string const& key) const;
- const char* GetInitializedCacheValue(std::string const& key) const;
+ const std::string* GetInitializedCacheValue(std::string const& key) const;
cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) const;
void SetCacheEntryValue(std::string const& key, std::string const& value);
void SetCacheValue(std::string const& key, std::string const& value);
}
}
-const char* cmStateDirectory::GetCurrentSource() const
+std::string const& cmStateDirectory::GetCurrentSource() const
{
- return this->DirectoryState->Location.c_str();
+ return this->DirectoryState->Location;
}
void cmStateDirectory::SetCurrentSource(std::string const& dir)
this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR", loc);
}
-const char* cmStateDirectory::GetCurrentBinary() const
+std::string const& cmStateDirectory::GetCurrentBinary() const
{
- return this->DirectoryState->OutputLocation.c_str();
+ return this->DirectoryState->OutputLocation;
}
void cmStateDirectory::SetCurrentBinary(std::string const& dir)
this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR", loc);
}
-const char* cmStateDirectory::GetRelativePathTopSource() const
+std::string const& cmStateDirectory::GetRelativePathTopSource() const
{
- return this->DirectoryState->RelativePathTopSource.c_str();
+ return this->DirectoryState->RelativePathTopSource;
}
-const char* cmStateDirectory::GetRelativePathTopBinary() const
+std::string const& cmStateDirectory::GetRelativePathTopBinary() const
{
- return this->DirectoryState->RelativePathTopBinary.c_str();
+ return this->DirectoryState->RelativePathTopBinary;
}
void cmStateDirectory::SetRelativePathTopSource(const char* dir)
this->Snapshot_.Position->CompileOptionsPosition);
}
+cmStringRange cmStateDirectory::GetLinkOptionsEntries() const
+{
+ return GetPropertyContent(this->DirectoryState->LinkOptions,
+ this->Snapshot_.Position->LinkOptionsPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetLinkOptionsEntryBacktraces() const
+{
+ return GetPropertyBacktraces(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition);
+}
+
+void cmStateDirectory::AppendLinkOptionsEntry(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::SetLinkOptions(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearLinkOptions()
+{
+ ClearContent(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition);
+}
+
+cmStringRange cmStateDirectory::GetLinkDirectoriesEntries() const
+{
+ return GetPropertyContent(this->DirectoryState->LinkDirectories,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetLinkDirectoriesEntryBacktraces() const
+{
+ return GetPropertyBacktraces(
+ this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
+void cmStateDirectory::AppendLinkDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+}
+void cmStateDirectory::PrependLinkDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ std::vector<std::string>::iterator entryEnd =
+ this->DirectoryState->LinkDirectories.begin() +
+ this->Snapshot_.Position->LinkDirectoriesPosition;
+
+ std::vector<std::string>::reverse_iterator rend =
+ this->DirectoryState->LinkDirectories.rend();
+ std::vector<std::string>::reverse_iterator rbegin =
+ cmMakeReverseIterator(entryEnd);
+ rbegin = std::find(rbegin, rend, cmPropertySentinal);
+
+ std::vector<std::string>::iterator entryIt = rbegin.base();
+ std::vector<std::string>::iterator entryBegin =
+ this->DirectoryState->LinkDirectories.begin();
+
+ std::vector<cmListFileBacktrace>::iterator btIt =
+ this->DirectoryState->LinkDirectoriesBacktraces.begin() +
+ std::distance(entryBegin, entryIt);
+
+ this->DirectoryState->LinkDirectories.insert(entryIt, vec);
+ this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt);
+
+ this->Snapshot_.Position->LinkDirectoriesPosition =
+ this->DirectoryState->LinkDirectories.size();
+}
+
+void cmStateDirectory::SetLinkDirectories(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearLinkDirectories()
+{
+ ClearContent(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
cmListFileBacktrace const& lfbt)
{
this->SetCompileDefinitions(value, lfbt);
return;
}
+ if (prop == "LINK_OPTIONS") {
+ if (!value) {
+ this->ClearLinkOptions();
+ return;
+ }
+ this->SetLinkOptions(value, lfbt);
+ return;
+ }
+ if (prop == "LINK_DIRECTORIES") {
+ if (!value) {
+ this->ClearLinkDirectories();
+ return;
+ }
+ this->SetLinkDirectories(value, lfbt);
+ return;
+ }
this->DirectoryState->Properties.SetProperty(prop, value);
}
this->AppendCompileDefinitionsEntry(value, lfbt);
return;
}
+ if (prop == "LINK_OPTIONS") {
+ this->AppendLinkOptionsEntry(value, lfbt);
+ return;
+ }
+ if (prop == "LINK_DIRECTORIES") {
+ this->AppendLinkDirectoriesEntry(value, lfbt);
+ return;
+ }
this->DirectoryState->Properties.AppendProperty(prop, value, asString);
}
if (prop == "PARENT_DIRECTORY") {
cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
if (parent.IsValid()) {
- return parent.GetDirectory().GetCurrentSource();
+ return parent.GetDirectory().GetCurrentSource().c_str();
}
return "";
}
output = cmJoin(this->GetCompileDefinitionsEntries(), ";");
return output.c_str();
}
+ if (prop == "LINK_OPTIONS") {
+ output = cmJoin(this->GetLinkOptionsEntries(), ";");
+ return output.c_str();
+ }
+ if (prop == "LINK_DIRECTORIES") {
+ output = cmJoin(this->GetLinkDirectoriesEntries(), ";");
+ return output.c_str();
+ }
const char* retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
if (!retVal && chain) {
cmStateSnapshot const& snapshot);
public:
- const char* GetCurrentSource() const;
+ std::string const& GetCurrentSource() const;
void SetCurrentSource(std::string const& dir);
- const char* GetCurrentBinary() const;
+ std::string const& GetCurrentBinary() const;
void SetCurrentBinary(std::string const& dir);
- const char* GetRelativePathTopSource() const;
- const char* GetRelativePathTopBinary() const;
+ std::string const& GetRelativePathTopSource() const;
+ std::string const& GetRelativePathTopBinary() const;
void SetRelativePathTopSource(const char* dir);
void SetRelativePathTopBinary(const char* dir);
cmListFileBacktrace const& lfbt);
void ClearCompileOptions();
+ cmStringRange GetLinkOptionsEntries() const;
+ cmBacktraceRange GetLinkOptionsEntryBacktraces() const;
+ void AppendLinkOptionsEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void PrependLinkDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt);
+ void ClearLinkOptions();
+
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesEntryBacktraces() const;
+ void AppendLinkDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetLinkDirectories(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void ClearLinkDirectories();
+
void SetProperty(const std::string& prop, const char* value,
cmListFileBacktrace const& lfbt);
void AppendProperty(const std::string& prop, const char* value,
std::vector<std::string>::size_type IncludeDirectoryPosition;
std::vector<std::string>::size_type CompileDefinitionsPosition;
std::vector<std::string>::size_type CompileOptionsPosition;
+ std::vector<std::string>::size_type LinkOptionsPosition;
+ std::vector<std::string>::size_type LinkDirectoriesPosition;
};
struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap
std::vector<std::string> CompileOptions;
std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
+ std::vector<std::string> LinkOptions;
+ std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
+
+ std::vector<std::string> LinkDirectories;
+ std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
+
std::vector<std::string> NormalTargetNames;
std::string ProjectName;
return !this->Position->Policies->IsEmpty();
}
-const char* cmStateSnapshot::GetDefinition(std::string const& name) const
+std::string const* cmStateSnapshot::GetDefinition(
+ std::string const& name) const
{
assert(this->Position->Vars.IsValid());
return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
this->Position->BuildSystemDirectory->CompileOptionsBacktraces,
this->Position->CompileOptionsPosition);
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->LinkOptions,
+ this->Position->BuildSystemDirectory->LinkOptions,
+ parent->BuildSystemDirectory->LinkOptionsBacktraces,
+ this->Position->BuildSystemDirectory->LinkOptionsBacktraces,
+ this->Position->LinkOptionsPosition);
+
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->LinkDirectories,
+ this->Position->BuildSystemDirectory->LinkDirectories,
+ parent->BuildSystemDirectory->LinkDirectoriesBacktraces,
+ this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces,
+ this->Position->LinkDirectoriesPosition);
+
const char* include_regex =
parent->BuildSystemDirectory->Properties.GetPropertyValue(
"INCLUDE_REGULAR_EXPRESSION");
void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand()
{
- std::string currentSrcDir = this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR");
- std::string currentBinDir = this->GetDefinition("CMAKE_CURRENT_BINARY_DIR");
+ std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR");
+ std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR");
this->InitializeFromParent();
this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
cmStateSnapshot(cmState* state = nullptr);
cmStateSnapshot(cmState* state, cmStateDetail::PositionType position);
- const char* GetDefinition(std::string const& name) const;
+ std::string const* GetDefinition(std::string const& name) const;
bool IsInitialized(std::string const& name) const;
void SetDefinition(std::string const& name, std::string const& value);
void RemoveDefinition(std::string const& name);
// Scan through the input for all matches.
std::string output;
- if (re.find(input.c_str())) {
+ if (re.find(input)) {
this->Makefile->StoreMatches(re);
std::string::size_type l = re.start();
std::string::size_type r = re.end();
// if they specified a relative path then compute the full
std::string srcPath =
- std::string(this->Makefile->GetCurrentSourceDirectory()) + "/" + i;
+ this->Makefile->GetCurrentSourceDirectory() + "/" + i;
if (cmSystemTools::FileIsDirectory(srcPath)) {
std::string binPath =
- std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" + i;
+ this->Makefile->GetCurrentBinaryDirectory() + "/" + i;
this->Makefile->AddSubDirectory(srcPath, binPath, excludeFromAll, false);
}
// otherwise it is a full path
else if (cmSystemTools::FileIsDirectory(i)) {
// we must compute the binPath from the srcPath, we just take the last
// element from the source path and use that
- std::string binPath =
- std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" +
+ std::string binPath = this->Makefile->GetCurrentBinaryDirectory() + "/" +
cmSystemTools::GetFilenameName(i);
this->Makefile->AddSubDirectory(i, binPath, excludeFromAll, false);
} else {
#include "cmDuration.h"
#include "cmProcessOutput.h"
#include "cm_sys_stat.h"
+#include "cm_uv.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmArchiveWrite.h"
#include <ctype.h>
#include <errno.h>
#include <iostream>
-#include <set>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
# include <wincrypt.h>
# include <fcntl.h> /* _O_TEXT */
-
-# include "cm_uv.h"
#else
# include <sys/time.h>
# include <unistd.h>
if (!val) {
return false;
}
- size_t len = strlen(val);
- if (len > 4) {
- return false;
+ /* clang-format off */
+ // "1"
+ if (val[0] == '1' && val[1] == '\0') {
+ return true;
}
- std::string v(val, len);
-
- static std::set<std::string> onValues;
- if (onValues.empty()) {
- onValues.insert("ON");
- onValues.insert("1");
- onValues.insert("YES");
- onValues.insert("TRUE");
- onValues.insert("Y");
+ // "ON"
+ if ((val[0] == 'O' || val[0] == 'o') &&
+ (val[1] == 'N' || val[1] == 'n') && val[2] == '\0') {
+ return true;
}
- for (char& c : v) {
- c = static_cast<char>(toupper(c));
+ // "Y", "YES"
+ if ((val[0] == 'Y' || val[0] == 'y') && (val[1] == '\0' || (
+ (val[1] == 'E' || val[1] == 'e') &&
+ (val[2] == 'S' || val[2] == 's') && val[3] == '\0'))) {
+ return true;
+ }
+ // "TRUE"
+ if ((val[0] == 'T' || val[0] == 't') &&
+ (val[1] == 'R' || val[1] == 'r') &&
+ (val[2] == 'U' || val[2] == 'u') &&
+ (val[3] == 'E' || val[3] == 'e') && val[4] == '\0') {
+ return true;
}
- return (onValues.count(v) > 0);
+ /* clang-format on */
+ return false;
+}
+
+bool cmSystemTools::IsOn(const std::string& val)
+{
+ return cmSystemTools::IsOn(val.c_str());
}
bool cmSystemTools::IsNOTFOUND(const char* val)
bool cmSystemTools::IsOff(const char* val)
{
- if (!val || !*val) {
+ // ""
+ if (!val || val[0] == '\0') {
return true;
}
- size_t len = strlen(val);
- // Try and avoid toupper() for large strings.
- if (len > 6) {
- return cmSystemTools::IsNOTFOUND(val);
+ /* clang-format off */
+ // "0"
+ if (val[0] == '0' && val[1] == '\0') {
+ return true;
}
-
- static std::set<std::string> offValues;
- if (offValues.empty()) {
- offValues.insert("OFF");
- offValues.insert("0");
- offValues.insert("NO");
- offValues.insert("FALSE");
- offValues.insert("N");
- offValues.insert("IGNORE");
+ // "OFF"
+ if ((val[0] == 'O' || val[0] == 'o') &&
+ (val[1] == 'F' || val[1] == 'f') &&
+ (val[2] == 'F' || val[2] == 'f') && val[3] == '\0') {
+ return true;
}
- // Try and avoid toupper().
- std::string v(val, len);
- for (char& c : v) {
- c = static_cast<char>(toupper(c));
+ // "N", "NO"
+ if ((val[0] == 'N' || val[0] == 'n') && (val[1] == '\0' || (
+ (val[1] == 'O' || val[1] == 'o') && val[2] == '\0'))) {
+ return true;
}
- return (offValues.count(v) > 0);
+ // "FALSE"
+ if ((val[0] == 'F' || val[0] == 'f') &&
+ (val[1] == 'A' || val[1] == 'a') &&
+ (val[2] == 'L' || val[2] == 'l') &&
+ (val[3] == 'S' || val[3] == 's') &&
+ (val[4] == 'E' || val[4] == 'e') && val[5] == '\0') {
+ return true;
+ }
+ // "IGNORE"
+ if ((val[0] == 'I' || val[0] == 'i') &&
+ (val[1] == 'G' || val[1] == 'g') &&
+ (val[2] == 'N' || val[2] == 'n') &&
+ (val[3] == 'O' || val[3] == 'o') &&
+ (val[4] == 'R' || val[4] == 'r') &&
+ (val[5] == 'E' || val[5] == 'e') && val[6] == '\0') {
+ return true;
+ }
+ /* clang-format on */
+ return cmSystemTools::IsNOTFOUND(val);
+}
+
+bool cmSystemTools::IsOff(const std::string& val)
+{
+ return cmSystemTools::IsOff(val.c_str());
}
void cmSystemTools::ParseWindowsCommandLine(const char* command,
// 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
+ // address where the dynamic 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
+ // calculated address. This may cause the dynamic 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
*value = strtoul(str, &endp, 10);
return (*endp == '\0') && (endp != str) && (errno == 0);
}
+
+bool cmSystemTools::CreateSymlink(const std::string& origName,
+ const std::string& newName)
+{
+ uv_fs_t req;
+ int flags = 0;
+#if defined(_WIN32)
+ if (cmsys::SystemTools::FileIsDirectory(origName)) {
+ flags |= UV_FS_SYMLINK_DIR;
+ }
+#endif
+ int err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(),
+ flags, nullptr);
+ if (err) {
+ std::string e =
+ "failed to create symbolic link '" + newName + "': " + uv_strerror(err);
+ cmSystemTools::Error(e.c_str());
+ return false;
+ }
+
+ return true;
+}
* as ifdef.
*/
static bool IsOn(const char* val);
+ static bool IsOn(const std::string& val);
/**
* does a string indicate a false or off value ? Note that this is
* NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
*/
static bool IsOff(const char* val);
+ static bool IsOff(const std::string& val);
///! Return true if value is NOTFOUND or ends in -NOTFOUND.
static bool IsNOTFOUND(const char* value);
/** Perform one-time initialization of libuv. */
static void InitializeLibUV();
+ /** Create a symbolic link if the platform supports it. Returns whether
+ creation succeeded. */
+ static bool CreateSymlink(const std::string& origName,
+ const std::string& newName);
+
private:
static bool s_ForceUnixPaths;
static bool s_RunCommandHideConsole;
std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
std::vector<std::string> SourceEntries;
std::vector<cmListFileBacktrace> SourceBacktraces;
+ std::vector<std::string> LinkOptionsEntries;
+ std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
+ std::vector<std::string> LinkDirectoriesEntries;
+ std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
std::vector<std::string> LinkImplementationPropertyEntries;
std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
};
// Check whether this is a DLL platform.
this->DLLPlatform =
- strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
- "") != 0;
+ !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
// Check whether we are targeting an Android platform.
this->IsAndroid =
- strcmp(this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"),
- "Android") == 0;
+ (this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
// Setup default property values.
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr);
this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr);
this->SetPropertyDefault("FOLDER", nullptr);
+#ifdef __APPLE__
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ this->SetPropertyDefault("XCODE_SCHEME_ADDRESS_SANITIZER", nullptr);
+ this->SetPropertyDefault(
+ "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_THREAD_SANITIZER", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_THREAD_SANITIZER_STOP", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER",
+ nullptr);
+ this->SetPropertyDefault(
+ "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER",
+ nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP",
+ nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_MALLOC_SCRIBBLE", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_MALLOC_GUARD_EDGES", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_GUARD_MALLOC", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_ZOMBIE_OBJECTS", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_MALLOC_STACK", nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE",
+ nullptr);
+ this->SetPropertyDefault("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS", nullptr);
+ }
+#endif
}
// Collect the set of configuration types.
this->SystemIncludeDirectories.insert(parentSystemIncludes.begin(),
parentSystemIncludes.end());
- const cmStringRange parentOptions =
+ const cmStringRange parentCompileOptions =
this->Makefile->GetCompileOptionsEntries();
- const cmBacktraceRange parentOptionsBts =
+ const cmBacktraceRange parentCompileOptionsBts =
this->Makefile->GetCompileOptionsBacktraces();
this->Internal->CompileOptionsEntries.insert(
- this->Internal->CompileOptionsEntries.end(), parentOptions.begin(),
- parentOptions.end());
+ this->Internal->CompileOptionsEntries.end(),
+ parentCompileOptions.begin(), parentCompileOptions.end());
this->Internal->CompileOptionsBacktraces.insert(
- this->Internal->CompileOptionsBacktraces.end(), parentOptionsBts.begin(),
- parentOptionsBts.end());
+ this->Internal->CompileOptionsBacktraces.end(),
+ parentCompileOptionsBts.begin(), parentCompileOptionsBts.end());
+
+ const cmStringRange parentLinkOptions =
+ this->Makefile->GetLinkOptionsEntries();
+ const cmBacktraceRange parentLinkOptionsBts =
+ this->Makefile->GetLinkOptionsBacktraces();
+
+ this->Internal->LinkOptionsEntries.insert(
+ this->Internal->LinkOptionsEntries.end(), parentLinkOptions.begin(),
+ parentLinkOptions.end());
+ this->Internal->LinkOptionsBacktraces.insert(
+ this->Internal->LinkOptionsBacktraces.end(),
+ parentLinkOptionsBts.begin(), parentLinkOptionsBts.end());
+
+ const cmStringRange parentLinkDirectories =
+ this->Makefile->GetLinkDirectoriesEntries();
+ const cmBacktraceRange parentLinkDirectoriesBts =
+ this->Makefile->GetLinkDirectoriesBacktraces();
+
+ this->Internal->LinkDirectoriesEntries.insert(
+ this->Internal->LinkDirectoriesEntries.end(),
+ parentLinkDirectories.begin(), parentLinkDirectories.end());
+ this->Internal->LinkDirectoriesBacktraces.insert(
+ this->Internal->LinkDirectoriesBacktraces.end(),
+ parentLinkDirectoriesBts.begin(), parentLinkDirectoriesBts.end());
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
if (this->TargetTypeValue <= cmStateEnums::UTILITY) {
this->SetPropertyDefault("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr);
}
+
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ this->GetType() != cmStateEnums::UTILITY) {
+
+ // check for "CMAKE_VS_GLOBALS" variable and set up target properties
+ // if any
+ const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
+ if (globals) {
+ const std::string genName = mf->GetGlobalGenerator()->GetName();
+ if (cmHasLiteralPrefix(genName, "Visual Studio")) {
+ std::vector<std::string> props;
+ cmSystemTools::ExpandListArgument(globals, props);
+ const std::string vsGlobal = "VS_GLOBAL_";
+ for (const std::string& i : props) {
+ // split NAME=VALUE
+ const std::string::size_type assignment = i.find('=');
+ if (assignment != std::string::npos) {
+ const std::string propName = vsGlobal + i.substr(0, assignment);
+ const std::string propValue = i.substr(assignment + 1);
+ this->SetPropertyDefault(propName, propValue.c_str());
+ }
+ }
+ }
+ }
+ }
}
cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
std::string srcFiles;
const char* sep = "";
for (auto filename : srcs) {
- const char* src = filename.c_str();
-
- if (!(src[0] == '$' && src[1] == '<')) {
+ if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
if (!filename.empty()) {
filename = this->ProcessSourceItemCMP0049(filename);
if (filename.empty()) {
cmSourceFileLocationKind::Known);
}
-void cmTarget::AddLinkDirectory(const std::string& d)
-{
- // Make sure we don't add unnecessary search directories.
- if (this->LinkDirectoriesEmmitted.insert(d).second) {
- this->LinkDirectories.push_back(d);
- }
-}
-
-const std::vector<std::string>& cmTarget::GetLinkDirectories() const
-{
- return this->LinkDirectories;
-}
-
void cmTarget::ClearDependencyInformation(cmMakefile& mf)
{
std::string depname = this->GetName();
void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt)
{
- cmTarget* tgt = this->Makefile->FindTargetToUse(lib);
+ this->AddLinkLibrary(mf, lib, lib, llt);
+}
+
+void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
+ std::string const& libRef,
+ cmTargetLinkLibraryType llt)
+{
+ cmTarget* tgt = mf.FindTargetToUse(lib);
{
const bool isNonImportedTarget = tgt && !tgt->IsImported();
const std::string libName =
(isNonImportedTarget && llt != GENERAL_LibraryType)
- ? targetNameGenex(lib)
- : lib;
+ ? targetNameGenex(libRef)
+ : libRef;
this->AppendProperty(
"LINK_LIBRARIES",
this->GetDebugGeneratorExpressions(libName, llt).c_str());
}
- if (cmGeneratorExpression::Find(lib) != std::string::npos ||
+ if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef ||
(tgt &&
(tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
return cmMakeRange(this->Internal->SourceBacktraces);
}
+cmStringRange cmTarget::GetLinkOptionsEntries() const
+{
+ return cmMakeRange(this->Internal->LinkOptionsEntries);
+}
+
+cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const
+{
+ return cmMakeRange(this->Internal->LinkOptionsBacktraces);
+}
+
+cmStringRange cmTarget::GetLinkDirectoriesEntries() const
+{
+ return cmMakeRange(this->Internal->LinkDirectoriesEntries);
+}
+
+cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const
+{
+ return cmMakeRange(this->Internal->LinkDirectoriesBacktraces);
+}
+
cmStringRange cmTarget::GetLinkImplementationEntries() const
{
return cmMakeRange(this->Internal->LinkImplementationPropertyEntries);
MAKE_STATIC_PROP(EXPORT_NAME);
MAKE_STATIC_PROP(IMPORTED_GLOBAL);
MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
+ MAKE_STATIC_PROP(LINK_OPTIONS);
+ MAKE_STATIC_PROP(LINK_DIRECTORIES);
MAKE_STATIC_PROP(LINK_LIBRARIES);
MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
MAKE_STATIC_PROP(NAME);
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
}
+ } else if (prop == propLINK_OPTIONS) {
+ this->Internal->LinkOptionsEntries.clear();
+ this->Internal->LinkOptionsBacktraces.clear();
+ if (value) {
+ this->Internal->LinkOptionsEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->LinkOptionsBacktraces.push_back(lfbt);
+ }
+ } else if (prop == propLINK_DIRECTORIES) {
+ this->Internal->LinkDirectoriesEntries.clear();
+ this->Internal->LinkDirectoriesBacktraces.clear();
+ if (value) {
+ this->Internal->LinkDirectoriesEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->LinkDirectoriesBacktraces.push_back(lfbt);
+ }
} else if (prop == propLINK_LIBRARIES) {
this->Internal->LinkImplementationPropertyEntries.clear();
this->Internal->LinkImplementationPropertyBacktraces.clear();
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
}
+ } else if (prop == "LINK_OPTIONS") {
+ if (value && *value) {
+ this->Internal->LinkOptionsEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->LinkOptionsBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "LINK_DIRECTORIES") {
+ if (value && *value) {
+ this->Internal->LinkDirectoriesEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->LinkDirectoriesBacktraces.push_back(lfbt);
+ }
} else if (prop == "LINK_LIBRARIES") {
if (value && *value) {
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->BuildInterfaceIncludesAppended = true;
if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
- const char* binDir = this->Makefile->GetCurrentBinaryDirectory();
- const char* srcDir = this->Makefile->GetCurrentSourceDirectory();
- const std::string dirs = std::string(binDir ? binDir : "") +
- std::string(binDir ? ";" : "") + std::string(srcDir ? srcDir : "");
+ std::string dirs = this->Makefile->GetCurrentBinaryDirectory();
+ if (!dirs.empty()) {
+ dirs += ';';
+ }
+ dirs += this->Makefile->GetCurrentSourceDirectory();
if (!dirs.empty()) {
this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
("$<BUILD_INTERFACE:" + dirs + ">").c_str());
this->Internal->CompileDefinitionsBacktraces.push_back(bt);
}
+void cmTarget::InsertLinkOption(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before)
+{
+ std::vector<std::string>::iterator position = before
+ ? this->Internal->LinkOptionsEntries.begin()
+ : this->Internal->LinkOptionsEntries.end();
+
+ std::vector<cmListFileBacktrace>::iterator btPosition = before
+ ? this->Internal->LinkOptionsBacktraces.begin()
+ : this->Internal->LinkOptionsBacktraces.end();
+
+ this->Internal->LinkOptionsEntries.insert(position, entry);
+ this->Internal->LinkOptionsBacktraces.insert(btPosition, bt);
+}
+
+void cmTarget::InsertLinkDirectory(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before)
+{
+ std::vector<std::string>::iterator position = before
+ ? this->Internal->LinkDirectoriesEntries.begin()
+ : this->Internal->LinkDirectoriesEntries.end();
+
+ std::vector<cmListFileBacktrace>::iterator btPosition = before
+ ? this->Internal->LinkDirectoriesBacktraces.begin()
+ : this->Internal->LinkDirectoriesBacktraces.end();
+
+ this->Internal->LinkDirectoriesEntries.insert(position, entry);
+ this->Internal->LinkDirectoriesBacktraces.insert(btPosition, bt);
+}
+
static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
const char* value,
cmMakefile* context,
MAKE_STATIC_PROP(COMPILE_FEATURES);
MAKE_STATIC_PROP(COMPILE_OPTIONS);
MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
+ MAKE_STATIC_PROP(LINK_OPTIONS);
+ MAKE_STATIC_PROP(LINK_DIRECTORIES);
MAKE_STATIC_PROP(IMPORTED);
MAKE_STATIC_PROP(IMPORTED_GLOBAL);
MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
specialProps.insert(propCOMPILE_FEATURES);
specialProps.insert(propCOMPILE_OPTIONS);
specialProps.insert(propCOMPILE_DEFINITIONS);
+ specialProps.insert(propLINK_OPTIONS);
+ specialProps.insert(propLINK_DIRECTORIES);
specialProps.insert(propIMPORTED);
specialProps.insert(propIMPORTED_GLOBAL);
specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES);
output = cmJoin(this->Internal->CompileDefinitionsEntries, ";");
return output.c_str();
}
+ if (prop == propLINK_OPTIONS) {
+ if (this->Internal->LinkOptionsEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->Internal->LinkOptionsEntries, ";");
+ return output.c_str();
+ }
+ if (prop == propLINK_DIRECTORIES) {
+ if (this->Internal->LinkDirectoriesEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->Internal->LinkDirectoriesEntries, ";");
+
+ return output.c_str();
+ }
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
if (this->Utilities.empty()) {
return nullptr;
return this->GetMakefile()
->GetStateSnapshot()
.GetDirectory()
- .GetCurrentBinary();
+ .GetCurrentBinary()
+ .c_str();
}
if (prop == propSOURCE_DIR) {
return this->GetMakefile()
->GetStateSnapshot()
.GetDirectory()
- .GetCurrentSource();
+ .GetCurrentSource()
+ .c_str();
}
}
return retVal;
}
+const char* cmTarget::GetSafeProperty(const std::string& prop) const
+{
+ const char* ret = this->GetProperty(prop);
+ if (!ret) {
+ return "";
+ }
+ return ret;
+}
+
bool cmTarget::GetPropertyAsBool(const std::string& prop) const
{
return cmSystemTools::IsOn(this->GetProperty(prop));
void AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt);
+ void AddLinkLibrary(cmMakefile& mf, std::string const& lib,
+ std::string const& libRef, cmTargetLinkLibraryType llt);
+
enum TLLSignature
{
KeywordTLLSignature,
cmListFileContext const& lfc);
void GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const;
- const std::vector<std::string>& GetLinkDirectories() const;
-
- void AddLinkDirectory(const std::string& d);
-
/**
* Set the path where this target should be installed. This is relative to
* INSTALL_PREFIX
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
+ ///! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
+ ///! Always returns a valid pointer
+ const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void CheckProperty(const std::string& prop, cmMakefile* context) const;
const char* GetComputedProperty(const std::string& prop,
cmListFileBacktrace const& bt, bool before = false);
void InsertCompileDefinition(std::string const& entry,
cmListFileBacktrace const& bt);
+ void InsertLinkOption(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before = false);
+ void InsertLinkDirectory(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before = false);
void AppendBuildInterfaceIncludes();
cmStringRange GetSourceEntries() const;
cmBacktraceRange GetSourceBacktraces() const;
+
+ cmStringRange GetLinkOptionsEntries() const;
+ cmBacktraceRange GetLinkOptionsBacktraces() const;
+
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesBacktraces() const;
+
cmStringRange GetLinkImplementationEntries() const;
cmBacktraceRange GetLinkImplementationBacktraces() const;
bool IsGeneratorProvided;
cmPropertyMap Properties;
std::set<std::string> SystemIncludeDirectories;
- std::set<std::string> LinkDirectoriesEmmitted;
std::set<std::string> Utilities;
std::map<std::string, cmListFileBacktrace> UtilityBacktraces;
cmPolicies::PolicyMap PolicyMap;
std::string Name;
std::string InstallPath;
std::string RuntimeInstallPath;
- std::vector<std::string> LinkDirectories;
std::vector<cmCustomCommand> PreBuildCommands;
std::vector<cmCustomCommand> PreLinkCommands;
std::vector<cmCustomCommand> PostBuildCommands;
{
std::string dirs;
std::string sep;
- std::string prefix =
- this->Makefile->GetCurrentSourceDirectory() + std::string("/");
+ std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/";
for (std::string const& it : content) {
if (cmSystemTools::FileIsFullPath(it) ||
cmGeneratorExpression::Find(it) == 0) {
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
tgt->InsertInclude(this->Join(content), lfbt, prepend);
if (system) {
- std::string prefix =
- this->Makefile->GetCurrentSourceDirectory() + std::string("/");
+ std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/";
std::set<std::string> sdirs;
for (std::string const& it : content) {
if (cmSystemTools::FileIsFullPath(it) ||
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetLinkDirectoriesCommand.h"
+
+#include <sstream>
+
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+
+bool cmTargetLinkDirectoriesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
+{
+ return this->HandleArguments(args, "LINK_DIRECTORIES", PROCESS_BEFORE);
+}
+
+void cmTargetLinkDirectoriesCommand::HandleMissingTarget(
+ const std::string& name)
+{
+ std::ostringstream e;
+ e << "Cannot specify link directories for target \"" << name
+ << "\" which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+std::string cmTargetLinkDirectoriesCommand::Join(
+ const std::vector<std::string>& content)
+{
+ std::vector<std::string> directories;
+
+ for (const auto& dir : content) {
+ auto unixPath = dir;
+ cmSystemTools::ConvertToUnixSlashes(unixPath);
+ if (!cmSystemTools::FileIsFullPath(unixPath) &&
+ !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) {
+ auto tmp = this->Makefile->GetCurrentSourceDirectory();
+ tmp += "/";
+ tmp += unixPath;
+ unixPath = tmp;
+ }
+ directories.push_back(unixPath);
+ }
+
+ return cmJoin(directories, ";");
+}
+
+bool cmTargetLinkDirectoriesCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
+{
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+
+ tgt->InsertLinkDirectory(this->Join(content), lfbt, prepend);
+
+ return true; // Successfully handled.
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetLinkDirectoriesCommand_h
+#define cmTargetLinkDirectoriesCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmTargetPropCommandBase.h"
+
+class cmCommand;
+class cmExecutionStatus;
+class cmTarget;
+
+class cmTargetLinkDirectoriesCommand : public cmTargetPropCommandBase
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ cmCommand* Clone() override { return new cmTargetLinkDirectoriesCommand; }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) override;
+
+private:
+ void HandleMissingTarget(const std::string& name) override;
+
+ std::string Join(const std::vector<std::string>& content) override;
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override;
+};
+
+#endif
}
}
+ bool warnRemoteInterface = false;
+ bool rejectRemoteLinking = false;
+ bool encodeRemoteReference = false;
+ if (this->Makefile != this->Target->GetMakefile()) {
+ // The LHS target was created in another directory.
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0079)) {
+ case cmPolicies::WARN:
+ warnRemoteInterface = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ rejectRemoteLinking = true;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ encodeRemoteReference = true;
+ break;
+ }
+ }
+
+ std::string libRef;
+ if (encodeRemoteReference && !cmSystemTools::FileIsFullPath(lib)) {
+ // This is a library name added by a caller that is not in the
+ // same directory as the target was created. Add a suffix to
+ // the name to tell ResolveLinkItem to look up the name in the
+ // caller's directory.
+ cmDirectoryId const dirId = this->Makefile->GetDirectoryId();
+ libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String;
+ } else {
+ // This is an absolute path or a library name added by a caller
+ // in the same directory as the target was created. We can use
+ // the original name directly.
+ libRef = lib;
+ }
+
// Handle normal case where the command was called with another keyword than
// INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES"
// property of the target on the LHS shall be populated.)
if (this->CurrentProcessingState != ProcessingKeywordLinkInterface &&
this->CurrentProcessingState != ProcessingPlainLinkInterface) {
- // Assure that the target on the LHS was created in the current directory.
- cmTarget* t =
- this->Makefile->FindLocalNonAliasTarget(this->Target->GetName());
- if (!t) {
- const std::vector<cmTarget*>& importedTargets =
- this->Makefile->GetOwnedImportedTargets();
- for (cmTarget* importedTarget : importedTargets) {
- if (importedTarget->GetName() == this->Target->GetName()) {
- t = importedTarget;
- break;
- }
- }
- }
- if (!t) {
+ if (rejectRemoteLinking) {
std::ostringstream e;
e << "Attempt to add link library \"" << lib << "\" to target \""
<< this->Target->GetName()
- << "\" which is not built in this directory.";
+ << "\" which is not built in this directory.\n"
+ << "This is allowed only when policy CMP0079 is set to NEW.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
- this->Target->AddLinkLibrary(*this->Makefile, lib, llt);
+ this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt);
+ }
+
+ if (warnRemoteInterface) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0079) << "\n"
+ "Target\n " << this->Target->GetName() << "\nis not created in this "
+ "directory. For compatibility with older versions of CMake, link "
+ "library\n " << lib << "\nwill be looked up in the directory in "
+ "which the target was created rather than in this calling "
+ "directory.";
+ /* clang-format on */
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
// Handle (additional) case where the command was called with PRIVATE /
this->CurrentProcessingState == ProcessingPlainPrivateInterface) {
if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
std::string configLib =
- this->Target->GetDebugGeneratorExpressions(lib, llt);
- if (cmGeneratorExpression::IsValidTargetName(lib) ||
- cmGeneratorExpression::Find(lib) != std::string::npos) {
+ this->Target->GetDebugGeneratorExpressions(libRef, llt);
+ if (cmGeneratorExpression::IsValidTargetName(libRef) ||
+ cmGeneratorExpression::Find(libRef) != std::string::npos) {
configLib = "$<LINK_ONLY:" + configLib + ">";
}
this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
// property of the target on the LHS shall be populated.)
this->Target->AppendProperty(
"INTERFACE_LINK_LIBRARIES",
- this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
+ this->Target->GetDebugGeneratorExpressions(libRef, llt).c_str());
// Stop processing if called without any keyword.
if (this->CurrentProcessingState == ProcessingLinkLibraries) {
for (std::string const& dc : debugConfigs) {
prop = "LINK_INTERFACE_LIBRARIES_";
prop += dc;
- this->Target->AppendProperty(prop, lib.c_str());
+ this->Target->AppendProperty(prop, libRef.c_str());
}
}
if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) {
// Put in the non-DEBUG configuration interfaces.
- this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib.c_str());
+ this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str());
// Make sure the DEBUG configuration interfaces exist so that the
// general one will not be used as a fall-back.
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetLinkOptionsCommand.h"
+
+#include <sstream>
+
+#include "cmAlgorithms.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+
+bool cmTargetLinkOptionsCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
+{
+ return this->HandleArguments(args, "LINK_OPTIONS", PROCESS_BEFORE);
+}
+
+void cmTargetLinkOptionsCommand::HandleMissingTarget(const std::string& name)
+{
+ std::ostringstream e;
+ e << "Cannot specify link options for target \"" << name
+ << "\" which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+std::string cmTargetLinkOptionsCommand::Join(
+ const std::vector<std::string>& content)
+{
+ return cmJoin(content, ";");
+}
+
+bool cmTargetLinkOptionsCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
+{
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ tgt->InsertLinkOption(this->Join(content), lfbt, prepend);
+ return true; // Successfully handled.
+}
--- /dev/null
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetLinkOptionsCommand_h
+#define cmTargetLinkOptionsCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmTargetPropCommandBase.h"
+
+class cmCommand;
+class cmExecutionStatus;
+class cmTarget;
+
+class cmTargetLinkOptionsCommand : public cmTargetPropCommandBase
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ cmCommand* Clone() override { return new cmTargetLinkOptionsCommand; }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) override;
+
+private:
+ void HandleMissingTarget(const std::string& name) override;
+
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override;
+ std::string Join(const std::vector<std::string>& content) override;
+};
+
+#endif
#include <sstream>
#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
return this->HandleArguments(args, "SOURCES");
}
+void cmTargetSourcesCommand::HandleInterfaceContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
+ bool system)
+{
+ cmTargetPropCommandBase::HandleInterfaceContent(
+ tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system);
+}
+
void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
{
std::ostringstream e;
bool cmTargetSourcesCommand::HandleDirectContent(
cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
{
- tgt->AppendProperty("SOURCES", this->Join(content).c_str());
+ tgt->AppendProperty(
+ "SOURCES",
+ this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str());
return true; // Successfully handled.
}
+
+std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent(
+ cmTarget* tgt, const std::vector<std::string>& content,
+ bool isInterfaceContent)
+{
+ // Skip conversion in case old behavior has been explicitly requested
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) ==
+ cmPolicies::OLD) {
+ return content;
+ }
+
+ bool changedPath = false;
+ std::vector<std::string> absoluteContent;
+ absoluteContent.reserve(content.size());
+ for (std::string const& src : content) {
+ std::string absoluteSrc;
+ if (cmSystemTools::FileIsFullPath(src) ||
+ cmGeneratorExpression::Find(src) == 0 ||
+ (!isInterfaceContent &&
+ (this->Makefile->GetCurrentSourceDirectory() ==
+ tgt->GetMakefile()->GetCurrentSourceDirectory()))) {
+ absoluteSrc = src;
+ } else {
+ changedPath = true;
+ absoluteSrc = this->Makefile->GetCurrentSourceDirectory();
+ absoluteSrc += "/";
+ absoluteSrc += src;
+ }
+ absoluteContent.push_back(absoluteSrc);
+ }
+
+ if (!changedPath) {
+ return content;
+ }
+
+ bool issueMessage = true;
+ bool useAbsoluteContent = false;
+ std::ostringstream e;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n";
+ break;
+ case cmPolicies::OLD:
+ issueMessage = false;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076));
+ break;
+ case cmPolicies::NEW: {
+ issueMessage = false;
+ useAbsoluteContent = true;
+ break;
+ }
+ }
+
+ if (issueMessage) {
+ if (isInterfaceContent) {
+ e << "An interface source of target \"" << tgt->GetName()
+ << "\" has a relative path.";
+ } else {
+ e << "A private source from a directory other than that of target \""
+ << tgt->GetName() << "\" has a relative path.";
+ }
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ }
+
+ return useAbsoluteContent ? absoluteContent : content;
+}
bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status) override;
+protected:
+ void HandleInterfaceContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override;
+
private:
void HandleMissingTarget(const std::string& name) override;
bool prepend, bool system) override;
std::string Join(const std::vector<std::string>& content) override;
+
+ std::vector<std::string> ConvertToAbsoluteContent(
+ cmTarget* tgt, const std::vector<std::string>& content,
+ bool isInterfaceContent);
};
#endif
}
} else {
// Use the command name given.
- exe = ge.Parse(exe.c_str())->Evaluate(this->LG, config);
+ exe = ge.Parse(exe)->Evaluate(this->LG, config);
cmSystemTools::ConvertToUnixSlashes(exe);
}
// From Linux timegm() manpage.
std::string tz_old;
- cmSystemTools::GetEnv("TZ", tz_old);
+ bool const tz_was_set = cmSystemTools::GetEnv("TZ", tz_old);
tz_old = "TZ=" + tz_old;
// The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC.
time_t result = mktime(&tm);
+# ifdef CMAKE_BUILD_WITH_CMAKE
+ if (tz_was_set) {
+ cmSystemTools::PutEnv(tz_old);
+ } else {
+ cmSystemTools::UnsetEnv("TZ");
+ }
+# else
+ // No UnsetEnv during bootstrap. This is good enough for CMake itself.
cmSystemTools::PutEnv(tz_old);
+ static_cast<void>(tz_was_set);
+# endif
tzset();
/** \class cmTryCompileCommand
* \brief Specifies where to install some files
*
- * cmTryCompileCommand is used to test if soucre code can be compiled
+ * cmTryCompileCommand is used to test if source code can be compiled
*/
class cmTryCompileCommand : public cmCoreTryCompile
{
/** \class cmTryRunCommand
* \brief Specifies where to install some files
*
- * cmTryRunCommand is used to test if soucre code can be compiled
+ * cmTryRunCommand is used to test if source code can be compiled
*/
class cmTryRunCommand : public cmCoreTryCompile
{
// regular expression for gl GL or xmesa in a file (match(1) of above)
cmsys::RegularExpression glLine("(gl|GL|xmesa)");
while (cmSystemTools::GetLineFromStream(fin, inLine)) {
- if (includeLine.find(inLine.c_str())) {
+ if (includeLine.find(inLine)) {
std::string includeFile = includeLine.match(1);
- if (glDirLine.find(includeFile.c_str())) {
+ if (glDirLine.find(includeFile)) {
std::string gfile = glDirLine.match(3);
fout << "#include \"" << outdir << "/" << gfile << "\"\n";
- } else if (glLine.find(includeFile.c_str())) {
+ } else if (glLine.find(includeFile)) {
fout << "#include \"" << outdir << "/" << includeLine.match(1)
<< "\"\n";
} else {
// If it exists already and appears up to date then we are done. If
// the string contains "(IntDir)" but that is not the
// CMAKE_CFG_INTDIR setting then the value is out of date.
- const char* intDir =
+ std::string const& intDir =
this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
bool haveCacheValue = false;
cmState* state = this->Makefile->GetState();
haveCacheValue = (cacheValue &&
(strstr(cacheValue, "(IntDir)") == nullptr ||
- (intDir && strcmp(intDir, "$(IntDir)") == 0)) &&
+ (intDir == "$(IntDir)")) &&
(state->GetCacheMajorVersion() != 0 &&
state->GetCacheMinorVersion() != 0));
}
{ "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
{ "", "link", "", "", 0 },
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
+ { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired },
+ { "ApplicationIcon", "win32icon:", "", "",
cmIDEFlagTable::UserValueRequired },
{ "ApplicationManifest", "win32manifest:", "", "",
{ "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
{ "", "link", "", "", 0 },
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
+ { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired },
+ { "ApplicationIcon", "win32icon:", "", "",
cmIDEFlagTable::UserValueRequired },
{ "ApplicationManifest", "win32manifest:", "", "",
{ "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
{ "", "link", "", "", 0 },
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
+ { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired },
+ { "ApplicationIcon", "win32icon:", "", "",
cmIDEFlagTable::UserValueRequired },
{ "ApplicationManifest", "win32manifest:", "", "",
{ "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
{ "", "link", "", "", 0 },
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
+ { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired },
+ { "ApplicationIcon", "win32icon:", "", "",
cmIDEFlagTable::UserValueRequired },
{ "ApplicationManifest", "win32manifest:", "", "",
{ "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 },
{ "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 },
+ { "SpectreMitigation", "Qspectre", "Spectre mitigations", "Spectre", 0 },
+
{ "LanguageStandard", "std:c++17", "ISO C++17 Standard", "stdcpp17", 0 },
{ "LanguageStandard", "std:c++14", "ISO C++14 Standard", "stdcpp14", 0 },
{ "LanguageStandard", "std:c++latest", "ISO C++ Latest Draft Standard",
{ "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
{ "", "link", "", "", 0 },
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
+ { "Win32Resource", "win32res:", "", "", cmIDEFlagTable::UserValueRequired },
+ { "ApplicationIcon", "win32icon:", "", "",
cmIDEFlagTable::UserValueRequired },
{ "ApplicationManifest", "win32manifest:", "", "",
{ "LangVersion", "langversion:4", "", "4", 0 },
{ "LangVersion", "langversion:5", "", "5", 0 },
{ "LangVersion", "langversion:6", "", "6", 0 },
+ { "LangVersion", "langversion:7.0", "", "7.0", 0 },
+ { "LangVersion", "langversion:7.1", "", "7.1", 0 },
+ { "LangVersion", "langversion:7.2", "", "7.2", 0 },
+ { "LangVersion", "langversion:7.3", "", "7.3", 0 },
{ "LangVersion", "langversion:default", "", "default", 0 },
+ { "LangVersion", "langversion:latest", "", "latest", 0 },
{ "DelaySign", "delaysign", "", "true", 0 },
{ "DelaySign", "delaysign-", "", "false", 0 },
this->TargetCompileAsWinRT = false;
this->IsMissingFiles = false;
this->DefaultArtifactDir =
- this->LocalGenerator->GetCurrentBinaryDirectory() + std::string("/") +
+ this->LocalGenerator->GetCurrentBinaryDirectory() + "/" +
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->InSourceBuild =
- (strcmp(this->Makefile->GetCurrentSourceDirectory(),
- this->Makefile->GetCurrentBinaryDirectory()) == 0);
+ this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() ==
+ this->Makefile->GetCurrentBinaryDirectory());
}
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
path += "/";
path += this->Name;
path += ProjectFileExtension;
- cmGeneratedFileStream BuildFileStream(path.c_str());
+ cmGeneratedFileStream BuildFileStream(path);
const std::string PathToProjectFile = path;
BuildFileStream.SetCopyIfDifferent(true);
if (!name.empty()) {
std::string path = i.second.GetValue();
if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = std::string(this->Makefile->GetCurrentSourceDirectory()) +
- "/" + path;
+ path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
}
ConvertToWindowsSlash(path);
this->DotNetHintReferences[""].push_back(
e2.SetHasElements();
if (this->ProjectType == csproj && !this->InSourceBuild) {
// add <Link> tag to written XAML source if necessary
- const std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
- const std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
+ const std::string& srcDir =
+ this->Makefile->GetCurrentSourceDirectory();
+ const std::string& binDir =
+ this->Makefile->GetCurrentBinaryDirectory();
std::string link;
if (obj.find(srcDir) == 0) {
link = obj.substr(srcDir.length() + 1);
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
e1.Element("WindowsAppContainer", "true");
}
+ if (this->IPOEnabledConfigurations.count(config) > 0) {
+ e1.Element("WholeProgramOptimization", "true");
+ }
+ if (this->SpectreMitigationConfigurations.count(config) > 0) {
+ e1.Element("SpectreMitigation", "Spectre");
+ }
}
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
Elem& e1, std::string const& config)
{
+ if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
+ return;
+ }
+
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
Options& o = *(this->ClOptions[config]);
path += this->Name;
path += computeProjectFileExtension(this->GeneratorTarget);
path += ".filters";
- cmGeneratedFileStream fout(path.c_str());
+ cmGeneratedFileStream fout(path);
fout.SetCopyIfDifferent(true);
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
fout.write(magic, 3);
e2.Element("Link", deployLocation + "\\%(FileName)%(Extension)");
}
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- if (0 ==
- strcmp(
- cge->Evaluate(this->LocalGenerator, this->Configurations[i]),
- "1")) {
+ if (cge->Evaluate(this->LocalGenerator, this->Configurations[i]) ==
+ "1") {
e2.WritePlatformConfigTag("DeploymentContent",
"'$(Configuration)|$(Platform)'=='" +
this->Configurations[i] + "|" +
ge.Parse(shaderEnableDebug);
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- const char* enableDebug =
+ const std::string& enableDebug =
cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
- if (strlen(enableDebug) > 0) {
+ if (!enableDebug.empty()) {
e2.WritePlatformConfigTag(
"EnableDebuggingInformation",
"'$(Configuration)|$(Platform)'=='" + this->Configurations[i] +
ge.Parse(shaderDisableOptimizations);
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- const char* disableOptimizations =
+ const std::string& disableOptimizations =
cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
- if (strlen(disableOptimizations) > 0) {
+ if (!disableOptimizations.empty()) {
e2.WritePlatformConfigTag(
"DisableOptimizations",
"'$(Configuration)|$(Platform)'=='" + this->Configurations[i] +
std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true);
size_t const maxLen = 250;
if (sf->GetCustomCommand() ||
- ((strlen(this->LocalGenerator->GetCurrentBinaryDirectory()) + 1 +
+ ((this->LocalGenerator->GetCurrentBinaryDirectory().length() + 1 +
sourceRel.length()) <= maxLen)) {
forceRelative = true;
sourceFile = sourceRel;
}
}
ConvertToWindowsSlash(sourceFile);
- e2.StartElement(tool.c_str());
+ e2.StartElement(tool);
e2.Attribute("Include", sourceFile);
ToolSource toolSource = { sf, forceRelative };
flagtable = gg->GetCSharpFlagTable();
}
cmGeneratorExpressionInterpreter genexInterpreter(
- this->LocalGenerator, this->GeneratorTarget, config,
- this->GeneratorTarget->GetName(), lang);
+ this->LocalGenerator, config, this->GeneratorTarget, lang);
cmVS10GeneratorOptions clOptions(
this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
flagtable, this);
if (configDependentFlags) {
clOptions.Parse(genexInterpreter.Evaluate(flags, "COMPILE_FLAGS"));
} else {
- clOptions.Parse(flags.c_str());
+ clOptions.Parse(flags);
}
if (!options.empty()) {
std::string expandedOptions;
} else {
this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
}
- clOptions.Parse(expandedOptions.c_str());
+ clOptions.Parse(expandedOptions);
}
if (clOptions.HasFlag("DisableSpecificWarnings")) {
clOptions.AppendFlag("DisableSpecificWarnings",
if (const char* workingDir = this->GeneratorTarget->GetProperty(
"VS_DEBUGGER_WORKING_DIRECTORY")) {
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(workingDir);
+ std::string genWorkingDir =
+ cge->Evaluate(this->LocalGenerator, config);
+
e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
- workingDir);
+ genWorkingDir);
+ }
+
+ if (const char* environment =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) {
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(environment);
+ std::string genEnvironment =
+ cge->Evaluate(this->LocalGenerator, config);
+
+ e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond,
+ genEnvironment);
}
if (const char* debuggerCommand =
this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
+
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(debuggerCommand);
+ std::string genDebuggerCommand =
+ cge->Evaluate(this->LocalGenerator, config);
+
e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
- debuggerCommand);
+ genDebuggerCommand);
+ }
+
+ if (const char* commandArguments = this->GeneratorTarget->GetProperty(
+ "VS_DEBUGGER_COMMAND_ARGUMENTS")) {
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(commandArguments);
+ std::string genCommandArguments =
+ cge->Evaluate(this->LocalGenerator, config);
+
+ e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond,
+ genCommandArguments);
}
std::string name =
Options& linkOptions = *(this->LinkOptions[configName]);
const std::string cond = this->CalcCondition(configName);
- const char* incremental = linkOptions.GetFlag("LinkIncremental");
- e1.WritePlatformConfigTag("LinkIncremental", cond,
- (incremental ? incremental : "true"));
+ if (this->IPOEnabledConfigurations.count(configName) == 0) {
+ const char* incremental = linkOptions.GetFlag("LinkIncremental");
+ e1.WritePlatformConfigTag("LinkIncremental", cond,
+ (incremental ? incremental : "true"));
+ }
linkOptions.RemoveFlag("LinkIncremental");
const char* manifest = linkOptions.GetFlag("GenerateManifest");
baseFlagVar += "_FLAGS";
flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
std::string flagVar =
- baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
+ baseFlagVar + "_" + cmSystemTools::UpperCase(configName);
flags += " ";
flags += this->Makefile->GetRequiredDefinition(flagVar);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
clOptions.AddFlag("CompileAs", "CompileAsCpp");
}
- // Check IPO related warning/error.
- this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
+ // Put the IPO enabled configurations into a set.
+ if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) {
+ this->IPOEnabledConfigurations.insert(configName);
+ }
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Makefile->GetDefineFlags();
if (this->MSTools) {
if (this->ProjectType == vcxproj) {
clOptions.FixExceptionHandlingDefault();
+ if (this->GlobalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VS15) {
+ // Toolsets that come with VS 2017 may now enable UseFullPaths
+ // by default and there is no negative /FC option that projects
+ // can use to switch it back. Older toolsets disable this by
+ // default anyway so this will not hurt them. If the project
+ // is using an explicit /FC option then parsing flags will
+ // replace this setting with "true" below.
+ clOptions.AddFlag("UseFullPaths", "false");
+ }
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
std::string asmLocation = configName + "/";
clOptions.AddFlag("AssemblerListingLocation", asmLocation);
}
}
- clOptions.Parse(flags.c_str());
- clOptions.Parse(defineFlags.c_str());
+ clOptions.Parse(flags);
+ clOptions.Parse(defineFlags);
std::vector<std::string> targetDefines;
switch (this->ProjectType) {
case vcxproj:
}
if (this->MSTools) {
- // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT.
- if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
+ // If we have the VS_WINRT_COMPONENT or CMAKE_VS_WINRT_BY_DEFAULT
+ // set then force Compile as WinRT.
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
+ this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) {
clOptions.AddFlag("CompileAsWinRT", "true");
// For WinRT components, add the _WINRT_DLL define to produce a lib
if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
}
}
+ if (clOptions.HasFlag("SpectreMitigation")) {
+ this->SpectreMitigationConfigurations.insert(configName);
+ clOptions.RemoveFlag("SpectreMitigation");
+ }
+
this->ClOptions[configName] = std::move(pOptions);
return true;
}
// Specify the compiler program database file if configured.
std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
if (!pdb.empty()) {
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ // CUDA does not quote paths with spaces correctly when forwarding
+ // this to the host compiler. Use a relative path to avoid spaces.
+ // FIXME: We can likely do this even when CUDA is not involved,
+ // but for now we will make a minimal change.
+ pdb = this->ConvertPath(pdb, true);
+ }
ConvertToWindowsSlash(pdb);
e2.Element("ProgramDataBaseFileName", pdb);
}
Options& rcOptions = *pOptions;
std::string CONFIG = cmSystemTools::UpperCase(configName);
- std::string rcConfigFlagsVar = std::string("CMAKE_RC_FLAGS_") + CONFIG;
- std::string flags =
- std::string(this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS")) +
- std::string(" ") +
- std::string(this->Makefile->GetSafeDefinition(rcConfigFlagsVar));
+ std::string rcConfigFlagsVar = "CMAKE_RC_FLAGS_" + CONFIG;
+ std::string flags = this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS") +
+ " " + this->Makefile->GetSafeDefinition(rcConfigFlagsVar);
- rcOptions.Parse(flags.c_str());
+ rcOptions.Parse(flags);
// For historical reasons, add the C preprocessor defines to RC.
Options& clOptions = *(this->ClOptions[configName]);
// 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));
+ std::string flags = this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS") +
+ " " + this->Makefile->GetSafeDefinition(configFlagsVar);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
configName);
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Makefile->GetDefineFlags();
- cudaOptions.Parse(flags.c_str());
- cudaOptions.Parse(defineFlags.c_str());
+ cudaOptions.Parse(flags);
+ cudaOptions.Parse(defineFlags);
cudaOptions.ParseFinish();
// If we haven't explicitly enabled GPU debug information
// Specify the compiler program database file if configured.
std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
if (!pdb.empty()) {
- // CUDA does not have a field for this and does not honor the
- // ProgramDataBaseFileName field in ClCompile. Work around this
- // limitation by creating the directory and passing the flag ourselves.
+ // CUDA does not make the directory if it is non-standard.
std::string const pdbDir = cmSystemTools::GetFilenamePath(pdb);
cmSystemTools::MakeDirectory(pdbDir);
- pdb = this->ConvertPath(pdb, true);
- ConvertToWindowsSlash(pdb);
- std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\"";
- cudaOptions.AppendFlagString("AdditionalOptions", clFd);
+ if (cmSystemTools::VersionCompareGreaterEq(
+ "9.2", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
+ // CUDA does not have a field for this and does not honor the
+ // ProgramDataBaseFileName field in ClCompile. Work around this
+ // limitation by creating the directory and passing the flag ourselves.
+ pdb = this->ConvertPath(pdb, true);
+ ConvertToWindowsSlash(pdb);
+ std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\"";
+ cudaOptions.AppendFlagString("AdditionalOptions", clFd);
+ }
}
// CUDA automatically passes the proper '--machine' flag to nvcc
std::string CONFIG = cmSystemTools::UpperCase(configName);
std::string configFlagsVar = std::string("CMAKE_ASM_MASM_FLAGS_") + CONFIG;
std::string flags =
- std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS")) +
- std::string(" ") +
- std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
+ this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS") + " " +
+ this->Makefile->GetSafeDefinition(configFlagsVar);
- masmOptions.Parse(flags.c_str());
+ masmOptions.Parse(flags);
// Get includes for this target
masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM"));
Options& nasmOptions = *pOptions;
std::string CONFIG = cmSystemTools::UpperCase(configName);
- std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG;
+ std::string configFlagsVar = "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->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS") + " -f" +
+ this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT") + " " +
+ this->Makefile->GetSafeDefinition(configFlagsVar);
+ nasmOptions.Parse(flags);
// Get includes for this target
nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM"));
this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
return;
}
+
+ const std::string& linkLanguage =
+ this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage;
+
std::string libflags;
this->LocalGenerator->GetStaticLibraryFlags(
- libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
+ libflags, cmSystemTools::UpperCase(config), linkLanguage,
+ this->GeneratorTarget);
if (!libflags.empty()) {
Elem e2(e1, "Lib");
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmVS10GeneratorOptions libOptions(this->LocalGenerator,
cmVisualStudioGeneratorOptions::Linker,
gg->GetLibFlagTable(), this);
- libOptions.Parse(libflags.c_str());
+ libOptions.Parse(libflags);
OptionsHelper oh(libOptions, e2);
oh.PrependInheritedString("AdditionalOptions");
oh.OutputFlagMap();
flags += flagsConfig;
}
+ std::vector<std::string> opts;
+ this->GeneratorTarget->GetLinkOptions(opts, config, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->LocalGenerator->AppendCompileOptions(flags, opts);
+
cmComputeLinkInformation* pcli =
this->GeneratorTarget->GetLinkInformation(config);
if (!pcli) {
linkOptions.AddFlag("SoName", targetNameSO);
}
- linkOptions.Parse(flags.c_str());
+ linkOptions.Parse(flags);
linkOptions.FixManifestUACFlags();
if (this->MSTools) {
e2.Element("Project", "{" + this->GlobalGenerator->GetGUID(name) + "}");
e2.Element("Name", name);
this->WriteDotNetReferenceCustomTags(e2, name);
- if (this->Managed) {
- // If the dependency target is not managed (compiled with /clr or
- // C# target) we cannot reference it and have to set
- // 'ReferenceOutputAssembly' to false.
- auto referenceNotManaged =
- dt->GetManagedType("") < cmGeneratorTarget::ManagedType::Mixed;
- // Workaround to check for manually set /clr flags.
- if (referenceNotManaged) {
- if (const auto* flags = dt->GetProperty("COMPILE_OPTIONS")) {
- std::string flagsStr = flags;
- if (flagsStr.find("clr") != std::string::npos) {
- // There is a warning already issued when building the flags.
- referenceNotManaged = false;
- }
+
+ // If the dependency target is not managed (compiled with /clr or
+ // C# target) we cannot reference it and have to set
+ // 'ReferenceOutputAssembly' to false.
+ auto referenceNotManaged =
+ dt->GetManagedType("") < cmGeneratorTarget::ManagedType::Mixed;
+ // Workaround to check for manually set /clr flags.
+ if (referenceNotManaged) {
+ if (const auto* flags = dt->GetProperty("COMPILE_OPTIONS")) {
+ std::string flagsStr = flags;
+ if (flagsStr.find("clr") != std::string::npos) {
+ // There is a warning already issued when building the flags.
+ referenceNotManaged = false;
}
}
- // Workaround for static library C# targets
- if (referenceNotManaged &&
- dt->GetType() == cmStateEnums::STATIC_LIBRARY) {
- referenceNotManaged = !dt->IsCSharpOnly();
- }
- if (referenceNotManaged) {
- e2.Element("ReferenceOutputAssembly", "false");
- e2.Element("CopyToOutputDirectory", "Never");
- }
+ }
+ // Workaround for static library C# targets
+ if (referenceNotManaged && dt->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ referenceNotManaged = !dt->IsCSharpOnly();
+ }
+ if (referenceNotManaged) {
+ e2.Element("ReferenceOutputAssembly", "false");
+ e2.Element("CopyToOutputDirectory", "Never");
}
}
}
// this can cause an overwrite problem if projects aren't organized in
// folders
std::string manifestFile =
- this->LocalGenerator->GetCurrentBinaryDirectory() +
- std::string("/WMAppManifest.xml");
+ this->LocalGenerator->GetCurrentBinaryDirectory() + "/WMAppManifest.xml";
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
ConvertToWindowsSlash(artifactDir);
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
std::string const& binaryDir = LocalGenerator->GetCurrentBinaryDirectory();
if (!cmSystemTools::IsSubDirectory(sourceFilePath, binaryDir)) {
- const std::string stripFromPath =
+ const std::string& stripFromPath =
this->Makefile->GetCurrentSourceDirectory();
if (sourceFilePath.find(stripFromPath) == 0) {
if (const char* l = sf->GetProperty("VS_CSHARP_Link")) {
bool NsightTegra;
unsigned int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
+ std::set<std::string> IPOEnabledConfigurations;
+ std::set<std::string> SpectreMitigationConfigurations;
cmGlobalVisualStudio10Generator* const GlobalGenerator;
cmLocalVisualStudio10Generator* const LocalGenerator;
std::set<std::string> CSharpCustomCommandNames;
AddFlag(ENABLE_UAC, "true");
}
-void cmVisualStudioGeneratorOptions::Parse(const char* flags)
+void cmVisualStudioGeneratorOptions::Parse(const std::string& flags)
{
// Parse the input string as a windows command line since the string
// is intended for writing directly into the build files.
std::vector<std::string> args;
- cmSystemTools::ParseWindowsCommandLine(flags, args);
+ cmSystemTools::ParseWindowsCommandLine(flags.c_str(), args);
// Process flags that need to be represented specially in the IDE
// project file.
std::string const original = i->second[0];
i->second[0] = "";
this->UnknownFlagField = key;
- this->Parse(original.c_str());
+ this->Parse(original);
}
void cmVisualStudioGeneratorOptions::StoreUnknownFlag(std::string const& flag)
void ClearTables();
// Store options from command line flags.
- void Parse(const char* flags);
+ void Parse(const std::string& flags);
void ParseFinish();
void PrependInheritedString(std::string const& key);
cmSystemTools::MakeDirectory(dir);
mode_t mode = 0;
+ bool writable = false;
// Set permissions to writable
if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) {
- cmSystemTools::SetPermissions(fileName.c_str(),
#if defined(_MSC_VER) || defined(__MINGW32__)
- mode | S_IWRITE
+ writable = mode & S_IWRITE;
+ mode_t newMode = mode | S_IWRITE;
#else
- mode | S_IWUSR | S_IWGRP
+ writable = mode & S_IWUSR;
+ mode_t newMode = mode | S_IWUSR | S_IWGRP;
#endif
- );
+ if (!writable) {
+ cmSystemTools::SetPermissions(fileName.c_str(), newMode);
+ }
}
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
}
file << message << std::endl;
file.close();
- if (mode) {
+ if (mode && !writable) {
cmSystemTools::SetPermissions(fileName.c_str(), mode);
}
xout.Attribute("debugServiceExtension", "internal");
xout.Attribute("allowLocationSimulation", "YES");
+ // Diagnostics tab begin
+
+ bool useAddressSanitizer = WriteLaunchActionAttribute(
+ xout, "enableAddressSanitizer",
+ "XCODE_SCHEME_ADDRESS_SANITIZER"); // not allowed with
+ // enableThreadSanitizer=YES
+ WriteLaunchActionAttribute(
+ xout, "enableASanStackUseAfterReturn",
+ "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN");
+
+ bool useThreadSanitizer = false;
+ if (!useAddressSanitizer) {
+ useThreadSanitizer = WriteLaunchActionAttribute(
+ xout, "enableThreadSanitizer",
+ "XCODE_SCHEME_THREAD_SANITIZER"); // not allowed with
+ // enableAddressSanitizer=YES
+ }
+
+ WriteLaunchActionAttribute(xout, "stopOnEveryThreadSanitizerIssue",
+ "XCODE_SCHEME_THREAD_SANITIZER_STOP");
+
+ WriteLaunchActionAttribute(xout, "enableUBSanitizer",
+ "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
+ WriteLaunchActionAttribute(
+ xout, "stopOnEveryUBSanitizerIssue",
+ "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
+
+ WriteLaunchActionAttribute(
+ xout, "disableMainThreadChecker",
+ "XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"); // negative enabled!
+ WriteLaunchActionAttribute(xout, "stopOnEveryMainThreadCheckerIssue",
+ "XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP");
+
+ // Diagnostics tab end
+
if (IsExecutable(this->Target)) {
xout.StartElement("BuildableProductRunnable");
xout.BreakAttributes();
xout.EndElement(); // MacroExpansion
+ // Info tab begin
+
+ if (const char* exe =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_EXECUTABLE")) {
+
+ xout.StartElement("PathRunnable");
+ xout.BreakAttributes();
+
+ xout.Attribute("runnableDebuggingMode", "0");
+ xout.Attribute("FilePath", exe);
+
+ xout.EndElement(); // PathRunnable
+ }
+
+ // Info tab end
+
+ // Arguments tab begin
+
+ if (const char* argList =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ARGUMENTS")) {
+ std::vector<std::string> arguments;
+ cmSystemTools::ExpandListArgument(argList, arguments);
+ if (!arguments.empty()) {
+ xout.StartElement("CommandLineArguments");
+
+ for (auto argument : arguments) {
+ xout.StartElement("CommandLineArgument");
+ xout.BreakAttributes();
+
+ xout.Attribute("argument", argument);
+ xout.Attribute("isEnabled", "YES");
+
+ xout.EndElement(); // CommandLineArgument
+ }
+
+ xout.EndElement(); // CommandLineArguments
+ }
+ }
+
+ if (const char* envList =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ENVIRONMENT")) {
+ std::vector<std::string> envs;
+ cmSystemTools::ExpandListArgument(envList, envs);
+ if (!envs.empty()) {
+ xout.StartElement("EnvironmentVariables");
+
+ for (auto env : envs) {
+
+ xout.StartElement("EnvironmentVariable");
+ xout.BreakAttributes();
+
+ std::string envValue;
+ const auto p = env.find_first_of('=');
+ if (p != std::string::npos) {
+ envValue = env.substr(p + 1);
+ env.resize(p);
+ }
+
+ xout.Attribute("key", env);
+ xout.Attribute("value", envValue);
+ xout.Attribute("isEnabled", "YES");
+
+ xout.EndElement(); // EnvironmentVariable
+ }
+
+ xout.EndElement(); // EnvironmentVariables
+ }
+ }
+
+ // Arguments tab end
+
xout.StartElement("AdditionalOptions");
+
+ if (!useThreadSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "MallocScribble", "",
+ "XCODE_SCHEME_MALLOC_SCRIBBLE");
+ }
+
+ if (!useThreadSanitizer && !useAddressSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "MallocGuardEdges", "",
+ "XCODE_SCHEME_MALLOC_GUARD_EDGES");
+ }
+
+ if (!useThreadSanitizer && !useAddressSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "DYLD_INSERT_LIBRARIES",
+ "/usr/lib/libgmalloc.dylib",
+ "XCODE_SCHEME_GUARD_MALLOC");
+ }
+
+ WriteLaunchActionAdditionalOption(xout, "NSZombieEnabled", "YES",
+ "XCODE_SCHEME_ZOMBIE_OBJECTS");
+
+ if (!useThreadSanitizer && !useAddressSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "MallocStackLogging", "",
+ "XCODE_SCHEME_MALLOC_STACK");
+ }
+
+ WriteLaunchActionAdditionalOption(xout, "DYLD_PRINT_APIS", "",
+ "XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
+
+ WriteLaunchActionAdditionalOption(xout, "DYLD_PRINT_LIBRARIES", "",
+ "XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS");
+
xout.EndElement();
xout.EndElement(); // LaunchAction
}
+bool cmXCodeScheme::WriteLaunchActionAttribute(cmXMLWriter& xout,
+ const std::string& attrName,
+ const std::string& varName)
+{
+ if (Target->GetTarget()->GetPropertyAsBool(varName)) {
+ xout.Attribute(attrName.c_str(), "YES");
+ return true;
+ }
+ return false;
+}
+
+bool cmXCodeScheme::WriteLaunchActionAdditionalOption(
+ cmXMLWriter& xout, const std::string& key, const std::string& value,
+ const std::string& varName)
+{
+ if (Target->GetTarget()->GetPropertyAsBool(varName)) {
+ xout.StartElement("AdditionalOption");
+ xout.BreakAttributes();
+
+ xout.Attribute("key", key);
+ xout.Attribute("value", value);
+ xout.Attribute("isEnabled", "YES");
+
+ xout.EndElement(); // AdditionalOption
+
+ return true;
+ }
+ return false;
+}
+
void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout,
const std::string& configuration)
{
const std::string& container);
void WriteLaunchAction(cmXMLWriter& xout, const std::string& configuration,
const std::string& container);
+
+ bool WriteLaunchActionAttribute(cmXMLWriter& xout,
+ const std::string& attrName,
+ const std::string& varName);
+
+ bool WriteLaunchActionAdditionalOption(cmXMLWriter& xout,
+ const std::string& attrName,
+ const std::string& value,
+ const std::string& varName);
+
void WriteProfileAction(cmXMLWriter& xout, const std::string& configuration);
void WriteAnalyzeAction(cmXMLWriter& xout, const std::string& configuration);
void WriteArchiveAction(cmXMLWriter& xout, const std::string& configuration);
void cmXMLParser::ReportXmlParseError()
{
XML_Parser parser = static_cast<XML_Parser>(this->Parser);
- this->ReportError(XML_GetCurrentLineNumber(parser),
- XML_GetCurrentColumnNumber(parser),
+ this->ReportError(static_cast<int>(XML_GetCurrentLineNumber(parser)),
+ static_cast<int>(XML_GetCurrentColumnNumber(parser)),
XML_ErrorString(XML_GetErrorCode(parser)));
}
}
#if defined(CMAKE_BUILD_WITH_CMAKE)
-Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
+Json::Value cmake::ReportVersionJson() const
{
- Json::Value obj = Json::objectValue;
- // Version information:
Json::Value version = Json::objectValue;
version["string"] = CMake_VERSION;
version["major"] = CMake_VERSION_MAJOR;
version["suffix"] = CMake_VERSION_SUFFIX;
version["isDirty"] = (CMake_VERSION_IS_DIRTY == 1);
version["patch"] = CMake_VERSION_PATCH;
+ return version;
+}
- obj["version"] = version;
+Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
+{
+ Json::Value obj = Json::objectValue;
+
+ // Version information:
+ obj["version"] = this->ReportVersionJson();
// Generators:
std::vector<cmake::GeneratorInfo> generatorInfoList;
bool haveValue = false;
std::string cachedValue;
if (this->WarnUnusedCli) {
- if (const char* v = this->State->GetInitializedCacheValue(var)) {
+ if (const std::string* v =
+ this->State->GetInitializedCacheValue(var)) {
haveValue = true;
- cachedValue = v;
+ cachedValue = *v;
}
}
if (this->WarnUnusedCli) {
if (!haveValue ||
- cachedValue != this->State->GetInitializedCacheValue(var)) {
+ cachedValue != *this->State->GetInitializedCacheValue(var)) {
this->WatchUnusedCli(var);
}
}
for (std::string const& ck : cacheKeys) {
cmStateEnums::CacheEntryType t = this->State->GetCacheEntryType(ck);
if (t != cmStateEnums::STATIC) {
- if (regex.find(ck.c_str())) {
+ if (regex.find(ck)) {
entriesToDelete.push_back(ck);
}
}
bool havePlatform = false;
for (unsigned int i = 1; i < args.size(); ++i) {
std::string const& arg = args[i];
- if (arg.find("-H", 0) == 0) {
+ if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) {
directoriesSet = true;
std::string path = arg.substr(2);
+ if (path.empty()) {
+ ++i;
+ if (i >= args.size()) {
+ cmSystemTools::Error("No source directory specified for -S");
+ return;
+ }
+ path = args[i];
+ if (path[0] == '-') {
+ cmSystemTools::Error("No source directory specified for -S");
+ return;
+ }
+ }
+
path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
this->SetHomeDirectory(path);
- } else if (arg.find("-S", 0) == 0) {
- // There is no local generate anymore. Ignore -S option.
} else if (arg.find("-O", 0) == 0) {
// There is no local generate anymore. Ignore -O option.
} else if (arg.find("-B", 0) == 0) {
directoriesSet = true;
std::string path = arg.substr(2);
+ if (path.empty()) {
+ ++i;
+ if (i >= args.size()) {
+ cmSystemTools::Error("No build directory specified for -B");
+ return;
+ }
+ path = args[i];
+ if (path[0] == '-') {
+ cmSystemTools::Error("No build directory specified for -B");
+ return;
+ }
+ }
+
path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
this->SetHomeOutputDirectory(path);
this->SetHomeOutputDirectory(listPath);
} else {
// Source directory given on command line. Use current working
- // directory as build tree.
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- this->SetHomeOutputDirectory(cwd);
+ // directory as build tree if -B hasn't been given already
+ if (this->GetHomeOutputDirectory().empty()) {
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ this->SetHomeOutputDirectory(cwd);
+ }
}
return;
}
- // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
- // argument. Assume it is the path to the source tree, and use the
- // current working directory as the build tree.
- std::string full = cmSystemTools::CollapseFullPath(arg);
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- this->SetHomeDirectory(full);
- this->SetHomeOutputDirectory(cwd);
+ if (this->GetHomeDirectory().empty()) {
+ // We didn't find a CMakeLists.txt and it wasn't specified
+ // with -S. Assume it is the path to the source tree
+ std::string full = cmSystemTools::CollapseFullPath(arg);
+ this->SetHomeDirectory(full);
+ }
+ if (this->GetHomeOutputDirectory().empty()) {
+ // We didn't find a CMakeCache.txt and it wasn't specified
+ // with -B. Assume the current working directory as the build tree.
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ this->SetHomeOutputDirectory(cwd);
+ }
}
// at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
// do a sanity check on some values
if (this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY")) {
std::string cacheStart =
- this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
+ *this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
cacheStart += "/CMakeLists.txt";
std::string currentStart = this->GetHomeDirectory();
currentStart += "/CMakeLists.txt";
this->UpdateConversionPathTable();
this->CleanupCommandsAndMacros();
- int res = 0;
- if (this->GetWorkingMode() == NORMAL_MODE) {
- res = this->DoPreConfigureChecks();
- }
+ int res = this->DoPreConfigureChecks();
if (res < 0) {
return -2;
}
// no generator specified on the command line
if (!this->GlobalGenerator) {
- const char* genName =
+ const std::string* genName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
- const char* extraGenName =
+ const std::string* extraGenName =
this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
if (genName) {
std::string fullName =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- genName, extraGenName ? extraGenName : "");
+ *genName, extraGenName ? *extraGenName : "");
this->GlobalGenerator = this->CreateGlobalGenerator(fullName);
}
if (this->GlobalGenerator) {
}
}
- const char* genName =
+ const std::string* genName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
if (genName) {
- if (!this->GlobalGenerator->MatchesGeneratorName(genName)) {
+ if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) {
std::string message = "Error: generator : ";
message += this->GlobalGenerator->GetName();
message += "\nDoes not match the generator used previously: ";
- message += genName;
+ message += *genName;
message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.";
cmSystemTools::Error(message.c_str());
cmStateEnums::INTERNAL);
}
- if (const char* instance =
+ if (const std::string* instance =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
if (!this->GeneratorInstance.empty() &&
- this->GeneratorInstance != instance) {
+ this->GeneratorInstance != *instance) {
std::string message = "Error: generator instance: ";
message += this->GeneratorInstance;
message += "\nDoes not match the instance used previously: ";
- message += instance;
+ message += *instance;
message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.";
cmSystemTools::Error(message.c_str());
"Generator instance identifier.", cmStateEnums::INTERNAL);
}
- if (const char* platformName =
+ if (const std::string* platformName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
if (!this->GeneratorPlatform.empty() &&
- this->GeneratorPlatform != platformName) {
+ this->GeneratorPlatform != *platformName) {
std::string message = "Error: generator platform: ";
message += this->GeneratorPlatform;
message += "\nDoes not match the platform used previously: ";
- message += platformName;
+ message += *platformName;
message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.";
cmSystemTools::Error(message.c_str());
"Name of generator platform.", cmStateEnums::INTERNAL);
}
- if (const char* tsName =
+ if (const std::string* tsName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
- if (!this->GeneratorToolset.empty() && this->GeneratorToolset != tsName) {
+ if (!this->GeneratorToolset.empty() && this->GeneratorToolset != *tsName) {
std::string message = "Error: generator toolset: ";
message += this->GeneratorToolset;
message += "\nDoes not match the toolset used previously: ";
- message += tsName;
+ message += *tsName;
message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.";
cmSystemTools::Error(message.c_str());
"CMakeLists.txt ?");
}
- // only save the cache if there were no fatal errors
- if (this->GetWorkingMode() == NORMAL_MODE) {
- this->State->SaveVerificationScript(this->GetHomeOutputDirectory());
- this->SaveCache(this->GetHomeOutputDirectory());
- }
+ this->State->SaveVerificationScript(this->GetHomeOutputDirectory());
+ this->SaveCache(this->GetHomeOutputDirectory());
if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
}
}
int ret = this->Configure();
- if (ret || this->GetWorkingMode() != NORMAL_MODE) {
+ if (ret) {
#if defined(CMAKE_HAVE_VS_GENERATORS)
if (!this->VSSolutionFile.empty() && this->GlobalGenerator) {
// CMake is running to regenerate a Visual Studio build tree
// Save the cache again after a successful Generate so that any internal
// variables created during Generate are saved. (Specifically target GUIDs
// for the Visual Studio and Xcode generators.)
- if (this->GetWorkingMode() == NORMAL_MODE) {
- this->SaveCache(this->GetHomeOutputDirectory());
- }
+ this->SaveCache(this->GetHomeOutputDirectory());
+
return 0;
}
const char* cmake::GetCacheDefinition(const std::string& name) const
{
- return this->State->GetInitializedCacheValue(name);
+ const std::string* p = this->State->GetInitializedCacheValue(name);
+ return p ? p->c_str() : nullptr;
}
void cmake::AddScriptingCommands()
void cmake::UpdateConversionPathTable()
{
// Update the path conversion table with any specified file:
- const char* tablepath =
+ const std::string* tablepath =
this->State->GetInitializedCacheValue("CMAKE_PATH_TRANSLATION_FILE");
if (tablepath) {
- cmsys::ifstream table(tablepath);
+ cmsys::ifstream table(tablepath->c_str());
if (!table) {
- cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath,
- ". CMake can not open file.");
+ cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ",
+ tablepath->c_str(), ". CMake can not open file.");
cmSystemTools::ReportLastSystemError("CMake can not open file.");
} else {
std::string a, b;
return 1;
}
}
+ const char* cachedGeneratorPlatform =
+ this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");
+ if (cachedGeneratorPlatform) {
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
+ if (!gen->SetGeneratorPlatform(cachedGeneratorPlatform, &mf)) {
+ return 1;
+ }
+ }
std::string output;
std::string projName;
const char* cachedProjectName =
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return false;
}
- const char* extraGenName =
+ const std::string* extraGenName =
this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
std::string fullName =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- genName, extraGenName ? extraGenName : "");
+ genName, extraGenName ? *extraGenName : "");
std::unique_ptr<cmGlobalGenerator> gen(
this->CreateGlobalGenerator(fullName));
~cmake();
#if defined(CMAKE_BUILD_WITH_CMAKE)
+ Json::Value ReportVersionJson() const;
Json::Value ReportCapabilitiesJson(bool haveServerMode) const;
#endif
std::string ReportCapabilities(bool haveServerMode) const;
///! this is called by generators to update the progress
void UpdateProgress(const char* msg, float prog);
+#if defined(CMAKE_BUILD_WITH_CMAKE)
///! Get the variable watch object
cmVariableWatch* GetVariableWatch() { return this->VariableWatch; }
+#endif
void GetGeneratorDocumentation(std::vector<cmDocumentationEntry>&);
void GenerateGraphViz(const char* fileName) const;
- cmVariableWatch* VariableWatch;
-
private:
ProgressCallbackType ProgressCallback;
void* ProgressCallbackClientData;
std::string GraphVizFile;
InstalledFilesMap InstalledFiles;
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ cmVariableWatch* VariableWatch;
+#endif
+
cmState* State;
cmStateSnapshot CurrentSnapshot;
cmMessenger* Messenger;
};
#define CMAKE_STANDARD_OPTIONS_TABLE \
- { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
+ { "-S <path-to-source>", "Explicitly specify a source directory." }, \
+ { "-B <path-to-build>", "Explicitly specify a build directory." }, \
+ { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
{ "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
{ "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \
{ "-G <generator-name>", "Specify a build system generator." }, \
static const char* cmDocumentationUsage[][2] = {
{ nullptr,
" cmake [options] <path-to-source>\n"
- " cmake [options] <path-to-existing-build>" },
+ " cmake [options] <path-to-existing-build>\n"
+ " cmake [options] -S <path-to-source> -B <path-to-build>" },
{ nullptr,
"Specify a source directory to (re-)generate a build system for "
"it in the current working directory. Specify an existing build "
#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32)
# include "bindexplib.h"
+# include "cmsys/ConsoleBuf.hxx"
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__)
<< " time command [args...] - run command and display elapsed time\n"
<< " touch file - touch a file.\n"
<< " touch_nocreate file - touch a file but do not create it.\n"
+ << " create_symlink old new - create a symbolic link new -> old\n"
#if defined(_WIN32) && !defined(__CYGWIN__)
<< "Available on Windows only:\n"
<< " delete_regv key - delete registry value\n"
<< " env_vs9_wince sdkname - displays a batch file which sets the "
"environment for the provided Windows CE SDK installed in VS2008\n"
<< " write_regv key value - write registry value\n"
-#else
- << "Available on UNIX only:\n"
- << " create_symlink old new - create a symbolic link new -> old\n"
#endif
;
/* clang-format on */
return 1;
}
if (!cmSystemTools::CreateSymlink(args[2], args[3])) {
- std::string emsg = cmSystemTools::GetLastSystemError();
- std::cerr << "failed to create symbolic link '" << destinationFileName
- << "': " << emsg << "\n";
return 1;
}
return 0;
if (args.size() >= 9 && args[8].length() >= 8 &&
args[8].substr(0, 8) == "--color=") {
// Enable or disable color based on the switch value.
- color = (args[8].size() == 8 ||
- cmSystemTools::IsOn(args[8].substr(8).c_str()));
+ color =
+ (args[8].size() == 8 || cmSystemTools::IsOn(args[8].substr(8)));
}
} else {
// Support older signature for existing makefiles:
// Enable or disable color based on the switch value.
std::string value = args[i].substr(9);
if (!value.empty()) {
- enabled = cmSystemTools::IsOn(value.c_str());
+ enabled = cmSystemTools::IsOn(value);
}
} else if (cmHasLiteralPrefix(args[i], "--progress-dir=")) {
progressDir = args[i].substr(15);
bool verbose = false;
if (args.size() >= 4) {
if (args[3].find("--verbose=") == 0) {
- if (!cmSystemTools::IsOff(args[3].substr(10).c_str())) {
+ if (!cmSystemTools::IsOff(args[3].substr(10))) {
verbose = true;
}
}
// still works.
int cmcmd::VisualStudioLink(std::vector<std::string> const& args, int type)
{
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+ // Replace streambuf so we output in the system codepage. CMake is set up
+ // to output in Unicode (see SetUTF8Pipes) but the Visual Studio linker
+ // outputs using the system codepage so we need to change behavior when
+ // we run the link command.
+ cmsys::ConsoleBuf::Manager consoleOut(std::cout);
+ cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
+#endif
+
if (args.size() < 2) {
return -1;
}
if (!fout) {
return -1;
}
+ // Insert a pragma statement to specify utf-8 encoding.
+ fout << "#pragma code_page(65001)\n";
fout << this->Type
<< " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
"24 /* RT_MANIFEST */ \""
static const char* cmDocumentationOptions[][2] = {
{ "-C <cfg>, --build-config <cfg>", "Choose configuration to test." },
+ { "--progress", "Enable short progress output from tests." },
{ "-V,--verbose", "Enable verbose output from tests." },
{ "-VV,--extra-verbose", "Enable more verbose output from tests." },
{ "--debug", "Displaying more verbose internals of CTest." },
# target_link_libraries. Because of how interface
# properties propagate, this target is not suitable
# for use with PUBLIC or INTERFACE linking.
+# KWSYS_ALIAS_TARGET = The name of an alias target to create to the actual target.
#
# Example:
#
ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} ${KWSYS_LIBRARY_TYPE}
${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS})
ENDIF()
+ if (KWSYS_ALIAS_TARGET)
+ add_library(${KWSYS_ALIAS_TARGET} ALIAS ${KWSYS_TARGET_INTERFACE})
+ endif ()
SET_TARGET_PROPERTIES(${KWSYS_TARGET_OBJECT} PROPERTIES
C_CLANG_TIDY ""
CXX_CLANG_TIDY ""
# Some Apple compilers produce bad optimizations in this source.
IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$")
SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0")
- 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"))
+ ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL")
# 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(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010")
+ IF(CMAKE_SYSTEM MATCHES "Linux.*ppc64le"
+ AND CMAKE_C_COMPILER_VERSION VERSION_LESS "16.1.0"
+ AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1")
+ # v13.1.[1-6] on Linux ppc64le is clang based and does not accept
+ # the -qsuppress option, so just suppress all warnings.
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -w")
+ ELSE()
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010")
+ ENDIF()
ENDIF()
IF(CMAKE_C_FLAGS MATCHES "-fsanitize=")
SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT")
wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN);
DWORD error;
cp->PipeChildStd[0] =
- CreateFileW(wstdin, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ CreateFileW(wstdin, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+ OPEN_EXISTING, 0, 0);
error = GetLastError(); /* Check now in case free changes this. */
free(wstdin);
if (cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) {
# endif
#endif
-#if defined(__linux) || defined(__sun) || defined(_SCO_DS)
+#if defined(__linux) || defined(__sun) || defined(_SCO_DS) || \
+ defined(__GLIBC__) || defined(__GNU__)
# include <netdb.h>
# include <netinet/in.h>
# include <sys/socket.h>
// Chip Model Name
this->ChipID.ModelName =
- this->ExtractValueFromCpuInfoFile(buffer, "model name").c_str();
+ this->ExtractValueFromCpuInfoFile(buffer, "model name");
// L1 Cache size
// Different architectures may show different names for the caches.
std::string SystemInformationImplementation::RunProcess(
std::vector<const char*> args)
{
- std::string buffer = "";
+ std::string buffer;
// Run the application
kwsysProcess* gp = kwsysProcess_New();
std::string SystemInformationImplementation::ParseValueFromKStat(
const char* arguments)
{
- std::vector<const char*> args;
- args.clear();
- args.push_back("kstat");
- args.push_back("-p");
-
+ std::vector<std::string> args_string;
std::string command = arguments;
size_t start = std::string::npos;
size_t pos = command.find(' ', 0);
}
if (!inQuotes) {
- std::string arg = command.substr(start + 1, pos - start - 1);
+ args_string.push_back(command.substr(start + 1, pos - start - 1));
+ std::string& arg = args_string.back();
// Remove the quotes if any
- size_t quotes = arg.find('"');
- while (quotes != std::string::npos) {
- arg.erase(quotes, 1);
- quotes = arg.find('"');
- }
- args.push_back(arg.c_str());
+ arg.erase(std::remove(arg.begin(), arg.end(), '"'), arg.end());
start = pos;
}
pos = command.find(' ', pos + 1);
}
- std::string lastArg = command.substr(start + 1, command.size() - start - 1);
- args.push_back(lastArg.c_str());
+ args_string.push_back(command.substr(start + 1, command.size() - start - 1));
+ std::vector<const char*> args;
+ args.reserve(3 + args_string.size());
+ args.push_back("kstat");
+ args.push_back("-p");
+ for (size_t i = 0; i < args_string.size(); ++i) {
+ args.push_back(args_string[i].c_str());
+ }
args.push_back(KWSYS_NULLPTR);
std::string buffer = this->RunProcess(args);
- std::string value = "";
+ std::string value;
for (size_t i = buffer.size() - 1; i > 0; i--) {
if (buffer[i] == ' ' || buffer[i] == '\t') {
break;
}
if (buffer[i] != '\n' && buffer[i] != '\r') {
- std::string val = value;
- value = buffer[i];
- value += val;
+ value.insert(0u, 1, buffer[i]);
}
}
return value;
for (iterator i = this->begin(); i != this->end(); ++i) {
# if defined(_WIN32)
const std::string s = Encoding::ToNarrow(*i);
- kwsysUnPutEnv(s.c_str());
+ kwsysUnPutEnv(s);
# else
kwsysUnPutEnv(*i);
# endif
}
return access(filename.c_str(), R_OK) == 0;
#elif defined(_WIN32)
- return (
- GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()) !=
- INVALID_FILE_ATTRIBUTES);
+ DWORD attr =
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str());
+ if (attr == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
+ // Using 0 instead of GENERIC_READ as it allows reading of file attributes
+ // even if we do not have permission to read the file itself
+ HANDLE handle =
+ CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), 0, 0,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ CloseHandle(handle);
+ }
+
+ return true;
#else
// SCO OpenServer 5.0.7/3.2's command has 711 permission.
# if defined(_SCO_DS)
return n;
}
-std::vector<kwsys::String> SystemTools::SplitString(const std::string& p,
- char sep, bool isPath)
+std::vector<std::string> SystemTools::SplitString(const std::string& p,
+ char sep, bool isPath)
{
std::string path = p;
- std::vector<kwsys::String> paths;
+ std::vector<std::string> paths;
if (path.empty()) {
return paths;
}
}
// escape spaces and () in the path
if (ret.find_first_of(" ") != std::string::npos) {
- std::string result = "";
+ std::string result;
char lastch = 1;
for (const char* ch = ret.c_str(); *ch != '\0'; ++ch) {
// if it is already escaped then don't try to escape it again
void SystemTools::AddKeepPath(const std::string& dir)
{
std::string cdir;
- Realpath(SystemTools::CollapseFullPath(dir).c_str(), cdir);
+ Realpath(SystemTools::CollapseFullPath(dir), cdir);
SystemTools::AddTranslationPath(cdir, dir);
}
std::string r = SystemTools::CollapseFullPath(remote);
// split up both paths into arrays of strings using / as a separator
- std::vector<kwsys::String> localSplit =
- SystemTools::SplitString(l, '/', true);
- std::vector<kwsys::String> remoteSplit =
+ std::vector<std::string> localSplit = SystemTools::SplitString(l, '/', true);
+ std::vector<std::string> remoteSplit =
SystemTools::SplitString(r, '/', true);
- std::vector<kwsys::String>
+ std::vector<std::string>
commonPath; // store shared parts of path in this array
- std::vector<kwsys::String> finalPath; // store the final relative path here
+ std::vector<std::string> finalPath; // store the final relative path here
// count up how many matching directory names there are from the start
unsigned int sameCount = 0;
while (((sameCount <= (localSplit.size() - 1)) &&
}
// for each entry that is not common in the remote path add it
// to the final path.
- for (std::vector<String>::iterator vit = remoteSplit.begin();
+ for (std::vector<std::string>::iterator vit = remoteSplit.begin();
vit != remoteSplit.end(); ++vit) {
if (!vit->empty()) {
finalPath.push_back(*vit);
std::string relativePath; // result string
// now turn the array of directories into a unix path by puttint /
// between each entry that does not already have one
- for (std::vector<String>::iterator vit1 = finalPath.begin();
+ for (std::vector<std::string>::iterator vit1 = finalPath.begin();
vit1 != finalPath.end(); ++vit1) {
if (!relativePath.empty() && *relativePath.rbegin() != '/') {
relativePath += "/";
while (lpos < data.length()) {
std::string::size_type rpos = data.find_first_of(separator, lpos);
if (rpos == std::string::npos) {
- // Line ends at end of string without a newline.
+ // String ends at end of string without a separator.
lines.push_back(data.substr(lpos));
return false;
} else {
- // Line ends in a "\n", remove the character.
+ // String ends in a separator, remove the character.
lines.push_back(data.substr(lpos, rpos - lpos));
}
lpos = rpos + 1;
std::string data(str);
std::string::size_type lpos = 0;
while (lpos < data.length()) {
- std::string::size_type rpos = data.find_first_of("\n", lpos);
+ std::string::size_type rpos = data.find_first_of('\n', lpos);
if (rpos == std::string::npos) {
// Line ends at end of string without a newline.
lines.push_back(data.substr(lpos));
#include <string>
#include <vector>
-#include <@KWSYS_NAMESPACE@/String.hxx>
-
#include <sys/types.h>
// include sys/stat.h after sys/types.h
#include <sys/stat.h>
s starts with a / then the first element of the returned array will
be /, so /foo/bar will be [/, foo, bar]
*/
- static std::vector<String> SplitString(const std::string& s,
- char separator = '/',
- bool isPath = false);
+ static std::vector<std::string> SplitString(const std::string& s,
+ char separator = '/',
+ bool isPath = false);
/**
* Perform a case-independent string comparison
*/
/* List of terminal names known to support VT100 color escape sequences. */
static const char* kwsysTerminalVT100Names[] = { "Eterm",
+ "alacritty",
+ "alacritty-direct",
"ansi",
"color-xterm",
"con132x25",
}
/* VT100 escape sequence strings. */
-#define KWSYS_TERMINAL_VT100_NORMAL "\33[0m"
-#define KWSYS_TERMINAL_VT100_BOLD "\33[1m"
-#define KWSYS_TERMINAL_VT100_UNDERLINE "\33[4m"
-#define KWSYS_TERMINAL_VT100_BLINK "\33[5m"
-#define KWSYS_TERMINAL_VT100_INVERSE "\33[7m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK "\33[30m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_RED "\33[31m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN "\33[32m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW "\33[33m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE "\33[34m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA "\33[35m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN "\33[36m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE "\33[37m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK "\33[40m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_RED "\33[41m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN "\33[42m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW "\33[43m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE "\33[44m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA "\33[45m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN "\33[46m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE "\33[47m"
+#if defined(__MVS__)
+/* if building on z/OS (aka MVS), assume we are using EBCDIC */
+# define ESCAPE_CHAR "\47"
+#else
+# define ESCAPE_CHAR "\33"
+#endif
+
+#define KWSYS_TERMINAL_VT100_NORMAL ESCAPE_CHAR "[0m"
+#define KWSYS_TERMINAL_VT100_BOLD ESCAPE_CHAR "[1m"
+#define KWSYS_TERMINAL_VT100_UNDERLINE ESCAPE_CHAR "[4m"
+#define KWSYS_TERMINAL_VT100_BLINK ESCAPE_CHAR "[5m"
+#define KWSYS_TERMINAL_VT100_INVERSE ESCAPE_CHAR "[7m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK ESCAPE_CHAR "[30m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_RED ESCAPE_CHAR "[31m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN ESCAPE_CHAR "[32m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW ESCAPE_CHAR "[33m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE ESCAPE_CHAR "[34m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA ESCAPE_CHAR "[35m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN ESCAPE_CHAR "[36m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE ESCAPE_CHAR "[37m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK ESCAPE_CHAR "[40m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_RED ESCAPE_CHAR "[41m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN ESCAPE_CHAR "[42m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW ESCAPE_CHAR "[43m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE ESCAPE_CHAR "[44m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA ESCAPE_CHAR "[45m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN ESCAPE_CHAR "[46m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE ESCAPE_CHAR "[47m"
/* Write VT100 escape sequences to the stream for the given color. */
static void kwsysTerminalSetVT100Color(FILE* stream, int color)
int some_int_variable = 10;
double some_double_variable = 10.10;
char* some_string_variable = KWSYS_NULLPTR;
- std::string some_stl_string_variable = "";
+ std::string some_stl_string_variable;
bool some_bool_variable = false;
bool some_bool_variable1 = false;
bool bool_arg1 = false;
res = false;
}
- if (!kwsys::SystemTools::Touch(testNewFile.c_str(), true)) {
+ if (!kwsys::SystemTools::Touch(testNewFile, true)) {
std::cerr << "Problem with Touch for: " << testNewFile << std::endl;
res = false;
}
res = false;
}
- kwsys::SystemTools::Touch(testNewFile.c_str(), true);
+ kwsys::SystemTools::Touch(testNewFile, true);
if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) {
std::cerr << "Problem with RemoveADirectory for: " << testNewDir
<< std::endl;
const std::string testFindFile(TEST_SYSTEMTOOLS_BINARY_DIR "/" +
testFindFileName);
- if (!kwsys::SystemTools::Touch(testFindFile.c_str(), true)) {
+ if (!kwsys::SystemTools::Touch(testFindFile, true)) {
std::cerr << "Problem with Touch for: " << testFindFile << std::endl;
// abort here as the existence of the file only makes the test meaningful
return false;
<DataSource Persistence="ProjectFile" ItemType="NASM" SourceType="Item"/>
</StringProperty.DataSource>
</StringProperty>
- <StringProperty Name="OutputFormat" Category="Assembler Options" HelpUrl="http://www.nasm.us/doc/" DisplayName="Output File Name" Description="Specify Output Filename.-o [value]" Switch="-o [value]"/>
+ <StringProperty Name="OutputFormat" Category="Assembler Options" HelpUrl="http://www.nasm.us/doc/" DisplayName="Output File Name" Description="Specify Output Filename.-o [value]" Switch="-o "[value]""/>
<BoolProperty Name="tasmmode" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="SciTech TASM compatible mode" Description="assemble in SciTech TASM compatible mode" Switch="-t"/>
<EnumProperty Name="Outputswitch" Category="Assembler Options" HelpUrl="http://www.nasm.us/doc/" DisplayName="Output Switch" Description="Select the type of output format required. Linking Should be disabled for ELF and Binary ,else error will popup">
<EnumValue Name="0" DisplayName="Object File win32" Switch="-fwin32"/>
<BoolProperty Name="GenerateDebugInformation" Category="Assembler Options" DisplayName="Generate Debug Information" Description="Generates Debug Information. (-g)" HelpUrl="http://www.nasm.us/doc/" Switch="-g"/>
<StringListProperty Name="ErrorReporting" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Redirect Error Messages to File" Description="Drops the error Message on specified device" Switch="-Z "[value]""/>
<StringListProperty Name="IncludePaths" Category="General" DisplayName="Include Paths" Description="Sets path for include file. (-I[path])" HelpUrl="http://www.nasm.us/doc/" Switch="-I"[value]""/>
- <StringListProperty Name="PreprocessorDefinitions" Category="Preprocessor" HelpUrl="http://www.nasm.us/doc/" DisplayName="Preprocessor Definitions" Description="Defines a text macro with the given name. (-D[symbol])" Switch="-D[value]"/>
- <StringListProperty Name="UndefinePreprocessorDefinitions" Category="Preprocessor" HelpUrl="http://www.nasm.us/doc/" DisplayName="Undefine Preprocessor Definitions" Description="Undefines a text macro with the given name. (-U[symbol])" Switch="-U[value]"/>
+ <StringListProperty Name="PreprocessorDefinitions" Category="Preprocessor" HelpUrl="http://www.nasm.us/doc/" DisplayName="Preprocessor Definitions" Description="Defines a text macro with the given name. (-D[symbol])" Switch="-D"[value]""/>
+ <StringListProperty Name="UndefinePreprocessorDefinitions" Category="Preprocessor" HelpUrl="http://www.nasm.us/doc/" DisplayName="Undefine Preprocessor Definitions" Description="Undefines a text macro with the given name. (-U[symbol])" Switch="-U"[value]""/>
<EnumProperty Name="ErrorReportingFormat" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Error Reporting Format" Description="Select the error reporting format ie. GNU or VC">
<EnumValue Name="0" DisplayName="-Xgnu GNU format: Default format" Switch="-Xgnu"/>
<EnumValue Name="1" DisplayName="-Xvc Style used by Microsoft Visual C++" Switch="-Xvc"/>
${TEST_LINK_DEPENDS}
")
endif()
+
+ set(linkdep2 ${BuildDepends_BINARY_DIR}/Project/linkdep2${CMAKE_EXECUTABLE_SUFFIX})
+ if(${linkdep2} IS_NEWER_THAN ${TEST_LINK_DEPENDS})
+ message("INTERFACE_LINK_DEPENDS worked")
+ else()
+ message(SEND_ERROR "INTERFACE_LINK_DEPENDS failed. Executable
+ ${linkdep2}
+is not newer than dependency
+ ${TEST_LINK_DEPENDS}
+")
+ endif()
endif()
if(EXISTS "${link_depends_no_shared_check_txt}")
if(TEST_LINK_DEPENDS)
add_executable(linkdep linkdep.cxx)
- set_property(TARGET linkdep PROPERTY LINK_DEPENDS ${TEST_LINK_DEPENDS})
+ set_property(TARGET linkdep PROPERTY LINK_DEPENDS $<1:${TEST_LINK_DEPENDS}>)
+
+ add_library(foo_interface INTERFACE)
+ set_property(TARGET foo_interface PROPERTY INTERFACE_LINK_DEPENDS $<1:${TEST_LINK_DEPENDS}>)
+ add_executable(linkdep2 linkdep.cxx)
+ target_link_libraries(linkdep2 PRIVATE foo_interface)
endif()
add_library(link_depends_no_shared_lib SHARED link_depends_no_shared_lib.c
--- /dev/null
+cmake_minimum_required(VERSION 3.11)
+
+project(add_link_options LANGUAGES C)
+
+
+add_link_options(-LINK_FLAG)
+
+add_executable(add_link_options EXCLUDE_FROM_ALL LinkOptionsExe.c)
+
+get_target_property(result add_link_options LINK_OPTIONS)
+if (NOT result MATCHES "-LINK_FLAG")
+ message(SEND_ERROR "add_link_options not populated the LINK_OPTIONS target property")
+endif()
+
+
+add_library(imp UNKNOWN IMPORTED)
+get_target_property(result imp LINK_OPTIONS)
+if (result)
+ message(FATAL_ERROR "add_link_options populated the LINK_OPTIONS target property")
+endif()
--- /dev/null
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+
+project(link_directories LANGUAGES C)
+
+
+link_directories(/A)
+link_directories(BEFORE /B)
+
+set(CMAKE_LINK_DIRECTORIES_BEFORE ON)
+link_directories(/C)
+
+get_directory_property(result LINK_DIRECTORIES)
+if (NOT result MATCHES "/C;/B;/A")
+ message(SEND_ERROR "link_directories not populated the LINK_DIRECTORIES directory property")
+endif()
+
+
+add_executable(link_directories EXCLUDE_FROM_ALL LinkDirectoriesExe.c)
+
+get_target_property(result link_directories LINK_DIRECTORIES)
+if (NOT result MATCHES "/C;/B;/A")
+ message(SEND_ERROR "link_directories not populated the LINK_DIRECTORIES target property")
+endif()
+
+
+add_library(imp UNKNOWN IMPORTED)
+get_target_property(result imp LINK_DIRECTORIES)
+if (result)
+ message(FATAL_ERROR "link_directories populated the LINK_DIRECTORIES target property")
+endif()
--- /dev/null
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+
+cmake_minimum_required(VERSION 3.12)
+
+project(target_link_directories LANGUAGES C)
+
+add_library(target_link_directories SHARED LinkDirectoriesLib.c)
+# Test no items
+target_link_directories(target_link_directories PRIVATE)
+
+add_library(target_link_directories_2 SHARED EXCLUDE_FROM_ALL LinkDirectoriesLib.c)
+target_link_directories(target_link_directories_2 PRIVATE /private/dir INTERFACE /interface/dir)
+get_target_property(result target_link_directories_2 LINK_DIRECTORIES)
+if (NOT result MATCHES "/private/dir")
+ message(SEND_ERROR "${result} target_link_directories not populated the LINK_DIRECTORIES target property")
+endif()
+get_target_property(result target_link_directories_2 INTERFACE_LINK_DIRECTORIES)
+if (NOT result MATCHES "/interface/dir")
+ message(SEND_ERROR "target_link_directories not populated the INTERFACE_LINK_DIRECTORIES target property of shared library")
+endif()
+
+add_library(target_link_directories_3 STATIC EXCLUDE_FROM_ALL LinkDirectoriesLib.c)
+target_link_directories(target_link_directories_3 INTERFACE /interface/dir)
+get_target_property(result target_link_directories_3 INTERFACE_LINK_DIRECTORIES)
+if (NOT result MATCHES "/interface/dir")
+ message(SEND_ERROR "target_link_directories not populated the INTERFACE_LINK_DIRECTORIES target property of static library")
+endif()
+
+add_library(target_link_directories_4 SHARED EXCLUDE_FROM_ALL LinkDirectoriesLib.c)
+target_link_directories(target_link_directories_4 PRIVATE relative/dir)
+get_target_property(result target_link_directories_4 LINK_DIRECTORIES)
+if (NOT result MATCHES "${CMAKE_CURRENT_SOURCE_DIR}/relative/dir")
+ message(SEND_ERROR "target_link_directories not populated the LINK_DIRECTORIES with relative path")
+endif()
+
+add_subdirectory(subdir)
+target_link_directories(target_link_directories_5 PRIVATE relative/dir)
+get_target_property(result target_link_directories_5 LINK_DIRECTORIES)
+if (NOT result MATCHES "${CMAKE_CURRENT_SOURCE_DIR}/relative/dir")
+ message(SEND_ERROR "target_link_directories not populated the LINK_DIRECTORIES with relative path")
+endif()
--- /dev/null
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ int flags_lib(void)
+{
+ return 0;
+}
--- /dev/null
+
+add_library(target_link_directories_5 SHARED EXCLUDE_FROM_ALL ../LinkDirectoriesLib.c)
assert_property(newsignature1 INTERFACE_LINK_LIBRARIES "depD;depB")
assert_property(newsignature1 LINK_LIBRARIES "depC;depB;subdirlib")
+
+#----------------------------------------------------------------------------
+# Test cross-directory linking.
+cmake_policy(PUSH)
+cmake_policy(SET CMP0079 NEW)
+add_executable(TopDir TopDir.c)
+add_subdirectory(SubDirA)
+add_subdirectory(SubDirB)
+target_link_libraries(SubDirB TopDirImported)
+add_library(TopDirImported IMPORTED INTERFACE)
+target_compile_definitions(TopDirImported INTERFACE DEF_TopDirImported)
+cmake_policy(POP)
--- /dev/null
+add_executable(SubDirA SubDirA.c)
+
+# Link to a target imported in this directory that would not normally
+# be visible to the directory in which TopDir is defined.
+target_link_libraries(TopDir PUBLIC SameNameImported)
+
+# Link SubDirA to a target imported in this directory that has the same
+# name as a target imported in SubDirB's directory. SubDirB will also
+# tell us to link its copy. At compile time we verify both are linked.
+target_link_libraries(SubDirA PRIVATE SameNameImported)
+
+# Import a target with the same name as a target imported in SubDirB.
+# Distinguish this copy by having a unique usage requirement.
+add_library(SameNameImported IMPORTED INTERFACE)
+target_compile_definitions(SameNameImported INTERFACE DEF_SameNameImportedSubDirA)
--- /dev/null
+#ifndef DEF_SameNameImportedSubDirA
+# error "DEF_SameNameImportedSubDirA is not defined but should be!"
+#endif
+#ifndef DEF_SameNameImportedSubDirB
+# error "DEF_SameNameImportedSubDirB is not defined but should be!"
+#endif
+#ifdef DEF_TopDirImported
+# error "DEF_TopDirImported is defined but should not be!"
+#endif
+
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+add_executable(SubDirB SubDirB.c)
+
+# Link to a target imported in this directory that would not normally
+# be visible to the directory in which TopDir is defined.
+target_link_libraries(TopDir PUBLIC SameNameImported)
+
+# Link SubDirA to a target imported in this directory that has the same
+# name as a target imported in SubDirA's directory. We verify when
+# compiling SubDirA that it sees our target and its own.
+target_link_libraries(SubDirA PRIVATE SameNameImported)
+
+# Import a target with the same name as a target imported in SubDirA.
+# Distinguish this copy by having a unique usage requirement.
+add_library(SameNameImported IMPORTED INTERFACE)
+target_compile_definitions(SameNameImported INTERFACE DEF_SameNameImportedSubDirB)
--- /dev/null
+#ifdef DEF_SameNameImportedSubDirA
+# error "DEF_SameNameImportedSubDirA is defined but should not be!"
+#endif
+#ifdef DEF_SameNameImportedSubDirB
+# error "DEF_SameNameImportedSubDirB is defined but should not be!"
+#endif
+#ifndef DEF_TopDirImported
+# error "DEF_TopDirImported is not defined but should be!"
+#endif
+
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+#ifndef DEF_SameNameImportedSubDirA
+# error "DEF_SameNameImportedSubDirA is not defined but should be!"
+#endif
+#ifndef DEF_SameNameImportedSubDirB
+# error "DEF_SameNameImportedSubDirB is not defined but should be!"
+#endif
+#ifdef DEF_TopDirImported
+# error "DEF_TopDirImported is defined but should not be!"
+#endif
+
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+
+cmake_minimum_required(VERSION 3.11)
+
+project(target_link_options LANGUAGES C)
+
+add_library(target_link_options SHARED LinkOptionsLib.c)
+# Test no items
+target_link_options(target_link_options PRIVATE)
+
+add_library(target_link_options_2 SHARED EXCLUDE_FROM_ALL LinkOptionsLib.c)
+target_link_options(target_link_options_2 PRIVATE -PRIVATE_FLAG INTERFACE -INTERFACE_FLAG)
+get_target_property(result target_link_options_2 LINK_OPTIONS)
+if (NOT result MATCHES "-PRIVATE_FLAG")
+ message(SEND_ERROR "target_link_options not populated the LINK_OPTIONS target property")
+endif()
+get_target_property(result target_link_options_2 INTERFACE_LINK_OPTIONS)
+if (NOT result MATCHES "-INTERFACE_FLAG")
+ message(SEND_ERROR "target_link_options not populated the INTERFACE_LINK_OPTIONS target property of shared library")
+endif()
+
+add_library(target_link_options_3 STATIC EXCLUDE_FROM_ALL LinkOptionsLib.c)
+target_link_options(target_link_options_3 INTERFACE -INTERFACE_FLAG)
+get_target_property(result target_link_options_3 INTERFACE_LINK_OPTIONS)
+if (NOT result MATCHES "-INTERFACE_FLAG")
+ message(SEND_ERROR "target_link_options not populated the INTERFACE_LINK_OPTIONS target property of static library")
+endif()
+
+add_library(target_link_options_4 SHARED EXCLUDE_FROM_ALL LinkOptionsLib.c)
+target_link_options(target_link_options_4 PRIVATE -PRIVATE_FLAG)
+target_link_options(target_link_options_4 BEFORE PRIVATE -BEFORE_PRIVATE_FLAG)
+get_target_property(result target_link_options_4 LINK_OPTIONS)
+if (NOT result MATCHES "-BEFORE_PRIVATE_FLAG.*-PRIVATE_FLAG")
+ message(SEND_ERROR "target_link_options not managing correctly 'BEFORE' keyword")
+endif()
--- /dev/null
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ int flags_lib(void)
+{
+ return 0;
+}
--- /dev/null
+
+cmake_minimum_required(VERSION 3.12)
+cmake_policy(SET CMP0076 NEW)
+
+project(target_sources)
+
+add_library(target_sources_lib)
+target_compile_definitions(target_sources_lib PRIVATE "-DIS_LIB")
+add_subdirectory(subdir)
+
+set(subdir_fullpath "${CMAKE_CURRENT_LIST_DIR}/subdir")
+
+get_property(target_sources_lib_property TARGET target_sources_lib PROPERTY SOURCES)
+if (NOT "$<1:${subdir_fullpath}/subdir_empty_1.cpp>" IN_LIST target_sources_lib_property)
+ message(SEND_ERROR "target_sources_lib: Generator expression to absolute sub directory file not found")
+endif()
+if (NOT "$<1:${subdir_fullpath}/../empty_1.cpp>" IN_LIST target_sources_lib_property)
+ message(SEND_ERROR "target_sources_lib: Generator expression to absolute main directory file not found")
+endif()
+if (NOT "${subdir_fullpath}/subdir_empty_2.cpp" IN_LIST target_sources_lib_property)
+ message(SEND_ERROR "target_sources_lib: Relative sub directory file not converted to absolute")
+endif()
+if (NOT "$<1:empty_2.cpp>" IN_LIST target_sources_lib_property)
+ message(SEND_ERROR "target_sources_lib: Generator expression to relative main directory file not found")
+endif()
+if (NOT "${subdir_fullpath}/../empty_3.cpp" IN_LIST target_sources_lib_property)
+ message(SEND_ERROR "target_sources_lib: Relative main directory file not converted to absolute")
+endif()
+
+add_executable(target_sources main.cpp)
+target_link_libraries(target_sources target_sources_lib)
+
+get_property(target_sources_property TARGET target_sources PROPERTY SOURCES)
+if (NOT "main.cpp" IN_LIST target_sources_property)
+ message(SEND_ERROR "target_sources: Relative main directory file converted to absolute")
+endif()
--- /dev/null
+#ifdef IS_LIB
+
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+ int internal_empty_1()
+{
+ return 0;
+}
+
+#else
+
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+ int empty_1()
+{
+ return 0;
+}
+
+#endif
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty_2()
+{
+ return 0;
+}
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty_3()
+{
+ return 0;
+}
--- /dev/null
+#include <iostream>
+
+int empty_1();
+int subdir_empty_1();
+int subdir_empty_2();
+
+int main()
+{
+ int e1 = empty_1();
+ int se1 = subdir_empty_1();
+ int se2 = subdir_empty_2();
+
+ std::cout << e1 << " " << se1 << " " << se2 << std::endl;
+
+ return 0;
+}
--- /dev/null
+
+target_sources(target_sources_lib PUBLIC $<1:${CMAKE_CURRENT_LIST_DIR}/subdir_empty_1.cpp>
+ $<1:${CMAKE_CURRENT_LIST_DIR}/../empty_1.cpp>
+ subdir_empty_2.cpp
+ PRIVATE $<1:empty_2.cpp>
+ ../empty_3.cpp)
--- /dev/null
+#ifdef IS_LIB
+
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+ int internal_subdir_empty_1()
+{
+ return 0;
+}
+
+#else
+
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+ int subdir_empty_1()
+{
+ return 0;
+}
+
+#endif
--- /dev/null
+#ifdef IS_LIB
+
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+ int internal_subdir_empty_2()
+{
+ return 0;
+}
+
+#else
+
+# ifdef _WIN32
+__declspec(dllexport)
+# endif
+ int subdir_empty_2()
+{
+ return 0;
+}
+
+#endif
Environment variable ``SOME_ENV_VAR``.
Environment variable ``some env var`` with space and target.
Generator ``Some Generator`` with space.
+Generator ``Some Generator`` with space.
Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
Inline link Link Text.
Inline link Link Text <With \-escaped Brackets>.
Environment variable :envvar:`SOME_ENV_VAR`.
Environment variable :envvar:`some env var <SOME_ENV_VAR>` with space and target.
Generator :generator:`Some Generator` with space.
+Generator :cpack_gen:`Some Generator` with space.
Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
Inline link `Link Text <ExternalDest>`_.
Inline link `Link Text \<With \\-escaped Brackets\> <ExternalDest>`_.
cmAssert(cmSystemTools::strverscmp("99999999999999", "99999999999991") > 0,
"strverscmp natural overflow");
cmAssert(cmSystemTools::strverscmp("00000000000009", "00000000000001") > 0,
- "strverscmp deciaml precision");
+ "strverscmp decimal precision");
cmAssert(cmSystemTools::strverscmp("a.b.c.0", "a.b.c.000") > 0,
"strverscmp multiple zeros");
cmAssert(cmSystemTools::strverscmp("lib_1.2_10", "lib_1.2_2") > 0,
ADD_TEST_MACRO(CxxSubdirC CxxSubdirC)
ADD_TEST_MACRO(IPO COnly/COnly)
ADD_TEST_MACRO(OutDir runtime/OutDir)
+ ADD_TEST_MACRO(OutName exe.OutName.exe)
ADD_TEST_MACRO(ObjectLibrary UseCshared)
ADD_TEST_MACRO(NewlineArgs NewlineArgs)
ADD_TEST_MACRO(SetLang SetLang)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
ADD_TEST_MACRO(AliasTarget AliasTarget)
ADD_TEST_MACRO(StagingPrefix StagingPrefix)
+ ADD_TEST_MACRO(ImportedSameName ImportedSameName)
ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary)
if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BuildDepends")
- set(SimpleInstallInstallDir
- "${CMake_BINARY_DIR}/Tests/SimpleInstall/InstallDirectory")
- add_test(SimpleInstall ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/SimpleInstall"
- "${CMake_BINARY_DIR}/Tests/SimpleInstall"
- ${build_generator_args}
- --build-project TestSimpleInstall
- --build-two-config
- --build-options ${build_options}
- "-DCMAKE_INSTALL_PREFIX:PATH=${SimpleInstallInstallDir}"
- "-DCTEST_TEST_CPACK:BOOL=${CTEST_TEST_CPACK}"
- --test-command ${SimpleInstallInstallDir}/MyTest/bin/SimpleInstExe)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SimpleInstall")
- add_test(SimpleInstall-Stage2 ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/SimpleInstallS2"
- "${CMake_BINARY_DIR}/Tests/SimpleInstallS2"
- ${build_generator_args}
- --build-project TestSimpleInstall
- --build-two-config
- --build-options ${build_options}
- "-DCMAKE_INSTALL_PREFIX:PATH=${SimpleInstallInstallDir}"
- "-DSTAGE2:BOOL=1"
- --test-command ${SimpleInstallInstallDir}/MyTest/bin/SimpleInstExeS2)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SimpleInstallS2")
-
set(MissingInstallInstallDir
"${CMake_BINARY_DIR}/Tests/MissingInstall/InstallDirectory")
add_test(MissingInstall ${CMAKE_CTEST_COMMAND}
set_tests_properties ( testdriver2 PROPERTIES DEPENDS testdriver1)
set_tests_properties ( testdriver3 PROPERTIES DEPENDS testdriver2)
set_tests_properties ( linkorder2 PROPERTIES DEPENDS linkorder1)
- set_tests_properties ( SimpleInstall-Stage2 PROPERTIES DEPENDS SimpleInstall)
# Test static linking on toolchains known to support it.
if(CMAKE_C_COMPILER_ID STREQUAL "GNU"
message(STATUS
".vcproj file association indicates VCExpress, avoiding MFC test")
set(CTEST_RUN_MFC OFF)
+ elseif( NOT ov )
+ message(STATUS
+ ".vcproj has no file association, avoiding MFC test")
+ set(CTEST_RUN_MFC OFF)
endif()
endif()
set(reg_vs10 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0;InstallDir]")
set(reg_vs11 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0;InstallDir]")
set(reg_vs12 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0;InstallDir]")
- set(reg_vs14 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]")
+ set(reg_vs14 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0;InstallDir]")
set(reg_ws80 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v8.0;InstallationFolder]")
set(reg_ws81 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v8.1;InstallationFolder]")
set(reg_ws10_0 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\Setup\\Build Tools for Windows 10;srcPath]")
get_filename_component(ntver "[HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion;CurrentVersion]" NAME)
if(WIN32 AND ntver VERSION_GREATER 6.1) # Windows >= 8.0
- macro(add_test_VSWinStorePhone name generator systemName systemVersion)
+ macro(add_test_VSWinStorePhone name generator systemName systemVersion architecture)
add_test(NAME VSWinStorePhone.${name} COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/VSWinStorePhone"
"${CMake_BINARY_DIR}/Tests/VSWinStorePhone/${name}"
--build-generator "${generator}"
+ --build-generator-platform "${architecture}"
--build-project VSWinStorePhone
--build-config $<CONFIGURATION>
--build-options -DCMAKE_SYSTEM_NAME=${systemName}
endmacro()
if(vs11 AND ws80)
- add_test_VSWinStorePhone(vs11-store80-X86 "Visual Studio 11 2012" WindowsStore 8.0)
- add_test_VSWinStorePhone(vs11-store80-ARM "Visual Studio 11 2012 ARM" WindowsStore 8.0)
- add_test_VSWinStorePhone(vs11-store80-X64 "Visual Studio 11 2012 Win64" WindowsStore 8.0)
+ add_test_VSWinStorePhone(vs11-store80-X86 "Visual Studio 11 2012" WindowsStore 8.0 Win32)
+ add_test_VSWinStorePhone(vs11-store80-ARM "Visual Studio 11 2012" WindowsStore 8.0 ARM)
+ add_test_VSWinStorePhone(vs11-store80-X64 "Visual Studio 11 2012" WindowsStore 8.0 x64)
endif()
if(vs12 AND ws81)
- add_test_VSWinStorePhone(vs12-store81-X86 "Visual Studio 12 2013" WindowsStore 8.1)
- add_test_VSWinStorePhone(vs12-store81-ARM "Visual Studio 12 2013 ARM" WindowsStore 8.1)
- add_test_VSWinStorePhone(vs12-store81-X64 "Visual Studio 12 2013 Win64" WindowsStore 8.1)
+ add_test_VSWinStorePhone(vs12-store81-X86 "Visual Studio 12 2013" WindowsStore 8.1 Win32)
+ add_test_VSWinStorePhone(vs12-store81-ARM "Visual Studio 12 2013" WindowsStore 8.1 ARM)
+ add_test_VSWinStorePhone(vs12-store81-X64 "Visual Studio 12 2013" WindowsStore 8.1 x64)
add_test(NAME VSXaml COMMAND ${CMAKE_CTEST_COMMAND}
--build-and-test
-DCMAKE_SYSTEM_VERSION=8.1
)
endif()
+ if(CMake_TEST_VSWinStorePhone_VS_2017 AND ws10_0)
+ add_test_VSWinStorePhone(vs15-store10_0-X86 "Visual Studio 15 2017" WindowsStore 10.0 Win32)
+ add_test_VSWinStorePhone(vs15-store10_0-ARM "Visual Studio 15 2017" WindowsStore 10.0 ARM)
+ add_test_VSWinStorePhone(vs15-store10_0-X64 "Visual Studio 15 2017" WindowsStore 10.0 x64)
+ add_test_VSWinStorePhone(vs15-store10_0-ARM64 "Visual Studio 15 2017" WindowsStore 10.0 ARM64)
+ endif()
if(vs14 AND ws10_0)
- add_test_VSWinStorePhone(vs14-store10_0-X86 "Visual Studio 14 2015" WindowsStore 10.0)
- add_test_VSWinStorePhone(vs14-store10_0-ARM "Visual Studio 14 2015 ARM" WindowsStore 10.0)
- add_test_VSWinStorePhone(vs14-store10_0-X64 "Visual Studio 14 2015 Win64" WindowsStore 10.0)
+ add_test_VSWinStorePhone(vs14-store10_0-X86 "Visual Studio 14 2015" WindowsStore 10.0 Win32)
+ add_test_VSWinStorePhone(vs14-store10_0-ARM "Visual Studio 14 2015" WindowsStore 10.0 ARM)
+ add_test_VSWinStorePhone(vs14-store10_0-X64 "Visual Studio 14 2015" WindowsStore 10.0 x64)
endif()
if(vs11 AND wp80)
- add_test_VSWinStorePhone(vs11-phone80-X86 "Visual Studio 11 2012" WindowsPhone 8.0)
- add_test_VSWinStorePhone(vs11-phone80-ARM "Visual Studio 11 2012 ARM" WindowsPhone 8.0)
+ add_test_VSWinStorePhone(vs11-phone80-X86 "Visual Studio 11 2012" WindowsPhone 8.0 Win32)
+ add_test_VSWinStorePhone(vs11-phone80-ARM "Visual Studio 11 2012" WindowsPhone 8.0 ARM)
endif()
if(vs12 AND wp81)
- add_test_VSWinStorePhone(vs12-phone81-X86 "Visual Studio 12 2013" WindowsPhone 8.1)
- add_test_VSWinStorePhone(vs12-phone81-ARM "Visual Studio 12 2013 ARM" WindowsPhone 8.1)
+ add_test_VSWinStorePhone(vs12-phone81-X86 "Visual Studio 12 2013" WindowsPhone 8.1 Win32)
+ add_test_VSWinStorePhone(vs12-phone81-ARM "Visual Studio 12 2013" WindowsPhone 8.1 ARM)
endif()
endif()
--build-generator "Green Hills MULTI"
--build-project ReturnNum
--build-config $<CONFIGURATION>
- --build-options -DGHS_PRIMARY_TARGET="arm_integrity.tgt"
+ --build-options -DGHS_PRIMARY_TARGET=arm_integrity.tgt
-DGHS_BSP_NAME="simarm"
)
endif ()
ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories)
ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions)
ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options)
+ ADD_TEST_MACRO(CMakeCommands.target_sources target_sources)
+
+ ADD_TEST_MACRO(CMakeCommands.add_link_options)
+ ADD_TEST_MACRO(CMakeCommands.target_link_options)
+ ADD_TEST_MACRO(CMakeCommands.link_directories)
+ ADD_TEST_MACRO(CMakeCommands.target_link_directories)
# The cmake server-mode test requires python for a simple client.
find_package(PythonInterp QUIET)
)
endif()
- add_test(NAME CMakeWizardTest COMMAND cmake -i)
- set_property(TEST CMakeWizardTest PROPERTY PASS_REGULAR_EXPRESSION
- "The \"cmake -i\" wizard mode is no longer supported.")
-
# Define a set of "contract" tests, each activated by a cache entry
# named "CMake_TEST_CONTRACT_<project>". For each Contract test,
# the project should provide a directory with a CMakeLists.txt file
list(INSERT result -1 bill ken)
TEST("INSERT result -1 bill ken" "andy;bill;ken;brad")
+set(result andy brad)
+list(INSERT result 2 bill ken)
+TEST("INSERT result 2 bill ken" "andy;brad;bill;ken")
+
set(result andy bill brad ken bob)
list(REMOVE_ITEM result bob)
TEST("REMOVE_ITEM result bob" "andy;bill;brad;ken")
add_executable(CSharpOnly csharponly.cs)
target_link_libraries(CSharpOnly lib1 lib2)
+
+add_custom_target(CSharpCustom ALL SOURCES empty.cs)
+add_custom_target(custom.cs ALL DEPENDS empty.txt)
ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary)
ADD_TEST_MACRO(Cuda.MixedStandardLevels MixedStandardLevels)
ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude)
+ADD_TEST_MACRO(Cuda.ProperDeviceLibraries ProperDeviceLibraries)
ADD_TEST_MACRO(Cuda.ProperLinkFlags ProperLinkFlags)
ADD_TEST_MACRO(Cuda.WithC CudaWithC)
cmake_minimum_required(VERSION 3.7)
-project (CudaComplex CXX CUDA)
+project (Complex CXX CUDA)
#Goal for this example:
#build a cpp dynamic library base
cmake_minimum_required(VERSION 3.7)
-project (CudaConsumeCompileFeatures CXX CUDA)
+project (ConsumeCompileFeatures CXX CUDA)
#Goal for this example:
#build a c++11 library that express a c++11 public compile feature
cmake_minimum_required(VERSION 3.7)
-project(CudaComplex CXX CUDA)
+project(MixedStandardLevels CXX CUDA)
string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
cmake_minimum_required(VERSION 3.7)
-project (CudaObjectLibrary CUDA CXX)
+project (ObjectLibrary CUDA CXX)
#Goal for this example:
#
#Build C++ and CUDA object files and than use them to make an executable
--- /dev/null
+cmake_minimum_required(VERSION 3.13)
+project(ProperDeviceLibraries CXX CUDA)
+
+string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_35,code=compute_35 -gencode arch=compute_35,code=sm_35")
+set(CMAKE_CUDA_STANDARD 11)
+
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads)
+
+add_executable(ProperDeviceLibraries main.cu)
+set_target_properties(ProperDeviceLibraries
+ PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
+
+add_library(UseThreadsMixed SHARED use_pthreads.cxx use_pthreads.cu)
+target_link_libraries(UseThreadsMixed Threads::Threads)
+
+add_library(UseThreadsCuda SHARED use_pthreads.cu)
+target_link_libraries(UseThreadsCuda Threads::Threads)
+
+target_link_libraries(ProperDeviceLibraries PRIVATE UseThreadsMixed UseThreadsCuda)
+
+if(THREADS_HAVE_PTHREAD_ARG AND CMAKE_USE_PTHREADS_INIT)
+ add_library(UseExplicitPThreadsFlag SHARED use_pthreads.cu)
+ target_compile_options(UseExplicitPThreadsFlag PUBLIC "-Xcompiler=-pthread")
+ target_link_libraries(UseExplicitPThreadsFlag PUBLIC "-pthread")
+
+ add_library(UseExplicitLThreadsFlag SHARED use_pthreads.cu)
+ target_compile_options(UseExplicitLThreadsFlag PUBLIC "-Xcompiler=-pthread")
+ target_link_libraries(UseExplicitLThreadsFlag PUBLIC "-lpthread")
+
+ add_library(UseExplicitLongThreadsFlag SHARED use_pthreads.cu)
+ target_link_libraries(UseExplicitLongThreadsFlag PUBLIC "--library pthread")
+
+ target_link_libraries(ProperDeviceLibraries PRIVATE UseExplicitPThreadsFlag UseExplicitLThreadsFlag UseExplicitLongThreadsFlag)
+endif()
+
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 10.0.0)
+ #CUDA 10 removed the cublas_device library
+ target_link_libraries(ProperDeviceLibraries PRIVATE cublas_device)
+endif()
+
+if(APPLE)
+ # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
+ set_property(TARGET ProperDeviceLibraries PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+endif()
#include <cuda_runtime.h>
#include <iostream>
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+
+# include <pthread.h>
+static int verify_linking_to_pthread()
+{
+ return static_cast<int>(pthread_self());
+}
+#endif
+
// this test only makes sense for versions of CUDA that ships
// static libraries that have separable compilation device symbols
#if __CUDACC_VER_MAJOR__ <= 9
--- /dev/null
+
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+
+# include <pthread.h>
+static int verify_linking_to_pthread_cuda()
+{
+ return static_cast<int>(pthread_self());
+}
+#endif
--- /dev/null
+
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+
+# include <pthread.h>
+static int verify_linking_to_pthread_cxx()
+{
+ return static_cast<int>(pthread_self());
+}
+#endif
cmake_minimum_required(VERSION 3.7)
-project(CudaComplex CUDA C)
+project(WithC CUDA C)
string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
+ADD_TEST_MACRO(CudaOnly.CircularLinkLine CudaOnlyCircularLinkLine)
ADD_TEST_MACRO(CudaOnly.EnableStandard CudaOnlyEnableStandard)
ADD_TEST_MACRO(CudaOnly.ExportPTX CudaOnlyExportPTX)
ADD_TEST_MACRO(CudaOnly.GPUDebugFlag CudaOnlyGPUDebugFlag)
-ADD_TEST_MACRO(CudaOnly.LinkSystemDeviceLibraries CudaOnlyLinkSystemDeviceLibraries)
ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs)
--- /dev/null
+cmake_minimum_required(VERSION 3.7)
+project (CircularLinkLine CUDA)
+
+#Goal for this example:
+# Verify that we de-duplicate the device link line
+# Verify that a de-duplicated link line still works with circular static libraries
+
+string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=[compute_30]")
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CUDA_STANDARD 11)
+
+add_library(CUDACircularDeviceLinking1 STATIC file1.cu)
+add_library(CUDACircularDeviceLinking2 STATIC file2.cu)
+add_library(CUDACircularDeviceLinking3 STATIC file3.cu)
+add_executable(CudaOnlyCircularLinkLine main.cu)
+
+target_link_libraries(CUDACircularDeviceLinking1 PUBLIC CUDACircularDeviceLinking2)
+target_link_libraries(CUDACircularDeviceLinking2 PUBLIC CUDACircularDeviceLinking3)
+target_link_libraries(CUDACircularDeviceLinking3 PUBLIC CUDACircularDeviceLinking1)
+
+target_link_libraries(CudaOnlyCircularLinkLine PRIVATE CUDACircularDeviceLinking3)
+
+
+set_target_properties(CUDACircularDeviceLinking1
+ PROPERTIES
+ CUDA_SEPARABLE_COMPILATION ON)
+
+set_target_properties(CUDACircularDeviceLinking2
+ PROPERTIES
+ CUDA_SEPARABLE_COMPILATION ON)
+
+set_target_properties(CUDACircularDeviceLinking3
+ PROPERTIES
+ CUDA_SEPARABLE_COMPILATION ON)
--- /dev/null
+
+extern __device__ int file2_func(int);
+int __device__ file1_func(int x)
+{
+ return file2_func(x);
+}
--- /dev/null
+
+extern __device__ int file3_func(int);
+int __device__ file2_func(int x)
+{
+ return x + file3_func(x);
+}
--- /dev/null
+
+extern __device__ int file1_func(int);
+int __device__ file3_func(int x)
+{
+ if (x > 0)
+ return file1_func(-x);
+ return x;
+}
--- /dev/null
+
+int main(int argc, char** argv)
+{
+ return 0;
+}
cmake_minimum_required(VERSION 3.7)
-project (CudaOnlyEnableStandard CUDA)
+project (EnableStandard CUDA)
#Goal for this example:
#build cuda sources that require C++11 to be enabled.
cmake_minimum_required(VERSION 3.8)
-project (CudaOnlyExportPTX CUDA)
+project (ExportPTX CUDA)
#Goal for this example:
# How to generate PTX files instead of OBJECT files
cmake_minimum_required(VERSION 3.7)
-project (CudaOnlGPUDebugFlag CUDA)
+project (GPUDebugFlag CUDA)
#Goal for this example:
#verify that -G enables gpu debug flags
+++ /dev/null
-cmake_minimum_required(VERSION 3.8)
-project(CudaOnlyLinkSystemDeviceLibraries CUDA)
-
-string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_35,code=compute_35 -gencode arch=compute_35,code=sm_35")
-set(CMAKE_CUDA_STANDARD 11)
-
-add_executable(CudaOnlyLinkSystemDeviceLibraries main.cu)
-set_target_properties( CudaOnlyLinkSystemDeviceLibraries
- PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
-target_link_libraries( CudaOnlyLinkSystemDeviceLibraries PRIVATE cublas_device)
-
-if(APPLE)
- # Help the static cuda runtime find the driver (libcuda.dyllib) at runtime.
- set_property(TARGET CudaOnlyLinkSystemDeviceLibraries PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
-endif()
cmake_minimum_required(VERSION 3.11)
-project (CudaOnlyPDB CUDA)
+project (PDB CUDA)
add_executable(CudaOnlyPDB main.cu)
set_target_properties(CudaOnlyPDB PROPERTIES
cmake_minimum_required(VERSION 3.7)
-project (CudaOnlyResolveDeviceSymbols CUDA)
+project (ResolveDeviceSymbols CUDA)
# Find nm and dumpbin
if(CMAKE_NM)
cmake_minimum_required(VERSION 3.7)
-project (CudaOnlySeparateCompilation CUDA)
+project (SeparateCompilation CUDA)
#Goal for this example:
#Build a static library that defines multiple methods and kernels that
cmake_minimum_required(VERSION 3.7)
-project (CudaOnlyWithDefs CUDA)
+project (WithDefs CUDA)
#verify that we can pass explicit cuda arch flags
string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
)
set_source_files_properties(
- "${TestWorkingDir_BINARY_DIR}/customTarget.c"
+ "${TestWorkingDir_BINARY_DIR}/customTarget1.c"
"${TestWorkingDir_BINARY_DIR}/customTarget2.c"
PROPERTIES GENERATED 1)
add_executable(working "${TestWorkingDir_BINARY_DIR}/working.c"
- "${TestWorkingDir_BINARY_DIR}/customTarget.c")
+ "${TestWorkingDir_BINARY_DIR}/customTarget1.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"
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different ./customTarget.c "${TestWorkingDir_BINARY_DIR}/customTarget1.c"
+ BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/customTarget1.c"
WORKING_DIRECTORY "${TestWorkingDir_SOURCE_DIR}"
)
)
add_dependencies(working2 Custom2)
+
+file(MAKE_DIRECTORY ${TestWorkingDir_BINARY_DIR}/genex)
+add_custom_command(
+ OUTPUT "${TestWorkingDir_BINARY_DIR}/genex/working.c"
+ COMMAND "${CMAKE_COMMAND}" -E copy "${TestWorkingDir_SOURCE_DIR}/working.c.in" "${TestWorkingDir_BINARY_DIR}/genex/working.c"
+ WORKING_DIRECTORY "$<0:not_used/>${TestWorkingDir_BINARY_DIR}/$<1:genex>/"
+ COMMENT "custom command"
+)
+
+add_executable(workinggenex "${TestWorkingDir_BINARY_DIR}/genex/working.c"
+ "${TestWorkingDir_BINARY_DIR}/genex/customTarget.c")
+
+add_custom_target(
+ CustomGenex ALL
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${TestWorkingDir_SOURCE_DIR}/customTarget.c" "${TestWorkingDir_BINARY_DIR}/genex/customTarget.c"
+ BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/genex/customTarget.c"
+ WORKING_DIRECTORY "$<0:not_used/>${TestWorkingDir_BINARY_DIR}/$<1:genex>/"
+)
+
+add_dependencies(workinggenex CustomGenex)
target_link_libraries(testLibDepends PRIVATE testStaticLibRequiredPrivate)
cmake_policy(POP)
+cmake_policy(PUSH)
+cmake_policy(SET CMP0079 NEW)
+add_library(TopDirLib STATIC testTopDirLib.c)
+add_subdirectory(SubDirLinkA)
+add_subdirectory(SubDirLinkB)
+cmake_policy(POP)
+
macro(add_include_lib _libName)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "/* no content */\n")
add_library(${_libName} "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c")
testLibCycleA testLibCycleB
testLibNoSONAME
cmp0022NEW cmp0022OLD
+ TopDirLib SubDirLinkA
systemlib
EXPORT exp
- RUNTIME DESTINATION $<1:bin>
- LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP
- ARCHIVE DESTINATION $<1:lib>
+ RUNTIME DESTINATION $<1:bin>$<0:/wrong>
+ LIBRARY DESTINATION $<1:lib>$<0:/wrong> NAMELINK_SKIP
+ ARCHIVE DESTINATION $<1:lib>$<0:/wrong>
${maybe_OBJECTS_DESTINATION}
FRAMEWORK DESTINATION Frameworks
BUNDLE DESTINATION Applications
testSharedLibRequired testSharedLibRequiredUser testSharedLibRequiredUser2
testSharedLibDepends renamed_on_export
cmp0022NEW cmp0022OLD
+ TopDirLib SubDirLinkA
systemlib
NAMESPACE bld_
FILE ExportBuildTree.cmake
)
install(DIRECTORY $<1:include/abs>$<0:/wrong> DESTINATION $<1:include>$<0:/wrong>)
install(EXPORT expAbs NAMESPACE expAbs_ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/expAbs)
+
+
+#------------------------------------------------------------------------------
+# test export of INTERFACE_LINK_OPTIONS
+add_library(testLinkOptions INTERFACE)
+target_link_options(testLinkOptions INTERFACE INTERFACE_FLAG)
+
+install(TARGETS testLinkOptions
+ EXPORT RequiredExp DESTINATION lib)
+export(TARGETS testLinkOptions NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
+
+
+#------------------------------------------------------------------------------
+# test export of INTERFACE_LINK_DIRECTORIES
+add_library(testLinkDirectories INTERFACE)
+target_link_directories(testLinkDirectories INTERFACE
+ $<BUILD_INTERFACE:/interface/build>
+ $<INSTALL_INTERFACE:interface/install>)
+
+install(TARGETS testLinkDirectories
+ EXPORT RequiredExp DESTINATION lib)
+export(TARGETS testLinkDirectories NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
+
+
+#------------------------------------------------------------------------------
+# test export of INTERFACE_LINK_DEPENDS
+if(CMAKE_GENERATOR MATCHES "Make|Ninja")
+ add_library(testLinkDepends INTERFACE)
+ set_property(TARGET testLinkDepends PROPERTY INTERFACE_LINK_DEPENDS
+ $<BUILD_INTERFACE:BUILD_LINK_DEPENDS>
+ $<INSTALL_INTERFACE:INSTALL_LINK_DEPENDS>)
+
+ install(TARGETS testLinkDepends
+ EXPORT RequiredExp DESTINATION lib)
+ export(TARGETS testLinkDepends NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
+endif()
--- /dev/null
+add_library(SubDirLinkAImported IMPORTED INTERFACE)
+target_compile_definitions(SubDirLinkAImported INTERFACE DEF_SubDirLinkAImportedForExport)
+
+target_link_libraries(TopDirLib PUBLIC SubDirLinkAImported)
+
+add_library(SubDirLinkA STATIC SubDirLinkA.c)
--- /dev/null
+#ifdef DEF_SubDirLinkAImportedForExport
+# error "DEF_SubDirLinkAImportedForExport is defined but should not be!"
+#endif
+#ifndef DEF_SubDirLinkBImportedForExport
+# error "DEF_SubDirLinkBImportedForExport is not defined but should be!"
+#endif
+
+int testSubDirLinkA(void)
+{
+ return 0;
+}
--- /dev/null
+add_library(SubDirLinkBImported IMPORTED INTERFACE)
+target_compile_definitions(SubDirLinkBImported INTERFACE DEF_SubDirLinkBImportedForExport)
+
+target_link_libraries(SubDirLinkA PUBLIC SubDirLinkBImported)
--- /dev/null
+#ifndef DEF_SubDirLinkAImportedForExport
+# error "DEF_SubDirLinkAImportedForExport is not defined but should be!"
+#endif
+#ifdef DEF_SubDirLinkBImportedForExport
+# error "DEF_SubDirLinkBImportedForExport is defined but should not be!"
+#endif
+
+int testTopDirLib(void)
+{
+ return 0;
+}
+# Prepare imported targets that the exported project itself imported.
+add_library(SubDirLinkAImported IMPORTED INTERFACE)
+target_compile_definitions(SubDirLinkAImported INTERFACE DEF_SubDirLinkAImportedForImport)
+add_library(SubDirLinkBImported IMPORTED INTERFACE)
+target_compile_definitions(SubDirLinkBImported INTERFACE DEF_SubDirLinkBImportedForImport)
+
# Import targets from the exported build tree.
include(${Import_BINARY_DIR}/../Export/ExportBuildTree.cmake)
add_executable(cmp0022NEW_exp_test cmp0022NEW_test_vs6_2.cpp)
target_link_libraries(cmp0022NEW_exp_test exp_cmp0022NEW)
+add_executable(SubDirLink_bld SubDirLink.c)
+target_link_libraries(SubDirLink_bld PRIVATE bld_TopDirLib bld_SubDirLinkA)
+add_executable(SubDirLink_exp SubDirLink.c)
+target_link_libraries(SubDirLink_exp PRIVATE exp_TopDirLib exp_SubDirLinkA)
+
# Try building a plugin to an executable imported from the build tree.
add_library(imp_mod1b MODULE imp_mod1.c)
target_link_libraries(imp_mod1b bld_testExe2)
endif()
endif()
endif()
+
+#---------------------------------------------------------------------------------
+# check that imported libraries have the expected INTERFACE_LINK_OPTIONS property
+checkForProperty(bld_testLinkOptions "INTERFACE_LINK_OPTIONS" "INTERFACE_FLAG")
+checkForProperty(Req::testLinkOptions "INTERFACE_LINK_OPTIONS" "INTERFACE_FLAG")
+
+#---------------------------------------------------------------------------------
+# check that imported libraries have the expected INTERFACE_LINK_DIRECTORIES property
+checkForProperty(bld_testLinkDirectories "INTERFACE_LINK_DIRECTORIES" "/interface/build")
+checkForProperty(Req::testLinkDirectories "INTERFACE_LINK_DIRECTORIES" "${CMAKE_INSTALL_PREFIX}/interface/install")
+
+#---------------------------------------------------------------------------------
+# check that imported libraries have the expected INTERFACE_LINK_DEPENDS property
+if(CMAKE_GENERATOR MATCHES "Make|Ninja")
+ checkForProperty(bld_testLinkDepends "INTERFACE_LINK_DEPENDS" "BUILD_LINK_DEPENDS")
+ checkForProperty(Req::testLinkDepends "INTERFACE_LINK_DEPENDS" "${CMAKE_INSTALL_PREFIX}/INSTALL_LINK_DEPENDS")
+endif()
--- /dev/null
+#ifndef DEF_SubDirLinkAImportedForImport
+# error "DEF_SubDirLinkAImportedForImport is not defined but should be!"
+#endif
+#ifndef DEF_SubDirLinkBImportedForImport
+# error "DEF_SubDirLinkBImportedForImport is not defined but should be!"
+#endif
+
+extern int testTopDirLib(void);
+extern int testSubDirLinkA(void);
+
+int main(void)
+{
+ return (testTopDirLib() + testSubDirLinkA() + 0);
+}
--- /dev/null
+
+#include "testSharedLibRequired.h"
+
+int foo()
+{
+ TestSharedLibRequired req;
+ return req.foo();
+}
+#include "foo.h"
+
int foo()
{
return 1477;
#ifndef FOO_H
#define FOO_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int foo();
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif
find_package(ArchD 4.0 EXACT NAMES zot)
unset(CMAKE_LIBRARY_ARCHITECTURE)
-# Test <Package>_DIR environment variable.
+# Test <PackageName>_DIR environment variable.
# We erase the main prefix path to ensure the env var is used.
set(CMAKE_PREFIX_PATH)
set(ENV{EnvA_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/lib/zot-3.1")
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)
+# Search specific sources to get the test list. Include an empty file
+# to ensure they are handled correctly too.
+add_executable(test_gtest2 main2.cxx empty.cxx)
target_link_libraries(test_gtest2 GTest::Main)
gtest_add_tests(TARGET test_gtest2
TEST_LIST testList
- SOURCES main2.h
+ SOURCES main2.h empty.cxx
)
set(expectedTests
GoogleTest.SomethingElse
--- /dev/null
+add_library(a STATIC a.c)
+target_compile_definitions(a INTERFACE DEF_A)
+
+add_library(sameName INTERFACE IMPORTED)
+target_link_libraries(sameName INTERFACE a)
+
+add_library(ifaceA INTERFACE)
+target_link_libraries(ifaceA INTERFACE sameName)
--- /dev/null
+void a(void)
+{
+}
--- /dev/null
+add_library(b STATIC b.c)
+target_compile_definitions(b INTERFACE DEF_B)
+
+add_library(sameName INTERFACE IMPORTED)
+target_link_libraries(sameName INTERFACE b)
+
+add_library(ifaceB INTERFACE)
+target_link_libraries(ifaceB INTERFACE sameName)
--- /dev/null
+void b(void)
+{
+}
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+project(ImportedSameName C)
+
+add_subdirectory(A)
+add_subdirectory(B)
+
+add_executable(ImportedSameName main.c)
+target_link_libraries(ImportedSameName PRIVATE ifaceA ifaceB)
--- /dev/null
+#ifndef DEF_A
+# error "DEF_A not defined"
+#endif
+#ifndef DEF_B
+# error "DEF_B not defined"
+#endif
+
+extern void a(void);
+extern void b(void);
+
+int main(void)
+{
+ a();
+ b();
+ return 0;
+}
cmake_minimum_required(VERSION 2.8)
project(LinkDirectoryExternal C)
+
+add_executable(myexe2 myexe.c)
+set_property(TARGET myexe2 PROPERTY OUTPUT_NAME LinkDirectory2)
+target_link_directories(myexe2 PRIVATE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib")
+target_link_libraries(myexe2 PRIVATE mylibA mylibB)
+
+add_library (mylibs INTERFACE)
+target_link_directories(mylibs INTERFACE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib")
+target_link_libraries(mylibs INTERFACE mylibA mylibB)
+add_executable(myexe3 myexe.c)
+set_property(TARGET myexe3 PROPERTY OUTPUT_NAME LinkDirectory3)
+target_link_libraries(myexe3 PRIVATE mylibs)
+
+
# Test CMP0015 OLD behavior: -L../lib
cmake_policy(SET CMP0015 OLD)
link_directories(../lib)
"-1 + +1"
"+1 - -1"
"+1 - - + + -(-3 + - - +1)"
+ "1000 -12*5"
+ "1000 +12*-5"
+ "1000 -12*-5"
)
-set(FILE_EXPRESSIONS "")
-foreach(expression
- ${expressions})
- math(EXPR expr "${expression}")
- string(APPEND FILE_EXPRESSIONS "TEST_EXPRESSION(${expression}, ${expr})\n")
-endforeach()
+set(FILE_EXPRESSIONS "extern void test_expression(int x, int y, const char * text);\n")
+
+
+macro(add_math_test expression)
+ math(EXPR result ${expression} ${ARGV1} ${ARGV2})
+ set(CODE "test_expression(${expression}, ${result}, \"${expression}\");")
+ string(APPEND FILE_EXPRESSIONS "${CODE}\n")
+endmacro()
+
+macro(add_math_tests)
+ foreach (expression ${expressions})
+ add_math_test(${expression} ${ARGV0} ${ARGV1})
+ endforeach ()
+endmacro()
+
+add_math_tests()
+add_math_tests("OUTPUT_FORMAT" "DECIMAL")
+add_math_tests("OUTPUT_FORMAT" "HEXADECIMAL")
+
+# Avoid the test with negative result and hexadecimal formatting
+# therefore more tests with a negative result
+add_math_test("-12*5")
+add_math_test("12*-5")
+
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/MathTestTests.h.in"
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-#define TEST_EXPRESSION(x, y) \
- if ((x) != (y)) { \
- printf("Problem with EXPR: Expression: \"%s\" in C returns %d while in " \
- "CMake returns: %d\n", \
- #x, (x), (y)); \
- res++; \
+int res = 0;
+bool print = false;
+
+void test_expression(int x, int y, const char* text)
+{
+ bool fail = (x) != (y);
+ if (fail) {
+ res++;
+ printf("Problem with EXPR:");
+ }
+ if (fail || print) {
+ printf("Expression: \"%s\" in CMake returns %d", text, (y));
+ if (fail) {
+ printf(" while in C returns: %d", (x));
+ }
+ printf("\n");
}
+}
int main(int argc, char* argv[])
{
- if (argc > 1) {
- printf("Usage: %s\n", argv[0]);
+ if (argc > 2) {
+ printf("Usage: %s [print]\n", argv[0]);
return 1;
}
- int res = 0;
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "print") != 0) {
+ printf("Usage: %s [print]\n", argv[0]);
+ return 1;
+ }
+ print = true;
+ }
+
#include "MathTestTests.h"
+
if (res != 0) {
printf("%s: %d math tests failed\n", argv[0], res);
return 1;
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+project(OutName C)
+
+add_executable(OutName main.c)
+set_property(TARGET OutName PROPERTY PREFIX exe.)
+set_property(TARGET OutName PROPERTY SUFFIX .exe)
--- /dev/null
+int main(void)
+{
+ return 0;
+}
list(APPEND CMAKE_PREFIX_PATH ${Qt_PREFIX_DIR})
endif()
-if (QT_TEST_VERSION STREQUAL 4)
+if (QT_TEST_VERSION EQUAL 4)
find_package(Qt4 REQUIRED)
include(UseQt4)
qt4_generate_moc(${ARGN})
endmacro()
-elseif(QT_TEST_VERSION STREQUAL 5)
+elseif(QT_TEST_VERSION EQUAL 5)
find_package(Qt5Widgets REQUIRED)
set(QT_QTCORE_TARGET Qt5::Core)
endif()
ADD_AUTOGEN_TEST(UicSkipSource)
ADD_AUTOGEN_TEST(RccSkipSource)
-if(NOT QT_TEST_VERSION STREQUAL 4)
+if(QT_TEST_VERSION GREATER 4)
ADD_AUTOGEN_TEST(MocMacroName mocMacroName)
endif()
ADD_AUTOGEN_TEST(MocDepends)
if(QT_TEST_ALLOW_QT_MACROS)
ADD_AUTOGEN_TEST(MocCMP0071)
endif()
+if(QT_TEST_VERSION GREATER 4)
+ ADD_AUTOGEN_TEST(MocOsMacros)
+endif()
ADD_AUTOGEN_TEST(UicInclude uicInclude)
ADD_AUTOGEN_TEST(UicInterface QtAutoUicInterface)
ADD_AUTOGEN_TEST(ObjectLibrary someProgram)
-if(APPLE AND (NOT QT_TEST_VERSION STREQUAL 4))
+if(APPLE AND (QT_TEST_VERSION GREATER 4))
ADD_AUTOGEN_TEST(MacOsFW)
endif()
ADD_AUTOGEN_TEST(Parallel parallel)
ADD_AUTOGEN_TEST(StaticLibraryCycle slc)
# Rerun tests
ADD_AUTOGEN_TEST(RerunMocBasic)
-if(NOT QT_TEST_VERSION STREQUAL 4)
+if(QT_TEST_VERSION GREATER 4)
ADD_AUTOGEN_TEST(RerunMocPlugin)
endif()
ADD_AUTOGEN_TEST(RerunRccDepends)
project(DefinesTest)
# Qt4 only definitions test
-if(NOT QT_TEST_VERSION STREQUAL 4)
+if(NOT QT_TEST_VERSION EQUAL 4)
message(ERROR "Invalid Qt test version. This test is for Qt4 only.")
endif()
set(MOC_INCLUDE_NAME "mocIncludeRelaxed")
include(${CMAKE_CURRENT_SOURCE_DIR}/../MocInclude/shared.cmake)
-# Relaxed ony executable
+# Relaxed only executable
add_executable(mocIncludeRelaxedOnly
RObjA.cpp
RObjB.cpp
--- /dev/null
+cmake_minimum_required(VERSION 3.11)
+project(MocOsMacros)
+include("../AutogenTest.cmake")
+
+# Tests if moc processes Q_OS_XXX macros
+
+message( "Qt5Core_VERSION: ${Qt5Core_VERSION}" )
+message(
+ "CMAKE_CXX_COMPILER_PREDEFINES_COMMAND: "
+ ${CMAKE_CXX_COMPILER_PREDEFINES_COMMAND} )
+
+# On some platforms (e.g. MAC) Q_OS_XXX requires moc to include moc_predefs.h
+# which is supported since Qt 5.8 and requires
+# CMAKE_CXX_COMPILER_PREDEFINES_COMMAND to be defined.
+if( ( ${Qt5Core_VERSION} VERSION_GREATER_EQUAL "5.8" ) AND
+ DEFINED CMAKE_CXX_COMPILER_PREDEFINES_COMMAND
+)
+ message( "Test enabled!" )
+ message(
+ "CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES: "
+ ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES} )
+
+ set(CMAKE_AUTOMOC True)
+ add_executable(mocOsMacros
+ main.cpp
+ TestClass.cpp
+ TestClass.hpp
+ )
+ target_link_libraries(mocOsMacros PRIVATE ${QT_QTCORE_TARGET})
+else()
+ message( "Test disabled!" )
+endif()
--- /dev/null
+#include "TestClass.hpp"
+#include <iostream>
+
+// -- Mac
+#ifndef Q_OS_MAC
+void TestClass::MacNotDef()
+{
+ std::cout << "MacNotDef\n";
+}
+#else
+void TestClass::MacNotDefElse()
+{
+ std::cout << "MacNotDefElse\n";
+}
+#endif
+
+#ifdef Q_OS_MAC
+void TestClass::MacDef()
+{
+ std::cout << "MacDef\n";
+}
+#else
+void TestClass::MacDefElse()
+{
+ std::cout << "MacDefElse\n";
+}
+#endif
+
+// -- Unix
+#ifndef Q_OS_UNIX
+void TestClass::UnixNotDef()
+{
+ std::cout << "UnixNotDef\n";
+}
+#else
+void TestClass::UnixNotDefElse()
+{
+ std::cout << "UnixNotDefElse\n";
+}
+#endif
+
+#ifdef Q_OS_UNIX
+void TestClass::UnixDef()
+{
+ std::cout << "UnixDef\n";
+}
+#else
+void TestClass::UnixDefElse()
+{
+ std::cout << "UnixDefElse\n";
+}
+#endif
+
+// -- Windows
+#ifndef Q_OS_WIN
+void TestClass::WindowsNotDef()
+{
+ std::cout << "WindowsNotDef\n";
+}
+#else
+void TestClass::WindowsNotDefElse()
+{
+ std::cout << "WindowsNotDefElse\n";
+}
+#endif
+
+#ifdef Q_OS_WIN
+void TestClass::WindowsDef()
+{
+ std::cout << "WindowsDef\n";
+}
+#else
+void TestClass::WindowsDefElse()
+{
+ std::cout << "WindowsDefElse\n";
+}
+#endif
--- /dev/null
+#ifndef TestClass_hpp
+#define TestClass_hpp
+
+#include <QObject>
+#include <QtGlobal>
+
+class TestClass : public QObject
+{
+ Q_OBJECT
+public Q_SLOTS:
+
+// -- Mac
+#ifndef Q_OS_MAC
+ void MacNotDef();
+#else
+ void MacNotDefElse();
+#endif
+
+#ifdef Q_OS_MAC
+ void MacDef();
+#else
+ void MacDefElse();
+#endif
+
+// -- Unix
+#ifndef Q_OS_UNIX
+ void UnixNotDef();
+#else
+ void UnixNotDefElse();
+#endif
+
+#ifdef Q_OS_UNIX
+ void UnixDef();
+#else
+ void UnixDefElse();
+#endif
+
+// -- Windows
+#ifndef Q_OS_WIN
+ void WindowsNotDef();
+#else
+ void WindowsNotDefElse();
+#endif
+
+#ifdef Q_OS_WIN
+ void WindowsDef();
+#else
+ void WindowsDefElse();
+#endif
+};
+
+#endif /* TestClass_hpp */
--- /dev/null
+#include "TestClass.hpp"
+#include <QtGlobal>
+
+int main()
+{
+ TestClass a;
+#ifdef Q_OS_MAC
+ a.MacNotDefElse();
+ a.MacDef();
+#else
+ a.MacNotDef();
+ a.MacDefElse();
+#endif
+
+#ifdef Q_OS_UNIX
+ a.UnixNotDefElse();
+ a.UnixDef();
+#else
+ a.UnixNotDef();
+ a.UnixDefElse();
+#endif
+
+#ifdef Q_OS_WIN
+ a.WindowsNotDefElse();
+ a.WindowsDef();
+#else
+ a.WindowsNotDef();
+ a.WindowsDefElse();
+#endif
+
+ return 0;
+}
"${mocBasicSrcDir}"
MocBasic
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+ "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
"${mocPlugSrcDir}"
MocPlugin
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+ "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
project(MocPlugin)
include("../../AutogenTest.cmake")
-if (NOT QT_TEST_VERSION STREQUAL 5)
- message(SEND_ERROR "Invalid Qt version specified.")
+if (QT_TEST_VERSION LESS 5)
+ message(SEND_ERROR "Qt 5 or higher required.")
endif()
set(CMAKE_AUTOMOC_DEPEND_FILTERS
"${rccDepSD}"
RccConfigChange
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+ "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
"${rccDepSD}"
RccDepends
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+ "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
)
# Set different compression levels
-if (QT_TEST_VERSION STREQUAL 4)
+if (QT_TEST_VERSION EQUAL 4)
set(rccCompress "-compress")
else()
set(rccCompress "--compress")
list(APPEND Autogen_BUILD_OPTIONS "-DCMAKE_BUILD_TYPE=$<CONFIGURATION>")
endif()
list(APPEND Autogen_BUILD_OPTIONS
+ "-DCMAKE_AUTOGEN_VERBOSE=1"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
)
# Qt4 moc does not support utf8 paths in _parameter files generated by
# qtx_wrap_cpp
# https://bugreports.qt.io/browse/QTBUG-35480
- if(QT_TEST_VERSION STREQUAL 4)
+ if(QT_TEST_VERSION EQUAL 4)
set(QT_TEST_ALLOW_QT_MACROS FALSE)
endif()
# On windows qtx_wrap_cpp also fails in Qt5 when used on a path that
add_library(bar bar.c)
add_library(dog foo.cxx)
target_link_libraries(foo PRIVATE car bar dog debug -lm)
-export(TARGETS bar dog car foo ANDROID_MK
+add_library(foo2 foo.cxx)
+target_link_options(foo2 INTERFACE -lm)
+export(TARGETS bar dog car foo foo2 ANDROID_MK
${build_BINARY_DIR}/Android.mk)
-install(TARGETS bar dog car foo DESTINATION lib EXPORT myexp)
+install(TARGETS bar dog car foo foo2 DESTINATION lib EXPORT myexp)
install(EXPORT_ANDROID_MK myexp DESTINATION share/ndk-modules)
LOCAL_EXPORT_LDLIBS := -lm
LOCAL_HAS_CPP := true
include.*PREBUILT_STATIC_LIBRARY.*
+.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*foo2
+LOCAL_SRC_FILES.*.*foo2.*
+LOCAL_CPP_FEATURES.*rtti exceptions
+LOCAL_EXPORT_LDFLAGS := -lm
+LOCAL_HAS_CPP := true
+include.*PREBUILT_STATIC_LIBRARY.*
LOCAL_EXPORT_LDLIBS := -lm
LOCAL_HAS_CPP := true
include.*PREBUILT_STATIC_LIBRARY.*
+
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*foo2
+LOCAL_SRC_FILES.*_IMPORT_PREFIX\)/lib.*foo2.*
+LOCAL_CPP_FEATURES.*rtti exceptions
+LOCAL_EXPORT_LDFLAGS := -lm
+LOCAL_HAS_CPP := true
+include.*PREBUILT_STATIC_LIBRARY.*
--- /dev/null
+if(DEFINED CMP0080_VALUE)
+ cmake_policy(SET CMP0080 ${CMP0080_VALUE})
+endif()
+
+include(BundleUtilities)
--- /dev/null
+CMake Error at .*/Modules/BundleUtilities\.cmake:[0-9]+ \(message\):
+ BundleUtilities cannot be included at configure time!
--- /dev/null
+cmake_policy(SET CMP0080 NEW)
+include(BundleUtilities)
--- /dev/null
+cmake_policy(SET CMP0080 OLD)
+include(BundleUtilities)
--- /dev/null
+CMake Warning \(dev\) at .*/Modules/BundleUtilities\.cmake:[0-9]+ \(message\):
+ Policy CMP0080 is not set: BundleUtilities prefers not to be included at
+ configure time\. Run "cmake --help-policy CMP0080" for policy details\. Use
+ the cmake_policy command to set the policy and suppress this warning\.
--- /dev/null
+include(BundleUtilities)
--- /dev/null
+cmake_minimum_required(VERSION 3.4)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+cmake_minimum_required(VERSION 3.4)
+include(RunCMake)
+
+# TODO Migrate Tests/BundleUtilities here
+
+run_cmake(CMP0080-OLD)
+run_cmake(CMP0080-NEW)
+run_cmake(CMP0080-WARN)
+run_cmake_command(CMP0080-COMMAND-OLD ${CMAKE_COMMAND} -DCMP0080_VALUE:STRING=OLD -P ${RunCMake_SOURCE_DIR}/CMP0080-COMMAND.cmake)
+run_cmake_command(CMP0080-COMMAND-NEW ${CMAKE_COMMAND} -DCMP0080_VALUE:STRING=NEW -P ${RunCMake_SOURCE_DIR}/CMP0080-COMMAND.cmake)
+run_cmake_command(CMP0080-COMMAND-WARN ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/CMP0080-COMMAND.cmake)
--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+project(CleanByproducts)
+
+# Configurable parameters
+set(TEST_CLEAN_NO_CUSTOM FALSE CACHE BOOL "Value for the CLEAN_NO_CUSTOM PROPERTY")
+set(TEST_BUILD_EVENTS TRUE CACHE BOOL "Create byproducts with build events")
+set(TEST_CUSTOM_TARGET TRUE CACHE BOOL "Create a byproduct with a custom target")
+set(TEST_CUSTOM_COMMAND TRUE CACHE BOOL "Create a byproduct with a custom command")
+
+set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM ${TEST_CLEAN_NO_CUSTOM})
+
+macro(add_build_event)
+ set(oneValueArgs EVENT)
+
+ cmake_parse_Arguments(ABE "" "${oneValueArgs}" "" ${ARGN})
+
+ # Create two byproducts and only declare one
+ add_custom_command(TARGET foo
+ ${ABE_EVENT}
+ COMMAND ${CMAKE_COMMAND} -E touch foo.${ABE_EVENT}
+ COMMAND ${CMAKE_COMMAND} -E touch foo.${ABE_EVENT}.notdeclared
+ COMMENT "Creating byproducts with ${ABE_EVENT}"
+ BYPRODUCTS foo.${ABE_EVENT}
+ )
+
+ # The nondeclared byproduct should always be present
+ list(APPEND EXPECTED_PRESENT foo.${ABE_EVENT}.notdeclared)
+
+ # If CLEAN_NO_CUSTOM is set, the declared byproduct should be present
+ if(TEST_CLEAN_NO_CUSTOM)
+ list(APPEND EXPECTED_PRESENT foo.${ABE_EVENT})
+ else()
+ list(APPEND EXPECTED_DELETED foo.${ABE_EVENT})
+ endif()
+endmacro()
+
+add_executable(foo foo.cpp)
+
+# Test build events
+if(TEST_BUILD_EVENTS)
+ add_build_event(EVENT "PRE_BUILD" ENABLE ${TEST_PRE_BUILD})
+ add_build_event(EVENT "PRE_LINK" ENABLE ${TEST_PRE_LINK})
+ add_build_event(EVENT "POST_BUILD" ENABLE ${TEST_POST_BUILD})
+endif()
+
+# Custom command that generates byproducts
+if(TEST_CUSTOM_COMMAND)
+ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp.in "void bar() {}\n")
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp
+ COMMAND ${CMAKE_COMMAND} -E touch foo.customcommand
+ COMMAND ${CMAKE_COMMAND} -E touch foo.customcommand.notdeclared
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/bar.cpp
+ BYPRODUCTS foo.customcommand
+ COMMENT "Creating byproducts with a custom command"
+ )
+
+ # The nondeclared byproduct should always be present
+ list(APPEND EXPECTED_PRESENT "foo.customcommand.notdeclared")
+
+ # If CLEAN_NO_CUSTOM is set, both the output and byproduct should be present
+ if(TEST_CLEAN_NO_CUSTOM)
+ list(APPEND EXPECTED_PRESENT "bar.cpp")
+ list(APPEND EXPECTED_PRESENT "foo.customcommand")
+ else()
+ list(APPEND EXPECTED_DELETED "bar.cpp")
+ list(APPEND EXPECTED_DELETED "foo.customcommand")
+ endif()
+
+ target_sources(foo PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/bar.cpp")
+endif()
+
+# Custom target that generates byproducts
+if(TEST_CUSTOM_TARGET)
+ add_custom_target(foo_file ALL
+ DEPENDS foo
+ COMMAND ${CMAKE_COMMAND} -E touch foo.customtarget
+ COMMAND ${CMAKE_COMMAND} -E touch foo.customtarget.notdeclared
+ BYPRODUCTS foo.customtarget
+ COMMENT "Creating byproducts with a custom target"
+ )
+
+ # The nondeclared byproduct should always be present
+ list(APPEND EXPECTED_PRESENT "foo.customtarget.notdeclared")
+
+ # If CLEAN_NO_CUSTOM is set, the declared byproduct should be present
+ if(TEST_CLEAN_NO_CUSTOM)
+ list(APPEND EXPECTED_PRESENT "foo.customtarget")
+ else()
+ list(APPEND EXPECTED_DELETED "foo.customtarget")
+ endif()
+endif()
+
+configure_file(files.cmake.in files.cmake)
--- /dev/null
+include(RunCMake)
+
+function(run_CleanByproducts case)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CleanByproducts-${case}-build)
+ set(RunCMake_TEST_OPTIONS "${ARGN}")
+
+ run_cmake(CleanByproducts)
+ set(RunCMake_TEST_NO_CLEAN 1)
+
+ run_cmake_command(CleanByProducts-build ${CMAKE_COMMAND} --build .)
+ include("${RunCMake_TEST_BINARY_DIR}/files.cmake")
+
+ message("Checking that all expected files are present")
+ check_files(EXPECTED_PRESENT "${RunCMake_TEST_BINARY_DIR}" TRUE)
+ check_files(EXPECTED_DELETED "${RunCMake_TEST_BINARY_DIR}" TRUE)
+
+ run_cmake_command(CleanByProducts-clean ${CMAKE_COMMAND} --build . --target clean)
+
+ message("Checking that only the expected files are present after cleaning")
+ check_files(EXPECTED_PRESENT "${RunCMake_TEST_BINARY_DIR}" TRUE)
+ check_files(EXPECTED_DELETED "${RunCMake_TEST_BINARY_DIR}" FALSE)
+endfunction()
+
+function(check_files list path has_to_exist)
+ foreach(file IN LISTS ${list})
+ message("Checking ${file}")
+ set(file_exists FALSE)
+ if(EXISTS "${path}/${file}")
+ set(file_exists TRUE)
+ endif()
+
+ if(file_exists AND NOT has_to_exist)
+ message(FATAL_ERROR "${file} should have been deleted")
+ elseif(NOT file_exists AND has_to_exist)
+ message(FATAL_ERROR "${file} does not exist")
+ elseif(file_exists AND has_to_exist)
+ message("${file} found as expected")
+ elseif(NOT file_exists AND NOT has_to_exist)
+ message("${file} deleted as expected")
+ endif()
+
+ endforeach()
+endfunction()
+
+
+# Iterate through all possible test values
+set(counter 0)
+foreach(test_clean_no_custom TRUE FALSE)
+ foreach(test_build_events TRUE FALSE)
+ foreach(test_custom_command TRUE FALSE)
+ foreach(test_custom_target TRUE FALSE)
+ math(EXPR counter "${counter} + 1")
+ message("Test ${counter} - CLEAN_NO_CUSTOM: ${test_clean_no_custom}, Build events: ${test_build_events}, Custom command: ${test_custom_command}, Custom target: ${test_custom_target}")
+ run_CleanByproducts("buildevents${counter}" -DCLEAN_NO_CUSTOM=${test_clean_no_custom} -DTEST_BUILD_EVENTS=${test_build_events} -DTEST_CUSTOM_COMMAND=${test_custom_command} -DTEST_CUSTOM_TARGET=${test_custom_target})
+ endforeach()
+ endforeach()
+ endforeach()
+endforeach()
--- /dev/null
+set(EXPECTED_PRESENT "@EXPECTED_PRESENT@")
+set(EXPECTED_DELETED "@EXPECTED_DELETED@")
--- /dev/null
+int bar(int y)
+{
+ return y * 6;
+}
+
+int foo(int x)
+{
+ return x * bar(x);
+}
+
+int main()
+{
+ return foo(4);
+}
--- /dev/null
+^CMake Deprecation Warning at CMP0055-OLD-Out-of-Scope.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0055 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\)$
--- /dev/null
+^CMake Deprecation Warning at CMP0055-OLD-Reject-Arguments.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0055 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\)$
--- /dev/null
+^CMake Deprecation Warning at CMP0060-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0060 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\)$
run_cmake(CMP0069-NEW-compiler)
run_cmake(CMP0069-WARN)
-if(RunCMake_GENERATOR MATCHES "^Visual Studio ")
+if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 ")
run_cmake(CMP0069-NEW-generator)
endif()
--- /dev/null
+
+enable_language(CXX)
+
+add_library(foo SHARED empty.cpp)
+set_target_properties(foo PROPERTIES LINK_DIRECTORIES "../lib")
--- /dev/null
+CMake Error in CMakeLists.txt:
+ Found relative path while evaluating link directories of "foo":
+
+ "../lib"
--- /dev/null
+
+cmake_policy(SET CMP0081 NEW)
+
+include (CMP0081-Common.cmake)
--- /dev/null
+
+cmake_policy(SET CMP0081 OLD)
+
+include (CMP0081-Common.cmake)
--- /dev/null
+CMake Warning \(dev\) in CMakeLists.txt:
+ Policy CMP0081 is not set: Relative paths not allowed in LINK_DIRECTORIES
+ target property. Run "cmake --help-policy CMP0081" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+
+ Found relative path while evaluating link directories of "foo":
+
+ "../lib"
+
+This warning is for project developers. Use -Wno-dev to suppress it.
--- /dev/null
+
+include (CMP0081-Common.cmake)
--- /dev/null
+cmake_minimum_required(VERSION 3.1)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+include(RunCMake)
+
+run_cmake(CMP0081-OLD)
+run_cmake(CMP0081-NEW)
+run_cmake(CMP0081-WARN)
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
add_RunCMake_test(CMP0068)
endif()
add_RunCMake_test(CMP0069)
+add_RunCMake_test(CMP0081)
# The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
add_RunCMake_test(AndroidTestUtilities)
add_RunCMake_test(BuildDepends)
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
+ add_RunCMake_test(Byproducts)
+endif()
+if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
add_RunCMake_test(CompilerChange)
endif()
add_RunCMake_test(CompilerNotFound)
add_RunCMake_test(FindBoost)
add_RunCMake_test(FindLua)
add_RunCMake_test(FindOpenGL)
+if(CMake_TEST_UseSWIG)
+ add_RunCMake_test(UseSWIG)
+endif()
if(NOT CMAKE_C_COMPILER_ID MATCHES "Watcom")
add_RunCMake_test(GenerateExportHeader)
endif()
add_RunCMake_test(include_directories)
add_RunCMake_test(include_guard)
add_RunCMake_test(list)
+add_RunCMake_test(math)
add_RunCMake_test(message)
+add_RunCMake_test(option)
add_RunCMake_test(project -DCMake_TEST_RESOURCES=${CMake_TEST_RESOURCES})
add_RunCMake_test(project_injected)
add_RunCMake_test(return)
add_RunCMake_test(set_property)
add_RunCMake_test(string)
add_RunCMake_test(test_include_dirs)
+add_RunCMake_test(BundleUtilities)
function(add_RunCMake_test_try_compile)
if(CMAKE_VERSION VERSION_LESS 3.9.20170907 AND "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
add_RunCMake_test(File_Generate)
add_RunCMake_test(ExportWithoutLanguage)
add_RunCMake_test(target_link_libraries)
+add_RunCMake_test(add_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
+add_RunCMake_test(target_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
add_RunCMake_test(target_compile_features)
add_RunCMake_test(CheckModules)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
set(CTestCommandLine_ARGS -DTEST_AFFINITY=$<TARGET_FILE:testAffinity>)
endif()
-add_RunCMake_test(CTestCommandLine)
+add_executable(print_stdin print_stdin.c)
+add_RunCMake_test(CTestCommandLine -DTEST_PRINT_STDIN=$<TARGET_FILE:print_stdin>)
add_RunCMake_test(CacheNewline)
# Only run this test on unix platforms that support
# symbolic links
add_RunCMake_test(ctest_labels_for_subprojects)
endif()
-add_RunCMake_test_group(CPack "DEB;RPM;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ")
+add_RunCMake_test_group(CPack "DEB;RPM;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External")
# add a test to make sure symbols are exported from a shared library
# for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used
add_RunCMake_test(AutoExportDll)
cmake_policy(SET CMP0057 NEW)
-function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACKAGING_TYPE)
+function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACKAGING_TYPE package_target)
if(TEST_TYPE IN_LIST types)
set(RunCMake_TEST_NO_CLEAN TRUE)
- set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${TEST_NAME}-build")
- set(full_test_name_ "${TEST_NAME}")
+ if(package_target)
+ set(full_test_name_ "${TEST_NAME}-package-target")
+ else()
+ set(full_test_name_ "${TEST_NAME}")
+ endif()
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${full_test_name_}-build")
if(SUBTEST_SUFFIX)
set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_BINARY_DIR}-${SUBTEST_SUFFIX}-subtest")
unset(pack_params_)
endif()
+ if(package_target)
+ set(cpack_command_ ${CMAKE_COMMAND} --build "${RunCMake_TEST_BINARY_DIR}" --target package)
+ else()
+ set(cpack_command_ ${CMAKE_CPACK_COMMAND} ${pack_params_})
+ endif()
+
# execute cpack
+ set(SETENV)
+ if(ENVIRONMENT)
+ set(SETENV ${CMAKE_COMMAND} -E env "${ENVIRONMENT}")
+ endif()
execute_process(
- COMMAND ${CMAKE_CPACK_COMMAND} ${pack_params_}
+ COMMAND ${SETENV} ${cpack_command_}
WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
RESULT_VARIABLE "result_"
OUTPUT_FILE "${RunCMake_TEST_BINARY_DIR}/test_output.txt"
function(run_cpack_test TEST_NAME types build PACKAGING_TYPES)
foreach(packaging_type_ IN LISTS PACKAGING_TYPES)
- run_cpack_test_common_("${TEST_NAME}" "${types}" "${build}" "" false "${packaging_type_}")
+ run_cpack_test_common_("${TEST_NAME}" "${types}" "${build}" "" false "${packaging_type_}" false)
+ endforeach()
+endfunction()
+
+function(run_cpack_test_package_target TEST_NAME types build PACKAGING_TYPES)
+ foreach(packaging_type_ IN LISTS PACKAGING_TYPES)
+ run_cpack_test_common_("${TEST_NAME}" "${types}" "${build}" "" false "${packaging_type_}" true)
endforeach()
endfunction()
function(run_cpack_test_subtests TEST_NAME SUBTEST_SUFFIXES types build PACKAGING_TYPES)
foreach(suffix_ IN LISTS SUBTEST_SUFFIXES)
foreach(packaging_type_ IN LISTS PACKAGING_TYPES)
- run_cpack_test_common_("${TEST_NAME}" "${types}" "${build}" "${suffix_}" false "${packaging_type_}")
+ run_cpack_test_common_("${TEST_NAME}" "${types}" "${build}" "${suffix_}" false "${packaging_type_}" false)
endforeach()
endforeach()
endfunction()
function(run_cpack_source_test TEST_NAME types)
- run_cpack_test_common_("${TEST_NAME}" "${types}" false "" true "")
+ run_cpack_test_common_("${TEST_NAME}" "${types}" false "" true "" false)
endfunction()
-set(ALL_FILES_GLOB "*.deb")
+set(ALL_FILES_GLOB "*.deb" "*.ddeb")
function(getPackageContent FILE RESULT_VAR)
- execute_process(COMMAND ${DPKG_EXECUTABLE} -c "${FILE}"
+ execute_process(COMMAND ${CMAKE_COMMAND} -E env TZ=Etc/UTC ${DPKG_EXECUTABLE} -c "${FILE}"
OUTPUT_VARIABLE package_content_
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
--- /dev/null
+function(getPackageNameGlobexpr NAME COMPONENT VERSION REVISION FILE_NO RESULT_VAR)
+ set(${RESULT_VAR} "${NAME}-${VERSION}-*.json" PARENT_SCOPE)
+endfunction()
+
+function(getPackageContentList FILE RESULT_VAR)
+ set("${RESULT_VAR}" "" PARENT_SCOPE)
+endfunction()
+
+function(toExpectedContentList FILE_NO CONTENT_VAR)
+ set("${CONTENT_VAR}" "" PARENT_SCOPE)
+endfunction()
+
+set(ALL_FILES_GLOB "*.json")
+
+function(check_ext_json EXPECTED_FILE ACTUAL_FILE)
+ file(READ "${EXPECTED_FILE}" _expected_regex)
+ file(READ "${ACTUAL_FILE}" _actual_contents)
+
+ string(REGEX REPLACE "\n+$" "" _expected_regex "${_expected_regex}")
+ string(REGEX REPLACE "\n+$" "" _actual_contents "${_actual_contents}")
+
+ if(NOT "${_actual_contents}" MATCHES "${_expected_regex}")
+ message(FATAL_ERROR
+ "Output JSON does not match expected regex.\n"
+ "Expected regex:\n"
+ "${_expected_regex}\n"
+ "Actual output:\n"
+ "${_actual_contents}\n"
+ )
+ endif()
+endfunction()
-^(CPackRPM: Will use GENERATED spec file: (/[^/]*)*/Tests/RunCMake/RPM/CPack/[^-]*-build((-[^-]*-subtest/)|/)_CPack_Packages/.*/RPM/SPECS/[^\.]*\.spec(\n|$))*$
+^(CPackRPM: Will use GENERATED spec file: (/[^/]*)*/Tests/RunCMake/RPM/CPack/[^-]*(-package-target)?-build((-[^-]*-subtest/)|/)_CPack_Packages/.*/RPM/SPECS/[^\.]*\.spec(\n|$))*$
# 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;TGZ" true "COMPONENT")
-run_cpack_test(DEBUGINFO "RPM" true "COMPONENT")
+run_cpack_test(DEBUGINFO "RPM;DEB" true "COMPONENT")
run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM;DEB" false "MONOLITHIC;COMPONENT")
run_cpack_test(DEPENDENCIES "RPM;DEB" true "COMPONENT")
run_cpack_test(DIST "RPM" false "MONOLITHIC")
run_cpack_test(INSTALL_SCRIPTS "RPM" false "COMPONENT")
run_cpack_test(LONG_FILENAMES "DEB" false "MONOLITHIC")
run_cpack_test_subtests(MAIN_COMPONENT "invalid;found" "RPM" false "COMPONENT")
-run_cpack_test(MINIMAL "RPM;DEB;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ" false "MONOLITHIC;COMPONENT")
+run_cpack_test(MINIMAL "RPM;DEB;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External" false "MONOLITHIC;COMPONENT")
+run_cpack_test_package_target(MINIMAL "RPM;DEB;7Z;TBZ2;TGZ;TXZ;TZ;ZIP;STGZ;External" false "MONOLITHIC;COMPONENT")
run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false "MONOLITHIC")
run_cpack_test(PARTIALLY_RELOCATABLE_WARNING "RPM" false "COMPONENT")
run_cpack_test(PER_COMPONENT_FIELDS "RPM;DEB" false "COMPONENT")
run_cpack_source_test(SOURCE_PACKAGE "RPM")
run_cpack_test(SUGGESTS "RPM" false "MONOLITHIC")
run_cpack_test(SYMLINKS "RPM;TGZ" false "MONOLITHIC;COMPONENT")
+set(ENVIRONMENT "SOURCE_DATE_EPOCH=123456789")
+run_cpack_test(TIMESTAMPS "DEB;TGZ" false "COMPONENT")
+unset(ENVIRONMENT)
run_cpack_test(USER_FILELIST "RPM" false "MONOLITHIC")
run_cpack_test(MD5SUMS "DEB" false "MONOLITHIC;COMPONENT")
run_cpack_test(CPACK_INSTALL_SCRIPT "ZIP" false "MONOLITHIC")
run_cpack_test(DEB_PACKAGE_VERSION_BACK_COMPATIBILITY "DEB" false "MONOLITHIC;COMPONENT")
+run_cpack_test_subtests(EXTERNAL "none;good;good_multi;bad_major;bad_minor;invalid_good;invalid_bad;stage_and_package" "External" false "MONOLITHIC;COMPONENT")
set(EXPECTED_FILE_CONTENT_${file_no_} "${EXPECTED_FILE_CONTENT_${file_no_}_LIST}")
toExpectedContentList("${file_no_}" "EXPECTED_FILE_CONTENT_${file_no_}")
- list(SORT PACKAGE_CONTENT)
- list(SORT EXPECTED_FILE_CONTENT_${file_no_})
+ if(NOT PACKAGE_CONTENT STREQUAL "")
+ list(SORT PACKAGE_CONTENT)
+ endif()
+ if(NOT EXPECTED_FILE_CONTENT_${file_no_} STREQUAL "")
+ list(SORT EXPECTED_FILE_CONTENT_${file_no_})
+ endif()
if(PACKAGE_CONTENT STREQUAL EXPECTED_FILE_CONTENT_${file_no_})
set(expected_content_list TRUE)
# check that there were no extra files generated
foreach(all_files_glob_ IN LISTS ALL_FILES_GLOB)
file(GLOB foundAll_ RELATIVE "${bin_dir}" "${all_files_glob_}")
- list(APPEND allFoundFiles_ "${foundAll_}")
+ list(APPEND allFoundFiles_ ${foundAll_})
endforeach()
list(LENGTH foundFiles_ foundFilesCount_)
set(EXPECTED_FILES_COUNT "5")
set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
-set(EXPECTED_FILE_1_NAME "Debuginfo")
+if(GENERATOR_TYPE STREQUAL "RPM")
+ set(NAME "Debuginfo")
+ set(DEBUG_SUFFIX "debuginfo")
+ set(PKG "rpm")
+ set(DEBUG_PKG "rpm")
+elseif(GENERATOR_TYPE STREQUAL "DEB")
+ set(NAME "debuginfo")
+ set(DEBUG_SUFFIX "dbgsym")
+ set(PKG "deb")
+ set(DEBUG_PKG "ddeb")
+endif()
+
+set(EXPECTED_FILE_1_NAME "${NAME}")
set(EXPECTED_FILE_1_COMPONENT "applications")
set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
-set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.rpm")
+
+set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.${PKG}")
set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
-set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.rpm")
+
+set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.${PKG}")
set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/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.*\.debug.*")
-set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm")
-set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*")
+set(EXPECTED_FILE_4 "${NAME}-applications-${DEBUG_SUFFIX}*.${DEBUG_PKG}")
+if(GENERATOR_TYPE STREQUAL "RPM")
+ set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*\.debug.*")
+elseif(GENERATOR_TYPE STREQUAL "DEB")
+ set(EXPECTED_FILE_CONTENT_4 ".*/usr/lib/debug/.build-id/.*\.debug.*")
+endif()
+
+if(GENERATOR_TYPE STREQUAL "RPM")
+ set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm")
+ set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*")
+elseif(GENERATOR_TYPE STREQUAL "DEB")
+ set(EXPECTED_FILE_5 "TestDinfo-pkg-libs-dbgsym.ddeb")
+ set(EXPECTED_FILE_CONTENT_5 ".*/usr/lib/debug/.build-id/.*\.debug.*")
+endif()
set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT")
set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON)
+set(CPACK_DEBIAN_APPLICATIONS_FILE_NAME "DEB-DEFAULT")
+set(CPACK_DEBIAN_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)
+set(CPACK_DEBIAN_PACKAGE_NAME "Debuginfo")
+set(CPACK_DEBIAN_LIBS_DEBUGINFO_PACKAGE ON)
# test debuginfo package rename
set(CPACK_RPM_DEBUGINFO_FILE_NAME
--- /dev/null
+if(RunCMake_SUBTEST_SUFFIX MATCHES "^(none|good(_multi)?|invalid_good)$"
+ OR RunCMake_SUBTEST_SUFFIX STREQUAL "stage_and_package")
+ set(EXPECTED_FILES_COUNT "1")
+ set(EXPECTED_FILE_CONTENT_1_LIST "/share;/share/cpack-test;/share/cpack-test/f1.txt;/share/cpack-test/f2.txt;/share/cpack-test/f3.txt;/share/cpack-test/f4.txt")
+else()
+ set(EXPECTED_FILES_COUNT "0")
+endif()
--- /dev/null
+if(RunCMake_SUBTEST_SUFFIX MATCHES "^(none|good(_multi)?|invalid_good)")
+ check_ext_json("${src_dir}/tests/EXTERNAL/expected-json-1.0.txt" "${FOUND_FILE_1}")
+endif()
--- /dev/null
+CMake Error at .*/Modules/Internal/CPack/CPackExternal\.cmake:[0-9]+ \(message\):
+ Could not find a suitable version in CPACK_EXTERNAL_REQUESTED_VERSIONS
+
+
+CPack Error: Error while executing CPackExternal\.cmake
+CPack Error: Cannot initialize the generator External
--- /dev/null
+CMake Error at .*/Modules/Internal/CPack/CPackExternal\.cmake:[0-9]+ \(message\):
+ Could not find a suitable version in CPACK_EXTERNAL_REQUESTED_VERSIONS
+
+
+CPack Error: Error while executing CPackExternal\.cmake
+CPack Error: Cannot initialize the generator External
--- /dev/null
+message("This script could run an external packaging tool")
+
+function(expect_variable VAR)
+ if(NOT ${VAR})
+ message(FATAL_ERROR "${VAR} is unexpectedly not set")
+ endif()
+endfunction()
+
+function(expect_file FILE)
+ if(NOT EXISTS "${FILE}")
+ message(FATAL_ERROR "${FILE} is unexpectedly missing")
+ endif()
+endfunction()
+
+expect_variable(CPACK_COMPONENTS_ALL)
+expect_variable(CPACK_TOPLEVEL_DIRECTORY)
+expect_variable(CPACK_TEMPORARY_DIRECTORY)
+expect_variable(CPACK_PACKAGE_DIRECTORY)
+expect_variable(CPACK_PACKAGE_FILE_NAME)
+
+expect_file(${CPACK_TEMPORARY_DIRECTORY}/f1/share/cpack-test/f1.txt)
+expect_file(${CPACK_TEMPORARY_DIRECTORY}/f2/share/cpack-test/f2.txt)
+expect_file(${CPACK_TEMPORARY_DIRECTORY}/f3/share/cpack-test/f3.txt)
+expect_file(${CPACK_TEMPORARY_DIRECTORY}/f4/share/cpack-test/f4.txt)
--- /dev/null
+^\{
+ "componentGroups" :[ ]
+ \{
+ "f12" :[ ]
+ \{
+ "components" :[ ]
+ \[
+ "f1",
+ "f2"
+ \],
+ "description" : "Component group for files 1 and 2",
+ "displayName" : "Files 1 and 2",
+ "isBold" : false,
+ "isExpandedByDefault" : false,
+ "name" : "f12",
+ "parentGroup" : "f1234",
+ "subgroups" : \[\]
+ \},
+ "f1234" :[ ]
+ \{
+ "components" : \[\],
+ "description" : "Component group for all files",
+ "displayName" : "Files 1-4",
+ "isBold" : false,
+ "isExpandedByDefault" : false,
+ "name" : "f1234",
+ "subgroups" :[ ]
+ \[
+ "f12",
+ "f34"
+ \]
+ \},
+ "f34" :[ ]
+ \{
+ "components" :[ ]
+ \[
+ "f3",
+ "f4"
+ \],
+ "description" : "Component group for files 3 and 4",
+ "displayName" : "Files 3 and 4",
+ "isBold" : false,
+ "isExpandedByDefault" : false,
+ "name" : "f34",
+ "parentGroup" : "f1234",
+ "subgroups" : \[\]
+ \}
+ \},
+ "components" :[ ]
+ \{
+ "f1" :[ ]
+ \{
+ "archiveFile" : "",
+ "dependencies" : \[\],
+ "description" : "Component for file 1",
+ "displayName" : "File 1",
+ "group" : "f12",
+ "installationTypes" :[ ]
+ \[
+ "full",
+ "f12"
+ \],
+ "isDisabledByDefault" : false,
+ "isDownloaded" : false,
+ "isHidden" : false,
+ "isRequired" : false,
+ "name" : "f1"
+ \},
+ "f2" :[ ]
+ \{
+ "archiveFile" : "",
+ "dependencies" :[ ]
+ \[
+ "f1"
+ \],
+ "description" : "Component for file 2",
+ "displayName" : "File 2",
+ "group" : "f12",
+ "installationTypes" :[ ]
+ \[
+ "full",
+ "f12"
+ \],
+ "isDisabledByDefault" : false,
+ "isDownloaded" : false,
+ "isHidden" : false,
+ "isRequired" : false,
+ "name" : "f2"
+ \},
+ "f3" :[ ]
+ \{
+ "archiveFile" : "",
+ "dependencies" :[ ]
+ \[
+ "f1",
+ "f2"
+ \],
+ "description" : "Component for file 3",
+ "displayName" : "File 3",
+ "group" : "f34",
+ "installationTypes" :[ ]
+ \[
+ "full"
+ \],
+ "isDisabledByDefault" : false,
+ "isDownloaded" : false,
+ "isHidden" : false,
+ "isRequired" : false,
+ "name" : "f3"
+ \},
+ "f4" :[ ]
+ \{
+ "archiveFile" : "",
+ "dependencies" :[ ]
+ \[
+ "f2",
+ "f3",
+ "f1"
+ \],
+ "description" : "Component for file 4",
+ "displayName" : "File 4",
+ "group" : "f34",
+ "installationTypes" :[ ]
+ \[
+ "full"
+ \],
+ "isDisabledByDefault" : false,
+ "isDownloaded" : false,
+ "isHidden" : false,
+ "isRequired" : false,
+ "name" : "f4"
+ \}
+ \},
+ "errorOnAbsoluteInstallDestination" : false,
+ "formatVersionMajor" : 1,
+ "formatVersionMinor" : 0,
+ "installationTypes" :[ ]
+ \{
+ "f12" :[ ]
+ \{
+ "displayName" : "Only files 1 and 2",
+ "index" : 2,
+ "name" : "f12"
+ \},
+ "full" :[ ]
+ \{
+ "displayName" : "Full installation",
+ "index" : 1,
+ "name" : "full"
+ \}
+ \},
+ "packageDescriptionFile" : ".*/Templates/CPack\.GenericDescription\.txt",
+ "packageDescriptionSummary" : "EXTERNAL-(none|good(_multi)?|invalid_good)-subtest-(MONOLITHIC|COMPONENT)-type built using CMake",
+ "packageName" : "external",
+ "packageVersion" : "0\.1\.1",
+ "projects" :[ ]
+ \[
+ \{
+ "component" : "ALL",
+ "components" :[ ]
+ \[
+ "f1",
+ "f2",
+ "f3",
+ "f4"
+ \],
+ "directory" : ".*/Tests/RunCMake/External/CPack/EXTERNAL-build-(none|good(_multi)?|invalid_good)-subtest",
+ "installationTypes" : \[\],
+ "projectName" : "EXTERNAL-(none|good(_multi)?|invalid_good)-subtest-(MONOLITHIC|COMPONENT)-type",
+ "subDirectory" : "/"
+ \}
+ \],
+ "setDestdir" : false,
+ "stripFiles" : false,
+ "warnOnAbsoluteInstallDestination" : false
+\}$
--- /dev/null
+CMake Error at .*/Modules/Internal/CPack/CPackExternal\.cmake:[0-9]+ \(message\):
+ Could not find a suitable version in CPACK_EXTERNAL_REQUESTED_VERSIONS
+
+
+CPack Error: Error while executing CPackExternal\.cmake
+CPack Error: Cannot initialize the generator External
--- /dev/null
+^This script could run an external packaging tool$
--- /dev/null
+include(CPackComponent)
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "none")
+ unset(CPACK_EXTERNAL_REQUESTED_VERSIONS)
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "good")
+ set(CPACK_EXTERNAL_REQUESTED_VERSIONS "1.0")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "good_multi")
+ set(CPACK_EXTERNAL_REQUESTED_VERSIONS "1.0;2.0")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "bad_major")
+ set(CPACK_EXTERNAL_REQUESTED_VERSIONS "2.0")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "bad_minor")
+ set(CPACK_EXTERNAL_REQUESTED_VERSIONS "1.1")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "invalid_good")
+ set(CPACK_EXTERNAL_REQUESTED_VERSIONS "1;1.0")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "invalid_bad")
+ set(CPACK_EXTERNAL_REQUESTED_VERSIONS "1")
+elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "stage_and_package")
+ set(CPACK_EXTERNAL_ENABLE_STAGING 1)
+ set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/create_package.cmake")
+endif()
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f1.txt" test1)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f2.txt" test2)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f3.txt" test3)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/f4.txt" test4)
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f1.txt" DESTINATION share/cpack-test COMPONENT f1)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f2.txt" DESTINATION share/cpack-test COMPONENT f2)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f3.txt" DESTINATION share/cpack-test COMPONENT f3)
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/f4.txt" DESTINATION share/cpack-test COMPONENT f4)
+
+cpack_add_component(f1
+ DISPLAY_NAME "File 1"
+ DESCRIPTION "Component for file 1"
+ GROUP f12
+ INSTALL_TYPES full f12
+)
+
+cpack_add_component(f2
+ DISPLAY_NAME "File 2"
+ DESCRIPTION "Component for file 2"
+ GROUP f12
+ DEPENDS f1
+ INSTALL_TYPES full f12
+)
+
+cpack_add_component(f3
+ DISPLAY_NAME "File 3"
+ DESCRIPTION "Component for file 3"
+ GROUP f34
+ DEPENDS f1 f2
+ INSTALL_TYPES full
+)
+
+cpack_add_component(f4
+ DISPLAY_NAME "File 4"
+ DESCRIPTION "Component for file 4"
+ GROUP f34
+ DEPENDS f2 f3 f1
+ INSTALL_TYPES full
+)
+
+cpack_add_component_group(f12
+ DISPLAY_NAME "Files 1 and 2"
+ DESCRIPTION "Component group for files 1 and 2"
+ PARENT_GROUP f1234
+)
+
+cpack_add_component_group(f34
+ DISPLAY_NAME "Files 3 and 4"
+ DESCRIPTION "Component group for files 3 and 4"
+ PARENT_GROUP f1234
+)
+
+cpack_add_component_group(f1234
+ DISPLAY_NAME "Files 1-4"
+ DESCRIPTION "Component group for all files"
+)
+
+cpack_add_install_type(full
+ DISPLAY_NAME "Full installation"
+)
+
+cpack_add_install_type(f12
+ DISPLAY_NAME "Only files 1 and 2"
+)
function(checkPackageInfo_ TYPE FILE REGEX)
getPackageInfo("${FILE}" "FILE_INFO_")
if(NOT FILE_INFO_ MATCHES "${REGEX}")
- message(FATAL_ERROR "Unexpected ${TYPE} in '${FILE}'; file info: '${FILE_INFO_}'")
+ message(FATAL_ERROR "Unexpected ${TYPE} in '${FILE}'; file info: '${FILE_INFO_}'; does not match '${REGEX}'")
endif()
endfunction()
checkPackageInfo_("group" "${FOUND_FILE_1}" ".*${group_}${whitespaces_}:${whitespaces_}default")
checkPackageInfo_("group" "${FOUND_FILE_2}" ".*${group_}${whitespaces_}:${whitespaces_}second_group")
checkPackageInfo_("group" "${FOUND_FILE_3}" ".*${group_}${whitespaces_}:${whitespaces_}default")
+
+# check package summaries (not available in DEB)
+if(GENERATOR_TYPE STREQUAL "RPM")
+ checkPackageInfo_("summary" "${FOUND_FILE_1}" ".*Summary${whitespaces_}:${whitespaces_}Global summary")
+ checkPackageInfo_("summary" "${FOUND_FILE_2}" ".*Summary${whitespaces_}:${whitespaces_}Summary for pkg_2")
+ checkPackageInfo_("summary" "${FOUND_FILE_3}" ".*Summary${whitespaces_}:${whitespaces_}Global summary")
+endif()
+
+# check package description
+checkPackageInfo_("description" "${FOUND_FILE_1}" ".*Description${whitespaces_}:${whitespaces_}Description for pkg_1")
+checkPackageInfo_("description" "${FOUND_FILE_2}" ".*Description${whitespaces_}:${whitespaces_}Description for pkg_2")
+checkPackageInfo_("description" "${FOUND_FILE_3}" ".*Description${whitespaces_}:${whitespaces_}Description for pkg_3")
set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PACKAGE_${group_} "default")
set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PKG_2_PACKAGE_NAME "second")
set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PKG_2_PACKAGE_${group_} "second_group")
+
+ set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PACKAGE_SUMMARY "Global summary") # not used for DEB
+ set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PKG_2_PACKAGE_SUMMARY "Summary for pkg_2") # not used for DEB
+
+ set(CPACK_COMPONENT_PKG_1_DESCRIPTION "Description for pkg_1")
+ set(CPACK_COMPONENT_PKG_2_DESCRIPTION "Description for pkg_2")
+ set(CPACK_COMPONENT_PKG_3_DESCRIPTION "Description for pkg_3")
endif()
install(FILES CMakeLists.txt DESTINATION foo COMPONENT pkg_1)
--- /dev/null
+set(EXPECTED_FILES_COUNT "1")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
--- /dev/null
+macro(getFileMetadata_ FILE RESULT_VAR)
+ if(GENERATOR_TYPE STREQUAL "TGZ")
+ # getPackageContent defined for archives omit the metadata (non-verbose)
+ execute_process(COMMAND ${CMAKE_COMMAND} -E env TZ=Etc/UTC ${CMAKE_COMMAND} -E tar -xtvf ${FILE}
+ OUTPUT_VARIABLE ${RESULT_VAR}
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ else()
+ getPackageContent("${FILE}" ${RESULT_VAR})
+ endif()
+endmacro()
+
+function(checkContentTimestamp FILE REGEX)
+ getFileMetadata_("${FILE}" METADATA_)
+
+ if(NOT METADATA_ MATCHES "${REGEX}")
+ string(REPLACE "\n" "\n " metadata_indented "${METADATA_}")
+ message(FATAL_ERROR
+ "Wrong timestamps in file:\n"
+ " ${FILE}\n"
+ "Expected timestamps to match:\n"
+ " ${REGEX}\n"
+ "Actual timestamps:\n"
+ " ${metadata_indented}")
+ endif()
+endfunction()
+
+function(checkTimestamp FILE_NAME)
+ file(READ ${FILE_NAME} ACTUAL_TIMESTAMP OFFSET 4 LIMIT 4 HEX)
+
+ if(NOT ACTUAL_TIMESTAMP STREQUAL "00000000")
+ message(FATAL_ERROR "${FILE_NAME} contains a timestamp [0x${ACTUAL_TIMESTAMP}]")
+ endif()
+endfunction()
+
+# Expected timestamp is UNIX time 123456789
+if(GENERATOR_TYPE STREQUAL "TGZ")
+ set(EXPECTED_TIMESTAMP "29 Nov +1973")
+ set(EXPECTED_FILES foo/ foo/CMakeLists.txt)
+else()
+ set(EXPECTED_TIMESTAMP "1973-11-29 21:33")
+ set(EXPECTED_FILES ./usr/ ./usr/foo/ ./usr/foo/CMakeLists.txt)
+endif()
+
+set(EXPECTED_METADATA)
+foreach(FILE ${EXPECTED_FILES})
+ list(APPEND EXPECTED_METADATA ".* ${EXPECTED_TIMESTAMP} ${FILE}")
+endforeach()
+list(JOIN EXPECTED_METADATA ".*" EXPECTED_REGEX)
+checkContentTimestamp("${FOUND_FILE_1}" "${EXPECTED_REGEX}")
+
+if(GENERATOR_TYPE STREQUAL "TGZ")
+ checkTimestamp("${FOUND_FILE_1}")
+else()
+ execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${FOUND_FILE_1}")
+ checkTimestamp("data.tar.gz")
+ checkTimestamp("control.tar.gz")
+endif()
--- /dev/null
+install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
+
+set(CPACK_COMPONENTS_ALL test)
if(TEST_AFFINITY)
run_TestAffinity()
endif()
+
+function(run_TestStdin)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestStdin)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+ add_test(TestStdin \"${TEST_PRINT_STDIN}\")
+ ")
+ run_cmake_command(TestStdin ${CMAKE_CTEST_COMMAND} -V)
+endfunction()
+run_TestStdin()
--- /dev/null
+Content for TestStdin
--- /dev/null
+Content for TestStdin
run_cmake(save-to-result)
run_cmake(cmp0069-is-old)
-if(RunCMake_GENERATOR MATCHES "^Visual Studio ")
+if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 ")
run_cmake(not-supported-by-generator)
endif()
--- /dev/null
+CMake Error: No build directory specified for -B
--- /dev/null
+CMake Error: No build directory specified for -B
-if(NOT IS_SYMLINK ${RunCMake_TEST_BINARY_DIR}/L)
- set(RunCMake_TEST_FAILED "Symlink 'L' incorrectly not created!")
-endif()
-if(EXISTS ${RunCMake_TEST_BINARY_DIR}/L)
- set(RunCMake_TEST_FAILED "Symlink 'L' not broken!")
+if(${actual_stderr_var} MATCHES "operation not permitted")
+ unset(msg)
+else()
+ if(NOT IS_SYMLINK ${RunCMake_TEST_BINARY_DIR}/L)
+ set(RunCMake_TEST_FAILED "Symlink 'L' incorrectly not created!")
+ endif()
+ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/L)
+ set(RunCMake_TEST_FAILED "Symlink 'L' not broken!")
+ endif()
endif()
-if(NOT IS_DIRECTORY ${RunCMake_TEST_BINARY_DIR}/L)
- set(RunCMake_TEST_FAILED "Symlink 'L' not replaced correctly!")
+if(${actual_stderr_var} MATCHES "operation not permitted")
+ unset(msg)
+else()
+ if(NOT IS_DIRECTORY ${RunCMake_TEST_BINARY_DIR}/L)
+ set(RunCMake_TEST_FAILED "Symlink 'L' not replaced correctly!")
+ endif()
endif()
--- /dev/null
+cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
+add_custom_command(
+ OUTPUT output.txt
+ COMMAND ${CMAKE_COMMAND} -E echo CustomCommand > output.txt
+ )
+add_custom_target(CustomTarget ALL DEPENDS output.txt)
+add_custom_target(CustomTarget2 ALL DEPENDS output.txt)
+add_custom_target(CustomTarget3 ALL DEPENDS output.txt)
cmake \[options\] <path-to-source>
cmake \[options\] <path-to-existing-build>
+ cmake \[options\] -S <path-to-source> -B <path-to-build>
Specify a source directory to \(re-\)generate a build system for it in the
current working directory. Specify an existing build directory to
include(RunCMake)
run_cmake_command(NoArgs ${CMAKE_COMMAND})
+run_cmake_command(Wizard ${CMAKE_COMMAND} -i)
run_cmake_command(C-no-arg ${CMAKE_COMMAND} -C)
run_cmake_command(C-no-file ${CMAKE_COMMAND} -C nosuchcachefile.txt)
run_cmake_command(cache-no-file ${CMAKE_COMMAND} nosuchsubdir/CMakeCache.txt)
run_cmake_command(cache-empty-entry
${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-empty-entry/)
+function(run_ExplicitDirs)
+ set(source_dir ${RunCMake_SOURCE_DIR}/ExplicitDirs)
+ set(binary_dir ${RunCMake_BINARY_DIR}/ExplicitDirs-build)
+
+ file(REMOVE_RECURSE "${binary_dir}")
+ file(MAKE_DIRECTORY "${binary_dir}")
+ run_cmake_command(S-arg ${CMAKE_COMMAND} -S ${source_dir} ${binary_dir})
+ run_cmake_command(S-arg-reverse-order ${CMAKE_COMMAND} ${binary_dir} -S${source_dir} )
+ run_cmake_command(S-no-arg ${CMAKE_COMMAND} -S )
+ run_cmake_command(S-no-arg2 ${CMAKE_COMMAND} -S -T)
+ run_cmake_command(S-B ${CMAKE_COMMAND} -S ${source_dir} -B ${binary_dir})
+
+ # make sure that -B can explicitly construct build directories
+ file(REMOVE_RECURSE "${binary_dir}")
+ run_cmake_command(B-arg ${CMAKE_COMMAND} -B ${binary_dir} ${source_dir})
+ file(REMOVE_RECURSE "${binary_dir}")
+ run_cmake_command(B-arg-reverse-order ${CMAKE_COMMAND} ${source_dir} -B${binary_dir})
+ run_cmake_command(B-no-arg ${CMAKE_COMMAND} -B )
+ run_cmake_command(B-no-arg2 ${CMAKE_COMMAND} -B -T)
+ file(REMOVE_RECURSE "${binary_dir}")
+ run_cmake_command(B-S ${CMAKE_COMMAND} -B${binary_dir} -S${source_dir})
+
+endfunction()
+run_ExplicitDirs()
+
function(run_BuildDir)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BuildDir-build)
unset(RunCMake_TEST_NO_CLEAN)
endif()
-if(UNIX)
- run_cmake_command(E_create_symlink-no-arg
- ${CMAKE_COMMAND} -E create_symlink
- )
- run_cmake_command(E_create_symlink-missing-dir
- ${CMAKE_COMMAND} -E create_symlink T missing-dir/L
- )
+run_cmake_command(E_create_symlink-no-arg
+ ${CMAKE_COMMAND} -E create_symlink
+ )
+run_cmake_command(E_create_symlink-missing-dir
+ ${CMAKE_COMMAND} -E create_symlink T missing-dir/L
+ )
- # Use a single build tree for a few tests without cleaning.
- set(RunCMake_TEST_BINARY_DIR
- ${RunCMake_BINARY_DIR}/E_create_symlink-broken-build)
- set(RunCMake_TEST_NO_CLEAN 1)
- file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
- run_cmake_command(E_create_symlink-broken-create
- ${CMAKE_COMMAND} -E create_symlink T L
- )
- run_cmake_command(E_create_symlink-broken-replace
- ${CMAKE_COMMAND} -E create_symlink . L
- )
- unset(RunCMake_TEST_BINARY_DIR)
- unset(RunCMake_TEST_NO_CLEAN)
+# Use a single build tree for a few tests without cleaning.
+# These tests are special on Windows since it will only fail if the user
+# running the test does not have the priveldge to create symlinks. If this
+# happens we clear the msg in the -check.cmake and say that the test passes
+set(RunCMake_DEFAULT_stderr "(operation not permitted)?")
+set(RunCMake_TEST_BINARY_DIR
+ ${RunCMake_BINARY_DIR}/E_create_symlink-broken-build)
+set(RunCMake_TEST_NO_CLEAN 1)
+file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+run_cmake_command(E_create_symlink-broken-create
+ ${CMAKE_COMMAND} -E create_symlink T L
+ )
+run_cmake_command(E_create_symlink-broken-replace
+ ${CMAKE_COMMAND} -E create_symlink . L
+ )
+unset(RunCMake_TEST_BINARY_DIR)
+unset(RunCMake_TEST_NO_CLEAN)
+unset(RunCMake_DEFAULT_stderr)
- run_cmake_command(E_create_symlink-no-replace-dir
- ${CMAKE_COMMAND} -E create_symlink T .
- )
-endif()
+run_cmake_command(E_create_symlink-no-replace-dir
+ ${CMAKE_COMMAND} -E create_symlink T .
+ )
set(in ${RunCMake_SOURCE_DIR}/copy_input)
set(out ${RunCMake_BINARY_DIR}/copy_output)
--- /dev/null
+CMake Error: No source directory specified for -S
--- /dev/null
+CMake Error: No source directory specified for -S
--- /dev/null
+^The "cmake -i" wizard mode is no longer supported\.
--- /dev/null
+^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ error: ExternalProject module must be explicitly included before using
+ ExternalProject_Add function
+Call Stack \(most recent call first\):
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_parse_arguments\)
+ IncludeScope-Add.cmake:[0-9]+ \(ExternalProject_Add\)
+ CMakeLists.txt:[0-9]+ \(include\)$
--- /dev/null
+function(IncludeScope_IncludeOnly)
+ include(ExternalProject)
+endfunction()
+
+IncludeScope_IncludeOnly()
+
+ExternalProject_Add(MyProj
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+)
--- /dev/null
+^CMake Error at .*/Modules/ExternalProject.cmake:[0-9]+ \(message\):
+ error: ExternalProject module must be explicitly included before using
+ ExternalProject_Add_Step function
+Call Stack \(most recent call first\):
+ .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_parse_arguments\)
+ IncludeScope-Add_Step.cmake:[0-9]+ \(ExternalProject_Add_Step\)
+ CMakeLists.txt:[0-9]+ \(include\)$
--- /dev/null
+function(IncludeScope_DefineProj)
+ include(ExternalProject)
+ ExternalProject_Add(MyProj
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ )
+endfunction()
+
+IncludeScope_DefineProj()
+
+ExternalProject_Add_Step(MyProj extraStep COMMENT "Foo")
include(RunCMake)
+run_cmake(IncludeScope-Add)
+run_cmake(IncludeScope-Add_Step)
run_cmake(NoOptions)
run_cmake(SourceEmpty)
run_cmake(SourceMissing)
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.12)
project(FindPkgConfig_IMPORTED_TARGET C)
find_package(PkgConfig REQUIRED)
pkg_check_modules(NCURSES IMPORTED_TARGET QUIET ncurses)
+message(STATUS "source: ${CMAKE_CURRENT_SOURCE_DIR} bin ${CMAKE_CURRENT_BINARY_DIR}")
+
if (NCURSES_FOUND)
set(tgt PkgConfig::NCURSES)
if (NOT TARGET ${tgt})
message(FATAL_ERROR "No import target for fake package 1 with prefix path")
endif()
+# find targets in subdir and check their visibility
+add_subdirectory(target_subdir)
+if (TARGET PkgConfig::FakePackage1_dir)
+ message(FATAL_ERROR "imported target PkgConfig::FakePackage1_dir is visible outside it's directory")
+endif()
+
+if (NOT TARGET PkgConfig::FakePackage1_global)
+ message(FATAL_ERROR "imported target PkgConfig::FakePackage1_global is not visible outside it's directory")
+endif()
+
# And now do the same for the NO_CMAKE_ENVIRONMENT_PATH - ENV{CMAKE_PREFIX_PATH}
# combination
unset(CMAKE_PREFIX_PATH)
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+
+project(FindPkgConfig_IMPORTED_TARGET C)
+
+find_package(PkgConfig REQUIRED)
+
+message(STATUS "source: ${CMAKE_CURRENT_SOURCE_DIR} bin ${CMAKE_CURRENT_BINARY_DIR}")
+
+# Setup for the remaining package tests below
+set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH)
+set(fakePkgDir ${CMAKE_CURRENT_BINARY_DIR}/pc-fakepackage)
+file(WRITE ${fakePkgDir}/lib/libcmakeinternalfakepackage.a "")
+file(WRITE ${fakePkgDir}/lib/cmakeinternalfakepackage.lib "")
+file(WRITE ${fakePkgDir}/lib/pkgconfig/cmakeinternalfakepackage.pc
+"Name: CMakeInternalFakePackage
+Description: Dummy package for FindPkgConfig VERSION_OPERATORS test
+Version: 8.9
+Libs: -lcmakeinternalfakepackage
+")
+
+# Always find the .pc file in the calls further below so that we can test that
+# the import target find_library() calls handle the NO...PATH options correctly
+set(ENV{PKG_CONFIG_PATH} ${fakePkgDir}/lib/pkgconfig)
+
+pkg_check_modules(FakePackageGE REQUIRED QUIET "cmakeinternalfakepackage >= 8")
+if (NOT FakePackageGE_FOUND)
+ message(FATAL_ERROR "fake package >= 8 not found")
+endif()
+
+pkg_check_modules(FakePackageGE_FAIL QUIET "cmakeinternalfakepackage >= 8.10")
+if (FakePackageGE_FAIL_FOUND)
+ message(FATAL_ERROR "fake package >= 8.10 found")
+endif()
+
+pkg_check_modules(FakePackageLE REQUIRED QUIET "cmakeinternalfakepackage<=9")
+if (NOT FakePackageLE_FOUND)
+ message(FATAL_ERROR "fake package <= 9 not found")
+endif()
+
+pkg_check_modules(FakePackageLE_FAIL QUIET "cmakeinternalfakepackage <= 8.1")
+if (FakePackageLE_FAIL_FOUND)
+ message(FATAL_ERROR "fake package <= 8.1 found")
+endif()
+
+pkg_check_modules(FakePackageGT REQUIRED QUIET "cmakeinternalfakepackage > 8")
+if (NOT FakePackageGT_FOUND)
+ message(FATAL_ERROR "fake package > 8 not found")
+endif()
+
+pkg_check_modules(FakePackageGT_FAIL QUIET "cmakeinternalfakepackage > 8.9")
+if (FakePackageGT_FAIL_FOUND)
+ message(FATAL_ERROR "fake package > 8.9 found")
+endif()
+
+pkg_check_modules(FakePackageLT REQUIRED QUIET "cmakeinternalfakepackage<9")
+if (NOT FakePackageLT_FOUND)
+ message(FATAL_ERROR "fake package < 9 not found")
+endif()
+
+pkg_check_modules(FakePackageLT_FAIL QUIET "cmakeinternalfakepackage < 8.9")
+if (FakePackageLT_FAIL_FOUND)
+ message(FATAL_ERROR "fake package < 8.9 found")
+endif()
+
+pkg_check_modules(FakePackageEQ REQUIRED QUIET "cmakeinternalfakepackage=8.9")
+if (NOT FakePackageEQ_FOUND)
+ message(FATAL_ERROR "fake package = 8.9 not found")
+endif()
+
+pkg_check_modules(FakePackageEQ_FAIL QUIET "cmakeinternalfakepackage = 8.8")
+if (FakePackageEQ_FAIL_FOUND)
+ message(FATAL_ERROR "fake package = 8.8 found")
+endif()
+
+pkg_check_modules(FakePackageEQ_INV QUIET "cmakeinternalfakepackage == 8.9")
+if (FakePackageEQ_FAIL_FOUND)
+ message(FATAL_ERROR "fake package == 8.9 found")
+endif()
+
+pkg_check_modules(FakePackageLLT_INV QUIET "cmakeinternalfakepackage <<= 9")
+if (FakePackageLLT_FAIL_FOUND)
+ message(FATAL_ERROR "fake package <<= 9 found")
+endif()
run_cmake(FindPkgConfig_GET_VARIABLE)
run_cmake(FindPkgConfig_cache_variables)
run_cmake(FindPkgConfig_IMPORTED_TARGET)
+ run_cmake(FindPkgConfig_VERSION_OPERATORS)
endif ()
--- /dev/null
+# a target with visibility only in this directory
+pkg_check_modules(FakePackage1_dir REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage1)
+
+# the same with global visibility
+pkg_check_modules(FakePackage1_global REQUIRED QUIET IMPORTED_TARGET GLOBAL cmakeinternalfakepackage1)
include(RunCMake)
-if(SYSTEM_NAME MATCHES "^(.*BSD|DragonFly)$")
+if(SYSTEM_NAME MATCHES "^(([^k].*)?BSD|DragonFly)$")
set(EXPECT_BSD 1)
endif()
--- /dev/null
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ int flags_lib(void)
+{
+ return 0;
+}
include(RunCMake)
run_cmake(LINK_SEARCH_STATIC)
+
+
+macro(run_cmake_target test subtest target)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
+ # Intel compiler does not reject bad flags or objects!
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+
+ run_cmake(STATIC_LIBRARY_OPTIONS)
+
+ run_cmake_target(STATIC_LIBRARY_OPTIONS basic StaticLinkOptions)
+ run_cmake_target(STATIC_LIBRARY_OPTIONS genex StaticLinkOptions_genex --config Release)
+ run_cmake_target(STATIC_LIBRARY_OPTIONS shared SharedLinkOptions)
+
+ unset(RunCMake_TEST_OPTIONS)
+ unset(RunCMake_TEST_OUTPUT_MERGE)
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_RELEASE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_RELEASE'.")
+endif()
+if (actual_stdout MATCHES "SHELL:")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix 'SHELL:'.")
+endif()
--- /dev/null
+
+if (actual_stdout MATCHES "BADFLAG")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected flag 'BADFLAG'.")
+endif()
--- /dev/null
+
+enable_language(C)
+
+set(obj "${CMAKE_C_OUTPUT_EXTENSION}")
+if(BORLAND)
+ set(pre -)
+endif()
+
+add_library(StaticLinkOptions STATIC LinkOptionsLib.c)
+set_property(TARGET StaticLinkOptions PROPERTY STATIC_LIBRARY_OPTIONS ${pre}BADFLAG${obj})
+
+# static library with generator expression
+add_library(StaticLinkOptions_genex STATIC LinkOptionsLib.c)
+set_property(TARGET StaticLinkOptions_genex PROPERTY STATIC_LIBRARY_OPTIONS
+ $<$<CONFIG:Release>:${pre}BADFLAG_RELEASE${obj}>
+ "SHELL:" # produces no options
+ )
+
+# shared library do not use property STATIC_LIBRARY_OPTIONS
+add_library(SharedLinkOptions SHARED LinkOptionsLib.c)
+set_property(TARGET SharedLinkOptions PROPERTY STATIC_LIBRARY_OPTIONS ${pre}BADFLAG${obj})
--- /dev/null
+^CMake Deprecation Warning at CMP0058-OLD-by.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0058 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\)$
--- /dev/null
+^CMake Deprecation Warning at CMP0058-OLD-no.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0058 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\)$
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+project(Test LANGUAGES C)
+
+configure_file(PreventConfigureFileDupBuildRule.cmake PreventTargetAliasesDupBuildRule.cmake @ONLY)
+add_subdirectory(SubDirConfigureFileDup)
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+project(Test LANGUAGES C)
+
+# fake launcher executable
+set(input_launcher_executable ${CMAKE_CURRENT_BINARY_DIR}/fake_launcher_executable)
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/fake_launcher_executable "")
+
+# application and executable name
+set(application_target "HelloApp")
+set(application_name "Hello")
+set(executable_name "Hello")
+
+# target built in "<root>/bin"
+add_executable(${application_target} hello.c)
+set_target_properties(${application_target} PROPERTIES
+ OUTPUT_NAME ${executable_name}
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin
+ )
+
+# configured launcher in "<root>"
+set(configured_launcher_executable "${CMAKE_CURRENT_BINARY_DIR}/${application_name}")
+
+# create command to copy the launcher
+add_custom_command(
+ DEPENDS
+ ${input_launcher_executable}
+ OUTPUT
+ ${configured_launcher_executable}
+ COMMAND
+ ${CMAKE_COMMAND} -E copy ${input_launcher_executable} ${configured_launcher_executable}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT
+ "Configuring application launcher: ${application_name}"
+ )
+
+add_custom_target(Configure${application_name}Launcher ALL
+ DEPENDS
+ ${application_target}
+ ${input_launcher_executable}
+ ${configured_launcher_executable}
+ )
set(cmd_prefix "")
set(cmd_suffix "")
endif()
+ set(fs_delay 3) # We assume the system as 1 sec timestamp resolution.
file(WRITE "${top_build_ninja}" "\
subninja ${escaped_ninja_output_path_prefix}/build.ninja
default ${escaped_ninja_output_path_prefix}/all
-# Sleep for 1 second before to regenerate to make sure the timestamp of
+# Sleep for long enough before regenerating to make sure the timestamp of
# the top build.ninja will be strictly greater than the timestamp of the
-# sub/build.ninja file. We assume the system as 1 sec timestamp resolution.
+# sub/build.ninja file.
rule RERUN
- command = ${cmd_prefix}\"${escaped_CMAKE_COMMAND}\" -E sleep 1 && \"${escaped_CMAKE_COMMAND}\" -E touch \"${escaped_top_build_ninja}\"${cmd_suffix}
+ command = ${cmd_prefix}\"${escaped_CMAKE_COMMAND}\" -E sleep ${fs_delay} && \"${escaped_CMAKE_COMMAND}\" -E touch \"${escaped_top_build_ninja}\"${cmd_suffix}
description = Testing regeneration
generator = 1
# Test regeneration rules run in order.
set(main_cmakelists "${RunCMake_SOURCE_DIR}/CMakeLists.txt")
- sleep(1) # Assume the system as 1 sec timestamp resolution.
+ sleep(${fs_delay})
touch("${main_cmakelists}")
touch("${build_ninja_dep}")
run_ninja("${top_build_dir}")
run_sub_cmake(SubDirPrefix "${ninja_output_path_prefix}")
run_sub_cmake(CustomCommandWorkingDirectory "${ninja_output_path_prefix}")
endforeach(ninja_output_path_prefix)
+
+function (run_PreventTargetAliasesDupBuildRule)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PreventTargetAliasesDupBuildRule-build)
+ run_cmake(PreventTargetAliasesDupBuildRule)
+ run_ninja("${RunCMake_TEST_BINARY_DIR}" -w dupbuild=err)
+endfunction ()
+run_PreventTargetAliasesDupBuildRule()
+
+function (run_PreventConfigureFileDupBuildRule)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PreventConfigureFileDupBuildRule-build)
+ run_cmake(PreventConfigureFileDupBuildRule)
+ run_ninja("${RunCMake_TEST_BINARY_DIR}" -w dupbuild=err)
+endfunction()
+run_PreventConfigureFileDupBuildRule()
--- /dev/null
+configure_file(../PreventConfigureFileDupBuildRule.cmake PreventTargetAliasesDupBuildRule.cmake @ONLY)
else()
set(maybe_timeout "")
endif()
+ if(RunCMake-stdin-file AND EXISTS ${top_src}/${RunCMake-stdin-file})
+ set(maybe_input_file INPUT_FILE ${top_src}/${RunCMake-stdin-file})
+ elseif(EXISTS ${top_src}/${test}-stdin.txt)
+ set(maybe_input_file INPUT_FILE ${top_src}/${test}-stdin.txt)
+ else()
+ set(maybe_input_file "")
+ endif()
if(RunCMake_TEST_COMMAND)
execute_process(
COMMAND ${RunCMake_TEST_COMMAND}
RESULT_VARIABLE actual_result
ENCODING UTF8
${maybe_timeout}
+ ${maybe_input_file}
)
else()
if(RunCMake_GENERATOR_INSTANCE)
RESULT_VARIABLE actual_result
ENCODING UTF8
${maybe_timeout}
+ ${maybe_input_file}
)
endif()
set(msg "")
--- /dev/null
+^-->value<--
+-->value<--$
--- /dev/null
+cmake_policy(SET CMP0053 NEW)
+
+set($ value)
+set(dollar $)
+message("-->${${dollar}}<--")
+message("-->${$}<--")
--- /dev/null
+^CMake Deprecation Warning at CMP0053-Dollar-OLD.cmake:1 \(cmake_policy\):
+ The OLD behavior for policy CMP0053 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:3 \(include\)
++
+-->value<--
+CMake Error at CMP0053-Dollar-OLD.cmake:6 \(message\):
+ Syntax error in cmake code at
+
+ .*CMP0053-Dollar-OLD.cmake:6
+
+ when parsing string
+
+ -->\${\$}<--
+
+ syntax error, unexpected \$, expecting } \(7\)
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+cmake_policy(SET CMP0053 OLD)
+
+set($ value)
+set(dollar $)
+message("-->${${dollar}}<--")
+message("-->${$}<--")
--- /dev/null
+-->cache value<--
+-->local value<--
--- /dev/null
+
+set(query_var "cache value" CACHE STRING "")
+set(query_var "local value")
+
+message("-->$CACHE{query_var}<--")
+message("-->${query_var}<--")
run_cmake(CMP0053-NameWithCarriageReturnQuoted)
run_cmake(CMP0053-NameWithEscapedSpacesQuoted)
run_cmake(CMP0053-NameWithEscapedTabsQuoted)
+run_cmake(CMP0053-Dollar-OLD)
+run_cmake(CMP0053-Dollar-NEW)
+
+# Variable special types
+run_cmake(QueryCache)
# Function and macro tests.
run_cmake(FunctionUnmatched)
\* CMP0068
\* CMP0069
\* CMP0073
+ \* CMP0076
+ \* CMP0081
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
--- /dev/null
+cmake_policy(SET CMP0076 OLD)
+
+add_library(iface INTERFACE)
+target_sources(iface INTERFACE empty_1.cpp)
+
+get_property(iface_sources TARGET iface PROPERTY INTERFACE_SOURCES)
+message(STATUS "iface: ${iface_sources}")
+
+add_executable(main main.cpp)
+target_link_libraries(main iface)
--- /dev/null
+CMake Warning \(dev\) at CMP0076-WARN/CMakeLists.txt:2 \(target_sources\):
+ Policy CMP0076 is not set: target_sources\(\) command converts relative paths
+ to absolute. Run "cmake --help-policy CMP0076" for policy details. Use
+ the cmake_policy command to set the policy and suppress this warning.
+
+ An interface source of target "publiclib" has a relative path.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\) at CMP0076-WARN/CMakeLists.txt:2 \(target_sources\):
+ Policy CMP0076 is not set: target_sources\(\) command converts relative paths
+ to absolute. Run "cmake --help-policy CMP0076" for policy details. Use
+ the cmake_policy command to set the policy and suppress this warning.
+
+ A private source from a directory other than that of target "publiclib" has
+ a relative path.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ Target "publiclib" contains relative path in its INTERFACE_SOURCES:
+
+ "CMP0076-WARN/subdir_empty_1.cpp"
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+
+add_library(publiclib)
+
+add_subdirectory(CMP0076-WARN)
+
+add_executable(main main.cpp)
+target_link_libraries(main publiclib)
--- /dev/null
+
+target_sources(publiclib INTERFACE CMP0076-WARN/subdir_empty_1.cpp
+ PRIVATE empty_1.cpp)
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
--- /dev/null
+-- iface: .*Tests/RunCMake/TargetSources/empty_1.cpp
+cmake_policy(SET CMP0076 NEW)
add_library(iface INTERFACE)
target_sources(iface INTERFACE empty_1.cpp)
+get_property(iface_sources TARGET iface PROPERTY INTERFACE_SOURCES)
+message(STATUS "iface: ${iface_sources}")
+
add_executable(main main.cpp)
target_link_libraries(main iface)
--- /dev/null
+-- genexlib: \$<1:.*Tests/RunCMake/TargetSources/RelativePathInSubdirGenEx/subdir_empty_1.cpp>;\$<1:.*Tests/RunCMake/TargetSources/RelativePathInSubdirGenEx/../empty_1.cpp>;\$<1:empty_2.cpp>
--- /dev/null
+cmake_policy(SET CMP0076 NEW)
+
+add_library(genexlib)
+add_subdirectory(RelativePathInSubdirGenEx)
+
+get_property(genexlib_sources TARGET genexlib PROPERTY SOURCES)
+message(STATUS "genexlib: ${genexlib_sources}")
+
+add_executable(genexmain main.cpp)
+target_link_libraries(genexmain genexlib)
--- /dev/null
+
+target_sources(genexlib PUBLIC $<1:${CMAKE_CURRENT_LIST_DIR}/subdir_empty_1.cpp>
+ $<1:${CMAKE_CURRENT_LIST_DIR}/../empty_1.cpp>
+ PRIVATE $<1:empty_2.cpp>)
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
--- /dev/null
+-- privatelib: .*Tests/RunCMake/TargetSources/RelativePathInSubdirInclude/subdir_empty_1.cpp;empty_1.cpp
--- /dev/null
+cmake_policy(SET CMP0076 NEW)
+
+add_library(privatelib)
+
+include("RelativePathInSubdirInclude/CMakeLists.txt")
+
+get_property(privatelib_sources TARGET privatelib PROPERTY SOURCES)
+message(STATUS "privatelib: ${privatelib_sources}")
--- /dev/null
+
+target_sources(privatelib PRIVATE "${CMAKE_CURRENT_LIST_DIR}/subdir_empty_1.cpp"
+ empty_1.cpp)
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
--- /dev/null
+-- iface: .*Tests/RunCMake/TargetSources/RelativePathInSubdirInterface/subdir_empty_1.cpp;.*Tests/RunCMake/TargetSources/RelativePathInSubdirInterface/subdir_empty_2.cpp;.*Tests/RunCMake/TargetSources/RelativePathInSubdirInterface/../empty_1.cpp;.*Tests/RunCMake/TargetSources/RelativePathInSubdirInterface/../empty_2.cpp
--- /dev/null
+cmake_policy(SET CMP0076 NEW)
+
+add_library(iface INTERFACE)
+
+add_subdirectory(RelativePathInSubdirInterface)
+
+get_property(iface_sources TARGET iface PROPERTY INTERFACE_SOURCES)
+message(STATUS "iface: ${iface_sources}")
+
+add_executable(main main.cpp)
+target_link_libraries(main iface)
--- /dev/null
+
+target_sources(iface INTERFACE subdir_empty_1.cpp
+ "${CMAKE_CURRENT_LIST_DIR}/subdir_empty_2.cpp"
+ ../empty_1.cpp
+ "${CMAKE_CURRENT_LIST_DIR}/../empty_2.cpp")
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
--- /dev/null
+-- privatelib: .*Tests/RunCMake/TargetSources/RelativePathInSubdirPrivate/subdir_empty_1.cpp;.*Tests/RunCMake/TargetSources/RelativePathInSubdirPrivate/subdir_empty_2.cpp;.*Tests/RunCMake/TargetSources/RelativePathInSubdirPrivate/../empty_1.cpp;.*Tests/RunCMake/TargetSources/RelativePathInSubdirPrivate/../empty_2.cpp
--- /dev/null
+cmake_policy(SET CMP0076 NEW)
+
+add_library(privatelib)
+
+add_subdirectory(RelativePathInSubdirPrivate)
+
+get_property(privatelib_sources TARGET privatelib PROPERTY SOURCES)
+message(STATUS "privatelib: ${privatelib_sources}")
--- /dev/null
+
+target_sources(privatelib PRIVATE subdir_empty_1.cpp
+ "${CMAKE_CURRENT_LIST_DIR}/subdir_empty_2.cpp"
+ ../empty_1.cpp
+ "${CMAKE_CURRENT_LIST_DIR}/../empty_2.cpp")
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
--- /dev/null
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
run_cmake(OriginDebug)
run_cmake(CMP0026-LOCATION)
+run_cmake(CMP0076-OLD)
+run_cmake(CMP0076-WARN)
run_cmake(RelativePathInInterface)
+run_cmake(RelativePathInSubdirGenEx)
+run_cmake(RelativePathInSubdirInterface)
+run_cmake(RelativePathInSubdirPrivate)
+run_cmake(RelativePathInSubdirInclude)
run_cmake(ExportBuild)
--- /dev/null
+-- PREFIX='_'
+-- TARGET NAME='example'
--- /dev/null
+cmake_policy(SET CMP0078 NEW)
+include(CMP0078-common.cmake)
--- /dev/null
+-- PREFIX=''
+-- TARGET NAME='_example'
--- /dev/null
+cmake_policy(SET CMP0078 OLD)
+include(CMP0078-common.cmake)
--- /dev/null
+CMake Warning \(dev\) at .*/Modules/UseSWIG.cmake:[0-9]+ \(message\):
+ Policy CMP0078 is not set. Run "cmake --help-policy CMP0078" for policy
+ details. Use the cmake_policy command to set the policy and suppress this
+ warning.
+Call Stack \(most recent call first\):
+ CMP0078-common.cmake:6 \(swig_add_library\)
+ CMP0078-WARN.cmake:1 \(include\)
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
--- /dev/null
+-- PREFIX=''
+-- TARGET NAME='_example'
--- /dev/null
+include(CMP0078-common.cmake)
--- /dev/null
+
+set(SWIG_EXECUTABLE "swig")
+set(SWIG_DIR "/swig")
+include(UseSWIG)
+
+swig_add_library(example LANGUAGE python TYPE MODULE SOURCES example.i)
+
+get_property(prefix TARGET ${SWIG_MODULE_example_REAL_NAME} PROPERTY PREFIX)
+message(STATUS "PREFIX='${prefix}'")
+message(STATUS "TARGET NAME='${SWIG_MODULE_example_REAL_NAME}'")
--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} C)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+include(RunCMake)
+
+run_cmake(CMP0078-WARN)
+run_cmake(CMP0078-OLD)
+run_cmake(CMP0078-NEW)
--- /dev/null
+/* File : example.i */
+%module example
run_cmake(VsCustomProps)
run_cmake(VsDebuggerWorkingDir)
run_cmake(VsDebuggerCommand)
+run_cmake(VsDebuggerCommandArguments)
+run_cmake(VsDebuggerEnvironment)
run_cmake(VsCSharpCustomTags)
run_cmake(VsCSharpReferenceProps)
run_cmake(VsCSharpWithoutSources)
run_cmake(VsSdkDirectories)
+run_cmake(VsGlobals)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "^ *<LocalDebuggerCommand[^>]*>([^<>]+)</LocalDebuggerCommand>$")
- if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command")
+ if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command foo")
message(STATUS "foo.vcxproj has debugger command set")
set(debuggerCommandSet TRUE)
endif()
add_library(foo foo.cpp)
set_target_properties(foo PROPERTIES
- VS_DEBUGGER_COMMAND "my-debugger-command")
+ VS_DEBUGGER_COMMAND "my-debugger-command $<TARGET_PROPERTY:foo,NAME>")
--- /dev/null
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+set(debuggerCommandArgumentsSet FALSE)
+
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<LocalDebuggerCommandArguments[^>]*>([^<>]+)</LocalDebuggerCommandArguments>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command-arguments foo")
+ message(STATUS "foo.vcxproj has debugger command arguments set")
+ set(debuggerCommandArgumentsSet TRUE)
+ endif()
+ endif()
+endforeach()
+
+if(NOT debuggerCommandArgumentsSet)
+ set(RunCMake_TEST_FAILED "LocalDebuggerCommandArguments not found or not set correctly.")
+ return()
+endif()
--- /dev/null
+enable_language(CXX)
+add_library(foo foo.cpp)
+
+set_target_properties(foo PROPERTIES
+ VS_DEBUGGER_COMMAND_ARGUMENTS "my-debugger-command-arguments $<TARGET_PROPERTY:foo,NAME>")
--- /dev/null
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+set(debuggerEnvironmentSet FALSE)
+
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<LocalDebuggerEnvironment[^>]*>([^<>]+)</LocalDebuggerEnvironment>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-environment foo")
+ message(STATUS "foo.vcxproj has debugger environment set")
+ set(debuggerEnvironmentSet TRUE)
+ endif()
+ endif()
+endforeach()
+
+if(NOT debuggerEnvironmentSet)
+ set(RunCMake_TEST_FAILED "LocalDebuggerEnvironment not found or not set correctly.")
+ return()
+endif()
--- /dev/null
+enable_language(CXX)
+add_library(foo foo.cpp)
+
+set_target_properties(foo PROPERTIES
+ VS_DEBUGGER_ENVIRONMENT "my-debugger-environment $<TARGET_PROPERTY:foo,NAME>")
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "^ *<LocalDebuggerWorkingDirectory[^>]*>([^<>]+)</LocalDebuggerWorkingDirectory>$")
- if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-directory")
+ if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-directory foo")
message(STATUS "foo.vcxproj has debugger working dir set")
set(debuggerWorkDirSet TRUE)
endif()
add_library(foo foo.cpp)
set_target_properties(foo PROPERTIES
- VS_DEBUGGER_WORKING_DIRECTORY "my-debugger-directory")
+ VS_DEBUGGER_WORKING_DIRECTORY "my-debugger-directory $<TARGET_PROPERTY:foo,NAME>")
--- /dev/null
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+set(InsideGlobals FALSE)
+set(DefaultLanguageSet FALSE)
+set(MinimumVisualStudioVersionSet FALSE)
+
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<PropertyGroup Label=\"Globals\"> *$")
+ set(InsideGlobals TRUE)
+ elseif(line MATCHES "^ *<DefaultLanguage>([a-zA-Z\\-]+)</DefaultLanguage> *$")
+ if("${CMAKE_MATCH_1}" STREQUAL "en-US")
+ if(InsideGlobals)
+ message(STATUS "foo.vcxproj has correct DefaultLanguage global property")
+ set(DefaultLanguageSet TRUE)
+ else()
+ message(STATUS "DefaultLanguage is set but not within \"Globals\" property group")
+ endif()
+ endif()
+ elseif(line MATCHES "^ *<MinimumVisualStudioVersion>([0-9\\.]+)</MinimumVisualStudioVersion> *$")
+ if("${CMAKE_MATCH_1}" STREQUAL "14.0")
+ if(InsideGlobals)
+ message(STATUS "foo.vcxproj has correct MinimumVisualStudioVersion global property")
+ set(MinimumVisualStudioVersionSet TRUE)
+ else()
+ message(STATUS "MinimumVisualStudioVersion is set but not within \"Globals\" property group")
+ endif()
+ endif()
+ endif()
+endforeach()
+
+if(NOT DefaultLanguageSet)
+ set(RunCMake_TEST_FAILED "DefaultLanguageSet not found or not set correctly.")
+ return()
+endif()
+
+if(NOT MinimumVisualStudioVersionSet)
+ set(RunCMake_TEST_FAILED "MinimumVisualStudioVersionSet not found or not set correctly.")
+ return()
+endif()
--- /dev/null
+enable_language(CXX)
+
+set(CMAKE_VS_GLOBALS
+ "DefaultLanguage=en-US"
+ "MinimumVisualStudioVersion=14.0"
+)
+
+add_library(foo foo.cpp)
--- /dev/null
+^CMake Deprecation Warning at CMP0063-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0063 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\)$
if(NOT XCODE_VERSION VERSION_LESS 7)
XcodeSchemaGeneration()
+ run_cmake(XcodeSchemaProperty)
endif()
if(XCODE_VERSION VERSION_GREATER_EQUAL 8)
--- /dev/null
+function(check_property property matcher)
+ set(schema "${RunCMake_TEST_BINARY_DIR}/XcodeSchemaProperty.xcodeproj/xcshareddata/xcschemes/${property}.xcscheme")
+ file(STRINGS ${schema} actual-${property}
+ REGEX "${matcher}" LIMIT_COUNT 1)
+ if(NOT actual-${property})
+ message(SEND_ERROR "Xcode schema property ${property}: Could not find ${matcher} in schema ${schema}")
+ endif()
+endfunction()
+
+check_property("ADDRESS_SANITIZER" "enableAddressSanitizer")
+check_property("ADDRESS_SANITIZER_USE_AFTER_RETURN" "enableASanStackUseAfterReturn")
+check_property("THREAD_SANITIZER" "enableThreadSanitizer")
+check_property("THREAD_SANITIZER_STOP" "stopOnEveryThreadSanitizerIssue")
+check_property("UNDEFINED_BEHAVIOUR_SANITIZER" "enableUBSanitizer")
+check_property("UNDEFINED_BEHAVIOUR_SANITIZER_STOP" "stopOnEveryUBSanitizerIssue")
+check_property("DISABLE_MAIN_THREAD_CHECKER" "disableMainThreadChecker")
+check_property("MAIN_THREAD_CHECKER_STOP" "stopOnEveryMainThreadCheckerIssue")
+
+check_property("MALLOC_SCRIBBLE" "MallocScribble")
+check_property("MALLOC_GUARD_EDGES" "MallocGuardEdges")
+check_property("GUARD_MALLOC" "DYLD_INSERT_LIBRARIES")
+check_property("ZOMBIE_OBJECTS" "NSZombieEnabled")
+check_property("MALLOC_STACK" "MallocStackLogging")
+check_property("DYNAMIC_LINKER_API_USAGE" "DYLD_PRINT_APIS")
+check_property("DYNAMIC_LIBRARY_LOADS" "DYLD_PRINT_LIBRARIES")
+
+check_property("EXECUTABLE" "myExecutable")
+check_property("ARGUMENTS" [=["--foo"]=])
+check_property("ARGUMENTS" [=["--bar=baz"]=])
+check_property("ENVIRONMENT" [=[key="FOO"]=])
+check_property("ENVIRONMENT" [=[value="foo"]=])
+check_property("ENVIRONMENT" [=[key="BAR"]=])
+check_property("ENVIRONMENT" [=[value="bar"]=])
--- /dev/null
+cmake_minimum_required(VERSION 3.7)
+
+set(CMAKE_XCODE_GENERATE_SCHEME ON)
+
+project(XcodeSchemaProperty CXX)
+
+function(create_scheme_for_variable variable)
+ set(CMAKE_XCODE_SCHEME_${variable} ON)
+ add_executable(${variable} main.cpp)
+endfunction()
+
+create_scheme_for_variable(ADDRESS_SANITIZER)
+create_scheme_for_variable(ADDRESS_SANITIZER_USE_AFTER_RETURN)
+create_scheme_for_variable(THREAD_SANITIZER)
+create_scheme_for_variable(THREAD_SANITIZER_STOP)
+create_scheme_for_variable(UNDEFINED_BEHAVIOUR_SANITIZER)
+create_scheme_for_variable(UNDEFINED_BEHAVIOUR_SANITIZER_STOP)
+create_scheme_for_variable(DISABLE_MAIN_THREAD_CHECKER)
+create_scheme_for_variable(MAIN_THREAD_CHECKER_STOP)
+
+create_scheme_for_variable(MALLOC_SCRIBBLE)
+create_scheme_for_variable(MALLOC_GUARD_EDGES)
+create_scheme_for_variable(GUARD_MALLOC)
+create_scheme_for_variable(ZOMBIE_OBJECTS)
+create_scheme_for_variable(MALLOC_STACK)
+create_scheme_for_variable(DYNAMIC_LINKER_API_USAGE)
+create_scheme_for_variable(DYNAMIC_LIBRARY_LOADS)
+
+function(create_scheme_for_property property value)
+ set(XCODE_SCHEME_${property} ON)
+ add_executable(${property} main.cpp)
+ set_target_properties(${property} PROPERTIES XCODE_SCHEME_${property} "${value}")
+endfunction()
+
+create_scheme_for_property(EXECUTABLE myExecutable)
+create_scheme_for_property(ARGUMENTS "--foo;--bar=baz")
+create_scheme_for_property(ENVIRONMENT "FOO=foo;BAR=bar")
--- /dev/null
+cmake_minimum_required(VERSION 3.11)
+
+project(${RunCMake_TEST} LANGUAGES NONE)
+
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+
+include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
--- /dev/null
+
+set (LINKER_OPTION "LINKER:SHELL:-foo bar")
+
+include ("LINKER_expansion-list.cmake")
--- /dev/null
+
+include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
--- /dev/null
+
+enable_language(C)
+
+add_executable(dump dump.c)
+
+add_link_options("${LINKER_OPTION}")
+
+# ensure no temp file will be used
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}")
+
+add_library(example SHARED LinkOptionsLib.c)
+# use LAUNCH facility to dump linker command
+set_property(TARGET example PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"")
+
+add_dependencies (example dump)
+
+# generate reference for LINKER flag
+if (CMAKE_C_LINKER_WRAPPER_FLAG)
+ set(linker_flag ${CMAKE_C_LINKER_WRAPPER_FLAG})
+ list(GET linker_flag -1 linker_space)
+ if (linker_space STREQUAL " ")
+ list(REMOVE_AT linker_flag -1)
+ else()
+ set(linker_space)
+ endif()
+ list (JOIN linker_flag " " linker_flag)
+ if (CMAKE_C_LINKER_WRAPPER_FLAG_SEP)
+ string (APPEND linker_flag "${linker_space}" "-foo${CMAKE_C_LINKER_WRAPPER_FLAG_SEP}bar")
+ else()
+ set (linker_flag "${linker_flag}${linker_space}-foo ${linker_flag}${linker_space}bar")
+ endif()
+else()
+ set(linker_flag "-foo bar")
+endif()
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER.txt" "${linker_flag}")
--- /dev/null
+
+if (actual_stdout MATCHES "(LINKER|SHELL):")
+ set (RunCMake_TEST_FAILED "LINKER: prefix was not expanded.")
+ return()
+endif()
+
+if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/LINKER.txt")
+ set (RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/LINKER.txt: Reference file not found.")
+ return()
+endif()
+file(READ "${RunCMake_TEST_BINARY_DIR}/LINKER.txt" linker_flag)
+
+if (NOT actual_stdout MATCHES "${linker_flag}")
+ set (RunCMake_TEST_FAILED "LINKER: was not expanded correctly.")
+endif()
--- /dev/null
+
+set (LINKER_OPTION "LINKER:-foo,bar")
+
+include ("LINKER_expansion-list.cmake")
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_EXECUTABLE_RELEASE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_EXECUTABLE_RELEASE'.")
+endif()
+if (actual_stdout MATCHES "BADFLAG_(SHARED|MODULE)_RELEASE")
+ set (RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(SHARED|MODULE)_RELEASE'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_MODULE_RELEASE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_MODULE_RELEASE'.")
+endif()
+if (actual_stdout MATCHES "BADFLAG_(SHARED|EXECUTABLE)_RELEASE")
+ set (RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(SHARED|EXECUTABLE)_RELEASE'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_SHARED_RELEASE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_SHARED_RELEASE'.")
+endif()
+if (actual_stdout MATCHES "BADFLAG_(MODULE|EXECUTABLE)_RELEASE")
+ set (RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(MODULE|EXECUTABLE)_RELEASE'.")
+endif()
--- /dev/null
+
+enable_language(C)
+
+set(obj "${CMAKE_C_OUTPUT_EXTENSION}")
+if(BORLAND)
+ set(pre -)
+endif()
+
+add_link_options($<$<AND:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>,$<CONFIG:Release>>:${pre}BADFLAG_SHARED_RELEASE${obj}>)
+add_link_options($<$<AND:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>,$<CONFIG:Release>>:${pre}BADFLAG_MODULE_RELEASE${obj}>)
+add_link_options($<$<AND:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>,$<CONFIG:Release>>:${pre}BADFLAG_EXECUTABLE_RELEASE${obj}>)
+
+add_library(LinkOptions_shared SHARED LinkOptionsLib.c)
+
+add_library(LinkOptions_mod MODULE LinkOptionsLib.c)
+
+add_executable(LinkOptions_exe LinkOptionsExe.c)
--- /dev/null
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ int flags_lib(void)
+{
+ return 0;
+}
--- /dev/null
+
+include(RunCMake)
+
+macro(run_cmake_target test subtest target)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
+ # Intel compiler does not reject bad flags or objects!
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+
+ run_cmake(LINK_OPTIONS)
+
+ run_cmake_target(LINK_OPTIONS shared LinkOptions_shared --config Release)
+ run_cmake_target(LINK_OPTIONS mod LinkOptions_mod --config Release)
+ run_cmake_target(LINK_OPTIONS exe LinkOptions_exe --config Release)
+
+ unset(RunCMake_TEST_OPTIONS)
+ unset(RunCMake_TEST_OUTPUT_MERGE)
+endif()
+
+run_cmake(bad_SHELL_usage)
+
+if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)")
+ run_cmake(LINKER_expansion)
+ run_cmake_target(LINKER_expansion build all)
+
+ run_cmake(LINKER_SHELL_expansion)
+ run_cmake_target(LINKER_SHELL_expansion build all)
+endif()
--- /dev/null
+CMake Error at bad_SHELL_usage.cmake:6 \(add_library\):
+ 'SHELL:' prefix is not supported as part of 'LINKER:' arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:5 \(include\)
--- /dev/null
+
+enable_language(C)
+
+add_link_options("LINKER:-foo,SHELL:-bar")
+
+add_library(example SHARED LinkOptionsLib.c)
--- /dev/null
+
+#include "stdio.h"
+
+int main(int argc, char* argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++)
+ printf("%s ", argv[i]);
+ printf("\n");
+
+ return 0;
+}
-^[^
+^CMake Deprecation Warning at CMP0061-OLD-make.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0061 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\)
++
+[^
]+ --build \. --config "Release" -- -i
[^
]+ --build \. --config "Release" --target "MyTarget" -- -i
-^[^
+^CMake Deprecation Warning at CMP0061-OLD-other.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0061 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\)
++
+[^
]+ --build \. --config "Release"
[^
]+ --build \. --config "Release" --target "MyTarget"
CMake Error at DirInput.cmake:[0-9]+ \(configure_file\):
configure_file input location
- .*/Tests/RunCMake/configure_file/.
+ .*/Tests/RunCMake/configure_file
is a directory but a file was expected.
Call Stack \(most recent call first\):
--- /dev/null
+ *Error message was: ([Cc]ould *n.t resolve host:? '?-no-site-'?.*|The requested URL returned error:.*)
--- /dev/null
+Upload file: .* to http:\/\/-no-site-\?FileName=test-site___test-build-name___.*-Experimental___XML___Configure.xml&build=test-build-name&site=test-site&stamp=.*-Experimental&subproject=mysubproj&MD5=.* Size: .*
--- /dev/null
+ *Error message was: ([Cc]ould *n.t resolve host:? '?-no-site-'?.*|The requested URL returned error:.*)
--- /dev/null
+Upload file: .* to http:\/\/-no-site-\?FileName=test-site___test-build-name___.*-Experimental___XML___RunCMakeTest.cmake&MD5=.* Size: .*
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_debug(CDashSubmitVerbose)
+run_ctest_submit_debug(FILESNoBuildId FILES ${CMAKE_CURRENT_LIST_FILE})
run_ctest_submit_debug(CDashSubmitHeaders HTTPHEADER "Authorization: Bearer asdf")
run_ctest_submit_debug(CDashUploadHeaders CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo HTTPHEADER "Authorization: Bearer asdf")
set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
+set_property(GLOBAL PROPERTY SubProject "mysubproj")
ctest_start(Experimental)
ctest_configure()
--- /dev/null
+-- PROG_ABS='PROG_ABS-NOTFOUND'
+-- PROG_ABS_NPD='PROG_ABS_NPD-NOTFOUND'
+-- PROG_CWD='PROG_CWD-NOTFOUND'
+-- PROG_CWD_NPD='PROG_CWD_NPD-NOTFOUND'
+-- PROG_CWD_DOT='[^']*/Tests/RunCMake/find_program/testCWD'
+-- PROG_CWD_DOT_NPD='[^']*/Tests/RunCMake/find_program/testCWD'
--- /dev/null
+# testNoSuchFile should only be found if the file absolute path is
+# incorrectly prepended with the search path.
+
+function(strip_windows_path_prefix p outvar)
+ if(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
+ string(REGEX REPLACE "^.:" "" p "${p}")
+ endif()
+ set(${outvar} "${p}" PARENT_SCOPE)
+endfunction()
+
+strip_windows_path_prefix("${CMAKE_CURRENT_SOURCE_DIR}" srcdir)
+
+file(MAKE_DIRECTORY "tmp${srcdir}")
+configure_file(testCWD "tmp${srcdir}/testNoSuchFile" COPYONLY)
+
+find_program(PROG_ABS
+ NAMES "${srcdir}/testNoSuchFile"
+ PATHS "${CMAKE_CURRENT_BINARY_DIR}/tmp"
+ NO_DEFAULT_PATH
+ )
+message(STATUS "PROG_ABS='${PROG_ABS}'")
+
+find_program(PROG_ABS_NPD
+ NAMES "${srcdir}/testNoSuchFile"
+ PATHS "${CMAKE_CURRENT_BINARY_DIR}/tmp"
+ NAMES_PER_DIR
+ NO_DEFAULT_PATH
+ )
+message(STATUS "PROG_ABS_NPD='${PROG_ABS_NPD}'")
+
+# ./testCWD should not be found without '.' being in the path list.
+
+configure_file(testCWD testCWD COPYONLY)
+
+find_program(PROG_CWD
+ NAMES testCWD
+ NO_DEFAULT_PATH
+ )
+message(STATUS "PROG_CWD='${PROG_CWD}'")
+
+find_program(PROG_CWD_NPD
+ NAMES testCWD
+ NAMES_PER_DIR
+ NO_DEFAULT_PATH
+ )
+message(STATUS "PROG_CWD_NPD='${PROG_CWD_NPD}'")
+
+# Confirm that adding '.' to path does locate ./testCWD.
+
+find_program(PROG_CWD_DOT
+ NAMES testCWD
+ PATHS .
+ NO_DEFAULT_PATH
+ )
+message(STATUS "PROG_CWD_DOT='${PROG_CWD_DOT}'")
+
+find_program(PROG_CWD_DOT_NPD
+ NAMES testCWD
+ PATHS .
+ NAMES_PER_DIR
+ NO_DEFAULT_PATH
+ )
+message(STATUS "PROG_CWD_DOT_NPD='${PROG_CWD_DOT_NPD}'")
run_cmake(EnvAndHints)
run_cmake(DirsPerName)
run_cmake(NamesPerDir)
+run_cmake(RelAndAbsPath)
if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN)$")
run_cmake(WindowsCom)
--- /dev/null
+^CMake Deprecation Warning at CMP0062-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0062 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\)$
--- /dev/null
+check_installed([[^dir;dir/empty.txt$]])
--- /dev/null
+install(DIRECTORY dir/ noexist/ DESTINATION dir OPTIONAL)
--- /dev/null
+check_installed([[^dir1;dir1/empty\.c;dir1/empty\.h;dir2;dir2/pattern;dir2/pattern/empty\.txt;dir3;dir3/empty\.c;dir3/empty\.h;dir3/empty\.txt;dir4;dir4/empty\.c;dir4/empty\.h;dir4/empty\.txt;empty$]])
--- /dev/null
+install(
+ DIRECTORY pattern/
+ DESTINATION dir1
+ FILES_MATCHING
+ PATTERN "*.h"
+ REGEX "\\.c$"
+ )
+
+# FIXME: If/when CMake gains a good way to read file permissions, we should
+# check that these permissions were set correctly.
+install(
+ DIRECTORY pattern
+ DESTINATION dir2
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE
+ DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ PATTERN "*.h" EXCLUDE
+ REGEX "\\.c$" EXCLUDE
+ )
+
+install(
+ DIRECTORY pattern/
+ DESTINATION dir3
+ PATTERN "*.h"
+ PERMISSIONS OWNER_READ OWNER_WRITE
+ )
+
+install(
+ DIRECTORY pattern/
+ DESTINATION dir4
+ USE_SOURCE_PERMISSIONS
+ )
+
+install(
+ DIRECTORY
+ DESTINATION empty
+ )
--- /dev/null
+check_installed([[^bin;bin/myexe(\.exe)?;scripts1;scripts1/script;scripts1/script\.bat;scripts2;scripts2/script;scripts2/script\.bat;scripts3;scripts3/script;scripts3/script\.bat;src;src/empty\.c;src/obj1\.c;src/obj\2.c$]])
--- /dev/null
+enable_language(C)
+
+add_executable(myexe main.c)
+
+install_files(/src FILES empty.c)
+install_files(/src .c obj1)
+install_files(/src "^obj2.c$")
+
+install_targets(/bin myexe)
+
+install_programs(/scripts1 FILES script script.bat)
+install_programs(/scripts2 script script.bat)
+install_programs(/scripts3 "^script(\.bat)?$")
--- /dev/null
+check_installed([[^src;src/main.c$]])
--- /dev/null
+install(FILES main.c noexist.c DESTINATION src OPTIONAL)
--- /dev/null
+check_installed([[^src;src/empty.c]])
--- /dev/null
+install(
+ FILES empty.c
+ DESTINATION src
+ PERMISSIONS OWNER_READ OWNER_WRITE
+ )
--- /dev/null
+enable_language(C)
+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)
+
+# FIXME: This test emits warnings because InstallRequiredSystemLibraries
+# doesn't currently work properly. The warnings have been suppressed in
+# InstallRequiredSystemLibraries-stderr.txt. This needs to be fixed.
--- /dev/null
+check_installed([[^bin;bin/myexe(\.exe)?;postinstall;preinstall]])
--- /dev/null
+enable_language(C)
+
+add_executable(myexe main.c)
+set_property(TARGET myexe PROPERTY PRE_INSTALL_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/preinstall.cmake")
+set_property(TARGET myexe PROPERTY POST_INSTALL_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/postinstall.cmake")
+
+install(TARGETS myexe DESTINATION bin)
run_install_test(FILES-TARGET_OBJECTS)
endif()
+run_install_test(TARGETS-InstallFromSubDir)
+run_install_test(TARGETS-OPTIONAL)
+run_install_test(FILES-OPTIONAL)
+run_install_test(DIRECTORY-OPTIONAL)
+
+set(RunCMake_TEST_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=Debug")
+run_install_test(TARGETS-OUTPUT_NAME)
+unset(RunCMake_TEST_OPTIONS)
+
+run_install_test(Deprecated)
+run_install_test(PRE_POST_INSTALL_SCRIPT)
+run_install_test(SCRIPT)
+run_install_test(TARGETS-CONFIGURATIONS)
+run_install_test(DIRECTORY-PATTERN)
+run_install_test(TARGETS-Parts)
+run_install_test(FILES-PERMISSIONS)
+run_install_test(TARGETS-RPATH)
+run_install_test(InstallRequiredSystemLibraries)
+
set(run_install_test_components 1)
run_install_test(FILES-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-EXCLUDE_FROM_ALL)
run_install_test(TARGETS-NAMELINK_COMPONENT)
+run_install_test(SCRIPT-COMPONENT)
--- /dev/null
+check_installed([[^empty1.txt;empty2.txt$]])
--- /dev/null
+check_installed([[^empty1.txt;empty2.txt$]])
--- /dev/null
+check_installed([[^$]])
--- /dev/null
+install(
+ SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/install_script.cmake"
+ CODE "write_empty_file(empty2.txt)"
+ COMPONENT dev
+ )
--- /dev/null
+check_installed([[^empty1.txt;empty2.txt$]])
--- /dev/null
+install(
+ SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/install_script.cmake"
+ CODE "write_empty_file(empty2.txt)"
+ )
--- /dev/null
+check_installed([[^src;src/main-d.c$]])
--- /dev/null
+install(FILES main.c DESTINATION src CONFIGURATIONS Debug RENAME main-d.c)
+install(FILES main.c DESTINATION src CONFIGURATIONS Release RENAME main-r.c)
--- /dev/null
+check_installed([[^bin;bin/myexe(\.exe)?;bin/subexe(\.exe)?$]])
--- /dev/null
+enable_language(C)
+add_executable(myexe main.c)
+add_subdirectory(TARGETS-InstallFromSubDir)
+install(TARGETS myexe subexe DESTINATION bin)
--- /dev/null
+add_executable(subexe ../main.c)
--- /dev/null
+check_installed([[^bin;bin/myexe(\.exe)?$]])
--- /dev/null
+^WARNING: Target "notall" has EXCLUDE_FROM_ALL set and will not be built by default but an install rule has been provided for it\. CMake does not define behavior for this case\.$
--- /dev/null
+enable_language(C)
+add_executable(myexe main.c)
+add_executable(notall EXCLUDE_FROM_ALL main.c)
+install(TARGETS myexe notall DESTINATION bin OPTIONAL)
--- /dev/null
+if(WIN32)
+ set(test123 [[bin/test1out\.exe;bin/test2deb\.exe;bin/test3exc\.exe]])
+ set(libtest45 [[bin/libtest4\.dll;bin/libtest4\.dll\.a;bin/libtest5ar\.a]])
+ set(test45 [[bin/test4\.dll;bin/test4\.lib;bin/test5ar\.lib]])
+
+ check_installed("^bin;(${libtest45};${test123})|(${test123};${test45})\$")
+elseif(CYGWIN)
+ check_installed([[^bin;bin/cygtest4\.dll;bin/libtest4\.dll\.a;bin/libtest5ar\.a;bin/test1out\.exe;bin/test2deb\.exe;bin/test3exc\.exe$]])
+elseif(APPLE)
+ check_installed([[^bin;bin/libtest4lib\.dylib;bin/libtest5ar\.a;bin/test1out;bin/test2deb;bin/test3exc$]])
+else()
+ check_installed([[^bin;bin/libtest4lib\.so;bin/libtest5ar\.a;bin/test1out;bin/test2deb;bin/test3exc$]])
+endif()
--- /dev/null
+enable_language(C)
+
+add_executable(test1 main.c)
+set_property(TARGET test1 PROPERTY OUTPUT_NAME test1out)
+set_property(TARGET test1 PROPERTY RELEASE_OUTPUT_NAME test1rel)
+
+add_executable(test2 main.c)
+set_property(TARGET test2 PROPERTY OUTPUT_NAME test2out)
+set_property(TARGET test2 PROPERTY DEBUG_OUTPUT_NAME test2deb)
+
+add_executable(test3 main.c)
+set_property(TARGET test3 PROPERTY RUNTIME_OUTPUT_NAME test3exc)
+
+add_library(test4 SHARED obj1.c)
+set_property(TARGET test4 PROPERTY LIBRARY_OUTPUT_NAME test4lib)
+
+add_library(test5 STATIC obj1.c)
+set_property(TARGET test5 PROPERTY ARCHIVE_OUTPUT_NAME test5ar)
+
+install(TARGETS
+ test1
+ test2
+ test3
+ test4
+ test5
+ DESTINATION bin
+ )
--- /dev/null
+check_installed([[^include;include/obj1\.h;lib;lib/(mylib\.lib|(lib|cyg)mylib\.a)$]])
--- /dev/null
+enable_language(C)
+add_library(mylib STATIC obj1.c)
+set_property(TARGET mylib PROPERTY PUBLIC_HEADER obj1.h)
+install(TARGETS mylib
+ ARCHIVE DESTINATION lib
+ PUBLIC_HEADER DESTINATION include
+ )
--- /dev/null
+execute_process(
+ COMMAND "${CMAKE_INSTALL_PREFIX}/bin/myexe"
+ RESULT_VARIABLE MYEXE_RESULT
+ OUTPUT_VARIABLE MYEXE_OUTPUT
+ ERROR_VARIABLE MYEXE_ERROR
+ )
+
+if(NOT MYEXE_RESULT EQUAL "0")
+ set(RunCMake_TEST_FAILED "myexe returned [${MYEXE_RESULT}], was expecting [0]")
+elseif(NOT MYEXE_OUTPUT STREQUAL "")
+ set(RunCMake_TEST_FAILED "myexe printed nonempty output:\n${MYEXE_OUTPUT}")
+elseif(NOT MYEXE_ERROR STREQUAL "")
+ set(RunCMake_TEST_FAILED "myexe printed nonempty error:\n${MYEXE_ERROR}")
+endif()
--- /dev/null
+cmake_minimum_required(VERSION 3.9)
+
+enable_language(C)
+
+set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
+add_library(mylib SHARED obj1.c)
+add_executable(myexe testobj1.c)
+target_link_libraries(myexe mylib)
+set_property(TARGET myexe PROPERTY INSTALL_RPATH "${CMAKE_CURRENT_BINARY_DIR}/root-all/bin")
+set_target_properties(mylib PROPERTIES VERSION 1.0 SOVERSION 1)
+
+install(TARGETS mylib myexe
+ DESTINATION bin
+ )
--- /dev/null
+function(write_empty_file FILENAME)
+ file(WRITE "${CMAKE_INSTALL_PREFIX}/${FILENAME}" "")
+endfunction()
+
+write_empty_file(empty1.txt)
-int obj1(void)
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int obj1(void)
{
return 0;
}
--- /dev/null
+#ifndef OBJ1_H
+#define OBJ1_H
+
+int obj1(void);
+
+#endif /* OBJ1_H */
--- /dev/null
+file(WRITE "${CMAKE_INSTALL_PREFIX}/postinstall" "postinstall")
--- /dev/null
+file(WRITE "${CMAKE_INSTALL_PREFIX}/preinstall" "preinstall")
--- /dev/null
+#ifdef _WIN32
+__declspec(dllimport)
+#endif
+ int obj1(void);
+
+int main(void)
+{
+ return obj1();
+}
^CMake Error at INSERT-InvalidIndex.cmake:2 \(list\):
- list index: 3 out of range \(-3, 2\)
+ list index: 4 out of range \(-3, 3\)
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
set(mylist alpha bravo charlie)
-list(INSERT mylist 3 delta)
+list(INSERT mylist 4 delta)
run_cmake(LENGTH-TooManyArguments)
run_cmake(REMOVE_DUPLICATES-TooManyArguments)
run_cmake(REVERSE-TooManyArguments)
-run_cmake(SORT-TooManyArguments)
run_cmake(SUBLIST-TooManyArguments)
run_cmake(FILTER-NotList)
run_cmake(TRANSFORM-APPEND)
run_cmake(TRANSFORM-PREPEND)
run_cmake(TRANSFORM-REPLACE)
+
+# argument tests
+run_cmake(SORT-WrongOption)
+run_cmake(SORT-BadCaseOption)
+run_cmake(SORT-BadCompareOption)
+run_cmake(SORT-BadOrderOption)
+run_cmake(SORT-DuplicateOrderOption)
+run_cmake(SORT-DuplicateCompareOption)
+run_cmake(SORT-DuplicateCaseOption)
+run_cmake(SORT-NoCaseOption)
+
+# Successful tests
+run_cmake(SORT)
--- /dev/null
+^CMake Error at SORT-BadCaseOption.cmake:1 \(list\):
+ list sub-command SORT value "BAD_CASE_OPTION" for option "CASE" is invalid.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(SORT mylist CASE BAD_CASE_OPTION)
--- /dev/null
+^CMake Error at SORT-BadCompareOption.cmake:1 \(list\):
+ list sub-command SORT value "BAD_COMPARE_OPTION" for option "COMPARE" is
+ invalid.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(SORT mylist COMPARE BAD_COMPARE_OPTION)
--- /dev/null
+^CMake Error at SORT-BadOrderOption.cmake:1 \(list\):
+ list sub-command SORT value "BAD_ODER_OPTION" for option "ORDER" is
+ invalid.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(SORT mylist ORDER BAD_ODER_OPTION)
--- /dev/null
+^CMake Error at SORT-DuplicateCaseOption.cmake:2 \(list\):
+ list sub-command SORT option "CASE" has been specified multiple times.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set (mylist a b c)
+list(SORT mylist CASE INSENSITIVE CASE INSENSITIVE )
--- /dev/null
+^CMake Error at SORT-DuplicateCompareOption.cmake:2 \(list\):
+ list sub-command SORT option "COMPARE" has been specified multiple times.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set (mylist a b c)
+list(SORT mylist COMPARE STRING COMPARE STRING)
--- /dev/null
+^CMake Error at SORT-DuplicateOrderOption.cmake:2 \(list\):
+ list sub-command SORT option "ORDER" has been specified multiple times.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set (mylist a b c)
+list(SORT mylist ORDER ASCENDING ORDER ASCENDING)
--- /dev/null
+^CMake Error at SORT-NoCaseOption.cmake:1 \(list\):
+ list sub-command SORT missing argument for option "CASE".
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+list(SORT mylist CASE)
+++ /dev/null
-^CMake Error at SORT-TooManyArguments.cmake:1 \(list\):
- list sub-command SORT only takes one argument.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)$
--- /dev/null
+^CMake Error at SORT-WrongOption.cmake:1 \(list\):
+ list sub-command SORT option "one_too_many" is unknown.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+set(source_unsorted
+ c/B.h
+ a/c.h
+ B/a.h
+ )
+
+## Test with default options
+set(expected
+ B/a.h
+ a/c.h
+ c/B.h
+ )
+set(list ${source_unsorted})
+list(SORT list)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE STRING)")
+endif ()
+
+
+## Test CASE INSENSITIVE ORDER ASCENDING COMPARE STRING
+set(expected
+ a/c.h
+ B/a.h
+ c/B.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE INSENSITIVE ORDER DESCENDING COMPARE STRING
+set(expected
+ c/B.h
+ B/a.h
+ a/c.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE SENSITIVE ORDER ASCENDING COMPARE STRING
+set(expected
+ B/a.h
+ a/c.h
+ c/B.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE SENSITIVE ORDER DESCENDING COMPARE STRING
+set(expected
+ c/B.h
+ a/c.h
+ B/a.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE STRING)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE STRING)")
+endif ()
+
+## Test CASE INSENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME
+set(expected
+ B/a.h
+ c/B.h
+ a/c.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)")
+endif ()
+
+## Test CASE INSENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME
+set(expected
+ a/c.h
+ c/B.h
+ B/a.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE INSENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)")
+endif ()
+
+## Test CASE SENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME
+set(expected
+ c/B.h
+ B/a.h
+ a/c.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER ASCENDING COMPARE FILE_BASENAME)")
+endif ()
+
+## Test CASE SENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME
+set(expected
+ a/c.h
+ B/a.h
+ c/B.h
+ )
+set(list ${source_unsorted})
+list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)
+if (NOT expected STREQUAL list)
+ message(FATAL_ERROR "wrong sort result with command list(SORT list CASE SENSITIVE ORDER DESCENDING COMPARE FILE_BASENAME)")
+endif ()
--- /dev/null
+cmake_minimum_required(VERSION 2.8.4)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+^CMake Error at MATH-DivideByZero.cmake:1 \(math\):
+ math cannot evaluate the expression: "100/0": divide by zero.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+math(EXPR var "100/0")
--- /dev/null
+^CMake Error at MATH-DoubleOption.cmake:1 \(math\):
+ math EXPR called with incorrect arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+math(EXPR var "10*10" OUTPUT_FORMAT DECIMAL OUTPUT_FORMAT HEXADECIMAL)
--- /dev/null
+^CMake Error at MATH-InvalidExpression.cmake:1 \(math\):
+ math cannot parse the expression: "INVALID": syntax error, unexpected \$end,
+ expecting exp_PLUS or exp_MINUS or exp_OPENPARENT or exp_NUMBER \(7\).
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+math(EXPR var "INVALID")
--- /dev/null
+^CMake Warning \(dev\) at MATH-ToleratedExpression.cmake:1 \(math\):
+ Unexpected character in expression at position 1: '
+
+ Unexpected character in expression at position 7: '
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
--- /dev/null
+math(EXPR var "'2*1-1'")
+if(NOT var EQUAL 1)
+ message(FATAL_ERROR "Expression did not evaluate to 1")
+endif()
--- /dev/null
+^CMake Error at MATH-TooManyArguments.cmake:1 \(math\):
+ math EXPR called with incorrect arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+math(EXPR var "10*10" OUTPUT_FORMAT DECIMAL OUTPUT_FORMAT )
--- /dev/null
+^CMake Error at MATH-WrongArgument.cmake:1 \(math\):
+ math sub-command EXPR option "OUT" is unknown.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
--- /dev/null
+math(EXPR var "10*10" OUT HEX )
--- /dev/null
+macro(math_test expression expected)
+ math(EXPR evaluated ${expression} ${ARGN})
+ if (NOT evaluated STREQUAL ${expected})
+ message(FATAL_ERROR "wrong math result: ${evaluated} != ${expected}")
+ endif ()
+endmacro()
+
+
+math_test("100 * 10" 1000)
+math_test("100 * 10" 1000 OUTPUT_FORMAT DECIMAL)
+math_test("100 * 0xA" 1000 OUTPUT_FORMAT DECIMAL)
+math_test("100 * 0xA" 0x3e8 OUTPUT_FORMAT HEXADECIMAL)
--- /dev/null
+include(RunCMake)
+
+run_cmake(MATH)
+run_cmake(MATH-WrongArgument)
+run_cmake(MATH-DoubleOption)
+run_cmake(MATH-TooManyArguments)
+run_cmake(MATH-InvalidExpression)
+run_cmake(MATH-ToleratedExpression)
+run_cmake(MATH-DivideByZero)
--- /dev/null
+
+#Verify that option DOESN'T overwrite existing normal variable when the policy
+#is set to NEW
+cmake_policy(SET CMP0077 NEW)
+set(OPT_LOCAL_VAR FALSE)
+option(OPT_LOCAL_VAR "TEST_VAR" ON)
+if(OPT_LOCAL_VAR)
+ message(FATAL_ERROR "option failed to overwrite existing normal variable")
+endif()
+
+get_property(_exists_in_cache CACHE OPT_LOCAL_VAR PROPERTY VALUE SET)
+if(_exists_in_cache)
+ message(FATAL_ERROR "value should not exist in cache as it was already a local variable")
+endif()
--- /dev/null
+
+#Verify that option overwrites existing normal variable when the policy
+#is set to OLD
+cmake_policy(SET CMP0077 OLD)
+set(OPT_LOCAL_VAR FALSE)
+option(OPT_LOCAL_VAR "TEST_VAR" ON)
+if(NOT OPT_LOCAL_VAR)
+ message(FATAL_ERROR "option failed to overwrite existing normal variable")
+endif()
--- /dev/null
+
+#Verify that when both a cache and local version of a value exist that CMake
+#doesn't produce a CMP0077 warning and that we get the expected values.
+option(OPT_LOCAL_VAR "TEST_VAR" ON)
+set(OPT_LOCAL_VAR FALSE)
+option(OPT_LOCAL_VAR "TEST_VAR" ON)
+if(OPT_LOCAL_VAR)
+ message(FATAL_ERROR "option improperly set a cache variable that already exists")
+endif()
+
+get_property(_exists_in_cache CACHE OPT_LOCAL_VAR PROPERTY VALUE SET)
+if(NOT _exists_in_cache)
+ message(FATAL_ERROR "value should exist in cache")
+endif()
--- /dev/null
+CMake Warning \(dev\) at CMP0077-WARN.cmake:5 \(option\):
+ Policy CMP0077 is not set: option\(\) honors normal variables. Run "cmake
+ --help-policy CMP0077" for policy details. Use the cmake_policy command to
+ set the policy and suppress this warning.
+
+ For compatibility with older versions of CMake, option is clearing the
+ normal variable 'OPT_LOCAL_VAR'.
--- /dev/null
+
+#Verify that option overwrites existing normal variable when the policy
+#is set to OLD
+set(OPT_LOCAL_VAR FALSE)
+option(OPT_LOCAL_VAR "TEST_VAR" ON)
--- /dev/null
+cmake_minimum_required(VERSION 3.12)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+include(RunCMake)
+
+run_cmake(CMP0077-OLD)
+run_cmake(CMP0077-NEW)
+run_cmake(CMP0077-WARN)
+run_cmake(CMP0077-SECOND-PASS)
--- /dev/null
+#include <stdio.h>
+
+int main()
+{
+ char buf[1024];
+ size_t nIn = sizeof(buf);
+ while (nIn == sizeof(buf)) {
+ nIn = fread(buf, 1, sizeof(buf), stdin);
+ if (nIn > 0) {
+ size_t nOut;
+ nOut = fwrite(buf, 1, nIn, stdout);
+ if (nOut != nIn) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
--- /dev/null
+cmake_policy(SET CMP0048 NEW)
+project(ProjectTwiceTestFirst
+ VERSION 1.2.3.4
+ DESCRIPTION "Test Project"
+ HOMEPAGE_URL "http://example.com"
+ LANGUAGES NONE
+)
+
+project(ProjectTwiceTestSecond LANGUAGES NONE)
+
+foreach(var
+ PROJECT_VERSION
+ PROJECT_VERSION_MAJOR
+ PROJECT_VERSION_MINOR
+ PROJECT_VERSION_PATCH
+ PROJECT_VERSION_TWEAK
+ PROJECT_DESCRIPTION
+ PROJECT_HOMEPAGE_URL
+)
+ if(${var})
+ message(SEND_ERROR "${var} set but should be empty")
+ endif()
+ if(CMAKE_${var})
+ message(SEND_ERROR "CMAKE_${var} set but should be empty")
+ endif()
+endforeach()
run_cmake(ProjectHomepage)
run_cmake(ProjectHomepage2)
run_cmake(ProjectHomepageNoArg)
+run_cmake(ProjectTwice)
run_cmake(VersionAndLanguagesEmpty)
run_cmake(VersionEmpty)
run_cmake(VersionInvalid)
--- /dev/null
+-- Target LINK_DIRECTORIES is 'a;b;c;d;;e'
+-- Directory LINK_DIRECTORIES is 'a;b;c;d;;e'
--- /dev/null
+include(Common.cmake)
+test_target_property(LINK_DIRECTORIES)
+test_directory_property(LINK_DIRECTORIES)
--- /dev/null
+-- Target LINK_OPTIONS is 'a;b;c;d;;e'
+-- Directory LINK_OPTIONS is 'a;b;c;d;;e'
--- /dev/null
+include(Common.cmake)
+test_target_property(LINK_OPTIONS)
+test_directory_property(LINK_OPTIONS)
run_cmake(COMPILE_OPTIONS)
run_cmake(IMPORTED_GLOBAL)
run_cmake(INCLUDE_DIRECTORIES)
+run_cmake(LINK_OPTIONS)
+run_cmake(LINK_DIRECTORIES)
run_cmake(LINK_LIBRARIES)
run_cmake(SOURCES)
run_cmake(TYPE)
--- /dev/null
+-- INTERFACE_LINK_LIBRARIES='foo::@<[Xx0-9A-Fa-f]+>'
--- /dev/null
+cmake_policy(SET CMP0079 NEW)
+include(CMP0079-iface-common.cmake)
--- /dev/null
+-- INTERFACE_LINK_LIBRARIES='foo'
--- /dev/null
+cmake_policy(SET CMP0079 OLD)
+include(CMP0079-iface-common.cmake)
--- /dev/null
+^CMake Warning \(dev\) at CMP0079-iface/CMakeLists.txt:[0-9]+ \(target_link_libraries\):
+ Policy CMP0079 is not set: target_link_libraries allows use with targets in
+ other directories. Run "cmake --help-policy CMP0079" for policy details.
+ Use the cmake_policy command to set the policy and suppress this warning.
+
+ Target
+
+ top
+
+ is not created in this directory. For compatibility with older versions of
+ CMake, link library
+
+ foo
+
+ will be looked up in the directory in which the target was created rather
+ than in this calling directory.
+This warning is for project developers. Use -Wno-dev to suppress it.$
--- /dev/null
+-- INTERFACE_LINK_LIBRARIES='foo'
--- /dev/null
+include(CMP0079-iface-common.cmake)
--- /dev/null
+enable_language(C)
+
+add_executable(top empty.c)
+add_subdirectory(CMP0079-iface)
+get_property(libs TARGET top PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "INTERFACE_LINK_LIBRARIES='${libs}'")
--- /dev/null
+target_link_libraries(top INTERFACE foo)
--- /dev/null
+^CMake Error at CMP0079-link-NEW-bogus.cmake:[0-9]+ \(add_executable\):
+ Target "top" links to target "foo::@<0xdeadbeef>" but the target was not
+ found. Perhaps a find_package\(\) call is missing for an IMPORTED target, or
+ an ALIAS target is missing\?
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
--- /dev/null
+cmake_policy(SET CMP0028 NEW)
+cmake_policy(SET CMP0079 NEW)
+enable_language(C)
+
+add_executable(top empty.c)
+set_property(TARGET top APPEND PROPERTY LINK_LIBRARIES "foo::@<0xdeadbeef>")
--- /dev/null
+-- LINK_LIBRARIES='foo::@<[Xx0-9A-Fa-f]+>'
--- /dev/null
+cmake_policy(SET CMP0079 NEW)
+include(CMP0079-link-common.cmake)
--- /dev/null
+^CMake Error at CMP0079-link/CMakeLists.txt:[0-9]+ \(target_link_libraries\):
+ Attempt to add link library "foo" to target "top" which is not built in
+ this directory.
+
+ This is allowed only when policy CMP0079 is set to NEW.$
--- /dev/null
+cmake_policy(SET CMP0079 OLD)
+include(CMP0079-link-common.cmake)
--- /dev/null
+^CMake Error at CMP0079-link/CMakeLists.txt:[0-9]+ \(target_link_libraries\):
+ Attempt to add link library "foo" to target "top" which is not built in
+ this directory.
+
+ This is allowed only when policy CMP0079 is set to NEW.$
--- /dev/null
+include(CMP0079-link-common.cmake)
--- /dev/null
+enable_language(C)
+
+add_executable(top empty.c)
+add_subdirectory(CMP0079-link)
+get_property(libs TARGET top PROPERTY LINK_LIBRARIES)
+message(STATUS "LINK_LIBRARIES='${libs}'")
--- /dev/null
+target_link_libraries(top PUBLIC foo)
cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
-include(${RunCMake_TEST}.cmake)
+include(${RunCMake_TEST}.cmake NO_POLICY_SCOPE)
run_cmake(CMP0023-NEW)
run_cmake(CMP0023-WARN-2)
run_cmake(CMP0023-NEW-2)
+run_cmake(CMP0079-iface-WARN)
+run_cmake(CMP0079-iface-OLD)
+run_cmake(CMP0079-iface-NEW)
+run_cmake(CMP0079-link-WARN)
+run_cmake(CMP0079-link-OLD)
+run_cmake(CMP0079-link-NEW)
+run_cmake(CMP0079-link-NEW-bogus)
run_cmake(ImportedTarget)
run_cmake(ImportedTargetFailure)
run_cmake(MixedSignature)
run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)
-run_cmake(SubDirTarget)
run_cmake(SharedDepNotTarget)
run_cmake(StaticPrivateDepNotExported)
run_cmake(StaticPrivateDepNotTarget)
+++ /dev/null
-^CMake Error at SubDirTarget.cmake:[0-9]+ \(target_link_libraries\):
- Attempt to add link library "m" to target "subexe" which is not built in
- this directory.
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
+++ /dev/null
-enable_language(C)
-add_subdirectory(SubDirTarget)
-target_link_libraries(subexe m)
+++ /dev/null
-add_executable(subexe ../empty.c)
--- /dev/null
+cmake_minimum_required(VERSION 3.11)
+
+project(${RunCMake_TEST} LANGUAGES NONE)
+
+include(${RunCMake_TEST}.cmake)
--- /dev/null
+
+include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
--- /dev/null
+
+include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
--- /dev/null
+
+if (actual_stdout MATCHES "LINKER:")
+ set (RunCMake_TEST_FAILED "LINKER: prefix was not expanded.")
+ return()
+endif()
+
+if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/LINKER.txt")
+ set (RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/LINKER.txt: Reference file not found.")
+ return()
+endif()
+file(READ "${RunCMake_TEST_BINARY_DIR}/LINKER.txt" linker_flag)
+
+if (NOT actual_stdout MATCHES "${linker_flag}")
+ set (RunCMake_TEST_FAILED "LINKER: was not expanded correctly.")
+endif()
--- /dev/null
+
+enable_language(C)
+
+add_executable(dump dump.c)
+
+# ensure no temp file will be used
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}")
+
+
+# Use LINKER alone
+add_library(linker SHARED LinkOptionsLib.c)
+target_link_options(linker PRIVATE "LINKER:-foo,bar")
+
+# use LAUNCH facility to dump linker command
+set_property(TARGET linker PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"")
+
+add_dependencies (linker dump)
+
+
+# Use LINKER with SHELL
+add_library(linker_shell SHARED LinkOptionsLib.c)
+target_link_options(linker_shell PRIVATE "LINKER:SHELL:-foo bar")
+
+# use LAUNCH facility to dump linker command
+set_property(TARGET linker_shell PROPERTY RULE_LAUNCH_LINK "\"${CMAKE_CURRENT_BINARY_DIR}/dump${CMAKE_EXECUTABLE_SUFFIX}\"")
+
+add_dependencies (linker_shell dump)
+
+
+# generate reference for LINKER flag
+if (CMAKE_C_LINKER_WRAPPER_FLAG)
+ set(linker_flag ${CMAKE_C_LINKER_WRAPPER_FLAG})
+ list(GET linker_flag -1 linker_space)
+ if (linker_space STREQUAL " ")
+ list(REMOVE_AT linker_flag -1)
+ else()
+ set(linker_space)
+ endif()
+ list (JOIN linker_flag " " linker_flag)
+ if (CMAKE_C_LINKER_WRAPPER_FLAG_SEP)
+ string (APPEND linker_flag "${linker_space}" "-foo${CMAKE_C_LINKER_WRAPPER_FLAG_SEP}bar")
+ else()
+ set (linker_flag "${linker_flag}${linker_space}-foo ${linker_flag}${linker_space}bar")
+ endif()
+else()
+ set(linker_flag "-foo bar")
+endif()
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER.txt" "${linker_flag}")
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_PRIVATE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_PRIVATE'.")
+endif()
+if (actual_stdout MATCHES "BADFLAG_INTERFACE")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected 'BADFLAG_INTERFACE'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_RELEASE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_RELEASE'.")
+endif()
+if (actual_stdout MATCHES "SHELL:")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix 'SHELL:'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_INTERFACE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_INTERFACE'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_INTERFACE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_INTERFACE'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_RELEASE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_RELEASE'.")
+endif()
+if (actual_stdout MATCHES "SHELL:")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix 'SHELL:'.")
+endif()
--- /dev/null
+
+if (NOT actual_stdout MATCHES "BADFLAG_RELEASE")
+ set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_RELEASE'.")
+endif()
+if (actual_stdout MATCHES "SHELL:")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix 'SHELL:'.")
+endif()
--- /dev/null
+
+if (actual_stdout MATCHES "BADFLAG_RELEASE")
+ set (RunCMake_TEST_FAILED "Found 'BADFLAG_RELEASE' which was not expected.")
+endif()
+if (actual_stdout MATCHES "SHELL:")
+ string (APPEND RunCMake_TEST_FAILED "\nFound unexpected prefix 'SHELL:'.")
+endif()
--- /dev/null
+
+enable_language(C)
+
+set(obj "${CMAKE_C_OUTPUT_EXTENSION}")
+if(BORLAND)
+ set(pre -)
+endif()
+
+# basic configuration
+add_library(LinkOptions SHARED LinkOptionsLib.c)
+target_link_options(LinkOptions
+ PRIVATE ${pre}BADFLAG_PRIVATE${obj}
+ INTERFACE ${pre}BADFLAG_INTERFACE${obj})
+
+
+# INTERFACE_LINK_OPTIONS
+add_library(LinkOptions_producer SHARED LinkOptionsLib.c)
+target_link_options(LinkOptions_producer
+ INTERFACE ${pre}BADFLAG_INTERFACE${obj})
+
+add_executable(LinkOptions_consumer LinkOptionsExe.c)
+target_link_libraries(LinkOptions_consumer PRIVATE LinkOptions_producer)
+
+
+# static library with INTERFACE_LINK_OPTIONS
+add_library(LinkOptions_producer_static STATIC LinkOptionsLib.c)
+target_link_options(LinkOptions_producer_static
+ INTERFACE ${pre}BADFLAG_INTERFACE${obj})
+
+add_executable(LinkOptions_consumer_static LinkOptionsExe.c)
+target_link_libraries(LinkOptions_consumer_static PRIVATE LinkOptions_producer_static)
+
+
+# static library with generator expression
+add_library(LinkOptions_static STATIC LinkOptionsLib.c)
+target_link_options(LinkOptions_static PRIVATE $<$<CONFIG:Release>:${pre}BADFLAG_RELEASE${obj}>
+ "SHELL:" # produces no options
+ )
+
+
+# shared library with generator expression
+add_library(LinkOptions_shared SHARED LinkOptionsLib.c)
+target_link_options(LinkOptions_shared PRIVATE $<$<CONFIG:Release>:${pre}BADFLAG_RELEASE${obj}>
+ "SHELL:" # produces no options
+ )
+
+
+# module library with generator expression
+add_library(LinkOptions_mod MODULE LinkOptionsLib.c)
+target_link_options(LinkOptions_mod PRIVATE $<$<CONFIG:Release>:${pre}BADFLAG_RELEASE${obj}>)
+
+
+# executable with generator expression
+add_executable(LinkOptions_exe LinkOptionsExe.c)
+target_link_options(LinkOptions_exe PRIVATE $<$<CONFIG:Release>:${pre}BADFLAG_RELEASE${obj}>)
--- /dev/null
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+#if defined(_WIN32)
+__declspec(dllexport)
+#endif
+ int flags_lib(void)
+{
+ return 0;
+}
--- /dev/null
+
+include(RunCMake)
+
+macro(run_cmake_target test subtest target)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
+
+ unset(RunCMake_TEST_BINARY_DIR)
+ unset(RunCMake_TEST_NO_CLEAN)
+endmacro()
+
+if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
+ # Intel compiler does not reject bad flags or objects!
+ set(RunCMake_TEST_OUTPUT_MERGE TRUE)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+ endif()
+
+ run_cmake(LINK_OPTIONS)
+
+ run_cmake_target(LINK_OPTIONS basic LinkOptions)
+ run_cmake_target(LINK_OPTIONS interface LinkOptions_consumer)
+ run_cmake_target(LINK_OPTIONS interface-static LinkOptions_consumer_static)
+ run_cmake_target(LINK_OPTIONS static LinkOptions_static --config Release)
+ run_cmake_target(LINK_OPTIONS shared LinkOptions_shared --config Release)
+ run_cmake_target(LINK_OPTIONS mod LinkOptions_mod --config Release)
+ run_cmake_target(LINK_OPTIONS exe LinkOptions_exe --config Release)
+
+ unset(RunCMake_TEST_OPTIONS)
+ unset(RunCMake_TEST_OUTPUT_MERGE)
+endif()
+
+run_cmake(bad_SHELL_usage)
+
+if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)")
+ run_cmake(LINKER_expansion)
+
+ run_cmake_target(LINKER_expansion LINKER linker)
+ run_cmake_target(LINKER_expansion LINKER_SHELL linker_shell)
+endif()
--- /dev/null
+CMake Error at bad_SHELL_usage.cmake:4 \(add_library\):
+ 'SHELL:' prefix is not supported as part of 'LINKER:' arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:5 \(include\)
--- /dev/null
+
+enable_language(C)
+
+add_library(example SHARED LinkOptionsLib.c)
+target_link_options(example PRIVATE "LINKER:-foo,SHELL:-bar")
--- /dev/null
+
+#include "stdio.h"
+
+int main(int argc, char* argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++)
+ printf("%s ", argv[i]);
+ printf("\n");
+
+ return 0;
+}
caller link flags \(e.g. CMAKE_EXE_LINKER_FLAGS\) in the test project.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.$
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Deprecation Warning at CMP0056.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0056 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\)$
+++ /dev/null
-cmake_minimum_required (VERSION 3.9)
-project (TestSimpleInstall)
-set(CMAKE_VERBOSE_MAKEFILE 1)
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
- "${TestSimpleInstall_BINARY_DIR}/bin")
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
- "${TestSimpleInstall_BINARY_DIR}/lib/static")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
- "${TestSimpleInstall_BINARY_DIR}/lib")
-
-# Skip generating the rpath pointing at the build tree to make sure
-# the executable is installed with the proper rpath in the install
-# tree.
-set(CMAKE_SKIP_BUILD_RPATH 1)
-
-# Make sure the executable can run from the install tree.
-set(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
-
-# Skip the dependency that causes a build when installing. This
-# avoids infinite loops when the post-build rule below installs.
-set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 1)
-set(CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY 1)
-
-set(CMAKE_DEBUG_POSTFIX "_test_debug_postfix")
-
-set(EXTRA_INSTALL_FLAGS)
-message("Extra install: ${EXTRA_INSTALL_FLAGS}")
-
-if(STAGE2)
- set(LIBPATHS
- ${CMAKE_INSTALL_PREFIX}/MyTest/lib/static
- ${CMAKE_INSTALL_PREFIX}/MyTest/lib
- )
- set(t1NAMES test1 test1${CMAKE_DEBUG_POSTFIX} test1rel)
- set(t2NAMES test2 test2${CMAKE_DEBUG_POSTFIX})
- set(t4NAMES test4out test4out${CMAKE_DEBUG_POSTFIX})
-
- # Make sure the install script ran.
- set(CMAKE_INSTALL_SCRIPT_DID_RUN 0)
- include(${CMAKE_INSTALL_PREFIX}/MyTest/InstallScriptOut.cmake OPTIONAL)
- if(CMAKE_INSTALL_SCRIPT_DID_RUN)
- message(STATUS "Stage 1 did run install script 2.")
- else()
- message(SEND_ERROR "Stage 1 did not run install script 2.")
- endif()
-
- if(CYGWIN OR MINGW)
- set(LIBPATHS ${LIBPATHS} "${CMAKE_INSTALL_PREFIX}/MyTest/bin")
- endif()
- message("Search for library in: ${LIBPATHS}")
-
- set(TEST1_LIBRARY "TEST1_LIBRARY-NOTFOUND" CACHE FILEPATH "Force find." FORCE)
- set(TEST2_LIBRARY "TEST2_LIBRARY-NOTFOUND" CACHE FILEPATH "Force find." FORCE)
- set(TEST4_LIBRARY "TEST4_LIBRARY-NOTFOUND" CACHE FILEPATH "Force find." FORCE)
-
- find_library(TEST1_LIBRARY
- NAMES ${t1NAMES}
- PATHS ${LIBPATHS}
- DOC "First library")
- find_library(TEST2_LIBRARY
- NAMES ${t2NAMES}
- PATHS ${LIBPATHS}
- DOC "Second library")
- find_library(TEST4_LIBRARY
- NAMES ${t4NAMES}
- PATHS ${LIBPATHS}
- DOC "Fourth library")
-
- # Test importing a library found on disk.
- add_library(lib_test4 UNKNOWN IMPORTED)
- set_property(TARGET lib_test4 PROPERTY IMPORTED_LOCATION ${TEST4_LIBRARY})
-
- include_directories(${CMAKE_INSTALL_PREFIX}/MyTest/include)
- add_executable (SimpleInstExeS2 inst2.cxx foo.c foo.h)
- target_link_libraries(SimpleInstExeS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} lib_test4)
- set(install_target SimpleInstExeS2)
-
- if("${TEST1_LIBRARY}" MATCHES "static")
- message(STATUS "test1 correctly found in lib/static")
- else()
- message(SEND_ERROR "test1 not found in lib/static!")
- endif()
-
- # Check for failure of configuration-specific installation.
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/include/Release/lib1debug.h")
- message(FATAL_ERROR "Debug-configuration file installed for Release!")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/include/Debug/lib1release.h")
- message(FATAL_ERROR "Release-configuration file installed for Debug!")
- endif()
-
- # Check for failure of directory installation.
- if(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/TestSubDir/TSD.h")
- message(FATAL_ERROR "Directory installation did not install TSD.h")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/TestSubDir/CVS")
- message(FATAL_ERROR "Directory installation installed CVS directory.")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CVS")
- message(FATAL_ERROR "Directory installation installed CVS directory.")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CMakeLists.txt")
- message(FATAL_ERROR "Directory installation installed CMakeLists.txt.")
- endif()
- if(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.h")
- message(FATAL_ERROR "Directory installation did not install alternate TSD.h")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.cxx")
- message(FATAL_ERROR "Directory installation installed alternate TSD.cxx")
- endif()
-
- # Check that scripts properly installed.
- if(WIN32 AND NOT CYGWIN)
- set(BAT .bat)
- else()
- set(BAT)
- endif()
- foreach(loc share share/old1 share/old2 share/old3 share/alt)
- set(CUR_SCRIPT "${CMAKE_INSTALL_PREFIX}/MyTest/${loc}/sample_script${BAT}")
- execute_process(
- COMMAND ${CUR_SCRIPT}
- RESULT_VARIABLE SAMPLE_SCRIPT_RESULT
- OUTPUT_VARIABLE SAMPLE_SCRIPT_OUTPUT
- )
- if(NOT "${SAMPLE_SCRIPT_RESULT}" STREQUAL "0")
- message(FATAL_ERROR
- "Sample script [${CUR_SCRIPT}] failed: [${SAMPLE_SCRIPT_RESULT}]")
- endif()
- if(NOT "${SAMPLE_SCRIPT_OUTPUT}" MATCHES "Sample Script Output")
- message(FATAL_ERROR
- "Bad sample script [${CUR_SCRIPT}] output: [${SAMPLE_SCRIPT_OUTPUT}]")
- endif()
- endforeach()
-
- # Check for failure of empty directory installation.
- if(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/empty")
- message(FATAL_ERROR "Empty directory installation did not install.")
- endif()
- file(GLOB EMPTY_FILES "${CMAKE_INSTALL_PREFIX}/MyTest/share/empty/*")
- if(EMPTY_FILES)
- message(FATAL_ERROR "Empty directory installed [${EMPTY_FILES}].")
- endif()
-
- # Make sure the test executable can run from the install tree.
- set_target_properties(SimpleInstExeS2 PROPERTIES
- INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
-
- install_targets(/MyTest/bin SimpleInstExeS2)
-
-# try to import the exported targets again
- set(SimpleInstallS1_DIR ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
- find_package(SimpleInstallS1 REQUIRED)
- get_target_property(simpleInstallImported S1_SimpleInstall IMPORTED)
- if(NOT simpleInstallImported)
- message(FATAL_ERROR "Target S1_SimpleInstall could not be imported")
- endif()
-
-else()
- # Wipe out the install directory to do a fresh test.
- file(REMOVE_RECURSE ${CMAKE_INSTALL_PREFIX}/MyTest)
-
- # this is stage 1, so create libraries and modules and install everything
- add_library(test1 STATIC lib1.cxx)
- add_library(test2 SHARED lib2.cxx)
- add_library(test3 MODULE lib3.cxx)
- add_library(test4 SHARED lib4.cxx)
-
- # Test <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME properties.
- set_property(TARGET test4 PROPERTY ARCHIVE_OUTPUT_NAME test4out)
- set_property(TARGET test4 PROPERTY LIBRARY_OUTPUT_NAME test4out)
-
- add_executable (SimpleInstall inst.cxx foo.c foo.h)
- target_link_libraries(SimpleInstall test1 test2 test4)
- set(install_target SimpleInstall)
-
- set_target_properties(SimpleInstall PROPERTIES OUTPUT_NAME SimpleInstExe)
- # Disable VERSION test until it is implemented in the Xcode generator.
- if(NOT XCODE)
- set_target_properties(SimpleInstall PROPERTIES VERSION 1.2)
- endif()
-
- # Make sure the test executable can run from the install tree.
- set_target_properties(SimpleInstall PROPERTIES
- INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
-
- # Test per-configuration output name.
- set_target_properties(test1 PROPERTIES RELEASE_OUTPUT_NAME test1rel)
- set_target_properties(test2 PROPERTIES PUBLIC_HEADER foo.h)
-
- if(CMAKE_GENERATOR MATCHES "Makefiles")
- add_subdirectory(TestSubDir)
- add_dependencies(SimpleInstall TSD)
- endif()
-
- add_dependencies(SimpleInstall test3)
- add_dependencies(test2 test3)
- add_dependencies(test4 test2)
-
- install(TARGETS SimpleInstall test1 test2 test3 EXPORT SimpleInstallS1
- RUNTIME DESTINATION MyTest/bin COMPONENT Runtime # .exe, .dll
- LIBRARY DESTINATION MyTest/lib COMPONENT Runtime # .so, mod.dll
- ARCHIVE DESTINATION MyTest/lib/static COMPONENT Development # .a, .lib
- PUBLIC_HEADER DESTINATION MyTest/include COMPONENT Development
- )
-
- install(TARGETS test4 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
- RUNTIME DESTINATION MyTest/bin
- LIBRARY DESTINATION MyTest/lib
- ARCHIVE DESTINATION MyTest/lib/static
- OPTIONAL # for coverage...target should always exist
- )
- install(FILES lib1.h DESTINATION MyTest/include/$<1:foo>$<0:/wrong>)
- install(FILES lib2.h
- DESTINATION $<1:MyTest/include/foo>$<0:/wrong>
- COMPONENT Development
- PERMISSIONS OWNER_READ OWNER_WRITE
- RENAME lib2renamed.h
- )
-
- # Test old-style install commands.
- install_files(/MyTest/include FILES lib3.h)
- install_files(/MyTest/include/old .h lib3)
- install_files(/MyTest/include/old "^lib2.h$")
- install_programs(/MyTest/share/old1 FILES
- scripts/sample_script scripts/sample_script.bat)
- install_programs(/MyTest/share/old2
- scripts/sample_script scripts/sample_script.bat)
-
-# "export" the targets collected in "SimpleInstallS1"
- install(EXPORT SimpleInstallS1 FILE SimpleInstallS1Config.cmake
- DESTINATION MyTest/lib
- NAMESPACE S1_ )
-
- export(TARGETS SimpleInstall test1 test2 test3
- FILE "${CMAKE_CURRENT_BINARY_DIR}/SimpleInstallS1Config.cmake"
- NAMESPACE S2_ )
-
- add_subdirectory(scripts)
-
- # Test optional installation.
- install(FILES does_not_exist.h DESTINATION MyTest/include/foo OPTIONAL)
-
- # Test configuration-specific installation.
- install(FILES lib1.h RENAME lib1release.h CONFIGURATIONS Release
- DESTINATION MyTest/include/Release
- )
- install(FILES lib1.h RENAME lib1debug.h CONFIGURATIONS Debug
- DESTINATION MyTest/include/Debug
- )
-
- # Test directory installation.
- file(REMOVE_RECURSE "${CMAKE_INSTALL_PREFIX}/MyTest/share/CVS")
- file(REMOVE_RECURSE "${CMAKE_INSTALL_PREFIX}/MyTest/share/TestSubDir/CVS")
- install(
- DIRECTORY TestSubDir $<1:scripts/>$<0:/wrong> DESTINATION $<1:MyTest/share>$<0:/wrong>
- FILE_PERMISSIONS OWNER_READ OWNER_WRITE
- DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
- GROUP_READ GROUP_EXECUTE
- PATTERN "CVS" EXCLUDE
- REGEX "\\.txt$" EXCLUDE
- PATTERN "scripts/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
- )
-
- # Alternate directory installation for coverage.
- install(
- DIRECTORY $<1:scripts/>$<0:/wrong> DESTINATION $<1:MyTest/share/alt>$<0:/wrong>
- COMPONENT Development
- USE_SOURCE_PERMISSIONS
- PATTERN "CVS" EXCLUDE
- REGEX "\\.txt$" EXCLUDE
- )
- install(
- DIRECTORY TestSubDir DESTINATION $<1:MyTest/share/alt>$<0:/wrong>
- FILE_PERMISSIONS OWNER_READ OWNER_WRITE
- DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
- GROUP_READ GROUP_EXECUTE
- FILES_MATCHING PATTERN "*.h"
- )
-
- # Test empty directory installation.
- install(DIRECTORY DESTINATION MyTest/share/empty)
-
- # Test optional directory installation.
- install(DIRECTORY does-not-exist DESTINATION MyTest/share OPTIONAL)
-
- # Test user-specified install scripts, with and without COMPONENT.
- install(
- SCRIPT InstallScript1.cmake
- CODE "set(INSTALL_CODE_DID_RUN 1)"
- SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/InstallScript2.cmake
- )
- install(
- SCRIPT InstallScript3.cmake
- CODE "set(INSTALL_CODE_WITH_COMPONENT_DID_RUN 1)"
- SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/InstallScript4.cmake
- COMPONENT Development
- )
- set_directory_properties(PROPERTIES
- ADDITIONAL_MAKE_CLEAN_FILES
- "${CMAKE_INSTALL_PREFIX}/InstallScriptOut.cmake;${CMAKE_INSTALL_PREFIX}/InstallScript4Out.cmake")
-
- set_target_properties(SimpleInstall PROPERTIES PRE_INSTALL_SCRIPT
- ${CMAKE_CURRENT_SOURCE_DIR}/PreInstall.cmake)
- set_target_properties(SimpleInstall PROPERTIES POST_INSTALL_SCRIPT
- ${CMAKE_CURRENT_SOURCE_DIR}/PostInstall.cmake)
- set_target_properties(test4 PROPERTIES VERSION 1.2 SOVERSION 3
- INSTALL_NAME_DIR @executable_path/../lib)
-endif()
-
-get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
-if(_isMultiConfig)
- set(SI_CONFIG --config $<CONFIGURATION>)
-else()
- set(SI_CONFIG)
-endif()
-
-# Dummy test of CPack
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Test of packaging with cpack")
-set(CPACK_PACKAGE_VENDOR "Kitware")
-set(CPACK_INSTALL_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/PackageScript.cmake")
-
-if(WIN32 AND NOT UNIX)
- find_program(NSIS_MAKENSIS NAMES makensis
- PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS]
- DOC "Where is makensis.exe located"
- )
- if(NOT NSIS_MAKENSIS)
- set(CPACK_GENERATOR TGZ)
- endif()
-endif()
-if(UNIX AND NOT APPLE)
- set(CPACK_GENERATOR "TGZ;STGZ;TZ")
- # find_program(found_compress
- # NAMES compress)
- # if(found_compress)
- # find_program(file_command NAMES file)
- # if(NOT file_command)
- # set(file_command file)
- # endif()
- # execute_process(COMMAND ${file_command} ${found_compress}
- # OUTPUT_VARIABLE output)
- # set(SKIP_TZ FALSE)
- # if("${output}" MATCHES "script")
- # set(SKIP_TZ TRUE)
- # endif()
- # if("${output}" MATCHES "dummy.sh")
- # set(SKIP_TZ TRUE)
- # endif()
- # if(NOT SKIP_TZ)
- # message("compress found and it was not a script")
- # message("output from file command: [${output}]")
- # list(APPEND CPACK_GENERATOR "TZ")
- # else()
- # message("compress found, but it was a script so don't use it")
- # message("output from file command: [${output}]")
- # endif()
- # endif()
- find_program(found_bz2
- NAMES bzip2)
- if(found_bz2)
- list(APPEND CPACK_GENERATOR "TBZ2")
- endif()
-endif()
-
-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)
- set(package_command COMMAND
- ${CMAKE_COMMAND} --build . --target package ${SI_CONFIG}
- )
-
- # Avoid settings that require the .zip file command line tools...
- # (just build an NSIS installer without component support)
- #
- set(CPACK_BINARY_ZIP OFF)
- set(CPACK_MONOLITHIC_INSTALL ON)
-else()
- set(package_command)
-endif()
-
-include(CPack)
-
-set(install_command COMMAND
- ${CMAKE_COMMAND} --build . --target install ${SI_CONFIG}
- )
-
-add_custom_command(
- TARGET ${install_target}
- POST_BUILD
- ${install_command}
- ${package_command}
- COMMENT "Install Project"
- )
+++ /dev/null
-message("This is install script 1.")
-set(INSTALL_SCRIPT_1_DID_RUN 1)
-if(INSTALL_CODE_DID_RUN)
- message(FATAL_ERROR "Install script 1 did not run before install code.")
-endif()
+++ /dev/null
-message("This is install script 2.")
-if(INSTALL_SCRIPT_1_DID_RUN)
- message("Install script ordering works.")
-else()
- message(FATAL_ERROR "Install script 1 did not run before install script 2.")
-endif()
-if(INSTALL_CODE_DID_RUN)
- message("Install code ordering works.")
-else()
- message(FATAL_ERROR "Install script 2 did not run after install code.")
-endif()
-file(WRITE "${CMAKE_INSTALL_PREFIX}/MyTest/InstallScriptOut.cmake"
- "set(CMAKE_INSTALL_SCRIPT_DID_RUN 1)\n"
- )
+++ /dev/null
-message("This is install script 3.")
-set(INSTALL_SCRIPT_3_DID_RUN 1)
-if(INSTALL_CODE_WITH_COMPONENT_DID_RUN)
- message(FATAL_ERROR "Install script 3 did not run before install code with component.")
-endif()
-
-if(CMAKE_INSTALL_COMPONENT)
-if(NOT "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Development")
- message("CMAKE_INSTALL_COMPONENT=\"${CMAKE_INSTALL_COMPONENT}\"")
- message(FATAL_ERROR "Install script 3 should only run for \"Development\" INSTALL COMPONENT.")
-endif()
-endif()
+++ /dev/null
-message("This is install script 4.")
-if(INSTALL_SCRIPT_3_DID_RUN)
- message("Install script ordering works.")
-else()
- message(FATAL_ERROR "Install script 3 did not run before install script 4.")
-endif()
-if(INSTALL_CODE_WITH_COMPONENT_DID_RUN)
- message("Install code ordering works.")
-else()
- message(FATAL_ERROR "Install script 4 did not run after install with component code.")
-endif()
-
-if(CMAKE_INSTALL_COMPONENT)
-if(NOT "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Development")
- message("CMAKE_INSTALL_COMPONENT=\"${CMAKE_INSTALL_COMPONENT}\"")
- message(FATAL_ERROR "Install script 4 should only run for \"Development\" INSTALL COMPONENT.")
-endif()
-endif()
-
-file(WRITE "${CMAKE_INSTALL_PREFIX}/MyTest/InstallScript4Out.cmake"
- "set(CMAKE_INSTALL_SCRIPT_4_DID_RUN 1)\n"
- )
+++ /dev/null
-message("This is packaging script")
-message("It writes a file with all variables available in ${CMAKE_INSTALL_PREFIX}/AllVariables.txt")
-
-file(WRITE ${CMAKE_INSTALL_PREFIX}/AllVariables.txt "")
-get_cmake_property(res VARIABLES)
-foreach(var ${res})
- file(APPEND ${CMAKE_INSTALL_PREFIX}/AllVariables.txt
- "${var} \"${${var}}\"\n")
-endforeach()
-
+++ /dev/null
-message("In post install")
-if(PRE_INSTALL_DID_RUN)
- message("Pre and post install work fine")
-else()
- message(FATAL_ERROR "Pre install did not run before post install")
-endif()
+++ /dev/null
-message("This is in pre install")
-set(PRE_INSTALL_DID_RUN 1)
+++ /dev/null
-add_executable(TSD TSD.cxx TSD_utils.cxx)
-install_files(/MyTest/include FILES TSD.h)
-install_targets(/MyTest/bin TSD)
+++ /dev/null
-#include <stdio.h>
-
-#include "TSD.h"
-
-int main()
-{
- int res = TSD("TEST");
- printf("Hello from TSD\n");
- return res;
-}
+++ /dev/null
-int TSD(const char*);
+++ /dev/null
-#include <string.h>
-
-int TSD(const char* foo)
-{
- if (strcmp(foo, "TEST") == 0) {
- return 0;
- }
- return 1;
-}
+++ /dev/null
-char* foo = "Foo";
-
-int SomeFunctionInFoo()
-{
- return 5;
-}
+++ /dev/null
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern char* foo;
-extern int SomeFunctionInFoo();
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-#include "foo.h"
-
-#ifdef STAGE_2
-# include <foo/lib1.h>
-# include <foo/lib2renamed.h>
-# include <lib3.h>
-# include <old/lib2.h>
-# include <old/lib3.h>
-#else
-# include "lib1.h"
-# include "lib2.h"
-#endif
-
-#include "lib4.h"
-
-#include <stdio.h>
-
-int main()
-{
- if (Lib1Func() != 2.0) {
- printf("Problem with lib1\n");
- return 1;
- }
- if (Lib2Func() != 1.0) {
- printf("Problem with lib2\n");
- return 1;
- }
- if (Lib4Func() != 4.0) {
- printf("Problem with lib4\n");
- return 1;
- }
- printf("The value of Foo: %s\n", foo);
- return SomeFunctionInFoo() - 5;
-}
+++ /dev/null
-#define STAGE_2
-#include "inst.cxx"
+++ /dev/null
-#include "lib1.h"
-
-float Lib1Func()
-{
- return 2.0;
-}
+++ /dev/null
-extern float Lib1Func();
+++ /dev/null
-#include "lib2.h"
-
-float Lib2Func()
-{
- return 1.0;
-}
+++ /dev/null
-#ifdef _WIN32
-# ifdef test2_EXPORTS
-# define CM_TEST_LIB_EXPORT __declspec(dllexport)
-# else
-# define CM_TEST_LIB_EXPORT __declspec(dllimport)
-# endif
-#else
-# define CM_TEST_LIB_EXPORT
-#endif
-
-CM_TEST_LIB_EXPORT float Lib2Func();
+++ /dev/null
-#include "lib3.h"
-
-float Lib3Func()
-{
- return 2.0;
-}
+++ /dev/null
-#ifdef _WIN32
-# ifdef test3_EXPORTS
-# define CM_TEST_LIB_EXPORT __declspec(dllexport)
-# else
-# define CM_TEST_LIB_EXPORT __declspec(dllimport)
-# endif
-#else
-# define CM_TEST_LIB_EXPORT
-#endif
-
-CM_TEST_LIB_EXPORT float Lib3Func();
+++ /dev/null
-#include "lib4.h"
-
-float Lib4Func()
-{
- return 4.0;
-}
+++ /dev/null
-#ifdef _WIN32
-# ifdef test4_EXPORTS
-# define CM_TEST_LIB_EXPORT __declspec(dllexport)
-# else
-# define CM_TEST_LIB_EXPORT __declspec(dllimport)
-# endif
-#else
-# define CM_TEST_LIB_EXPORT
-#endif
-
-CM_TEST_LIB_EXPORT float Lib4Func();
+++ /dev/null
-install_programs(/MyTest/share/old3 "^sample_script(\\.bat)?$")
+++ /dev/null
-#!/bin/sh
-echo "Sample Script Output"
+++ /dev/null
-@echo Sample Script Output\r
+++ /dev/null
-cmake_minimum_required (VERSION 3.9)
-project (TestSimpleInstall)
-set(CMAKE_VERBOSE_MAKEFILE 1)
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
- "${TestSimpleInstall_BINARY_DIR}/bin")
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
- "${TestSimpleInstall_BINARY_DIR}/lib/static")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
- "${TestSimpleInstall_BINARY_DIR}/lib")
-
-# Skip generating the rpath pointing at the build tree to make sure
-# the executable is installed with the proper rpath in the install
-# tree.
-set(CMAKE_SKIP_BUILD_RPATH 1)
-
-# Make sure the executable can run from the install tree.
-set(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
-
-# Skip the dependency that causes a build when installing. This
-# avoids infinite loops when the post-build rule below installs.
-set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 1)
-set(CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY 1)
-
-set(CMAKE_DEBUG_POSTFIX "_test_debug_postfix")
-
-set(EXTRA_INSTALL_FLAGS)
-message("Extra install: ${EXTRA_INSTALL_FLAGS}")
-
-if(STAGE2)
- set(LIBPATHS
- ${CMAKE_INSTALL_PREFIX}/MyTest/lib/static
- ${CMAKE_INSTALL_PREFIX}/MyTest/lib
- )
- set(t1NAMES test1 test1${CMAKE_DEBUG_POSTFIX} test1rel)
- set(t2NAMES test2 test2${CMAKE_DEBUG_POSTFIX})
- set(t4NAMES test4out test4out${CMAKE_DEBUG_POSTFIX})
-
- # Make sure the install script ran.
- set(CMAKE_INSTALL_SCRIPT_DID_RUN 0)
- include(${CMAKE_INSTALL_PREFIX}/MyTest/InstallScriptOut.cmake OPTIONAL)
- if(CMAKE_INSTALL_SCRIPT_DID_RUN)
- message(STATUS "Stage 1 did run install script 2.")
- else()
- message(SEND_ERROR "Stage 1 did not run install script 2.")
- endif()
-
- if(CYGWIN OR MINGW)
- set(LIBPATHS ${LIBPATHS} "${CMAKE_INSTALL_PREFIX}/MyTest/bin")
- endif()
- message("Search for library in: ${LIBPATHS}")
-
- set(TEST1_LIBRARY "TEST1_LIBRARY-NOTFOUND" CACHE FILEPATH "Force find." FORCE)
- set(TEST2_LIBRARY "TEST2_LIBRARY-NOTFOUND" CACHE FILEPATH "Force find." FORCE)
- set(TEST4_LIBRARY "TEST4_LIBRARY-NOTFOUND" CACHE FILEPATH "Force find." FORCE)
-
- find_library(TEST1_LIBRARY
- NAMES ${t1NAMES}
- PATHS ${LIBPATHS}
- DOC "First library")
- find_library(TEST2_LIBRARY
- NAMES ${t2NAMES}
- PATHS ${LIBPATHS}
- DOC "Second library")
- find_library(TEST4_LIBRARY
- NAMES ${t4NAMES}
- PATHS ${LIBPATHS}
- DOC "Fourth library")
-
- # Test importing a library found on disk.
- add_library(lib_test4 UNKNOWN IMPORTED)
- set_property(TARGET lib_test4 PROPERTY IMPORTED_LOCATION ${TEST4_LIBRARY})
-
- include_directories(${CMAKE_INSTALL_PREFIX}/MyTest/include)
- add_executable (SimpleInstExeS2 inst2.cxx foo.c foo.h)
- target_link_libraries(SimpleInstExeS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} lib_test4)
- set(install_target SimpleInstExeS2)
-
- if("${TEST1_LIBRARY}" MATCHES "static")
- message(STATUS "test1 correctly found in lib/static")
- else()
- message(SEND_ERROR "test1 not found in lib/static!")
- endif()
-
- # Check for failure of configuration-specific installation.
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/include/Release/lib1debug.h")
- message(FATAL_ERROR "Debug-configuration file installed for Release!")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/include/Debug/lib1release.h")
- message(FATAL_ERROR "Release-configuration file installed for Debug!")
- endif()
-
- # Check for failure of directory installation.
- if(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/TestSubDir/TSD.h")
- message(FATAL_ERROR "Directory installation did not install TSD.h")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/TestSubDir/CVS")
- message(FATAL_ERROR "Directory installation installed CVS directory.")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CVS")
- message(FATAL_ERROR "Directory installation installed CVS directory.")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CMakeLists.txt")
- message(FATAL_ERROR "Directory installation installed CMakeLists.txt.")
- endif()
- if(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.h")
- message(FATAL_ERROR "Directory installation did not install alternate TSD.h")
- endif()
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.cxx")
- message(FATAL_ERROR "Directory installation installed alternate TSD.cxx")
- endif()
-
- # Check that scripts properly installed.
- if(WIN32 AND NOT CYGWIN)
- set(BAT .bat)
- else()
- set(BAT)
- endif()
- foreach(loc share share/old1 share/old2 share/old3 share/alt)
- set(CUR_SCRIPT "${CMAKE_INSTALL_PREFIX}/MyTest/${loc}/sample_script${BAT}")
- execute_process(
- COMMAND ${CUR_SCRIPT}
- RESULT_VARIABLE SAMPLE_SCRIPT_RESULT
- OUTPUT_VARIABLE SAMPLE_SCRIPT_OUTPUT
- )
- if(NOT "${SAMPLE_SCRIPT_RESULT}" STREQUAL "0")
- message(FATAL_ERROR
- "Sample script [${CUR_SCRIPT}] failed: [${SAMPLE_SCRIPT_RESULT}]")
- endif()
- if(NOT "${SAMPLE_SCRIPT_OUTPUT}" MATCHES "Sample Script Output")
- message(FATAL_ERROR
- "Bad sample script [${CUR_SCRIPT}] output: [${SAMPLE_SCRIPT_OUTPUT}]")
- endif()
- endforeach()
-
- # Check for failure of empty directory installation.
- if(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/empty")
- message(FATAL_ERROR "Empty directory installation did not install.")
- endif()
- file(GLOB EMPTY_FILES "${CMAKE_INSTALL_PREFIX}/MyTest/share/empty/*")
- if(EMPTY_FILES)
- message(FATAL_ERROR "Empty directory installed [${EMPTY_FILES}].")
- endif()
-
- # Make sure the test executable can run from the install tree.
- set_target_properties(SimpleInstExeS2 PROPERTIES
- INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
-
- install_targets(/MyTest/bin SimpleInstExeS2)
-
-# try to import the exported targets again
- set(SimpleInstallS1_DIR ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
- find_package(SimpleInstallS1 REQUIRED)
- get_target_property(simpleInstallImported S1_SimpleInstall IMPORTED)
- if(NOT simpleInstallImported)
- message(FATAL_ERROR "Target S1_SimpleInstall could not be imported")
- endif()
-
-else()
- # Wipe out the install directory to do a fresh test.
- file(REMOVE_RECURSE ${CMAKE_INSTALL_PREFIX}/MyTest)
-
- # this is stage 1, so create libraries and modules and install everything
- add_library(test1 STATIC lib1.cxx)
- add_library(test2 SHARED lib2.cxx)
- add_library(test3 MODULE lib3.cxx)
- add_library(test4 SHARED lib4.cxx)
-
- # Test <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME properties.
- set_property(TARGET test4 PROPERTY ARCHIVE_OUTPUT_NAME test4out)
- set_property(TARGET test4 PROPERTY LIBRARY_OUTPUT_NAME test4out)
-
- add_executable (SimpleInstall inst.cxx foo.c foo.h)
- target_link_libraries(SimpleInstall test1 test2 test4)
- set(install_target SimpleInstall)
-
- set_target_properties(SimpleInstall PROPERTIES OUTPUT_NAME SimpleInstExe)
- # Disable VERSION test until it is implemented in the Xcode generator.
- if(NOT XCODE)
- set_target_properties(SimpleInstall PROPERTIES VERSION 1.2)
- endif()
-
- # Make sure the test executable can run from the install tree.
- set_target_properties(SimpleInstall PROPERTIES
- INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/MyTest/lib)
-
- # Test per-configuration output name.
- set_target_properties(test1 PROPERTIES RELEASE_OUTPUT_NAME test1rel)
- set_target_properties(test2 PROPERTIES PUBLIC_HEADER foo.h)
-
- if(CMAKE_GENERATOR MATCHES "Makefiles")
- add_subdirectory(TestSubDir)
- add_dependencies(SimpleInstall TSD)
- endif()
-
- add_dependencies(SimpleInstall test3)
- add_dependencies(test2 test3)
- add_dependencies(test4 test2)
-
- install(TARGETS SimpleInstall test1 test2 test3 EXPORT SimpleInstallS1
- RUNTIME DESTINATION MyTest/bin COMPONENT Runtime # .exe, .dll
- LIBRARY DESTINATION MyTest/lib COMPONENT Runtime # .so, mod.dll
- ARCHIVE DESTINATION MyTest/lib/static COMPONENT Development # .a, .lib
- PUBLIC_HEADER DESTINATION MyTest/include COMPONENT Development
- )
-
- install(TARGETS test4 PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
- RUNTIME DESTINATION MyTest/bin
- LIBRARY DESTINATION MyTest/lib
- ARCHIVE DESTINATION MyTest/lib/static
- OPTIONAL # for coverage...target should always exist
- )
- install(FILES lib1.h DESTINATION MyTest/include/$<1:foo>$<0:/wrong>)
- install(FILES lib2.h
- DESTINATION $<1:MyTest/include/foo>$<0:/wrong>
- COMPONENT Development
- PERMISSIONS OWNER_READ OWNER_WRITE
- RENAME lib2renamed.h
- )
-
- # Test old-style install commands.
- install_files(/MyTest/include FILES lib3.h)
- install_files(/MyTest/include/old .h lib3)
- install_files(/MyTest/include/old "^lib2.h$")
- install_programs(/MyTest/share/old1 FILES
- scripts/sample_script scripts/sample_script.bat)
- install_programs(/MyTest/share/old2
- scripts/sample_script scripts/sample_script.bat)
-
-# "export" the targets collected in "SimpleInstallS1"
- install(EXPORT SimpleInstallS1 FILE SimpleInstallS1Config.cmake
- DESTINATION MyTest/lib
- NAMESPACE S1_ )
-
- export(TARGETS SimpleInstall test1 test2 test3
- FILE "${CMAKE_CURRENT_BINARY_DIR}/SimpleInstallS1Config.cmake"
- NAMESPACE S2_ )
-
- add_subdirectory(scripts)
-
- # Test optional installation.
- install(FILES does_not_exist.h DESTINATION MyTest/include/foo OPTIONAL)
-
- # Test configuration-specific installation.
- install(FILES lib1.h RENAME lib1release.h CONFIGURATIONS Release
- DESTINATION MyTest/include/Release
- )
- install(FILES lib1.h RENAME lib1debug.h CONFIGURATIONS Debug
- DESTINATION MyTest/include/Debug
- )
-
- # Test directory installation.
- file(REMOVE_RECURSE "${CMAKE_INSTALL_PREFIX}/MyTest/share/CVS")
- file(REMOVE_RECURSE "${CMAKE_INSTALL_PREFIX}/MyTest/share/TestSubDir/CVS")
- install(
- DIRECTORY TestSubDir $<1:scripts/>$<0:/wrong> DESTINATION $<1:MyTest/share>$<0:/wrong>
- FILE_PERMISSIONS OWNER_READ OWNER_WRITE
- DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
- GROUP_READ GROUP_EXECUTE
- PATTERN "CVS" EXCLUDE
- REGEX "\\.txt$" EXCLUDE
- PATTERN "scripts/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
- )
-
- # Alternate directory installation for coverage.
- install(
- DIRECTORY $<1:scripts/>$<0:/wrong> DESTINATION $<1:MyTest/share/alt>$<0:/wrong>
- COMPONENT Development
- USE_SOURCE_PERMISSIONS
- PATTERN "CVS" EXCLUDE
- REGEX "\\.txt$" EXCLUDE
- )
- install(
- DIRECTORY TestSubDir DESTINATION $<1:MyTest/share/alt>$<0:/wrong>
- FILE_PERMISSIONS OWNER_READ OWNER_WRITE
- DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
- GROUP_READ GROUP_EXECUTE
- FILES_MATCHING PATTERN "*.h"
- )
-
- # Test empty directory installation.
- install(DIRECTORY DESTINATION MyTest/share/empty)
-
- # Test optional directory installation.
- install(DIRECTORY does-not-exist DESTINATION MyTest/share OPTIONAL)
-
- # Test user-specified install scripts, with and without COMPONENT.
- install(
- SCRIPT InstallScript1.cmake
- CODE "set(INSTALL_CODE_DID_RUN 1)"
- SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/InstallScript2.cmake
- )
- install(
- SCRIPT InstallScript3.cmake
- CODE "set(INSTALL_CODE_WITH_COMPONENT_DID_RUN 1)"
- SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/InstallScript4.cmake
- COMPONENT Development
- )
- set_directory_properties(PROPERTIES
- ADDITIONAL_MAKE_CLEAN_FILES
- "${CMAKE_INSTALL_PREFIX}/InstallScriptOut.cmake;${CMAKE_INSTALL_PREFIX}/InstallScript4Out.cmake")
-
- set_target_properties(SimpleInstall PROPERTIES PRE_INSTALL_SCRIPT
- ${CMAKE_CURRENT_SOURCE_DIR}/PreInstall.cmake)
- set_target_properties(SimpleInstall PROPERTIES POST_INSTALL_SCRIPT
- ${CMAKE_CURRENT_SOURCE_DIR}/PostInstall.cmake)
- set_target_properties(test4 PROPERTIES VERSION 1.2 SOVERSION 3
- INSTALL_NAME_DIR @executable_path/../lib)
-endif()
-
-get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
-if(_isMultiConfig)
- set(SI_CONFIG --config $<CONFIGURATION>)
-else()
- set(SI_CONFIG)
-endif()
-
-# Dummy test of CPack
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Test of packaging with cpack")
-set(CPACK_PACKAGE_VENDOR "Kitware")
-set(CPACK_INSTALL_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/PackageScript.cmake")
-
-if(WIN32 AND NOT UNIX)
- find_program(NSIS_MAKENSIS NAMES makensis
- PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS]
- DOC "Where is makensis.exe located"
- )
- if(NOT NSIS_MAKENSIS)
- set(CPACK_GENERATOR TGZ)
- endif()
-endif()
-if(UNIX AND NOT APPLE)
- set(CPACK_GENERATOR "TGZ;STGZ;TZ")
- # find_program(found_compress
- # NAMES compress)
- # if(found_compress)
- # find_program(file_command NAMES file)
- # if(NOT file_command)
- # set(file_command file)
- # endif()
- # execute_process(COMMAND ${file_command} ${found_compress}
- # OUTPUT_VARIABLE output)
- # set(SKIP_TZ FALSE)
- # if("${output}" MATCHES "script")
- # set(SKIP_TZ TRUE)
- # endif()
- # if("${output}" MATCHES "dummy.sh")
- # set(SKIP_TZ TRUE)
- # endif()
- # if(NOT SKIP_TZ)
- # message("compress found and it was not a script")
- # message("output from file command: [${output}]")
- # list(APPEND CPACK_GENERATOR "TZ")
- # else()
- # message("compress found, but it was a script so don't use it")
- # message("output from file command: [${output}]")
- # endif()
- # endif()
- find_program(found_bz2
- NAMES bzip2)
- if(found_bz2)
- list(APPEND CPACK_GENERATOR "TBZ2")
- endif()
-endif()
-
-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)
-include(InstallRequiredSystemLibraries)
-
-if(CTEST_TEST_CPACK)
- set(package_command COMMAND
- ${CMAKE_COMMAND} --build . --target package ${SI_CONFIG}
- )
-
- # Avoid settings that require the .zip file command line tools...
- # (just build an NSIS installer without component support)
- #
- set(CPACK_BINARY_ZIP OFF)
- set(CPACK_MONOLITHIC_INSTALL ON)
-else()
- set(package_command)
-endif()
-
-include(CPack)
-
-set(install_command COMMAND
- ${CMAKE_COMMAND} --build . --target install ${SI_CONFIG}
- )
-
-add_custom_command(
- TARGET ${install_target}
- POST_BUILD
- ${install_command}
- ${package_command}
- COMMENT "Install Project"
- )
+++ /dev/null
-message("This is install script 1.")
-set(INSTALL_SCRIPT_1_DID_RUN 1)
-if(INSTALL_CODE_DID_RUN)
- message(FATAL_ERROR "Install script 1 did not run before install code.")
-endif()
+++ /dev/null
-message("This is install script 2.")
-if(INSTALL_SCRIPT_1_DID_RUN)
- message("Install script ordering works.")
-else()
- message(FATAL_ERROR "Install script 1 did not run before install script 2.")
-endif()
-if(INSTALL_CODE_DID_RUN)
- message("Install code ordering works.")
-else()
- message(FATAL_ERROR "Install script 2 did not run after install code.")
-endif()
-file(WRITE "${CMAKE_INSTALL_PREFIX}/MyTest/InstallScriptOut.cmake"
- "set(CMAKE_INSTALL_SCRIPT_DID_RUN 1)\n"
- )
+++ /dev/null
-message("This is install script 3.")
-set(INSTALL_SCRIPT_3_DID_RUN 1)
-if(INSTALL_CODE_WITH_COMPONENT_DID_RUN)
- message(FATAL_ERROR "Install script 3 did not run before install code with component.")
-endif()
-
-if(CMAKE_INSTALL_COMPONENT)
-if(NOT "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Development")
- message("CMAKE_INSTALL_COMPONENT=\"${CMAKE_INSTALL_COMPONENT}\"")
- message(FATAL_ERROR "Install script 3 should only run for \"Development\" INSTALL COMPONENT.")
-endif()
-endif()
+++ /dev/null
-message("This is install script 4.")
-if(INSTALL_SCRIPT_3_DID_RUN)
- message("Install script ordering works.")
-else()
- message(FATAL_ERROR "Install script 3 did not run before install script 4.")
-endif()
-if(INSTALL_CODE_WITH_COMPONENT_DID_RUN)
- message("Install code ordering works.")
-else()
- message(FATAL_ERROR "Install script 4 did not run after install with component code.")
-endif()
-
-if(CMAKE_INSTALL_COMPONENT)
-if(NOT "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Development")
- message("CMAKE_INSTALL_COMPONENT=\"${CMAKE_INSTALL_COMPONENT}\"")
- message(FATAL_ERROR "Install script 4 should only run for \"Development\" INSTALL COMPONENT.")
-endif()
-endif()
-
-file(WRITE "${CMAKE_INSTALL_PREFIX}/MyTest/InstallScript4Out.cmake"
- "set(CMAKE_INSTALL_SCRIPT_4_DID_RUN 1)\n"
- )
+++ /dev/null
-message("This is packaging script")
-message("It writes a file with all variables available in ${CMAKE_INSTALL_PREFIX}/AllVariables.txt")
-
-file(WRITE ${CMAKE_INSTALL_PREFIX}/AllVariables.txt "")
-get_cmake_property(res VARIABLES)
-foreach(var ${res})
- file(APPEND ${CMAKE_INSTALL_PREFIX}/AllVariables.txt
- "${var} \"${${var}}\"\n")
-endforeach()
-
+++ /dev/null
-message("In post install")
-if(PRE_INSTALL_DID_RUN)
- message("Pre and post install work fine")
-else()
- message(FATAL_ERROR "Pre install did not run before post install")
-endif()
+++ /dev/null
-message("This is in pre install")
-set(PRE_INSTALL_DID_RUN 1)
+++ /dev/null
-add_executable(TSD TSD.cxx TSD_utils.cxx)
-install_files(/MyTest/include FILES TSD.h)
-install_targets(/MyTest/bin TSD)
+++ /dev/null
-#include <stdio.h>
-
-#include "TSD.h"
-
-int main()
-{
- int res = TSD("TEST");
- printf("Hello from TSD\n");
- return res;
-}
+++ /dev/null
-int TSD(const char*);
+++ /dev/null
-#include <string.h>
-
-int TSD(const char* foo)
-{
- if (strcmp(foo, "TEST") == 0) {
- return 0;
- }
- return 1;
-}
+++ /dev/null
-char* foo = "Foo";
-
-int SomeFunctionInFoo()
-{
- return 5;
-}
+++ /dev/null
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern char* foo;
-extern int SomeFunctionInFoo();
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-#include "foo.h"
-
-#ifdef STAGE_2
-# include <foo/lib1.h>
-# include <foo/lib2renamed.h>
-# include <lib3.h>
-# include <old/lib2.h>
-# include <old/lib3.h>
-#else
-# include "lib1.h"
-# include "lib2.h"
-#endif
-
-#include "lib4.h"
-
-#include <stdio.h>
-
-int main()
-{
- if (Lib1Func() != 2.0) {
- printf("Problem with lib1\n");
- return 1;
- }
- if (Lib2Func() != 1.0) {
- printf("Problem with lib2\n");
- return 1;
- }
- if (Lib4Func() != 4.0) {
- printf("Problem with lib4\n");
- return 1;
- }
- printf("The value of Foo: %s\n", foo);
- return SomeFunctionInFoo() - 5;
-}
+++ /dev/null
-#define STAGE_2
-#include "inst.cxx"
+++ /dev/null
-#include "lib1.h"
-
-float Lib1Func()
-{
- return 2.0;
-}
+++ /dev/null
-extern float Lib1Func();
+++ /dev/null
-#include "lib2.h"
-
-float Lib2Func()
-{
- return 1.0;
-}
+++ /dev/null
-#ifdef _WIN32
-# ifdef test2_EXPORTS
-# define CM_TEST_LIB_EXPORT __declspec(dllexport)
-# else
-# define CM_TEST_LIB_EXPORT __declspec(dllimport)
-# endif
-#else
-# define CM_TEST_LIB_EXPORT
-#endif
-
-CM_TEST_LIB_EXPORT float Lib2Func();
+++ /dev/null
-#include "lib3.h"
-
-float Lib3Func()
-{
- return 2.0;
-}
+++ /dev/null
-#ifdef _WIN32
-# ifdef test3_EXPORTS
-# define CM_TEST_LIB_EXPORT __declspec(dllexport)
-# else
-# define CM_TEST_LIB_EXPORT __declspec(dllimport)
-# endif
-#else
-# define CM_TEST_LIB_EXPORT
-#endif
-
-CM_TEST_LIB_EXPORT float Lib3Func();
+++ /dev/null
-#include "lib4.h"
-
-float Lib4Func()
-{
- return 4.0;
-}
+++ /dev/null
-#ifdef _WIN32
-# ifdef test4_EXPORTS
-# define CM_TEST_LIB_EXPORT __declspec(dllexport)
-# else
-# define CM_TEST_LIB_EXPORT __declspec(dllimport)
-# endif
-#else
-# define CM_TEST_LIB_EXPORT
-#endif
-
-CM_TEST_LIB_EXPORT float Lib4Func();
+++ /dev/null
-install_programs(/MyTest/share/old3 "^sample_script(\\.bat)?$")
set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES})
endif()
-set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
unset(CMAKE_SWIG_FLAGS)
set (CMAKE_INCLUDE_CURRENT_DIR ON)
-cmake_minimum_required(VERSION 3.12)
+cmake_minimum_required(VERSION 3.12...3.13)
project(TestBasicCsharp CXX CSharp)
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1...3.13)
project(TestBasicPerl CXX)
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1...3.13)
project(TestBasicPython CXX)
--build-options ${build_options}
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
+
+
+add_test(NAME UseSWIG.UseTargetINCLUDE_DIRECTORIES COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/UseSWIG/UseTargetINCLUDE_DIRECTORIES"
+ "${CMake_BINARY_DIR}/Tests/UseSWIG/UseTargetINCLUDE_DIRECTORIES"
+ ${build_generator_args}
+ --build-project TestModuleVersion2
+ --build-options ${build_options}
+ )
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1...3.13)
project(TestModuleVersion2 CXX)
set (PS ":")
endif()
-set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
set (UseSWIG_MODULE_VERSION 2)
unset(CMAKE_SWIG_FLAGS)
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1...3.13)
project(TestMultipleModules CXX)
set (PS ":")
endif()
-set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
unset(CMAKE_SWIG_FLAGS)
set_property(SOURCE "../example.i" PROPERTY CPLUSPLUS ON)
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1...3.13)
project(TestMultiplePython CXX)
set (PS ":")
endif()
-set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
unset(CMAKE_SWIG_FLAGS)
set_property(SOURCE "../example.i" PROPERTY CPLUSPLUS ON)
--- /dev/null
+cmake_minimum_required(VERSION 3.1...3.13)
+
+project(TestUseTargetINCLUDE_DIRECTORIES CXX)
+
+include(CTest)
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+
+unset(CMAKE_SWIG_FLAGS)
+
+set_property(SOURCE "example.i" PROPERTY CPLUSPLUS ON)
+set_property(SOURCE "example.i" PROPERTY COMPILE_OPTIONS -includeall)
+
+swig_add_library(example1
+ LANGUAGE python
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/example1"
+ SOURCES example.i ../example.cxx)
+set_target_properties (example1 PROPERTIES
+ INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/.."
+ SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE
+ OUTPUT_NAME example1
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1")
+target_link_libraries(example1 PRIVATE Python3::Python)
+
+
+# Check that source property override target property
+set_property(SOURCE "example.i" PROPERTY USE_TARGET_INCLUDE_DIRECTORIES TRUE)
+
+swig_add_library(example2
+ LANGUAGE python
+ OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/example2"
+ SOURCES example.i ../example.cxx)
+set_target_properties (example2 PROPERTIES
+ INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/.."
+ SWIG_USE_TARGET_INCLUDE_DIRECTORIES FALSE
+ OUTPUT_NAME example2
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example2"
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example2"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example2")
+target_link_libraries(example2 PRIVATE Python3::Python)
--- /dev/null
+/* File : example.i */
+%module example
+
+%{
+#include "example.h"
+%}
+
+/* Let's just grab the original header file here */
+%include "example.h"
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()
+
+# Test quoting for definitions with spaces.
+add_definitions("-DEAX_COMMA_SPACE_ZERO=eax, 0")
+
+# Test quoting for file names with spaces. The file is generated because CMake
+# itself cannot have files with spaces.
+file(READ bar.asm BAR_ASM_CONTENTS)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/bar baz.asm" "${BAR_ASM_CONTENTS}")
+
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
-add_executable(VSNASM main.c foo.asm)
+add_executable(VSNASM main.c foo.asm "${CMAKE_CURRENT_BINARY_DIR}/bar baz.asm")
--- /dev/null
+section .text
+%ifdef TEST2x64
+global bar
+%else
+global _bar
+%endif
+%ifdef TESTx64
+bar:
+%else
+_bar:
+%endif
+ mov EAX_COMMA_SPACE_ZERO
+ ret
%else
_foo:
%endif
- mov eax, 0
+ mov EAX_COMMA_SPACE_ZERO
ret
extern int foo(void);
+extern int bar(void);
int main(void)
{
- return foo();
+ return foo() + bar();
}
#{ symbol: [ "std::pair", private, "<map>", public ] },
#{ symbol: [ "std::pair", private, "<set>", public ] },
+ # HACK: iwyu wrongly thinks that <system_error> is needed for std::hash
+ { symbol: [ "std::hash", private, "<functional>", public ] },
+
# __decay_and_strip is used internally in the C++11 standard library.
# IWYU does not classify it as internal and suggests to add <type_traits>.
# To ignore it, we simply map it to a file that is included anyway.
-DCMAKE_INSTALL_PREFIX=\"\$inst/\" \\
-DCMAKE_DOC_DIR=doc/cmake \\
-DSPHINX_EXECUTABLE=\"${SPHINX_EXECUTABLE}\" \\
- -DSPHINX_HTML=ON -DSPHINX_MAN=ON &&
+ -DSPHINX_HTML=ON -DSPHINX_MAN=ON -DSPHINX_QTHELP=ON &&
make install &&
cd .. &&
tar czf \${name}.tar.gz \${name} ||
set(HOST linux64)
set(MAKE_PROGRAM "make")
set(CPACK_BINARY_GENERATORS "STGZ TGZ")
-set(CC /opt/gcc-6.1.0/bin/gcc)
-set(CXX /opt/gcc-6.1.0/bin/g++)
+set(CC /opt/gcc-8.2.0/bin/gcc)
+set(CXX /opt/gcc-8.2.0/bin/g++)
set(CFLAGS "")
set(CXXFLAGS "")
set(qt_prefix "/home/kitware/qt-5.7.0")
OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.1.0h/lib/libssl.a
PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3
CPACK_SYSTEM_NAME:STRING=Linux-x86_64
+BUILD_CursesDialog:BOOL=ON
BUILD_QtDialog:BOOL=TRUE
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMAKE_PREFIX_PATH:STRING=${qt_prefix}
CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES:STRING=${qt_xcb_libs}
")
+set(ENV [[
+export CMAKE_PREFIX_PATH=/opt/binutils-2.31
+]])
# Exclude Qt5 tests because our Qt5 is static.
set(EXTRA_CTEST_ARGS "-E Qt5")
CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.7
CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CPACK_SYSTEM_NAME:STRING=Darwin-x86_64
+BUILD_CursesDialog:BOOL=ON
BUILD_QtDialog:BOOL=TRUE
CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
CMake_INSTALL_DEPENDENCIES:BOOL=ON
set(CTEST_RUN_CURRENT_SCRIPT 0)
if(NOT VERSION)
- set(VERSION 3.12)
+ set(VERSION 3.13)
endif()
if(NOT DEFINED PROJECT_PREFIX)
set(PROJECT_PREFIX cmake-${VERSION})
set(GIT_EXTRA "git config core.autocrlf true")
if(CMAKE_CREATE_VERSION STREQUAL "nightly")
# Some tests fail spuriously too often.
- set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf'")
+ set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf|Module.ExternalData'")
endif()
include(${path}/release_cmake.cmake)
set(GIT_EXTRA "git config core.autocrlf true")
if(CMAKE_CREATE_VERSION STREQUAL "nightly")
# Some tests fail spuriously too often.
- set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf'")
+ set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf|Module.ExternalData'")
endif()
include(${path}/release_cmake.cmake)
# Special-case since it is part of mpi; look only in boost/mpi/python*
if(component STREQUAL "mpi_python")
- set(_boost_DEPS "python")
+ set(_boost_DEPS "python\${component_python_version}")
set(library_component TRUE)
set(_boost_unprocessed_headers ${_boost_mpi_python_headers})
# Special-case since it is part of python; look only in boost/python/numpy*
elseif(component STREQUAL "numpy")
- set(_boost_DEPS "python")
+ set(_boost_DEPS "python\${component_python_version}")
set(library_component TRUE)
set(_boost_unprocessed_headers ${_boost_python_numpy_headers})
# Special-case since it is a serialization variant; look in boost/serialization
readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_60_0"
+readonly tag="curl-7_62_0"
readonly shortlog=false
readonly paths="
CMake/*
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
readonly subtree="Utilities/cmlibarchive"
readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="v3.3.2"
+readonly tag="v3.3.3"
readonly shortlog=false
readonly paths="
CMakeLists.txt
readonly name="liblzma"
readonly ownership="liblzma upstream <xz-devel@tukaani.org>"
readonly subtree="Utilities/cmliblzma"
-readonly repo="http://git.tukaani.org/xz.git"
-readonly tag="v5.0.8"
+readonly repo="https://git.tukaani.org/xz.git"
+readonly tag="v5.2.4"
readonly shortlog=false
readonly paths="
COPYING
mv src/common .
mv src/liblzma .
rmdir src
+ rm liblzma/Makefile.*
+ rm liblzma/*/Makefile.*
+ rm liblzma/liblzma.map
+ rm liblzma/validate_map.sh
popd
}
_cmake_index_objs = {
'command': _cmake_index_entry('command'),
+ 'cpack_gen': _cmake_index_entry('cpack generator'),
'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
'manual': _cmake_index_entry('manual'),
label = 'CMake'
object_types = {
'command': ObjType('command', 'command'),
+ 'cpack_gen': ObjType('cpack_gen', 'cpack_gen'),
'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
'variable': ObjType('variable', 'variable'),
}
roles = {
'command': CMakeXRefRole(fix_parens = True, lowercase = True),
+ 'cpack_gen': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
'variable': CMakeXRefRole(),
for line in lines:
mapping = (("command", "command"),
+ ("cpack generator", "cpack_gen"),
("envvar", "envvar"),
("variable", "variable"),
("generator", "generator"),
@CMAKE_CONFIGURABLE_FILE_CONTENT@
-
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
if(CURL_HIDDEN_SYMBOLS)
- set(SUPPORTS_SYMBOL_HIDING FALSE)
+ set(SUPPORTS_SYMBOL_HIDING FALSE)
- if(CMAKE_C_COMPILER_ID MATCHES "Clang")
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
- set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
- elseif(CMAKE_COMPILER_IS_GNUCC)
- if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
- set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
- else()
- execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
- OUTPUT_VARIABLE GCC_VERSION)
- endif()
- if(NOT GCC_VERSION VERSION_LESS 3.4)
- # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
- set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
- endif()
- elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__global")
- set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
- elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
- # note: this should probably just check for version 9.1.045 but I'm not 100% sure
- # so let's to it the same way autotools do.
- set(SUPPORTS_SYMBOL_HIDING TRUE)
- set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
- set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
- check_c_source_compiles("#include <stdio.h>
- int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
- if(NOT _no_bug)
- set(SUPPORTS_SYMBOL_HIDING FALSE)
- set(_SYMBOL_EXTERN "")
- set(_CFLAG_SYMBOLS_HIDE "")
- endif()
- elseif(MSVC)
- set(SUPPORTS_SYMBOL_HIDING TRUE)
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+ elseif(CMAKE_COMPILER_IS_GNUCC)
+ if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
+ set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
+ else()
+ execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+ endif()
+ if(NOT GCC_VERSION VERSION_LESS 3.4)
+ # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
endif()
+ elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__global")
+ set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
+ elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
+ # note: this should probably just check for version 9.1.045 but I'm not 100% sure
+ # so let's to it the same way autotools do.
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+ set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+ check_c_source_compiles("#include <stdio.h>
+ int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
+ if(NOT _no_bug)
+ set(SUPPORTS_SYMBOL_HIDING FALSE)
+ set(_SYMBOL_EXTERN "")
+ set(_CFLAG_SYMBOLS_HIDE "")
+ endif()
+ elseif(MSVC)
+ set(SUPPORTS_SYMBOL_HIDING TRUE)
+ endif()
- set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
+ set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
elseif(MSVC)
- if(NOT CMAKE_VERSION VERSION_LESS 3.7)
- set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
- set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
- else()
- message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
- set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
- endif()
-elseif()
+ if(NOT CMAKE_VERSION VERSION_LESS 3.7)
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
+ else()
+ message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
+ set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
+ endif()
+elseif()
+ set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
endif()
set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE})
#ifdef HAVE_GLIBC_STRERROR_R
#include <string.h>
#include <errno.h>
+
+void check(char c) {}
+
int
main () {
- char buffer[1024]; /* big enough to play with */
- char *string =
- strerror_r(EACCES, buffer, sizeof(buffer));
- /* this should've returned a string */
- if(!string || !string[0])
- return 99;
- return 0;
+ char buffer[1024];
+ /* This will not compile if strerror_r does not return a char* */
+ check(strerror_r(EACCES, buffer, sizeof(buffer))[0]);
+ return 0;
}
#endif
#ifdef HAVE_POSIX_STRERROR_R
#include <string.h>
#include <errno.h>
+
+/* float, because a pointer can't be implicitly cast to float */
+void check(float f) {}
+
int
main () {
- char buffer[1024]; /* big enough to play with */
- int error =
- strerror_r(EACCES, buffer, sizeof(buffer));
- /* This should've returned zero, and written an error string in the
- buffer.*/
- if(!buffer[0] || error)
- return 99;
- return 0;
+ char buffer[1024];
+ /* This will not compile if strerror_r does not return an int */
+ check(strerror_r(EACCES, buffer, sizeof(buffer)));
+ return 0;
}
#endif
#ifdef HAVE_FSETXATTR_6
return 0;
}
#endif
+#ifdef HAVE_CLOCK_GETTIME_MONOTONIC
+#include <time.h>
+int
+main() {
+ struct timespec ts = {0, 0};
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return 0;
+}
+#endif
+#ifdef HAVE_BUILTIN_AVAILABLE
+int
+main() {
+ if(__builtin_available(macOS 10.12, *)) {}
+ return 0;
+}
+#endif
# also defined, but not for general use are
# CARES_LIBRARY, where to find the c-ares library.
-FIND_PATH(CARES_INCLUDE_DIR ares.h
+find_path(CARES_INCLUDE_DIR ares.h
/usr/local/include
/usr/include
)
-SET(CARES_NAMES ${CARES_NAMES} cares)
-FIND_LIBRARY(CARES_LIBRARY
+set(CARES_NAMES ${CARES_NAMES} cares)
+find_library(CARES_LIBRARY
NAMES ${CARES_NAMES}
PATHS /usr/lib /usr/local/lib
)
-IF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
- SET(CARES_LIBRARIES ${CARES_LIBRARY})
- SET(CARES_FOUND "YES")
-ELSE (CARES_LIBRARY AND CARES_INCLUDE_DIR)
- SET(CARES_FOUND "NO")
-ENDIF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
+if(CARES_LIBRARY AND CARES_INCLUDE_DIR)
+ set(CARES_LIBRARIES ${CARES_LIBRARY})
+ set(CARES_FOUND "YES")
+else()
+ set(CARES_FOUND "NO")
+endif()
-IF (CARES_FOUND)
- IF (NOT CARES_FIND_QUIETLY)
- MESSAGE(STATUS "Found c-ares: ${CARES_LIBRARIES}")
- ENDIF (NOT CARES_FIND_QUIETLY)
-ELSE (CARES_FOUND)
- IF (CARES_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find c-ares library")
- ENDIF (CARES_FIND_REQUIRED)
-ENDIF (CARES_FOUND)
+if(CARES_FOUND)
+ if(NOT CARES_FIND_QUIETLY)
+ message(STATUS "Found c-ares: ${CARES_LIBRARIES}")
+ endif()
+else()
+ if(CARES_FIND_REQUIRED)
+ message(FATAL_ERROR "Could not find c-ares library")
+ endif()
+endif()
-MARK_AS_ADVANCED(
+mark_as_advanced(
CARES_LIBRARY
CARES_INCLUDE_DIR
)
# try to find library using system pkg-config if user didn't specify root dir
if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
- if(UNIX)
- find_package(PkgConfig QUIET)
- pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
- list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
- elseif(WIN32)
- list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
- endif()
+ if(UNIX)
+ find_package(PkgConfig QUIET)
+ pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
+ list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
+ elseif(WIN32)
+ list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
+ endif()
endif()
if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach.
- find_file(_GSS_CONFIGURE_SCRIPT
- NAMES
- "krb5-config"
- HINTS
- ${_GSS_ROOT_HINTS}
- PATH_SUFFIXES
- bin
- NO_CMAKE_PATH
- NO_CMAKE_ENVIRONMENT_PATH
+ find_file(_GSS_CONFIGURE_SCRIPT
+ NAMES
+ "krb5-config"
+ HINTS
+ ${_GSS_ROOT_HINTS}
+ PATH_SUFFIXES
+ bin
+ NO_CMAKE_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ )
+
+ # if not found in user-supplied directories, maybe system knows better
+ find_file(_GSS_CONFIGURE_SCRIPT
+ NAMES
+ "krb5-config"
+ PATH_SUFFIXES
+ bin
+ )
+
+ if(_GSS_CONFIGURE_SCRIPT)
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
+ OUTPUT_VARIABLE _GSS_CFLAGS
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+ )
+ message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
+ if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+ # should also work in an odd case when multiple directories are given
+ string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
+ string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
+ string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
+
+ foreach(_flag ${_GSS_CFLAGS})
+ if(_flag MATCHES "^-I.*")
+ string(REGEX REPLACE "^-I" "" _val "${_flag}")
+ list(APPEND _GSS_INCLUDE_DIR "${_val}")
+ else()
+ list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
+ endif()
+ endforeach()
+ endif()
+
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
+ OUTPUT_VARIABLE _GSS_LIB_FLAGS
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
+ message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
+
+ if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+ # this script gives us libraries and link directories. Blah. We have to deal with it.
+ string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
+ string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+ string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+
+ foreach(_flag ${_GSS_LIB_FLAGS})
+ if(_flag MATCHES "^-l.*")
+ string(REGEX REPLACE "^-l" "" _val "${_flag}")
+ list(APPEND _GSS_LIBRARIES "${_val}")
+ elseif(_flag MATCHES "^-L.*")
+ string(REGEX REPLACE "^-L" "" _val "${_flag}")
+ list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
+ else()
+ list(APPEND _GSS_LINKER_FLAGS "${_flag}")
+ endif()
+ endforeach()
+ endif()
- # if not found in user-supplied directories, maybe system knows better
- find_file(_GSS_CONFIGURE_SCRIPT
- NAMES
- "krb5-config"
- PATH_SUFFIXES
- bin
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
+ OUTPUT_VARIABLE _GSS_VERSION
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
)
- if(_GSS_CONFIGURE_SCRIPT)
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
- OUTPUT_VARIABLE _GSS_CFLAGS
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
-message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
- if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
- # should also work in an odd case when multiple directories are given
- string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
- string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
- string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
-
- foreach(_flag ${_GSS_CFLAGS})
- if(_flag MATCHES "^-I.*")
- string(REGEX REPLACE "^-I" "" _val "${_flag}")
- list(APPEND _GSS_INCLUDE_DIR "${_val}")
- else()
- list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
- endif()
- endforeach()
- endif()
+ # older versions may not have the "--version" parameter. In this case we just don't care.
+ if(_GSS_CONFIGURE_FAILED)
+ set(_GSS_VERSION 0)
+ endif()
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
- OUTPUT_VARIABLE _GSS_LIB_FLAGS
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
-message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
- if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
- # this script gives us libraries and link directories. Blah. We have to deal with it.
- string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
- string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
- string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
-
- foreach(_flag ${_GSS_LIB_FLAGS})
- if(_flag MATCHES "^-l.*")
- string(REGEX REPLACE "^-l" "" _val "${_flag}")
- list(APPEND _GSS_LIBRARIES "${_val}")
- elseif(_flag MATCHES "^-L.*")
- string(REGEX REPLACE "^-L" "" _val "${_flag}")
- list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
- else()
- list(APPEND _GSS_LINKER_FLAGS "${_flag}")
- endif()
- endforeach()
- endif()
+ execute_process(
+ COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
+ OUTPUT_VARIABLE _GSS_VENDOR
+ RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+ )
+ # older versions may not have the "--vendor" parameter. In this case we just don't care.
+ if(_GSS_CONFIGURE_FAILED)
+ set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
+ else()
+ if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
+ set(GSS_FLAVOUR "Heimdal")
+ else()
+ set(GSS_FLAVOUR "MIT")
+ endif()
+ endif()
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
- OUTPUT_VARIABLE _GSS_VERSION
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
+ else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
- # older versions may not have the "--version" parameter. In this case we just don't care.
- if(_GSS_CONFIGURE_FAILED)
- set(_GSS_VERSION 0)
- endif()
+ find_path(_GSS_INCLUDE_DIR
+ NAMES
+ "gssapi/gssapi.h"
+ HINTS
+ ${_GSS_ROOT_HINTS}
+ PATH_SUFFIXES
+ include
+ inc
+ )
+ if(_GSS_INCLUDE_DIR) #jay, we've found something
+ set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
+ check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
- execute_process(
- COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
- OUTPUT_VARIABLE _GSS_VENDOR
- RESULT_VARIABLE _GSS_CONFIGURE_FAILED
- )
+ if(_GSS_HAVE_MIT_HEADERS)
+ set(GSS_FLAVOUR "MIT")
+ else()
+ # prevent compiling the header - just check if we can include it
+ set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
+ check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
+
+ check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
+ if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
+ set(GSS_FLAVOUR "Heimdal")
+ endif()
+ set(CMAKE_REQUIRED_DEFINITIONS "")
+ endif()
+ else()
+ # I'm not convienced if this is the right way but this is what autotools do at the moment
+ find_path(_GSS_INCLUDE_DIR
+ NAMES
+ "gssapi.h"
+ HINTS
+ ${_GSS_ROOT_HINTS}
+ PATH_SUFFIXES
+ include
+ inc
+ )
+
+ if(_GSS_INCLUDE_DIR)
+ set(GSS_FLAVOUR "Heimdal")
+ endif()
+ endif()
+
+ # if we have headers, check if we can link libraries
+ if(GSS_FLAVOUR)
+ set(_GSS_LIBDIR_SUFFIXES "")
+ set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
+ get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
+ list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
- # older versions may not have the "--vendor" parameter. In this case we just don't care.
- if(_GSS_CONFIGURE_FAILED)
- set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
+ if(WIN32)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
+ if(GSS_FLAVOUR STREQUAL "MIT")
+ set(_GSS_LIBNAME "gssapi64")
+ else()
+ set(_GSS_LIBNAME "libgssapi")
+ endif()
else()
- if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
- set(GSS_FLAVOUR "Heimdal")
- else()
- set(GSS_FLAVOUR "MIT")
- endif()
+ list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
+ if(GSS_FLAVOUR STREQUAL "MIT")
+ set(_GSS_LIBNAME "gssapi32")
+ else()
+ set(_GSS_LIBNAME "libgssapi")
+ endif()
endif()
-
- else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
-
- find_path(_GSS_INCLUDE_DIR
- NAMES
- "gssapi/gssapi.h"
- HINTS
- ${_GSS_ROOT_HINTS}
- PATH_SUFFIXES
- include
- inc
- )
-
- if(_GSS_INCLUDE_DIR) #jay, we've found something
- set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
- check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
-
- if(_GSS_HAVE_MIT_HEADERS)
- set(GSS_FLAVOUR "MIT")
- else()
- # prevent compiling the header - just check if we can include it
- set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
- check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
-
- check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
- if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
- set(GSS_FLAVOUR "Heimdal")
- endif()
- set(CMAKE_REQUIRED_DEFINITIONS "")
- endif()
+ else()
+ list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
+ if(GSS_FLAVOUR STREQUAL "MIT")
+ set(_GSS_LIBNAME "gssapi_krb5")
else()
- # I'm not convienced if this is the right way but this is what autotools do at the moment
- find_path(_GSS_INCLUDE_DIR
- NAMES
- "gssapi.h"
- HINTS
- ${_GSS_ROOT_HINTS}
- PATH_SUFFIXES
- include
- inc
- )
-
- if(_GSS_INCLUDE_DIR)
- set(GSS_FLAVOUR "Heimdal")
- endif()
+ set(_GSS_LIBNAME "gssapi")
endif()
+ endif()
- # if we have headers, check if we can link libraries
- if(GSS_FLAVOUR)
- set(_GSS_LIBDIR_SUFFIXES "")
- set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
- get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
- list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
-
- if(WIN32)
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
- if(GSS_FLAVOUR STREQUAL "MIT")
- set(_GSS_LIBNAME "gssapi64")
- else()
- set(_GSS_LIBNAME "libgssapi")
- endif()
- else()
- list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
- if(GSS_FLAVOUR STREQUAL "MIT")
- set(_GSS_LIBNAME "gssapi32")
- else()
- set(_GSS_LIBNAME "libgssapi")
- endif()
- endif()
- else()
- list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
- if(GSS_FLAVOUR STREQUAL "MIT")
- set(_GSS_LIBNAME "gssapi_krb5")
- else()
- set(_GSS_LIBNAME "gssapi")
- endif()
- endif()
-
- find_library(_GSS_LIBRARIES
- NAMES
- ${_GSS_LIBNAME}
- HINTS
- ${_GSS_LIBDIR_HINTS}
- PATH_SUFFIXES
- ${_GSS_LIBDIR_SUFFIXES}
- )
-
- endif()
+ find_library(_GSS_LIBRARIES
+ NAMES
+ ${_GSS_LIBNAME}
+ HINTS
+ ${_GSS_LIBDIR_HINTS}
+ PATH_SUFFIXES
+ ${_GSS_LIBDIR_SUFFIXES}
+ )
endif()
+ endif()
else()
- if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
- set(GSS_FLAVOUR "MIT")
- set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
- else()
- set(GSS_FLAVOUR "Heimdal")
- set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
- endif()
+ if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
+ set(GSS_FLAVOUR "MIT")
+ set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
+ else()
+ set(GSS_FLAVOUR "Heimdal")
+ set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
+ endif()
endif()
set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR})
set(GSS_VERSION ${_GSS_VERSION})
if(GSS_FLAVOUR)
+ if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
+ else()
+ set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
+ endif()
- if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
- else()
- set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
- endif()
-
- if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
- file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
- REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
+ if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
+ file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
+ REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
- string(REGEX MATCH "[0-9]\\.[^\"]+"
- GSS_VERSION "${heimdal_version_str}")
- endif()
+ string(REGEX MATCH "[0-9]\\.[^\"]+"
+ GSS_VERSION "${heimdal_version_str}")
+ endif()
- if(NOT GSS_VERSION)
- set(GSS_VERSION "Heimdal Unknown")
- endif()
- elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
- get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
- if(WIN32 AND _MIT_VERSION)
- set(GSS_VERSION "${_MIT_VERSION}")
- else()
- set(GSS_VERSION "MIT Unknown")
- endif()
+ if(NOT GSS_VERSION)
+ set(GSS_VERSION "Heimdal Unknown")
endif()
+ elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
+ get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
+ if(WIN32 AND _MIT_VERSION)
+ set(GSS_VERSION "${_MIT_VERSION}")
+ else()
+ set(GSS_VERSION "MIT Unknown")
+ endif()
+ endif()
endif()
-
include(FindPackageHandleStandardArgs)
set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR)
# LIBSSH2_INCLUDE_DIR - the libssh2 include directory
# LIBSSH2_LIBRARY - the libssh2 library name
-if (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
+if(LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
set(LibSSH2_FIND_QUIETLY TRUE)
-endif (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
+endif()
-FIND_PATH(LIBSSH2_INCLUDE_DIR libssh2.h
+find_path(LIBSSH2_INCLUDE_DIR libssh2.h
)
-FIND_LIBRARY(LIBSSH2_LIBRARY NAMES ssh2
+find_library(LIBSSH2_LIBRARY NAMES ssh2
)
if(LIBSSH2_INCLUDE_DIR)
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_PATCH "${LIBSSH2_VERSION_PATCH}")
set(LIBSSH2_VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}")
-endif(LIBSSH2_INCLUDE_DIR)
+endif()
include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
+find_package_handle_standard_args(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
-MARK_AS_ADVANCED(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
+mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
"Could NOT find NGHTTP2"
)
-set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR} )
+set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
# multiple times with a sequence of possibly dependent libraries in
# order of least-to-most-dependent. Some libraries depend on others
# to link correctly.
-macro(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE)
+macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE)
check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
${VARIABLE})
if(${VARIABLE})
set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
- endif(${VARIABLE})
-endmacro(CHECK_LIBRARY_EXISTS_CONCAT)
+ endif()
+endmacro()
# Check if header file exists and add it to the list.
# This macro is intended to be called multiple times with a sequence of
# possibly dependent header files. Some headers depend on others to be
# compiled correctly.
-macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
+macro(check_include_file_concat FILE VARIABLE)
check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE})
if(${VARIABLE})
set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}")
- endif(${VARIABLE})
-endmacro(CHECK_INCLUDE_FILE_CONCAT)
+ endif()
+endmacro()
# For other curl specific tests, use this macro.
-macro(CURL_INTERNAL_TEST CURL_TEST)
+macro(curl_internal_test CURL_TEST)
if(NOT DEFINED "${CURL_TEST}")
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LIBRARIES)
set(CURL_TEST_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
- endif(CMAKE_REQUIRED_LIBRARIES)
+ endif()
message(STATUS "Performing Curl Test ${CURL_TEST}")
try_compile(${CURL_TEST}
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing Curl Test ${CURL_TEST} passed with the following output:\n"
"${OUTPUT}\n")
- else(${CURL_TEST})
+ else()
message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
"${OUTPUT}\n")
- endif(${CURL_TEST})
- endif()
-endmacro(CURL_INTERNAL_TEST)
-
-macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
- if(NOT DEFINED "${CURL_TEST}_COMPILE")
- set(MACRO_CHECK_FUNCTION_DEFINITIONS
- "-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
- if(CMAKE_REQUIRED_LIBRARIES)
- set(CURL_TEST_ADD_LIBRARIES
- "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
- endif(CMAKE_REQUIRED_LIBRARIES)
-
- message(STATUS "Performing Curl Test ${CURL_TEST}")
- try_run(${CURL_TEST} ${CURL_TEST}_COMPILE
- ${CMAKE_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
- CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
- "${CURL_TEST_ADD_LIBRARIES}"
- OUTPUT_VARIABLE OUTPUT)
- if(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
- set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
- message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
- else(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
- message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
- set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
- file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
- "Performing Curl Test ${CURL_TEST} failed with the following output:\n"
- "${OUTPUT}")
- if(${CURL_TEST}_COMPILE)
- file(APPEND
- "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
- "There was a problem running this test\n")
- endif(${CURL_TEST}_COMPILE)
- file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
- "\n\n")
- endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
+ endif()
endif()
-endmacro(CURL_INTERNAL_TEST_RUN)
+endmacro()
-macro(CURL_NROFF_CHECK)
+macro(curl_nroff_check)
find_program(NROFF NAMES gnroff nroff)
if(NROFF)
# Need a way to write to stdin, this will do
else()
message(WARNING "Found no *nroff program")
endif()
-endmacro(CURL_NROFF_CHECK)
+endmacro()
macro(add_header_include check header)
if(${check})
set(_source_epilogue "${_source_epilogue}\n#include <${header}>")
- endif(${check})
-endmacro(add_header_include)
+ endif()
+endmacro()
set(signature_call_conv)
if(HAVE_WINDOWS_H)
if(HAVE_LIBWS2_32)
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
endif()
-else(HAVE_WINDOWS_H)
+else()
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
-endif(HAVE_WINDOWS_H)
+endif()
check_c_source_compiles("${_source_epilogue}
int main(void) {
set(RECV_TYPE_RETV "${recv_retv}")
set(HAVE_RECV 1)
set(curl_cv_func_recv_done 1)
- endif(curl_cv_func_recv_test)
- endif(NOT curl_cv_func_recv_done)
- endforeach(recv_arg4)
- endforeach(recv_arg3)
- endforeach(recv_arg2)
- endforeach(recv_arg1)
- endforeach(recv_retv)
+ endif()
+ endif()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
if("${curl_cv_func_recv_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for recv args")
- endif("${curl_cv_func_recv_args}" STREQUAL "unknown")
-else(curl_cv_recv)
+ endif()
+else()
message(FATAL_ERROR "Unable to link function recv")
-endif(curl_cv_recv)
+endif()
set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
set(HAVE_RECV 1)
set(SEND_TYPE_RETV "${send_retv}")
set(HAVE_SEND 1)
set(curl_cv_func_send_done 1)
- endif(curl_cv_func_send_test)
- endif(NOT curl_cv_func_send_done)
- endforeach(send_arg4)
- endforeach(send_arg3)
- endforeach(send_arg2)
- endforeach(send_arg1)
- endforeach(send_retv)
+ endif()
+ endif()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
+ endforeach()
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
if("${curl_cv_func_send_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for send args")
- endif("${curl_cv_func_send_args}" STREQUAL "unknown")
+ endif()
set(SEND_QUAL_ARG2 "const")
-else(curl_cv_send)
+else()
message(FATAL_ERROR "Unable to link function send")
-endif(curl_cv_send)
+endif()
set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
set(HAVE_SEND 1)
set(CMAKE_REQUIRED_FLAGS)
if(HAVE_SYS_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
- endif(HAVE_SYS_POLL_H)
+ endif()
check_c_source_runs("
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
if(HAVE_SIGNAL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H")
set(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
-endif(HAVE_SIGNAL_H)
+endif()
check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T)
if(HAVE_SIZEOF_SIG_ATOMIC_T)
check_c_source_compiles("
}" HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
set(HAVE_SIG_ATOMIC_T_VOLATILE 1)
- endif(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
-endif(HAVE_SIZEOF_SIG_ATOMIC_T)
+ endif()
+endif()
if(HAVE_WINDOWS_H)
set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
set(CMAKE_EXTRA_INCLUDE_FILES)
if(HAVE_SYS_SOCKET_H)
set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
- endif(HAVE_SYS_SOCKET_H)
+ endif()
endif()
check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
-endif(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
-
+endif()
set(HAVE_SIGACTION 0)
set(HAVE_MACRO_SIGSETJMP 0)
- else(WIN32)
+ else()
message("This file should be included on Windows platform only")
- endif(WIN32)
-endif(NOT UNIX)
-
+ endif()
+endif()
# File containing various utilities
-# Converts a CMake list to a string containing elements separated by spaces
-function(TO_LIST_SPACES _LIST_NAME OUTPUT_VAR)
- set(NEW_LIST_SPACE)
- foreach(ITEM ${${_LIST_NAME}})
- set(NEW_LIST_SPACE "${NEW_LIST_SPACE} ${ITEM}")
- endforeach()
- string(STRIP ${NEW_LIST_SPACE} NEW_LIST_SPACE)
- set(${OUTPUT_VAR} "${NEW_LIST_SPACE}" PARENT_SCOPE)
-endfunction()
-
-# Appends a lis of item to a string which is a space-separated list, if they don't already exist.
-function(LIST_SPACES_APPEND_ONCE LIST_NAME)
- string(REPLACE " " ";" _LIST ${${LIST_NAME}})
- list(APPEND _LIST ${ARGN})
- list(REMOVE_DUPLICATES _LIST)
- to_list_spaces(_LIST NEW_LIST_SPACE)
- set(${LIST_NAME} "${NEW_LIST_SPACE}" PARENT_SCOPE)
-endfunction()
-
-# Convenience function that does the same as LIST(FIND ...) but with a TRUE/FALSE return value.
-# Ex: IN_STR_LIST(MY_LIST "Searched item" WAS_FOUND)
-function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL)
- list(FIND ${LIST_NAME} ${ITEM_SEARCHED} FIND_POS)
- if(${FIND_POS} EQUAL -1)
- set(${RETVAL} FALSE PARENT_SCOPE)
- else()
- 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})
+function(count_true output_count_var)
+ set(lst)
foreach(option_var IN LISTS ARGN)
if(${option_var})
- list(APPEND ${output_var} ${option_var})
+ list(APPEND lst ${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)
+ list(LENGTH lst lst_len)
+ set(${output_count_var} ${lst_len} PARENT_SCOPE)
endfunction()
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
-endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+endif()
-if (NOT DEFINED CMAKE_INSTALL_PREFIX)
- set (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
-endif ()
- message(${CMAKE_INSTALL_PREFIX})
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
+endif()
+message(${CMAKE_INSTALL_PREFIX})
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
- endif(NOT "${rm_retval}" STREQUAL 0)
- else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ endif()
+ else()
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
- endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
-endforeach(file)
+ endif()
+endforeach()
+++ /dev/null
-
-get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-if(NOT CURL_FIND_COMPONENTS)
- set(CURL_FIND_COMPONENTS curl libcurl)
- if(CURL_FIND_REQUIRED)
- set(CURL_FIND_REQUIRED_curl TRUE)
- set(CURL_FIND_REQUIRED_libcurl TRUE)
- endif()
-endif()
-
-set(_curl_missing_components)
-foreach(_comp ${CURL_FIND_COMPONENTS})
- if(EXISTS "${_DIR}/${_comp}-target.cmake")
- include("${_DIR}/${_comp}-target.cmake")
- set(CURL_${_comp}_FOUND TRUE)
- else()
- set(CURL_${_comp}_FOUND FALSE)
- if(CURL_FIND_REQUIRED_${_comp})
- set(CURL_FOUND FALSE)
- list(APPEND _curl_missing_components ${_comp})
- endif()
- endif()
-endforeach()
-
-if(_curl_missing_components)
- set(CURL_NOT_FOUND_MESSAGE "Following required components not found: " ${_curl_missing_components})
-else()
- if(TARGET CURL::libcurl)
- string(TOUPPER "${CMAKE_BUILD_TYPE}" _curl_current_config)
- if(NOT _curl_current_config)
- set(_curl_current_config "NOCONFIG")
- endif()
- get_target_property(_curl_configurations CURL::libcurl IMPORTED_CONFIGURATIONS)
- list(FIND _curl_configurations "${_curl_current_config}" _i)
- if(_i LESS 0)
- set(_curl_config "RELEASE")
- list(FIND _curl_configurations "${_curl_current_config}" _i)
- if(_i LESS 0)
- set(_curl_config "NOCONFIG")
- list(FIND _curl_configurations "${_curl_current_config}" _i)
- endif()
- endif()
-
- if(_i LESS 0)
- set(_curl_current_config "") # let CMake pick config at random
- else()
- set(_curl_current_config "_${_curl_current_config}")
- endif()
-
- get_target_property(CURL_INCLUDE_DIRS CURL::libcurl INTERFACE_INCLUDE_DIRECTORIES)
- get_target_property(CURL_LIBRARIES CURL::libcurl "LOCATION${_curl_current_config}")
- set(_curl_current_config)
- set(_curl_configurations)
- set(_i)
- endif()
-endif()
-
-unset(_curl_missing_components)
--- /dev/null
+@PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+if(@USE_OPENSSL@)
+ find_dependency(OpenSSL @OPENSSL_VERSION_MAJOR@)
+endif()
+if(@USE_ZLIB@)
+ find_dependency(ZLIB @ZLIB_VERSION_MAJOR@)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
+check_required_components("@PROJECT_NAME@")
set(BUILD_CURL_EXE OFF CACHE INTERNAL "No curl exe")
set(BUILD_DASHBOARD_REPORTS OFF CACHE INTERNAL "No curl dashboard reports")
set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs")
+set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries")
set(CMAKE_USE_GSSAPI OFF CACHE INTERNAL "Disable curl gssapi")
set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2")
set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP")
set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols")
-set(CURL_STATICLIB ON CACHE INTERNAL "Static curl")
set(CURL_WERROR OFF CACHE INTERNAL "Turn compiler warnings into errors")
set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions")
set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support")
# To check:
# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
-cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
include(Macros)
include(CMakeDependentOption)
include(CheckCCompilerFlag)
-project( CURL C )
+project(CURL C)
if(0) # This code not needed for building within CMake.
message(WARNING "the curl cmake build system is poorly maintained. Be aware")
endif()
-file (READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
-string (REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
+file(READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
+string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
CURL_VERSION ${CURL_VERSION_H_CONTENTS})
-string (REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
-string (REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
+string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
+string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
-string (REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
+string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
include_regular_expression("^.*$") # Sukender: Is it necessary?
set(OS "\"${CMAKE_SYSTEM_NAME}\"")
include_directories(${PROJECT_BINARY_DIR}/include/curl)
-include_directories( ${CURL_SOURCE_DIR}/include )
+include_directories(${CURL_SOURCE_DIR}/include)
option(CURL_WERROR "Turn compiler warnings into errors" OFF)
option(PICKY_COMPILER "Enable picky compiler options" ON)
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
-option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
endif()
-CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
+cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
ON "NOT ENABLE_ARES"
OFF)
option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
- if (PICKY_COMPILER)
- foreach (_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers)
+ if(PICKY_COMPILER)
+ foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format)
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
# test result in.
- CHECK_C_COMPILER_FLAG(${_CCOPT} OPT${_CCOPT})
+ check_c_compiler_flag(${_CCOPT} OPT${_CCOPT})
if(OPT${_CCOPT})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
endif()
endforeach()
- endif(PICKY_COMPILER)
-endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+ endif()
+endif()
-if (ENABLE_DEBUG)
+if(ENABLE_DEBUG)
# DEBUGBUILD will be defined only for Debug builds
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
set(ENABLE_CURLDEBUG ON)
endif()
-if (ENABLE_CURLDEBUG)
+if(ENABLE_CURLDEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG)
endif()
if(0) # This code not needed for building within CMake.
# For debug libs and exes, add "-d" postfix
-set(CMAKE_DEBUG_POSTFIX "-d" CACHE STRING "Set debug library postfix")
+if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
+ set(CMAKE_DEBUG_POSTFIX "-d")
+endif()
endif()
# initialize CURL_LIBS
if(ENABLE_ARES)
set(USE_ARES 1)
find_package(CARES REQUIRED)
- list(APPEND CURL_LIBS ${CARES_LIBRARY} )
+ list(APPEND CURL_LIBS ${CARES_LIBRARY})
set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY})
endif()
endif()
if(0) # This code not needed for building within CMake.
-CURL_NROFF_CHECK()
# Required for building manual, docs, tests
+curl_nroff_check()
find_package(Perl)
-CMAKE_DEPENDENT_OPTION(ENABLE_MANUAL "to provide the built-in manual"
+cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual"
ON "NROFF_USEFUL;PERL_FOUND"
OFF)
# Disable warnings on Borland to avoid changing 3rd party code.
if(BORLAND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
-endif(BORLAND)
+endif()
# If we are on AIX, do the _ALL_SOURCE magic
if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
set(_ALL_SOURCE 1)
-endif(${CMAKE_SYSTEM_NAME} MATCHES AIX)
+endif()
# Include all the necessary files for macros
-include (CheckFunctionExists)
-include (CheckIncludeFile)
-include (CheckIncludeFiles)
-include (CheckLibraryExists)
-include (CheckSymbolExists)
-include (CheckTypeSize)
-include (CheckCSourceCompiles)
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckIncludeFiles)
+include(CheckLibraryExists)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+include(CheckCSourceCompiles)
# On windows preload settings
if(WIN32)
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=")
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
-endif(WIN32)
+endif()
if(ENABLE_THREADED_RESOLVER)
find_package(Threads REQUIRED)
set(NOT_NEED_LIBNSL 1)
check_library_exists_concat("bind" gethostbyname HAVE_LIBBIND)
check_library_exists_concat("bnetapi" closesocket HAVE_LIBBNETAPI)
-endif(BEOS)
+endif()
check_library_exists_concat("network" recv HAVE_LIBNETWORK)
if(NOT NOT_NEED_LIBNSL)
check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL)
-endif(NOT NOT_NEED_LIBNSL)
+endif()
check_function_exists(gethostname HAVE_GETHOSTNAME)
set(openssl_default OFF)
endif()
-collect_true(enabled_ssl_options enabled_ssl_options_count
+count_true(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.")
+if(enabled_ssl_options_count GREATER "1")
+ set(CURL_WITH_MULTI_SSL ON)
endif()
if(CMAKE_USE_WINSSL)
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/rsa.h" HAVE_OPENSSL_RSA_H)
endif()
endif()
endif()
-
endif()
# No ldap, no ldaps.
option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
-set(HAVE_ZLIB OFF)
+set(USE_ZLIB OFF)
if(CURL_ZLIB)
find_package(ZLIB QUIET)
if(ZLIB_FOUND)
set(HAVE_ZLIB_H ON)
- set(HAVE_ZLIB ON)
set(HAVE_LIBZ ON)
- list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
- include_directories(${ZLIB_INCLUDE_DIRS})
+ set(USE_ZLIB ON)
+
+ # Depend on ZLIB via imported targets if supported by the running
+ # version of CMake. This allows our dependents to get our dependencies
+ # transitively.
+ if(NOT CMAKE_VERSION VERSION_LESS 3.4)
+ list(APPEND CURL_LIBS ZLIB::ZLIB)
+ else()
+ list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
+ include_directories(${ZLIB_INCLUDE_DIRS})
+ endif()
list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
endif()
endif()
check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64)
check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
set(CMAKE_EXTRA_INCLUDE_FILES "")
-
- endif(LIBSSH2_FOUND)
-endif(CMAKE_USE_LIBSSH2)
+ endif()
+endif()
option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
mark_as_advanced(CMAKE_USE_GSSAPI)
"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.")
+ 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)
+ unset(CURL_CA_BUNDLE CACHE)
elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
- unset(CURL_CA_BUNDLE CACHE)
- set(CURL_CA_BUNDLE_AUTODETECT TRUE)
+ unset(CURL_CA_BUNDLE CACHE)
+ set(CURL_CA_BUNDLE_AUTODETECT TRUE)
else()
- set(CURL_CA_BUNDLE_SET TRUE)
+ 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.")
+ 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)
+ unset(CURL_CA_PATH CACHE)
elseif("${CURL_CA_PATH}" STREQUAL "auto")
- unset(CURL_CA_PATH CACHE)
- set(CURL_CA_PATH_AUTODETECT TRUE)
+ unset(CURL_CA_PATH CACHE)
+ set(CURL_CA_PATH_AUTODETECT TRUE)
else()
- set(CURL_CA_PATH_SET TRUE)
+ 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
+ # 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
+ # 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()
+ # 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()
+ 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.")
+ 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)
if(HAVE_SIZEOF_LONG_LONG)
set(HAVE_LONGLONG 1)
set(HAVE_LL 1)
-endif(HAVE_SIZEOF_LONG_LONG)
+endif()
find_file(RANDOM_FILE urandom /dev)
mark_as_advanced(RANDOM_FILE)
check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM)
if(NOT HAVE_STRNCMPI)
set(HAVE_STRCMPI)
-endif(NOT HAVE_STRNCMPI)
+endif()
check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT)
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
+check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME)
check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
set(HAVE_SIGNAL 1)
-endif(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
+endif()
check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME)
check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64)
add_definitions(-D_WIN32_WINNT=0x0501)
endif()
else()
- check_function_exists(inet_pton HAVE_INET_PTON)
+ check_function_exists(inet_pton HAVE_INET_PTON)
endif()
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)
+ curl_internal_test(${CURL_TEST})
+ endforeach()
+endif()
# sigaction and sigsetjmp are special. Use special mechanism for
# detecting those, but only if previous attempt failed.
if(HAVE_SIGNAL_H)
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
-endif(HAVE_SIGNAL_H)
+endif()
if(NOT HAVE_SIGSETJMP)
if(HAVE_SETJMP_H)
check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
if(HAVE_MACRO_SIGSETJMP)
set(HAVE_SIGSETJMP 1)
- endif(HAVE_MACRO_SIGSETJMP)
- endif(HAVE_SETJMP_H)
-endif(NOT HAVE_SIGSETJMP)
+ endif()
+ endif()
+endif()
# If there is no stricmp(), do not allow LDAP to parse URLs
if(NOT HAVE_STRICMP)
set(HAVE_LDAP_URL_PARSE 1)
-endif(NOT HAVE_STRICMP)
+endif()
# Do curl specific tests
foreach(CURL_TEST
HAVE_GETHOSTBYNAME_R_3_REENTRANT
HAVE_GETHOSTBYNAME_R_5_REENTRANT
HAVE_GETHOSTBYNAME_R_6_REENTRANT
- HAVE_SOCKLEN_T
HAVE_IN_ADDR_T
HAVE_BOOL_T
STDC_HEADERS
HAVE_FILE_OFFSET_BITS
)
curl_internal_test(${CURL_TEST})
-endforeach(CURL_TEST)
+endforeach()
if(HAVE_FILE_OFFSET_BITS)
set(_FILE_OFFSET_BITS 64)
set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
-endif(HAVE_FILE_OFFSET_BITS)
+endif()
check_type_size("off_t" SIZEOF_OFF_T)
# include this header to get the type
HAVE_GLIBC_STRERROR_R
HAVE_POSIX_STRERROR_R
)
- curl_internal_test_run(${CURL_TEST})
-endforeach(CURL_TEST)
+ curl_internal_test(${CURL_TEST})
+endforeach()
# Check for reentrant
foreach(CURL_TEST
if(NOT ${CURL_TEST})
if(${CURL_TEST}_REENTRANT)
set(NEED_REENTRANT 1)
- endif(${CURL_TEST}_REENTRANT)
- endif(NOT ${CURL_TEST})
-endforeach(CURL_TEST)
+ endif()
+ endif()
+endforeach()
if(NEED_REENTRANT)
foreach(CURL_TEST
set(${CURL_TEST} 0)
if(${CURL_TEST}_REENTRANT)
set(${CURL_TEST} 1)
- endif(${CURL_TEST}_REENTRANT)
- endforeach(CURL_TEST)
-endif(NEED_REENTRANT)
+ endif()
+ endforeach()
+endif()
if(HAVE_INET_NTOA_R_DECL_REENTRANT)
set(HAVE_INET_NTOA_R_DECL 1)
set(NEED_REENTRANT 1)
-endif(HAVE_INET_NTOA_R_DECL_REENTRANT)
+endif()
+
+# Check clock_gettime(CLOCK_MONOTONIC, x) support
+curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+# Check compiler support of __builtin_available()
+curl_internal_test(HAVE_BUILTIN_AVAILABLE)
# Some other minor tests
if(NOT HAVE_IN_ADDR_T)
set(in_addr_t "unsigned long")
-endif(NOT HAVE_IN_ADDR_T)
+endif()
# Fix libz / zlib.h
if(NOT CURL_SPECIAL_LIBZ)
if(NOT HAVE_LIBZ)
set(HAVE_ZLIB_H 0)
- endif(NOT HAVE_LIBZ)
+ endif()
if(NOT HAVE_ZLIB_H)
set(HAVE_LIBZ 0)
- endif(NOT HAVE_ZLIB_H)
-endif(NOT CURL_SPECIAL_LIBZ)
+ endif()
+endif()
# Check for nonblocking
set(HAVE_DISABLED_NONBLOCKING 1)
HAVE_IOCTLSOCKET_CASE OR
HAVE_O_NONBLOCK)
set(HAVE_DISABLED_NONBLOCKING)
-endif(HAVE_FIONBIO OR
- HAVE_IOCTLSOCKET OR
- HAVE_IOCTLSOCKET_CASE OR
- HAVE_O_NONBLOCK)
+endif()
if(RETSIGTYPE_TEST)
set(RETSIGTYPE void)
-else(RETSIGTYPE_TEST)
+else()
set(RETSIGTYPE int)
-endif(RETSIGTYPE_TEST)
+endif()
if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
include(CheckCCompilerFlag)
get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS)
if(MPRINTF_COMPILE_FLAGS)
set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double")
- else(MPRINTF_COMPILE_FLAGS)
+ else()
set(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
- endif(MPRINTF_COMPILE_FLAGS)
+ endif()
set_source_files_properties(mprintf.c PROPERTIES
COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
- endif(HAVE_C_FLAG_Wno_long_double)
-endif(CMAKE_COMPILER_IS_GNUCC AND APPLE)
-
-if(HAVE_SOCKLEN_T)
- set(CURL_HAVE_SOCKLEN_T 1)
- set(CURL_TYPEOF_CURL_SOCKLEN_T "socklen_t")
- if(WIN32)
- set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h;ws2tcpip.h")
- elseif(HAVE_SYS_SOCKET_H)
- set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
- endif()
- check_type_size("socklen_t" CURL_SIZEOF_CURL_SOCKLEN_T)
- set(CMAKE_EXTRA_INCLUDE_FILES)
- if(NOT HAVE_CURL_SIZEOF_CURL_SOCKLEN_T)
- message(FATAL_ERROR
- "Check for sizeof socklen_t failed, see CMakeFiles/CMakerror.log")
endif()
-else()
- set(CURL_HAVE_SOCKLEN_T 0)
endif()
# TODO test which of these headers are required
add_definitions(-DHAVE_CONFIG_H)
-# For windows, all compilers used by cmake should support large files
+# For Windows, all compilers used by CMake should support large files
if(WIN32)
set(USE_WIN32_LARGE_FILES ON)
-endif(WIN32)
+
+ # Use the manifest embedded in the Windows Resource
+ set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
+endif()
if(MSVC)
+ # Disable default manifest added by CMake
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
+
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
- else(CMAKE_C_FLAGS MATCHES "/W[0-4]")
+ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
- endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
-endif(MSVC)
+ endif()
+endif()
if(CURL_WERROR)
if(MSVC_VERSION)
# this assumes clang or gcc style options
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
endif()
-endif(CURL_WERROR)
+endif()
# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
endfunction()
-if(WIN32 AND NOT CYGWIN)
- set(CURL_INSTALL_CMAKE_DIR CMake)
-else()
- set(CURL_INSTALL_CMAKE_DIR lib/cmake/curl)
+if(0) # This code not needed for building within CMake.
+include(GNUInstallDirs)
+
+set(CURL_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
+set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
+set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
+set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
+set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
endif()
if(USE_MANUAL)
#-----------------------------------------------------------------------------
# CMake-specific curl code.
-add_executable(LIBCURL curltest.c)
-target_link_libraries(LIBCURL cmcurl)
+add_executable(curltest curltest.c)
+target_link_libraries(curltest cmcurl)
-if(CMAKE_CURL_TEST_URL)
- add_test(curl LIBCURL ${CMAKE_CURL_TEST_URL})
+if(BUILD_TESTING AND CMAKE_CURL_TEST_URL)
+ add_test(curl curltest ${CMAKE_CURL_TEST_URL})
endif()
install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl)
# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
set(CPPFLAG_CURL_STATICLIB "")
set(CURLVERSION "${CURL_VERSION}")
-set(ENABLE_SHARED "yes")
-if(CURL_STATICLIB)
- set(ENABLE_STATIC "yes")
-else()
+if(BUILD_SHARED_LIBS)
+ set(ENABLE_SHARED "yes")
set(ENABLE_STATIC "no")
+else()
+ set(ENABLE_SHARED "no")
+ set(ENABLE_STATIC "yes")
endif()
set(exec_prefix "\${prefix}")
set(includedir "\${prefix}/include")
set(VERSIONNUM "${CURL_VERSION_NUM}")
# Finally generate a "curl-config" matching this config
+# Use:
+# * ENABLE_SHARED
+# * ENABLE_STATIC
configure_file("${CURL_SOURCE_DIR}/curl-config.in"
"${CURL_BINARY_DIR}/curl-config" @ONLY)
install(FILES "${CURL_BINARY_DIR}/curl-config"
- DESTINATION bin
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
"${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
- DESTINATION lib/pkgconfig)
-
-# This needs to be run very last so other parts of the scripts can take advantage of this.
-if(NOT CURL_CONFIG_HAS_BEEN_RUN_BEFORE)
- set(CURL_CONFIG_HAS_BEEN_RUN_BEFORE 1 CACHE INTERNAL "Flag to track whether this is the first time running CMake or if CMake has been configured before")
-endif()
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# install headers
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
- DESTINATION include
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
-
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
- "${PROJECT_BINARY_DIR}/curl-config-version.cmake"
+ "${version_config}"
VERSION ${CURL_VERSION}
COMPATIBILITY SameMajorVersion
)
-configure_file(CMake/curl-config.cmake
- "${PROJECT_BINARY_DIR}/curl-config.cmake"
- COPYONLY
+# Use:
+# * TARGETS_EXPORT_NAME
+# * PROJECT_NAME
+configure_package_config_file(CMake/curl-config.cmake.in
+ "${project_config}"
+ INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
+)
+
+install(
+ EXPORT "${TARGETS_EXPORT_NAME}"
+ NAMESPACE "${PROJECT_NAME}::"
+ DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
install(
- FILES ${PROJECT_BINARY_DIR}/curl-config.cmake
- ${PROJECT_BINARY_DIR}/curl-config-version.cmake
+ FILES ${version_config} ${project_config}
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
-/* Prevent warnings on Visual Studio */
-struct _RPC_ASYNC_STATE;
-
#include "curl/curl.h"
+
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-int GetFtpFile(void)
+int test_curl(const char* url)
{
- int retVal = 0;
- CURL *curl;
- CURLcode res;
- curl = curl_easy_init();
- if(curl)
- {
- /* Get curl 7.9.2 from sunet.se's FTP site: */
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_HEADER, 1);
- curl_easy_setopt(curl, CURLOPT_URL,
- "ftp://public.kitware.com/pub/cmake/cygwin/setup.hint");
- res = curl_easy_perform(curl);
- if ( res != 0 )
- {
- printf("Error fetching: ftp://public.kitware.com/pub/cmake/cygwin/setup.hint\n");
- retVal = 1;
- }
-
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
- else
- {
- printf("Cannot create curl object\n");
- retVal = 1;
- }
- return retVal;
-}
-
-int GetWebFiles(char *url1, char *url2)
-{
- int retVal = 0;
- CURL *curl;
- CURLcode res;
-
+ CURL* curl;
+ CURLcode r;
char proxy[1024];
int proxy_type = 0;
- if ( getenv("HTTP_PROXY") )
- {
+ if (getenv("HTTP_PROXY")) {
proxy_type = 1;
- if (getenv("HTTP_PROXY_PORT") )
- {
+ if (getenv("HTTP_PROXY_PORT")) {
sprintf(proxy, "%s:%s", getenv("HTTP_PROXY"), getenv("HTTP_PROXY_PORT"));
- }
- else
- {
+ } else {
sprintf(proxy, "%s", getenv("HTTP_PROXY"));
- }
- if ( getenv("HTTP_PROXY_TYPE") )
- {
+ }
+ if (getenv("HTTP_PROXY_TYPE")) {
/* HTTP/SOCKS4/SOCKS5 */
- if ( strcmp(getenv("HTTP_PROXY_TYPE"), "HTTP") == 0 )
- {
+ if (strcmp(getenv("HTTP_PROXY_TYPE"), "HTTP") == 0) {
proxy_type = 1;
- }
- else if ( strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS4") == 0 )
- {
+ } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS4") == 0) {
proxy_type = 2;
- }
- else if ( strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS5") == 0 )
- {
+ } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS5") == 0) {
proxy_type = 3;
- }
}
}
+ }
curl = curl_easy_init();
- if(curl)
- {
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(curl, CURLOPT_HEADER, 1);
-
- /* Using proxy */
- if ( proxy_type > 0 )
- {
- curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
- switch (proxy_type)
- {
- case 2:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
- break;
- case 3:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
- break;
- default:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
- }
- }
-
- /* get the first document */
- curl_easy_setopt(curl, CURLOPT_URL, url1);
- res = curl_easy_perform(curl);
- if ( res != 0 )
- {
- printf("Error fetching: %s\n", url1);
- retVal = 1;
- }
+ if (!curl) {
+ fprintf(stderr, "curl_easy_init failed\n");
+ return 1;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+ curl_easy_setopt(curl, CURLOPT_HEADER, 1);
+
+ if (proxy_type > 0) {
+ curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
+ switch (proxy_type) {
+ case 2:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+ break;
+ case 3:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+ break;
+ default:
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ }
+ }
- /* get another document from the same server using the same
- connection */
- /* avoid warnings about url2 since below block is commented out: */
- (void) url2;
- /*
- curl_easy_setopt(curl, CURLOPT_URL, url2);
- res = curl_easy_perform(curl);
- if ( res != 0 )
- {
- printf("Error fetching: %s\n", url2);
- retVal = 1;
- }
- */
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ r = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
- else
- {
- printf("Cannot create curl object\n");
- retVal = 1;
- }
+ if (r != CURLE_OK) {
+ fprintf(stderr, "error: fetching '%s' failed: %s\n", url,
+ curl_easy_strerror(r));
+ return 1;
+ }
- return retVal;
+ return 0;
}
-
-int main(int argc, char **argv)
+int main(int argc, const char* argv[])
{
- int retVal = 0;
-
+ int r;
curl_global_init(CURL_GLOBAL_DEFAULT);
-
- if(argc>1)
- {
- retVal += GetWebFiles(argv[1], 0);
- }
- else
- {
- printf("error: first argument should be a url to download\n");
- retVal = 1;
- }
-
- /* Do not check the output of FTP socks5 cannot handle FTP yet */
- /* GetFtpFile(); */
- /* do not test ftp right now because we don't enable that port */
-
+ if (argc == 2) {
+ r = test_curl(argv[1]);
+ } else {
+ fprintf(stderr, "error: no URL given as first argument\n");
+ r = 1;
+ }
curl_global_cleanup();
-
- return retVal;
+ return r;
}
CURLSSLBACKEND_SCHANNEL = 8,
CURLSSLBACKEND_DARWINSSL = 9,
CURLSSLBACKEND_AXTLS = 10,
- CURLSSLBACKEND_MBEDTLS = 11
+ CURLSSLBACKEND_MBEDTLS = 11,
+ CURLSSLBACKEND_MESALINK = 12
} curl_sslbackend;
/* aliases for library clones and renames */
CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */
CURLE_OBSOLETE50, /* 50 - NOT USED */
- CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
- wasn't verified fine */
+ CURLE_OBSOLETE51, /* 51 - NOT USED */
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
CURLE_OBSOLETE57, /* 57 - NOT IN USE */
CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
- CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
+ CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint
+ wasn't verified fine */
CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
CURL_LAST /* never use! */
} CURLcode;
+/* added in 7.62.0 */
+#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
+
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
* CURLAUTH_NTLM - HTTP NTLM authentication
* CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
* CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_BEARER - HTTP Bearer token authentication
* CURLAUTH_ONLY - Use together with a single other type to force no
* authentication or just that single type
* CURLAUTH_ANY - All fine types set
#define CURLAUTH_NTLM (((unsigned long)1)<<3)
#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
+#define CURLAUTH_BEARER (((unsigned long)1)<<6)
#define CURLAUTH_ONLY (((unsigned long)1)<<31)
#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
this value, keep them in sync. */
#define CURL_HET_DEFAULT 200L
+/* The default connection upkeep interval in milliseconds. */
+#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L
+
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
/* shuffle addresses before use when DNS returns multiple */
CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+ /* Specify which TLS 1.3 ciphers suites to use */
+ CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
+ CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
+
+ /* Disallow specifying username/login in URL. */
+ CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
+
+ /* DNS-over-HTTPS URL */
+ CINIT(DOH_URL, STRINGPOINT, 279),
+
+ /* Preferred buffer size to use for uploads */
+ CINIT(UPLOAD_BUFFERSIZE, LONG, 280),
+
+ /* Time in ms between connection upkeep calls for long-lived connections. */
+ CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
CURLINFO_SCHEME = CURLINFO_STRING + 49,
/* Fill in new entries below here! */
- CURLINFO_LASTONE = 49
+ /* Preferably these would be defined conditionally based on the
+ sizeof curl_off_t being 64-bits */
+ CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50,
+ CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
+ CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52,
+ CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
+ CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
+ CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55,
+ CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
+
+ CURLINFO_LASTONE = 56
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
CURL_LOCK_DATA_DNS,
CURL_LOCK_DATA_SSL_SESSION,
CURL_LOCK_DATA_CONNECT,
+ CURL_LOCK_DATA_PSL,
CURL_LOCK_DATA_LAST
} curl_lock_data;
stuff before they can be included! */
#include "easy.h" /* nothing in curl is fun without the easy stuff */
#include "multi.h"
+#include "urlapi.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.60.0"
+#define LIBCURL_VERSION "7.62.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 60
+#define LIBCURL_VERSION_MINOR 62
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
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 0x073C00
+#define LIBCURL_VERSION_NUM 0x073E00
/*
* This is the date and time when the full source package was created. The
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
size_t buflen, size_t *n);
+
+/*
+ * NAME curl_easy_upkeep()
+ *
+ * DESCRIPTION
+ *
+ * Performs connection upkeep for the given session handle.
+ */
+CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
+
#ifdef __cplusplus
}
#endif
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
-#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
defined(__i386) || \
defined(__sparcv8) || \
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
+#elif defined(__xlc__) /* IBM xlc compiler */
+# if !defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
/* ===================================== */
/* KEEP MSVC THE PENULTIMATE ENTRY */
/* ===================================== */
/* KEEP GENERIC GCC THE LAST ENTRY */
/* ===================================== */
-#elif defined(__GNUC__)
+#elif defined(__GNUC__) && !defined(_SCO_DS)
# if !defined(__LP64__) && \
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
(option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \
(option) == CURLOPT_DNS_SERVERS || \
+ (option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
* == or whatsoever.
*/
-/* XXX: should evaluate to true iff expr is a pointer */
+/* XXX: should evaluate to true if expr is a pointer */
#define _curl_is_any_ptr(expr) \
(sizeof(expr) == sizeof(void *))
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define _curl_is_postfields(expr) \
(_curl_is_ptr((expr), void) || \
- _curl_is_arr((expr), char))
+ _curl_is_arr((expr), char) || \
+ _curl_is_arr((expr), unsigned char))
/* FIXME: the whole callback checking is messy...
* The idea is to tolerate char vs. void and const vs. not const
--- /dev/null
+#ifndef __CURL_URLAPI_H
+#define __CURL_URLAPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2018, Daniel Stenberg, <daniel@haxx.se>, 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.
+ *
+ ***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* the error codes for the URL API */
+typedef enum {
+ CURLUE_OK,
+ CURLUE_BAD_HANDLE, /* 1 */
+ CURLUE_BAD_PARTPOINTER, /* 2 */
+ CURLUE_MALFORMED_INPUT, /* 3 */
+ CURLUE_BAD_PORT_NUMBER, /* 4 */
+ CURLUE_UNSUPPORTED_SCHEME, /* 5 */
+ CURLUE_URLDECODE, /* 6 */
+ CURLUE_OUT_OF_MEMORY, /* 7 */
+ CURLUE_USER_NOT_ALLOWED, /* 8 */
+ CURLUE_UNKNOWN_PART, /* 9 */
+ CURLUE_NO_SCHEME, /* 10 */
+ CURLUE_NO_USER, /* 11 */
+ CURLUE_NO_PASSWORD, /* 12 */
+ CURLUE_NO_OPTIONS, /* 13 */
+ CURLUE_NO_HOST, /* 14 */
+ CURLUE_NO_PORT, /* 15 */
+ CURLUE_NO_QUERY, /* 16 */
+ CURLUE_NO_FRAGMENT /* 17 */
+} CURLUcode;
+
+typedef enum {
+ CURLUPART_URL,
+ CURLUPART_SCHEME,
+ CURLUPART_USER,
+ CURLUPART_PASSWORD,
+ CURLUPART_OPTIONS,
+ CURLUPART_HOST,
+ CURLUPART_PORT,
+ CURLUPART_PATH,
+ CURLUPART_QUERY,
+ CURLUPART_FRAGMENT
+} CURLUPart;
+
+#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
+#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
+ if the port number matches the
+ default for the scheme */
+#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
+ missing */
+#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
+#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
+#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
+#define CURLU_URLDECODE (1<<6) /* URL decode on get */
+#define CURLU_URLENCODE (1<<7) /* URL encode on set */
+#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
+#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
+
+typedef struct Curl_URL CURLU;
+
+/*
+ * curl_url() creates a new CURLU handle and returns a pointer to it.
+ * Must be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url(void);
+
+/*
+ * curl_url_cleanup() frees the CURLU handle and related resources used for
+ * the URL parsing. It will not free strings previously returned with the URL
+ * API.
+ */
+CURL_EXTERN void curl_url_cleanup(CURLU *handle);
+
+/*
+ * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
+ * handle must also be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
+
+/*
+ * curl_url_get() extracts a specific part of the URL from a CURLU
+ * handle. Returns error code. The returned pointer MUST be freed with
+ * curl_free() afterwards.
+ */
+CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
+ char **part, unsigned int flags);
+
+/*
+ * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
+ * error code. The passed in string will be copied. Passing a NULL instead of
+ * a part string, clears that part.
+ */
+CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
+ const char *part, unsigned int flags);
+
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
set(LIB_NAME cmcurl)
+if(BUILD_SHARED_LIBS)
+ set(CURL_STATICLIB NO)
+else()
+ set(CURL_STATICLIB YES)
+endif()
+
+# Use:
+# * CURL_STATICLIB
configure_file(curl_config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
include_directories(${CARES_INCLUDE_DIR})
endif()
-if(CURL_STATICLIB)
- # Static lib
- set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC STATIC)
-else()
- # DLL / so dynamic lib
- set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC SHARED)
-endif()
-
# For windows we want to install OPENSSL_LIBRARIES dlls
# and also copy them into the build tree so that testing
# can find them.
add_library(
${LIB_NAME}
- ${CURL_USER_DEFINED_DYNAMIC_OR_STATIC}
${HHEADERS} ${CSOURCES}
${CMAKE_CURL_SSL_DLLS}
)
+if(NOT BUILD_SHARED_LIBS)
+ set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
+endif()
+
target_link_libraries(${LIB_NAME} ${CURL_LIBS})
if(0) # This code not needed for building within CMake.
if(WIN32)
- add_definitions( -D_USRDLL )
+ add_definitions(-D_USRDLL)
endif()
endif()
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
if(WIN32)
- if(NOT CURL_STATICLIB)
+ if(BUILD_SHARED_LIBS)
# Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
-
- set_target_properties (${LIB_NAME} PROPERTIES
- DEBUG_POSTFIX "-d"
- # Note: no postfix for release variants, let user choose what style of release he wants
- # MINSIZEREL_POSTFIX "-z"
- # RELWITHDEBINFO_POSTFIX "-g"
- )
endif()
endif()
target_include_directories(${LIB_NAME} INTERFACE
- $<INSTALL_INTERFACE:include>)
+ $<INSTALL_INTERFACE:include>
+ $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
install(TARGETS ${LIB_NAME}
- EXPORT libcurl-target
- ARCHIVE DESTINATION lib
- LIBRARY DESTINATION lib
- RUNTIME DESTINATION bin
+ EXPORT ${TARGETS_EXPORT_NAME}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
export(TARGETS ${LIB_NAME}
NAMESPACE CURL::
)
-install(EXPORT libcurl-target
- FILE libcurl-target.cmake
- NAMESPACE CURL::
- DESTINATION ${CURL_INSTALL_CMAKE_DIR}
-)
-
endif()
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c \
vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \
- vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c
+ vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h \
vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h \
- vtls/mbedtls.h
+ vtls/mbedtls.h vtls/mesalink.h
LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.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 \
- mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c
+ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \
+ doh.c urlapi.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.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 rand.h mime.h curl_sha256.h setopt.h \
- curl_path.h curl_ctype.h curl_range.h
+ curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h
LIB_RCFILES = libcurl.rc
#endif
#endif /* HEADER_CURL_AMIGAOS_H */
-
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#define CURL_NEW_ENV_VAR 0
#define CURL_NEW_ENV_VALUE 1
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
/*
* The telnet options represented as strings
*/
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
+#endif
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
#define CURL_DONT 254 /* DON'T use this option! */
#define CURL_IAC 255 /* Interpret As Command */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
/*
* Then those numbers represented as strings:
*/
"AYT", "EC", "EL", "GA", "SB",
"WILL", "WONT", "DO", "DONT", "IAC"
};
+#endif
#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */
#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
conn->async.os_specific;
CURLcode result = CURLE_OK;
- *dns = NULL;
+ if(dns)
+ *dns = NULL;
waitperform(conn, 0);
if(res && !res->num_pending) {
- (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
- /* temp_ai ownership is moved to the connection, so we need not free-up
- them */
- res->temp_ai = NULL;
+ if(dns) {
+ (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+ /* temp_ai ownership is moved to the connection, so we need not free-up
+ them */
+ res->temp_ai = NULL;
+ }
if(!conn->async.dns) {
failf(data, "Could not resolve: %s (%s)",
conn->async.hostname, ares_strerror(conn->async.status));
result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
- else
+ else if(dns)
*dns = conn->async.dns;
destroy_async_data(&conn->async);
timeout_ms = 1000;
waitperform(conn, timeout_ms);
- result = Curl_resolver_is_resolved(conn, &temp_entry);
+ result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL);
if(result || conn->async.done)
break;
return;
res = (struct ResolverResults *)conn->async.os_specific;
- res->num_pending--;
+ if(res) {
+ res->num_pending--;
- if(CURL_ASYNC_SUCCESS == status) {
- Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
- if(ai) {
- compound_results(res, ai);
+ if(CURL_ASYNC_SUCCESS == status) {
+ Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+ if(ai) {
+ compound_results(res, ai);
+ }
}
+ /* A successful result overwrites any previous error */
+ if(res->last_status != ARES_SUCCESS)
+ res->last_status = status;
}
- /* A successful result overwrites any previous error */
- if(res->last_status != ARES_SUCCESS)
- res->last_status = status;
}
/*
return &(((struct thread_data *)conn->async.os_specific)->tsd);
}
-#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd);
-
/* Destroy resolver thread synchronization data */
static
void destroy_thread_sync_data(struct thread_sync_data * tsd)
DEBUGASSERT(conn && td);
/* wait for the thread to resolve the name */
- if(Curl_thread_join(&td->thread_hnd))
- result = getaddrinfo_complete(conn);
+ if(Curl_thread_join(&td->thread_hnd)) {
+ if(entry)
+ result = getaddrinfo_complete(conn);
+ }
else
DEBUGASSERT(0);
(void)socks;
(void)numsocks;
ms = Curl_timediff(Curl_now(), reslv->start);
- if(ms < 10)
- milli = ms/3;
+ if(ms < 3)
+ milli = 0;
else if(ms <= 50)
- milli = 10;
+ milli = ms/3;
else if(ms <= 250)
milli = 50;
else
unsigned long i, x = 0;
for(i = 0, s = src; i < 4; i++, s++) {
- unsigned long v = 0;
-
if(*s == '=') {
x = (x << 6);
padding++;
}
else {
+ unsigned long v = 0;
p = base64;
while(*p && (*p != *s)) {
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
static void conn_llist_dtor(void *user, void *element)
{
- struct connectdata *data = element;
+ struct connectdata *conn = element;
(void)user;
-
- data->bundle = NULL;
+ conn->bundle = NULL;
}
static CURLcode bundle_create(struct Curl_easy *data,
}
/* Add a connection to a bundle */
-static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
- struct connectdata *conn)
+static void bundle_add_conn(struct connectbundle *cb_ptr,
+ struct connectdata *conn)
{
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;
}
/* Remove a connection from a bundle */
CURLcode Curl_conncache_add_conn(struct conncache *connc,
struct connectdata *conn)
{
- CURLcode result;
+ CURLcode result = CURLE_OK;
struct connectbundle *bundle;
struct connectbundle *new_bundle = NULL;
struct Curl_easy *data = conn->data;
bundle = new_bundle;
}
- result = bundle_add_conn(bundle, conn);
- if(result) {
- if(new_bundle)
- conncache_remove_bundle(data->state.conn_cache, new_bundle);
- goto unlock;
- }
-
+ bundle_add_conn(bundle, conn);
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
DEBUGF(infof(conn->data, "Added connection %ld. "
- "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n",
- conn->connection_id, (curl_off_t) connc->num_conn));
+ "The cache now contains %zu members\n",
+ conn->connection_id, connc->num_conn));
unlock:
CONN_UNLOCK(data);
due to a failed connection attempt, before being added to a bundle */
if(bundle) {
if(lock) {
- CONN_LOCK(conn->data);
+ CONN_LOCK(data);
}
bundle_remove_conn(bundle, conn);
if(bundle->num_connections == 0)
conn->bundle = NULL; /* removed from it */
if(connc) {
connc->num_conn--;
- DEBUGF(infof(conn->data, "The cache now contains %"
- CURL_FORMAT_CURL_OFF_TU " members\n",
- (curl_off_t) connc->num_conn));
+ DEBUGF(infof(data, "The cache now contains %zu members\n",
+ connc->num_conn));
}
if(lock) {
- CONN_UNLOCK(conn->data);
+ CONN_UNLOCK(data);
}
}
}
infof(data, "Connection cache is full, closing the oldest one.\n");
conn_candidate = Curl_conncache_extract_oldest(data);
-
if(conn_candidate) {
- /* Set the connection's owner correctly */
- conn_candidate->data = data;
-
/* the winner gets the honour of being disconnected */
- (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+ (void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
}
}
- CONN_LOCK(data);
- conn->inuse = FALSE; /* Mark the connection unused */
- CONN_UNLOCK(data);
return (conn_candidate == conn) ? FALSE : TRUE;
while(curr) {
conn = curr->ptr;
- if(!conn->inuse) {
+ if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->now);
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle, conn_candidate);
data->state.conn_cache->num_conn--;
- DEBUGF(infof(data, "The cache now contains %"
- CURL_FORMAT_CURL_OFF_TU " members\n",
- (curl_off_t) data->state.conn_cache->num_conn));
+ DEBUGF(infof(data, "The cache now contains %zu members\n",
+ data->state.conn_cache->num_conn));
+ conn_candidate->data = data; /* associate! */
}
return conn_candidate;
while(curr) {
conn = curr->ptr;
- if(!conn->inuse) {
+ if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->now);
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle_candidate, conn_candidate);
connc->num_conn--;
- DEBUGF(infof(data, "The cache now contains %"
- CURL_FORMAT_CURL_OFF_TU " members\n",
- (curl_off_t) connc->num_conn));
+ DEBUGF(infof(data, "The cache now contains %zu members\n",
+ connc->num_conn));
+ conn_candidate->data = data; /* associate! */
}
CONN_UNLOCK(data);
pointer */
/* This will remove the connection from the cache */
connclose(conn, "kill all");
- (void)Curl_disconnect(conn, FALSE);
+ (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
sigpipe_restore(&pipe_st);
conn = Curl_conncache_find_first_connection(connc);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
bool Curl_conncache_return_conn(struct connectdata *conn);
CURLcode Curl_conncache_add_conn(struct conncache *connc,
- struct connectdata *conn);
+ struct connectdata *conn) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct connectdata *conn,
bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data,
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp)
{
- curl_socket_t sockfd;
-
DEBUGASSERT(data);
/* this works for an easy handle:
return CURL_SOCKET_BAD;
}
- if(connp)
+ if(connp) {
/* only store this if the caller cares for it */
*connp = c;
- sockfd = c->sock[FIRSTSOCKET];
+ c->data = data;
+ }
+ return c->sock[FIRSTSOCKET];
}
else
return CURL_SOCKET_BAD;
-
- return sockfd;
}
/*
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#define RESERVED 0xE0 /* bits 5..7: reserved */
typedef enum {
- ZLIB_UNINIT, /* uninitialized */
- ZLIB_INIT, /* initialized */
- ZLIB_INFLATING, /* Inflating started. */
- ZLIB_GZIP_HEADER, /* reading gzip header */
- ZLIB_GZIP_TRAILER, /* reading gzip trailer */
- ZLIB_GZIP_INFLATING, /* inflating gzip stream */
- ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
+ ZLIB_UNINIT, /* uninitialized */
+ ZLIB_INIT, /* initialized */
+ ZLIB_INFLATING, /* inflating started. */
+ ZLIB_EXTERNAL_TRAILER, /* reading external trailer */
+ ZLIB_GZIP_HEADER, /* reading gzip header */
+ ZLIB_GZIP_INFLATING, /* inflating gzip stream */
+ ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
/* Writer parameters. */
if(result || !zp->trailerlen)
result = exit_zlib(conn, z, &zp->zlib_init, result);
else {
- /* Only occurs for gzip with zlib < 1.2.0.4. */
- zp->zlib_init = ZLIB_GZIP_TRAILER;
+ /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
+ zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
}
return result;
}
z_stream *z = &zp->z; /* zlib state structure */
uInt nread = z->avail_in;
Bytef *orig_in = z->next_in;
- int status; /* zlib status */
bool done = FALSE;
CURLcode result = CURLE_OK; /* Curl_client_write status */
char *decomp; /* Put the decompressed data here. */
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via downstream_write function. */
while(!done) {
+ int status; /* zlib status */
done = TRUE;
/* (re)set buffer for decompressed output for every iteration */
z->next_out = (Bytef *) decomp;
z->avail_out = DSIZ;
+#ifdef Z_BLOCK
+ /* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */
status = inflate(z, Z_BLOCK);
+#else
+ /* fallback for zlib ver. < 1.2.0.5 */
+ status = inflate(z, Z_SYNC_FLUSH);
+#endif
/* Flush output data if some. */
if(z->avail_out != DSIZ) {
z->next_in = orig_in;
z->avail_in = nread;
zp->zlib_init = ZLIB_INFLATING;
+ zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
done = FALSE;
break;
}
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
+ if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
+ return process_trailer(conn, zp);
+
/* Now uncompress the data */
return inflate_stream(conn, writer, ZLIB_INFLATING);
}
}
break;
- case ZLIB_GZIP_TRAILER:
+ case ZLIB_EXTERNAL_TRAILER:
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
return process_trailer(conn, zp);
const content_encoding * const *cep;
const content_encoding *ce;
char *ace;
- char *p;
for(cep = encodings; *cep; cep++) {
ce = *cep;
ace = malloc(len);
if(ace) {
- p = ace;
+ char *p = ace;
for(cep = encodings; *cep; cep++) {
ce = *cep;
if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
static const content_encoding *find_encoding(const char *name, size_t len)
{
const content_encoding * const *cep;
- const content_encoding *ce;
for(cep = encodings; *cep; cep++) {
- ce = *cep;
+ const content_encoding *ce = *cep;
if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
(ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
return ce;
received from a server.
The function need to replace previously stored lines that this new
- line superceeds.
+ line supersedes.
It may remove lines that are expired.
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-#ifdef USE_LIBPSL
-# include <libpsl.h>
-#endif
-
#include "urldata.h"
#include "cookie.h"
+#include "psl.h"
#include "strtok.h"
#include "sendf.h"
#include "slist.h"
len = strlen(domain);
last = memrchr(domain, '.', len);
if(last) {
- first = memrchr(domain, '.', (size_t) (last - domain));
+ first = memrchr(domain, '.', (last - domain));
if(first)
- len -= (size_t) (++first - domain);
+ len -= (++first - domain);
}
if(outlen)
*/
static void remove_expired(struct CookieInfo *cookies)
{
- struct Cookie *co, *nx, *pv;
+ struct Cookie *co, *nx;
curl_off_t now = (curl_off_t)time(NULL);
unsigned int i;
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ struct Cookie *pv = NULL;
co = cookies->cookies[i];
- pv = NULL;
while(co) {
nx = co->next;
if(co->expires && co->expires < now) {
}
}
+/* Make sure domain contains a dot or is localhost. */
+static bool bad_domain(const char *domain)
+{
+ return !strchr(domain, '.') && !strcasecompare(domain, "localhost");
+}
+
/****************************************************************************
*
* Curl_cookie_add()
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
size_t myhash;
-#ifdef USE_LIBPSL
- const psl_ctx_t *psl;
-#endif
-
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
name + contents. Chrome and Firefox support 4095 or 4096 bytes
combo. */
freecookie(co);
- infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
+ infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n",
nlen, len);
return NULL;
}
* 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 = ":";
- }
+ if(bad_domain(whatptr))
+ domain = ":";
#endif
is_ip = isip(domain ? domain : whatptr);
if(!queryp)
endslash = strrchr(path, '/');
else
- endslash = memrchr(path, '/', (size_t)(queryp - path));
+ endslash = memrchr(path, '/', (queryp - path));
if(endslash) {
- size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */
+ size_t pathlen = (endslash-path + 1); /* include end slash */
co->path = malloc(pathlen + 1); /* one extra for the zero byte */
if(co->path) {
memcpy(co->path, path, pathlen);
}
co->livecookie = c->running;
+ co->creationtime = ++c->lastct;
/* now, we have parsed the incoming line, we must now check if this
- superceeds an already existing cookie, which it may if the previous have
+ supersedes an already existing cookie, which it may if the previous have
the same domain and path as this */
/* at first, remove expired cookies */
remove_expired(c);
#ifdef USE_LIBPSL
- /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
- This needs a libpsl compiled with builtin data. */
+ /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */
if(domain && co->domain && !isip(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);
+ const psl_ctx_t *psl = Curl_psl_use(data);
+ int acceptable;
+
+ if(psl) {
+ acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
+ Curl_psl_release(data);
+ }
+ else
+ acceptable = !bad_domain(domain);
+
+ if(!acceptable) {
+ infof(data, "cookie '%s' dropped, domain '%s' must not "
+ "set cookies for '%s'\n", co->name, domain, co->domain);
freecookie(co);
return NULL;
}
if(replace_old) {
co->next = clist->next; /* get the next-pointer first */
+ /* when replacing, creationtime is kept from old */
+ co->creationtime = clist->creationtime;
+
/* then free all the old pointers */
free(clist->name);
free(clist->value);
if(l1 != l2)
return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
- /* 3 - compare cookie names */
- if(c1->name && c2->name)
- return strcmp(c1->name, c2->name);
+ /* 3 - compare cookie name lengths */
+ l1 = c1->name ? strlen(c1->name) : 0;
+ l2 = c2->name ? strlen(c2->name) : 0;
- /* sorry, can't be more deterministic */
- return 0;
+ if(l1 != l2)
+ return (l2 > l1) ? 1 : -1;
+
+ /* 4 - compare cookie creation time */
+ return (c2->creationtime > c1->creationtime) ? 1 : -1;
+}
+
+/* sort cookies only according to creation time */
+static int cookie_sort_ct(const void *p1, const void *p2)
+{
+ struct Cookie *c1 = *(struct Cookie **)p1;
+ struct Cookie *c2 = *(struct Cookie **)p2;
+
+ return (c2->creationtime > c1->creationtime) ? 1 : -1;
}
#define CLONE(field) \
d->secure = src->secure;
d->livecookie = src->livecookie;
d->httponly = src->httponly;
+ d->creationtime = src->creationtime;
}
return d;
{
struct Cookie *newco;
struct Cookie *co;
- time_t now = time(NULL);
struct Cookie *mainco = NULL;
size_t matches = 0;
bool is_ip;
co = c->cookies[myhash];
while(co) {
- /* only process this cookie if it is not expired or had no expire
- date AND that if the cookie requires we're secure we must only
- continue if we are! */
- if((!co->expires || (co->expires > now)) &&
- (co->secure?secure:TRUE)) {
+ /* if the cookie requires we're secure we must only continue if we are! */
+ if(co->secure?secure:TRUE) {
/* now check if the domain is correct */
if(!co->domain ||
matches++;
}
- else {
- fail:
- /* failure, clear up the allocated chain and return NULL */
- Curl_cookie_freelist(mainco);
- return NULL;
- }
+ else
+ goto fail;
}
}
}
}
return mainco; /* return the new list */
+
+fail:
+ /* failure, clear up the allocated chain and return NULL */
+ Curl_cookie_freelist(mainco);
+ return NULL;
}
/*****************************************************************************
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
- unsigned int i;
-
if(c) {
+ unsigned int i;
free(c->filename);
for(i = 0; i < COOKIE_HASH_SIZE; i++)
Curl_cookie_freelist(c->cookies[i]);
bool use_stdout = FALSE;
char *format_ptr;
unsigned int i;
+ unsigned int j;
+ struct Cookie **array;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
if(0 == c->numcookies)
return 0;
+ array = malloc(sizeof(struct Cookie *) * c->numcookies);
+ if(!array)
+ return 1;
+
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
}
else {
out = fopen(dumphere, FOPEN_WRITETEXT);
- if(!out)
+ if(!out) {
+ free(array);
return 1; /* failure */
+ }
}
fputs("# Netscape HTTP Cookie File\n"
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
+ j = 0;
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
for(co = c->cookies[i]; co; co = co->next) {
if(!co->domain)
continue;
- format_ptr = get_netscape_format(co);
- if(format_ptr == NULL) {
- fprintf(out, "#\n# Fatal libcurl error\n");
- if(!use_stdout)
- fclose(out);
- return 1;
- }
- fprintf(out, "%s\n", format_ptr);
- free(format_ptr);
+ array[j++] = co;
}
}
+ qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+
+ for(i = 0; i < j; i++) {
+ format_ptr = get_netscape_format(array[i]);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ free(array);
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
+ }
+
+ free(array);
+
if(!use_stdout)
fclose(out);
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */
- bool tailmatch; /* weather we do tail-matchning of the domain name */
+ bool tailmatch; /* whether we do tail-matching of the domain name */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
bool httponly; /* true if the httponly directive is present */
+ int creationtime; /* time when the cookie was written */
};
#define COOKIE_HASH_SIZE 256
bool running; /* state info, for cookie adding information */
long numcookies; /* number of cookies in the "jar" */
bool newsession; /* new session, discard session cookies on load */
+ int lastct; /* last creation-time used in the jar */
};
/* This is the maximum line length we accept for a cookie line. RFC 2109
}
#endif
-#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
+#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
+ defined(HAVE_FREEADDRINFO)
/*
* curl_dofreeaddrinfo()
*
/* Define to 1 if bool is an available type. */
#cmakedefine HAVE_BOOL_T 1
+/* Define to 1 if you have the __builtin_available function. */
+#cmakedefine HAVE_BUILTIN_AVAILABLE 1
+
/* Define to 1 if you have the clock_gettime function and monotonic timer. */
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1
/* Define to 1 if you have the `getpwuid' function. */
#cmakedefine HAVE_GETPWUID 1
+/* Define to 1 if you have the `getpwuid_r' function. */
+#cmakedefine HAVE_GETPWUID_R 1
+
/* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT 1
/* The size of `long', as computed by sizeof. */
@SIZEOF_LONG_CODE@
+/* The size of `long long', as computed by sizeof. */
+@SIZEOF_LONG_LONG_CODE@
+
+/* The size of `__int64', as computed by sizeof. */
+@SIZEOF___INT64_CODE@
+
/* The size of `off_t', as computed by sizeof. */
@SIZEOF_OFF_T_CODE@
/* to enable Windows SSL */
#cmakedefine USE_SCHANNEL 1
+/* enable multiple SSL backends */
+#cmakedefine CURL_WITH_MULTI_SSL 1
+
/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
#cmakedefine USE_YASSLEMUL 1
/* The last #include file should be: */
#include "memdebug.h"
+#ifndef HAVE_FNMATCH
+
+/*
+ * TODO:
+ *
+ * Make this function match POSIX. Test 1307 includes a set of test patterns
+ * that returns different results with a POSIX fnmatch() than with this
+ * implementation and this is considered a bug where POSIX is the guiding
+ * light.
+ */
+
#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
s++;
break;
}
+ /* Syntax error in set; mismatch! */
+ return CURL_FNMATCH_NOMATCH;
- /* Syntax error in set: this must be taken as a regular character. */
- /* FALLTHROUGH */
default:
if(*p++ != *s++)
return CURL_FNMATCH_NOMATCH;
if(!pattern || !string) {
return CURL_FNMATCH_FAIL;
}
- return loop((unsigned char *)pattern, (unsigned char *)string, 5);
+ return loop((unsigned char *)pattern, (unsigned char *)string, 2);
+}
+#else
+#include <fnmatch.h>
+/*
+ * @unittest: 1307
+ */
+int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
+{
+ int rc;
+ (void)ptr; /* the argument is specified by the curl_fnmatch_callback
+ prototype, but not used by Curl_fnmatch() */
+ if(!pattern || !string) {
+ return CURL_FNMATCH_FAIL;
+ }
+ rc = fnmatch(pattern, string, 0);
+ switch(rc) {
+ case 0:
+ return CURL_FNMATCH_MATCH;
+ case FNM_NOMATCH:
+ return CURL_FNMATCH_NOMATCH;
+ default:
+ return CURL_FNMATCH_FAIL;
+ }
+ /* not reached */
}
+
+#endif
#endif
#endif /* HEADER_CURL_LDAP_H */
-
unsigned char *ntbuffer /* 21 bytes */)
{
size_t len = strlen(password);
- unsigned char *pw = len ? malloc(len * 2) : strdup("");
+ unsigned char *pw;
CURLcode result;
+ if(len > SIZE_T_MAX/2) /* avoid integer overflow */
+ return CURLE_OUT_OF_MEMORY;
+ pw = len ? malloc(len * 2) : strdup("");
if(!pw)
return CURLE_OUT_OF_MEMORY;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
return CURLE_REMOTE_ACCESS_DENIED;
}
+/* if larger than this, something is seriously wrong */
+#define MAX_NTLM_WB_RESPONSE 100000
+
static CURLcode ntlm_wb_response(struct connectdata *conn,
const char *input, curlntlm state)
{
buf[len_out - 1] = '\0';
break;
}
+
+ if(len_out > MAX_NTLM_WB_RESPONSE) {
+ failf(conn->data, "too large ntlm_wb response!");
+ free(buf);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
if(!newbuf)
return CURLE_OUT_OF_MEMORY;
conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
free(buf);
+ if(!conn->response_header)
+ return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
done:
free(buf);
conn->response_header);
DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
free(conn->response_header);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
conn->response_header = NULL;
break;
case NTLMSTATE_TYPE2:
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
authp->done = TRUE;
Curl_ntlm_wb_cleanup(conn);
+ if(!*allocuserpwd)
+ return CURLE_OUT_OF_MEMORY;
break;
case NTLMSTATE_TYPE3:
/* connection is already authenticated,
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
char *working_path;
size_t working_path_len;
CURLcode result =
- Curl_urldecode(data, data->state.path, 0, &working_path,
+ Curl_urldecode(data, data->state.up.path, 0, &working_path,
&working_path_len, FALSE);
if(result)
return result;
char **path);
CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
-#endif
+#endif /* HEADER_CURL_PATH_H */
/* The last #include file should be: */
#include "memdebug.h"
-#ifdef _WIN32
+#if defined(WIN32) && !defined(USE_LWIPSOCK)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
+#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD)
+#define SET_RCVTIMEO(tv,s) int tv = s*1000
#else
#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
#endif
const char *value, size_t len)
{
CURLcode result = CURLE_OK;
- unsigned int mechbit;
size_t mechlen;
if(!len)
if(!strncmp(value, "*", len))
sasl->prefmech = SASL_AUTH_DEFAULT;
else {
- mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
+ unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
if(mechbit && mechlen == len)
sasl->prefmech |= mechbit;
else
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
+# ifndef NOGDI
+# define NOGDI
+# endif
#endif
/*
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
- * interface doesn’t support IPv4, but supports IPv6, NAT64, and DNS64,
+ * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
* performing this task will result in a synthesized IPv6 address.
*/
#ifdef __APPLE__
# if defined(_UNICODE) && !defined(UNICODE)
# define UNICODE
# endif
+# include <winerror.h>
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
- defined(USE_DARWINSSL) || defined(USE_GSKIT)
+ defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK)
#define USE_SSL /* SSL support has been enabled */
#endif
#define CURL_SA_FAMILY_T unsigned short
#endif
+/* Some convenience macros to get the larger/smaller value out of two given.
+ We prefix with CURL to prevent name collisions. */
+#define CURLMAX(x,y) ((x)>(y)?(x):(y))
+#define CURLMIN(x,y) ((x)<(y)?(x):(y))
+
+/* Some versions of the Android SDK is missing the declaration */
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING)
+struct passwd;
+int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
+ size_t buflen, struct passwd **result);
+#endif
+
#endif /* HEADER_CURL_SETUP_H */
#endif /* HEADER_CURL_SETUP_ONCE_H */
-
return CURLE_FAILED_INIT;
/* Get address of the InitSecurityInterfaceA function from the SSPI dll */
- pInitSecurityInterface = (INITSECURITYINTERFACE_FN)
- GetProcAddress(s_hSecDll, SECURITYENTRYPOINT);
+ pInitSecurityInterface =
+ CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN,
+ (GetProcAddress(s_hSecDll, SECURITYENTRYPOINT)));
if(!pInitSecurityInterface)
return CURLE_FAILED_INIT;
* Parameters:
*
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* identity [in/out] - The identity structure.
*
* Returns CURLE_OK on success.
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg)
{
+#ifdef _WIN32_WCE
+ typedef HANDLE curl_win_thread_handle_t;
+#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+ typedef unsigned long curl_win_thread_handle_t;
+#else
+ typedef uintptr_t curl_win_thread_handle_t;
+#endif
curl_thread_t t;
+ curl_win_thread_handle_t thread_handle;
#ifdef _WIN32_WCE
- t = CreateThread(NULL, 0, func, arg, 0, NULL);
+ thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL);
#else
- t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
+ thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL);
#endif
+ t = (curl_thread_t)thread_handle;
if((t == 0) || (t == LongToHandle(-1L))) {
#ifdef _WIN32_WCE
DWORD gle = GetLastError();
# define curl_thread_t HANDLE
# define curl_thread_t_null (HANDLE)0
# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
- (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
+ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
# define Curl_mutex_init(m) InitializeCriticalSection(m)
# else
# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
#endif /* ENABLE_CURLX_PRINTF */
#endif /* HEADER_CURL_CURLX_H */
-
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
{
char *newp = NULL;
char *dictp;
- char *ptr;
size_t len;
- char ch;
- int olen = 0;
CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
if(!newp || result)
return NULL;
- dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
+ dictp = malloc(len*2 + 1); /* add one for terminating zero */
if(dictp) {
+ char *ptr;
+ char ch;
+ int olen = 0;
/* According to RFC2229 section 2.2, these letters need to be escaped with
\[letter] */
for(ptr = newp;
struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- char *path = data->state.path;
+ char *path = data->state.up.path;
curl_off_t *bytecount = &data->req.bytecount;
*done = TRUE; /* unconditionally */
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2018, Daniel Stenberg, <daniel@haxx.se>, 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"
+
+#include "urldata.h"
+#include "curl_addrinfo.h"
+#include "doh.h"
+
+#ifdef USE_NGHTTP2
+#include "sendf.h"
+#include "multiif.h"
+#include "url.h"
+#include "share.h"
+#include "curl_base64.h"
+#include "connect.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define DNS_CLASS_IN 0x01
+#define DOH_MAX_RESPONSE_SIZE 3000 /* bytes */
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static const char * const errors[]={
+ "",
+ "Bad label",
+ "Out of range",
+ "Label loop",
+ "Too small",
+ "Out of memory",
+ "RDATA length",
+ "Malformat",
+ "Bad RCODE",
+ "Unexpected TYPE",
+ "Unexpected CLASS",
+ "No content",
+ "Bad ID"
+};
+
+static const char *doh_strerror(DOHcode code)
+{
+ if((code >= DOH_OK) && (code <= DOH_DNS_BAD_ID))
+ return errors[code];
+ return "bad error code";
+}
+#endif
+
+#ifdef DEBUGBUILD
+#define UNITTEST
+#else
+#define UNITTEST static
+#endif
+
+UNITTEST DOHcode doh_encode(const char *host,
+ DNStype dnstype,
+ unsigned char *dnsp, /* buffer */
+ size_t len, /* buffer size */
+ size_t *olen) /* output length */
+{
+ size_t hostlen = strlen(host);
+ unsigned char *orig = dnsp;
+ const char *hostp = host;
+
+ if(len < (12 + hostlen + 4))
+ return DOH_TOO_SMALL_BUFFER;
+
+ *dnsp++ = 0; /* 16 bit id */
+ *dnsp++ = 0;
+ *dnsp++ = 0x01; /* |QR| Opcode |AA|TC|RD| Set the RD bit */
+ *dnsp++ = '\0'; /* |RA| Z | RCODE | */
+ *dnsp++ = '\0';
+ *dnsp++ = 1; /* QDCOUNT (number of entries in the question section) */
+ *dnsp++ = '\0';
+ *dnsp++ = '\0'; /* ANCOUNT */
+ *dnsp++ = '\0';
+ *dnsp++ = '\0'; /* NSCOUNT */
+ *dnsp++ = '\0';
+ *dnsp++ = '\0'; /* ARCOUNT */
+
+ /* store a QNAME */
+ do {
+ char *dot = strchr(hostp, '.');
+ size_t labellen;
+ bool found = false;
+ if(dot) {
+ found = true;
+ labellen = dot - hostp;
+ }
+ else
+ labellen = strlen(hostp);
+ if(labellen > 63) {
+ /* too long label, error out */
+ *olen = 0;
+ return DOH_DNS_BAD_LABEL;
+ }
+ *dnsp++ = (unsigned char)labellen;
+ memcpy(dnsp, hostp, labellen);
+ dnsp += labellen;
+ hostp += labellen + 1;
+ if(!found) {
+ *dnsp++ = 0; /* terminating zero */
+ break;
+ }
+ } while(1);
+
+ *dnsp++ = '\0'; /* upper 8 bit TYPE */
+ *dnsp++ = (unsigned char)dnstype;
+ *dnsp++ = '\0'; /* upper 8 bit CLASS */
+ *dnsp++ = DNS_CLASS_IN; /* IN - "the Internet" */
+
+ *olen = dnsp - orig;
+ return DOH_OK;
+}
+
+static size_t
+doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
+{
+ size_t realsize = size * nmemb;
+ struct dohresponse *mem = (struct dohresponse *)userp;
+
+ if((mem->size + realsize) > DOH_MAX_RESPONSE_SIZE)
+ /* suspiciously much for us */
+ return 0;
+
+ mem->memory = realloc(mem->memory, mem->size + realsize);
+ if(mem->memory == NULL)
+ /* out of memory! */
+ return 0;
+
+ memcpy(&(mem->memory[mem->size]), contents, realsize);
+ mem->size += realsize;
+
+ return realsize;
+}
+
+/* called from multi.c when this DOH transfer is complete */
+static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
+{
+ struct Curl_easy *data = doh->set.dohfor;
+ /* so one of the DOH request done for the 'data' transfer is now complete! */
+ data->req.doh.pending--;
+ infof(data, "a DOH request is completed, %d to go\n", data->req.doh.pending);
+ if(result)
+ infof(data, "DOH request %s\n", curl_easy_strerror(result));
+
+ if(!data->req.doh.pending) {
+ /* DOH completed */
+ curl_slist_free_all(data->req.doh.headers);
+ data->req.doh.headers = NULL;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+ return 0;
+}
+
+#define ERROR_CHECK_SETOPT(x,y) result = curl_easy_setopt(doh, x, y); \
+ if(result) goto error
+
+static CURLcode dohprobe(struct Curl_easy *data,
+ struct dnsprobe *p, DNStype dnstype,
+ const char *host,
+ const char *url, CURLM *multi,
+ struct curl_slist *headers)
+{
+ struct Curl_easy *doh = NULL;
+ char *nurl = NULL;
+ CURLcode result = CURLE_OK;
+ timediff_t timeout_ms;
+ DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
+ &p->dohlen);
+ if(d) {
+ failf(data, "Failed to encode DOH packet [%d]\n", d);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ p->dnstype = dnstype;
+ p->serverdoh.memory = NULL;
+ /* the memory will be grown as needed by realloc in the doh_write_cb
+ function */
+ p->serverdoh.size = 0;
+
+ /* Note: this is code for sending the DoH request with GET but there's still
+ no logic that actually enables this. We should either add that ability or
+ yank out the GET code. Discuss! */
+ if(data->set.doh_get) {
+ char *b64;
+ size_t b64len;
+ result = Curl_base64url_encode(data, (char *)p->dohbuffer, p->dohlen,
+ &b64, &b64len);
+ if(result)
+ goto error;
+ nurl = aprintf("%s?dns=%s", url, b64);
+ free(b64);
+ if(!nurl) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ url = nurl;
+ }
+
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ /* Curl_open() is the internal version of curl_easy_init() */
+ result = Curl_open(&doh);
+ if(!result) {
+ /* pass in the struct pointer via a local variable to please coverity and
+ the gcc typecheck helpers */
+ struct dohresponse *resp = &p->serverdoh;
+ ERROR_CHECK_SETOPT(CURLOPT_URL, url);
+ ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
+ ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
+ if(!data->set.doh_get) {
+ ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer);
+ ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
+ }
+ ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
+ ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+#ifndef CURLDEBUG
+ /* enforce HTTPS if not debug */
+ ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
+#endif
+ ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
+ ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+ doh->set.fmultidone = Curl_doh_done;
+ doh->set.dohfor = data; /* identify for which transfer this is done */
+ p->easy = doh;
+
+ /* add this transfer to the multi handle */
+ if(curl_multi_add_handle(multi, doh))
+ goto error;
+ }
+ else
+ goto error;
+ free(nurl);
+ return CURLE_OK;
+
+ error:
+ free(nurl);
+ Curl_close(doh);
+ return result;
+}
+
+/*
+ * Curl_doh() resolves a name using DOH. It resolves a name and returns a
+ * 'Curl_addrinfo *' with the address information.
+ */
+
+Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ struct Curl_easy *data = conn->data;
+ CURLcode result = CURLE_OK;
+ *waitp = TRUE; /* this never returns synchronously */
+ (void)conn;
+ (void)hostname;
+ (void)port;
+
+ /* start clean, consider allocating this struct on demand */
+ memset(&data->req.doh, 0, sizeof(struct dohdata));
+
+ data->req.doh.host = hostname;
+ data->req.doh.port = port;
+ data->req.doh.headers =
+ curl_slist_append(NULL,
+ "Content-Type: application/dns-message");
+ if(!data->req.doh.headers)
+ goto error;
+
+ if(conn->ip_version != CURL_IPRESOLVE_V6) {
+ /* create IPv4 DOH request */
+ result = dohprobe(data, &data->req.doh.probe[0], DNS_TYPE_A,
+ hostname, data->set.str[STRING_DOH],
+ data->multi, data->req.doh.headers);
+ if(result)
+ goto error;
+ data->req.doh.pending++;
+ }
+
+ if(conn->ip_version != CURL_IPRESOLVE_V4) {
+ /* create IPv6 DOH request */
+ result = dohprobe(data, &data->req.doh.probe[1], DNS_TYPE_AAAA,
+ hostname, data->set.str[STRING_DOH],
+ data->multi, data->req.doh.headers);
+ if(result)
+ goto error;
+ data->req.doh.pending++;
+ }
+ return NULL;
+
+ error:
+ curl_slist_free_all(data->req.doh.headers);
+ data->req.doh.headers = NULL;
+ curl_easy_cleanup(data->req.doh.probe[0].easy);
+ data->req.doh.probe[0].easy = NULL;
+ curl_easy_cleanup(data->req.doh.probe[1].easy);
+ data->req.doh.probe[1].easy = NULL;
+ return NULL;
+}
+
+static DOHcode skipqname(unsigned char *doh, size_t dohlen,
+ unsigned int *indexp)
+{
+ unsigned char length;
+ do {
+ if(dohlen < (*indexp + 1))
+ return DOH_DNS_OUT_OF_RANGE;
+ length = doh[*indexp];
+ if((length & 0xc0) == 0xc0) {
+ /* name pointer, advance over it and be done */
+ if(dohlen < (*indexp + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+ *indexp += 2;
+ break;
+ }
+ if(length & 0xc0)
+ return DOH_DNS_BAD_LABEL;
+ if(dohlen < (*indexp + 1 + length))
+ return DOH_DNS_OUT_OF_RANGE;
+ *indexp += 1 + length;
+ } while(length);
+ return DOH_OK;
+}
+
+static unsigned short get16bit(unsigned char *doh, int index)
+{
+ return (unsigned short)((doh[index] << 8) | doh[index + 1]);
+}
+
+static unsigned int get32bit(unsigned char *doh, int index)
+{
+ return (doh[index] << 24) | (doh[index + 1] << 16) |
+ (doh[index + 2] << 8) | doh[index + 3];
+}
+
+static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d)
+{
+ /* silently ignore addresses over the limit */
+ if(d->numaddr < DOH_MAX_ADDR) {
+ struct dohaddr *a = &d->addr[d->numaddr];
+ a->type = DNS_TYPE_A;
+ memcpy(&a->ip.v4, &doh[index], 4);
+ d->numaddr++;
+ }
+ return DOH_OK;
+}
+
+static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d)
+{
+ /* silently ignore addresses over the limit */
+ if(d->numaddr < DOH_MAX_ADDR) {
+ struct dohaddr *a = &d->addr[d->numaddr];
+ a->type = DNS_TYPE_AAAA;
+ memcpy(&a->ip.v6, &doh[index], 16);
+ d->numaddr++;
+ }
+ return DOH_OK;
+}
+
+static DOHcode cnameappend(struct cnamestore *c,
+ unsigned char *src,
+ size_t len)
+{
+ if(!c->alloc) {
+ c->allocsize = len + 1;
+ c->alloc = malloc(c->allocsize);
+ if(!c->alloc)
+ return DOH_OUT_OF_MEM;
+ }
+ else if(c->allocsize < (c->allocsize + len + 1)) {
+ char *ptr;
+ c->allocsize += len + 1;
+ ptr = realloc(c->alloc, c->allocsize);
+ if(!ptr) {
+ free(c->alloc);
+ return DOH_OUT_OF_MEM;
+ }
+ c->alloc = ptr;
+ }
+ memcpy(&c->alloc[c->len], src, len);
+ c->len += len;
+ c->alloc[c->len] = 0; /* keep it zero terminated */
+ return DOH_OK;
+}
+
+static DOHcode store_cname(unsigned char *doh,
+ size_t dohlen,
+ unsigned int index,
+ struct dohentry *d)
+{
+ struct cnamestore *c;
+ unsigned int loop = 128; /* a valid DNS name can never loop this much */
+ unsigned char length;
+
+ if(d->numcname == DOH_MAX_CNAME)
+ return DOH_OK; /* skip! */
+
+ c = &d->cname[d->numcname++];
+ do {
+ if(index >= dohlen)
+ return DOH_DNS_OUT_OF_RANGE;
+ length = doh[index];
+ if((length & 0xc0) == 0xc0) {
+ int newpos;
+ /* name pointer, get the new offset (14 bits) */
+ if((index + 1) >= dohlen)
+ return DOH_DNS_OUT_OF_RANGE;
+
+ /* move to the the new index */
+ newpos = (length & 0x3f) << 8 | doh[index + 1];
+ index = newpos;
+ continue;
+ }
+ else if(length & 0xc0)
+ return DOH_DNS_BAD_LABEL; /* bad input */
+ else
+ index++;
+
+ if(length) {
+ DOHcode rc;
+ if(c->len) {
+ rc = cnameappend(c, (unsigned char *)".", 1);
+ if(rc)
+ return rc;
+ }
+ if((index + length) > dohlen)
+ return DOH_DNS_BAD_LABEL;
+
+ rc = cnameappend(c, &doh[index], length);
+ if(rc)
+ return rc;
+ index += length;
+ }
+ } while(length && --loop);
+
+ if(!loop)
+ return DOH_DNS_LABEL_LOOP;
+ return DOH_OK;
+}
+
+static DOHcode rdata(unsigned char *doh,
+ size_t dohlen,
+ unsigned short rdlength,
+ unsigned short type,
+ int index,
+ struct dohentry *d)
+{
+ /* RDATA
+ - A (TYPE 1): 4 bytes
+ - AAAA (TYPE 28): 16 bytes
+ - NS (TYPE 2): N bytes */
+ DOHcode rc;
+
+ switch(type) {
+ case DNS_TYPE_A:
+ if(rdlength != 4)
+ return DOH_DNS_RDATA_LEN;
+ rc = store_a(doh, index, d);
+ if(rc)
+ return rc;
+ break;
+ case DNS_TYPE_AAAA:
+ if(rdlength != 16)
+ return DOH_DNS_RDATA_LEN;
+ rc = store_aaaa(doh, index, d);
+ if(rc)
+ return rc;
+ break;
+ case DNS_TYPE_CNAME:
+ rc = store_cname(doh, dohlen, index, d);
+ if(rc)
+ return rc;
+ break;
+ default:
+ /* unsupported type, just skip it */
+ break;
+ }
+ return DOH_OK;
+}
+
+static void init_dohentry(struct dohentry *de)
+{
+ memset(de, 0, sizeof(*de));
+ de->ttl = INT_MAX;
+}
+
+
+UNITTEST DOHcode doh_decode(unsigned char *doh,
+ size_t dohlen,
+ DNStype dnstype,
+ struct dohentry *d)
+{
+ unsigned char rcode;
+ unsigned short qdcount;
+ unsigned short ancount;
+ unsigned short type = 0;
+ unsigned short class;
+ unsigned short rdlength;
+ unsigned short nscount;
+ unsigned short arcount;
+ unsigned int index = 12;
+ DOHcode rc;
+
+ if(dohlen < 12)
+ return DOH_TOO_SMALL_BUFFER; /* too small */
+ if(doh[0] || doh[1])
+ return DOH_DNS_BAD_ID; /* bad ID */
+ rcode = doh[3] & 0x0f;
+ if(rcode)
+ return DOH_DNS_BAD_RCODE; /* bad rcode */
+
+ qdcount = get16bit(doh, 4);
+ while(qdcount) {
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+ if(dohlen < (index + 4))
+ return DOH_DNS_OUT_OF_RANGE;
+ index += 4; /* skip question's type and class */
+ qdcount--;
+ }
+
+ ancount = get16bit(doh, 6);
+ while(ancount) {
+ unsigned int ttl;
+
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ type = get16bit(doh, index);
+ if((type != DNS_TYPE_CNAME) && (type != dnstype))
+ /* Not the same type as was asked for nor CNAME */
+ return DOH_DNS_UNEXPECTED_TYPE;
+ index += 2;
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+ class = get16bit(doh, index);
+ if(DNS_CLASS_IN != class)
+ return DOH_DNS_UNEXPECTED_CLASS; /* unsupported */
+ index += 2;
+
+ if(dohlen < (index + 4))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ ttl = get32bit(doh, index);
+ if(ttl < d->ttl)
+ d->ttl = ttl;
+ index += 4;
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rdlength = get16bit(doh, index);
+ index += 2;
+ if(dohlen < (index + rdlength))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rc = rdata(doh, dohlen, rdlength, type, index, d);
+ if(rc)
+ return rc; /* bad rdata */
+ index += rdlength;
+ ancount--;
+ }
+
+ nscount = get16bit(doh, 8);
+ while(nscount) {
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+
+ if(dohlen < (index + 8))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ index += 2 + 2 + 4; /* type, class and ttl */
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rdlength = get16bit(doh, index);
+ index += 2;
+ if(dohlen < (index + rdlength))
+ return DOH_DNS_OUT_OF_RANGE;
+ index += rdlength;
+ nscount--;
+ }
+
+ arcount = get16bit(doh, 10);
+ while(arcount) {
+ rc = skipqname(doh, dohlen, &index);
+ if(rc)
+ return rc; /* bad qname */
+
+ if(dohlen < (index + 8))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ index += 2 + 2 + 4; /* type, class and ttl */
+
+ if(dohlen < (index + 2))
+ return DOH_DNS_OUT_OF_RANGE;
+
+ rdlength = get16bit(doh, index);
+ index += 2;
+ if(dohlen < (index + rdlength))
+ return DOH_DNS_OUT_OF_RANGE;
+ index += rdlength;
+ arcount--;
+ }
+
+ if(index != dohlen)
+ return DOH_DNS_MALFORMAT; /* something is wrong */
+
+ if((type != DNS_TYPE_NS) && !d->numcname && !d->numaddr)
+ /* nothing stored! */
+ return DOH_NO_CONTENT;
+
+ return DOH_OK; /* ok */
+}
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void showdoh(struct Curl_easy *data,
+ struct dohentry *d)
+{
+ int i;
+ infof(data, "TTL: %u seconds\n", d->ttl);
+ for(i = 0; i < d->numaddr; i++) {
+ struct dohaddr *a = &d->addr[i];
+ if(a->type == DNS_TYPE_A) {
+ infof(data, "DOH A: %u.%u.%u.%u\n",
+ a->ip.v4[0], a->ip.v4[1],
+ a->ip.v4[2], a->ip.v4[3]);
+ }
+ else if(a->type == DNS_TYPE_AAAA) {
+ int j;
+ char buffer[128];
+ char *ptr;
+ size_t len;
+ snprintf(buffer, 128, "DOH AAAA: ");
+ ptr = &buffer[10];
+ len = 118;
+ for(j = 0; j < 16; j += 2) {
+ size_t l;
+ snprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
+ d->addr[i].ip.v6[j + 1]);
+ l = strlen(ptr);
+ len -= l;
+ ptr += l;
+ }
+ infof(data, "%s\n", buffer);
+ }
+ }
+ for(i = 0; i < d->numcname; i++) {
+ infof(data, "CNAME: %s\n", d->cname[i].alloc);
+ }
+}
+#else
+#define showdoh(x,y)
+#endif
+
+/*
+ * doh2ai()
+ *
+ * This function returns a pointer to the first element of a newly allocated
+ * Curl_addrinfo struct linked list filled with the data from a set of DOH
+ * lookups. Curl_addrinfo is meant to work like the addrinfo struct does for
+ * a IPv6 stack, but usable also for IPv4, all hosts and environments.
+ *
+ * The memory allocated by this function *MUST* be free'd later on calling
+ * Curl_freeaddrinfo(). For each successful call to this function there
+ * must be an associated call later to Curl_freeaddrinfo().
+ */
+
+static Curl_addrinfo *
+doh2ai(const struct dohentry *de, const char *hostname, int port)
+{
+ Curl_addrinfo *ai;
+ Curl_addrinfo *prevai = NULL;
+ Curl_addrinfo *firstai = NULL;
+ struct sockaddr_in *addr;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *addr6;
+#endif
+ CURLcode result = CURLE_OK;
+ int i;
+
+ if(!de)
+ /* no input == no output! */
+ return NULL;
+
+ for(i = 0; i < de->numaddr; i++) {
+ size_t ss_size;
+ CURL_SA_FAMILY_T addrtype;
+ if(de->addr[i].type == DNS_TYPE_AAAA) {
+#ifndef ENABLE_IPV6
+ /* we can't handle IPv6 addresses */
+ continue;
+#else
+ ss_size = sizeof(struct sockaddr_in6);
+ addrtype = AF_INET6;
+#endif
+ }
+ else {
+ ss_size = sizeof(struct sockaddr_in);
+ addrtype = AF_INET;
+ }
+
+ ai = calloc(1, sizeof(Curl_addrinfo));
+ if(!ai) {
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ ai->ai_canonname = strdup(hostname);
+ if(!ai->ai_canonname) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai);
+ break;
+ }
+ ai->ai_addr = calloc(1, ss_size);
+ if(!ai->ai_addr) {
+ result = CURLE_OUT_OF_MEMORY;
+ free(ai->ai_canonname);
+ free(ai);
+ break;
+ }
+
+ if(!firstai)
+ /* store the pointer we want to return from this function */
+ firstai = ai;
+
+ if(prevai)
+ /* make the previous entry point to this */
+ prevai->ai_next = ai;
+
+ ai->ai_family = addrtype;
+
+ /* we return all names as STREAM, so when using this address for TFTP
+ the type must be ignored and conn->socktype be used instead! */
+ ai->ai_socktype = SOCK_STREAM;
+
+ ai->ai_addrlen = (curl_socklen_t)ss_size;
+
+ /* leave the rest of the struct filled with zero */
+
+ switch(ai->ai_family) {
+ case AF_INET:
+ addr = (void *)ai->ai_addr; /* storage area for this info */
+ DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4));
+ memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr));
+ addr->sin_family = (CURL_SA_FAMILY_T)addrtype;
+ addr->sin_port = htons((unsigned short)port);
+ break;
+
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ addr6 = (void *)ai->ai_addr; /* storage area for this info */
+ DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6));
+ memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr));
+ addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype;
+ addr6->sin6_port = htons((unsigned short)port);
+ break;
+#endif
+ }
+
+ prevai = ai;
+ }
+
+ if(result) {
+ Curl_freeaddrinfo(firstai);
+ firstai = NULL;
+ }
+
+ return firstai;
+}
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static const char *type2name(DNStype dnstype)
+{
+ return (dnstype == DNS_TYPE_A)?"A":"AAAA";
+}
+#endif
+
+UNITTEST void de_cleanup(struct dohentry *d)
+{
+ int i = 0;
+ for(i = 0; i < d->numcname; i++) {
+ free(d->cname[i].alloc);
+ }
+}
+
+CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dnsp)
+{
+ struct Curl_easy *data = conn->data;
+ *dnsp = NULL; /* defaults to no response */
+
+ if(!data->req.doh.probe[0].easy && !data->req.doh.probe[1].easy) {
+ failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
+ return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else if(!data->req.doh.pending) {
+ DOHcode rc;
+ DOHcode rc2;
+ struct dohentry de;
+ struct Curl_dns_entry *dns;
+ struct Curl_addrinfo *ai;
+ /* remove DOH handles from multi handle and close them */
+ curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy);
+ Curl_close(data->req.doh.probe[0].easy);
+ curl_multi_remove_handle(data->multi, data->req.doh.probe[1].easy);
+ Curl_close(data->req.doh.probe[1].easy);
+
+ /* parse the responses, create the struct and return it! */
+ init_dohentry(&de);
+ rc = doh_decode(data->req.doh.probe[0].serverdoh.memory,
+ data->req.doh.probe[0].serverdoh.size,
+ data->req.doh.probe[0].dnstype,
+ &de);
+ free(data->req.doh.probe[0].serverdoh.memory);
+ if(rc) {
+ infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc),
+ type2name(data->req.doh.probe[0].dnstype),
+ data->req.doh.host);
+ }
+ rc2 = doh_decode(data->req.doh.probe[1].serverdoh.memory,
+ data->req.doh.probe[1].serverdoh.size,
+ data->req.doh.probe[1].dnstype,
+ &de);
+ free(data->req.doh.probe[1].serverdoh.memory);
+ if(rc2) {
+ infof(data, "DOG: %s type %s for %s\n", doh_strerror(rc2),
+ type2name(data->req.doh.probe[1].dnstype),
+ data->req.doh.host);
+ }
+ if(!rc || !rc2) {
+ infof(data, "DOH Host name: %s\n", data->req.doh.host);
+ showdoh(data, &de);
+
+ ai = doh2ai(&de, data->req.doh.host, data->req.doh.port);
+ if(!ai) {
+ de_cleanup(&de);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->share)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+ /* we got a response, store it in the cache */
+ dns = Curl_cache_addr(data, ai, data->req.doh.host, data->req.doh.port);
+
+ if(data->share)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+ de_cleanup(&de);
+ if(!dns)
+ /* returned failure, bail out nicely */
+ Curl_freeaddrinfo(ai);
+ else {
+ conn->async.dns = dns;
+ *dnsp = dns;
+ return CURLE_OK;
+ }
+ }
+ de_cleanup(&de);
+
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
+
+ return CURLE_OK;
+}
+
+#else /* !USE_NGHTTP2 */
+/*
+ */
+Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
+{
+ (void)conn;
+ (void)hostname;
+ (void)port;
+ (void)waitp;
+ return NULL;
+}
+
+CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dnsp)
+{
+ (void)conn;
+ (void)dnsp;
+ return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* USE_NGHTTP2 */
--- /dev/null
+#ifndef HEADER_CURL_DOH_H
+#define HEADER_CURL_DOH_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2018, Daniel Stenberg, <daniel@haxx.se>, 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 "urldata.h"
+#include "curl_addrinfo.h"
+
+/*
+ * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
+ * and returns a 'Curl_addrinfo *' with the address information.
+ */
+
+Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
+
+CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+ struct Curl_dns_entry **dns);
+
+int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks,
+ int numsocks);
+
+typedef enum {
+ DOH_OK,
+ DOH_DNS_BAD_LABEL, /* 1 */
+ DOH_DNS_OUT_OF_RANGE, /* 2 */
+ DOH_DNS_LABEL_LOOP, /* 3 */
+ DOH_TOO_SMALL_BUFFER, /* 4 */
+ DOH_OUT_OF_MEM, /* 5 */
+ DOH_DNS_RDATA_LEN, /* 6 */
+ DOH_DNS_MALFORMAT, /* 7 */
+ DOH_DNS_BAD_RCODE, /* 8 - no such name */
+ DOH_DNS_UNEXPECTED_TYPE, /* 9 */
+ DOH_DNS_UNEXPECTED_CLASS, /* 10 */
+ DOH_NO_CONTENT, /* 11 */
+ DOH_DNS_BAD_ID /* 12 */
+} DOHcode;
+
+typedef enum {
+ DNS_TYPE_A = 1,
+ DNS_TYPE_NS = 2,
+ DNS_TYPE_CNAME = 5,
+ DNS_TYPE_AAAA = 28
+} DNStype;
+
+#define DOH_MAX_ADDR 24
+#define DOH_MAX_CNAME 4
+
+struct cnamestore {
+ size_t len; /* length of cname */
+ char *alloc; /* allocated pointer */
+ size_t allocsize; /* allocated size */
+};
+
+struct dohaddr {
+ int type;
+ union {
+ unsigned char v4[4]; /* network byte order */
+ unsigned char v6[16];
+ } ip;
+};
+
+struct dohentry {
+ unsigned int ttl;
+ int numaddr;
+ struct dohaddr addr[DOH_MAX_ADDR];
+ int numcname;
+ struct cnamestore cname[DOH_MAX_CNAME];
+};
+
+
+#ifdef DEBUGBUILD
+DOHcode doh_encode(const char *host,
+ DNStype dnstype,
+ unsigned char *dnsp, /* buffer */
+ size_t len, /* buffer size */
+ size_t *olen); /* output length */
+DOHcode doh_decode(unsigned char *doh,
+ size_t dohlen,
+ DNStype dnstype,
+ struct dohentry *d);
+void de_cleanup(struct dohentry *d);
+#endif
+#endif /* HEADER_CURL_DOH_H */
if(!out)
return NULL; /* out of memory */
+ *out = 0; /* zero terminates, for inputs like "./" */
+
/* get a cloned copy of the input */
clone = strdup(input);
if(!clone) {
*
***************************************************************************/
char *Curl_dedotdotify(const char *input);
-#endif
+#endif /* HEADER_CURL_DOTDOT_H */
res = WSAStartup(wVersionRequested, &wsaData);
if(res != 0)
- /* Tell the user that we couldn't find a useable */
+ /* Tell the user that we couldn't find a usable */
/* winsock.dll. */
return CURLE_FAILED_INIT;
if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
- /* Tell the user that we couldn't find a useable */
+ /* Tell the user that we couldn't find a usable */
/* winsock.dll. */
WSACleanup();
bool done = FALSE;
CURLMcode mcode = CURLM_OK;
CURLcode result = CURLE_OK;
- struct curltime before;
- int without_fds = 0; /* count number of consecutive returns from
- curl_multi_wait() without any filedescriptors */
while(!done && !mcode) {
int still_running = 0;
int rc;
- before = Curl_now();
mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
if(!mcode) {
if(!rc) {
- struct curltime after = Curl_now();
+ long sleep_ms;
/* If it returns without any filedescriptor instantly, we need to
avoid busy-looping during periods where it has nothing particular
to wait for */
- if(Curl_timediff(after, before) <= 10) {
- without_fds++;
- if(without_fds > 2) {
- int sleep_ms = without_fds < 10 ? (1 << (without_fds - 1)) : 1000;
- Curl_wait_ms(sleep_ms);
- }
+ curl_multi_timeout(multi, &sleep_ms);
+ if(sleep_ms) {
+ if(sleep_ms > 1000)
+ sleep_ms = 1000;
+ Curl_wait_ms((int)sleep_ms);
}
- else
- /* it wasn't "instant", restart counter */
- without_fds = 0;
}
- else
- /* got file descriptor, restart counter */
- without_fds = 0;
mcode = curl_multi_perform(multi, &still_running);
}
outcurl->change.referer_alloc = TRUE;
}
+ /* Reinitialize an SSL engine for the new handle
+ * note: the engine name has already been copied by dupset */
+ if(outcurl->set.str[STRING_SSL_ENGINE]) {
+ if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE]))
+ goto fail;
+ }
+
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(&outcurl->state.resolver,
data->state.resolver))
*/
void curl_easy_reset(struct Curl_easy *data)
{
- Curl_safefree(data->state.pathbuffer);
-
- data->state.path = NULL;
-
Curl_free_request_state(data);
/* zero out UserDefined data: */
return result;
}
+
+/*
+ * Performs connection upkeep for the given session handle.
+ */
+CURLcode curl_easy_upkeep(struct Curl_easy *data)
+{
+ /* Verify that we got an easy handle we can work with. */
+ if(!GOOD_EASY_HANDLE(data))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(data->multi_easy) {
+ /* Use the common function to keep connections alive. */
+ return Curl_upkeep(&data->multi_easy->conn_cache, data);
+ }
+ else {
+ /* No connections, so just return success */
+ return CURLE_OK;
+ }
+}
#endif
#endif /* HEADER_CURL_EASYIF_H */
-
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
its behavior is altered by the current locale.
See https://tools.ietf.org/html/rfc3986#section-2.3
*/
-static bool Curl_isunreserved(unsigned char in)
+bool Curl_isunreserved(unsigned char in)
{
switch(in) {
case '0': case '1': case '2': case '3': case '4':
size_t alloc;
char *ns;
char *testing_ptr = NULL;
- unsigned char in; /* we need to treat the characters unsigned */
size_t newlen;
size_t strindex = 0;
size_t length;
length = alloc-1;
while(length--) {
- in = *string;
+ unsigned char in = *string; /* we need to treat the characters unsigned */
if(Curl_isunreserved(in))
/* just copy this */
* Returns a pointer to a malloced string in *ostring with length given in
* *olen. If length == 0, the length is assumed to be strlen(string).
*
+ * 'data' can be set to NULL but then this function can't convert network
+ * data to host for non-ascii.
*/
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
{
size_t alloc = (length?length:strlen(string)) + 1;
char *ns = malloc(alloc);
- unsigned char in;
size_t strindex = 0;
unsigned long hex;
- CURLcode result;
+ CURLcode result = CURLE_OK;
if(!ns)
return CURLE_OUT_OF_MEMORY;
while(--alloc > 0) {
- in = *string;
+ unsigned char in = *string;
if(('%' == in) && (alloc > 2) &&
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
- result = Curl_convert_from_network(data, (char *)&in, 1);
- if(result) {
- /* Curl_convert_from_network calls failf if unsuccessful */
- free(ns);
- return result;
+ if(data) {
+ result = Curl_convert_from_network(data, (char *)&in, 1);
+ if(result) {
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ free(ns);
+ return result;
+ }
}
string += 2;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
+bool Curl_isunreserved(unsigned char in);
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
char **ostring, size_t *olen,
bool reject_crlf);
#endif /* HEADER_CURL_ESCAPE_H */
-
#endif
size_t real_path_len;
- CURLcode result = Curl_urldecode(data, data->state.path, 0, &real_path,
+ CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path,
&real_path_len, FALSE);
if(result)
return result;
file->fd = fd;
if(!data->set.upload && (fd == -1)) {
- failf(data, "Couldn't open file %s", data->state.path);
+ failf(data, "Couldn't open file %s", data->state.up.path);
file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
return CURLE_FILE_COULDNT_READ_FILE;
}
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
- size_t nread;
- size_t nwrite;
curl_off_t bytecount = 0;
struct_stat file_stat;
const char *buf2;
}
while(!result) {
- int readcount;
- result = Curl_fillreadbuffer(conn, (int)data->set.buffer_size, &readcount);
+ size_t nread;
+ size_t nwrite;
+ size_t readcount;
+ result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount);
if(result)
break;
if(readcount <= 0) /* fix questionable compare error. curlvms */
break;
- nread = (size_t)readcount;
+ nread = readcount;
/*skip bytes before resume point*/
if(data->state.resume_from) {
curl_off_t expected_size = 0;
bool size_known;
bool fstated = FALSE;
- ssize_t nread;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
*done = TRUE; /* unconditionally */
- Curl_initinfo(data);
Curl_pgrsStartNow(data);
if(data->set.upload)
}
}
- /* If we have selected NOBODY and HEADER, it means that we only want file
- information. Which for FILE can't be much more than the file size and
- date. */
- if(data->set.opt_no_body && data->set.include_header && fstated) {
+ if(fstated) {
time_t filetime;
struct tm buffer;
const struct tm *tm = &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, header, 0);
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
if(result)
return result;
- result = Curl_client_write(conn, CLIENTWRITE_BOTH,
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER,
(char *)"Accept-ranges: bytes\r\n", 0);
if(result)
return result;
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
snprintf(header, sizeof(header),
- "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
Curl_month[tm->tm_mon],
tm->tm_year + 1900,
tm->tm_hour,
tm->tm_min,
- tm->tm_sec);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, header, 0);
- if(!result)
- /* set the file size to make it available post transfer */
- Curl_pgrsSetDownloadSize(data, expected_size);
- return result;
+ tm->tm_sec,
+ data->set.opt_no_body ? "": "\r\n");
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
+ if(result)
+ return result;
+ /* set the file size to make it available post transfer */
+ Curl_pgrsSetDownloadSize(data, expected_size);
+ if(data->set.opt_no_body)
+ return result;
}
/* Check whether file range has been specified */
return result;
/* Adjust the start offset in case we want to get the N last bytes
- * of the stream iff the filesize could be determined */
+ * of the stream if the filesize could be determined */
if(data->state.resume_from < 0) {
if(!fstated) {
failf(data, "Can't get the size of file.");
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
while(!result) {
+ ssize_t nread;
/* Don't fill a whole buffer if we want less than all data */
size_t bytestoread;
#endif
#endif /* HEADER_CURL_FILE_H */
-
#include "sendf.h"
#include "strdup.h"
#include "rand.h"
+#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-/* What kind of Content-Type to use on un-specified files with unrecognized
- extensions. */
-#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
-
#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
* Set the contents property.
*/
case CURLFORM_PTRCONTENTS:
- current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
+ current_form->flags |= HTTPPOST_PTRCONTENTS;
+ /* FALLTHROUGH */
case CURLFORM_COPYCONTENTS:
if(current_form->value)
return_value = CURL_FORMADD_OPTION_TWICE;
while(!result) {
char buffer[8192];
- size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
+ size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart);
if(!nread)
break;
{
CURLcode result = CURLE_OK;
curl_mime *form = NULL;
- curl_mime *multipart;
curl_mimepart *part;
struct curl_httppost *file;
/* Process each top part. */
for(; !result && post; post = post->next) {
/* If we have more than a file here, create a mime subpart and fill it. */
- multipart = form;
+ curl_mime *multipart = form;
if(post->more) {
part = curl_mime_addpart(form);
if(!part)
compatibility: use of "-" pseudo file name should be avoided. */
result = curl_mime_data_cb(part, (curl_off_t) -1,
(curl_read_callback) fread,
- (curl_seek_callback) fseek,
+ CURLX_FUNCTION_CAST(curl_seek_callback,
+ fseek),
NULL, (void *) stdin);
}
else
static void freedirs(struct ftp_conn *ftpc)
{
- int i;
if(ftpc->dirs) {
+ int i;
for(i = 0; i < ftpc->dirdepth; i++) {
free(ftpc->dirs[i]);
ftpc->dirs[i] = NULL;
* line in a response or continue reading. */
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- 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;
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
- timeout = Curl_pp_state_timeout(pp);
+ time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */
+ time_t interval_ms;
if(timeout <= 0) {
failf(data, "FTP response timeout");
{
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
+ struct FTP *ftp = data->req.protop;
/* If this output is to be machine-parsed, the NLST command might be better
to use, since the LIST command output is not specified or standard in any
then just do LIST (in that case: nothing to do here)
*/
char *cmd, *lstArg, *slashPos;
- const char *inpath = data->state.path;
+ const char *inpath = ftp->path;
lstArg = NULL;
if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
struct FTP *ftp = conn->data->req.protop;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- int seekerr = CURL_SEEKFUNC_OK;
if((data->state.resume_from && !sizechecked) ||
((data->state.resume_from > 0) && sizechecked)) {
/* 3. pass file-size number of bytes in the source file */
/* 4. lower the infilesize counter */
/* => transfer as usual */
+ int seekerr = CURL_SEEKFUNC_OK;
if(data->state.resume_from < 0) {
/* Got no given size to start from, figure it out */
char *ptr = &data->state.buffer[4]; /* start on the first letter */
const size_t buf_size = data->set.buffer_size;
char *dir;
- char *store;
bool entry_extracted = FALSE;
dir = malloc(nread + 1);
if('\"' == *ptr) {
/* it started good */
+ char *store;
ptr++;
for(store = dir; *ptr;) {
if('\"' == *ptr) {
int ftpcode;
CURLcode result = CURLE_OK;
char *path = NULL;
- const char *path_to_use = data->state.path;
if(!ftp)
return CURLE_OK;
if(!result)
/* get the "raw" path */
- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, TRUE);
+ result = Curl_urldecode(data, ftp->path, 0, &path, NULL, TRUE);
if(result) {
/* We can limp along anyway (and should try to since we may already be in
* the error path) */
ftpc->prevpath[dlen] = 0; /* terminate */
}
else {
+ free(path);
/* we never changed dir */
ftpc->prevpath = strdup("");
- free(path);
+ if(!ftpc->prevpath)
+ return CURLE_OUT_OF_MEMORY;
}
if(ftpc->prevpath)
infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
/* Send any post-transfer QUOTE strings? */
if(!status && !result && !premature && data->set.postquote)
result = ftp_sendquote(conn, data->set.postquote);
-
+ Curl_safefree(ftp->pathalloc);
return result;
}
static CURLcode init_wc_data(struct connectdata *conn)
{
char *last_slash;
- char *path = conn->data->state.path;
+ struct FTP *ftp = conn->data->req.protop;
+ char *path = ftp->path;
struct WildcardData *wildcard = &(conn->data->wildcard);
CURLcode result = CURLE_OK;
struct ftp_wc *ftpwc = NULL;
- last_slash = strrchr(conn->data->state.path, '/');
+ last_slash = strrchr(ftp->path, '/');
if(last_slash) {
last_slash++;
if(last_slash[0] == '\0') {
goto fail;
}
- wildcard->path = strdup(conn->data->state.path);
+ wildcard->path = strdup(ftp->path);
if(!wildcard->path) {
result = CURLE_OUT_OF_MEMORY;
goto fail;
/* filelist has at least one file, lets get first one */
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
+ struct FTP *ftp = conn->data->req.protop;
char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
if(!tmp_path)
return CURLE_OUT_OF_MEMORY;
- /* switch default "state.pathbuffer" and tmp_path, good to see
- ftp_parse_url_path function to understand this trick */
- Curl_safefree(conn->data->state.pathbuffer);
- conn->data->state.pathbuffer = tmp_path;
- conn->data->state.path = tmp_path;
+ /* switch default ftp->path and tmp_path */
+ free(ftp->pathalloc);
+ ftp->pathalloc = ftp->path = tmp_path;
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
if(conn->data->set.chunk_bgn) {
enum protection_level data_sec = conn->data_prot;
#endif
+ if(!cmd)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
write_len = strlen(cmd);
- if(write_len > (sizeof(s) -3))
+ if(!write_len || write_len > (sizeof(s) -3))
return CURLE_BAD_FUNCTION_ARGUMENT;
+ memcpy(&s, cmd, write_len);
strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
write_len += 2;
bytes_written = 0;
break;
if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT,
- sptr, (size_t)bytes_written, conn);
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
if(bytes_written != (ssize_t)write_len) {
write_len -= bytes_written;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
const char *slash_pos; /* position of the first '/' char in curpos */
- const char *path_to_use = data->state.path;
+ const char *path_to_use = ftp->path;
const char *cur_pos;
const char *filename = NULL;
/* parse the URL path into separate path components */
while((slash_pos = strchr(cur_pos, '/')) != NULL) {
/* 1 or 0 pointer offset to indicate absolute directory */
- ssize_t absolute_dir = ((cur_pos - data->state.path > 0) &&
+ ssize_t absolute_dir = ((cur_pos - ftp->path > 0) &&
(ftpc->dirdepth == 0))?1:0;
/* seek out the next path component */
size_t dlen;
char *path;
CURLcode result =
- Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, TRUE);
+ Curl_urldecode(conn->data, ftp->path, 0, &path, &dlen, TRUE);
if(result) {
freedirs(ftpc);
return result;
{
struct Curl_easy *data = conn->data;
char *type;
- char command;
struct FTP *ftp;
- conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
+ conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1);
if(NULL == ftp)
return CURLE_OUT_OF_MEMORY;
- data->state.path++; /* don't include the initial slash */
+ ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
data->state.slash_removed = TRUE; /* we've skipped the slash */
/* FTP URLs support an extension like ";type=<typecode>" that
* we'll try to get now! */
- type = strstr(data->state.path, ";type=");
+ type = strstr(ftp->path, ";type=");
if(!type)
type = strstr(conn->host.rawalloc, ";type=");
if(type) {
+ char command;
*type = 0; /* it was in the middle of the hostname */
command = Curl_raw_toupper(type[6]);
conn->bits.type_set = TRUE;
curl_off_t *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
+ char *path; /* points to the urlpieces struct field */
+ char *pathalloc; /* if non-NULL a pointer to an allocated path */
/* transfer a file/body or not, done as a typedefed enum just to make
debuggers display the full symbol and not just the numerical value */
#ifdef USE_SSL
Curl_ssl_free_certinfo(data);
#endif
-
return CURLE_OK;
}
*param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
data->progress.size_ul:-1;
break;
+ case CURLINFO_TOTAL_TIME_T:
+ *param_offt = data->progress.timespent;
+ break;
+ case CURLINFO_NAMELOOKUP_TIME_T:
+ *param_offt = data->progress.t_nslookup;
+ break;
+ case CURLINFO_CONNECT_TIME_T:
+ *param_offt = data->progress.t_connect;
+ break;
+ case CURLINFO_APPCONNECT_TIME_T:
+ *param_offt = data->progress.t_appconnect;
+ break;
+ case CURLINFO_PRETRANSFER_TIME_T:
+ *param_offt = data->progress.t_pretransfer;
+ break;
+ case CURLINFO_STARTTRANSFER_TIME_T:
+ *param_offt = data->progress.t_starttransfer;
+ break;
+ case CURLINFO_REDIRECT_TIME_T:
+ *param_offt = data->progress.t_redirect;
+ break;
+
default:
return CURLE_UNKNOWN_OPTION;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
curl_off_t *bytecount = &data->req.bytecount;
- char *path = data->state.path;
+ char *path = data->state.up.path;
char *sel = NULL;
char *sel_org = NULL;
ssize_t amount, k;
/* Create selector. Degenerate cases: / and /1 => convert to "" */
if(strlen(path) <= 2) {
sel = (char *)"";
- len = (int)strlen(sel);
+ len = strlen(sel);
}
else {
char *newp;
- size_t j, i;
/* Otherwise, drop / and the first character (i.e., item type) ... */
newp = path;
newp += 2;
- /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
- j = strlen(newp);
- for(i = 0; i<j; i++)
- if(newp[i] == '?')
- newp[i] = '\x09';
-
/* ... and finally unescape */
result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
if(result)
comp_function comparator,
curl_hash_dtor dtor)
{
- int i;
-
if(!slots || !hfunc || !comparator ||!dtor) {
return 1; /* failure */
}
h->table = malloc(slots * sizeof(struct curl_llist));
if(h->table) {
+ int i;
for(i = 0; i < slots; ++i)
Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor);
return 0; /* fine */
int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
{
struct curl_llist_element *le;
- struct curl_hash_element *he;
struct curl_llist *l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- he = le->ptr;
+ struct curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
--h->size;
Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
{
struct curl_llist_element *le;
- struct curl_hash_element *he;
struct curl_llist *l;
if(h) {
l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- he = le->ptr;
+ struct curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
return he->ptr;
}
struct curl_hash_element *
Curl_hash_next_element(struct curl_hash_iterator *iter)
{
- int i;
struct curl_hash *h = iter->hash;
/* Get the next element in the current list, if any */
/* If we have reached the end of the list, find the next one */
if(!iter->current_element) {
+ int i;
for(i = iter->slot_index; i < h->slots; i++) {
if(h->table[i].head) {
iter->current_element = h->table[i].head;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
unsigned char b;
/* Create HMAC context. */
- i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize +
+ i = sizeof(*ctxt) + 2 * hashparams->hmac_ctxtsize +
hashparams->hmac_resultlen;
ctxt = malloc(i);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
return result;
}
-/* Call this function after Curl_connect() has returned async=TRUE and
- then a successful name resolve has been received.
-
- Note: this function disconnects and frees the conn data in case of
- resolve failure */
-CURLcode Curl_async_resolved(struct connectdata *conn,
- bool *protocol_done)
-{
- CURLcode result;
-
- if(conn->async.dns) {
- conn->dns_entry = conn->async.dns;
- conn->async.dns = NULL;
- }
-
- result = Curl_setup_conn(conn, protocol_done);
-
- if(result)
- /* We're not allowed to return failure with memory left allocated
- in the connectdata struct, free those here */
- Curl_disconnect(conn, FALSE); /* close the connection */
-
- return result;
-}
-
/*
* Curl_getaddrinfo() is the generic low-level name resolve API within this
* source file. There are several versions of this function - for different
int Curl_cert_hostcheck(const char *match_pattern, const char *hostname);
#endif /* HEADER_CURL_HOSTCHECK_H */
-
#include "url.h"
#include "inet_ntop.h"
#include "multiif.h"
+#include "doh.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
/* shuffle addresses if requested */
if(data->set.dns_shuffle_addresses) {
CURLcode result = Curl_shuffle_addr(data, &addr);
- if(!result)
+ if(result)
return NULL;
}
return CURLRESOLV_ERROR;
}
- /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
- non-zero value indicating that we need to wait for the response to the
- resolve call */
- addr = Curl_getaddrinfo(conn,
+ if(data->set.doh) {
+ addr = Curl_doh(conn, hostname, port, &respwait);
+ }
+ else {
+ /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
+ non-zero value indicating that we need to wait for the response to the
+ resolve call */
+ addr = Curl_getaddrinfo(conn,
#ifdef DEBUGBUILD
- (data->set.str[STRING_DEVICE]
- && !strcmp(data->set.str[STRING_DEVICE],
- "LocalHost"))?"localhost":
+ (data->set.str[STRING_DEVICE]
+ && !strcmp(data->set.str[STRING_DEVICE],
+ "LocalHost"))?"localhost":
#endif
- hostname, port, &respwait);
-
+ hostname, port, &respwait);
+ }
if(!addr) {
if(respwait) {
/* the response to our resolve call will come asynchronously at
a later time, good or bad */
/* First, check that we haven't received the info by now */
- result = Curl_resolver_is_resolved(conn, &dns);
+ result = Curl_resolv_check(conn, &dns);
if(result) /* error detected */
return CURLRESOLV_ERROR;
if(dns)
char *entry_id;
size_t entry_len;
char address[64];
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char *addresses = NULL;
+#endif
char *addr_begin;
char *addr_end;
char *port_ptr;
goto err;
port = (int)tmp_port;
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
addresses = end_ptr + 1;
+#endif
while(*end_ptr) {
size_t alen;
/* See if its already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
+ if(dns) {
+ infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
+ hostname, port);
+ /* delete old entry entry, there are two reasons for this
+ 1. old entry may have different addresses.
+ 2. even if entry with correct addresses is already in the cache,
+ but if it is close to expire, then by the time next http
+ request is made, it can get expired and pruned because old
+ entry is not necessarily marked as added by CURLOPT_RESOLVE. */
+
+ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ }
/* free the allocated entry_id again */
free(entry_id);
- if(!dns) {
- /* if not in the cache already, put this host in the cache */
- dns = Curl_cache_addr(data, head, hostname, port);
- if(dns) {
- dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
- /* release the returned reference; the cache itself will keep the
- * entry alive: */
- dns->inuse--;
- }
- }
- else {
- /* this is a duplicate, free it again */
- infof(data, "RESOLVE %s:%d is already cached, %s not stored!\n",
- hostname, port, addresses);
- Curl_freeaddrinfo(head);
+ /* put this new host in the cache */
+ dns = Curl_cache_addr(data, head, hostname, port);
+ if(dns) {
+ dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
+ /* release the returned reference; the cache itself will keep the
+ * entry alive: */
+ dns->inuse--;
}
if(data->share)
return CURLE_OK;
}
+
+CURLcode Curl_resolv_check(struct connectdata *conn,
+ struct Curl_dns_entry **dns)
+{
+ if(conn->data->set.doh)
+ return Curl_doh_is_resolved(conn, dns);
+ return Curl_resolver_is_resolved(conn, dns);
+}
+
+int Curl_resolv_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks)
+{
+#ifdef CURLRES_ASYNCH
+ if(conn->data->set.doh)
+ /* nothing to wait for during DOH resolve, those handles have their own
+ sockets */
+ return GETSOCK_BLANK;
+ return Curl_resolver_getsock(conn, socks, numsocks);
+#else
+ (void)conn;
+ (void)socks;
+ (void)numsocks;
+ return GETSOCK_BLANK;
+#endif
+}
+
+/* Call this function after Curl_connect() has returned async=TRUE and
+ then a successful name resolve has been received.
+
+ Note: this function disconnects and frees the conn data in case of
+ resolve failure */
+CURLcode Curl_once_resolved(struct connectdata *conn,
+ bool *protocol_done)
+{
+ CURLcode result;
+
+ if(conn->async.dns) {
+ conn->dns_entry = conn->async.dns;
+ conn->async.dns = NULL;
+ }
+
+ result = Curl_setup_conn(conn, protocol_done);
+
+ if(result)
+ /* We're not allowed to return failure with memory left allocated
+ in the connectdata struct, free those here */
+ Curl_disconnect(conn->data, conn, TRUE); /* close the connection */
+
+ return result;
+}
/* IPv4 threadsafe resolve function used for synch and asynch builds */
Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
-CURLcode Curl_async_resolved(struct connectdata *conn,
- bool *protocol_connect);
-
-#ifndef CURLRES_ASYNCH
-#define Curl_async_resolved(x,y) CURLE_OK
-#endif
+CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
/*
* Curl_addrinfo_callback() is used when we build with any asynch specialty.
*/
CURLcode Curl_loadhostpairs(struct Curl_easy *data);
+CURLcode Curl_resolv_check(struct connectdata *conn,
+ struct Curl_dns_entry **dns);
+int Curl_resolv_getsock(struct connectdata *conn,
+ curl_socket_t *socks,
+ int numsocks);
+
#endif /* HEADER_CURL_HOSTIP_H */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
-/* These are strictly for memory tracing and are using the same style as the
- * family otherwise present in memdebug.c. I put these ones here since they
- * require a bunch of structs I didn't want to include in memdebug.c
- */
-
-/*
- * For CURLRES_ARS, this should be written using ares_gethostbyaddr()
- * (ignoring the fact c-ares doesn't return 'serv').
- */
-
-int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
- GETNAMEINFO_TYPE_ARG2 salen,
- char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
- char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
- GETNAMEINFO_TYPE_ARG7 flags,
- int line, const char *source)
-{
- int res = (getnameinfo)(sa, salen,
- host, hostlen,
- serv, servlen,
- flags);
- if(0 == res)
- /* success */
- curl_memlog("GETNAME %s:%d getnameinfo()\n",
- source, line);
- else
- curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n",
- source, line, res);
- return res;
-}
-#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
-
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
/* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
struct HTTP *http;
- DEBUGASSERT(conn->data->req.protop == NULL);
+ struct Curl_easy *data = conn->data;
+ DEBUGASSERT(data->req.protop == NULL);
http = calloc(1, sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
Curl_mime_initpart(&http->form, conn->data);
- conn->data->req.protop = http;
-
- Curl_http2_setup_conn(conn);
- Curl_http2_setup_req(conn->data);
+ data->req.protop = http;
+ if(!CONN_INUSE(conn))
+ /* if not already multi-using, setup connection details */
+ Curl_http2_setup_conn(conn);
+ Curl_http2_setup_req(data);
return CURLE_OK;
}
return result;
}
+/*
+ * http_output_bearer() sets up an Authorization: header
+ * for HTTP Bearer authentication.
+ *
+ * Returns CURLcode.
+ */
+static CURLcode http_output_bearer(struct connectdata *conn)
+{
+ char **userp;
+ CURLcode result = CURLE_OK;
+
+ userp = &conn->allocptr.userpwd;
+ free(*userp);
+ *userp = aprintf("Authorization: Bearer %s\r\n",
+ conn->oauth_bearer);
+
+ if(!*userp) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+
+ fail:
+ return result;
+}
+
/* pickoneauth() selects the most favourable authentication method from the
* ones available and the ones we want.
*
* return TRUE if one was picked
*/
-static bool pickoneauth(struct auth *pick)
+static bool pickoneauth(struct auth *pick, unsigned long mask)
{
bool picked;
/* only deal with authentication we want */
- unsigned long avail = pick->avail & pick->want;
+ unsigned long avail = pick->avail & pick->want & mask;
picked = TRUE;
/* The order of these checks is highly relevant, as this will be the order
of preference in case of the existence of multiple accepted types. */
if(avail & CURLAUTH_NEGOTIATE)
pick->picked = CURLAUTH_NEGOTIATE;
+ else if(avail & CURLAUTH_BEARER)
+ pick->picked = CURLAUTH_BEARER;
else if(avail & CURLAUTH_DIGEST)
pick->picked = CURLAUTH_DIGEST;
else if(avail & CURLAUTH_NTLM)
bool pickhost = FALSE;
bool pickproxy = FALSE;
CURLcode result = CURLE_OK;
+ unsigned long authmask = ~0ul;
+
+ if(!conn->oauth_bearer)
+ authmask &= (unsigned long)~CURLAUTH_BEARER;
if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
/* this is a transient response code, ignore */
if(data->state.authproblem)
return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
- if(conn->bits.user_passwd &&
+ if((conn->bits.user_passwd || conn->oauth_bearer) &&
((data->req.httpcode == 401) ||
(conn->bits.authneg && data->req.httpcode < 300))) {
- pickhost = pickoneauth(&data->state.authhost);
+ pickhost = pickoneauth(&data->state.authhost, authmask);
if(!pickhost)
data->state.authproblem = TRUE;
}
if(conn->bits.proxy_user_passwd &&
((data->req.httpcode == 407) ||
(conn->bits.authneg && data->req.httpcode < 300))) {
- pickproxy = pickoneauth(&data->state.authproxy);
+ pickproxy = pickoneauth(&data->state.authproxy,
+ authmask & ~CURLAUTH_BEARER);
if(!pickproxy)
data->state.authproblem = TRUE;
}
if(pickhost || pickproxy) {
- /* In case this is GSS auth, the newurl field is already allocated so
- we must make sure to free it before allocating a new one. As figured
- out in bug #2284386 */
- Curl_safefree(data->req.newurl);
- data->req.newurl = strdup(data->change.url); /* clone URL */
- if(!data->req.newurl)
- return CURLE_OUT_OF_MEMORY;
-
if((data->set.httpreq != HTTPREQ_GET) &&
(data->set.httpreq != HTTPREQ_HEAD) &&
!conn->bits.rewindaftersend) {
if(result)
return result;
}
+ /* In case this is GSS auth, the newurl field is already allocated so
+ we must make sure to free it before allocating a new one. As figured
+ out in bug #2284386 */
+ Curl_safefree(data->req.newurl);
+ data->req.newurl = strdup(data->change.url); /* clone URL */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
}
else if((data->req.httpcode < 300) &&
(!data->state.authhost.done) &&
functions work that way */
authstatus->done = TRUE;
}
+ if(authstatus->picked == CURLAUTH_BEARER) {
+ /* Bearer */
+ if((!proxy && conn->oauth_bearer &&
+ !Curl_checkheaders(conn, "Authorization:"))) {
+ auth = "Bearer";
+ result = http_output_bearer(conn);
+ if(result)
+ return result;
+ }
+
+ /* NOTE: this function should set 'done' TRUE, as the other auth
+ functions work that way */
+ authstatus->done = TRUE;
+ }
if(auth) {
infof(data, "%s auth using %s with user '%s'\n",
authproxy = &data->state.authproxy;
if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
- conn->bits.user_passwd)
+ conn->bits.user_passwd || conn->oauth_bearer)
/* continue please */;
else {
authhost->done = TRUE;
data->state.authproblem = TRUE;
}
}
+ else
+ if(checkprefix("Bearer", auth)) {
+ *availp |= CURLAUTH_BEARER;
+ authp->avail |= CURLAUTH_BEARER;
+ if(authp->picked == CURLAUTH_BEARER) {
+ /* We asked for Bearer authentication but got a 40X back
+ anyway, which basically means our token isn't valid. */
+ authp->avail = CURLAUTH_NONE;
+ infof(data, "Authentication problem. Ignoring this.\n");
+ data->state.authproblem = TRUE;
+ }
+ }
/* there may be multiple methods on one line, so keep reading */
while(*auth && *auth != ',') /* read up to the next comma */
/*
* Curl_add_buffer_free() frees all associated resources.
*/
-void Curl_add_buffer_free(Curl_send_buffer *buff)
+void Curl_add_buffer_free(Curl_send_buffer **inp)
{
- if(buff) /* deal with NULL input */
- free(buff->buffer);
- free(buff);
+ Curl_send_buffer *in = *inp;
+ if(in) /* deal with NULL input */
+ free(in->buffer);
+ free(in);
+ *inp = NULL;
}
/*
*
* Returns CURLcode
*/
-CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
struct connectdata *conn,
/* add the number of sent bytes to this
CURLcode result;
char *ptr;
size_t size;
- struct HTTP *http = conn->data->req.protop;
+ struct Curl_easy *data = conn->data;
+ struct HTTP *http = data->req.protop;
size_t sendsize;
curl_socket_t sockfd;
size_t headersize;
+ Curl_send_buffer *in = *inp;
DEBUGASSERT(socketindex <= SECONDARYSOCKET);
DEBUGASSERT(size > included_body_bytes);
- result = Curl_convert_to_network(conn->data, ptr, headersize);
+ result = Curl_convert_to_network(data, ptr, headersize);
/* Curl_convert_to_network calls failf if unsuccessful */
if(result) {
/* conversion failed, free memory and return to the caller */
- Curl_add_buffer_free(in);
+ Curl_add_buffer_free(inp);
return result;
}
must copy the data to the uploadbuffer first, since that is the buffer
we will be using if this send is retried later.
*/
- memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
- ptr = conn->data->state.uploadbuffer;
+ result = Curl_get_upload_buffer(data);
+ if(result) {
+ /* malloc failed, free memory and return to the caller */
+ Curl_add_buffer_free(&in);
+ return result;
+ }
+ memcpy(data->state.ulbuf, ptr, sendsize);
+ ptr = data->state.ulbuf;
}
else
sendsize = size;
size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
size_t bodylen = amount - headlen;
- if(conn->data->set.verbose) {
+ if(data->set.verbose) {
/* this data _may_ contain binary stuff */
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
+ Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
if(bodylen) {
/* there was body data sent beyond the initial header part, pass that
on to the debug callback too */
- Curl_debug(conn->data, CURLINFO_DATA_OUT,
- ptr + headlen, bodylen, conn);
+ Curl_debug(data, CURLINFO_DATA_OUT,
+ ptr + headlen, bodylen);
}
}
ptr = in->buffer + amount;
/* backup the currently set pointers */
- http->backup.fread_func = conn->data->state.fread_func;
- http->backup.fread_in = conn->data->state.in;
+ http->backup.fread_func = data->state.fread_func;
+ http->backup.fread_in = data->state.in;
http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize;
/* set the new pointers for the request-sending */
- conn->data->state.fread_func = (curl_read_callback)readmoredata;
- conn->data->state.in = (void *)conn;
+ data->state.fread_func = (curl_read_callback)readmoredata;
+ data->state.in = (void *)conn;
http->postdata = ptr;
http->postsize = (curl_off_t)size;
Curl_pipeline_leave_write(conn);
}
}
- Curl_add_buffer_free(in);
+ Curl_add_buffer_free(&in);
return result;
}
/*
* add_bufferf() add the formatted input to the buffer.
*/
-CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
+CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
{
char *s;
va_list ap;
+ Curl_send_buffer *in = *inp;
va_start(ap, fmt);
s = vaprintf(fmt, ap); /* this allocs a new string to append */
va_end(ap);
if(s) {
- CURLcode result = Curl_add_buffer(in, s, strlen(s));
+ CURLcode result = Curl_add_buffer(inp, s, strlen(s));
free(s);
return result;
}
/* If we failed, we cleanup the whole buffer and return error */
free(in->buffer);
free(in);
+ *inp = NULL;
return CURLE_OUT_OF_MEMORY;
}
/*
- * add_buffer() appends a memory chunk to the existing buffer
+ * Curl_add_buffer() appends a memory chunk to the existing buffer
*/
-CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
+CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
+ size_t size)
{
char *new_rb;
- size_t new_size;
+ Curl_send_buffer *in = *inp;
if(~size < in->size_used) {
/* If resulting used size of send buffer would wrap size_t, cleanup
size will fit into a single allocatable memory chunk */
Curl_safefree(in->buffer);
free(in);
+ *inp = NULL;
return CURLE_OUT_OF_MEMORY;
}
if(!in->buffer ||
((in->size_used + size) > (in->size_max - 1))) {
-
/* If current buffer size isn't enough to hold the result, use a
buffer size that doubles the required size. If this new size
would wrap size_t, then just use the largest possible one */
+ size_t new_size;
if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) ||
(~(size * 2) < (in->size_used * 2)))
if(!new_rb) {
/* If we failed, we cleanup the whole buffer and return error */
free(in);
+ *inp = NULL;
return CURLE_OUT_OF_MEMORY;
}
}
snprintf(proxy_header,
- sizeof proxy_header,
+ sizeof(proxy_header),
"PROXY %s %s %s %li %li\r\n",
tcp_version,
conn->data->info.conn_local_ip,
if(!req_buffer)
return CURLE_OUT_OF_MEMORY;
- result = Curl_add_bufferf(req_buffer, proxy_header);
+ result = Curl_add_bufferf(&req_buffer, proxy_header);
if(result)
return result;
- result = Curl_add_buffer_send(req_buffer,
+ result = Curl_add_buffer_send(&req_buffer,
conn,
&conn->data->info.request_size,
0,
return CURLE_OK;
if(http->send_buffer) {
- Curl_add_buffer_free(http->send_buffer);
- http->send_buffer = NULL; /* clear the pointer */
+ Curl_add_buffer_free(&http->send_buffer);
}
Curl_http2_done(conn, premature);
Curl_send_buffer *req_buffer)
{
CURLcode result = CURLE_OK;
- const char *ptr;
data->state.expect100header = FALSE; /* default to false unless it is set
to TRUE below */
if(use_http_1_1plus(data, conn) &&
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
- ptr = Curl_checkheaders(conn, "Expect");
+ const char *ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
}
else {
- result = Curl_add_bufferf(req_buffer,
- "Expect: 100-continue\r\n");
+ result = Curl_add_bufferf(&req_buffer,
+ "Expect: 100-continue\r\n");
if(!result)
data->state.expect100header = TRUE;
}
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
- result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
+ result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data);
}
if(semicolonp)
*semicolonp = ';'; /* put back the semicolon */
tm->tm_min,
tm->tm_sec);
- result = Curl_add_buffer(req_buffer, datestr, strlen(datestr));
+ result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
return result;
}
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct HTTP *http;
- const char *ppath = data->state.path;
+ const char *path = data->state.up.path;
+ const char *query = data->state.up.query;
bool paste_ftp_userpwd = FALSE;
char ftp_typecode[sizeof("/;type=?")] = "";
const char *host = conn->host.name;
const char *httpstring;
Curl_send_buffer *req_buffer;
curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
- int seekerr = CURL_SEEKFUNC_CANTSEEK;
/* Always consider the DO phase done after this function call, even if there
may be parts of the request that is not yet sent, since we can deal with
}
http = data->req.protop;
+ DEBUGASSERT(http);
if(!data->state.this_is_a_follow) {
/* Free to avoid leaking memory on multiple requests*/
}
/* setup the authentication headers */
- result = Curl_http_output_auth(conn, request, ppath, FALSE);
+ result = Curl_http_output_auth(conn, request, path, FALSE);
if(result)
return result;
else {
/* If the host begins with '[', we start searching for the port after
the bracket has been closed */
- int startsearch = 0;
if(*cookiehost == '[') {
char *closingbracket;
/* since the 'cookiehost' is an allocated memory area that will be
*closingbracket = 0;
}
else {
+ int startsearch = 0;
char *colon = strchr(cookiehost + startsearch, ':');
if(colon)
*colon = 0; /* The host must not include an embedded port number */
/* The path sent to the proxy is in fact the entire URL. But if the remote
host is a IDN-name, we must make sure that the request we produce only
uses the encoded host name! */
+
+ /* and no fragment part */
+ CURLUcode uc;
+ char *url;
+ CURLU *h = curl_url_dup(data->state.uh);
+ if(!h)
+ return CURLE_OUT_OF_MEMORY;
+
if(conn->host.dispname != conn->host.name) {
- char *url = data->change.url;
- ptr = strstr(url, conn->host.dispname);
- if(ptr) {
- /* This is where the display name starts in the URL, now replace this
- part with the encoded name. TODO: This method of replacing the host
- name is rather crude as I believe there's a slight risk that the
- user has entered a user name or password that contain the host name
- string. */
- size_t currlen = strlen(conn->host.dispname);
- size_t newlen = strlen(conn->host.name);
- size_t urllen = strlen(url);
-
- char *newurl;
-
- newurl = malloc(urllen + newlen - currlen + 1);
- if(newurl) {
- /* copy the part before the host name */
- memcpy(newurl, url, ptr - url);
- /* append the new host name instead of the old */
- memcpy(newurl + (ptr - url), conn->host.name, newlen);
- /* append the piece after the host name */
- memcpy(newurl + newlen + (ptr - url),
- ptr + currlen, /* copy the trailing zero byte too */
- urllen - (ptr-url) - currlen + 1);
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
- data->change.url = newurl;
- data->change.url_alloc = TRUE;
- }
- else
- return CURLE_OUT_OF_MEMORY;
+ uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(strcasecompare("http", data->state.up.scheme)) {
+ /* when getting HTTP, we don't want the userinfo the URL */
+ uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
}
+ uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ /* now extract the new version of the URL */
+ uc = curl_url_get(h, CURLUPART_URL, &url, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
}
- ppath = data->change.url;
- if(checkprefix("ftp://", ppath)) {
+
+ if(data->change.url_alloc)
+ free(data->change.url);
+
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
+
+ curl_url_cleanup(h);
+
+ if(strcasecompare("ftp", data->state.up.scheme)) {
if(data->set.proxy_transfer_mode) {
/* when doing ftp, append ;type=<a|i> if not present */
- char *type = strstr(ppath, ";type=");
+ char *type = strstr(path, ";type=");
if(type && type[6] && type[7] == 0) {
switch(Curl_raw_toupper(type[6])) {
case 'A':
char *p = ftp_typecode;
/* avoid sending invalid URLs like ftp://example.com;type=i if the
* user specified ftp://example.com without the slash */
- if(!*data->state.path && ppath[strlen(ppath) - 1] != '/') {
+ if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
*p++ = '/';
}
snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
/* Now, let's read off the proper amount of bytes from the
input. */
+ int seekerr = CURL_SEEKFUNC_CANTSEEK;
if(conn->seek_func) {
Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
/* add the main request stuff */
/* GET/HEAD/POST/PUT */
- result = Curl_add_bufferf(req_buffer, "%s ", request);
+ result = Curl_add_bufferf(&req_buffer, "%s ", request);
if(result)
return result;
- if(data->set.str[STRING_TARGET])
- ppath = data->set.str[STRING_TARGET];
+ if(data->set.str[STRING_TARGET]) {
+ path = data->set.str[STRING_TARGET];
+ query = NULL;
+ }
/* url */
- if(paste_ftp_userpwd)
- result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s",
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ char *url = data->change.url;
+ result = Curl_add_buffer(&req_buffer, url, strlen(url));
+ }
+ else if(paste_ftp_userpwd)
+ result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s",
conn->user, conn->passwd,
- ppath + sizeof("ftp://") - 1);
- else
- result = Curl_add_buffer(req_buffer, ppath, strlen(ppath));
+ path + sizeof("ftp://") - 1);
+ else {
+ result = Curl_add_buffer(&req_buffer, path, strlen(path));
+ if(result)
+ return result;
+ if(query)
+ result = Curl_add_bufferf(&req_buffer, "?%s", query);
+ }
if(result)
return result;
result =
- Curl_add_bufferf(req_buffer,
+ Curl_add_bufferf(&req_buffer,
"%s" /* ftp typecode (;type=x) */
" HTTP/%s\r\n" /* HTTP version */
"%s" /* host */
co = Curl_cookie_getlist(data->cookies,
conn->allocptr.cookiehost?
conn->allocptr.cookiehost:host,
- data->state.path,
+ data->state.up.path,
(conn->handler->protocol&CURLPROTO_HTTPS)?
TRUE:FALSE);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
while(co) {
if(co->value) {
if(0 == count) {
- result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ result = Curl_add_bufferf(&req_buffer, "Cookie: ");
if(result)
break;
}
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"%s%s=%s", count?"; ":"",
co->name, co->value);
if(result)
}
if(addcookies && !result) {
if(!count)
- result = Curl_add_bufferf(req_buffer, "Cookie: ");
+ result = Curl_add_bufferf(&req_buffer, "Cookie: ");
if(!result) {
- result = Curl_add_bufferf(req_buffer, "%s%s", count?"; ":"",
+ result = Curl_add_bufferf(&req_buffer, "%s%s", count?"; ":"",
addcookies);
count++;
}
}
if(count && !result)
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
if((postsize != -1) && !data->req.upload_chunky &&
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize);
if(result)
return result;
}
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers */
if(result)
return result;
Curl_pgrsSetUploadSize(data, postsize);
/* this sends the buffer and frees all the buffer resources */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
failf(data, "Failed sending PUT request");
/* This is form posting using mime data. */
if(conn->bits.authneg) {
/* nothing to post! */
- result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
+ result = Curl_add_bufferf(&req_buffer, "Content-Length: 0\r\n\r\n");
if(result)
return result;
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
(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,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize);
if(result)
struct curl_slist *hdr;
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
- result = Curl_add_bufferf(req_buffer, "%s\r\n", hdr->data);
+ result = Curl_add_bufferf(&req_buffer, "%s\r\n", hdr->data);
if(result)
return result;
}
data->state.expect100header = FALSE;
/* make the request end in a true CRLF */
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
(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,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
"\r\n", postsize);
if(result)
}
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"Content-Type: application/"
"x-www-form-urlencoded\r\n");
if(result)
is no magic limit but only set to prevent really huge POSTs to
get the data duplicated with malloc() and family. */
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result)
return result;
if(!data->req.upload_chunky) {
/* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */
- result = Curl_add_buffer(req_buffer, data->set.postfields,
+ result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize);
included_body = postsize;
}
else {
if(postsize) {
/* Append the POST data chunky-style */
- result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize);
+ result = Curl_add_bufferf(&req_buffer, "%x\r\n", (int)postsize);
if(!result) {
- result = Curl_add_buffer(req_buffer, data->set.postfields,
+ result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize);
if(!result)
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
included_body = postsize + 2;
}
}
if(!result)
- result = Curl_add_buffer(req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
+ result = Curl_add_buffer(&req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
/* 0 CR LF CR LF */
included_body += 5;
}
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result)
return result;
}
}
else {
- result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
if(result)
return result;
if(data->req.upload_chunky && conn->bits.authneg) {
/* Chunky upload is selected and we're negotiating auth still, send
end-of-data only */
- result = Curl_add_buffer(req_buffer,
+ result = Curl_add_buffer(&req_buffer,
"\x30\x0d\x0a\x0d\x0a", 5);
/* 0 CR LF CR LF */
if(result)
}
}
/* issue the request */
- result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size,
+ result = Curl_add_buffer_send(&req_buffer, conn, &data->info.request_size,
(size_t)included_body, FIRSTSOCKET);
if(result)
break;
default:
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
/* issue the request */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
data->req.exp100 = EXP100_SEND_DATA; /* already sent */
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
}
+ else
+ data->req.writebytecount = http->writebytecount;
}
if((conn->httpversion == 20) && data->req.upload_chunky)
return result;
}
+typedef enum {
+ STATUS_UNKNOWN, /* not enough data to tell yet */
+ STATUS_DONE, /* a status line was read */
+ STATUS_BAD /* not a status line */
+} statusline;
+
+
+/* Check a string for a prefix. Check no more than 'len' bytes */
+static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
+{
+ size_t ch = CURLMIN(strlen(prefix), len);
+ return curl_strnequal(prefix, buffer, ch);
+}
+
/*
* checkhttpprefix()
*
* Returns TRUE if member of the list matches prefix of string
*/
-static bool
+static statusline
checkhttpprefix(struct Curl_easy *data,
- const char *s)
+ const char *s, size_t len)
{
struct curl_slist *head = data->set.http200aliases;
- bool rc = FALSE;
+ statusline rc = STATUS_BAD;
+ statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding using a scratch area */
char *scratch = strdup(s);
#endif /* CURL_DOES_CONVERSIONS */
while(head) {
- if(checkprefix(head->data, s)) {
- rc = TRUE;
+ if(checkprefixmax(head->data, s, len)) {
+ rc = onmatch;
break;
}
head = head->next;
}
- if(!rc && (checkprefix("HTTP/", s)))
- rc = TRUE;
+ if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
+ rc = onmatch;
#ifdef CURL_DOES_CONVERSIONS
free(scratch);
}
#ifndef CURL_DISABLE_RTSP
-static bool
+static statusline
checkrtspprefix(struct Curl_easy *data,
- const char *s)
+ const char *s, size_t len)
{
- bool result = FALSE;
+ statusline result = STATUS_BAD;
+ statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding using a scratch area */
/* Curl_convert_from_network calls failf if unsuccessful */
result = FALSE; /* can't return CURLE_foobar so return FALSE */
}
- else
- result = checkprefix("RTSP/", scratch)? TRUE: FALSE;
+ else if(checkprefixmax("RTSP/", scratch, len))
+ result = onmatch;
free(scratch);
#else
(void)data; /* unused */
- result = checkprefix("RTSP/", s)? TRUE: FALSE;
+ if(checkprefixmax("RTSP/", s, len))
+ result = onmatch;
#endif /* CURL_DOES_CONVERSIONS */
return result;
}
#endif /* CURL_DISABLE_RTSP */
-static bool
+static statusline
checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
- const char *s)
+ const char *s, size_t len)
{
#ifndef CURL_DISABLE_RTSP
if(conn->handler->protocol & CURLPROTO_RTSP)
- return checkrtspprefix(data, s);
+ return checkrtspprefix(data, s, len);
#else
(void)conn;
#endif /* CURL_DISABLE_RTSP */
- return checkhttpprefix(data, s);
+ return checkhttpprefix(data, s, len);
}
/*
/* 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, "Rejected %zd bytes header (max is %d)!", newsize,
+ failf(data, "Rejected %zu bytes header (max is %d)!", newsize,
CURL_MAX_HTTP_HEADER);
return CURLE_OUT_OF_MEMORY;
}
if(result)
return result;
- if(!k->headerline && (k->hbuflen>5)) {
- /* make a first check that this looks like a protocol header */
- if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
+ if(!k->headerline) {
+ /* check if this looks like a protocol header */
+ statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
+ k->hbuflen);
+ if(st == STATUS_BAD) {
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
k->badheader = HEADER_ALLBAD;
+ streamclose(conn, "bad HTTP: No end-of-message indicator");
break;
}
}
if(!k->headerline) {
/* the first read header */
- if((k->hbuflen>5) &&
- !checkprotoprefix(data, conn, data->state.headerbuff)) {
+ statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
+ k->hbuflen);
+ if(st == STATUS_BAD) {
+ streamclose(conn, "bad HTTP: No end-of-message indicator");
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
if(*nread)
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- k->str_start, headerlen, conn);
+ k->str_start, headerlen);
break; /* exit header line loop */
}
compare header line against list of aliases
*/
if(!nc) {
- if(checkhttpprefix(data, k->p)) {
+ if(checkhttpprefix(data, k->p, k->hbuflen) == STATUS_DONE) {
nc = 1;
k->httpcode = 200;
conn->httpversion = 10;
* depending on how authentication is working. Other codes
* are definitely errors, so give up here.
*/
- if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
+ if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET &&
+ k->httpcode == 416) {
+ /* "Requested Range Not Satisfiable", just proceed and
+ pretend this is no error */
+ k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
+ }
+ else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
((k->httpcode != 401) || !conn->bits.user_passwd) &&
((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
-
- if(data->state.resume_from &&
- (data->set.httpreq == HTTPREQ_GET) &&
- (k->httpcode == 416)) {
- /* "Requested Range Not Satisfiable", just proceed and
- pretend this is no error */
- }
- else {
- /* serious error, go home! */
- print_http_error(data);
- return CURLE_HTTP_RETURNED_ERROR;
- }
+ /* serious error, go home! */
+ print_http_error(data);
+ return CURLE_HTTP_RETURNED_ERROR;
}
if(conn->httpversion == 10) {
here, or else use real peer host name. */
conn->allocptr.cookiehost?
conn->allocptr.cookiehost:conn->host.name,
- data->state.path);
+ data->state.up.path);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
#endif
writetype |= CLIENTWRITE_BODY;
if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- k->p, (size_t)k->hbuflen, conn);
+ Curl_debug(data, CURLINFO_HEADER_IN, k->p, (size_t)k->hbuflen);
result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
if(result)
typedef struct Curl_send_buffer Curl_send_buffer;
Curl_send_buffer *Curl_add_buffer_init(void);
-void Curl_add_buffer_free(Curl_send_buffer *buff);
-CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...);
-CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size);
-CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
+void Curl_add_buffer_free(Curl_send_buffer **inp);
+CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
+ WARN_UNUSED_RESULT;
+CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
+ size_t size) WARN_UNUSED_RESULT;
+CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
struct connectdata *conn,
long *bytes_written,
size_t included_body_bytes,
HTTPSEND_LAST /* never use this */
} sending;
- void *send_buffer; /* used if the request couldn't be sent in one chunk,
- points to an allocated send_buffer struct */
-
+#ifndef CURL_DISABLE_HTTP
+ Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in
+ one chunk, points to an allocated
+ send_buffer struct */
+#endif
#ifdef USE_NGHTTP2
/*********** for HTTP/2 we store stream-local data here *************/
int32_t stream_id; /* stream we are interested in */
up the proxy tunnel */
#endif /* HEADER_CURL_HTTP_H */
-
#include "memdebug.h"
#define H2_BUFSIZE 32768
-#define MIN(x,y) ((x)<(y)?(x):(y))
#if (NGHTTP2_VERSION_NUM < 0x010000)
#error too old nghttp2 version, upgrade!
static void http2_stream_free(struct HTTP *http)
{
if(http) {
- Curl_add_buffer_free(http->header_recvbuf);
- http->header_recvbuf = NULL; /* clear the pointer */
- Curl_add_buffer_free(http->trailer_recvbuf);
- http->trailer_recvbuf = NULL; /* clear the pointer */
+ Curl_add_buffer_free(&http->header_recvbuf);
+ Curl_add_buffer_free(&http->trailer_recvbuf);
for(; http->push_headers_used > 0; --http->push_headers_used) {
free(http->push_headers[http->push_headers_used - 1]);
}
}
}
+/*
+ * Disconnects *a* connection used for HTTP/2. It might be an old one from the
+ * connection cache and not the "main" one. Don't touch the easy handle!
+ */
+
static CURLcode http2_disconnect(struct connectdata *conn,
bool dead_connection)
{
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
- http2_stream_free(conn->data->req.protop);
- conn->data->state.drain = 0;
H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
dead = !Curl_connalive(conn);
if(!dead) {
/* This happens before we've sent off a request and the connection is
- not in use by any other thransfer, there shouldn't be any data here,
+ not in use by any other transfer, there shouldn't be any data here,
only "protocol frames" */
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
+ struct http_conn *c = &check->proto.httpc;
+ int rc;
+ bool send_frames = false;
if(checks_to_perform & CONNCHECK_ISDEAD) {
if(http2_connisdead(check))
ret_val |= CONNRESULT_DEAD;
}
+ if(checks_to_perform & CONNCHECK_KEEPALIVE) {
+ struct curltime now = Curl_now();
+ time_t elapsed = Curl_timediff(now, check->keepalive);
+
+ if(elapsed > check->upkeep_interval_ms) {
+ /* Perform an HTTP/2 PING */
+ rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
+ if(!rc) {
+ /* Successfully added a PING frame to the session. Need to flag this
+ so the frame is sent. */
+ send_frames = true;
+ }
+ else {
+ failf(check->data, "nghttp2_submit_ping() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ }
+
+ check->keepalive = now;
+ }
+ }
+
+ if(send_frames) {
+ rc = nghttp2_session_send(c->h2);
+ if(rc)
+ failf(check->data, "nghttp2_session_send() failed: %s(%d)",
+ nghttp2_strerror(rc), rc);
+ }
+
return ret_val;
}
"INADEQUATE_SECURITY", /* 0xC */
"HTTP_1_1_REQUIRED" /* 0xD */
};
- return (err < sizeof str / sizeof str[0]) ? str[err] : "unknown";
+ return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown";
#else
return nghttp2_http2_strerror(err);
#endif
(void)h2;
(void)flags;
+ if(!c->send_underlying)
+ /* called before setup properly! */
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+
written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET,
data, length, &result);
return NULL;
}
+/*
+ * This specific transfer on this connection has been "drained".
+ */
+static void drained_transfer(struct Curl_easy *data,
+ struct http_conn *httpc)
+{
+ DEBUGASSERT(httpc->drain_total >= data->state.drain);
+ httpc->drain_total -= data->state.drain;
+ data->state.drain = 0;
+}
+
+/*
+ * Mark this transfer to get "drained".
+ */
+static void drain_this(struct Curl_easy *data,
+ struct http_conn *httpc)
+{
+ data->state.drain++;
+ httpc->drain_total++;
+ DEBUGASSERT(httpc->drain_total >= data->state.drain);
+}
+
static struct Curl_easy *duphandle(struct Curl_easy *data)
{
struct Curl_easy *second = curl_easy_duphandle(data);
if(rv) {
/* denied, kill off the new handle again */
http2_stream_free(newhandle->req.protop);
+ newhandle->req.protop = NULL;
(void)Curl_close(newhandle);
goto fail;
}
if(rc) {
infof(data, "failed to add handle to multi\n");
http2_stream_free(newhandle->req.protop);
+ newhandle->req.protop = NULL;
Curl_close(newhandle);
rv = 1;
goto fail;
}
httpc = &conn->proto.httpc;
- nghttp2_session_set_stream_user_data(httpc->h2,
- frame->promised_stream_id, newhandle);
+ rv = nghttp2_session_set_stream_user_data(httpc->h2,
+ frame->promised_stream_id,
+ newhandle);
+ if(rv) {
+ infof(data, "failed to set user_data for stream %d\n",
+ frame->promised_stream_id);
+ DEBUGASSERT(0);
+ goto fail;
+ }
}
else {
H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
int rv;
size_t left, ncopy;
int32_t stream_id = frame->hd.stream_id;
+ CURLcode result;
if(!stream_id) {
/* stream ID zero is for connection-oriented stuff */
if(max_conn != httpc->settings.max_concurrent_streams) {
/* only signal change if the value actually changed */
infof(conn->data,
- "Connection state changed (MAX_CONCURRENT_STREAMS == %d)!\n",
+ "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
httpc->settings.max_concurrent_streams);
Curl_multi_connchanged(conn->data->multi);
}
stream->status_code = -1;
}
- Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
+ result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
- ncopy = MIN(stream->len, left);
+ ncopy = CURLMIN(stream->len, left);
memcpy(&stream->mem[stream->memlen],
stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
stream->len -= ncopy;
stream->memlen += ncopy;
- data_s->state.drain++;
- httpc->drain_total++;
+ drain_this(data_s, httpc);
{
/* get the pointer from userp again since it was re-assigned above */
struct connectdata *conn_s = (struct connectdata *)userp;
return 0;
}
-static int on_invalid_frame_recv(nghttp2_session *session,
- const nghttp2_frame *frame,
- int lib_error_code, void *userp)
-{
- struct Curl_easy *data_s = NULL;
- (void)userp;
-#if !defined(DEBUG_HTTP2) || 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) {
- H2BUGF(infof(data_s,
- "on_invalid_frame_recv() was called, error=%d:%s\n",
- lib_error_code, nghttp2_strerror(lib_error_code)));
- }
- return 0;
-}
-
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const uint8_t *data, size_t len, void *userp)
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- nread = MIN(stream->len, len);
+ nread = CURLMIN(stream->len, len);
memcpy(&stream->mem[stream->memlen], data, nread);
stream->len -= nread;
stream->memlen += nread;
- data_s->state.drain++;
- conn->proto.httpc.drain_total++;
+ drain_this(data_s, &conn->proto.httpc);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
return 0;
}
-static int before_frame_send(nghttp2_session *session,
- const nghttp2_frame *frame,
- void *userp)
-{
- struct Curl_easy *data_s;
- (void)userp;
-
- data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
- if(data_s) {
- H2BUGF(infof(data_s, "before_frame_send() was called\n"));
- }
-
- return 0;
-}
-static int on_frame_send(nghttp2_session *session,
- const nghttp2_frame *frame,
- void *userp)
-{
- struct Curl_easy *data_s;
- (void)userp;
-
- data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
- if(data_s) {
- H2BUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
- frame->hd.length));
- }
- return 0;
-}
-static int on_frame_not_send(nghttp2_session *session,
- const nghttp2_frame *frame,
- int lib_error_code, void *userp)
-{
- struct Curl_easy *data_s;
- (void)userp;
-#if !defined(DEBUG_HTTP2) || 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) {
- H2BUGF(infof(data_s,
- "on_frame_not_send() was called, lib_error_code = %d\n",
- lib_error_code));
- }
- return 0;
-}
static int on_stream_close(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *userp)
{
struct Curl_easy *data_s;
struct HTTP *stream;
struct connectdata *conn = (struct connectdata *)userp;
+ int rv;
(void)session;
(void)stream_id;
return NGHTTP2_ERR_CALLBACK_FAILURE;
stream->closed = TRUE;
- data_s->state.drain++;
httpc = &conn->proto.httpc;
- httpc->drain_total++;
+ drain_this(data_s, httpc);
httpc->error_code = error_code;
/* remove the entry from the hash as the stream is now gone */
- nghttp2_session_set_stream_user_data(session, stream_id, 0);
+ rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
+ if(rv) {
+ infof(data_s, "http/2: failed to clear user_data for stream %d!\n",
+ stream_id);
+ DEBUGASSERT(0);
+ }
H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
+ stream->stream_id = 0; /* cleared */
}
return 0;
}
struct Curl_easy *data_s;
int32_t stream_id = frame->hd.stream_id;
struct connectdata *conn = (struct connectdata *)userp;
+ CURLcode result;
(void)flags;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
stream->push_headers_alloc = 10;
stream->push_headers = malloc(stream->push_headers_alloc *
sizeof(char *));
+ if(!stream->push_headers)
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
stream->push_headers_used = 0;
}
else if(stream->push_headers_used ==
H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value));
- Curl_add_buffer(stream->trailer_recvbuf, &n, sizeof(n));
- Curl_add_buffer(stream->trailer_recvbuf, name, namelen);
- Curl_add_buffer(stream->trailer_recvbuf, ": ", 2);
- Curl_add_buffer(stream->trailer_recvbuf, value, valuelen);
- Curl_add_buffer(stream->trailer_recvbuf, "\r\n\0", 3);
+ result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n));
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
return 0;
}
stream->status_code = decode_status_code(value, valuelen);
DEBUGASSERT(stream->status_code != -1);
- Curl_add_buffer(stream->header_recvbuf, "HTTP/2 ", 7);
- Curl_add_buffer(stream->header_recvbuf, value, valuelen);
+ result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* the space character after the status code is mandatory */
- Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
+ result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
/* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */
/* convert to a HTTP1-style header */
- Curl_add_buffer(stream->header_recvbuf, name, namelen);
- Curl_add_buffer(stream->header_recvbuf, ": ", 2);
- Curl_add_buffer(stream->header_recvbuf, value, valuelen);
- Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
+ result = Curl_add_buffer(&stream->header_recvbuf, name, namelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ if(result)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
else
return NGHTTP2_ERR_INVALID_ARGUMENT;
- nread = MIN(stream->upload_len, length);
+ nread = CURLMIN(stream->upload_len, length);
if(nread > 0) {
memcpy(buf, stream->upload_mem, nread);
stream->upload_mem += nread;
return nread;
}
-#ifdef NGHTTP2_HAS_ERROR_CALLBACK
+#if defined(NGHTTP2_HAS_ERROR_CALLBACK) && \
+ !defined(CURL_DISABLE_VERBOSE_STRINGS)
static int error_callback(nghttp2_session *session,
const char *msg,
size_t len,
struct HTTP *http = data->req.protop;
struct http_conn *httpc = &conn->proto.httpc;
+ /* there might be allocated resources done before this got the 'h2' pointer
+ setup */
if(http->header_recvbuf) {
- Curl_add_buffer_free(http->header_recvbuf);
- http->header_recvbuf = NULL; /* clear the pointer */
- Curl_add_buffer_free(http->trailer_recvbuf);
- http->trailer_recvbuf = NULL; /* clear the pointer */
+ Curl_add_buffer_free(&http->header_recvbuf);
+ Curl_add_buffer_free(&http->trailer_recvbuf);
if(http->push_headers) {
/* if they weren't used and then freed before */
for(; http->push_headers_used > 0; --http->push_headers_used) {
}
}
+ if(!httpc->h2) /* not HTTP/2 ? */
+ return;
+
+ if(data->state.drain)
+ drained_transfer(data, httpc);
+
if(premature) {
/* RST_STREAM */
- nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, http->stream_id,
- NGHTTP2_STREAM_CLOSED);
+ if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
+ http->stream_id, NGHTTP2_STREAM_CLOSED))
+ (void)nghttp2_session_send(httpc->h2);
+
if(http->stream_id == httpc->pause_stream_id) {
infof(data, "stopped the pause stream!\n");
httpc->pause_stream_id = 0;
}
}
- if(http->stream_id) {
- nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
+ /* -1 means unassigned and 0 means cleared */
+ if(http->stream_id > 0) {
+ int rv = nghttp2_session_set_stream_user_data(httpc->h2,
+ http->stream_id, 0);
+ if(rv) {
+ infof(data, "http/2: failed to clear user_data for stream %d!\n",
+ http->stream_id);
+ DEBUGASSERT(0);
+ }
http->stream_id = 0;
}
}
/* nghttp2_on_frame_recv_callback */
nghttp2_session_callbacks_set_on_frame_recv_callback
(callbacks, on_frame_recv);
- /* nghttp2_on_invalid_frame_recv_callback */
- nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
- (callbacks, on_invalid_frame_recv);
/* nghttp2_on_data_chunk_recv_callback */
nghttp2_session_callbacks_set_on_data_chunk_recv_callback
(callbacks, on_data_chunk_recv);
- /* nghttp2_before_frame_send_callback */
- nghttp2_session_callbacks_set_before_frame_send_callback
- (callbacks, before_frame_send);
- /* nghttp2_on_frame_send_callback */
- nghttp2_session_callbacks_set_on_frame_send_callback
- (callbacks, on_frame_send);
- /* nghttp2_on_frame_not_send_callback */
- nghttp2_session_callbacks_set_on_frame_not_send_callback
- (callbacks, on_frame_not_send);
/* nghttp2_on_stream_close_callback */
nghttp2_session_callbacks_set_on_stream_close_callback
(callbacks, on_stream_close);
/* nghttp2_on_header_callback */
nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
+#endif
/* The nghttp2 session is not yet setup, do it */
rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
httpc->local_settings_num);
if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
- Curl_add_buffer_free(req);
+ Curl_add_buffer_free(&req);
return CURLE_FAILED_INIT;
}
conn->proto.httpc.binlen = binlen;
result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
&base64, &blen);
if(result) {
- Curl_add_buffer_free(req);
+ Curl_add_buffer_free(&req);
return result;
}
- result = Curl_add_bufferf(req,
+ result = Curl_add_bufferf(&req,
"Connection: Upgrade, HTTP2-Settings\r\n"
"Upgrade: %s\r\n"
"HTTP2-Settings: %s\r\n",
if(rv < 0) {
failf(data,
"h2_process_pending_input: nghttp2_session_mem_recv() returned "
- "%d:%s\n", rv, nghttp2_strerror((int)rv));
+ "%zd:%s\n", rv, nghttp2_strerror((int)rv));
*err = CURLE_RECV_ERROR;
return -1;
}
return result;
}
-
static ssize_t http2_handle_stream_close(struct connectdata *conn,
struct Curl_easy *data,
struct HTTP *stream, CURLcode *err)
httpc->pause_stream_id = 0;
}
- DEBUGASSERT(httpc->drain_total >= data->state.drain);
- httpc->drain_total -= data->state.drain;
- data->state.drain = 0;
+ drained_transfer(data, httpc);
if(httpc->pause_stream_id == 0) {
if(h2_process_pending_input(conn, httpc, err) != 0) {
return -1;
}
else if(httpc->error_code != NGHTTP2_NO_ERROR) {
- failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
+ failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
stream->stream_id, Curl_http2_strerror(httpc->error_code),
httpc->error_code);
*err = CURLE_HTTP2_STREAM;
}
if(!stream->bodystarted) {
- failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
+ failf(data, "HTTP/2 stream %d was closed cleanly, but before getting "
" all response header fields, treated as error",
stream->stream_id);
*err = CURLE_HTTP2_STREAM;
/* If there is body data pending for this stream to return, do that */
size_t left =
stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
- size_t ncopy = MIN(len, left);
+ size_t ncopy = CURLMIN(len, left);
memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
ncopy);
stream->nread_header_recvbuf += ncopy;
}
else if(stream->pausedata) {
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
- nread = MIN(len, stream->pauselen);
+ nread = CURLMIN(len, stream->pauselen);
memcpy(mem, stream->pausedata, nread);
stream->pausedata += nread;
stream->pauselen -= nread;
- infof(data, "%zu data bytes written\n", nread);
+ infof(data, "%zd data bytes written\n", nread);
if(stream->pauselen == 0) {
H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
if(nghttp2_is_fatal((int)rv)) {
- failf(data, "nghttp2_session_mem_recv() returned %d:%s\n",
+ failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n",
rv, nghttp2_strerror((int)rv));
*err = CURLE_RECV_ERROR;
return -1;
stream->stream_id));
}
else if(!stream->closed) {
- DEBUGASSERT(httpc->drain_total >= data->state.drain);
- httpc->drain_total -= data->state.drain;
- data->state.drain = 0; /* this stream is hereby drained */
+ drained_transfer(data, httpc);
}
return retlen;
}
infof(conn->data, "Using Stream ID: %x (easy handle %p)\n",
- stream_id, conn->data);
+ stream_id, (void *)conn->data);
stream->stream_id = stream_id;
/* this does not call h2_session_send() since there can not have been any
stream->stream_id = -1;
- if(!stream->header_recvbuf)
+ if(!stream->header_recvbuf) {
stream->header_recvbuf = Curl_add_buffer_init();
+ if(!stream->header_recvbuf)
+ return CURLE_OUT_OF_MEMORY;
+ }
if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2))
conn->handler = &Curl_handler_http2;
result = Curl_http2_init(conn);
- if(result)
+ if(result) {
+ Curl_add_buffer_free(&stream->header_recvbuf);
return result;
+ }
infof(conn->data, "Using HTTP2, server supports multi-use\n");
stream->upload_left = 0;
return CURLE_HTTP2;
}
- nghttp2_session_set_stream_user_data(httpc->h2,
- stream->stream_id,
- conn->data);
+ rv = nghttp2_session_set_stream_user_data(httpc->h2,
+ stream->stream_id,
+ data);
+ if(rv) {
+ infof(data, "http/2: failed to set user_data for stream %d!\n",
+ stream->stream_id);
+ DEBUGASSERT(0);
+ }
}
else {
populate_settings(conn, httpc);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_setup_conn(x)
+#define Curl_http2_setup_conn(x) Curl_nop_stmt
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
#endif
#endif /* HEADER_CURL_HTTP2_H */
-
};
#endif /* HEADER_CURL_HTTP_CHUNKS_H */
-
/* connection is already authenticated,
* don't send a header in future requests */
ntlm->state = NTLMSTATE_LAST;
- /* fall-through */
+ /* FALLTHROUGH */
case NTLMSTATE_LAST:
Curl_safefree(*allocuserpwd);
authp->done = TRUE;
struct SingleRequest *k = &data->req;
CURLcode result;
curl_socket_t tunnelsocket = conn->sock[sockindex];
- timediff_t check;
struct http_connect_state *s = conn->connect_state;
#define SELECT_OK 0
#define SELECT_ERROR 1
-#define SELECT_TIMEOUT 2
if(Curl_connect_complete(conn))
return CURLE_OK; /* CONNECT is already completed */
conn->bits.proxy_connect_closed = FALSE;
do {
+ timediff_t check;
if(TUNNEL_INIT == s->tunnel_state) {
/* BEGIN CONNECT PHASE */
char *host_port;
Curl_send_buffer *req_buffer;
- infof(data, "Establish HTTP proxy tunnel to %s:%hu\n",
+ infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
hostname, remote_port);
/* This only happens if we've looped here due to authentication
host_port = aprintf("%s:%d", hostname, remote_port);
if(!host_port) {
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY;
}
aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port);
if(!hostheader) {
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY;
}
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
return CURLE_OUT_OF_MEMORY;
}
}
useragent = conn->allocptr.uagent;
result =
- Curl_add_bufferf(req_buffer,
+ Curl_add_bufferf(&req_buffer,
"CONNECT %s HTTP/%s\r\n"
"%s" /* Host: */
"%s" /* Proxy-Authorization */
if(!result)
/* CRLF terminate the request */
- result = Curl_add_bufferf(req_buffer, "\r\n");
+ result = Curl_add_bufferf(&req_buffer, "\r\n");
if(!result) {
/* Send the connect request to the proxy */
/* BLOCKING */
result =
- Curl_add_buffer_send(req_buffer, conn,
+ Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, sockindex);
}
req_buffer = NULL;
failf(data, "Failed sending CONNECT to proxy");
}
- Curl_add_buffer_free(req_buffer);
+ Curl_add_buffer_free(&req_buffer);
if(result)
return result;
/* output debug if that is requested */
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- s->line_start, (size_t)s->perline, conn);
+ s->line_start, (size_t)s->perline);
if(!data->set.suppress_connect_headers) {
/* send the header to the callback */
ZERO_NULL, /* connection_check */
PORT_IMAPS, /* defport */
CURLPROTO_IMAPS, /* protocol */
- PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */
+ PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
+ PROTOPT_URLOPTIONS
};
#endif
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
-
imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */
imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */
imapc->tls_supported = FALSE; /* Clear the TLS capability */
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
- char *mailbox;
if(imap->custom)
/* Send the custom request */
imap->custom_params ? imap->custom_params : "");
else {
/* Make sure the mailbox is in the correct atom format if necessary */
- mailbox = imap->mailbox ? imap_atom(imap->mailbox, true) : strdup("");
+ char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true)
+ : strdup("");
if(!mailbox)
return CURLE_OUT_OF_MEMORY;
{
CURLcode result = CURLE_OK;
struct IMAP *imap = conn->data->req.protop;
-
/* Check we have a UID */
- if(!imap->uid) {
- failf(conn->data, "Cannot FETCH without a UID.");
- return CURLE_URL_MALFORMAT;
+ if(imap->uid) {
+
+ /* Send the FETCH command */
+ if(imap->partial)
+ result = imap_sendf(conn, "UID FETCH %s BODY[%s]<%s>",
+ imap->uid,
+ imap->section ? imap->section : "",
+ imap->partial);
+ else
+ result = imap_sendf(conn, "UID FETCH %s BODY[%s]",
+ imap->uid,
+ imap->section ? imap->section : "");
+ }
+ else if(imap->mindex) {
+
+ /* Send the FETCH command */
+ if(imap->partial)
+ result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
+ imap->mindex,
+ imap->section ? imap->section : "",
+ imap->partial);
+ else
+ result = imap_sendf(conn, "FETCH %s BODY[%s]",
+ imap->mindex,
+ imap->section ? imap->section : "");
+ }
+ else {
+ failf(conn->data, "Cannot FETCH without a UID.");
+ return CURLE_URL_MALFORMAT;
}
-
- /* Send the FETCH command */
- if(imap->partial)
- result = imap_sendf(conn, "FETCH %s BODY[%s]<%s>",
- imap->uid,
- imap->section ? imap->section : "",
- imap->partial);
- else
- result = imap_sendf(conn, "FETCH %s BODY[%s]",
- imap->uid,
- imap->section ? imap->section : "");
-
if(!result)
state(conn, IMAP_FETCH);
struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
- size_t wordlen;
(void)instate; /* no use for this yet */
/* Loop through the data line */
for(;;) {
+ size_t wordlen;
while(*line &&
(*line == ' ' || *line == '\t' ||
*line == '\r' || *line == '\n')) {
struct IMAP *imap = conn->data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
- char tmp[20];
(void)instate; /* no use for this yet */
if(imapcode == '*') {
/* See if this is an UIDVALIDITY response */
+ char tmp[20];
if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
Curl_safefree(imapc->mailbox_uidvalidity);
imapc->mailbox_uidvalidity = strdup(tmp);
}
if(parsed) {
- infof(data, "Found %" CURL_FORMAT_CURL_OFF_TU " bytes to download\n",
+ infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download\n",
size);
Curl_pgrsSetDownloadSize(data, size);
data->req.bytecount += chunk;
- infof(data, "Written %" CURL_FORMAT_CURL_OFF_TU
- " bytes, %" CURL_FORMAT_CURL_OFF_TU
- " bytes are left for transfer\n", (curl_off_t)chunk,
- size - chunk);
+ infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
+ " bytes are left for transfer\n", chunk, size - chunk);
/* Have we used the entire cache or just part of it?*/
if(pp->cache_size > chunk) {
result = status; /* use the already set error code */
}
else if(!data->set.connect_only && !imap->custom &&
- (imap->uid || data->set.upload ||
+ (imap->uid || imap->mindex || data->set.upload ||
data->set.mimepost.kind != MIMEKIND_NONE)) {
/* Handle responses after FETCH or APPEND transfer has finished */
+
if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
state(conn, IMAP_FETCH_FINAL);
else {
Curl_safefree(imap->mailbox);
Curl_safefree(imap->uidvalidity);
Curl_safefree(imap->uid);
+ Curl_safefree(imap->mindex);
Curl_safefree(imap->section);
Curl_safefree(imap->partial);
Curl_safefree(imap->query);
else if(imap->custom && (selected || !imap->mailbox))
/* Custom command using the same mailbox or no mailbox */
result = imap_perform_list(conn);
- else if(!imap->custom && selected && imap->uid)
+ else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
result = imap_perform_fetch(conn);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
result = imap_perform_search(conn);
else if(imap->mailbox && !selected &&
- (imap->custom || imap->uid || imap->query))
+ (imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
result = imap_perform_select(conn);
else
static CURLcode imap_setup_connection(struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
-
/* Initialise the IMAP layer */
CURLcode result = imap_init(conn);
if(result)
/* Clear the TLS upgraded flag */
conn->tls_upgraded = FALSE;
- data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
- const char *begin = data->state.path;
+ const char *begin = &data->state.up.path[1]; /* skip leading slash */
const char *ptr = begin;
/* See how much of the URL is a valid path and decode it */
imap->uid = value;
value = NULL;
}
+ else if(strcasecompare(name, "MAILINDEX") && !imap->mindex) {
+ if(valuelen > 0 && value[valuelen - 1] == '/')
+ value[valuelen - 1] = '\0';
+
+ imap->mindex = value;
+ value = NULL;
+ }
else if(strcasecompare(name, "SECTION") && !imap->section) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
/* Does the URL contain a query parameter? Only valid when we have a mailbox
and no UID as per RFC-5092 */
- if(imap->mailbox && !imap->uid && *ptr == '?') {
- /* Find the length of the query parameter */
- begin = ++ptr;
- while(imap_is_bchar(*ptr))
- ptr++;
-
- /* Decode the query parameter */
- result = Curl_urldecode(data, begin, ptr - begin, &imap->query, NULL,
- TRUE);
- if(result)
- return result;
+ if(imap->mailbox && !imap->uid && !imap->mindex) {
+ /* Get the query parameter, URL decoded */
+ (void)curl_url_get(data->state.uh, CURLUPART_QUERY, &imap->query,
+ CURLU_URLDECODE);
}
/* Any extra stuff at the end of the URL is an error */
char *mailbox; /* Mailbox to select */
char *uidvalidity; /* UIDVALIDITY to check in select */
char *uid; /* Message UID to fetch */
+ char *mindex; /* Index in mail box of mail to fetch */
char *section; /* Message SECTION to fetch */
char *partial; /* Message PARTIAL to fetch */
char *query; /* Query to search for */
*/
static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
{
- char tmp[sizeof "255.255.255.255"];
+ char tmp[sizeof("255.255.255.255")];
size_t len;
DEBUGASSERT(size >= 16);
#endif
#endif /* HEADER_CURL_INET_NTOP_H */
-
#endif
#endif /* HEADER_CURL_INET_PTON_H */
-
if(maj != GSS_S_COMPLETE) {
gss_release_name(&min, &gssname);
if(service == srv_host) {
- Curl_failf(data, "Error importing service name %s@%s", service, host);
+ failf(data, "Error importing service name %s@%s", service, host);
return AUTH_ERROR;
}
service = srv_host;
result = CURLE_OUT_OF_MEMORY;
free(p);
+ free(cmd);
if(result) {
ret = -2;
(unsigned char **)&_gssresp.value,
&_gssresp.length);
if(result) {
- Curl_failf(data, "base64-decoding: %s",
- curl_easy_strerror(result));
+ failf(data, "base64-decoding: %s", curl_easy_strerror(result));
ret = AUTH_CONTINUE;
break;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
#endif
-/* These are macros in both <wincrypt.h> (in above <winldap.h>) and typedefs
- * in BoringSSL's <openssl/x509.h>
- */
-#ifdef HAVE_BORINGSSL
-# undef X509_NAME
-# undef X509_CERT_PAIR
-# undef X509_EXTENSIONS
-#endif
-
#include "urldata.h"
#include <curl/curl.h>
#include "sendf.h"
#endif
}
if(rc != 0) {
- failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
+#ifdef USE_WIN32_LDAP
+ failf(data, "LDAP local: bind via ldap_win_bind %s",
+ ldap_err2string(rc));
+#else
+ failf(data, "LDAP local: bind via ldap_simple_bind_s %s",
+ ldap_err2string(rc));
+#endif
result = CURLE_LDAP_CANNOT_BIND;
goto quit;
}
size_t i;
if(!conn->data ||
- !conn->data->state.path ||
- conn->data->state.path[0] != '/' ||
- !checkprefix("LDAP", conn->data->change.url))
+ !conn->data->state.up.path ||
+ conn->data->state.up.path[0] != '/' ||
+ !strcasecompare("LDAP", conn->data->state.up.scheme))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
ludp->lud_host = conn->host.name;
/* Duplicate the path */
- p = path = strdup(conn->data->state.path + 1);
+ p = path = strdup(conn->data->state.up.path + 1);
if(!path)
return LDAP_NO_MEMORY;
struct curl_llist *, struct curl_llist_element *);
#endif /* HEADER_CURL_LLIST_H */
-
* MD4 Message-Digest Algorithm (RFC 1320).
*
* Homepage:
- http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
+ https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
- http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
#endif /* CRYPTO LIBS */
-/* Disable this picky gcc-8 compiler warning */
-#if defined(__GNUC__) && (__GNUC__ >= 8)
-#pragma GCC diagnostic ignored "-Wcast-function-type"
-#endif
-
const HMAC_params Curl_HMAC_MD5[] = {
{
- (HMAC_hinit_func) MD5_Init, /* Hash initialization function. */
- (HMAC_hupdate_func) MD5_Update, /* Hash update function. */
- (HMAC_hfinal_func) MD5_Final, /* Hash computation end function. */
- sizeof(MD5_CTX), /* Size of hash context structure. */
- 64, /* Maximum key length. */
- 16 /* Result size. */
+ /* Hash initialization function. */
+ CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init),
+ /* Hash update function. */
+ CURLX_FUNCTION_CAST(HMAC_hupdate_func, MD5_Update),
+ /* Hash computation end function. */
+ CURLX_FUNCTION_CAST(HMAC_hfinal_func, MD5_Final),
+ /* Size of hash context structure. */
+ sizeof(MD5_CTX),
+ /* Maximum key length. */
+ 64,
+ /* Result size. */
+ 16
}
};
const MD5_params Curl_DIGEST_MD5[] = {
{
- (Curl_MD5_init_func) MD5_Init, /* Digest initialization function */
- (Curl_MD5_update_func) MD5_Update, /* Digest update function */
- (Curl_MD5_final_func) MD5_Final, /* Digest computation end function */
- sizeof(MD5_CTX), /* Size of digest context struct */
- 16 /* Result size */
+ /* Digest initialization function */
+ CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init),
+ /* Digest update function */
+ CURLX_FUNCTION_CAST(Curl_MD5_update_func, MD5_Update),
+ /* Digest computation end function */
+ CURLX_FUNCTION_CAST(Curl_MD5_final_func, MD5_Final),
+ /* Size of digest context struct */
+ sizeof(MD5_CTX),
+ /* Result size */
+ 16
}
};
MD5_context *ctxt;
/* Create MD5 context */
- ctxt = malloc(sizeof *ctxt);
+ ctxt = malloc(sizeof(*ctxt));
if(!ctxt)
return ctxt;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#endif
#endif /* HAVE_GETADDRINFO */
-#ifdef HAVE_GETNAMEINFO
-#undef getnameinfo
-#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
- curl_dogetnameinfo(sa, salen, host, hostlen, serv, servlen, flags, \
- __LINE__, __FILE__)
-#endif /* HAVE_GETNAMEINFO */
-
#ifdef HAVE_FREEADDRINFO
#undef freeaddrinfo
#define freeaddrinfo(data) \
mime_encoder_state *st = &part->encstate;
char *ptr = buffer;
size_t cursize = 0;
- int i;
- size_t len;
- size_t consumed;
int softlinebreak;
char buf[4];
character constants that can be interpreted as non-ascii on some
platforms. Preserve ASCII encoding on output too. */
while(st->bufbeg < st->bufend) {
- len = 1;
- consumed = 1;
- i = st->buf[st->bufbeg];
+ size_t len = 1;
+ size_t consumed = 1;
+ int i = st->buf[st->bufbeg];
buf[0] = (char) i;
buf[1] = aschex[(i >> 4) & 0xF];
buf[2] = aschex[i & 0xF];
st->bufbeg = 0;
st->bufend = len;
}
- if(st->bufend >= sizeof st->buf)
+ if(st->bufend >= sizeof(st->buf))
return cursize? cursize: READ_ERROR; /* Buffer full. */
sz = read_part_content(part, st->buf + st->bufend,
- sizeof st->buf - st->bufend);
+ sizeof(st->buf) - st->bufend);
switch(sz) {
case 0:
ateof = TRUE;
char *buffer, size_t bufsize)
{
size_t cursize = 0;
- size_t sz;
- struct curl_slist *hdr;
#ifdef CURL_DOES_CONVERSIONS
char *convbuf = buffer;
#endif
/* Readback from part. */
while(bufsize) {
- sz = 0;
- hdr = (struct curl_slist *) part->state.ptr;
+ size_t sz = 0;
+ struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
switch(part->state.state) {
case MIMESTATE_BEGIN:
mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
{
curl_mime *mime = (curl_mime *) instream;
size_t cursize = 0;
- size_t sz;
- curl_mimepart *part;
#ifdef CURL_DOES_CONVERSIONS
char *convbuf = buffer;
#endif
(void) size; /* Always 1. */
while(nitems) {
- sz = 0;
- part = mime->state.ptr;
+ size_t sz = 0;
+ curl_mimepart *part = mime->state.ptr;
switch(mime->state.state) {
case MIMESTATE_BEGIN:
case MIMESTATE_BODY:
curl_mime *mime = (curl_mime *) instream;
curl_mimepart *part;
int result = CURL_SEEKFUNC_OK;
- int res;
if(whence != SEEK_SET || offset)
return CURL_SEEKFUNC_CANTSEEK; /* Only support full rewind. */
return CURL_SEEKFUNC_OK; /* Already rewound. */
for(part = mime->firstpart; part; part = part->nextpart) {
- res = mime_part_rewind(part);
+ int res = mime_part_rewind(part);
if(res != CURL_SEEKFUNC_OK)
result = res;
}
{
curl_mime *mime;
- mime = (curl_mime *) malloc(sizeof *mime);
+ mime = (curl_mime *) malloc(sizeof(*mime));
if(mime) {
mime->easy = easy;
}
memset(mime->boundary, '-', 24);
- Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
- MIME_RAND_BOUNDARY_CHARS + 1);
+ if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+ MIME_RAND_BOUNDARY_CHARS + 1)) {
+ /* failed to get random separator, bail out */
+ free(mime->boundary);
+ free(mime);
+ return NULL;
+ }
mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
}
/* Initialize a mime part. */
void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
{
- memset((char *) part, 0, sizeof *part);
+ memset((char *) part, 0, sizeof(*part));
part->easy = easy;
mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
}
if(!mime)
return NULL;
- part = (curl_mimepart *) malloc(sizeof *part);
+ part = (curl_mimepart *) malloc(sizeof(*part));
if(part) {
Curl_mime_initpart(part, mime->easy);
CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
{
CURLcode result = CURLE_OK;
- char *base;
if(!part)
return CURLE_BAD_FUNCTION_ARGUMENT;
cleanup_part_content(part);
if(filename) {
+ char *base;
struct_stat sbuf;
if(stat(filename, &sbuf) || access(filename, R_OK))
static curl_off_t multipart_size(curl_mime *mime)
{
curl_off_t size;
- curl_off_t sz;
size_t boundarysize;
curl_mimepart *part;
size = boundarysize; /* Final boundary - CRLF after headers. */
for(part = mime->firstpart; part; part = part->nextpart) {
- sz = Curl_mime_size(part);
+ curl_off_t sz = Curl_mime_size(part);
if(sz < 0)
size = sz;
const char *Curl_mime_contenttype(const char *filename)
{
- unsigned int i;
-
/*
* If no content type was specified, we scan through a few well-known
* extensions and pick the first we match!
if(filename) {
size_t len1 = strlen(filename);
const char *nameend = filename + len1;
+ unsigned int i;
- for(i = 0; i < sizeof ctts / sizeof ctts[0]; i++) {
+ for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) {
size_t len2 = strlen(ctts[i].extension);
if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
#include "progress.h"
#include "easyif.h"
#include "share.h"
+#include "psl.h"
#include "multiif.h"
#include "sendf.h"
#include "timeval.h"
#define GOOD_MULTI_HANDLE(x) \
((x) && (x)->type == CURL_MULTI_HANDLE)
-static void singlesocket(struct Curl_multi *multi,
- struct Curl_easy *data);
+static CURLMcode singlesocket(struct Curl_multi *multi,
+ struct Curl_easy *data);
static int update_timer(struct Curl_multi *multi);
static CURLMcode add_next_timeout(struct curltime now,
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);
+static void Curl_init_completed(struct Curl_easy *data)
+{
+ /* this is a completed transfer */
+
+ /* Important: reset the conn pointer so that we don't point to memory
+ that could be freed anytime */
+ data->easy_conn = NULL;
+ Curl_expire_clear(data); /* stop all timers */
+}
+
/* always use this function to change state, to make debugging easier */
static void mstate(struct Curl_easy *data, CURLMstate state
#ifdef DEBUGBUILD
{
CURLMstate oldstate = data->mstate;
static const init_multistate_func finit[CURLM_STATE_LAST] = {
- NULL,
- NULL,
+ NULL, /* INIT */
+ NULL, /* CONNECT_PEND */
Curl_init_CONNECT, /* CONNECT */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- Curl_connect_free /* DO */
- /* the rest is NULL too */
+ NULL, /* WAITRESOLVE */
+ NULL, /* WAITCONNECT */
+ NULL, /* WAITPROXYCONNECT */
+ NULL, /* SENDPROTOCONNECT */
+ NULL, /* PROTOCONNECT */
+ NULL, /* WAITDO */
+ Curl_connect_free, /* DO */
+ NULL, /* DOING */
+ NULL, /* DO_MORE */
+ NULL, /* DO_DONE */
+ NULL, /* WAITPERFORM */
+ NULL, /* PERFORM */
+ NULL, /* TOOFAST */
+ NULL, /* DONE */
+ Curl_init_completed, /* COMPLETED */
+ NULL /* MSGSENT */
};
#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
Curl_llist_init(&multi->pending, multi_freeamsg);
multi->max_pipeline_length = 5;
+ multi->pipelining = CURLPIPE_MULTIPLEX;
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
else
data->state.conn_cache = &multi->conn_cache;
+#ifdef USE_LIBPSL
+ /* Do the same for PSL. */
+ if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
+ data->psl = &data->share->psl;
+ else
+ data->psl = &multi->psl;
+#endif
+
/* This adds the new entry at the 'end' of the doubly-linked circular
list of Curl_easy structs to try and maintain a FIFO queue so
the pipelined requests are in order. */
happens if the lastcall time is set to the same time when the handle is
removed as when the next handle is added, as then the check in
update_timer() that prevents calling the application multiple times with
- the same timer infor will not trigger and then the new handle's timeout
+ the same timer info will not trigger and then the new handle's timeout
will not be notified to the app.
The work-around is thus simply to clear the 'lastcall' variable to force
data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
data->state.conn_cache->closure_handle->set.server_response_timeout =
data->set.server_response_timeout;
+ data->state.conn_cache->closure_handle->set.no_signal =
+ data->set.no_signal;
update_timer(multi);
return CURLM_OK;
/* Stop if multi_done() has already been called */
return CURLE_OK;
+ if(data->mstate == CURLM_STATE_WAITRESOLVE) {
+ /* still waiting for the resolve to complete */
+ (void)Curl_resolver_wait_resolv(conn, NULL);
+ }
+
Curl_getoff_all_pipelines(data, conn);
/* Cleanup possible redirect junk */
- free(data->req.newurl);
- data->req.newurl = NULL;
- free(data->req.location);
- data->req.location = NULL;
+ Curl_safefree(data->req.newurl);
+ Curl_safefree(data->req.location);
switch(status) {
case CURLE_ABORTED_BY_CALLBACK:
if(conn->send_pipe.size || conn->recv_pipe.size) {
/* Stop if pipeline is not empty . */
data->easy_conn = NULL;
- DEBUGF(infof(data, "Connection still in use %d/%d, "
+ DEBUGF(infof(data, "Connection still in use %zu/%zu, "
"no more multi_done now!\n",
conn->send_pipe.size, conn->recv_pipe.size));
return CURLE_OK;
conn->dns_entry = NULL;
}
Curl_hostcache_prune(data);
+ Curl_safefree(data->state.ulbuf);
/* if the transfer was completed in a paused state there can be buffered
data left to free */
#endif
) || conn->bits.close
|| (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
- CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
+ CURLcode res2 = Curl_disconnect(data, conn, premature);
/* If we had an error already, make sure we return that one. But
if we got a new error, return that. */
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname);
- /* the connection is no longer in use */
+ /* the connection is no longer in use by this transfer */
if(Curl_conncache_return_conn(conn)) {
/* remember the most recently used connection */
data->state.lastconnect = conn;
cache here, and therefore cannot be used from this point on
*/
Curl_free_request_state(data);
-
return result;
}
Curl_getoff_all_pipelines(data, data->easy_conn);
}
+ if(data->connect_queue.ptr)
+ /* the handle was in the pending list waiting for an available connection,
+ so go ahead and remove it */
+ Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
+
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* stop using the multi handle's DNS cache, *after* the possible
multi_done() call above */
data->easy_conn = NULL;
}
+#ifdef USE_LIBPSL
+ /* Remove the PSL association. */
+ if(data->psl == &multi->psl)
+ data->psl = NULL;
+#endif
+
data->multi = NULL; /* clear the association to this multi handle */
/* make sure there's no pending message in the queue sent from this easy
of sockets */
int numsocks)
{
- /* If the pipe broke, or if there's no connection left for this easy handle,
- then we MUST bail out now with no bitmask set. The no connection case can
- happen when this is called from curl_multi_remove_handle() =>
- singlesocket() => multi_getsock().
+ /* The no connection case can happen when this is called from
+ curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/
- if(data->state.pipe_broke || !data->easy_conn)
+ if(!data->easy_conn)
return 0;
if(data->mstate > CURLM_STATE_CONNECT &&
return 0;
case CURLM_STATE_WAITRESOLVE:
- return Curl_resolver_getsock(data->easy_conn, socks, numsocks);
+ return Curl_resolv_getsock(data->easy_conn, socks, numsocks);
case CURLM_STATE_PROTOCONNECT:
case CURLM_STATE_SENDPROTOCONNECT:
struct Curl_easy *data;
int this_max_fd = -1;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
- int bitmap;
int i;
(void)exc_fd_set; /* not used */
data = multi->easyp;
while(data) {
- bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+ int bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- /* If the internally desired timeout is actually shorter than requested from
- the outside, then use the shorter time! But only if the internal timer
- is actually larger than -1! */
- (void)multi_timeout(multi, &timeout_internal);
- if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
- timeout_ms = (int)timeout_internal;
-
/* Count up how many fds we have from the multi handle */
data = multi->easyp;
while(data) {
data = data->next; /* check next handle */
}
+ /* If the internally desired timeout is actually shorter than requested from
+ the outside, then use the shorter time! But only if the internal timer
+ is actually larger than -1! */
+ (void)multi_timeout(multi, &timeout_internal);
+ if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
+ timeout_ms = (int)timeout_internal;
+
curlfds = nfds; /* number of internal file descriptors */
nfds += extra_nfds; /* add the externally provided ones */
int pollrc;
/* wait... */
pollrc = Curl_poll(ufds, nfds, timeout_ms);
- DEBUGF(infof(data, "Curl_poll(%d ds, %d ms) == %d\n",
- nfds, timeout_ms, pollrc));
if(pollrc > 0) {
retcode = pollrc;
return result;
/* Resolved, continue with the connection */
- result = Curl_async_resolved(conn, &protocol_done);
+ result = Curl_once_resolved(conn, &protocol_done);
if(result)
return result;
}
bool stream_error = FALSE;
rc = CURLM_OK;
- /* Handle the case when the pipe breaks, i.e., the connection
- we're using gets cleaned up and we're left with nothing. */
- if(data->state.pipe_broke) {
- infof(data, "Pipe broke: handle %p, url = %s\n",
- (void *)data, data->state.path);
-
- if(data->mstate < CURLM_STATE_COMPLETED) {
- /* Head back to the CONNECT state */
- multistate(data, CURLM_STATE_CONNECT);
- rc = CURLM_CALL_MULTI_PERFORM;
- result = CURLE_OK;
- }
-
- data->state.pipe_broke = FALSE;
- data->easy_conn = NULL;
- continue;
- }
-
if(!data->easy_conn &&
data->mstate > CURLM_STATE_CONNECT &&
data->mstate < CURLM_STATE_DONE) {
}
if(!dns)
- result = Curl_resolver_is_resolved(data->easy_conn, &dns);
+ result = Curl_resolv_check(data->easy_conn, &dns);
/* Update sockets here, because the socket(s) may have been
closed and the application thus needs to be told, even if it
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
- result = Curl_async_resolved(data->easy_conn, &protocol_connect);
+ result = Curl_once_resolved(data->easy_conn, &protocol_connect);
if(result)
- /* if Curl_async_resolved() returns failure, the connection struct
+ /* if Curl_once_resolved() returns failure, the connection struct
is already freed and gone */
data->easy_conn = NULL; /* no more connection */
else {
multistate(data, CURLM_STATE_SENDPROTOCONNECT);
}
}
+ else if(result)
+ stream_error = TRUE;
break;
#endif
case CURLM_STATE_SENDPROTOCONNECT:
result = Curl_protocol_connect(data->easy_conn, &protocol_connect);
- if(!protocol_connect)
+ if(!result && !protocol_connect)
/* switch to waiting state */
multistate(data, CURLM_STATE_PROTOCONNECT);
else if(!result) {
char *newurl = NULL;
followtype follow = FOLLOW_NONE;
CURLcode drc;
- bool retry = FALSE;
drc = Curl_retry_request(data->easy_conn, &newurl);
if(drc) {
result = drc;
stream_error = TRUE;
}
- else
- retry = (newurl)?TRUE:FALSE;
Curl_posttransfer(data);
drc = multi_done(&data->easy_conn, result, FALSE);
/* When set to retry the connection, we must to go back to
* the CONNECT state */
- if(retry) {
+ if(newurl) {
if(!drc || (drc == CURLE_SEND_ERROR)) {
follow = FOLLOW_RETRY;
drc = Curl_follow(data, newurl, follow);
CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
if(!ret)
retry = (newurl)?TRUE:FALSE;
+ else if(!result)
+ result = ret;
if(retry) {
/* if we are to retry, set the result to OK and consider the
rc = CURLM_CALL_MULTI_PERFORM;
}
}
+ free(newurl);
}
else {
/* after the transfer is done, go DONE */
newurl = data->req.location;
data->req.location = NULL;
result = Curl_follow(data, newurl, FOLLOW_FAKE);
- if(result)
+ free(newurl);
+ if(result) {
stream_error = TRUE;
+ result = multi_done(&data->easy_conn, result, TRUE);
+ }
}
- multistate(data, CURLM_STATE_DONE);
- rc = CURLM_CALL_MULTI_PERFORM;
+ if(!result) {
+ multistate(data, CURLM_STATE_DONE);
+ rc = CURLM_CALL_MULTI_PERFORM;
+ }
}
}
else if(comeback)
rc = CURLM_CALL_MULTI_PERFORM;
-
- free(newurl);
break;
}
break;
case CURLM_STATE_COMPLETED:
- /* this is a completed transfer, it is likely to still be connected */
-
- /* This node should be delinked from the list now and we should post
- an information message that we are complete. */
-
- /* Important: reset the conn pointer so that we don't point to memory
- that could be freed anytime */
- data->easy_conn = NULL;
-
- Curl_expire_clear(data); /* stop all timers */
break;
case CURLM_STATE_MSGSENT:
/* NOTE: no attempt to disconnect connections must be made
in the case blocks above - cleanup happens only here */
- data->state.pipe_broke = FALSE;
-
/* Check if we can move pending requests to send pipe */
process_pending_handles(multi); /* connection */
/* Don't attempt to send data over a connection that timed out */
bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
/* disconnect properly */
- Curl_disconnect(data->easy_conn, dead_connection);
+ Curl_disconnect(data, data->easy_conn, dead_connection);
/* This is where we make sure that the easy_conn pointer is reset.
We don't have to do this in every case block above where a
}
multistate(data, CURLM_STATE_COMPLETED);
+ rc = CURLM_CALL_MULTI_PERFORM;
}
/* if there's still a connection to use, call the progress function */
else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
}
if(CURLM_STATE_COMPLETED == data->mstate) {
- /* now fill in the Curl_message with this info */
- msg = &data->msg;
-
- msg->extmsg.msg = CURLMSG_DONE;
- msg->extmsg.easy_handle = data;
- msg->extmsg.data.result = result;
+ if(data->set.fmultidone) {
+ /* signal via callback instead */
+ data->set.fmultidone(data, result);
+ }
+ else {
+ /* now fill in the Curl_message with this info */
+ msg = &data->msg;
- rc = multi_addmsg(multi, msg);
+ msg->extmsg.msg = CURLMSG_DONE;
+ msg->extmsg.easy_handle = data;
+ msg->extmsg.data.result = result;
+ rc = multi_addmsg(multi, msg);
+ DEBUGASSERT(!data->easy_conn);
+ }
multistate(data, CURLM_STATE_MSGSENT);
}
} while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
data->result = result;
-
-
return rc;
}
data->state.conn_cache = NULL;
data->multi = NULL; /* clear the association */
+#ifdef USE_LIBPSL
+ if(data->psl == &multi->psl)
+ data->psl = NULL;
+#endif
+
data = nextdata;
}
Curl_llist_destroy(&multi->pending, NULL);
Curl_hash_destroy(&multi->hostcache);
+ Curl_psl_destroy(&multi->psl);
/* Free the blacklists by setting them to NULL */
Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
* and if we have a different state in any of those sockets from last time we
* call the callback accordingly.
*/
-static void singlesocket(struct Curl_multi *multi,
- struct Curl_easy *data)
+static CURLMcode singlesocket(struct Curl_multi *multi,
+ struct Curl_easy *data)
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int i;
entry = sh_addentry(&multi->sockhash, s, data);
if(!entry)
/* fatal */
- return;
+ return CURLM_OUT_OF_MEMORY;
}
/* we know (entry != NULL) at this point, see the logic above */
memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
data->numsocks = num;
+ return CURLM_OK;
}
void Curl_updatesocket(struct Curl_easy *data)
void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
{
- struct Curl_multi *multi = conn->data->multi;
- if(multi) {
- /* this is set if this connection is part of a handle that is added to
- a multi handle, and only then this is necessary */
- struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
-
- if(entry) {
- if(multi->socket_cb)
- multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
- multi->socket_userp,
- entry->socketp);
+ if(conn->data) {
+ /* if there's still an easy handle associated with this connection */
+ struct Curl_multi *multi = conn->data->multi;
+ if(multi) {
+ /* this is set if this connection is part of a handle that is added to
+ a multi handle, and only then this is necessary */
+ struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
+
+ if(entry) {
+ if(multi->socket_cb)
+ multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+ multi->socket_userp,
+ entry->socketp);
- /* now remove it from the socket hash */
- sh_delentry(&multi->sockhash, s);
+ /* now remove it from the socket hash */
+ sh_delentry(&multi->sockhash, s);
+ }
}
}
}
and callbacks */
if(result != CURLM_BAD_HANDLE) {
data = multi->easyp;
- while(data) {
- singlesocket(multi, data);
+ while(data && !result) {
+ result = singlesocket(multi, data);
data = data->next;
}
}
/* clear the bitmask only if not locked */
data->easy_conn->cselect_bits = 0;
- if(CURLM_OK >= result)
+ if(CURLM_OK >= result) {
/* get the socket(s) and check if the state has been changed since
last */
- singlesocket(multi, data);
+ result = singlesocket(multi, data);
+ if(result)
+ return result;
+ }
/* Now we fall-through and do the timer-based stuff, since we don't want
to force the user to have to deal with timeouts as long as at least
result = multi_runsingle(multi, now, data);
sigpipe_restore(&pipe_st);
- if(CURLM_OK >= result)
+ if(CURLM_OK >= result) {
/* get the socket(s) and check if the state has been changed since
last */
- singlesocket(multi, data);
+ result = singlesocket(multi, data);
+ if(result)
+ return result;
+ }
}
/* Check if there's one (more) expired timer to deal with! This function
multi->push_userp = va_arg(param, void *);
break;
case CURLMOPT_PIPELINING:
- multi->pipelining = va_arg(param, long);
+ multi->pipelining = va_arg(param, long) & CURLPIPE_MULTIPLEX;
break;
case CURLMOPT_TIMERFUNCTION:
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
{
struct Curl_multi *multi = data->multi;
struct curltime *nowp = &data->state.expiretime;
- int rc;
struct curltime set;
/* this is only interesting while there is still an associated multi struct
Compare if the new time is earlier, and only remove-old/add-new if it
is. */
timediff_t diff = Curl_timediff(set, *nowp);
+ int rc;
if(diff > 0) {
/* The current splay tree entry is sooner than this new expiry time.
{
struct Curl_multi *multi = data->multi;
struct curltime *nowp = &data->state.expiretime;
- int rc;
/* this is only interesting while there is still an associated multi struct
remaining! */
/* Since this is an cleared time, we must remove the previous entry from
the splay tree */
struct curl_llist *list = &data->state.timeoutlist;
+ int rc;
rc = Curl_splayremovebyaddr(multi->timetree,
&data->state.timenode,
}
}
-void Curl_set_in_callback(struct Curl_easy *easy, bool value)
+void Curl_set_in_callback(struct Curl_easy *data, bool value)
{
- if(easy->multi_easy)
- easy->multi_easy->in_callback = value;
- else if(easy->multi)
- easy->multi->in_callback = value;
+ /* might get called when there is no data pointer! */
+ if(data) {
+ if(data->multi_easy)
+ data->multi_easy->in_callback = value;
+ else if(data->multi)
+ data->multi->in_callback = value;
+ }
}
bool Curl_is_in_callback(struct Curl_easy *easy)
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
***************************************************************************/
#include "conncache.h"
+#include "psl.h"
struct Curl_message {
struct curl_llist_element list;
/* Hostname cache */
struct curl_hash hostcache;
+#ifdef USE_LIBPSL
+ /* PSL cache. */
+ struct PslCache psl;
+#endif
+
/* timetree points to the splay-tree of time nodes to figure out expire
times of all currently set timers */
struct Curl_tree *timetree;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
{
FILE *file;
int retcode = 1;
- int specific_login = (*loginp && **loginp != 0);
+ char *login = *loginp;
+ char *password = *passwordp;
+ bool specific_login = (login && *login != 0);
+ bool login_alloc = FALSE;
+ bool password_alloc = FALSE;
bool netrc_alloc = FALSE;
enum host_lookup_state state = NOTHING;
char *tok;
char *tok_buf;
bool done = FALSE;
- char netrcbuffer[256];
+ char netrcbuffer[4096];
int netrcbuffsize = (int)sizeof(netrcbuffer);
while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
continue;
while(!done && tok) {
- if((*loginp && **loginp) && (*passwordp && **passwordp)) {
+ if((login && *login) && (password && *password)) {
done = TRUE;
break;
}
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
- state_our_login = strcasecompare(*loginp, tok);
+ state_our_login = strcasecompare(login, tok);
}
else {
- free(*loginp);
- *loginp = strdup(tok);
- if(!*loginp) {
+ if(login_alloc) {
+ free(login);
+ login_alloc = FALSE;
+ }
+ login = strdup(tok);
+ if(!login) {
retcode = -1; /* allocation failed */
goto out;
}
+ login_alloc = TRUE;
}
state_login = 0;
}
else if(state_password) {
if(state_our_login || !specific_login) {
- free(*passwordp);
- *passwordp = strdup(tok);
- if(!*passwordp) {
+ if(password_alloc) {
+ free(password);
+ password_alloc = FALSE;
+ }
+ password = strdup(tok);
+ if(!password) {
retcode = -1; /* allocation failed */
goto out;
}
+ password_alloc = TRUE;
}
state_password = 0;
}
} /* while fgets() */
out:
+ if(!retcode) {
+ if(login_alloc) {
+ if(*loginp)
+ free(*loginp);
+ *loginp = login;
+ }
+ if(password_alloc) {
+ if(*passwordp)
+ free(*passwordp);
+ *passwordp = password;
+ }
+ }
+ else {
+ if(login_alloc)
+ free(login);
+ if(password_alloc)
+ free(password);
+ }
fclose(file);
}
int nonblock /* TRUE or FALSE */)
{
#if defined(USE_BLOCKING_SOCKETS)
-
+ (void)sockfd;
+ (void)nonblock;
return 0; /* returns success */
#elif defined(HAVE_FCNTL_O_NONBLOCK)
int nonblock /* TRUE or FALSE */);
#endif /* HEADER_CURL_NONBLOCK_H */
-
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
if(!app_data->tenbytes || !app_data->lock) {
if(app_data->lock)
NXMutexFree(app_data->lock);
-
+ free(app_data->tenbytes);
free(app_data);
app_data = (libdata_t *) NULL;
err = ENOMEM;
err = set_app_data(gLibId, app_data);
if(err) {
+ if(app_data->lock)
+ NXMutexFree(app_data->lock);
+ free(app_data->tenbytes);
free(app_data);
app_data = (libdata_t *) NULL;
err = ENOMEM;
CURLcode Curl_gmtime(time_t intime, struct tm *store);
#endif /* HEADER_CURL_PARSEDATE_H */
-
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
struct connectdata *conn = pp->conn;
struct Curl_easy *data = conn->data;
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;
if(data->set.timeout) {
/* if timeout is requested, find out how much remaining time we have */
- timeout2_ms = data->set.timeout - /* timeout time */
+ time_t timeout2_ms = data->set.timeout - /* timeout time */
Curl_timediff(Curl_now(), conn->now); /* spent time */
/* pick the lowest number */
}
if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT,
- s, (size_t)bytes_written, conn);
+ Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
if(bytes_written != (ssize_t)write_len) {
/* the whole chunk was not sent, keep it around and adjust sizes */
#endif
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- pp->linestart_resp, (size_t)perline, conn);
+ pp->linestart_resp, (size_t)perline);
/*
* We pass all response-lines to the callback function registered
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2013 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
penalized = TRUE;
infof(data, "Conn: %ld (%p) Receive pipe weight: (%"
- CURL_FORMAT_CURL_OFF_T "/%zu), penalized: %s\n",
+ CURL_FORMAT_CURL_OFF_T "/%" CURL_FORMAT_CURL_OFF_T
+ "), penalized: %s\n",
conn->connection_id, (void *)conn, recv_size,
conn->chunk.datasize, penalized?"TRUE":"FALSE");
return penalized;
pipeline = &conn->send_pipe;
result = addHandleToPipeline(handle, pipeline);
-
- if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) {
+ if((conn->bundle->multiuse == BUNDLE_PIPELINING) &&
+ (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, EXPIRE_RUN_NOW);
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
- size_t i;
(void)instate; /* no use for this yet */
/* Does the server support APOP authentication? */
if(len >= 4 && line[len - 2] == '>') {
/* Look for the APOP timestamp */
+ size_t i;
for(i = 3; i < len - 2; ++i) {
if(line[i] == '<') {
/* Calculate the length of the timestamp */
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
- size_t wordlen;
(void)instate; /* no use for this yet */
/* Loop through the data line */
for(;;) {
size_t llen;
+ size_t wordlen;
unsigned int mechbit;
while(len &&
static CURLcode pop3_setup_connection(struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
-
/* Initialise the POP3 layer */
CURLcode result = pop3_init(conn);
if(result)
/* Clear the TLS upgraded flag */
conn->tls_upgraded = FALSE;
- data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
/* The POP3 struct is already initialised in pop3_connect() */
struct Curl_easy *data = conn->data;
struct POP3 *pop3 = data->req.protop;
- const char *path = data->state.path;
+ const char *path = &data->state.up.path[1]; /* skip leading path */
/* URL decode the path for the message ID */
return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
byte) */
static void time2str(char *r, curl_off_t seconds)
{
- curl_off_t d, h, m, s;
+ curl_off_t h;
if(seconds <= 0) {
strcpy(r, "--:--:--");
return;
}
h = seconds / CURL_OFF_T_C(3600);
if(h <= CURL_OFF_T_C(99)) {
- m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
- s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
+ curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
+ curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
}
else {
/* this equals to more than 99 hours, switch to a more suitable output
format to fit within the limits. */
- d = seconds / CURL_OFF_T_C(86400);
+ curl_off_t d = seconds / CURL_OFF_T_C(86400);
h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
if(d <= CURL_OFF_T_C(999))
snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
int Curl_pgrsUpdate(struct connectdata *conn)
{
struct curltime now;
- int result;
- char max5[6][10];
- curl_off_t dlpercen = 0;
- curl_off_t ulpercen = 0;
- curl_off_t total_percen = 0;
- curl_off_t total_transfer;
- curl_off_t total_expected_transfer;
curl_off_t timespent;
curl_off_t timespent_ms; /* milliseconds */
struct Curl_easy *data = conn->data;
int nowindex = data->progress.speeder_c% CURR_TIME;
- int checkindex;
- int countindex; /* amount of seconds stored in the speeder array */
- char time_left[10];
- char time_total[10];
- char time_spent[10];
- curl_off_t ulestimate = 0;
- curl_off_t dlestimate = 0;
- curl_off_t total_estimate;
bool shownow = FALSE;
curl_off_t dl = data->progress.downloaded;
curl_off_t ul = data->progress.uploaded;
/* Calculations done at most once a second, unless end is reached */
if(data->progress.lastshow != now.tv_sec) {
+ int countindex; /* amount of seconds stored in the speeder array */
shownow = TRUE;
data->progress.lastshow = now.tv_sec;
/* first of all, we don't do this if there's no counted seconds yet */
if(countindex) {
+ int checkindex;
timediff_t span_ms;
/* Get the index position to compare with the 'nowindex' position.
if(!(data->progress.flags & PGRS_HIDE)) {
/* progress meter has not been shut off */
+ char max5[6][10];
+ curl_off_t dlpercen = 0;
+ curl_off_t ulpercen = 0;
+ curl_off_t total_percen = 0;
+ curl_off_t total_transfer;
+ curl_off_t total_expected_transfer;
+ char time_left[10];
+ char time_total[10];
+ char time_spent[10];
+ curl_off_t ulestimate = 0;
+ curl_off_t dlestimate = 0;
+ curl_off_t total_estimate;
if(data->set.fxferinfo) {
+ int result;
/* There's a callback set, call that */
Curl_set_in_callback(data, true);
result = data->set.fxferinfo(data->set.progress_client,
return result;
}
if(data->set.fprogress) {
+ int result;
/* The older deprecated callback is set, call that */
Curl_set_in_callback(data, true);
result = data->set.fprogress(data->set.progress_client,
struct curltime start,
struct curltime now);
-/* Don't show progress for sizes smaller than: */
-#define LEAST_SIZE_PROGRESS BUFSIZE
-
-#define PROGRESS_DOWNLOAD (1<<0)
-#define PROGRESS_UPLOAD (1<<1)
-#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD)
-
-#define PGRS_SHOW_DL (1<<0)
-#define PGRS_SHOW_UL (1<<1)
-#define PGRS_DONE_DL (1<<2)
-#define PGRS_DONE_UL (1<<3)
#define PGRS_HIDE (1<<4)
#define PGRS_UL_SIZE_KNOWN (1<<5)
#define PGRS_DL_SIZE_KNOWN (1<<6)
-
#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
-
#endif /* HEADER_CURL_PROGRESS_H */
-
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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"
+
+#include <curl/curl.h>
+
+#ifdef USE_LIBPSL
+
+#include "psl.h"
+#include "share.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+void Curl_psl_destroy(struct PslCache *pslcache)
+{
+ if(pslcache->psl) {
+ if(pslcache->dynamic)
+ psl_free((psl_ctx_t *) pslcache->psl);
+ pslcache->psl = NULL;
+ pslcache->dynamic = FALSE;
+ }
+}
+
+static time_t now_seconds(void)
+{
+ struct curltime now = Curl_now();
+
+ return now.tv_sec;
+}
+
+const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy)
+{
+ struct PslCache *pslcache = easy->psl;
+ const psl_ctx_t *psl;
+ time_t now;
+
+ if(!pslcache)
+ return NULL;
+
+ Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED);
+ now = now_seconds();
+ if(!pslcache->psl || pslcache->expires <= now) {
+ /* Let a chance to other threads to do the job: avoids deadlock. */
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+
+ /* Update cache: this needs an exclusive lock. */
+ Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SINGLE);
+
+ /* Recheck in case another thread did the job. */
+ now = now_seconds();
+ if(!pslcache->psl || pslcache->expires <= now) {
+ bool dynamic = FALSE;
+ time_t expires = TIME_T_MAX;
+
+#if defined(PSL_VERSION_NUMBER) && PSL_VERSION_NUMBER >= 0x001000
+ psl = psl_latest(NULL);
+ dynamic = psl != NULL;
+ /* Take care of possible time computation overflow. */
+ expires = now < TIME_T_MAX - PSL_TTL? now + PSL_TTL: TIME_T_MAX;
+
+ /* Only get the built-in PSL if we do not already have the "latest". */
+ if(!psl && !pslcache->dynamic)
+#endif
+
+ psl = psl_builtin();
+
+ if(psl) {
+ Curl_psl_destroy(pslcache);
+ pslcache->psl = psl;
+ pslcache->dynamic = dynamic;
+ pslcache->expires = expires;
+ }
+ }
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); /* Release exclusive lock. */
+ Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED);
+ }
+ psl = pslcache->psl;
+ if(!psl)
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+ return psl;
+}
+
+void Curl_psl_release(struct Curl_easy *easy)
+{
+ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+}
+
+#endif /* USE_LIBPSL */
--- /dev/null
+#ifndef HEADER_PSL_H
+#define HEADER_PSL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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.
+ *
+ ***************************************************************************/
+
+#ifdef USE_LIBPSL
+#include <libpsl.h>
+
+#define PSL_TTL (72 * 3600) /* PSL time to live before a refresh. */
+
+struct PslCache {
+ const psl_ctx_t *psl; /* The PSL. */
+ time_t expires; /* Time this PSL life expires. */
+ bool dynamic; /* PSL should be released when no longer needed. */
+};
+
+const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy);
+void Curl_psl_release(struct Curl_easy *easy);
+void Curl_psl_destroy(struct PslCache *pslcache);
+
+#else
+
+#define Curl_psl_use(easy) NULL
+#define Curl_psl_release(easy)
+#define Curl_psl_destroy(pslcache)
+
+#endif /* USE_LIBPSL */
+#endif /* HEADER_PSL_H */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
DEBUGASSERT(num > 1);
#ifdef __clang_analyzer__
- /* This silences a scan-build warning about accesssing this buffer with
+ /* This silences a scan-build warning about accessing this buffer with
uninitialized memory. */
memset(buffer, 0, sizeof(buffer));
#endif
return result;
while(num) {
+ /* clang-tidy warns on this line without this comment: */
+ /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
*rnd++ = hex[(*bufp & 0xF0)>>4];
*rnd++ = hex[*bufp & 0x0F];
bufp++;
struct Curl_easy *data = conn->data;
struct RTSP *rtsp = data->req.protop;
CURLcode httpStatus;
- long CSeq_sent;
- long CSeq_recv;
/* Bypass HTTP empty-reply checks on receive */
if(data->set.rtspreq == RTSPREQ_RECEIVE)
if(rtsp) {
/* Check the sequence numbers */
- CSeq_sent = rtsp->CSeq_sent;
- CSeq_recv = rtsp->CSeq_recv;
+ long CSeq_sent = rtsp->CSeq_sent;
+ long CSeq_recv = rtsp->CSeq_recv;
if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) {
failf(data,
"The CSeq of this request %ld did not match the response %ld",
return CURLE_OUT_OF_MEMORY;
result =
- Curl_add_bufferf(req_buffer,
+ Curl_add_bufferf(&req_buffer,
"%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
"CSeq: %ld\r\n", /* CSeq */
p_request, p_stream_uri, rtsp->CSeq_sent);
* to make comparison easier
*/
if(p_session_id) {
- result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id);
+ result = Curl_add_bufferf(&req_buffer, "Session: %s\r\n", p_session_id);
if(result)
return result;
}
/*
* Shared HTTP-like options
*/
- result = Curl_add_bufferf(req_buffer,
+ result = Curl_add_bufferf(&req_buffer,
"%s" /* transport */
"%s" /* accept */
"%s" /* accept-encoding */
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
if(!Curl_checkheaders(conn, "Content-Length")) {
- result = Curl_add_bufferf(req_buffer,
- "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
- (data->set.upload ? putsize : postsize));
+ result =
+ Curl_add_bufferf(&req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
+ (data->set.upload ? putsize : postsize));
if(result)
return result;
}
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(req_buffer,
- "Content-Type: text/parameters\r\n");
+ result = Curl_add_bufferf(&req_buffer,
+ "Content-Type: text/parameters\r\n");
if(result)
return result;
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(req_buffer,
- "Content-Type: application/sdp\r\n");
+ result = Curl_add_bufferf(&req_buffer,
+ "Content-Type: application/sdp\r\n");
if(result)
return result;
}
/* RTSP never allows chunked transfer */
data->req.forbidchunk = TRUE;
/* Finish the request buffer */
- result = Curl_add_buffer(req_buffer, "\r\n", 2);
+ result = Curl_add_buffer(&req_buffer, "\r\n", 2);
if(result)
return result;
if(postsize > 0) {
- result = Curl_add_buffer(req_buffer, data->set.postfields,
+ result = Curl_add_buffer(&req_buffer, data->set.postfields,
(size_t)postsize);
if(result)
return result;
}
/* issue the request */
- result = Curl_add_buffer_send(req_buffer, conn,
+ result = Curl_add_buffer_send(&req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
#endif /* HEADER_CURL_RTSP_H */
-
#include "strcase.h"
#include "warnless.h"
#include "strdup.h"
-/* The last #include file should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
#include "memdebug.h"
static const struct {
if(conn->data->set.verbose) {
buf[decoded_len] = '\n';
- Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn);
+ Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
}
buf[decoded_len] = '\0';
if(!conn->sec_complete) {
infof(conn->data, "Trying to change the protection level after the"
- "completion of the data exchange.\n");
+ " completion of the data exchange.\n");
return -1;
}
tmp_allocation = realloc(conn->app_data, mech->size);
if(tmp_allocation == NULL) {
- failf(data, "Failed realloc of size %u", mech->size);
+ failf(data, "Failed realloc of size %zu", mech->size);
mech = NULL;
return CURLE_OUT_OF_MEMORY;
}
#endif
struct curltime initial_tv;
int pending_ms;
- int error;
#endif
int r = 0;
pending_ms = timeout_ms;
initial_tv = Curl_now();
do {
+ int error;
#if defined(HAVE_POLL_FINE)
r = poll(NULL, 0, pending_ms);
#else
#endif
struct curltime initial_tv = {0, 0};
int pending_ms = 0;
- int error;
int r;
int ret;
}
do {
+ int error;
if(timeout_ms < 0)
pending_ms = -1;
else if(!timeout_ms)
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
do {
+ int error;
if(timeout_ms > 0) {
pending_tv.tv_sec = pending_ms / 1000;
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
bool fds_none = TRUE;
unsigned int i;
int pending_ms = 0;
- int error;
int r;
if(ufds) {
#ifdef HAVE_POLL_FINE
do {
+ int error;
if(timeout_ms < 0)
pending_ms = -1;
else if(!timeout_ms)
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
do {
+ int error;
if(timeout_ms > 0) {
pending_tv.tv_sec = pending_ms / 1000;
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
#endif
#endif /* HEADER_CURL_SELECT_H */
-
vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
va_end(ap);
len = strlen(print_buffer);
- Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
+ Curl_debug(data, CURLINFO_TEXT, print_buffer, len);
}
}
if(data->set.verbose) {
error[len] = '\n';
error[++len] = '\0';
- Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
+ Curl_debug(data, CURLINFO_TEXT, error, len);
}
va_end(ap);
}
break;
if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
if((size_t)bytes_written != write_len) {
/* if not all was written at once, we must advance the pointer, decrease
}
/* return 0 on success */
-static int showit(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size)
+int Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size)
{
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
#endif
return rc;
}
-
-int Curl_debug(struct Curl_easy *data, curl_infotype type,
- char *ptr, size_t size,
- struct connectdata *conn)
-{
- int rc;
- if(data->set.printhost && conn && conn->host.dispname) {
- char buffer[160];
- const char *t = NULL;
- const char *w = "Data";
- switch(type) {
- case CURLINFO_HEADER_IN:
- w = "Header";
- /* FALLTHROUGH */
- case CURLINFO_DATA_IN:
- t = "from";
- break;
- case CURLINFO_HEADER_OUT:
- w = "Header";
- /* FALLTHROUGH */
- case CURLINFO_DATA_OUT:
- t = "to";
- break;
- default:
- break;
- }
-
- if(t) {
- snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
- conn->host.dispname);
- rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
- if(rc)
- return rc;
- }
- }
- rc = showit(data, type, ptr, size);
- return rc;
-}
#elif defined(HAVE_VARIADIC_MACROS_GCC)
#define infof(x...) Curl_nop_stmt
#else
-#define infof (void)
+#error "missing VARIADIC macro define, fix and rebuild!"
#endif
#else /* CURL_DISABLE_VERBOSE_STRINGS */
ssize_t *written);
/* the function used to output verbose information */
-int Curl_debug(struct Curl_easy *handle, curl_infotype type,
- char *data, size_t size,
- struct connectdata *conn);
+int Curl_debug(struct Curl_easy *data, curl_infotype type,
+ char *ptr, size_t size);
#endif /* HEADER_CURL_SENDF_H */
data->set.dns_cache_timeout = arg;
break;
case CURLOPT_DNS_USE_GLOBAL_CACHE:
+#if 0 /* deprecated */
/* remember we want this enabled */
arg = va_arg(param, long);
data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
+#endif
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
va_arg(param, char *));
break;
+ case CURLOPT_TLS13_CIPHERS:
+ if(Curl_ssl_tls13_ciphersuites()) {
+ /* set preferred list of TLS 1.3 cipher suites */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG],
+ va_arg(param, char *));
+ }
+ else
+ return CURLE_NOT_BUILT_IN;
+ break;
+ case CURLOPT_PROXY_TLS13_CIPHERS:
+ if(Curl_ssl_tls13_ciphersuites()) {
+ /* set preferred list of TLS 1.3 cipher suites for proxy */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
+ va_arg(param, char *));
+ }
+ else
+ return CURLE_NOT_BUILT_IN;
+ break;
+
case CURLOPT_RANDOM_FILE:
/*
* This is the path name to a file that contains random data to seed
#else
if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
return CURLE_UNSUPPORTED_PROTOCOL;
+ if(arg == CURL_HTTP_VERSION_NONE)
+ arg = CURL_HTTP_VERSION_2TLS;
#endif
data->set.httpversion = arg;
break;
* String that holds the SSL crypto engine.
*/
argptr = va_arg(param, char *);
- if(argptr && argptr[0])
- result = Curl_ssl_set_engine(data, argptr);
+ if(argptr && argptr[0]) {
+ result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr);
+ if(!result) {
+ result = Curl_ssl_set_engine(data, argptr);
+ }
+ }
break;
case CURLOPT_SSLENGINE_DEFAULT:
/*
* flag to set engine as default.
*/
+ Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL);
result = Curl_ssl_set_engine_default(data);
break;
case CURLOPT_CRLF:
break;
+ case CURLOPT_UPLOAD_BUFFERSIZE:
+ /*
+ * The application kindly asks for a differently sized upload buffer.
+ * Cap it to sensible.
+ */
+ arg = va_arg(param, long);
+
+ if(arg > UPLOADBUFFER_MAX)
+ arg = UPLOADBUFFER_MAX;
+ else if(arg < UPLOADBUFFER_MIN)
+ arg = UPLOADBUFFER_MIN;
+
+ data->set.upload_buffer_size = arg;
+ Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */
+ break;
+
case CURLOPT_NOSIGNAL:
/*
* The application asks not to set any signal() or alarm() handlers,
if(data->share->sslsession == data->state.session)
data->state.session = NULL;
+#ifdef USE_LIBPSL
+ if(data->psl == &data->share->psl)
+ data->psl = data->multi? &data->multi->psl: NULL;
+#endif
+
data->share->dirty--;
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
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);
+#ifdef USE_LIBPSL
+ if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
+ data->psl = &data->share->psl;
+#endif
+ Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}
/* check for host cache not needed,
* it will be done by curl_easy_perform */
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
break;
+ case CURLOPT_DISALLOW_USERNAME_IN_URL:
+ data->set.disallow_username_in_url =
+ (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+ case CURLOPT_DOH_URL:
+ result = Curl_setstropt(&data->set.str[STRING_DOH],
+ va_arg(param, char *));
+ data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE;
+ break;
+ case CURLOPT_UPKEEP_INTERVAL_MS:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.upkeep_interval_ms = arg;
+ break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Florin Petriuc, <petriuc.florin@gmail.com>
+ * Copyright (C) 1998 - 2018, Florin Petriuc, <petriuc.florin@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-#ifndef MIN
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#endif
/* compress 512-bits */
static int sha256_compress(struct sha256_state *md,
unsigned char *buf)
{
- unsigned long S[8], W[64], t0, t1;
- unsigned long t;
+ unsigned long S[8], W[64];
int i;
/* copy state into S */
for(i = 0; i < 8; i++) {
W[i - 16];
}
/* Compress */
-#define RND(a,b,c,d,e,f,g,h,i) \
- t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
- t1 = Sigma0(a) + Maj(a, b, c); \
- d += t0; \
+#define RND(a,b,c,d,e,f,g,h,i) \
+ unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ unsigned long t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
h = t0 + t1;
for(i = 0; i < 64; ++i) {
+ unsigned long t;
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
inlen -= block_size;
}
else {
- n = MIN(inlen, (block_size - md->curlen));
+ n = CURLMIN(inlen, (block_size - md->curlen));
memcpy(md->buf + md->curlen, in, n);
md->curlen += n;
in += n;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include <curl/curl.h>
#include "urldata.h"
#include "share.h"
+#include "psl.h"
#include "vtls/vtls.h"
#include "curl_memory.h"
res = CURLSHE_NOMEM;
break;
+ case CURL_LOCK_DATA_PSL:
+#ifndef USE_LIBPSL
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
default:
res = CURLSHE_BAD_OPTION;
}
}
#endif
+ Curl_psl_destroy(&share->psl);
+
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
free(share);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "curl_setup.h"
#include <curl/curl.h>
#include "cookie.h"
+#include "psl.h"
#include "urldata.h"
#include "conncache.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies;
#endif
+#ifdef USE_LIBPSL
+ struct PslCache psl;
+#endif
struct curl_ssl_session *sslsession;
size_t max_ssl_sessions;
item = next;
} while(next);
}
-
char *data);
#endif /* HEADER_CURL_SLIST_H */
-
static CURLcode smb_setup_connection(struct connectdata *conn);
static CURLcode smb_connect(struct connectdata *conn, bool *done);
static CURLcode smb_connection_state(struct connectdata *conn, bool *done);
+static CURLcode smb_do(struct connectdata *conn, bool *done);
static CURLcode smb_request_state(struct connectdata *conn, bool *done);
static CURLcode smb_done(struct connectdata *conn, CURLcode status,
bool premature);
const struct Curl_handler Curl_handler_smb = {
"SMB", /* scheme */
smb_setup_connection, /* setup_connection */
- ZERO_NULL, /* do_it */
+ smb_do, /* do_it */
smb_done, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
const struct Curl_handler Curl_handler_smbs = {
"SMBS", /* scheme */
smb_setup_connection, /* setup_connection */
- ZERO_NULL, /* do_it */
+ smb_do, /* do_it */
smb_done, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
/* SMB request data */
struct smb_request {
enum smb_req_state state;
- char *share;
char *path;
unsigned short tid; /* Even if we connect to the same tree as another */
unsigned short fid; /* request, the tid will be different */
static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
{
- struct smb_conn *smb = &conn->proto.smbc;
+ struct smb_conn *smbc = &conn->proto.smbc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
/* LAST */
};
- if(smb->state != newstate)
+ if(smbc->state != newstate)
infof(conn->data, "SMB conn %p state change from %s to %s\n",
- (void *)smb, names[smb->state], names[newstate]);
+ (void *)smbc, names[smbc->state], names[newstate]);
#endif
- smb->state = newstate;
+ smbc->state = newstate;
}
static void request_state(struct connectdata *conn,
req->state = newstate;
}
+/* this should setup things in the connection, not in the easy
+ handle */
static CURLcode smb_setup_connection(struct connectdata *conn)
{
struct smb_request *req;
return CURLE_LOGIN_DENIED;
/* Initialize the connection state */
- memset(smbc, 0, sizeof(*smbc));
smbc->state = SMB_CONNECTING;
smbc->recv_buf = malloc(MAX_MESSAGE_SIZE);
if(!smbc->recv_buf)
ssize_t bytes_written;
CURLcode result;
- result = Curl_write(conn, FIRSTSOCKET, conn->data->state.uploadbuffer,
+ result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf,
len, &bytes_written);
if(result)
return result;
return CURLE_OK;
result = Curl_write(conn, FIRSTSOCKET,
- conn->data->state.uploadbuffer + smbc->sent,
+ conn->data->state.ulbuf + smbc->sent,
len, &bytes_written);
if(result)
return result;
static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd,
const void *msg, size_t msg_len)
{
- smb_format_message(conn, (struct smb_header *)conn->data->state.uploadbuffer,
+ CURLcode result = Curl_get_upload_buffer(conn->data);
+ if(result)
+ return result;
+ smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf,
cmd, msg_len);
- memcpy(conn->data->state.uploadbuffer + sizeof(struct smb_header),
+ memcpy(conn->data->state.ulbuf + sizeof(struct smb_header),
msg, msg_len);
return smb_send(conn, sizeof(struct smb_header) + msg_len, 0);
static CURLcode smb_send_tree_connect(struct connectdata *conn)
{
- struct smb_request *req = conn->data->req.protop;
struct smb_tree_connect msg;
+ struct smb_conn *smbc = &conn->proto.smbc;
char *p = msg.bytes;
- size_t byte_count = strlen(conn->host.name) + strlen(req->share);
+ size_t byte_count = strlen(conn->host.name) + strlen(smbc->share);
byte_count += strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;
MSGCAT("\\\\");
MSGCAT(conn->host.name);
MSGCAT("\\");
- MSGCATNULL(req->share);
+ MSGCATNULL(smbc->share);
MSGCATNULL(SERVICENAME); /* Match any type of service */
byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count);
static CURLcode smb_send_write(struct connectdata *conn)
{
- struct smb_write *msg = (struct smb_write *)conn->data->state.uploadbuffer;
+ struct smb_write *msg;
struct smb_request *req = conn->data->req.protop;
curl_off_t offset = conn->data->req.offset;
-
curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
+ CURLcode result = Curl_get_upload_buffer(conn->data);
+ if(result)
+ return result;
+ msg = (struct smb_write *)conn->data->state.ulbuf;
+
if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
upload_size = MAX_PAYLOAD_SIZE - 1;
/* Check if there is data in the transfer buffer */
if(!smbc->send_size && 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;
+ size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ?
+ conn->data->set.upload_buffer_size :
+ smbc->upload_size;
+ conn->data->req.upload_fromhere = conn->data->state.ulbuf;
result = Curl_fillreadbuffer(conn, nread, &nread);
if(result && result != CURLE_AGAIN)
return result;
static CURLcode smb_done(struct connectdata *conn, CURLcode status,
bool premature)
{
- struct smb_request *req = conn->data->req.protop;
-
(void) premature;
-
- Curl_safefree(req->share);
Curl_safefree(conn->data->req.protop);
-
return status;
}
static CURLcode smb_disconnect(struct connectdata *conn, bool dead)
{
struct smb_conn *smbc = &conn->proto.smbc;
- struct smb_request *req = conn->data->req.protop;
-
(void) dead;
-
+ Curl_safefree(smbc->share);
Curl_safefree(smbc->domain);
Curl_safefree(smbc->recv_buf);
-
- /* smb_done is not always called, so cleanup the request */
- if(req) {
- Curl_safefree(req->share);
- }
-
return CURLE_OK;
}
static int smb_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks)
{
- struct smb_conn *smbc = &conn->proto.smbc;
-
if(!numsocks)
return GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
+}
- if(smbc->send_size || smbc->upload_size)
- return GETSOCK_WRITESOCK(0);
+static CURLcode smb_do(struct connectdata *conn, bool *done)
+{
+ struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_request *req = conn->data->req.protop;
- return GETSOCK_READSOCK(0);
+ *done = FALSE;
+ if(smbc->share) {
+ req->path = strchr(smbc->share, '\0');
+ if(req->path) {
+ req->path++;
+ return CURLE_OK;
+ }
+ }
+ return CURLE_URL_MALFORMAT;
}
static CURLcode smb_parse_url_path(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
- struct smb_request *req = data->req.protop;
+ struct smb_conn *smbc = &conn->proto.smbc;
char *path;
char *slash;
/* URL decode the path */
- result = Curl_urldecode(data, data->state.path, 0, &path, NULL, TRUE);
+ result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL, TRUE);
if(result)
return result;
/* Parse the path for the share */
- req->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path);
- if(!req->share) {
- free(path);
-
+ smbc->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path);
+ free(path);
+ if(!smbc->share)
return CURLE_OUT_OF_MEMORY;
- }
- slash = strchr(req->share, '/');
+ slash = strchr(smbc->share, '/');
if(!slash)
- slash = strchr(req->share, '\\');
+ slash = strchr(smbc->share, '\\');
/* The share must be present */
if(!slash) {
- free(path);
-
+ Curl_safefree(smbc->share);
return CURLE_URL_MALFORMAT;
}
/* Parse the path for the file path converting any forward slashes into
backslashes */
*slash++ = 0;
- req->path = slash;
+
for(; *slash; slash++) {
if(*slash == '/')
*slash = '\\';
}
-
- free(path);
-
return CURLE_OK;
}
enum smb_conn_state state;
char *user;
char *domain;
+ char *share;
unsigned char challenge[8];
unsigned int session_key;
unsigned short uid;
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *line = data->state.buffer;
size_t len = strlen(line);
- size_t wordlen;
(void)instate; /* no use for this yet */
/* Loop through the data line */
for(;;) {
size_t llen;
+ size_t wordlen;
unsigned int mechbit;
while(len &&
static CURLcode smtp_setup_connection(struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
CURLcode result;
/* Clear the TLS upgraded flag */
if(result)
return result;
- data->state.path++; /* don't include the initial slash */
-
return CURLE_OK;
}
/* The SMTP struct is already initialised in smtp_connect() */
struct Curl_easy *data = conn->data;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- const char *path = data->state.path;
+ const char *path = &data->state.up.path[1]; /* skip leading path */
char localhost[HOSTNAME_MAX + 1];
/* Calculate the path if necessary */
if(!scratch || data->set.crlf) {
oldscratch = scratch;
- scratch = newscratch = malloc(2 * data->set.buffer_size);
+ scratch = newscratch = malloc(2 * data->set.upload_buffer_size);
if(!newscratch) {
failf(data, "Failed to alloc scratch buffer!");
return CURLE_OUT_OF_MEMORY;
}
}
+ DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread);
/* Have we already sent part of the EOB? */
eob_sent = smtp->eob;
};
#endif /* HEADER_CURL_SOCKADDR_H */
-
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
ssize_t nread;
ssize_t allread = 0;
int result;
- timediff_t timeleft;
*n = 0;
for(;;) {
- timeleft = Curl_timeleft(conn->data, NULL, TRUE);
+ timediff_t timeleft = Curl_timeleft(conn->data, NULL, TRUE);
if(timeleft < 0) {
/* we already got the timeout */
result = CURLE_OPERATION_TIMEDOUT;
* destination server.
*
* Reference :
-* http://socks.permeo.com/protocol/socks4.protocol
+* https://www.openssh.com/txt/socks4.protocol
*
* Note :
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
#define SOCKS4REQLEN 262
unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
id */
- int result;
CURLcode code;
curl_socket_t sock = conn->sock[sockindex];
struct Curl_easy *data = conn->data;
* Make connection
*/
{
+ int result;
ssize_t actualread;
ssize_t written;
ssize_t hostnamelen = 0;
- int packetsize = 9 +
- (int)strlen((char *)socksreq + 8); /* size including NUL */
+ ssize_t packetsize = 9 +
+ strlen((char *)socksreq + 8); /* size including NUL */
/* If SOCKS4a, set special invalid IP address 0.0.0.x */
if(protocol4a) {
if(dns)
hp = dns->addr;
if(hp) {
- int i;
char buf[64];
Curl_printable_address(hp, buf, sizeof(buf));
if(hp->ai_family == AF_INET) {
+ int i;
struct sockaddr_in *saddr_in;
socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
+ int i;
struct sockaddr_in6 *saddr_in6;
socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
}
#endif /* CURL_DISABLE_PROXY */
-
#endif /* CURL_DISABLE_PROXY */
#endif /* HEADER_CURL_SOCKS_H */
-
struct Curl_tree *t)
{
struct Curl_tree N, *l, *r, *y;
- long comp;
if(t == NULL)
return t;
l = r = &N;
for(;;) {
- comp = compare(i, t->key);
+ long comp = compare(i, t->key);
if(comp < 0) {
if(t->smaller == NULL)
break;
return 0;
}
-
return CURLE_SSH;
}
+#ifndef DEBUGBUILD
+#define state(x,y) mystate(x,y)
+#else
+#define state(x,y) mystate(x,y, __LINE__)
+#endif
+
/*
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void state(struct connectdata *conn, sshstate nowstate)
+static void mystate(struct connectdata *conn, sshstate nowstate
+#ifdef DEBUGBUILD
+ , int lineno
+#endif
+ )
{
struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(sshc->state != nowstate) {
- infof(conn->data, "SSH %p state change from %s to %s\n",
- (void *) sshc, names[sshc->state], names[nowstate]);
+ infof(conn->data, "SSH %p state change from %s to %s (line %d)\n",
+ (void *) sshc, names[sshc->state], names[nowstate],
+ lineno);
}
#endif
}
#define MOVE_TO_ERROR_STATE(_r) { \
- state(conn, SSH_SESSION_FREE); \
+ state(conn, SSH_SESSION_DISCONNECT); \
sshc->actualcode = _r; \
rc = SSH_ERROR; \
break; \
if(rc < 0)
return SSH_ERROR;
- /* fallthrough */
+ /* FALLTHROUGH */
case 1:
sshc->kbd_state = 1;
ssh_set_blocking(sshc->ssh_session, 0);
state(conn, SSH_S_STARTUP);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_S_STARTUP:
rc = ssh_connect(sshc->ssh_session);
state(conn, SSH_HOSTKEY);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_HOSTKEY:
rc = myssh_is_known(conn);
}
state(conn, SSH_AUTHLIST);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_AUTHLIST:{
sshc->authed = FALSE;
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
state(conn, SSH_AUTH_PKEY_INIT);
+ infof(data, "Authentication using SSH public key file\n");
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
state(conn, SSH_AUTH_GSSAPI);
if(rc != SSH_OK) {
failf(data, "Could not load private key file %s",
data->set.str[STRING_SSH_PRIVATE_KEY]);
+ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
break;
}
}
else {
- infof(data, "Authentication using SSH public key file\n");
-
rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
data->set.ssl.key_passwd);
if(rc == SSH_AUTH_AGAIN) {
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
}
state(conn, SSH_AUTH_PASS);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_AUTH_PASS:
rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
break;
}
state(conn, SSH_SFTP_REALPATH);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SFTP_REALPATH:
/*
* Get the "home" directory
if(sshc->readdir_attrs) {
sshc->readdir_filename = sshc->readdir_attrs->name;
sshc->readdir_longentry = sshc->readdir_attrs->longname;
- sshc->readdir_len = (int)strlen(sshc->readdir_filename);
+ sshc->readdir_len = strlen(sshc->readdir_filename);
if(data->set.ftp_list_only) {
char *tmpLine;
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT,
(char *)sshc->readdir_filename,
- sshc->readdir_len, conn);
+ sshc->readdir_len);
}
}
else {
- sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+ sshc->readdir_currLen = strlen(sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
if(sshc->readdir_filename == NULL)
sshc->readdir_len = 0;
else
- sshc->readdir_len = (int)strlen(sshc->readdir_tmp);
+ sshc->readdir_len = strlen(sshc->readdir_tmp);
sshc->readdir_longentry = NULL;
sshc->readdir_filename = sshc->readdir_tmp;
}
else {
- sshc->readdir_len = (int)strlen(sshc->readdir_link_attrs->name);
+ sshc->readdir_len = strlen(sshc->readdir_link_attrs->name);
sshc->readdir_filename = sshc->readdir_link_attrs->name;
sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
}
sshc->readdir_longentry = NULL;
state(conn, SSH_SFTP_READDIR_BOTTOM);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SFTP_READDIR_BOTTOM:
sshc->readdir_currLen += snprintf(sshc->readdir_line +
sshc->readdir_currLen,
/* output debug output if that is requested */
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen, conn);
+ sshc->readdir_currLen);
}
data->req.bytecount += sshc->readdir_currLen;
}
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
state(conn, SSH_SCP_DOWNLOAD);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SCP_DOWNLOAD:{
curl_off_t bytecount;
ssh_set_blocking(sshc->ssh_session, 0);
state(conn, SSH_SESSION_DISCONNECT);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SESSION_DISCONNECT:
/* during weird times when we've been prematurely aborted, the channel
conn->data->state.most_recent_ftp_entrypath = NULL;
state(conn, SSH_SESSION_FREE);
- /* fall through */
+ /* FALLTHROUGH */
case SSH_SESSION_FREE:
if(sshc->ssh_session) {
ssh_free(sshc->ssh_session);
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!status && !premature && conn->data->set.postquote) {
+ if(!status && !premature && conn->data->set.postquote &&
+ !conn->bits.retry) {
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
state(conn, SSH_SFTP_CLOSE);
}
return -1;
}
- /* fall-through */
+ /* FALLTHROUGH */
case 1:
conn->proto.sshc.sftp_recv_state = 1;
return;
}
if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4, conn);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
}
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
libssh2_session_set_blocking(sshc->ssh_session, 0);
state(conn, SSH_S_STARTUP);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_S_STARTUP:
rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
state(conn, SSH_HOSTKEY);
- /* fall-through */
+ /* FALLTHROUGH */
case SSH_HOSTKEY:
/*
* Before we authenticate we should check the hostkey's fingerprint
break;
}
if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
}
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
break;
case SSH_SFTP_READDIR:
- sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
- sshc->readdir_filename,
- PATH_MAX,
- sshc->readdir_longentry,
- PATH_MAX,
- &sshc->readdir_attrs);
- if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
+ rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
+ sshc->readdir_filename,
+ PATH_MAX,
+ sshc->readdir_longentry,
+ PATH_MAX,
+ &sshc->readdir_attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- if(sshc->readdir_len > 0) {
+ if(rc > 0) {
+ sshc->readdir_len = (size_t) rc;
sshc->readdir_filename[sshc->readdir_len] = '\0';
if(data->set.ftp_list_only) {
/* output debug output if that is requested */
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
- sshc->readdir_len, conn);
+ sshc->readdir_len);
}
}
else {
- sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+ sshc->readdir_currLen = strlen(sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
break;
}
}
- else if(sshc->readdir_len == 0) {
+ else if(rc == 0) {
Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry);
state(conn, SSH_SFTP_READDIR_DONE);
break;
}
- else if(sshc->readdir_len <= 0) {
+ else if(rc < 0) {
err = sftp_libssh2_last_error(sshc->sftp_session);
result = sftp_libssh2_error_to_CURLE(err);
sshc->actualcode = result?result:CURLE_SSH;
break;
case SSH_SFTP_READDIR_LINK:
- sshc->readdir_len =
+ rc =
libssh2_sftp_symlink_ex(sshc->sftp_session,
sshc->readdir_linkPath,
curlx_uztoui(strlen(sshc->readdir_linkPath)),
sshc->readdir_filename,
PATH_MAX, LIBSSH2_SFTP_READLINK);
- if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
+ sshc->readdir_len = (size_t) rc;
Curl_safefree(sshc->readdir_linkPath);
/* get room for the filename and extra output */
/* output debug output if that is requested */
if(data->set.verbose) {
Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen, conn);
+ sshc->readdir_currLen);
}
data->req.bytecount += sshc->readdir_currLen;
}
int rc;
ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
if(!ssh->kh) {
- /* eeek. TODO: free the ssh_session! */
+ libssh2_session_free(ssh->ssh_session);
return CURLE_FAILED_INIT;
}
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!status && !premature && conn->data->set.postquote) {
+ if(!status && !premature && conn->data->set.postquote &&
+ !conn->bits.retry) {
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
state(conn, SSH_SFTP_CLOSE);
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
quote command fails) */
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */
- int readdir_len, readdir_totalLen, readdir_currLen;
+ size_t readdir_len, readdir_totalLen, readdir_currLen;
char *readdir_line;
char *readdir_linkPath;
/* end of READDIR stuff */
#define checkprefix(a,b) curl_strnequal(a,b,strlen(a))
void Curl_strntoupper(char *dest, const char *src, size_t n);
-char Curl_raw_toupper(char in);
#endif /* HEADER_CURL_STRCASE_H */
* 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.
+ * fails. If 'size' is non-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
case CURLE_TELNET_OPTION_SYNTAX :
return "Malformed telnet option";
- case CURLE_PEER_FAILED_VERIFICATION:
- return "SSL peer certificate or SSH remote key was not OK";
-
case CURLE_GOT_NOTHING:
return "Server returned nothing (no headers, no data)";
case CURLE_SSL_CIPHER:
return "Couldn't use specified SSL cipher";
- case CURLE_SSL_CACERT:
- return "Peer certificate cannot be authenticated with given CA "
- "certificates";
+ case CURLE_PEER_FAILED_VERIFICATION:
+ return "SSL peer certificate or SSH remote key was not OK";
case CURLE_SSL_CACERT_BADFILE:
return "Problem with the SSL CA cert (path? access rights?)";
case CURLE_OBSOLETE44:
case CURLE_OBSOLETE46:
case CURLE_OBSOLETE50:
+ case CURLE_OBSOLETE51:
case CURLE_OBSOLETE57:
case CURL_LAST:
break;
#include <curl/curl.h>
#include "system_win32.h"
+#include "warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
break;
case VERSION_LESS_THAN_EQUAL:
- if(osver.dwMajorVersion <= majorVersion &&
- osver.dwMinorVersion <= minorVersion)
+ if(osver.dwMajorVersion < majorVersion ||
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion <= minorVersion))
matched = TRUE;
break;
break;
case VERSION_GREATER_THAN_EQUAL:
- if(osver.dwMajorVersion >= majorVersion &&
- osver.dwMinorVersion >= minorVersion)
+ if(osver.dwMajorVersion > majorVersion ||
+ (osver.dwMajorVersion == majorVersion &&
+ osver.dwMinorVersion >= minorVersion))
matched = TRUE;
break;
/* Attempt to find LoadLibraryEx() which is only available on Windows 2000
and above */
- pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX);
+ pLoadLibraryEx =
+ CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN,
+ (GetProcAddress(hKernel32, LOADLIBARYEX)));
/* Detect if there's already a path in the filename and load the library if
there is. Note: Both back slashes and forward slashes have been supported
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#include "connect.h"
#include "progress.h"
#include "system_win32.h"
-
-#define TELOPTS
-#define TELCMDS
-
#include "arpa_telnet.h"
#include "select.h"
#include "strcase.h"
x->subend = x->subpointer; \
CURL_SB_CLEAR(x); \
} WHILE_FALSE
-#define CURL_SB_ACCUM(x,c) \
- do { \
- if(x->subpointer < (x->subbuffer + sizeof x->subbuffer)) \
- *x->subpointer++ = (c); \
+#define CURL_SB_ACCUM(x,c) \
+ do { \
+ if(x->subpointer < (x->subbuffer + sizeof(x->subbuffer))) \
+ *x->subpointer++ = (c); \
} WHILE_FALSE
#define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
#endif
#ifdef USE_WINSOCK
+typedef WSAEVENT (WINAPI *WSOCK2_EVENT)(void);
typedef FARPROC WSOCK2_FUNC;
static CURLcode check_wsock2(struct Curl_easy *data);
#endif
static void negotiate(struct connectdata *);
static void send_negotiation(struct connectdata *, int cmd, int option);
-static void set_local_option(struct connectdata *, int cmd, int option);
-static void set_remote_option(struct connectdata *, int cmd, int option);
+static void set_local_option(struct connectdata *conn,
+ int option, int newstate);
+static void set_remote_option(struct connectdata *conn,
+ int option, int newstate);
static void printsub(struct Curl_easy *data,
int direction, unsigned char *pointer,
static void printoption(struct Curl_easy *data,
const char *direction, int cmd, int option)
{
- const char *fmt;
- const char *opt;
-
if(data->set.verbose) {
if(cmd == CURL_IAC) {
if(CURL_TELCMD_OK(option))
infof(data, "%s IAC %d\n", direction, option);
}
else {
- fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
- (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
+ const char *fmt = (cmd == CURL_WILL) ? "WILL" :
+ (cmd == CURL_WONT) ? "WONT" :
+ (cmd == CURL_DO) ? "DO" :
+ (cmd == CURL_DONT) ? "DONT" : 0;
if(fmt) {
+ const char *opt;
if(CURL_TELOPT_OK(option))
opt = CURL_TELOPT(option);
else if(option == CURL_TELOPT_EXOPL)
{
unsigned char buf[3];
ssize_t bytes_written;
- int err;
struct Curl_easy *data = conn->data;
buf[0] = CURL_IAC;
bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
if(bytes_written < 0) {
- err = SOCKERRNO;
+ int err = SOCKERRNO;
failf(data,"Sending data failed (%d)",err);
}
unsigned char *pointer, /* where suboption data is */
size_t length) /* length of suboption data */
{
- unsigned int i = 0;
-
if(data->set.verbose) {
+ unsigned int i = 0;
if(direction) {
infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
if(length >= 3) {
switch(pointer[0]) {
case CURL_TELOPT_NAWS:
if(length > 4)
- infof(data, "Width: %hu ; Height: %hu", (pointer[1]<<8) | pointer[2],
+ infof(data, "Width: %d ; Height: %d", (pointer[1]<<8) | pointer[2],
(pointer[3]<<8) | pointer[4]);
break;
default:
unsigned char temp[2048];
ssize_t bytes_written;
size_t len;
- size_t tmplen;
int err;
char varname[128] = "";
char varval[128] = "";
len = 4;
for(v = tn->telnet_vars; v; v = v->next) {
- tmplen = (strlen(v->data) + 1);
+ size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
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 endian processors */
+ /* We must deal either with little or big endian processors */
/* Window size must be sent according to the 'network order' */
x = htons(tn->subopt_wsx);
y = htons(tn->subopt_wsy);
static CURLcode send_telnet_data(struct connectdata *conn,
char *buffer, ssize_t nread)
{
- ssize_t escapes, i, j, outlen;
+ ssize_t escapes, i, outlen;
unsigned char *outbuf = NULL;
CURLcode result = CURLE_OK;
ssize_t bytes_written, total_written;
if(outlen == nread)
outbuf = (unsigned char *)buffer;
else {
+ ssize_t j;
outbuf = malloc(nread + escapes + 1);
if(!outbuf)
return CURLE_OUT_OF_MEMORY;
#ifdef USE_WINSOCK
HMODULE wsock2;
WSOCK2_FUNC close_event_func;
- WSOCK2_FUNC create_event_func;
+ WSOCK2_EVENT create_event_func;
WSOCK2_FUNC event_select_func;
WSOCK2_FUNC enum_netevents_func;
WSAEVENT event_handle;
HANDLE objs[2];
DWORD obj_count;
DWORD wait_timeout;
- DWORD waitret;
DWORD readfile_read;
int err;
#else
}
/* Grab a pointer to WSACreateEvent */
- create_event_func = GetProcAddress(wsock2, "WSACreateEvent");
+ create_event_func =
+ CURLX_FUNCTION_CAST(WSOCK2_EVENT,
+ (GetProcAddress(wsock2, "WSACreateEvent")));
if(create_event_func == NULL) {
failf(data, "failed to find WSACreateEvent function (%u)", GetLastError());
FreeLibrary(wsock2);
/* 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);
+ DWORD waitret = WaitForMultipleObjects(obj_count, objs,
+ FALSE, wait_timeout);
switch(waitret) {
case WAIT_TIMEOUT:
{
case 0: /* timeout */
pfd[0].revents = 0;
pfd[1].revents = 0;
- /* fall through */
+ /* FALLTHROUGH */
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
#endif
#endif /* HEADER_CURL_TELNET_H */
-
ssize_t senddata;
const char *mode = "octet";
char *filename;
- char buf[64];
struct Curl_easy *data = state->conn->data;
CURLcode result = CURLE_OK;
/* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path
string. */
- result = Curl_urldecode(data, &state->conn->data->state.path[1], 0,
+ result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
&filename, NULL, FALSE);
if(result)
return result;
/* optional addition of TFTP options */
if(!data->set.tftp_no_options) {
+ char buf[64];
/* add tsize option */
if(data->set.upload && (data->state.infilesize != -1))
snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
{
struct Curl_easy *data = state->conn->data;
ssize_t sbytes;
- int rblock;
CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
- int cb; /* Bytes currently read */
+ size_t cb; /* Bytes currently read */
switch(event) {
case TFTP_EVENT_OACK:
if(event == TFTP_EVENT_ACK) {
/* Ack the packet */
- rblock = getrpacketblock(&state->rpacket);
+ int rblock = getrpacketblock(&state->rpacket);
if(rblock != state->block &&
/* There's a bug in tftpd-hpa that causes it to send us an ack for
state->retries = 0;
setpacketevent(&state->spacket, TFTP_EVENT_DATA);
setpacketblock(&state->spacket, state->block);
- if(state->block > 1 && state->sbytes < (int)state->blksize) {
+ if(state->block > 1 && state->sbytes < state->blksize) {
state->state = TFTP_STATE_FIN;
return CURLE_OK;
}
&cb);
if(result)
return result;
- state->sbytes += cb;
+ state->sbytes += (int)cb;
state->conn->data->req.upload_fromhere += cb;
} while(state->sbytes < state->blksize && cb != 0);
static CURLcode tftp_connect(struct connectdata *conn, bool *done)
{
tftp_state_data_t *state;
- int blksize, rc;
+ int blksize;
blksize = TFTP_BLKSIZE_DEFAULT;
* assume uses the same IP version and thus hopefully this works for both
* IPv4 and IPv6...
*/
- rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
- conn->ip_addr->ai_addrlen);
+ int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
+ conn->ip_addr->ai_addrlen);
if(rc) {
failf(conn->data, "bind() failed; %s",
Curl_strerror(conn, SOCKERRNO));
case TFTP_EVENT_ERROR:
{
unsigned short error = getrpacketblock(&state->rpacket);
+ char *str = (char *)state->rpacket.data + 4;
+ size_t strn = state->rbytes - 4;
state->error = (tftp_error_t)error;
- infof(data, "%s\n", (const char *)state->rpacket.data + 4);
+ if(Curl_strnlen(str, strn) < strn)
+ infof(data, "TFTP error: %s\n", str);
break;
}
case TFTP_EVENT_ACK:
**********************************************************/
static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
{
- int rc;
tftp_event_t event;
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
}
else {
/* no timeouts to handle, check our socket */
- rc = SOCKET_READABLE(state->sockfd, 0);
+ int rc = SOCKET_READABLE(state->sockfd, 0);
if(rc == -1) {
/* bail out */
{
struct Curl_easy *data = conn->data;
char *type;
- char command;
conn->socktype = SOCK_DGRAM; /* UDP datagram based */
/* TFTP URLs support an extension like ";mode=<typecode>" that
* we'll try to get now! */
- type = strstr(data->state.path, ";mode=");
+ type = strstr(data->state.up.path, ";mode=");
if(!type)
type = strstr(conn->host.rawalloc, ";mode=");
if(type) {
+ char command;
*type = 0; /* it was in the middle of the hostname */
command = Curl_raw_toupper(type[6]);
#endif
#endif /* HEADER_CURL_TFTP_H */
-
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
*/
struct curltime now;
#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
- (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+ (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
+ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
DWORD milliseconds = GetTickCount();
now.tv_sec = milliseconds / 1000;
now.tv_usec = (milliseconds % 1000) * 1000;
struct timeval now;
struct curltime cnow;
struct timespec tsnow;
- if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
+
+ /*
+ ** clock_gettime() may be defined by Apple's SDK as weak symbol thus
+ ** code compiles but fails during run-time if clock_gettime() is
+ ** called on unsupported OS version.
+ */
+#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
+ bool have_clock_gettime = FALSE;
+ if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *))
+ have_clock_gettime = TRUE;
+#endif
+
+ if(
+#if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
+ have_clock_gettime &&
+#endif
+ (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) {
cnow.tv_sec = tsnow.tv_sec;
cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000);
}
#include "http2.h"
#include "mime.h"
#include "strcase.h"
+#include "urlapi-int.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
}
#endif
+CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
+{
+ if(!data->state.ulbuf) {
+ data->state.ulbuf = malloc(data->set.upload_buffer_size);
+ if(!data->state.ulbuf)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
/*
* This function will call the read callback to fill our buffer with data
* to upload.
*/
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+ size_t *nreadp)
{
struct Curl_easy *data = conn->data;
- size_t buffersize = (size_t)bytes;
- int nread;
+ size_t buffersize = bytes;
+ size_t nread;
#ifdef CURL_DOES_CONVERSIONS
bool sending_http_headers = FALSE;
data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
}
- /* this function returns a size_t, so we typecast to int to prevent warnings
- with picky compilers */
Curl_set_in_callback(data, true);
- nread = (int)data->state.fread_func(data->req.upload_fromhere, 1,
- buffersize, data->state.in);
+ nread = data->state.fread_func(data->req.upload_fromhere, 1,
+ buffersize, data->state.in);
Curl_set_in_callback(data, false);
if(nread == CURL_READFUNC_ABORT) {
return CURLE_OK; /* nothing was read */
}
- else if((size_t)nread > buffersize) {
+ else if(nread > buffersize) {
/* the read function returned a too large value */
*nreadp = 0;
failf(data, "read function returned funny value");
#ifdef CURL_DOES_CONVERSIONS
{
CURLcode result;
- int length;
+ size_t length;
if(data->set.prefer_ascii)
/* translate the protocol and data */
length = nread;
else
/* just translate the protocol portion */
- length = (int)strlen(hexbuffer);
+ length = strlen(hexbuffer);
result = Curl_convert_to_network(data, data->req.upload_fromhere,
length);
/* Curl_convert_to_network calls failf if unsuccessful */
infof(data, "Signaling end of chunked upload via terminating chunk.\n");
}
- nread += (int)strlen(endofline_native); /* for the added end of line */
+ nread += strlen(endofline_native); /* for the added end of line */
}
#ifdef CURL_DOES_CONVERSIONS
else if((data->set.prefer_ascii) && (!sending_http_headers)) {
return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
#if defined(USE_NGHTTP2)
Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
- /* For HTTP/2, we may read up everything including responde body
+ /* For HTTP/2, we may read up everything including response body
with header fields in Curl_http_readwrite_headers. If no
content-length is provided, curl waits for the connection
close, which we emulate it using conn->proto.httpc.closed =
CURLcode result = CURLE_OK;
ssize_t nread; /* number of bytes read */
size_t excess = 0; /* excess bytes read */
- bool is_empty_data = FALSE;
bool readmore = FALSE; /* used by RTP to signal for more data */
int maxloops = 100;
/* This is where we loop until we have read everything there is to
read or we get a CURLE_AGAIN */
do {
+ bool is_empty_data = FALSE;
size_t buffersize = data->set.buffer_size;
size_t bytestoread = buffersize;
infof(data,
"Rewinding stream by : %zd"
" bytes on url %s (zero-length body)\n",
- nread, data->state.path);
+ nread, data->state.up.path);
read_rewind(conn, (size_t)nread);
}
else {
"Excess found in a non pipelined read:"
" excess = %zd"
" url = %s (zero-length body)\n",
- nread, data->state.path);
+ nread, data->state.up.path);
}
}
if(data->set.verbose) {
if(k->badheader) {
Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
- (size_t)k->hbuflen, conn);
+ (size_t)k->hbuflen);
if(k->badheader == HEADER_PARTHEADER)
Curl_debug(data, CURLINFO_DATA_IN,
- k->str, (size_t)nread, conn);
+ k->str, (size_t)nread);
}
else
Curl_debug(data, CURLINFO_DATA_IN,
- k->str, (size_t)nread, conn);
+ k->str, (size_t)nread);
}
#ifndef CURL_DISABLE_HTTP
" bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
", maxdownload = %" CURL_FORMAT_CURL_OFF_T
", bytecount = %" CURL_FORMAT_CURL_OFF_T ", nread = %zd)\n",
- excess, data->state.path,
+ excess, data->state.up.path,
k->size, k->maxdownload, k->bytecount, nread);
read_rewind(conn, excess);
}
nread);
}
}
- else
+ else if(!k->ignorebody)
result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
}
k->badheader = HEADER_NORMAL; /* taken care of now */
return CURLE_OK;
}
+#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
+#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
+#endif
+
+static void win_update_buffer_size(curl_socket_t sockfd)
+{
+ int result;
+ ULONG ideal;
+ DWORD ideallen;
+ result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
+ &ideal, sizeof(ideal), &ideallen, 0, 0);
+ if(result == 0) {
+ setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
+ (const char *)&ideal, sizeof(ideal));
+ }
+}
+#else
+#define win_update_buffer_size(x)
+#endif
/*
* Send data to upload to the server, when the socket is writable.
/* only read more data if there's no upload data already
present in the upload buffer */
if(0 == k->upload_present) {
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
/* init the "upload from here" pointer */
- k->upload_fromhere = data->state.uploadbuffer;
+ k->upload_fromhere = data->state.ulbuf;
if(!k->upload_done) {
/* HTTP pollution, this should be written nicer to become more
protocol agnostic. */
- int fillcount;
+ size_t fillcount;
struct HTTP *http = k->protop;
if((k->exp100 == EXP100_SENDING_REQUEST) &&
sending_http_headers = FALSE;
}
- result = Curl_fillreadbuffer(conn, UPLOAD_BUFSIZE, &fillcount);
+ result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size,
+ &fillcount);
if(result)
return result;
- nread = (ssize_t)fillcount;
+ nread = fillcount;
}
else
nread = 0; /* we're done uploading/reading */
(data->set.crlf))) {
/* Do we need to allocate a scratch buffer? */
if(!data->state.scratch) {
- data->state.scratch = malloc(2 * data->set.buffer_size);
+ data->state.scratch = malloc(2 * data->set.upload_buffer_size);
if(!data->state.scratch) {
failf(data, "Failed to alloc scratch buffer!");
k->upload_fromhere, /* buffer pointer */
k->upload_present, /* buffer size */
&bytes_written); /* actually sent */
-
if(result)
return result;
+ win_update_buffer_size(conn->writesockfd);
+
if(data->set.verbose)
/* show the data before we change the pointer upload_fromhere */
Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
- (size_t)bytes_written, conn);
+ (size_t)bytes_written);
k->writebytecount += bytes_written;
}
else {
/* we've uploaded that buffer now */
- k->upload_fromhere = data->state.uploadbuffer;
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+ k->upload_fromhere = data->state.ulbuf;
k->upload_present = 0; /* no more bytes left */
if(k->upload_done) {
return CURLE_OK;
}
-#ifndef CURL_DISABLE_HTTP
-/*
- * Find the separator at the end of the host name, or the '?' in cases like
- * http://www.url.com?id=2380
- */
-static const char *find_host_sep(const char *url)
-{
- const char *sep;
- const char *query;
-
- /* Find the start of the hostname */
- sep = strstr(url, "//");
- if(!sep)
- sep = url;
- else
- sep += 2;
-
- query = strchr(sep, '?');
- sep = strchr(sep, '/');
-
- if(!sep)
- sep = url + strlen(url);
-
- if(!query)
- query = url + strlen(url);
-
- return sep < query ? sep : query;
-}
-
-/*
- * Decide in an encoding-independent manner whether a character in an
- * URL must be escaped. The same criterion must be used in strlen_url()
- * and strcpy_url().
- */
-static bool urlchar_needs_escaping(int c)
-{
- return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
-}
-
-/*
- * strlen_url() returns the length of the given URL if the spaces within the
- * URL were properly URL encoded.
- * URL encoding should be skipped for host names, otherwise IDN resolution
- * will fail.
- */
-static size_t strlen_url(const char *url, bool relative)
-{
- const unsigned char *ptr;
- size_t newlen = 0;
- bool left = TRUE; /* left side of the ? */
- const unsigned char *host_sep = (const unsigned char *) url;
-
- if(!relative)
- host_sep = (const unsigned char *) find_host_sep(url);
-
- for(ptr = (unsigned char *)url; *ptr; ptr++) {
-
- if(ptr < host_sep) {
- ++newlen;
- continue;
- }
-
- switch(*ptr) {
- case '?':
- left = FALSE;
- /* fall through */
- default:
- if(urlchar_needs_escaping(*ptr))
- newlen += 2;
- newlen++;
- break;
- case ' ':
- if(left)
- newlen += 3;
- else
- newlen++;
- break;
- }
- }
- return newlen;
-}
-
-/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
- * the source URL accordingly.
- * URL encoding should be skipped for host names, otherwise IDN resolution
- * will fail.
- */
-static void strcpy_url(char *output, const char *url, bool relative)
-{
- /* we must add this with whitespace-replacing */
- bool left = TRUE;
- const unsigned char *iptr;
- char *optr = output;
- const unsigned char *host_sep = (const unsigned char *) url;
-
- if(!relative)
- host_sep = (const unsigned char *) find_host_sep(url);
-
- for(iptr = (unsigned char *)url; /* read from here */
- *iptr; /* until zero byte */
- iptr++) {
-
- if(iptr < host_sep) {
- *optr++ = *iptr;
- continue;
- }
-
- switch(*iptr) {
- case '?':
- left = FALSE;
- /* fall through */
- default:
- if(urlchar_needs_escaping(*iptr)) {
- snprintf(optr, 4, "%%%02x", *iptr);
- optr += 3;
- }
- else
- *optr++=*iptr;
- break;
- case ' ':
- if(left) {
- *optr++='%'; /* add a '%' */
- *optr++='2'; /* add a '2' */
- *optr++='0'; /* add a '0' */
- }
- else
- *optr++='+'; /* add a '+' here */
- break;
- }
- }
- *optr = 0; /* zero terminate output buffer */
-
-}
-
-/*
- * Returns true if the given URL is absolute (as opposed to relative)
- */
-static bool is_absolute_url(const char *url)
-{
- char prot[16]; /* URL protocol string storage */
- char letter; /* used for a silly sscanf */
-
- return (2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter)) ? TRUE : FALSE;
-}
-
-/*
- * Concatenate a relative URL to a base URL making it absolute.
- * URL-encodes any spaces.
- * The returned pointer must be freed by the caller unless NULL
- * (returns NULL on out of memory).
- */
-static char *concat_url(const char *base, const char *relurl)
-{
- /***
- TRY to append this new path to the old URL
- to the right of the host part. Oh crap, this is doomed to cause
- problems in the future...
- */
- char *newest;
- char *protsep;
- char *pathsep;
- size_t newlen;
- bool host_changed = FALSE;
-
- const char *useurl = relurl;
- size_t urllen;
-
- /* we must make our own copy of the URL to play with, as it may
- point to read-only data */
- char *url_clone = strdup(base);
-
- if(!url_clone)
- return NULL; /* skip out of this NOW */
-
- /* protsep points to the start of the host name */
- protsep = strstr(url_clone, "//");
- if(!protsep)
- protsep = url_clone;
- else
- protsep += 2; /* pass the slashes */
-
- if('/' != relurl[0]) {
- int level = 0;
-
- /* First we need to find out if there's a ?-letter in the URL,
- and cut it and the right-side of that off */
- pathsep = strchr(protsep, '?');
- if(pathsep)
- *pathsep = 0;
-
- /* we have a relative path to append to the last slash if there's one
- available, or if the new URL is just a query string (starts with a
- '?') we append the new one at the end of the entire currently worked
- out URL */
- if(useurl[0] != '?') {
- pathsep = strrchr(protsep, '/');
- if(pathsep)
- *pathsep = 0;
- }
-
- /* Check if there's any slash after the host name, and if so, remember
- that position instead */
- pathsep = strchr(protsep, '/');
- if(pathsep)
- protsep = pathsep + 1;
- else
- protsep = NULL;
-
- /* now deal with one "./" or any amount of "../" in the newurl
- and act accordingly */
-
- if((useurl[0] == '.') && (useurl[1] == '/'))
- useurl += 2; /* just skip the "./" */
-
- while((useurl[0] == '.') &&
- (useurl[1] == '.') &&
- (useurl[2] == '/')) {
- level++;
- useurl += 3; /* pass the "../" */
- }
-
- if(protsep) {
- while(level--) {
- /* cut off one more level from the right of the original URL */
- pathsep = strrchr(protsep, '/');
- if(pathsep)
- *pathsep = 0;
- else {
- *protsep = 0;
- break;
- }
- }
- }
- }
- else {
- /* We got a new absolute path for this server */
-
- if((relurl[0] == '/') && (relurl[1] == '/')) {
- /* the new URL starts with //, just keep the protocol part from the
- original one */
- *protsep = 0;
- useurl = &relurl[2]; /* we keep the slashes from the original, so we
- skip the new ones */
- host_changed = TRUE;
- }
- else {
- /* cut off the original URL from the first slash, or deal with URLs
- without slash */
- pathsep = strchr(protsep, '/');
- if(pathsep) {
- /* When people use badly formatted URLs, such as
- "http://www.url.com?dir=/home/daniel" we must not use the first
- slash, if there's a ?-letter before it! */
- char *sep = strchr(protsep, '?');
- if(sep && (sep < pathsep))
- pathsep = sep;
- *pathsep = 0;
- }
- else {
- /* There was no slash. Now, since we might be operating on a badly
- formatted URL, such as "http://www.url.com?id=2380" which doesn't
- use a slash separator as it is supposed to, we need to check for a
- ?-letter as well! */
- pathsep = strchr(protsep, '?');
- if(pathsep)
- *pathsep = 0;
- }
- }
- }
-
- /* If the new part contains a space, this is a mighty stupid redirect
- but we still make an effort to do "right". To the left of a '?'
- letter we replace each space with %20 while it is replaced with '+'
- on the right side of the '?' letter.
- */
- newlen = strlen_url(useurl, !host_changed);
-
- urllen = strlen(url_clone);
-
- newest = malloc(urllen + 1 + /* possible slash */
- newlen + 1 /* zero byte */);
-
- if(!newest) {
- free(url_clone); /* don't leak this */
- return NULL;
- }
-
- /* copy over the root url part */
- memcpy(newest, url_clone, urllen);
-
- /* check if we need to append a slash */
- if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
- ;
- else
- newest[urllen++]='/';
-
- /* then append the new piece on the right side */
- strcpy_url(&newest[urllen], useurl, !host_changed);
-
- free(url_clone);
-
- return newest;
-}
-#endif /* CURL_DISABLE_HTTP */
-
/*
* Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
* as given by the remote server and set up the new URL to request.
+ *
+ * This function DOES NOT FREE the given url.
*/
CURLcode Curl_follow(struct Curl_easy *data,
char *newurl, /* the Location: string */
/* Location: redirect */
bool disallowport = FALSE;
bool reachedmax = FALSE;
+ CURLUcode uc;
if(type == FOLLOW_REDIR) {
if((data->set.maxredirs != -1) &&
}
}
- if(!is_absolute_url(newurl)) {
- /***
- *DANG* this is an RFC 2068 violation. The URL is supposed
- to be absolute and this doesn't seem to be that!
- */
- char *absolute = concat_url(data->change.url, newurl);
- if(!absolute)
- return CURLE_OUT_OF_MEMORY;
- newurl = absolute;
- }
- else {
- /* The new URL MAY contain space or high byte values, that means a mighty
- stupid redirect URL but we still make an effort to do "right". */
- char *newest;
- size_t newlen = strlen_url(newurl, FALSE);
-
+ if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
/* This is an absolute URL, don't allow the custom port number */
disallowport = TRUE;
- newest = malloc(newlen + 1); /* get memory for this */
- if(!newest)
- return CURLE_OUT_OF_MEMORY;
+ DEBUGASSERT(data->state.uh);
+ uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
+ (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME : 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
- strcpy_url(newest, newurl, FALSE); /* create a space-free URL */
- newurl = newest; /* use this instead now */
-
- }
+ uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
if(type == FOLLOW_FAKE) {
/* we're only figuring out the new url if we would've followed locations
if(disallowport)
data->state.allow_port = FALSE;
- if(data->change.url_alloc) {
+ if(data->change.url_alloc)
Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
data->change.url = newurl;
data->change.url_alloc = TRUE;
if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
struct HTTP *http = data->req.protop;
- if(http->writebytecount)
- return Curl_readrewind(conn);
+ if(http->writebytecount) {
+ CURLcode result = Curl_readrewind(conn);
+ if(result) {
+ Curl_safefree(*url);
+ return result;
+ }
+ }
}
}
return CURLE_OK;
curl_socket_t *socks,
int numsocks);
CURLcode Curl_readrewind(struct connectdata *conn);
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+ size_t *nreadp);
CURLcode Curl_retry_request(struct connectdata *conn, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
+CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
/* This sets up a forthcoming transfer */
void
);
#endif /* HEADER_CURL_TRANSFER_H */
-
#include "non-ascii.h"
#include "inet_pton.h"
#include "getinfo.h"
+#include "urlapi-int.h"
/* And now for the protocols */
#include "ftp.h"
static void conn_free(struct connectdata *conn);
static void free_fixed_hostname(struct hostname *host);
-static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
-static CURLcode parse_url_login(struct Curl_easy *data,
- struct connectdata *conn,
- char **userptr, char **passwdptr,
- char **optionsptr);
static unsigned int get_protocol_family(unsigned int protocol);
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
Curl_mime_cleanpart(&data->set.mimepost);
}
+/* free the URL pieces */
+void Curl_up_free(struct Curl_easy *data)
+{
+ struct urlpieces *up = &data->state.up;
+ Curl_safefree(up->scheme);
+ Curl_safefree(up->hostname);
+ Curl_safefree(up->port);
+ Curl_safefree(up->user);
+ Curl_safefree(up->password);
+ Curl_safefree(up->options);
+ Curl_safefree(up->path);
+ Curl_safefree(up->query);
+ curl_url_cleanup(data->state.uh);
+ data->state.uh = NULL;
+}
+
/*
* This is the internal function curl_easy_cleanup() calls. This should
* cleanup and free all resources associated with this sessionhandle.
Curl_expire_clear(data); /* shut off timers */
m = data->multi;
-
if(m)
/* This handle is still part of a multi handle, take care of this first
and detach this handle from there. */
curl_multi_remove_handle(data->multi, data);
- if(data->multi_easy)
+ if(data->multi_easy) {
/* when curl_easy_perform() is used, it creates its own multi handle to
use and this is the one */
curl_multi_cleanup(data->multi_easy);
+ data->multi_easy = NULL;
+ }
/* 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
if(data->state.rangestringalloc)
free(data->state.range);
- /* Free the pathbuffer */
- Curl_safefree(data->state.pathbuffer);
- data->state.path = NULL;
-
/* freed here just in case DONE wasn't called */
Curl_free_request_state(data);
}
data->change.referer = NULL;
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
- data->change.url = NULL;
-
+ Curl_up_free(data);
Curl_safefree(data->state.buffer);
Curl_safefree(data->state.headerbuff);
-
+ Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, 1);
-
Curl_digest_cleanup(data);
-
Curl_safefree(data->info.contenttype);
Curl_safefree(data->info.wouldredirect);
set->wildcard_enabled = FALSE;
set->chunk_bgn = ZERO_NULL;
set->chunk_end = ZERO_NULL;
-
- /* tcp keepalives are disabled by default, but provide reasonable values for
- * the interval and idle times.
- */
set->tcp_keepalive = FALSE;
set->tcp_keepintvl = 60;
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
-
set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
-
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
set->buffer_size = READBUFFER_SIZE;
+ set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
-
+ set->fnmatch = ZERO_NULL;
+ set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
+ set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
+ set->httpversion =
+#ifdef USE_NGHTTP2
+ CURL_HTTP_VERSION_2TLS
+#else
+ CURL_HTTP_VERSION_1_1
+#endif
+ ;
Curl_http2_init_userset(set);
return result;
}
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
- data->set.fnmatch = ZERO_NULL;
- data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
Curl_http2_init_state(&data->state);
}
* primary connection, like when freeing room in the connection cache or
* killing of a dead old connection.
*
+ * A connection needs an easy handle when closing down. We support this passed
+ * in separately since the connection to get closed here is often already
+ * disassociated from an easy handle.
+ *
* This function MUST NOT reset state in the Curl_easy struct if that
* isn't strictly bound to the life-time of *this* particular connection.
*
*/
-CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
+CURLcode Curl_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
- struct Curl_easy *data;
if(!conn)
return CURLE_OK; /* this is closed and fine already */
- data = conn->data;
if(!data) {
- DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
+ DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
return CURLE_OK;
}
* If this connection isn't marked to force-close, leave it open if there
* are other users of it
*/
- if(!conn->bits.close &&
- (conn->send_pipe.size + conn->recv_pipe.size)) {
- DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
- conn->send_pipe.size + conn->recv_pipe.size));
+ if(CONN_INUSE(conn) && !dead_connection) {
+ DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
return CURLE_OK;
}
+ conn->data = data;
if(conn->dns_entry != NULL) {
Curl_resolv_unlock(data, conn->dns_entry);
conn->dns_entry = NULL;
free_fixed_hostname(&conn->http_proxy.host);
free_fixed_hostname(&conn->socks_proxy.host);
+ DEBUGASSERT(conn->data == data);
+ /* this assumes that the pointer is still there after the connection was
+ detected from the cache */
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);
- }
-
conn_free(conn);
-
return CURLE_OK;
}
return avail;
}
+/* Returns non-zero if a handle was removed */
int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
struct curl_llist *pipeline)
{
static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
{
struct curl_llist_element *curr = pipeline->head;
+#ifdef DEBUGBUILD
+ {
+ struct curl_llist_element *p = pipeline->head;
+ while(p) {
+ struct Curl_easy *e = p->ptr;
+ DEBUGASSERT(GOOD_EASY_HANDLE(e));
+ p = p->next;
+ }
+ }
+#endif
if(curr) {
return (struct Curl_easy *) curr->ptr;
}
void Curl_getoff_all_pipelines(struct Curl_easy *data,
struct connectdata *conn)
{
- bool recv_head = (conn->readchannel_inuse &&
- Curl_recvpipe_head(data, conn));
- bool send_head = (conn->writechannel_inuse &&
- Curl_sendpipe_head(data, conn));
-
- if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
- Curl_pipeline_leave_read(conn);
- if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
- Curl_pipeline_leave_write(conn);
-}
-
-static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
-{
- struct curl_llist_element *curr;
-
- if(!pipeline)
+ if(!conn->bundle)
return;
+ if(conn->bundle->multiuse == BUNDLE_PIPELINING) {
+ bool recv_head = (conn->readchannel_inuse &&
+ Curl_recvpipe_head(data, conn));
+ bool send_head = (conn->writechannel_inuse &&
+ Curl_sendpipe_head(data, conn));
- curr = pipeline->head;
- while(curr) {
- struct curl_llist_element *next = curr->next;
- struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
-
-#ifdef DEBUGBUILD /* debug-only code */
- if(data->magic != CURLEASY_MAGIC_NUMBER) {
- /* MAJOR BADNESS */
- infof(data, "signalPipeClose() found BAAD easy handle\n");
- }
-#endif
-
- if(pipe_broke)
- data->state.pipe_broke = TRUE;
- Curl_multi_handlePipeBreak(data);
- Curl_llist_remove(pipeline, curr, NULL);
- curr = next;
+ if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
+ Curl_pipeline_leave_read(conn);
+ if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
+ Curl_pipeline_leave_write(conn);
+ }
+ else {
+ (void)Curl_removeHandleFromPipeline(data, &conn->recv_pipe);
+ (void)Curl_removeHandleFromPipeline(data, &conn->send_pipe);
}
}
struct Curl_easy *data)
{
size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size;
- if(!pipeLen && !conn->inuse) {
+ if(!pipeLen && !CONN_INUSE(conn)) {
/* The check for a dead socket makes sense only if there are no
handles in pipeline and the connection isn't already marked in
use */
bool dead;
+ conn->data = data;
if(conn->handler->connection_check) {
/* The protocol has a special method for checking the state of the
connection. Use it to check if the connection is dead. */
}
if(dead) {
- conn->data = data;
infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
Curl_conncache_remove_conn(conn, FALSE);
+ conn->data = NULL; /* detach */
return TRUE;
}
}
while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
call_extract_if_dead)) {
/* disconnect it */
- (void)Curl_disconnect(prune.extracted, /* dead_connection */TRUE);
+ (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
}
data->state.conn_cache->last_cleanup = now;
}
if(extract_if_dead(check, data)) {
/* disconnect it */
- (void)Curl_disconnect(check, /* dead_connection */TRUE);
+ (void)Curl_disconnect(data, check, /* dead_connection */TRUE);
continue;
}
}
}
- if(!canpipe && check->inuse)
+ if(!canpipe && CONN_INUSE(check))
/* this request can't be pipelined but the checked connection is
already in use so we skip it */
continue;
- if((check->inuse) && (check->data->multi != needle->data->multi))
+ if(CONN_INUSE(check) && (check->data->multi != needle->data->multi))
/* this could be subject for pipeline/multiplex use, but only
if they belong to the same multi handle */
continue;
if(chosen) {
/* mark it as used before releasing the lock */
- chosen->inuse = TRUE;
+ chosen->data = data; /* own it! */
Curl_conncache_unlock(needle);
*usethis = chosen;
return TRUE; /* yes, we found one to use! */
{
if(conn->handler->proto_getsock)
return conn->handler->proto_getsock(conn, socks, numsocks);
- return GETSOCK_BLANK;
+ /* Backup getsock logic. Since there is a live socket in use, we must wait
+ for it or it will be removed from watching when the multi_socket API is
+ used. */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}
int Curl_doing_getsock(struct connectdata *conn,
/* Store creation time to help future close decision making */
conn->created = Curl_now();
+ /* Store current time to give a baseline to keepalive connection times. */
+ conn->keepalive = Curl_now();
+
+ /* Store off the configured connection upkeep time. */
+ conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
+
conn->data = data; /* Setup the association between this connection
and the Curl_easy */
return NULL;
}
-static CURLcode findprotocol(struct Curl_easy *data,
- struct connectdata *conn,
- const char *protostr)
+/* returns the handler if the given scheme is built-in */
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
{
const struct Curl_handler * const *pp;
const struct Curl_handler *p;
-
- /* Scan protocol handler table and match against 'protostr' to set a few
- variables based on the URL. Now that the handler may be changed later
- when the protocol specific setup function is called. */
- for(pp = protocols; (p = *pp) != NULL; pp++) {
- if(strcasecompare(p->scheme, protostr)) {
+ /* Scan protocol handler table and match against 'scheme'. The handler may
+ be changed later when the protocol specific setup function is called. */
+ for(pp = protocols; (p = *pp) != NULL; pp++)
+ if(strcasecompare(p->scheme, scheme))
/* Protocol found in table. Check if allowed */
- if(!(data->set.allowed_protocols & p->protocol))
- /* nope, get out */
- break;
+ return p;
+ return NULL; /* not found */
+}
+
+
+static CURLcode findprotocol(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *protostr)
+{
+ const struct Curl_handler *p = Curl_builtin_scheme(protostr);
- /* it is allowed for "normal" request, now do an extra check if this is
- the result of a redirect */
- if(data->state.this_is_a_follow &&
- !(data->set.redir_protocols & p->protocol))
- /* nope, get out */
- break;
+ if(p && /* Protocol found in table. Check if allowed */
+ (data->set.allowed_protocols & p->protocol)) {
+ /* it is allowed for "normal" request, now do an extra check if this is
+ the result of a redirect */
+ if(data->state.this_is_a_follow &&
+ !(data->set.redir_protocols & p->protocol))
+ /* nope, get out */
+ ;
+ else {
/* Perform setup complement if some. */
conn->handler = conn->given = p;
}
}
-
/* The protocol was not found in the table, but we don't have to assign it
to anything since it is already assigned to a dummy-struct in the
create_conn() function when the connectdata struct is allocated. */
return CURLE_UNSUPPORTED_PROTOCOL;
}
+
+CURLcode Curl_uc_to_curlcode(CURLUcode uc)
+{
+ switch(uc) {
+ default:
+ return CURLE_URL_MALFORMAT;
+ case CURLUE_UNSUPPORTED_SCHEME:
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ case CURLUE_OUT_OF_MEMORY:
+ return CURLE_OUT_OF_MEMORY;
+ case CURLUE_USER_NOT_ALLOWED:
+ return CURLE_LOGIN_DENIED;
+ }
+}
+
/*
* Parse URL and fill in the relevant members of the connection struct.
*/
static CURLcode parseurlandfillconn(struct Curl_easy *data,
- struct connectdata *conn,
- bool *prot_missing,
- char **userp, char **passwdp,
- char **optionsp)
+ struct connectdata *conn)
{
- char *at;
- char *fragment;
- char *path = data->state.path;
- char *query;
- int i;
- int rc;
- const char *protop = "";
CURLcode result;
- bool rebuild_url = FALSE;
- bool url_has_scheme = FALSE;
- char protobuf[16];
-
- *prot_missing = FALSE;
+ CURLU *uh;
+ CURLUcode uc;
+ char *hostname;
- /* We might pass the entire URL into the request so we need to make sure
- * there are no bad characters in there.*/
- if(strpbrk(data->change.url, "\r\n")) {
- failf(data, "Illegal characters found in URL");
- return CURLE_URL_MALFORMAT;
- }
+ Curl_up_free(data); /* cleanup previous leftovers first */
- /*************************************************************
- * Parse the URL.
- *
- * We need to parse the url even when using the proxy, because we will need
- * the hostname and port in case we are trying to SSL connect through the
- * proxy -- and we don't know if we will need to use SSL until we parse the
- * url ...
- ************************************************************/
- if(data->change.url[0] == ':') {
- failf(data, "Bad URL, colon is first character");
- return CURLE_URL_MALFORMAT;
- }
+ /* parse the URL */
+ uh = data->state.uh = curl_url();
+ if(!uh)
+ return CURLE_OUT_OF_MEMORY;
- /* MSDOS/Windows style drive prefix, eg c: in c:foo */
-#define STARTS_WITH_DRIVE_PREFIX(str) \
- ((('a' <= str[0] && str[0] <= 'z') || \
- ('A' <= str[0] && str[0] <= 'Z')) && \
- (str[1] == ':'))
-
- /* MSDOS/Windows style drive prefix, optionally with
- * a '|' instead of ':', followed by a slash or NUL */
-#define STARTS_WITH_URL_DRIVE_PREFIX(str) \
- ((('a' <= (str)[0] && (str)[0] <= 'z') || \
- ('A' <= (str)[0] && (str)[0] <= 'Z')) && \
- ((str)[1] == ':' || (str)[1] == '|') && \
- ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0))
-
- /* Don't mistake a drive letter for a scheme if the default protocol is file.
- curld --proto-default file c:/foo/bar.txt */
- if(STARTS_WITH_DRIVE_PREFIX(data->change.url) &&
- 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;
- }
- }
+ if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
+ !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) {
+ char *url;
+ if(data->change.url_alloc)
+ free(data->change.url);
+ url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
+ data->change.url);
+ if(!url)
+ return CURLE_OUT_OF_MEMORY;
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
}
- /* 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"))) {
- 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;
- }
-
- /* Extra handling URLs with an authority component (i.e. that start with
- * "file://")
- *
- * We allow omitted hostname (e.g. file:/<path>) -- valid according to
- * RFC 8089, but not the (current) WHAT-WG URL spec.
- */
- if(url_has_scheme && path[0] == '/' && path[1] == '/') {
- /* swallow the two slashes */
- char *ptr = &path[2];
-
- /*
- * According to RFC 8089, a file: URL can be reliably dereferenced if:
- *
- * o it has no/blank hostname, or
- *
- * o the hostname matches "localhost" (case-insensitively), or
- *
- * o the hostname is a FQDN that resolves to this machine.
- *
- * For brevity, we only consider URLs with empty, "localhost", or
- * "127.0.0.1" hostnames as local.
- *
- * Additionally, there is an exception for URLs with a Windows drive
- * letter in the authority (which was accidentally omitted from RFC 8089
- * Appendix E, but believe me, it was meant to be there. --MK)
- */
- if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) {
- /* the URL includes a host name, it must match "localhost" or
- "127.0.0.1" to be valid */
- if(!checkprefix("localhost/", ptr) &&
- !checkprefix("127.0.0.1/", ptr)) {
- failf(data, "Invalid file://hostname/, "
- "expected localhost or 127.0.0.1 or none");
- return CURLE_URL_MALFORMAT;
- }
- ptr += 9; /* now points to the slash after the host */
- }
+ uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
+ CURLU_GUESS_SCHEME |
+ CURLU_NON_SUPPORT_SCHEME |
+ (data->set.disallow_username_in_url ?
+ CURLU_DISALLOW_USER : 0) |
+ (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
- /* This cannot be done with strcpy, as the memory chunks overlap! */
- memmove(path, ptr, strlen(ptr) + 1);
- }
+ uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
-#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
- /* Don't allow Windows drive letters when not in Windows.
- * This catches both "file:/c:" and "file:c:" */
- if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
- STARTS_WITH_URL_DRIVE_PREFIX(path)) {
- failf(data, "File drive letters are only accepted in MSDOS/Windows.");
- return CURLE_URL_MALFORMAT;
- }
-#else
- /* If the path starts with a slash and a drive letter, ditch the slash */
- if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
- /* This cannot be done with strcpy, as the memory chunks overlap! */
- memmove(path, &path[1], strlen(&path[1]) + 1);
- }
-#endif
+ result = findprotocol(data, conn, data->state.up.scheme);
+ if(result)
+ return result;
- protop = "file"; /* protocol string */
- *prot_missing = !url_has_scheme;
+ uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
+ CURLU_URLDECODE);
+ if(!uc) {
+ conn->user = strdup(data->state.up.user);
+ if(!conn->user)
+ return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE;
}
- else {
- /* clear path */
- char slashbuf[4];
- path[0] = 0;
-
- rc = sscanf(data->change.url,
- "%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]",
- protobuf, slashbuf, conn->host.name, path);
- if(2 == rc) {
- failf(data, "Bad URL");
- return CURLE_URL_MALFORMAT;
- }
- if(3 > rc) {
-
- /*
- * The URL was badly formatted, let's try the browser-style _without_
- * protocol specified like 'http://'.
- */
- rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
- if(1 > rc) {
- /*
- * We couldn't even get this format.
- * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is
- * assigned, but the return value is EOF!
- */
-#if defined(__DJGPP__) && (DJGPP_MINOR == 4)
- if(!(rc == -1 && *conn->host.name))
-#endif
- {
- failf(data, "<url> malformed");
- return CURLE_URL_MALFORMAT;
- }
- }
-
- /*
- * Since there was no protocol part specified in the URL use the
- * user-specified default protocol. If we weren't given a default make a
- * guess by matching some protocols against the host's outermost
- * sub-domain name. Finally if there was no match use HTTP.
- */
-
- protop = data->set.str[STRING_DEFAULT_PROTOCOL];
- if(!protop) {
- /* Note: if you add a new protocol, please update the list in
- * lib/version.c too! */
- if(checkprefix("FTP.", conn->host.name))
- protop = "ftp";
- else if(checkprefix("DICT.", conn->host.name))
- protop = "DICT";
- else if(checkprefix("LDAP.", conn->host.name))
- protop = "LDAP";
- else if(checkprefix("IMAP.", conn->host.name))
- protop = "IMAP";
- else if(checkprefix("SMTP.", conn->host.name))
- protop = "smtp";
- else if(checkprefix("POP3.", conn->host.name))
- protop = "pop3";
- else
- protop = "http";
- }
+ else if(uc != CURLUE_NO_USER)
+ return Curl_uc_to_curlcode(uc);
- *prot_missing = TRUE; /* not given in URL */
- }
- else {
- size_t s = strlen(slashbuf);
- protop = protobuf;
- if(s != 2) {
- infof(data, "Unwillingly accepted illegal URL using %d slash%s!\n",
- s, s>1?"es":"");
-
- if(data->change.url_alloc)
- free(data->change.url);
- /* repair the URL to use two slashes */
- data->change.url = aprintf("%s://%s%s",
- protobuf, conn->host.name, path);
- if(!data->change.url)
- return CURLE_OUT_OF_MEMORY;
- data->change.url_alloc = TRUE;
- }
- }
+ uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
+ CURLU_URLDECODE);
+ if(!uc) {
+ conn->passwd = strdup(data->state.up.password);
+ if(!conn->passwd)
+ return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE;
}
+ else if(uc != CURLUE_NO_PASSWORD)
+ return Curl_uc_to_curlcode(uc);
- /* We search for '?' in the host name (but only on the right side of a
- * @-letter to allow ?-letters in username and password) to handle things
- * like http://example.com?param= (notice the missing '/').
- */
- at = strchr(conn->host.name, '@');
- if(at)
- query = strchr(at + 1, '?');
- else
- query = strchr(conn->host.name, '?');
-
- if(query) {
- /* We must insert a slash before the '?'-letter in the URL. If the URL had
- a slash after the '?', that is where the path currently begins and the
- '?string' is still part of the host name.
-
- We must move the trailing part from the host name and put it first in
- the path. And have it all prefixed with a slash.
- */
-
- size_t hostlen = strlen(query);
- size_t pathlen = strlen(path);
-
- /* move the existing path plus the zero byte forward, to make room for
- the host-name part */
- memmove(path + hostlen + 1, path, pathlen + 1);
-
- /* now copy the trailing host part in front of the existing path */
- memcpy(path + 1, query, hostlen);
-
- path[0]='/'; /* prepend the missing slash */
- rebuild_url = TRUE;
-
- *query = 0; /* now cut off the hostname at the ? */
- }
- else if(!path[0]) {
- /* if there's no path set, use a single slash */
- strcpy(path, "/");
- rebuild_url = TRUE;
+ uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
+ CURLU_URLDECODE);
+ if(!uc) {
+ conn->options = strdup(data->state.up.options);
+ if(!conn->options)
+ return CURLE_OUT_OF_MEMORY;
}
+ else if(uc != CURLUE_NO_OPTIONS)
+ return Curl_uc_to_curlcode(uc);
- /* If the URL is malformatted (missing a '/' after hostname before path) we
- * insert a slash here. The only letters except '/' that can start a path is
- * '?' and '#' - as controlled by the two sscanf() patterns above.
- */
- if(path[0] != '/') {
- /* We need this function to deal with overlapping memory areas. We know
- that the memory area 'path' points to is 'urllen' bytes big and that
- is bigger than the path. Use +1 to move the zero byte too. */
- memmove(&path[1], path, strlen(path) + 1);
- path[0] = '/';
- rebuild_url = TRUE;
- }
- else if(!data->set.path_as_is) {
- /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
- char *newp = Curl_dedotdotify(path);
- if(!newp)
+ uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
+ if(uc) {
+ if(!strcasecompare("file", data->state.up.scheme))
return CURLE_OUT_OF_MEMORY;
-
- if(strcmp(newp, path)) {
- rebuild_url = TRUE;
- free(data->state.pathbuffer);
- data->state.pathbuffer = newp;
- data->state.path = newp;
- path = newp;
- }
- else
- free(newp);
}
- /*
- * "rebuild_url" means that one or more URL components have been modified so
- * we need to generate an updated full version. We need the corrected URL
- * when communicating over HTTP proxy and we don't know at this point if
- * we're using a proxy or not.
- */
- if(rebuild_url) {
- char *reurl;
-
- size_t plen = strlen(path); /* new path, should be 1 byte longer than
- the original */
- size_t prefixlen = strlen(conn->host.name);
-
- if(!*prot_missing) {
- size_t protolen = strlen(protop);
-
- if(curl_strnequal(protop, data->change.url, protolen))
- prefixlen += protolen;
- else {
- failf(data, "<url> 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, "<url> malformed");
- return CURLE_URL_MALFORMAT;
- }
- }
+ uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
- reurl = malloc(prefixlen + plen + 1);
- if(!reurl)
+ uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
+ CURLU_DEFAULT_PORT);
+ if(uc) {
+ if(!strcasecompare("file", data->state.up.scheme))
return CURLE_OUT_OF_MEMORY;
-
- /* copy the prefix */
- memcpy(reurl, data->change.url, prefixlen);
-
- /* append the trailing piece + zerobyte */
- memcpy(&reurl[prefixlen], path, plen + 1);
-
- /* possible free the old one */
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
-
- infof(data, "Rebuilt URL to: %s\n", reurl);
-
- data->change.url = reurl;
- data->change.url_alloc = TRUE; /* free this later */
+ }
+ else {
+ unsigned long port = strtoul(data->state.up.port, NULL, 10);
+ conn->remote_port = curlx_ultous(port);
}
- result = findprotocol(data, conn, protop);
- if(result)
- return result;
+ (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
- /*
- * Parse the login details from the URL and strip them out of
- * the host name
- */
- result = parse_url_login(data, conn, userp, passwdp, optionsp);
- if(result)
- return result;
+ hostname = data->state.up.hostname;
+ if(!hostname)
+ /* this is for file:// transfers, get a dummy made */
+ hostname = (char *)"";
- if(conn->host.name[0] == '[') {
+ if(hostname[0] == '[') {
/* This looks like an IPv6 address literal. See if there is an address
- scope if there is no location header */
- char *percent = strchr(conn->host.name, '%');
+ scope. */
+ char *percent = strchr(++hostname, '%');
+ conn->bits.ipv6_ip = TRUE;
if(percent) {
unsigned int identifier_offset = 3;
char *endp;
infof(data, "Invalid IPv6 address format\n");
}
}
+ percent = strchr(hostname, ']');
+ if(percent)
+ /* terminate IPv6 numerical at end bracket */
+ *percent = 0;
}
+ /* make sure the connect struct gets its own copy of the host name */
+ conn->host.rawalloc = strdup(hostname);
+ if(!conn->host.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+ conn->host.name = conn->host.rawalloc;
+
if(data->set.scope_id)
/* Override any scope that was set above. */
conn->scope_id = data->set.scope_id;
- /* Remove the fragment part of the path. Per RFC 2396, this is always the
- last part of the URI. We are looking for the first '#' so that we deal
- gracefully with non conformant URI such as http://example.com#foo#bar. */
- fragment = strchr(path, '#');
- if(fragment) {
- *fragment = 0;
-
- /* we know the path part ended with a fragment, so we know the full URL
- string does too and we need to cut it off from there so it isn't used
- over proxy */
- fragment = strchr(data->change.url, '#');
- if(fragment)
- *fragment = 0;
- }
-
- /*
- * So if the URL was A://B/C#D,
- * protop is A
- * conn->host.name is B
- * data->state.path is /C
- */
return CURLE_OK;
}
free(s->range);
if(s->resume_from)
- s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
+ s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
else
s->range = strdup(data->set.str[STRING_SET_RANGE]);
{
const struct Curl_handler * p;
CURLcode result;
- struct Curl_easy *data = conn->data;
-
- /* in some case in the multi state-machine, we go back to the CONNECT state
- and then a second (or third or...) call to this function will be made
- without doing a DISCONNECT or DONE in between (since the connection is
- yet in place) and therefore this function needs to first make sure
- there's no lingering previous data allocated. */
- Curl_free_request_state(data);
-
- memset(&data->req, 0, sizeof(struct SingleRequest));
- data->req.maxdownload = -1;
-
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
/* Perform setup complement if some. */
* not be proxied, or an asterisk to override
* all proxy variables)
*/
- size_t tok_start;
- size_t tok_end;
- const char *separator = ", ";
- size_t no_proxy_len;
- size_t namelen;
- char *endptr;
-
if(no_proxy && no_proxy[0]) {
+ size_t tok_start;
+ size_t tok_end;
+ const char *separator = ", ";
+ size_t no_proxy_len;
+ size_t namelen;
+ char *endptr;
if(strcasecompare("*", no_proxy)) {
return TRUE;
}
if(!endptr)
return FALSE;
name++;
- }
- else
- endptr = strchr(name, ':');
- if(endptr)
namelen = endptr - name;
+ }
else
namelen = strlen(name);
#endif /* CURL_DISABLE_PROXY */
/*
- * parse_url_login()
- *
- * Parse the login details (user name, password and options) from the URL and
- * strip them out of the host name
- *
- * Inputs: data->set.use_netrc (CURLOPT_NETRC)
- * conn->host.name
- *
- * Outputs: (almost :- all currently undefined)
- * conn->bits.user_passwd - non-zero if non-default passwords exist
- * user - non-zero length if defined
- * passwd - non-zero length if defined
- * options - non-zero length if defined
- * conn->host.name - remove user name and password
- */
-static CURLcode parse_url_login(struct Curl_easy *data,
- struct connectdata *conn,
- char **user, char **passwd, char **options)
-{
- CURLcode result = CURLE_OK;
- char *userp = NULL;
- char *passwdp = NULL;
- char *optionsp = NULL;
-
- /* At this point, we're hoping all the other special cases have
- * been taken care of, so conn->host.name is at most
- * [user[:password][;options]]@]hostname
- *
- * We need somewhere to put the embedded details, so do that first.
- */
-
- char *ptr = strchr(conn->host.name, '@');
- char *login = conn->host.name;
-
- DEBUGASSERT(!**user);
- DEBUGASSERT(!**passwd);
- DEBUGASSERT(!**options);
- DEBUGASSERT(conn->handler);
-
- if(!ptr)
- goto out;
-
- /* We will now try to extract the
- * possible login information in a string like:
- * ftp://user:password@ftp.my.site:8021/README */
- conn->host.name = ++ptr;
-
- /* So the hostname is sane. Only bother interpreting the
- * results if we could care. It could still be wasted
- * work because it might be overtaken by the programmatically
- * set user/passwd, but doing that first adds more cases here :-(
- */
-
- if(data->set.use_netrc == CURL_NETRC_REQUIRED)
- goto out;
-
- /* We could use the login information in the URL so extract it. Only parse
- options if the handler says we should. */
- result =
- Curl_parse_login_details(login, ptr - login - 1,
- &userp, &passwdp,
- (conn->handler->flags & PROTOPT_URLOPTIONS)?
- &optionsp:NULL);
- if(result)
- goto out;
-
- if(userp) {
- char *newname;
-
- /* We have a user in the URL */
- conn->bits.userpwd_in_url = TRUE;
- conn->bits.user_passwd = TRUE; /* enable user+password */
-
- /* Decode the user */
- result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
- if(result) {
- goto out;
- }
-
- free(*user);
- *user = newname;
- }
-
- if(passwdp) {
- /* We have a password in the URL so decode it */
- char *newpasswd;
- result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
- if(result) {
- goto out;
- }
-
- free(*passwd);
- *passwd = newpasswd;
- }
-
- if(optionsp) {
- /* We have an options list in the URL so decode it */
- char *newoptions;
- result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
- if(result) {
- goto out;
- }
-
- free(*options);
- *options = newoptions;
- }
-
-
- out:
-
- free(userp);
- free(passwdp);
- free(optionsp);
-
- return result;
-}
-
-/*
* Curl_parse_login_details()
*
* This is used to parse a login string for user name, password and options in
* len [in] - The length of the login string.
* userp [in/out] - The address where a pointer to newly allocated memory
* holding the user will be stored upon completion.
- * passdwp [in/out] - The address where a pointer to newly allocated memory
+ * passwdp [in/out] - The address where a pointer to newly allocated memory
* holding the password will be stored upon completion.
* optionsp [in/out] - The address where a pointer to newly allocated memory
* holding the options will be stored upon completion.
* No matter if we use a proxy or not, we have to figure out the remote
* port number of various reasons.
*
- * To be able to detect port number flawlessly, we must not confuse them
- * IPv6-specified addresses in the [0::1] style. (RFC2732)
- *
- * The conn->host.name is currently [user:passwd@]host[:port] where host
- * could be a hostname, IPv4 address or IPv6 address.
- *
* The port number embedded in the URL is replaced, if necessary.
*************************************************************/
static CURLcode parse_remote_port(struct Curl_easy *data,
struct connectdata *conn)
{
- char *portptr;
- char endbracket;
-
- /* Note that at this point, the IPv6 address cannot contain any scope
- suffix as that has already been removed in the parseurlandfillconn()
- function */
- if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
- &endbracket)) &&
- (']' == endbracket)) {
- /* this is a RFC2732-style specified IP-address */
- conn->bits.ipv6_ip = TRUE;
-
- conn->host.name++; /* skip over the starting bracket */
- portptr = strchr(conn->host.name, ']');
- if(portptr) {
- *portptr++ = '\0'; /* zero terminate, killing the bracket */
- if(*portptr) {
- if (*portptr != ':') {
- failf(data, "IPv6 closing bracket followed by '%c'", *portptr);
- return CURLE_URL_MALFORMAT;
- }
- }
- else
- portptr = NULL; /* no port number available */
- }
- }
- else {
-#ifdef ENABLE_IPV6
- struct in6_addr in6;
- if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
- /* This is a numerical IPv6 address, meaning this is a wrongly formatted
- URL */
- failf(data, "IPv6 numerical address used in URL without brackets");
- return CURLE_URL_MALFORMAT;
- }
-#endif
-
- portptr = strchr(conn->host.name, ':');
- }
if(data->set.use_port && data->state.allow_port) {
- /* if set, we use this and ignore the port possibly given in the URL */
+ /* if set, we use this instead of the port possibly given in the URL */
+ char portbuf[16];
+ CURLUcode uc;
conn->remote_port = (unsigned short)data->set.use_port;
- if(portptr)
- *portptr = '\0'; /* cut off the name there anyway - if there was a port
- number - since the port number is to be ignored! */
- if(conn->bits.httpproxy) {
- /* we need to create new URL with the new port number */
- char *url;
- char type[12]="";
-
- if(conn->bits.type_set)
- snprintf(type, sizeof(type), ";type=%c",
- data->set.prefer_ascii?'A':
- (data->set.ftp_list_only?'D':'I'));
-
- /*
- * This synthesized URL isn't always right--suffixes like ;type=A are
- * stripped off. It would be better to work directly from the original
- * URL and simply replace the port part of it.
- */
- url = aprintf("%s://%s%s%s:%d%s%s%s", conn->given->scheme,
- conn->bits.ipv6_ip?"[":"", conn->host.name,
- conn->bits.ipv6_ip?"]":"", conn->remote_port,
- data->state.slash_removed?"/":"", data->state.path,
- type);
- if(!url)
- return CURLE_OUT_OF_MEMORY;
-
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
-
- data->change.url = url;
- data->change.url_alloc = TRUE;
- }
- }
- else if(portptr) {
- /* no CURLOPT_PORT given, extract the one from the URL */
-
- char *rest;
- long port;
-
- port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */
-
- if((port < 0) || (port > 0xffff)) {
- /* Single unix standard says port numbers are 16 bits long */
- failf(data, "Port number out of range");
- return CURLE_URL_MALFORMAT;
- }
-
- 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 {
- /* 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';
- }
+ snprintf(portbuf, sizeof(portbuf), "%u", conn->remote_port);
+ uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
+ if(uc)
+ return CURLE_OUT_OF_MEMORY;
}
- /* only if remote_port was not already parsed off the URL we use the
- default port number */
- if(conn->remote_port < 0)
- conn->remote_port = (unsigned short)conn->given->defport;
-
return CURLE_OK;
}
struct connectdata *conn,
char **userp, char **passwdp, char **optionsp)
{
+ bool user_changed = FALSE;
+ bool passwd_changed = FALSE;
+ CURLUcode uc;
if(data->set.str[STRING_USERNAME]) {
free(*userp);
*userp = strdup(data->set.str[STRING_USERNAME]);
if(!*userp)
return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+ user_changed = TRUE;
}
if(data->set.str[STRING_PASSWORD]) {
*passwdp = strdup(data->set.str[STRING_PASSWORD]);
if(!*passwdp)
return CURLE_OUT_OF_MEMORY;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+ passwd_changed = TRUE;
}
if(data->set.str[STRING_OPTIONS]) {
conn->bits.netrc = FALSE;
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
- int ret = Curl_parsenetrc(conn->host.name,
- userp, passwdp,
- data->set.str[STRING_NETRC_FILE]);
+ char *nuser = NULL;
+ char *npasswd = NULL;
+ int ret;
+
+ if(data->set.use_netrc == CURL_NETRC_OPTIONAL)
+ nuser = *userp; /* to separate otherwise identical machines */
+
+ ret = Curl_parsenetrc(conn->host.name,
+ &nuser, &npasswd,
+ data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the "
DOT_CHAR "netrc file; using defaults\n",
file, so that it is safe to use even if we followed a Location: to a
different host or similar. */
conn->bits.netrc = TRUE;
-
conn->bits.user_passwd = TRUE; /* enable user+password */
+
+ if(data->set.use_netrc == CURL_NETRC_OPTIONAL) {
+ /* prefer credentials outside netrc */
+ if(nuser && !*userp) {
+ free(*userp);
+ *userp = nuser;
+ user_changed = TRUE;
+ }
+ if(npasswd && !*passwdp) {
+ free(*passwdp);
+ *passwdp = npasswd;
+ passwd_changed = TRUE;
+ }
+ }
+ else {
+ /* prefer netrc credentials */
+ if(nuser) {
+ free(*userp);
+ *userp = nuser;
+ user_changed = TRUE;
+ }
+ if(npasswd) {
+ free(*passwdp);
+ *passwdp = npasswd;
+ passwd_changed = TRUE;
+ }
+ }
}
}
+ /* for updated strings, we update them in the URL */
+ if(user_changed) {
+ uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ }
+ if(passwd_changed) {
+ uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ }
return CURLE_OK;
}
/*
* Set the login details so they're available in the connection
*/
-static CURLcode set_login(struct connectdata *conn,
- const char *user, const char *passwd,
- const char *options)
+static CURLcode set_login(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
+ const char *setuser = CURL_DEFAULT_USER;
+ const char *setpasswd = CURL_DEFAULT_PASSWORD;
/* If our protocol needs a password and we have none, use the defaults */
- if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
- /* Store the default user */
- conn->user = strdup(CURL_DEFAULT_USER);
-
- /* Store the default password */
- if(conn->user)
- conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
- else
- conn->passwd = NULL;
-
- /* This is the default password, so DON'T set conn->bits.user_passwd */
- }
+ if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
+ ;
else {
- /* Store the user, zero-length if not set */
- conn->user = strdup(user);
-
- /* Store the password (only if user is present), zero-length if not set */
- if(conn->user)
- conn->passwd = strdup(passwd);
- else
- conn->passwd = NULL;
+ setuser = "";
+ setpasswd = "";
+ }
+ /* Store the default user */
+ if(!conn->user) {
+ conn->user = strdup(setuser);
+ if(!conn->user)
+ return CURLE_OUT_OF_MEMORY;
}
- if(!conn->user || !conn->passwd)
- result = CURLE_OUT_OF_MEMORY;
-
- /* Store the options, null if not set */
- if(!result && options[0]) {
- conn->options = strdup(options);
+ /* Store the default password */
+ if(!conn->passwd) {
+ conn->passwd = strdup(setpasswd);
+ if(!conn->passwd)
+ result = CURLE_OUT_OF_MEMORY;
+ }
- if(!conn->options)
+ /* if there's a user without password, consider password blank */
+ if(conn->user && !conn->passwd) {
+ conn->passwd = strdup("");
+ if(!conn->passwd)
result = CURLE_OUT_OF_MEMORY;
}
Curl_safefree(old_conn->user);
Curl_safefree(old_conn->passwd);
+ Curl_safefree(old_conn->options);
Curl_safefree(old_conn->http_proxy.user);
Curl_safefree(old_conn->socks_proxy.user);
Curl_safefree(old_conn->http_proxy.passwd);
CURLcode result = CURLE_OK;
struct connectdata *conn;
struct connectdata *conn_temp = NULL;
- size_t urllen;
- char *user = NULL;
- char *passwd = NULL;
- char *options = NULL;
bool reuse;
- bool prot_missing = FALSE;
bool connections_available = TRUE;
bool force_reuse = FALSE;
bool waitpipe = FALSE;
/*************************************************************
* Check input data
*************************************************************/
-
if(!data->change.url) {
result = CURLE_URL_MALFORMAT;
goto out;
any failure */
*in_connect = conn;
- /* This initing continues below, see the comment "Continue connectdata
- * initialization here" */
-
- /***********************************************************
- * We need to allocate memory to store the path in. We get the size of the
- * full URL to be sure, and we need to make it at least 256 bytes since
- * other parts of the code will rely on this fact
- ***********************************************************/
-#define LEAST_PATH_ALLOC 256
- urllen = strlen(data->change.url);
- if(urllen < LEAST_PATH_ALLOC)
- urllen = LEAST_PATH_ALLOC;
-
- /*
- * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
- * 1 - an extra terminating zero
- * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
- */
-
- Curl_safefree(data->state.pathbuffer);
- data->state.path = NULL;
-
- data->state.pathbuffer = malloc(urllen + 2);
- if(NULL == data->state.pathbuffer) {
- result = CURLE_OUT_OF_MEMORY; /* really bad error */
- goto out;
- }
- data->state.path = data->state.pathbuffer;
-
- conn->host.rawalloc = malloc(urllen + 2);
- if(NULL == conn->host.rawalloc) {
- Curl_safefree(data->state.pathbuffer);
- data->state.path = NULL;
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- conn->host.name = conn->host.rawalloc;
- conn->host.name[0] = 0;
-
- user = strdup("");
- passwd = strdup("");
- options = strdup("");
- if(!user || !passwd || !options) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
- &options);
+ result = parseurlandfillconn(data, conn);
if(result)
goto out;
- /*************************************************************
- * No protocol part in URL was used, add it!
- *************************************************************/
- if(prot_missing) {
- /* We're guessing prefixes here and if we're told to use a proxy or if
- we're going to follow a Location: later or... then we need the protocol
- part added so that we have a valid URL. */
- char *reurl;
- char *ch_lower;
-
- reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
-
- if(!reurl) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- /* Change protocol prefix to lower-case */
- for(ch_lower = reurl; *ch_lower != ':'; ch_lower++)
- *ch_lower = (char)TOLOWER(*ch_lower);
-
- if(data->change.url_alloc) {
- Curl_safefree(data->change.url);
- data->change.url_alloc = FALSE;
- }
-
- data->change.url = reurl;
- data->change.url_alloc = TRUE; /* free this later */
- }
-
- /*************************************************************
- * If the protocol can't handle url query strings, then cut
- * off the unhandable part
- *************************************************************/
- if((conn->given->flags&PROTOPT_NOURLQUERY)) {
- char *path_q_sep = strchr(conn->data->state.path, '?');
- if(path_q_sep) {
- /* according to rfc3986, allow the query (?foo=bar)
- also on protocols that can't handle it.
-
- cut the string-part after '?'
- */
-
- /* terminate the string */
- path_q_sep[0] = 0;
- }
- }
-
if(data->set.str[STRING_BEARER]) {
conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
if(!conn->oauth_bearer) {
/* Check for overridden login details and set them accordingly so they
they are known when protocol->setup_connection is called! */
- result = override_login(data, conn, &user, &passwd, &options);
+ result = override_login(data, conn, &conn->user, &conn->passwd,
+ &conn->options);
if(result)
goto out;
- result = set_login(conn, user, passwd, options);
+
+ result = set_login(conn); /* default credentials */
if(result)
goto out;
/* this is supposed to be the connect function so we better at least check
that the file is present here! */
DEBUGASSERT(conn->handler->connect_it);
+ Curl_persistconninfo(conn);
result = conn->handler->connect_it(conn, &done);
/* Setup a "faked" transfer that'll do nothing */
conn->data = data;
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
- Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ if(result)
+ goto out;
/*
* Setup whatever necessary for a resumed transfer
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.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
+ data->set.proxy_ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_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];
* new one.
*************************************************************/
+ DEBUGASSERT(conn->user);
+ DEBUGASSERT(conn->passwd);
+
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
we only acknowledge this option if this is not a re-used connection
already (which happens due to follow-location or during a HTTP
conn_candidate = Curl_conncache_extract_bundle(data, bundle);
Curl_conncache_unlock(conn);
- if(conn_candidate) {
- /* Set the connection's owner correctly, then kill it */
- conn_candidate->data = data;
- (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
- }
+ if(conn_candidate)
+ (void)Curl_disconnect(data, conn_candidate,
+ /* dead_connection */ FALSE);
else {
- infof(data, "No more connections allowed to host: %d\n",
+ infof(data, "No more connections allowed to host: %zu\n",
max_host_connections);
connections_available = FALSE;
}
/* The cache is full. Let's see if we can kill a connection. */
conn_candidate = Curl_conncache_extract_oldest(data);
-
- if(conn_candidate) {
- /* Set the connection's owner correctly, then kill it */
- conn_candidate->data = data;
- (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
- }
+ if(conn_candidate)
+ (void)Curl_disconnect(data, conn_candidate,
+ /* dead_connection */ FALSE);
else {
infof(data, "No connections available in cache\n");
connections_available = FALSE;
goto out;
}
else {
- /* Mark the connection as used, before we add it */
- conn->inuse = TRUE;
-
/*
* This is a brand new connection, so let's store it in the connection
* cache of ours!
*/
- Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ if(result)
+ goto out;
}
#if defined(USE_NTLM)
result = resolve_server(data, conn, async);
out:
-
- free(options);
- free(passwd);
- free(user);
return result;
}
*asyncp = FALSE; /* assume synchronous resolves by default */
+ /* init the single-transfer specific data */
+ Curl_free_request_state(data);
+ memset(&data->req, 0, sizeof(struct SingleRequest));
+ data->req.maxdownload = -1;
+
/* call the stuff that needs to be called */
result = create_conn(data, in_connect, asyncp);
if(!result) {
- /* no error */
- if((*in_connect)->send_pipe.size || (*in_connect)->recv_pipe.size)
+ if(CONN_INUSE(*in_connect))
/* pipelining */
*protocol_done = TRUE;
else if(!*asyncp) {
*in_connect = NULL;
return result;
}
-
- if(result && *in_connect) {
- /* We're not allowed to return failure with memory left allocated
- in the connectdata struct, free those here */
- Curl_disconnect(*in_connect, FALSE); /* close the connection */
- *in_connect = NULL; /* return a NULL */
+ else if(result && *in_connect) {
+ /* We're not allowed to return failure with memory left allocated in the
+ connectdata struct, free those here */
+ Curl_disconnect(data, *in_connect, TRUE);
+ *in_connect = NULL; /* return a NULL */
}
return result;
{
struct SingleRequest *k = &data->req;
- conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
- use */
+ if(conn) {
+ conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
+ use */
+ /* if the protocol used doesn't support wildcards, switch it off */
+ if(data->state.wildcardmatch &&
+ !(conn->handler->flags & PROTOPT_WILDCARD))
+ data->state.wildcardmatch = FALSE;
+ }
data->state.done = FALSE; /* *_done() is not called yet */
data->state.expect100header = FALSE;
- /* if the protocol used doesn't support wildcards, switch it off */
- if(data->state.wildcardmatch &&
- !(conn->handler->flags & PROTOPT_WILDCARD))
- data->state.wildcardmatch = FALSE;
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
return family;
}
+
+
+/*
+ * Wrapper to call functions in Curl_conncache_foreach()
+ *
+ * Returns always 0.
+ */
+static int conn_upkeep(struct connectdata *conn,
+ void *param)
+{
+ /* Param is unused. */
+ (void)param;
+
+ if(conn->handler->connection_check) {
+ /* Do a protocol-specific keepalive check on the connection. */
+ conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
+ }
+
+ return 0; /* continue iteration */
+}
+
+CURLcode Curl_upkeep(struct conncache *conn_cache,
+ void *data)
+{
+ /* Loop over every connection and make connection alive. */
+ Curl_conncache_foreach(data,
+ conn_cache,
+ data,
+ conn_upkeep);
+ return CURLE_OK;
+}
#define READBUFFER_MAX CURL_MAX_READ_SIZE
#define READBUFFER_MIN 1024
+/* The default upload buffer size, should not be smaller than
+ CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
+ a write callback.
+
+ The size was 16KB for many years but was bumped to 64KB because it makes
+ libcurl able to do significantly faster uploads in some circumstances. Even
+ larger buffers can help further, but this is deemed a fair memory/speed
+ compromise. */
+#define UPLOADBUFFER_DEFAULT 65536
+#define UPLOADBUFFER_MAX (2*1024*1024)
+#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
+
/*
* Prototypes for library-wide functions provided by url.c
*/
CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_open(struct Curl_easy **curl);
CURLcode Curl_init_userdefined(struct Curl_easy *data);
-CURLcode Curl_dupset(struct Curl_easy * dst, struct Curl_easy * src);
+
void Curl_freeset(struct Curl_easy * data);
+/* free the URL pieces */
+void Curl_up_free(struct Curl_easy *data);
+CURLcode Curl_uc_to_curlcode(CURLUcode uc);
CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, struct connectdata **,
bool *async, bool *protocol_connect);
-CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
+CURLcode Curl_disconnect(struct Curl_easy *data,
+ struct connectdata *, bool dead_connection);
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
-bool Curl_isPipeliningEnabled(const struct Curl_easy *handle);
-CURLcode Curl_addHandleToPipeline(struct Curl_easy *handle,
- struct curl_llist *pipeline);
+
int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
struct curl_llist *pipeline);
/* remove the specified connection from all (possible) pipelines and related
void Curl_getoff_all_pipelines(struct Curl_easy *data,
struct connectdata *conn);
-void Curl_close_connections(struct Curl_easy *data);
+CURLcode Curl_upkeep(struct conncache *conn_cache, void *data);
+
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
--- /dev/null
+#ifndef HEADER_CURL_URLAPI_INT_H
+#define HEADER_CURL_URLAPI_INT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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"
+/* scheme is not URL encoded, the longest libcurl supported ones are 6
+ letters */
+#define MAX_SCHEME_LEN 8
+
+bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
+char *Curl_concat_url(const char *base, const char *relurl);
+size_t Curl_strlen_url(const char *url, bool relative);
+void Curl_strcpy_url(char *output, const char *url, bool relative);
+#endif /* HEADER_CURL_URLAPI_INT_H */
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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"
+
+#include "urldata.h"
+#include "urlapi-int.h"
+#include "strcase.h"
+#include "dotdot.h"
+#include "url.h"
+#include "escape.h"
+#include "curl_ctype.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+ /* MSDOS/Windows style drive prefix, eg c: in c:foo */
+#define STARTS_WITH_DRIVE_PREFIX(str) \
+ ((('a' <= str[0] && str[0] <= 'z') || \
+ ('A' <= str[0] && str[0] <= 'Z')) && \
+ (str[1] == ':'))
+
+ /* MSDOS/Windows style drive prefix, optionally with
+ * a '|' instead of ':', followed by a slash or NUL */
+#define STARTS_WITH_URL_DRIVE_PREFIX(str) \
+ ((('a' <= (str)[0] && (str)[0] <= 'z') || \
+ ('A' <= (str)[0] && (str)[0] <= 'Z')) && \
+ ((str)[1] == ':' || (str)[1] == '|') && \
+ ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0))
+
+/* Internal representation of CURLU. Point to URL-encoded strings. */
+struct Curl_URL {
+ char *scheme;
+ char *user;
+ char *password;
+ char *options; /* IMAP only? */
+ char *host;
+ char *port;
+ char *path;
+ char *query;
+ char *fragment;
+
+ char *scratch; /* temporary scratch area */
+ long portnum; /* the numerical version */
+};
+
+#define DEFAULT_SCHEME "https"
+
+static void free_urlhandle(struct Curl_URL *u)
+{
+ free(u->scheme);
+ free(u->user);
+ free(u->password);
+ free(u->options);
+ free(u->host);
+ free(u->port);
+ free(u->path);
+ free(u->query);
+ free(u->fragment);
+ free(u->scratch);
+}
+
+/* move the full contents of one handle onto another and
+ free the original */
+static void mv_urlhandle(struct Curl_URL *from,
+ struct Curl_URL *to)
+{
+ free_urlhandle(to);
+ *to = *from;
+ free(from);
+}
+
+/*
+ * Find the separator at the end of the host name, or the '?' in cases like
+ * http://www.url.com?id=2380
+ */
+static const char *find_host_sep(const char *url)
+{
+ const char *sep;
+ const char *query;
+
+ /* Find the start of the hostname */
+ sep = strstr(url, "//");
+ if(!sep)
+ sep = url;
+ else
+ sep += 2;
+
+ query = strchr(sep, '?');
+ sep = strchr(sep, '/');
+
+ if(!sep)
+ sep = url + strlen(url);
+
+ if(!query)
+ query = url + strlen(url);
+
+ return sep < query ? sep : query;
+}
+
+/*
+ * Decide in an encoding-independent manner whether a character in an
+ * URL must be escaped. The same criterion must be used in strlen_url()
+ * and strcpy_url().
+ */
+static bool urlchar_needs_escaping(int c)
+{
+ return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
+}
+
+/*
+ * strlen_url() returns the length of the given URL if the spaces within the
+ * URL were properly URL encoded.
+ * URL encoding should be skipped for host names, otherwise IDN resolution
+ * will fail.
+ */
+size_t Curl_strlen_url(const char *url, bool relative)
+{
+ const unsigned char *ptr;
+ size_t newlen = 0;
+ bool left = TRUE; /* left side of the ? */
+ const unsigned char *host_sep = (const unsigned char *) url;
+
+ if(!relative)
+ host_sep = (const unsigned char *) find_host_sep(url);
+
+ for(ptr = (unsigned char *)url; *ptr; ptr++) {
+
+ if(ptr < host_sep) {
+ ++newlen;
+ continue;
+ }
+
+ switch(*ptr) {
+ case '?':
+ left = FALSE;
+ /* FALLTHROUGH */
+ default:
+ if(urlchar_needs_escaping(*ptr))
+ newlen += 2;
+ newlen++;
+ break;
+ case ' ':
+ if(left)
+ newlen += 3;
+ else
+ newlen++;
+ break;
+ }
+ }
+ return newlen;
+}
+
+/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in
+ * the source URL accordingly.
+ * URL encoding should be skipped for host names, otherwise IDN resolution
+ * will fail.
+ */
+void Curl_strcpy_url(char *output, const char *url, bool relative)
+{
+ /* we must add this with whitespace-replacing */
+ bool left = TRUE;
+ const unsigned char *iptr;
+ char *optr = output;
+ const unsigned char *host_sep = (const unsigned char *) url;
+
+ if(!relative)
+ host_sep = (const unsigned char *) find_host_sep(url);
+
+ for(iptr = (unsigned char *)url; /* read from here */
+ *iptr; /* until zero byte */
+ iptr++) {
+
+ if(iptr < host_sep) {
+ *optr++ = *iptr;
+ continue;
+ }
+
+ switch(*iptr) {
+ case '?':
+ left = FALSE;
+ /* FALLTHROUGH */
+ default:
+ if(urlchar_needs_escaping(*iptr)) {
+ snprintf(optr, 4, "%%%02x", *iptr);
+ optr += 3;
+ }
+ else
+ *optr++=*iptr;
+ break;
+ case ' ':
+ if(left) {
+ *optr++='%'; /* add a '%' */
+ *optr++='2'; /* add a '2' */
+ *optr++='0'; /* add a '0' */
+ }
+ else
+ *optr++='+'; /* add a '+' here */
+ break;
+ }
+ }
+ *optr = 0; /* zero terminate output buffer */
+
+}
+
+/*
+ * Returns true if the given URL is absolute (as opposed to relative) within
+ * the buffer size. Returns the scheme in the buffer if TRUE and 'buf' is
+ * non-NULL.
+ */
+bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
+{
+ size_t i;
+#ifdef WIN32
+ if(STARTS_WITH_DRIVE_PREFIX(url))
+ return FALSE;
+#endif
+ for(i = 0; i < buflen && url[i]; ++i) {
+ char s = url[i];
+ if(s == ':') {
+ if(buf)
+ buf[i] = 0;
+ return TRUE;
+ }
+ /* RFC 3986 3.1 explains:
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ */
+ else if(ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') ) {
+ if(buf)
+ buf[i] = (char)TOLOWER(s);
+ }
+ else
+ break;
+ }
+ return FALSE;
+}
+
+/*
+ * Concatenate a relative URL to a base URL making it absolute.
+ * URL-encodes any spaces.
+ * The returned pointer must be freed by the caller unless NULL
+ * (returns NULL on out of memory).
+ */
+char *Curl_concat_url(const char *base, const char *relurl)
+{
+ /***
+ TRY to append this new path to the old URL
+ to the right of the host part. Oh crap, this is doomed to cause
+ problems in the future...
+ */
+ char *newest;
+ char *protsep;
+ char *pathsep;
+ size_t newlen;
+ bool host_changed = FALSE;
+
+ const char *useurl = relurl;
+ size_t urllen;
+
+ /* we must make our own copy of the URL to play with, as it may
+ point to read-only data */
+ char *url_clone = strdup(base);
+
+ if(!url_clone)
+ return NULL; /* skip out of this NOW */
+
+ /* protsep points to the start of the host name */
+ protsep = strstr(url_clone, "//");
+ if(!protsep)
+ protsep = url_clone;
+ else
+ protsep += 2; /* pass the slashes */
+
+ if('/' != relurl[0]) {
+ int level = 0;
+
+ /* First we need to find out if there's a ?-letter in the URL,
+ and cut it and the right-side of that off */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep = 0;
+
+ /* we have a relative path to append to the last slash if there's one
+ available, or if the new URL is just a query string (starts with a
+ '?') we append the new one at the end of the entire currently worked
+ out URL */
+ if(useurl[0] != '?') {
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep = 0;
+ }
+
+ /* Check if there's any slash after the host name, and if so, remember
+ that position instead */
+ pathsep = strchr(protsep, '/');
+ if(pathsep)
+ protsep = pathsep + 1;
+ else
+ protsep = NULL;
+
+ /* now deal with one "./" or any amount of "../" in the newurl
+ and act accordingly */
+
+ if((useurl[0] == '.') && (useurl[1] == '/'))
+ useurl += 2; /* just skip the "./" */
+
+ while((useurl[0] == '.') &&
+ (useurl[1] == '.') &&
+ (useurl[2] == '/')) {
+ level++;
+ useurl += 3; /* pass the "../" */
+ }
+
+ if(protsep) {
+ while(level--) {
+ /* cut off one more level from the right of the original URL */
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ *pathsep = 0;
+ else {
+ *protsep = 0;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* We got a new absolute path for this server */
+
+ if((relurl[0] == '/') && (relurl[1] == '/')) {
+ /* the new URL starts with //, just keep the protocol part from the
+ original one */
+ *protsep = 0;
+ useurl = &relurl[2]; /* we keep the slashes from the original, so we
+ skip the new ones */
+ host_changed = TRUE;
+ }
+ else {
+ /* cut off the original URL from the first slash, or deal with URLs
+ without slash */
+ pathsep = strchr(protsep, '/');
+ if(pathsep) {
+ /* When people use badly formatted URLs, such as
+ "http://www.url.com?dir=/home/daniel" we must not use the first
+ slash, if there's a ?-letter before it! */
+ char *sep = strchr(protsep, '?');
+ if(sep && (sep < pathsep))
+ pathsep = sep;
+ *pathsep = 0;
+ }
+ else {
+ /* There was no slash. Now, since we might be operating on a badly
+ formatted URL, such as "http://www.url.com?id=2380" which doesn't
+ use a slash separator as it is supposed to, we need to check for a
+ ?-letter as well! */
+ pathsep = strchr(protsep, '?');
+ if(pathsep)
+ *pathsep = 0;
+ }
+ }
+ }
+
+ /* If the new part contains a space, this is a mighty stupid redirect
+ but we still make an effort to do "right". To the left of a '?'
+ letter we replace each space with %20 while it is replaced with '+'
+ on the right side of the '?' letter.
+ */
+ newlen = Curl_strlen_url(useurl, !host_changed);
+
+ urllen = strlen(url_clone);
+
+ newest = malloc(urllen + 1 + /* possible slash */
+ newlen + 1 /* zero byte */);
+
+ if(!newest) {
+ free(url_clone); /* don't leak this */
+ return NULL;
+ }
+
+ /* copy over the root url part */
+ memcpy(newest, url_clone, urllen);
+
+ /* check if we need to append a slash */
+ if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
+ ;
+ else
+ newest[urllen++]='/';
+
+ /* then append the new piece on the right side */
+ Curl_strcpy_url(&newest[urllen], useurl, !host_changed);
+
+ free(url_clone);
+
+ return newest;
+}
+
+/*
+ * parse_hostname_login()
+ *
+ * Parse the login details (user name, password and options) from the URL and
+ * strip them out of the host name
+ *
+ */
+static CURLUcode parse_hostname_login(struct Curl_URL *u,
+ const struct Curl_handler *h,
+ char **hostname,
+ unsigned int flags)
+{
+ CURLUcode result = CURLUE_OK;
+ CURLcode ccode;
+ char *userp = NULL;
+ char *passwdp = NULL;
+ char *optionsp = NULL;
+
+ /* At this point, we're hoping all the other special cases have
+ * been taken care of, so conn->host.name is at most
+ * [user[:password][;options]]@]hostname
+ *
+ * We need somewhere to put the embedded details, so do that first.
+ */
+
+ char *ptr = strchr(*hostname, '@');
+ char *login = *hostname;
+
+ if(!ptr)
+ goto out;
+
+ /* We will now try to extract the
+ * possible login information in a string like:
+ * ftp://user:password@ftp.my.site:8021/README */
+ *hostname = ++ptr;
+
+ /* We could use the login information in the URL so extract it. Only parse
+ options if the handler says we should. Note that 'h' might be NULL! */
+ ccode = Curl_parse_login_details(login, ptr - login - 1,
+ &userp, &passwdp,
+ (h && (h->flags & PROTOPT_URLOPTIONS)) ?
+ &optionsp:NULL);
+ if(ccode) {
+ result = CURLUE_MALFORMED_INPUT;
+ goto out;
+ }
+
+ if(userp) {
+ if(flags & CURLU_DISALLOW_USER) {
+ /* Option DISALLOW_USER is set and url contains username. */
+ result = CURLUE_USER_NOT_ALLOWED;
+ goto out;
+ }
+
+ u->user = userp;
+ }
+
+ if(passwdp)
+ u->password = passwdp;
+
+ if(optionsp)
+ u->options = optionsp;
+
+ return CURLUE_OK;
+ out:
+
+ free(userp);
+ free(passwdp);
+ free(optionsp);
+
+ return result;
+}
+
+static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
+{
+ char *portptr;
+ char endbracket;
+ int len;
+
+ if((1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.%%]%c%n",
+ &endbracket, &len)) &&
+ (']' == endbracket)) {
+ /* this is a RFC2732-style specified IP-address */
+ portptr = &hostname[len];
+ if (*portptr != ':')
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else
+ portptr = strchr(hostname, ':');
+
+ if(portptr) {
+ char *rest;
+ long port;
+ char portbuf[7];
+
+ if(!ISDIGIT(portptr[1]))
+ return CURLUE_BAD_PORT_NUMBER;
+
+ port = strtol(portptr + 1, &rest, 10); /* Port number must be decimal */
+
+ if((port <= 0) || (port > 0xffff))
+ /* Single unix standard says port numbers are 16 bits long, but we don't
+ treat port zero as OK. */
+ return CURLUE_BAD_PORT_NUMBER;
+
+ if(rest[0])
+ return CURLUE_BAD_PORT_NUMBER;
+
+ if(rest != &portptr[1]) {
+ *portptr++ = '\0'; /* cut off the name there */
+ *rest = 0;
+ /* generate a new to get rid of leading zeroes etc */
+ snprintf(portbuf, sizeof(portbuf), "%ld", port);
+ u->portnum = port;
+ u->port = strdup(portbuf);
+ if(!u->port)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ 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';
+ }
+ }
+
+ return CURLUE_OK;
+}
+
+/* scan for byte values < 31 or 127 */
+static CURLUcode junkscan(char *part)
+{
+ char badbytes[]={
+ /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x7f,
+ 0x00 /* zero terminate */
+ };
+ if(part) {
+ size_t n = strlen(part);
+ size_t nfine = strcspn(part, badbytes);
+ if(nfine != n)
+ /* since we don't know which part is scanned, return a generic error
+ code */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ return CURLUE_OK;
+}
+
+static CURLUcode hostname_check(char *hostname, unsigned int flags)
+{
+ const char *l = NULL; /* accepted characters */
+ size_t len;
+ size_t hlen = strlen(hostname);
+ (void)flags;
+
+ if(hostname[0] == '[') {
+ hostname++;
+ l = "0123456789abcdefABCDEF::.%";
+ hlen -= 2;
+ }
+
+ if(l) {
+ /* only valid letters are ok */
+ len = strspn(hostname, l);
+ if(hlen != len)
+ /* hostname with bad content */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else {
+ /* letters from the second string is not ok */
+ len = strcspn(hostname, " ");
+ if(hlen != len)
+ /* hostname with bad content */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ return CURLUE_OK;
+}
+
+#define HOSTNAME_END(x) (((x) == '/') || ((x) == '?') || ((x) == '#'))
+
+static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
+{
+ char *path;
+ bool path_alloced = FALSE;
+ char *hostname;
+ char *query = NULL;
+ char *fragment = NULL;
+ CURLUcode result;
+ bool url_has_scheme = FALSE;
+ char schemebuf[MAX_SCHEME_LEN];
+ char *schemep = NULL;
+ size_t schemelen = 0;
+ size_t urllen;
+ const struct Curl_handler *h = NULL;
+
+ if(!url)
+ return CURLUE_MALFORMED_INPUT;
+
+ /*************************************************************
+ * Parse the URL.
+ ************************************************************/
+ /* allocate scratch area */
+ urllen = strlen(url);
+ path = u->scratch = malloc(urllen * 2 + 2);
+ if(!path)
+ return CURLUE_OUT_OF_MEMORY;
+
+ hostname = &path[urllen + 1];
+ hostname[0] = 0;
+
+ if(Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf))) {
+ url_has_scheme = TRUE;
+ schemelen = strlen(schemebuf);
+ }
+
+ /* handle the file: scheme */
+ if(url_has_scheme && strcasecompare(schemebuf, "file")) {
+ /* path has been allocated large enough to hold this */
+ strcpy(path, &url[5]);
+
+ hostname = NULL; /* no host for file: URLs */
+ u->scheme = strdup("file");
+ if(!u->scheme)
+ return CURLUE_OUT_OF_MEMORY;
+
+ /* Extra handling URLs with an authority component (i.e. that start with
+ * "file://")
+ *
+ * We allow omitted hostname (e.g. file:/<path>) -- valid according to
+ * RFC 8089, but not the (current) WHAT-WG URL spec.
+ */
+ if(path[0] == '/' && path[1] == '/') {
+ /* swallow the two slashes */
+ char *ptr = &path[2];
+
+ /*
+ * According to RFC 8089, a file: URL can be reliably dereferenced if:
+ *
+ * o it has no/blank hostname, or
+ *
+ * o the hostname matches "localhost" (case-insensitively), or
+ *
+ * o the hostname is a FQDN that resolves to this machine.
+ *
+ * For brevity, we only consider URLs with empty, "localhost", or
+ * "127.0.0.1" hostnames as local.
+ *
+ * Additionally, there is an exception for URLs with a Windows drive
+ * letter in the authority (which was accidentally omitted from RFC 8089
+ * Appendix E, but believe me, it was meant to be there. --MK)
+ */
+ if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) {
+ /* the URL includes a host name, it must match "localhost" or
+ "127.0.0.1" to be valid */
+ if(!checkprefix("localhost/", ptr) &&
+ !checkprefix("127.0.0.1/", ptr)) {
+ /* Invalid file://hostname/, expected localhost or 127.0.0.1 or
+ none */
+ return CURLUE_MALFORMED_INPUT;
+ }
+ ptr += 9; /* now points to the slash after the host */
+ }
+
+ path = ptr;
+ }
+
+#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
+ /* Don't allow Windows drive letters when not in Windows.
+ * This catches both "file:/c:" and "file:c:" */
+ if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
+ STARTS_WITH_URL_DRIVE_PREFIX(path)) {
+ /* File drive letters are only accepted in MSDOS/Windows */
+ return CURLUE_MALFORMED_INPUT;
+ }
+#else
+ /* If the path starts with a slash and a drive letter, ditch the slash */
+ if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
+ /* This cannot be done with strcpy, as the memory chunks overlap! */
+ memmove(path, &path[1], strlen(&path[1]) + 1);
+ }
+#endif
+
+ }
+ else {
+ /* clear path */
+ const char *p;
+ const char *hostp;
+ size_t len;
+ path[0] = 0;
+
+ if(url_has_scheme) {
+ int i = 0;
+ p = &url[schemelen + 1];
+ while(p && (*p == '/') && (i < 4)) {
+ p++;
+ i++;
+ }
+ if((i < 1) || (i>3))
+ /* less than one or more than three slashes */
+ return CURLUE_MALFORMED_INPUT;
+
+ schemep = schemebuf;
+ if(!Curl_builtin_scheme(schemep) &&
+ !(flags & CURLU_NON_SUPPORT_SCHEME))
+ return CURLUE_UNSUPPORTED_SCHEME;
+
+ if(junkscan(schemep))
+ return CURLUE_MALFORMED_INPUT;
+ }
+ else {
+ /* no scheme! */
+
+ if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
+ return CURLUE_MALFORMED_INPUT;
+ if(flags & CURLU_DEFAULT_SCHEME)
+ schemep = (char *) DEFAULT_SCHEME;
+
+ /*
+ * The URL was badly formatted, let's try without scheme specified.
+ */
+ p = url;
+ }
+ hostp = p; /* host name starts here */
+
+ while(*p && !HOSTNAME_END(*p)) /* find end of host name */
+ p++;
+
+ len = p - hostp;
+ if(!len)
+ return CURLUE_MALFORMED_INPUT;
+
+ memcpy(hostname, hostp, len);
+ hostname[len] = 0;
+
+ if((flags & CURLU_GUESS_SCHEME) && !schemep) {
+ /* legacy curl-style guess based on host name */
+ if(checkprefix("ftp.", hostname))
+ schemep = (char *)"ftp";
+ else if(checkprefix("dict.", hostname))
+ schemep = (char *)"dict";
+ else if(checkprefix("ldap.", hostname))
+ schemep = (char *)"ldap";
+ else if(checkprefix("imap.", hostname))
+ schemep = (char *)"imap";
+ else if(checkprefix("smtp.", hostname))
+ schemep = (char *)"smtp";
+ else if(checkprefix("pop3.", hostname))
+ schemep = (char *)"pop3";
+ else
+ schemep = (char *)"http";
+ }
+
+ len = strlen(p);
+ memcpy(path, p, len);
+ path[len] = 0;
+
+ u->scheme = strdup(schemep);
+ if(!u->scheme)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ /* if this is a known scheme, get some details */
+ h = Curl_builtin_scheme(u->scheme);
+
+ if(junkscan(path))
+ return CURLUE_MALFORMED_INPUT;
+
+ query = strchr(path, '?');
+ if(query)
+ *query++ = 0;
+
+ fragment = strchr(query?query:path, '#');
+ if(fragment)
+ *fragment++ = 0;
+
+ if(!path[0])
+ /* if there's no path set, unset */
+ path = NULL;
+ else if(!(flags & CURLU_PATH_AS_IS)) {
+ /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
+ char *newp = Curl_dedotdotify(path);
+ if(!newp)
+ return CURLUE_OUT_OF_MEMORY;
+
+ if(strcmp(newp, path)) {
+ /* if we got a new version */
+ path = newp;
+ path_alloced = TRUE;
+ }
+ else
+ free(newp);
+ }
+ if(path) {
+ u->path = path_alloced?path:strdup(path);
+ if(!u->path)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ if(hostname) {
+ /*
+ * Parse the login details and strip them out of the host name.
+ */
+ if(junkscan(hostname))
+ return CURLUE_MALFORMED_INPUT;
+
+ result = parse_hostname_login(u, h, &hostname, flags);
+ if(result)
+ return result;
+
+ result = parse_port(u, hostname);
+ if(result)
+ return result;
+
+ result = hostname_check(hostname, flags);
+ if(result)
+ return result;
+
+ u->host = strdup(hostname);
+ if(!u->host)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ if(query && query[0]) {
+ u->query = strdup(query);
+ if(!u->query)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ if(fragment && fragment[0]) {
+ u->fragment = strdup(fragment);
+ if(!u->fragment)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+
+ free(u->scratch);
+ u->scratch = NULL;
+
+ return CURLUE_OK;
+}
+
+/*
+ * Parse the URL and set the relevant members of the Curl_URL struct.
+ */
+static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
+{
+ CURLUcode result = seturl(url, u, flags);
+ if(result) {
+ free_urlhandle(u);
+ memset(u, 0, sizeof(struct Curl_URL));
+ }
+ return result;
+}
+
+/*
+ */
+CURLU *curl_url(void)
+{
+ return calloc(sizeof(struct Curl_URL), 1);
+}
+
+void curl_url_cleanup(CURLU *u)
+{
+ if(u) {
+ free_urlhandle(u);
+ free(u);
+ }
+}
+
+#define DUP(dest, src, name) \
+ if(src->name) { \
+ dest->name = strdup(src->name); \
+ if(!dest->name) \
+ goto fail; \
+ }
+
+CURLU *curl_url_dup(CURLU *in)
+{
+ struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
+ if(u) {
+ DUP(u, in, scheme);
+ DUP(u, in, user);
+ DUP(u, in, password);
+ DUP(u, in, options);
+ DUP(u, in, host);
+ DUP(u, in, port);
+ DUP(u, in, path);
+ DUP(u, in, query);
+ DUP(u, in, fragment);
+ u->portnum = in->portnum;
+ }
+ return u;
+ fail:
+ curl_url_cleanup(u);
+ return NULL;
+}
+
+CURLUcode curl_url_get(CURLU *u, CURLUPart what,
+ char **part, unsigned int flags)
+{
+ char *ptr;
+ CURLUcode ifmissing = CURLUE_UNKNOWN_PART;
+ char portbuf[7];
+ bool urldecode = (flags & CURLU_URLDECODE)?1:0;
+ bool plusdecode = FALSE;
+ (void)flags;
+ if(!u)
+ return CURLUE_BAD_HANDLE;
+ if(!part)
+ return CURLUE_BAD_PARTPOINTER;
+ *part = NULL;
+
+ switch(what) {
+ case CURLUPART_SCHEME:
+ ptr = u->scheme;
+ ifmissing = CURLUE_NO_SCHEME;
+ urldecode = FALSE; /* never for schemes */
+ break;
+ case CURLUPART_USER:
+ ptr = u->user;
+ ifmissing = CURLUE_NO_USER;
+ break;
+ case CURLUPART_PASSWORD:
+ ptr = u->password;
+ ifmissing = CURLUE_NO_PASSWORD;
+ break;
+ case CURLUPART_OPTIONS:
+ ptr = u->options;
+ ifmissing = CURLUE_NO_OPTIONS;
+ break;
+ case CURLUPART_HOST:
+ ptr = u->host;
+ ifmissing = CURLUE_NO_HOST;
+ break;
+ case CURLUPART_PORT:
+ ptr = u->port;
+ ifmissing = CURLUE_NO_PORT;
+ urldecode = FALSE; /* never for port */
+ if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) {
+ /* there's no stored port number, but asked to deliver
+ a default one for the scheme */
+ const struct Curl_handler *h =
+ Curl_builtin_scheme(u->scheme);
+ if(h) {
+ snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ ptr = portbuf;
+ }
+ }
+ else if(ptr && u->scheme) {
+ /* there is a stored port number, but ask to inhibit if
+ it matches the default one for the scheme */
+ const struct Curl_handler *h =
+ Curl_builtin_scheme(u->scheme);
+ if(h && (h->defport == u->portnum) &&
+ (flags & CURLU_NO_DEFAULT_PORT))
+ ptr = NULL;
+ }
+ break;
+ case CURLUPART_PATH:
+ ptr = u->path;
+ if(!ptr) {
+ ptr = u->path = strdup("/");
+ if(!u->path)
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ break;
+ case CURLUPART_QUERY:
+ ptr = u->query;
+ ifmissing = CURLUE_NO_QUERY;
+ plusdecode = urldecode;
+ break;
+ case CURLUPART_FRAGMENT:
+ ptr = u->fragment;
+ ifmissing = CURLUE_NO_FRAGMENT;
+ break;
+ case CURLUPART_URL: {
+ char *url;
+ char *scheme;
+ char *options = u->options;
+ char *port = u->port;
+ if(u->scheme && strcasecompare("file", u->scheme)) {
+ url = aprintf("file://%s%s%s",
+ u->path,
+ u->fragment? "#": "",
+ u->fragment? u->fragment : "");
+ }
+ else if(!u->host)
+ return CURLUE_NO_HOST;
+ else {
+ const struct Curl_handler *h = NULL;
+ if(u->scheme)
+ scheme = u->scheme;
+ else if(flags & CURLU_DEFAULT_SCHEME)
+ scheme = (char *) DEFAULT_SCHEME;
+ else
+ return CURLUE_NO_SCHEME;
+
+ if(scheme) {
+ h = Curl_builtin_scheme(scheme);
+ if(!port && (flags & CURLU_DEFAULT_PORT)) {
+ /* there's no stored port number, but asked to deliver
+ a default one for the scheme */
+ if(h) {
+ snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ port = portbuf;
+ }
+ }
+ else if(port) {
+ /* there is a stored port number, but asked to inhibit if it matches
+ the default one for the scheme */
+ if(h && (h->defport == u->portnum) &&
+ (flags & CURLU_NO_DEFAULT_PORT))
+ port = NULL;
+ }
+ }
+ if(h && !(h->flags & PROTOPT_URLOPTIONS))
+ options = NULL;
+
+ url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ scheme,
+ u->user ? u->user : "",
+ u->password ? ":": "",
+ u->password ? u->password : "",
+ options ? ";" : "",
+ options ? options : "",
+ (u->user || u->password || options) ? "@": "",
+ u->host,
+ port ? ":": "",
+ port ? port : "",
+ (u->path && (u->path[0] != '/')) ? "/": "",
+ u->path ? u->path : "/",
+ u->query? "?": "",
+ u->query? u->query : "",
+ u->fragment? "#": "",
+ u->fragment? u->fragment : "");
+ }
+ if(!url)
+ return CURLUE_OUT_OF_MEMORY;
+ *part = url;
+ return CURLUE_OK;
+ break;
+ }
+ default:
+ ptr = NULL;
+ }
+ if(ptr) {
+ *part = strdup(ptr);
+ if(!*part)
+ return CURLUE_OUT_OF_MEMORY;
+ if(plusdecode) {
+ /* convert + to space */
+ char *plus;
+ for(plus = *part; *plus; ++plus) {
+ if(*plus == '+')
+ *plus = ' ';
+ }
+ }
+ if(urldecode) {
+ char *decoded;
+ size_t dlen;
+ CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE);
+ free(*part);
+ if(res) {
+ *part = NULL;
+ return CURLUE_URLDECODE;
+ }
+ *part = decoded;
+ }
+ return CURLUE_OK;
+ }
+ else
+ return ifmissing;
+}
+
+CURLUcode curl_url_set(CURLU *u, CURLUPart what,
+ const char *part, unsigned int flags)
+{
+ char **storep = NULL;
+ long port = 0;
+ bool urlencode = (flags & CURLU_URLENCODE)? 1 : 0;
+ bool plusencode = FALSE;
+ bool urlskipslash = FALSE;
+ bool appendquery = FALSE;
+
+ if(!u)
+ return CURLUE_BAD_HANDLE;
+ if(!part) {
+ /* setting a part to NULL clears it */
+ switch(what) {
+ case CURLUPART_URL:
+ break;
+ case CURLUPART_SCHEME:
+ storep = &u->scheme;
+ break;
+ case CURLUPART_USER:
+ storep = &u->user;
+ break;
+ case CURLUPART_PASSWORD:
+ storep = &u->password;
+ break;
+ case CURLUPART_OPTIONS:
+ storep = &u->options;
+ break;
+ case CURLUPART_HOST:
+ storep = &u->host;
+ break;
+ case CURLUPART_PORT:
+ storep = &u->port;
+ break;
+ case CURLUPART_PATH:
+ storep = &u->path;
+ break;
+ case CURLUPART_QUERY:
+ storep = &u->query;
+ break;
+ case CURLUPART_FRAGMENT:
+ storep = &u->fragment;
+ break;
+ default:
+ return CURLUE_UNKNOWN_PART;
+ }
+ if(storep && *storep) {
+ free(*storep);
+ *storep = NULL;
+ }
+ return CURLUE_OK;
+ }
+
+ switch(what) {
+ case CURLUPART_SCHEME:
+ if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
+ /* verify that it is a fine scheme */
+ !Curl_builtin_scheme(part))
+ return CURLUE_UNSUPPORTED_SCHEME;
+ storep = &u->scheme;
+ urlencode = FALSE; /* never */
+ break;
+ case CURLUPART_USER:
+ storep = &u->user;
+ break;
+ case CURLUPART_PASSWORD:
+ storep = &u->password;
+ break;
+ case CURLUPART_OPTIONS:
+ storep = &u->options;
+ break;
+ case CURLUPART_HOST:
+ storep = &u->host;
+ break;
+ case CURLUPART_PORT:
+ urlencode = FALSE; /* never */
+ port = strtol(part, NULL, 10); /* Port number must be decimal */
+ if((port <= 0) || (port > 0xffff))
+ return CURLUE_BAD_PORT_NUMBER;
+ storep = &u->port;
+ break;
+ case CURLUPART_PATH:
+ urlskipslash = TRUE;
+ storep = &u->path;
+ break;
+ case CURLUPART_QUERY:
+ plusencode = urlencode;
+ appendquery = (flags & CURLU_APPENDQUERY)?1:0;
+ storep = &u->query;
+ break;
+ case CURLUPART_FRAGMENT:
+ storep = &u->fragment;
+ break;
+ case CURLUPART_URL: {
+ /*
+ * Allow a new URL to replace the existing (if any) contents.
+ *
+ * If the existing contents is enough for a URL, allow a relative URL to
+ * replace it.
+ */
+ CURLUcode result;
+ char *oldurl;
+ char *redired_url;
+ CURLU *handle2;
+
+ if(Curl_is_absolute_url(part, NULL, MAX_SCHEME_LEN)) {
+ handle2 = curl_url();
+ if(!handle2)
+ return CURLUE_OUT_OF_MEMORY;
+ result = parseurl(part, handle2, flags);
+ if(!result)
+ mv_urlhandle(handle2, u);
+ else
+ curl_url_cleanup(handle2);
+ return result;
+ }
+ /* extract the full "old" URL to do the redirect on */
+ result = curl_url_get(u, CURLUPART_URL, &oldurl, flags);
+ if(result) {
+ /* couldn't get the old URL, just use the new! */
+ handle2 = curl_url();
+ if(!handle2)
+ return CURLUE_OUT_OF_MEMORY;
+ result = parseurl(part, handle2, flags);
+ if(!result)
+ mv_urlhandle(handle2, u);
+ else
+ curl_url_cleanup(handle2);
+ return result;
+ }
+
+ /* apply the relative part to create a new URL */
+ redired_url = Curl_concat_url(oldurl, part);
+ free(oldurl);
+ if(!redired_url)
+ return CURLUE_OUT_OF_MEMORY;
+
+ /* now parse the new URL */
+ handle2 = curl_url();
+ if(!handle2) {
+ free(redired_url);
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ result = parseurl(redired_url, handle2, flags);
+ free(redired_url);
+ if(!result)
+ mv_urlhandle(handle2, u);
+ else
+ curl_url_cleanup(handle2);
+ return result;
+ }
+ default:
+ return CURLUE_UNKNOWN_PART;
+ }
+ if(storep) {
+ const char *newp = part;
+ size_t nalloc = strlen(part);
+
+ if(urlencode) {
+ const char *i;
+ char *o;
+ bool free_part = FALSE;
+ char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
+ if(!enc)
+ return CURLUE_OUT_OF_MEMORY;
+ if(plusencode) {
+ /* space to plus */
+ i = part;
+ for(o = enc; *i; ++o, ++i)
+ *o = (*i == ' ') ? '+' : *i;
+ *o = 0; /* zero terminate */
+ part = strdup(enc);
+ if(!part) {
+ free(enc);
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ free_part = TRUE;
+ }
+ for(i = part, o = enc; *i; i++) {
+ if(Curl_isunreserved(*i) ||
+ ((*i == '/') && urlskipslash) ||
+ ((*i == '=') && appendquery) ||
+ ((*i == '+') && plusencode)) {
+ *o = *i;
+ o++;
+ }
+ else {
+ snprintf(o, 4, "%%%02x", *i);
+ o += 3;
+ }
+ }
+ *o = 0; /* zero terminate */
+ newp = enc;
+ if(free_part)
+ free((char *)part);
+ }
+ else {
+ char *p;
+ newp = strdup(part);
+ if(!newp)
+ return CURLUE_OUT_OF_MEMORY;
+ p = (char *)newp;
+ while(*p) {
+ /* make sure percent encoded are lower case */
+ if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) &&
+ (ISUPPER(p[1]) || ISUPPER(p[2]))) {
+ p[1] = (char)TOLOWER(p[1]);
+ p[2] = (char)TOLOWER(p[2]);
+ p += 3;
+ }
+ else
+ p++;
+ }
+ }
+
+ if(appendquery) {
+ /* Append the string onto the old query. Add a '&' separator if none is
+ present at the end of the exsting query already */
+ size_t querylen = u->query ? strlen(u->query) : 0;
+ bool addamperand = querylen && (u->query[querylen -1] != '&');
+ if(querylen) {
+ size_t newplen = strlen(newp);
+ char *p = malloc(querylen + addamperand + newplen + 1);
+ if(!p) {
+ free((char *)newp);
+ return CURLUE_OUT_OF_MEMORY;
+ }
+ strcpy(p, u->query); /* original query */
+ if(addamperand)
+ p[querylen] = '&'; /* ampersand */
+ strcpy(&p[querylen + addamperand], newp); /* new suffix */
+ free((char *)newp);
+ free(*storep);
+ *storep = p;
+ return CURLUE_OK;
+ }
+ }
+
+ free(*storep);
+ *storep = (char *)newp;
+ }
+ /* set after the string, to make it not assigned if the allocation above
+ fails */
+ if(port)
+ u->portnum = port;
+ return CURLUE_OK;
+}
#define RESP_TIMEOUT (1800*1000)
#include "cookie.h"
+#include "psl.h"
#include "formdata.h"
#ifdef HAVE_NETINET_IN_H
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */
-/* 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
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
-/* Some convenience macros to get the larger/smaller value out of two given.
- We prefix with CURL to prevent name collisions. */
-#define CURLMAX(x,y) ((x)>(y)?(x):(y))
-#define CURLMIN(x,y) ((x)<(y)?(x):(y))
-
#ifdef HAVE_GSSAPI
/* Types needed for krb5-ftp connections */
struct krb5buffer {
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
char *cipher_list; /* list of ciphers to use */
+ char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
};
struct ssl_config_data {
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
-#ifdef CURLRES_ASYNCH
struct Curl_async {
char *hostname;
int port;
int status; /* if done is TRUE, this is the status from the callback */
void *os_specific; /* 'struct thread_data' for Windows */
};
-#endif
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
UPGR101_WORKING /* talking upgraded protocol */
};
+struct dohresponse {
+ unsigned char *memory;
+ size_t size;
+};
+
+/* one of these for each DoH request */
+struct dnsprobe {
+ CURL *easy;
+ int dnstype;
+ unsigned char dohbuffer[512];
+ size_t dohlen;
+ struct dohresponse serverdoh;
+};
+
+struct dohdata {
+ struct curl_slist *headers;
+ struct dnsprobe probe[2];
+ unsigned int pending; /* still outstanding requests */
+ const char *host;
+ int port;
+};
+
/*
* Request specific data in the easy handle (Curl_easy). Previously,
* these members were on the connectdata struct but since a conn struct may
void *protop; /* Allocated protocol-specific data. Each protocol
handler makes sure this points to data it needs. */
+ struct dohdata doh; /* DoH specific data for this request */
};
/*
*/
CURLcode (*connect_it)(struct connectdata *, bool *done);
- /* See above. Currently only used for FTP. */
+ /* See above. */
CURLcode (*connecting)(struct connectdata *, bool *done);
CURLcode (*doing)(struct connectdata *, bool *done);
#define CONNCHECK_NONE 0 /* No checks */
#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */
+#define CONNCHECK_KEEPALIVE (1<<1) /* Perform any keepalive function. */
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
void *closesocket_client;
- bool inuse; /* This is a marker for the connection cache logic. If this is
- TRUE this handle is being used by one or more easy handles
- and can only used by any other easy handle without careful
- consideration (== only for pipelining/multiplexing) and it
- cannot be used by another multi handle! */
+ /* This is used by the connection cache logic. If this returns TRUE, this
+ handle is being used by one or more easy handles and can only used by any
+ other easy handle without careful consideration (== only for
+ pipelining/multiplexing) and it cannot be used by another multi
+ handle! */
+#define CONN_INUSE(c) ((c)->send_pipe.size + (c)->recv_pipe.size)
/**** Fields set when inited and not modified again */
long connection_id; /* Contains a unique number to make it easier to
long ip_version; /* copied from the Curl_easy at creation time */
+ /* Protocols can use a custom keepalive mechanism to keep connections alive.
+ This allows those protocols to track the last time the keepalive mechanism
+ was used on this connection. */
+ struct curltime keepalive;
+
+ long upkeep_interval_ms; /* Time between calls for connection upkeep. */
+
/**** curl_get() phase fields */
curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
#endif
char syserr_buf [256]; /* buffer for Curl_strerror() */
-
-#ifdef CURLRES_ASYNCH
/* data used for the asynch name resolve callback */
struct Curl_async async;
-#endif
/* These three are used for chunked-encoding trailer support */
char *trailer; /* allocated buffer to store trailer in */
expire_id eid;
};
+/* individual pieces of the URL */
+struct urlpieces {
+ char *scheme;
+ char *hostname;
+ char *port;
+ char *user;
+ char *password;
+ char *options;
+ char *path;
+ char *query;
+};
+
struct UrlState {
/* Points to the connection cache */
size_t headersize; /* size of the allocation */
char *buffer; /* download buffer */
- char uploadbuffer[UPLOAD_BUFSIZE + 1]; /* upload buffer */
+ char *ulbuf; /* allocated upload buffer or NULL */
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
void *resolver; /* resolver state, if it is used in the URL state -
ares_channel f.e. */
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */
void *engine;
#endif /* USE_OPENSSL */
involved in this request */
bool expect100header; /* TRUE if we added Expect: 100-continue */
- bool pipe_broke; /* TRUE if the connection we were pipelined on broke
- and we need to restart from the beginning */
-
#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
!defined(__SYMBIAN32__)
/* do FTP line-end conversions on most platforms */
/* for FTP downloads: how many CRLFs did we converted to LFs? */
curl_off_t crlf_conversions;
#endif
- char *pathbuffer;/* allocated buffer to store the URL's path part in */
- char *path; /* path to use, points to somewhere within the pathbuffer
- area */
bool slash_removed; /* set TRUE if the 'path' points to a path where the
initial URL slash separator has been taken off */
bool use_range;
#ifdef CURLDEBUG
bool conncache_lock;
#endif
+ CURLU *uh; /* URL handle for the current parsed URL */
+ struct urlpieces up;
};
char *url; /* work URL, copied from UserDefined */
bool url_alloc; /* URL string is malloc()'ed */
char *referer; /* referer string */
- bool referer_alloc; /* referer sting is malloc()ed */
+ bool referer_alloc; /* referer string is malloc()ed */
struct curl_slist *cookielist; /* list of cookie files set by
curl_easy_setopt(COOKIEFILE) calls */
struct curl_slist *resolve; /* set to point to the set.resolve list when
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_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */
+ STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */
STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
STRING_USERAGENT, /* User-Agent string */
STRING_SSL_CRLFILE_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_SSL_ENGINE, /* name of ssl engine */
STRING_USERNAME, /* <username>, if used */
STRING_PASSWORD, /* <password>, if used */
STRING_OPTIONS, /* <options>, if used */
STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
#endif
STRING_TARGET, /* CURLOPT_REQUEST_TARGET */
+ STRING_DOH, /* CURLOPT_DOH_URL */
/* -- end of zero-terminated strings -- */
STRING_LASTZEROTERMINATED,
- /* -- below this are pointers to binary data that cannot be strdup'ed.
- Each such pointer must be added manually to Curl_dupset() --- */
+ /* -- below this are pointers to binary data that cannot be strdup'ed. --- */
STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
STRING_LAST /* not used, just an end-of-list marker */
};
+/* callback that gets called when this easy handle is completed within a multi
+ handle. Only used for internally created transfers, like for example
+ DoH. */
+typedef int (*multidone_func)(struct Curl_easy *easy, CURLcode result);
+
struct UserDefined {
FILE *err; /* the stderr user data goes here */
void *debugdata; /* the data that will be passed to fdebug */
curl_proxytype proxytype; /* what kind of proxy that is in use */
long dns_cache_timeout; /* DNS cache timeout */
long buffer_size; /* size of receive buffer to use */
+ size_t upload_buffer_size; /* size of upload buffer to use,
+ keep it >= CURL_MAX_WRITE_SIZE */
void *private_data; /* application-private data */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
/* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially
and they don't change during operations. */
-
- bool printhost; /* printing host name in debug info */
bool get_filetime; /* get the time and get of the remote file */
bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */
bool prefer_ascii; /* ASCII rather than binary */
bool stream_depends_e; /* set or don't set the Exclusive bit */
int stream_weight;
- bool haproxyprotocol; /* whether to send HAProxy PROXY protocol header */
+ bool haproxyprotocol; /* whether to send HAProxy PROXY protocol v1 header */
struct Curl_http2_dep *stream_dependents;
curl_resolver_start_callback resolver_start; /* optional callback called
before resolver start */
void *resolver_start_client; /* pointer to pass to resolver start callback */
+ bool disallow_username_in_url; /* disallow username in url */
+ long upkeep_interval_ms; /* Time between calls for connection upkeep. */
+ bool doh; /* DNS-over-HTTPS enabled */
+ bool doh_get; /* use GET for DoH requests, instead of POST */
+ multidone_func fmultidone;
+ struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
};
struct Names {
struct to which this "belongs" when used
by the easy interface */
struct Curl_share *share; /* Share, handles global variable mutexing */
+#ifdef USE_LIBPSL
+ struct PslCache *psl; /* The associated PSL cache. */
+#endif
struct SingleRequest req; /* Request-specific data */
struct UserDefined set; /* values set by the libcurl user */
struct DynamicStatic change; /* possibly modified userdefined data */
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen [out] - The length of the output message.
plen = strlen(passwdp);
/* Compute binary message length. Check for overflows. */
- if((ulen > SIZE_T_MAX/2) || (plen > (SIZE_T_MAX/2 - 2)))
+ if((ulen > SIZE_T_MAX/4) || (plen > (SIZE_T_MAX/2 - 2)))
return CURLE_OUT_OF_MEMORY;
plainlen = 2 * ulen + plen + 2;
* data [in] - The session handle.
* chlg [in] - The challenge.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen [out] - The length of the output message.
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
/* Perform quoted-string escaping as described in RFC2616 and its errata */
static char *auth_digest_string_quoted(const char *source)
{
- char *dest, *d;
+ char *dest;
const char *s = source;
size_t n = 1; /* null terminator */
dest = malloc(n);
if(dest) {
+ char *d = dest;
s = source;
- d = dest;
while(*s) {
if(*s == '"' || *s == '\\') {
*d++ = '\\';
* data [in] - The session handle.
* chlg64 [in] - The base64 encoded challenge message.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* request [in] - The HTTP request.
* uripath [in] - The path of the HTTP uri.
* digest [in/out] - The digest data struct being used and modified.
unsigned char ha1[65]; /* 64 digits and 1 zero byte */
unsigned char ha2[65]; /* 64 digits and 1 zero byte */
char userh[65];
- char cnoncebuf[33];
char *cnonce = NULL;
size_t cnonce_sz = 0;
char *userp_quoted;
digest->nc = 1;
if(!digest->cnonce) {
+ char cnoncebuf[33];
result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
sizeof(cnoncebuf));
if(result)
*/
hashthis = (unsigned char *) aprintf("%s:%s", request, uripath);
+ if(!hashthis)
+ return CURLE_OUT_OF_MEMORY;
if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
/* We don't support auth-int for PUT or POST at the moment.
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* request [in] - The HTTP request.
* uripath [in] - The path of the HTTP uri.
* digest [in/out] - The digest data struct being used and modified.
* data [in] - The session handle.
* chlg64 [in] - The base64 encoded challenge message.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* request [in] - The HTTP request.
* uripath [in] - The path of the HTTP uri.
* digest [in/out] - The digest data struct being used and modified.
*
* data [in] - The session handle.
* userp [in] - The user name.
- * passdwp [in] - The user's password.
+ * passwdp [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 specifying whether or not mutual authentication
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [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 specifying whether or not mutual authentication
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
*
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * passwdp [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* chlg64 [in] - The optional base64 encoded challenge message.
* Parameters:
*
* data [in] - The session handle.
- * userp [in] - The user name in the format User or Domain\User.
- * passdwp [in] - The user's password.
+ * user [in] - The user name in the format User or Domain\User.
+ * password [in] - The user's password.
* service [in] - The service type such as http, smtp, pop or imap.
* host [in] - The host name.
* chlg64 [in] - The optional base64 encoded challenge message.
#ifdef HAVE_BROTLI
version_info.brotli_ver_num = BrotliDecoderVersion();
- brotli_version(brotli_buffer, sizeof brotli_buffer);
+ brotli_version(brotli_buffer, sizeof(brotli_buffer));
version_info.brotli_version = brotli_buffer;
#endif
#include "curl_setup.h"
#ifdef USE_AXTLS
+
+#error axTLS support has been disabled in curl due to doubts about quality,
+#error user dedication and a lack of use/testing. We urge users to consider
+#error using a more established TLS backend instead.
+
#include <axTLS/config.h>
#include <axTLS/ssl.h>
#include "axtls.h"
#endif /* USE_AXTLS */
#endif /* HEADER_CURL_AXTLS_H */
-
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
}
- memset(&x509_parsed, 0, sizeof x509_parsed);
+ memset(&x509_parsed, 0, sizeof(x509_parsed));
if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
return CURLE_FAILED_INIT;
if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
return CURLE_FAILED_INIT;
+ if(FreeRng(&rng))
+ return CURLE_FAILED_INIT;
return CURLE_OK;
}
#define CURL_BUILD_IOS 0
#define CURL_BUILD_IOS_7 0
+#define CURL_BUILD_IOS_9 0
#define CURL_BUILD_IOS_11 0
#define CURL_BUILD_MAC 1
/* This is the maximum API level we are allowed to use when building: */
#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
+#define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
/* These macros mean "the following code is present to allow runtime backward
compatibility with at least this cat or earlier":
#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
#define CURL_BUILD_IOS 1
#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
+#define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
#define CURL_BUILD_MAC 0
#define CURL_BUILD_MAC_10_5 0
#define CURL_BUILD_MAC_10_7 0
#define CURL_BUILD_MAC_10_8 0
#define CURL_BUILD_MAC_10_9 0
+#define CURL_BUILD_MAC_10_11 0
#define CURL_BUILD_MAC_10_13 0
#define CURL_SUPPORT_MAC_10_5 0
#define CURL_SUPPORT_MAC_10_6 0
#include "vtls.h"
#include "darwinssl.h"
#include "curl_printf.h"
+#include "strdup.h"
#include "curl_memory.h"
/* The last #include file should be: */
if(!c) {
failf(data, "SSL: invalid CA certificate subject");
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_SSL_CACERT;
}
/* If the subject is already available as UTF-8 encoded (ie 'direct') then
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_3:
/* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
- /* We can assume __builtin_available() will always work in the
- 10.13/11.0 SDK: */
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
*darwinver = kTLSProtocol13;
return CURLE_OK;
}
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+ HAVE_BUILTIN_AVAILABLE == 1 */
break;
}
return CURLE_SSL_CONNECT_ERROR;
/* macOS 10.5-10.7 supported TLS 1.0 only.
macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
}
}
#else
max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+ HAVE_BUILTIN_AVAILABLE == 1 */
switch(ssl_version) {
case CURL_SSLVERSION_DEFAULT:
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version << 16;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
ssl_version_max = max_supported_version_by_os;
break;
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
(void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
(void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13);
}
}
#else
(void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+ HAVE_BUILTIN_AVAILABLE == 1 */
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
}
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+ if(conn->bits.tls_enable_alpn) {
+ if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+ CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
+ &kCFTypeArrayCallBacks);
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+ (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+ CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ /* expects length prefixed preference ordered list of protocols in wire
+ * format
+ */
+ err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr);
+ if(err != noErr)
+ infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n",
+ err);
+ CFRelease(alpnArr);
+ }
+ }
+#endif
+
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");
}
CFRelease(cert);
+ if(result == CURLE_SSL_CACERT)
+ return CURLE_SSL_CERTPROBLEM;
if(result)
return result;
}
higher priority, but it's probably better that we not connect at all than
to give the user a false sense of security if the server only supports
insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
- (void)SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count);
+ err = SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count);
+ if(err != noErr) {
+ failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
+ err);
+ return CURLE_SSL_CIPHER;
+ }
all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
- if(all_ciphers && allowed_ciphers &&
- SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
- &all_ciphers_count) == noErr) {
- for(i = 0UL ; i < all_ciphers_count ; i++) {
-#if CURL_BUILD_MAC
- /* There's a known bug in early versions of Mountain Lion where ST's ECC
- ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
- Work around the problem here by disabling those ciphers if we are
- running in an affected version of OS X. */
- if(darwinver_maj == 12 && darwinver_min <= 3 &&
- all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
- continue;
- }
-#endif /* CURL_BUILD_MAC */
- switch(all_ciphers[i]) {
- /* Disable NULL ciphersuites: */
- case SSL_NULL_WITH_NULL_NULL:
- case SSL_RSA_WITH_NULL_MD5:
- case SSL_RSA_WITH_NULL_SHA:
- case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
- case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
- case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
- case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
- case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
- case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
- case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
- case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
- case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
- case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
- case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
- case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
- case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
- case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
- case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
- /* Disable anonymous ciphersuites: */
- case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
- case SSL_DH_anon_WITH_RC4_128_MD5:
- case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_anon_WITH_DES_CBC_SHA:
- case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
- case TLS_DH_anon_WITH_AES_128_CBC_SHA:
- case TLS_DH_anon_WITH_AES_256_CBC_SHA:
- case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
- case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
- case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
- case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
- case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
- case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
- case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
- case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
- case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
- /* Disable weak key ciphersuites: */
- case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
- case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
- case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
- case SSL_RSA_WITH_DES_CBC_SHA:
- case SSL_DH_DSS_WITH_DES_CBC_SHA:
- case SSL_DH_RSA_WITH_DES_CBC_SHA:
- case SSL_DHE_DSS_WITH_DES_CBC_SHA:
- case SSL_DHE_RSA_WITH_DES_CBC_SHA:
- /* Disable IDEA: */
- case SSL_RSA_WITH_IDEA_CBC_SHA:
- case SSL_RSA_WITH_IDEA_CBC_MD5:
- /* Disable RC4: */
- case SSL_RSA_WITH_RC4_128_MD5:
- case SSL_RSA_WITH_RC4_128_SHA:
- case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
- case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
- case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
- case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
- case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
- case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
- case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
- break;
- default: /* enable everything else */
- allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
- break;
- }
- }
- err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
- allowed_ciphers_count);
- if(err != noErr) {
- failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
- return CURLE_SSL_CONNECT_ERROR;
- }
+ if(!all_ciphers) {
+ failf(data, "SSL: Failed to allocate memory for all ciphers");
+ return CURLE_OUT_OF_MEMORY;
}
- else {
+ allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
+ if(!allowed_ciphers) {
Curl_safefree(all_ciphers);
- Curl_safefree(allowed_ciphers);
failf(data, "SSL: Failed to allocate memory for allowed ciphers");
return CURLE_OUT_OF_MEMORY;
}
+ err = SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
+ &all_ciphers_count);
+ if(err != noErr) {
+ Curl_safefree(all_ciphers);
+ Curl_safefree(allowed_ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ for(i = 0UL ; i < all_ciphers_count ; i++) {
+#if CURL_BUILD_MAC
+ /* There's a known bug in early versions of Mountain Lion where ST's ECC
+ ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
+ Work around the problem here by disabling those ciphers if we are
+ running in an affected version of OS X. */
+ if(darwinver_maj == 12 && darwinver_min <= 3 &&
+ all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
+ continue;
+ }
+#endif /* CURL_BUILD_MAC */
+ switch(all_ciphers[i]) {
+ /* Disable NULL ciphersuites: */
+ case SSL_NULL_WITH_NULL_NULL:
+ case SSL_RSA_WITH_NULL_MD5:
+ case SSL_RSA_WITH_NULL_SHA:
+ case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
+ case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
+ case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
+ case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
+ case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
+ case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
+ case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
+ case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
+ case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
+ case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
+ case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
+ case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
+ case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
+ case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
+ case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
+ /* Disable anonymous ciphersuites: */
+ case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
+ case SSL_DH_anon_WITH_RC4_128_MD5:
+ case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_anon_WITH_DES_CBC_SHA:
+ case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_128_CBC_SHA:
+ case TLS_DH_anon_WITH_AES_256_CBC_SHA:
+ case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
+ case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
+ case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
+ case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+ case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
+ case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
+ case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
+ case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
+ case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
+ /* Disable weak key ciphersuites: */
+ case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
+ case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
+ case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ case SSL_DH_DSS_WITH_DES_CBC_SHA:
+ case SSL_DH_RSA_WITH_DES_CBC_SHA:
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ /* Disable IDEA: */
+ case SSL_RSA_WITH_IDEA_CBC_SHA:
+ case SSL_RSA_WITH_IDEA_CBC_MD5:
+ /* Disable RC4: */
+ case SSL_RSA_WITH_RC4_128_MD5:
+ case SSL_RSA_WITH_RC4_128_SHA:
+ case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
+ case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
+ case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
+ case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
+ case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
+ case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
+ case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
+ break;
+ default: /* enable everything else */
+ allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
+ break;
+ }
+ }
+ err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
+ allowed_ciphers_count);
Curl_safefree(all_ciphers);
Curl_safefree(allowed_ciphers);
+ if(err != noErr) {
+ failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
+ return CURLE_SSL_CIPHER;
+ }
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
/* We want to enable 1/n-1 when using a CBC cipher unless the user
if(len + n >= cap) {
cap *= 2;
- data = realloc(data, cap);
+ data = Curl_saferealloc(data, cap);
if(!data) {
close(fd);
return -1;
return 0;
}
-static int sslerr_to_curlerr(struct Curl_easy *data, int err)
-{
- switch(err) {
- case errSSLXCertChainInvalid:
- failf(data, "SSL certificate problem: Invalid certificate chain");
- return CURLE_SSL_CACERT;
- case errSSLUnknownRootCert:
- failf(data, "SSL certificate problem: Untrusted root certificate");
- return CURLE_SSL_CACERT;
- case errSSLNoRootCert:
- failf(data, "SSL certificate problem: No root certificate");
- return CURLE_SSL_CACERT;
- case errSSLCertExpired:
- failf(data, "SSL certificate problem: Certificate chain had an "
- "expired certificate");
- return CURLE_SSL_CACERT;
- case errSSLBadCert:
- failf(data, "SSL certificate problem: Couldn't understand the server "
- "certificate format");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLHostNameMismatch:
- failf(data, "SSL certificate peer hostname mismatch");
- return CURLE_PEER_FAILED_VERIFICATION;
- default:
- failf(data, "SSL unexpected certificate error %d", err);
- return CURLE_SSL_CACERT;
- }
-}
-
static int append_cert_to_array(struct Curl_easy *data,
unsigned char *buf, size_t buflen,
CFMutableArrayRef array)
CFRelease(certdata);
if(!cacert) {
failf(data, "SSL: failed to create SecCertificate from CA certificate");
- return CURLE_SSL_CACERT;
+ return CURLE_SSL_CACERT_BADFILE;
}
/* Check if cacert is valid. */
result = CopyCertSubject(data, cacert, &certp);
- if(result)
- return result;
+ switch(result) {
+ case CURLE_OK:
+ break;
+ case CURLE_PEER_FAILED_VERIFICATION:
+ return CURLE_SSL_CACERT_BADFILE;
+ case CURLE_OUT_OF_MEMORY:
+ default:
+ return result;
+ }
free(certp);
CFArrayAppendValue(array, cacert);
if(read_cert(cafile, &certbuf, &buflen) < 0) {
failf(data, "SSL: failed to read or invalid CA certificate");
- return CURLE_SSL_CACERT;
+ return CURLE_SSL_CACERT_BADFILE;
}
/*
CFRelease(array);
failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle",
n, offset);
- return CURLE_SSL_CACERT;
+ return CURLE_SSL_CACERT_BADFILE;
}
offset += res;
if(trust == NULL) {
failf(data, "SSL: error getting certificate chain");
CFRelease(array);
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
else if(ret != noErr) {
CFRelease(array);
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SSLCopyPeerTrust() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
ret = SecTrustSetAnchorCertificates(trust, array);
if(ret != noErr) {
+ CFRelease(array);
CFRelease(trust);
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
ret = SecTrustSetAnchorCertificatesOnly(trust, true);
if(ret != noErr) {
+ CFRelease(array);
CFRelease(trust);
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
SecTrustResultType trust_eval = 0;
CFRelease(array);
CFRelease(trust);
if(ret != noErr) {
- return sslerr_to_curlerr(data, ret);
+ failf(data, "SecTrustEvaluate() returned error %d", ret);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
switch(trust_eval) {
/* the documentation says we need to call SSLHandshake() again */
return darwinssl_connect_step2(conn, sockindex);
+ /* Problem with encrypt / decrypt */
+ case errSSLPeerDecodeError:
+ failf(data, "Decode failed");
+ break;
+ case errSSLDecryptionFail:
+ case errSSLPeerDecryptionFail:
+ failf(data, "Decryption failed");
+ break;
+ case errSSLPeerDecryptError:
+ failf(data, "A decryption error occurred");
+ break;
+ case errSSLBadCipherSuite:
+ failf(data, "A bad SSL cipher suite was encountered");
+ break;
+ case errSSLCrypto:
+ failf(data, "An underlying cryptographic error was encountered");
+ break;
+#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
+ case errSSLWeakPeerEphemeralDHKey:
+ failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
+ break;
+#endif
+
+ /* Problem with the message record validation */
+ case errSSLBadRecordMac:
+ case errSSLPeerBadRecordMac:
+ failf(data, "A record with a bad message authentication code (MAC) "
+ "was encountered");
+ break;
+ case errSSLRecordOverflow:
+ case errSSLPeerRecordOverflow:
+ failf(data, "A record overflow occurred");
+ break;
+
+ /* Problem with zlib decompression */
+ case errSSLPeerDecompressFail:
+ failf(data, "Decompression failed");
+ break;
+
+ /* Problem with access */
+ case errSSLPeerAccessDenied:
+ failf(data, "Access was denied");
+ break;
+ case errSSLPeerInsufficientSecurity:
+ failf(data, "There is insufficient security for this operation");
+ break;
+
/* These are all certificate problems with the server: */
case errSSLXCertChainInvalid:
failf(data, "SSL certificate problem: Invalid certificate chain");
case errSSLNoRootCert:
failf(data, "SSL certificate problem: No root certificate");
return CURLE_SSL_CACERT;
+ case errSSLCertNotYetValid:
+ failf(data, "SSL certificate problem: The certificate chain had a "
+ "certificate that is not yet valid");
+ return CURLE_SSL_CACERT;
case errSSLCertExpired:
+ case errSSLPeerCertExpired:
failf(data, "SSL certificate problem: Certificate chain had an "
"expired certificate");
return CURLE_SSL_CACERT;
case errSSLBadCert:
+ case errSSLPeerBadCert:
failf(data, "SSL certificate problem: Couldn't understand the server "
"certificate format");
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CACERT;
+ case errSSLPeerUnsupportedCert:
+ failf(data, "SSL certificate problem: An unsupported certificate "
+ "format was encountered");
+ return CURLE_SSL_CACERT;
+ case errSSLPeerCertRevoked:
+ failf(data, "SSL certificate problem: The certificate was revoked");
+ return CURLE_SSL_CACERT;
+ case errSSLPeerCertUnknown:
+ failf(data, "SSL certificate problem: The certificate is unknown");
+ return CURLE_SSL_CACERT;
/* These are all certificate problems with the client: */
case errSecAuthFailed:
failf(data, "SSL authentication failed");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLPeerHandshakeFail:
failf(data, "SSL peer handshake failed, the server most likely "
"requires a client certificate to connect");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLPeerUnknownCA:
failf(data, "SSL server rejected the client certificate due to "
"the certificate being signed by an unknown certificate "
"authority");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
/* This error is raised if the server's cert didn't match the server's
host name: */
"certificate did not match \"%s\"\n", conn->host.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
+ /* Problem with SSL / TLS negotiation */
+ case errSSLNegotiation:
+ failf(data, "Could not negotiate an SSL cipher suite with the server");
+ break;
+ case errSSLBadConfiguration:
+ failf(data, "A configuration error occurred");
+ break;
+ case errSSLProtocol:
+ failf(data, "SSL protocol error");
+ break;
+ case errSSLPeerProtocolVersion:
+ failf(data, "A bad protocol version was encountered");
+ break;
+ case errSSLPeerNoRenegotiation:
+ failf(data, "No renegotiation is allowed");
+ break;
+
/* Generic handshake errors: */
case errSSLConnectionRefused:
failf(data, "Server dropped the connection during the SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLClosedAbort:
failf(data, "Server aborted the SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
- case errSSLNegotiation:
- failf(data, "Could not negotiate an SSL cipher suite with the server");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
+ case errSSLClosedGraceful:
+ failf(data, "The connection closed gracefully");
+ break;
+ case errSSLClosedNoNotify:
+ failf(data, "The server closed the session with no notification");
+ break;
/* Sometimes paramErr happens with buggy ciphers: */
- case paramErr: case errSSLInternal:
+ case paramErr:
+ case errSSLInternal:
+ case errSSLPeerInternalError:
failf(data, "Internal SSL engine error encountered during the "
"SSL handshake");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
case errSSLFatalAlert:
failf(data, "Fatal SSL engine error encountered during the SSL "
"handshake");
- return CURLE_SSL_CONNECT_ERROR;
+ break;
+ /* Unclassified error */
+ case errSSLBufferOverflow:
+ failf(data, "An insufficient buffer was provided");
+ break;
+ case errSSLIllegalParam:
+ failf(data, "An illegal parameter was encountered");
+ break;
+ case errSSLModuleAttach:
+ failf(data, "Module attach failure");
+ break;
+ case errSSLSessionNotFound:
+ failf(data, "An attempt to restore an unknown session failed");
+ break;
+ case errSSLPeerExportRestriction:
+ failf(data, "An export restriction occurred");
+ break;
+ case errSSLPeerUserCancelled:
+ failf(data, "The user canceled the operation");
+ break;
+ case errSSLPeerUnexpectedMsg:
+ failf(data, "Peer rejected unexpected message");
+ break;
+#if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
+ /* Treaing non-fatal error as fatal like before */
+ case errSSLClientHelloReceived:
+ failf(data, "A non-fatal result for providing a server name "
+ "indication");
+ break;
+#endif
+
+ /* Error codes defined in the enum but should never be returned.
+ We list them here just in case. */
+#if CURL_BUILD_MAC_10_6
+ /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
+ case errSSLClientCertRequested:
+ failf(data, "The server has requested a client certificate");
+ break;
+#endif
+#if CURL_BUILD_MAC_10_9
+ /* Alias for errSSLLast, end of error range */
+ case errSSLUnexpectedRecord:
+ failf(data, "Unexpected (skipped) record in DTLS");
+ break;
+#endif
default:
+ /* May also return codes listed in Security Framework Result Codes */
failf(data, "Unknown SSL protocol error in connection to %s:%d",
hostname, err);
- return CURLE_SSL_CONNECT_ERROR;
+ break;
}
+ return CURLE_SSL_CONNECT_ERROR;
}
else {
/* we have been connected fine, we're not waiting for anything else. */
break;
}
+#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+ if(conn->bits.tls_enable_alpn) {
+ if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+ CFArrayRef alpnArr = NULL;
+ CFStringRef chosenProtocol = NULL;
+ err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr);
+
+ if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
+ chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
+
+#ifdef USE_NGHTTP2
+ if(chosenProtocol &&
+ !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID),
+ 0)) {
+ conn->negnpn = CURL_HTTP_VERSION_2;
+ }
+ else
+#endif
+ if(chosenProtocol &&
+ !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ else
+ infof(data, "ALPN, server did not agree to a protocol\n");
+
+ /* chosenProtocol is a reference to the string within alpnArr
+ and doesn't need to be freed separately */
+ if(alpnArr)
+ CFRelease(alpnArr);
+ }
+ }
+#endif
+
return CURLE_OK;
}
}
GSKit tokens are always shorter than their cipher names, allocated buffers
will always be large enough to accommodate the result. */
l = strlen(cipherlist) + 1;
- memset((char *) ciphers, 0, sizeof ciphers);
+ memset((char *) ciphers, 0, sizeof(ciphers));
for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
ciphers[i].buf = malloc(l);
if(!ciphers[i].buf) {
lfd = socket(AF_INET, SOCK_STREAM, 0);
if(lfd < 0)
return -1;
- memset((char *) &addr1, 0, sizeof addr1);
+ 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) ||
+ if(bind(lfd, (struct sockaddr *) &addr1, sizeof(addr1)) ||
listen(lfd, 2) < 0) {
close(lfd);
return -1;
}
/* Get the allocated port. */
- len = sizeof addr1;
+ len = sizeof(addr1);
if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 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 &&
+ if(connect(cfd, (struct sockaddr *) &addr1, sizeof(addr1)) < 0 &&
errno != EINPROGRESS) {
close(lfd);
close(cfd);
}
/* Get the client dynamic port for intrusion check below. */
- len = sizeof addr2;
+ len = sizeof(addr2);
if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
close(lfd);
close(cfd);
/* Accept the incoming connection and get the server socket. */
curlx_nonblock(lfd, TRUE);
for(;;) {
- len = sizeof addr1;
+ len = sizeof(addr1);
sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
if(sfd < 0) {
close(lfd);
/* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0;
i = gsk_secure_soc_read(connproxyssl->backend->handle,
- buf, sizeof buf, &n);
+ buf, sizeof(buf), &n);
switch(i) {
case GSK_OK:
if(n) {
if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
FD_ISSET(conn->sock[sockindex], &fds_write)) {
/* Pipe data to HTTPS proxy. */
- n = read(BACKEND->remotefd, buf, sizeof buf);
+ n = read(BACKEND->remotefd, buf, sizeof(buf));
if(n < 0)
return -1;
if(n) {
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;
BACKEND->localfd = sockpair[0];
BACKEND->remotefd = sockpair[1];
setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
- (void *) sobufsize, sizeof sobufsize);
+ (void *) sobufsize, sizeof(sobufsize));
curlx_nonblock(BACKEND->localfd, TRUE);
curlx_nonblock(BACKEND->remotefd, TRUE);
}
if(!result) {
/* Start handshake. Try asynchronous first. */
- memset(&commarea, 0, sizeof commarea);
+ memset(&commarea, 0, sizeof(commarea));
BACKEND->iocport = QsoCreateIOCompletionPort();
if(BACKEND->iocport != -1) {
result = gskit_status(data,
static size_t Curl_gskit_version(char *buffer, size_t size)
{
- strncpy(buffer, "GSKit", size);
- return strlen(buffer);
+ return snprintf(buffer, size, "GSKit");
}
return 0; /* connection has been closed */
err = 0;
- errlen = sizeof err;
+ errlen = sizeof(err);
if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
(unsigned char *) &err, &errlen) ||
- errlen != sizeof err || err)
+ errlen != sizeof(err) || err)
return 0; /* connection has been closed */
return -1; /* connection status unknown */
# endif
#endif
+#if (GNUTLS_VERSION_NUMBER >= 0x030603)
+#define HAS_TLS13
+#endif
+
#ifdef HAS_OCSP
# include <gnutls/ocsp.h>
#endif
switch(ssl_version_max) {
case CURL_SSLVERSION_MAX_NONE:
- ssl_version_max = ssl_version << 16;
- break;
case CURL_SSLVERSION_MAX_DEFAULT:
+#ifdef HAS_TLS13
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
+#endif
ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
break;
}
protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
break;
case CURL_SSLVERSION_TLSv1_3:
+#ifdef HAS_TLS13
+ protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_3;
+ break;
+#else
failf(data, "GnuTLS: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
+#endif
}
}
return CURLE_OK;
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;
+ ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
}
switch(ssl_version | ssl_version_max) {
case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
"+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;
"+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;
+ case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
+#ifdef HAS_TLS13
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.3:" GNUTLS_SRP;
+ return CURLE_OK;
+#else
+ failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
+#endif
+ 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:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.1:+VERS-TLS1.2:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+ "+VERS-TLS1.2:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
+ return CURLE_OK;
}
failf(data, "GnuTLS: cannot set ssl protocol");
protocol_priority[0] = GNUTLS_TLS1_0;
protocol_priority[1] = GNUTLS_TLS1_1;
protocol_priority[2] = GNUTLS_TLS1_2;
+#ifdef HAS_TLS13
+ protocol_priority[3] = GNUTLS_TLS1_3;
+#endif
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_SSLv3:
prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
- sni = false;
break;
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
+ prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:"
+#ifdef HAS_TLS13
+ "+VERS-TLS1.3:"
+#endif
+ GNUTLS_SRP;
break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
return CURLE_SSL_INVALIDCERTSTATUS;
}
- rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
- &status, NULL, NULL, NULL, &reason);
+ (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
+ &status, NULL, NULL, NULL, &reason);
switch(status) {
case GNUTLS_OCSP_CERT_GOOD:
ssize_t result;
int retval = 0;
struct Curl_easy *data = conn->data;
- int done = 0;
+ bool done = FALSE;
char buf[120];
/* This has only been tested on the proftpd server, and the mod_tls code
case 0:
/* This is the expected response. There was no data but only
the close notify alert */
- done = 1;
+ done = TRUE;
break;
case GNUTLS_E_AGAIN:
case GNUTLS_E_INTERRUPTED:
break;
default:
retval = -1;
- done = 1;
+ done = TRUE;
break;
}
}
else if(0 == what) {
/* timeout */
failf(data, "SSL shutdown timeout");
- done = 1;
- break;
+ done = TRUE;
}
else {
/* anything that gets here is fatally bad */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
retval = -1;
- done = 1;
+ done = TRUE;
}
}
gnutls_deinit(BACKEND->session);
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;
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com>
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, 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.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for all MesaLink-specific code for the TLS/SSL layer. No code
+ * but vtls.c should ever call or use these functions.
+ *
+ */
+
+/*
+ * Based upon the CyaSSL implementation in cyassl.c and cyassl.h:
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * Thanks for code and inspiration!
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_MESALINK
+
+#include <mesalink/options.h>
+#include <mesalink/version.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "vtls.h"
+#include "parsedate.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "strcase.h"
+#include "x509asn1.h"
+#include "curl_printf.h"
+
+#include "mesalink.h"
+#include <mesalink/openssl/ssl.h>
+#include <mesalink/openssl/err.h>
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define MESALINK_MAX_ERROR_SZ 80
+
+struct ssl_backend_data
+{
+ SSL_CTX *ctx;
+ SSL *handle;
+};
+
+#define BACKEND connssl->backend
+
+static Curl_recv mesalink_recv;
+static Curl_send mesalink_send;
+
+/*
+ * This function loads all the client/CA certificates and CRLs. Setup the TLS
+ * layer and do all necessary magic.
+ */
+static CURLcode
+mesalink_connect_step1(struct connectdata *conn, int sockindex)
+{
+ char *ciphers;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const char *const ssl_capath = SSL_CONN_CONFIG(CApath);
+ struct in_addr addr4;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+ const char *const hostname =
+ SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name;
+ size_t hostname_len = strlen(hostname);
+
+ SSL_METHOD *req_method = NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+
+ if(connssl->state == ssl_connection_complete)
+ return CURLE_OK;
+
+ if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+ failf(data, "MesaLink does not support to set maximum SSL/TLS version");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ switch(SSL_CONN_CONFIG(version)) {
+ case CURL_SSLVERSION_SSLv3:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ failf(data, "MesaLink does not support SSL 3.0, TLS 1.0, or TLS 1.1");
+ return CURLE_NOT_BUILT_IN;
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1_2:
+ req_method = TLSv1_2_client_method();
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ req_method = TLSv1_3_client_method();
+ break;
+ case CURL_SSLVERSION_SSLv2:
+ failf(data, "MesaLink does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(!req_method) {
+ failf(data, "SSL: couldn't create a method!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(BACKEND->ctx)
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = SSL_CTX_new(req_method);
+
+ if(!BACKEND->ctx) {
+ failf(data, "SSL: couldn't create a context!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ SSL_CTX_set_verify(
+ BACKEND->ctx, verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
+
+ if(ssl_cafile || ssl_capath) {
+ if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) {
+ if(verifypeer) {
+ failf(data,
+ "error setting certificate verify locations:\n"
+ " CAfile: %s\n CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ infof(data,
+ "error setting certificate verify locations,"
+ " continuing anyway:\n");
+ }
+ else {
+ infof(data, "successfully set certificate verify locations:\n");
+ }
+ infof(data,
+ " CAfile: %s\n"
+ " CApath: %s\n",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ }
+
+ ciphers = SSL_CONN_CONFIG(cipher_list);
+ if(ciphers) {
+#ifdef MESALINK_HAVE_CIPHER
+ if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
+ failf(data, "failed setting cipher list: %s", ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+#endif
+ infof(data, "Cipher selection: %s\n", ciphers);
+ }
+
+ if(BACKEND->handle)
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = SSL_new(BACKEND->ctx);
+ if(!BACKEND->handle) {
+ failf(data, "SSL: couldn't create a context (handle)!");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if((hostname_len < USHRT_MAX) &&
+ (0 == Curl_inet_pton(AF_INET, hostname, &addr4))
+#ifdef ENABLE_IPV6
+ && (0 == Curl_inet_pton(AF_INET6, hostname, &addr6))
+#endif
+ ) {
+ /* hostname is not a valid IP address */
+ if(SSL_set_tlsext_host_name(BACKEND->handle, hostname) != SSL_SUCCESS) {
+ failf(data,
+ "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+#ifdef CURLDEBUG
+ /* Check if the hostname is 127.0.0.1 or [::1];
+ * otherwise reject because MesaLink always wants a valid DNS Name
+ * specified in RFC 5280 Section 7.2 */
+ if(strncmp(hostname, "127.0.0.1", 9) == 0
+#ifdef ENABLE_IPV6
+ || strncmp(hostname, "[::1]", 5) == 0
+#endif
+ ) {
+ SSL_set_tlsext_host_name(BACKEND->handle, "localhost");
+ }
+ else
+#endif
+ {
+ failf(data,
+ "ERROR: MesaLink does not accept an IP address as a hostname\n");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+#ifdef MESALINK_HAVE_SESSION
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ void *ssl_sessionid = NULL;
+
+ Curl_ssl_sessionid_lock(conn);
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
+ Curl_ssl_sessionid_unlock(conn);
+ failf(
+ data,
+ "SSL: SSL_set_session failed: %s",
+ ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof(data, "SSL re-using session ID\n");
+ }
+ Curl_ssl_sessionid_unlock(conn);
+ }
+#endif /* MESALINK_HAVE_SESSION */
+
+ if(SSL_set_fd(BACKEND->handle, (int)sockfd) != SSL_SUCCESS) {
+ failf(data, "SSL: SSL_set_fd failed");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+}
+
+static CURLcode
+mesalink_connect_step2(struct connectdata *conn, int sockindex)
+{
+ int ret = -1;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ conn->recv[sockindex] = mesalink_recv;
+ conn->send[sockindex] = mesalink_send;
+
+ ret = SSL_connect(BACKEND->handle);
+ if(ret != SSL_SUCCESS) {
+ char error_buffer[MESALINK_MAX_ERROR_SZ];
+ int detail = SSL_get_error(BACKEND->handle, ret);
+
+ if(SSL_ERROR_WANT_CONNECT == detail) {
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_OK;
+ }
+ else {
+ failf(data,
+ "SSL_connect failed with error %d: %s",
+ detail,
+ ERR_error_string_n(detail, error_buffer, sizeof(error_buffer)));
+ ERR_print_errors_fp(stderr);
+ if(detail && SSL_CONN_CONFIG(verifypeer)) {
+ detail &= ~0xFF;
+ if(detail == TLS_ERROR_WEBPKI_ERRORS) {
+ failf(data, "Cert verify failed");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_3;
+ infof(data,
+ "SSL connection using %s / %s\n",
+ SSL_get_version(BACKEND->handle),
+ SSL_get_cipher_name(BACKEND->handle));
+
+ return CURLE_OK;
+}
+
+static CURLcode
+mesalink_connect_step3(struct connectdata *conn, int sockindex)
+{
+ CURLcode result = CURLE_OK;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+#ifdef MESALINK_HAVE_SESSION
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ bool incache;
+ SSL_SESSION *our_ssl_sessionid;
+ void *old_ssl_sessionid = NULL;
+
+ our_ssl_sessionid = SSL_get_session(BACKEND->handle);
+
+ Curl_ssl_sessionid_lock(conn);
+ 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");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
+ }
+
+ if(!incache) {
+ result = Curl_ssl_addsessionid(
+ conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
+ if(result) {
+ Curl_ssl_sessionid_unlock(conn);
+ failf(data, "failed to store ssl session");
+ return result;
+ }
+ }
+ Curl_ssl_sessionid_unlock(conn);
+ }
+#endif /* MESALINK_HAVE_SESSION */
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return result;
+}
+
+static ssize_t
+mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
+ size_t len, CURLcode *curlcode)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ char error_buffer[MESALINK_MAX_ERROR_SZ];
+ int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
+ int rc = SSL_write(BACKEND->handle, mem, memlen);
+
+ if(rc < 0) {
+ int err = SSL_get_error(BACKEND->handle, rc);
+ switch(err) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_write() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data,
+ "SSL write: %s, errno %d",
+ ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
+ SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
+ }
+ return rc;
+}
+
+static void
+Curl_mesalink_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(BACKEND->handle) {
+ (void)SSL_shutdown(BACKEND->handle);
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
+ }
+ if(BACKEND->ctx) {
+ SSL_CTX_free(BACKEND->ctx);
+ BACKEND->ctx = NULL;
+ }
+}
+
+static ssize_t
+mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
+ CURLcode *curlcode)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[num];
+ char error_buffer[MESALINK_MAX_ERROR_SZ];
+ int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
+ int nread = SSL_read(BACKEND->handle, buf, buffsize);
+
+ if(nread <= 0) {
+ int err = SSL_get_error(BACKEND->handle, nread);
+
+ switch(err) {
+ case SSL_ERROR_ZERO_RETURN: /* no more data */
+ case IO_ERROR_CONNECTION_ABORTED:
+ break;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ /* there's data pending, re-invoke SSL_read() */
+ *curlcode = CURLE_AGAIN;
+ return -1;
+ default:
+ failf(conn->data,
+ "SSL read: %s, errno %d",
+ ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
+ SOCKERRNO);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ }
+ return nread;
+}
+
+static size_t
+Curl_mesalink_version(char *buffer, size_t size)
+{
+ return snprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
+}
+
+static int
+Curl_mesalink_init(void)
+{
+ return (SSL_library_init() == SSL_SUCCESS);
+}
+
+/*
+ * This function is called to shut down the SSL layer but keep the
+ * socket open (CCC - Clear Command Channel)
+ */
+static int
+Curl_mesalink_shutdown(struct connectdata *conn, int sockindex)
+{
+ int retval = 0;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+ if(BACKEND->handle) {
+ SSL_free(BACKEND->handle);
+ BACKEND->handle = NULL;
+ }
+ return retval;
+}
+
+static CURLcode
+mesalink_connect_common(struct connectdata *conn, int sockindex,
+ bool nonblocking, bool *done)
+{
+ CURLcode result;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ time_t timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1 == connssl->connecting_state) {
+ /* Find out how much more time we're allowed */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ result = mesalink_connect_step1(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(connssl->connecting_state == ssl_connect_2_reading ||
+ connssl->connecting_state == ssl_connect_2_writing) {
+
+ curl_socket_t writefd =
+ ssl_connect_2_writing == connssl->connecting_state ? sockfd
+ : CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading == connssl->connecting_state
+ ? sockfd
+ : CURL_SOCKET_BAD;
+
+ what = Curl_socket_check(
+ readfd, CURL_SOCKET_BAD, writefd, nonblocking ? 0 : timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if
+ * this connection is part of a multi handle and this loop would
+ * execute again. This permits the owner of a multi handle to
+ * abort a connection attempt before step2 has completed while
+ * ensuring that a client using select() or epoll() will always
+ * have a valid fdset to wait on.
+ */
+ result = mesalink_connect_step2(conn, sockindex);
+
+ if(result ||
+ (nonblocking && (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state))) {
+ return result;
+ }
+ } /* repeat step2 until all transactions are done. */
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ result = mesalink_connect_step3(conn, sockindex);
+ if(result)
+ return result;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = mesalink_recv;
+ conn->send[sockindex] = mesalink_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+static CURLcode
+Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex,
+ bool *done)
+{
+ return mesalink_connect_common(conn, sockindex, TRUE, done);
+}
+
+static CURLcode
+Curl_mesalink_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode result;
+ bool done = FALSE;
+
+ result = mesalink_connect_common(conn, sockindex, FALSE, &done);
+ if(result)
+ return result;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+static void *
+Curl_mesalink_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ (void)info;
+ return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_mesalink = {
+ { CURLSSLBACKEND_MESALINK, "MesaLink" }, /* info */
+
+ SSLSUPP_SSL_CTX,
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_mesalink_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ Curl_mesalink_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_mesalink_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ Curl_mesalink_connect, /* connect */
+ Curl_mesalink_connect_nonblocking, /* connect_nonblocking */
+ Curl_mesalink_get_internals, /* get_internals */
+ Curl_mesalink_close, /* close_one */
+ Curl_none_close_all, /* close_all */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ Curl_none_md5sum, /* md5sum */
+ NULL /* sha256sum */
+};
+
+#endif
--- /dev/null
+#ifndef HEADER_CURL_MESALINK_H
+#define HEADER_CURL_MESALINK_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com>
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, 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 USE_MESALINK
+
+extern const struct Curl_ssl Curl_ssl_mesalink;
+
+#endif /* USE_MESALINK */
+#endif /* HEADER_CURL_MESALINK_H */
#endif
};
+#ifdef WIN32
+static const char *pem_library = "nsspem.dll";
+static const char *trust_library = "nssckbi.dll";
+#else
static const char *pem_library = "libnsspem.so";
-static SECMODModule *pem_module = NULL;
-
static const char *trust_library = "libnssckbi.so";
+#endif
+
+static SECMODModule *pem_module = NULL;
static SECMODModule *trust_module = NULL;
/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
/* 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);
+ struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
if(!wrap)
return CURLE_OUT_OF_MEMORY;
PRTime now;
int i;
- if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
- SECSuccess && channel.length == sizeof channel &&
+ if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) ==
+ SECSuccess && channel.length == sizeof(channel) &&
channel.cipherSuite) {
if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
- &suite, sizeof suite) == SECSuccess) {
+ &suite, sizeof(suite)) == SECSuccess) {
infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
}
}
return CURLE_OUT_OF_MEMORY;
/* the default methods just call down to the lower I/O layer */
- memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods);
+ memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(),
+ sizeof(nspr_io_methods));
/* override certain methods in the table by our wrappers */
nspr_io_methods.recv = nspr_io_recv;
{
switch(err) {
case CURLE_PEER_FAILED_VERIFICATION:
- case CURLE_SSL_CACERT:
case CURLE_SSL_CERTPROBLEM:
case CURLE_SSL_CONNECT_ERROR:
case CURLE_SSL_ISSUER_ERROR:
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;
+ /* If libnssckbi.so is not available (or fails to load), one can still
+ use CA certificates stored in NSS database. Ignore the failure. */
+ result = CURLE_OK;
}
else if(!use_trust_module && trust_module) {
/* libnssckbi.so not needed but already loaded --> unload it! */
failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
return result;
}
- if(max == CURL_SSLVERSION_MAX_NONE)
- sslver->max = sslver->min;
}
switch(max) {
#include "hostcheck.h"
#include "curl_printf.h"
#include <openssl/ssl.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
#include <openssl/rand.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_DSA
#include <openssl/ocsp.h>
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && /* 0.9.8 or later */ \
+ !defined(OPENSSL_NO_ENGINE)
+#define USE_OPENSSL_ENGINE
+#include <openssl/engine.h>
+#endif
+
#include "warnless.h"
#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */
#error "OPENSSL_VERSION_NUMBER not defined"
#endif
-#if defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
#include <openssl/ui.h>
#endif
#define X509_get0_notBefore(x) X509_get_notBefore(x)
#define X509_get0_notAfter(x) X509_get_notAfter(x)
#define CONST_EXTS /* nope */
-#ifdef LIBRESSL_VERSION_NUMBER
-static unsigned long OpenSSL_version_num(void)
-{
- return LIBRESSL_VERSION_NUMBER;
-}
-#else
+#ifndef LIBRESSL_VERSION_NUMBER
#define OpenSSL_version_num() SSLeay()
#endif
#endif
+#ifdef LIBRESSL_VERSION_NUMBER
+#define OpenSSL_version_num() LIBRESSL_VERSION_NUMBER
+#endif
+
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
!(defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define HAVE_KEYLOG_CALLBACK
#endif
+/* Whether SSL_CTX_set_ciphersuites is available.
+ * OpenSSL: supported since 1.1.1 (commit a53b5be6a05)
+ * BoringSSL: no
+ * LibreSSL: no
+ */
+#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER) && \
+ !defined(OPENSSL_IS_BORINGSSL))
+#define HAVE_SSL_CTX_SET_CIPHERSUITES
+#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+#endif
+
#if defined(LIBRESSL_VERSION_NUMBER)
#define OSSL_PACKAGE "LibreSSL"
#elif defined(OPENSSL_IS_BORINGSSL)
if(!buf)
return;
}
- strncpy(buf, line, linelen);
+ memcpy(buf, line, linelen);
buf[linelen] = '\n';
buf[linelen + 1] = '\0';
return -1;
}
-#if defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
/*
* Supply default password to the engine user interface conversation.
* The password is passed by OpenSSL engine from ENGINE_load_private_key()
}
return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
}
+
+/*
+ * Check if a given string is a PKCS#11 URI
+ */
+static bool is_pkcs11_uri(const char *string)
+{
+ return (string && strncasecompare(string, "pkcs11:", 7));
+}
+
#endif
+static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
+ const char *engine);
+
static
int cert_stuff(struct connectdata *conn,
SSL_CTX* ctx,
}
break;
case SSL_FILETYPE_ENGINE:
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
+#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
{
+ /* Implicitly use pkcs11 engine if none was provided and the
+ * cert_file is a PKCS#11 URI */
+ if(!data->state.engine) {
+ if(is_pkcs11_uri(cert_file)) {
+ if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ return 0;
+ }
+ }
+ }
+
if(data->state.engine) {
const char *cmd_name = "LOAD_CERT_CTRL";
struct {
}
break;
case SSL_FILETYPE_ENGINE:
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
{ /* XXXX still needs some work */
EVP_PKEY *priv_key = NULL;
+
+ /* Implicitly use pkcs11 engine if none was provided and the
+ * key_file is a PKCS#11 URI */
+ if(!data->state.engine) {
+ if(is_pkcs11_uri(key_file)) {
+ if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ return 0;
+ }
+ }
+ }
+
if(data->state.engine) {
UI_METHOD *ui_method =
UI_create_method((char *)"curl user interface");
OPENSSL_load_builtin_modules();
-#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
+#ifdef USE_OPENSSL_ENGINE
ENGINE_load_builtin_engines();
#endif
#define CONF_MFLAGS_DEFAULT_SECTION 0x0
#endif
+#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
CONF_modules_load_file(NULL, NULL,
CONF_MFLAGS_DEFAULT_SECTION|
CONF_MFLAGS_IGNORE_MISSING_FILE);
+#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
!defined(LIBRESSL_VERSION_NUMBER)
static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
const char *engine)
{
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
ENGINE *e;
#if OPENSSL_VERSION_NUMBER >= 0x00909000L
*/
static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
{
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
infof(data, "set default crypto engine '%s'\n",
static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
{
struct curl_slist *list = NULL;
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
struct curl_slist *beg;
ENGINE *e;
ssize_t nread;
int buffsize;
int err;
- int done = 0;
+ bool done = FALSE;
/* This has only been tested on the proftpd server, and the mod_tls code
sends a close notify alert without waiting for a close notify alert in
case SSL_ERROR_ZERO_RETURN: /* no more data */
/* This is the expected response. There was no data but only
the close notify alert */
- done = 1;
+ done = TRUE;
break;
case SSL_ERROR_WANT_READ:
/* there's data pending, re-invoke SSL_read() */
case SSL_ERROR_WANT_WRITE:
/* SSL wants a write. Really odd. Let's bail out. */
infof(data, "SSL_ERROR_WANT_WRITE\n");
- done = 1;
+ done = TRUE;
break;
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
ossl_strerror(sslerror, buf, sizeof(buf)) :
SSL_ERROR_to_str(err)),
SOCKERRNO);
- done = 1;
+ done = TRUE;
break;
}
}
else if(0 == what) {
/* timeout */
failf(data, "SSL shutdown timeout");
- done = 1;
+ done = TRUE;
}
else {
/* anything that gets here is fatally bad */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
retval = -1;
- done = 1;
+ done = TRUE;
}
} /* while()-loop for the select() */
*/
static void Curl_ossl_close_all(struct Curl_easy *data)
{
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
ENGINE_finish(data->state.engine);
ENGINE_free(data->state.engine);
}
#else
{
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)dispname;
+ (void)data;
+#endif
if(Curl_cert_hostcheck(match_pattern, hostname)) {
infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
dispname, match_pattern);
}
else
#endif
- {
+ if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ msg_type = *(char *)buf;
+ msg_name = "Change cipher spec";
+ }
+ else if(content_type == SSL3_RT_ALERT) {
+ msg_type = (((char *)buf)[0] << 8) + ((char *)buf)[1];
+ msg_name = SSL_alert_desc_string_long(msg_type);
+ }
+ else {
msg_type = *(char *)buf;
msg_name = ssl_msg_type(ssl_ver, msg_type);
}
verstr, direction?"OUT":"IN",
tls_rt_name, msg_name, msg_type);
if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
- Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+ Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len);
}
}
Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
- CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
+ CURLINFO_SSL_DATA_IN, (char *)buf, len);
(void) ssl;
}
#endif
}
#endif /* HAS_NPN */
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
static const char *
get_ssl_version_txt(SSL *ssl)
{
}
return "unknown";
}
+#endif
static CURLcode
set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
- if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
- ssl_version_max = ssl_version << 16;
- }
-
switch(ssl_version) {
case CURL_SSLVERSION_TLSv1_3:
#ifdef TLS1_3_VERSION
#endif
/* FALLTHROUGH */
case CURL_SSLVERSION_TLSv1_0:
- *ctx_options |= SSL_OP_NO_SSLv2;
- *ctx_options |= SSL_OP_NO_SSLv3;
+ case CURL_SSLVERSION_TLSv1:
break;
}
#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
switch(ssl_version) {
case CURL_SSLVERSION_SSLv3:
-#ifdef USE_TLS_SRP
- if(ssl_authtype == CURL_TLSAUTH_SRP) {
- infof(data, "Set version TLSv1.x for SRP authorisation\n");
- }
-#endif
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_TLSv1;
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- break;
-
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
+ /* asking for any TLS version as the minimum, means no SSL versions
+ allowed */
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
result = set_ssl_version_min_max(&ctx_options, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
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
#endif
#endif
break;
-#else
- failf(data, OSSL_PACKAGE " was built without SSLv2 support");
- return CURLE_NOT_BUILT_IN;
-#endif
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
infof(data, "Cipher selection: %s\n", ciphers);
}
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+ {
+ char *ciphers13 = SSL_CONN_CONFIG(cipher_list13);
+ if(ciphers13) {
+ if(!SSL_CTX_set_ciphersuites(BACKEND->ctx, ciphers13)) {
+ failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "TLS 1.3 cipher selection: %s\n", ciphers13);
+ }
+ }
+#endif
+
+#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+ /* OpenSSL 1.1.1 requires clients to opt-in for PHA */
+ SSL_CTX_set_post_handshake_auth(BACKEND->ctx, 1);
+#endif
+
#ifdef USE_TLS_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP) {
char * const ssl_username = SSL_SET_OPTION(username);
}
#ifdef CURL_CA_FALLBACK
else if(verifypeer) {
- /* verfying the peer without any CA certificates won't
+ /* verifying the peer without any CA certificates won't
work so use openssl's built in default as fallback */
SSL_CTX_set_default_verify_paths(BACKEND->ctx);
}
{
CURLcode result = CURLE_OK;
int rc;
- long lerr, len;
+ long lerr;
struct Curl_easy *data = conn->data;
X509 *issuer;
BIO *fp = NULL;
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)) );
BIO_free(mem);
- return 0;
+ return CURLE_OUT_OF_MEMORY;
}
BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
buffer, sizeof(buffer));
infof(data, " subject: %s\n", rc?"[NONE]":buffer);
- ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
- len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " start date: %.*s\n", len, ptr);
- (void)BIO_reset(mem);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ {
+ long len;
+ ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
+ len = BIO_get_mem_data(mem, (char **) &ptr);
+ infof(data, " start date: %.*s\n", len, ptr);
+ (void)BIO_reset(mem);
- ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
- len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " expire date: %.*s\n", len, ptr);
- (void)BIO_reset(mem);
+ ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
+ len = BIO_get_mem_data(mem, (char **) &ptr);
+ infof(data, " expire date: %.*s\n", len, ptr);
+ (void)BIO_reset(mem);
+ }
+#endif
BIO_free(mem);
if(rc) {
if(strict)
failf(data, "SSL: couldn't get X509-issuer name!");
- result = CURLE_SSL_CONNECT_ERROR;
+ result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
infof(data, " issuer: %s\n", buffer);
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_SSL_CTX |
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+ SSLSUPP_TLS13_CIPHERSUITES |
+#endif
SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
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;
#endif
#endif
+#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX)
+#define HAS_CLIENT_CERT_PATH
+#endif
+
+#ifdef HAS_CLIENT_CERT_PATH
#ifdef UNICODE
#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
#else
#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A
#endif
+#endif
#ifndef SP_PROT_SSL2_CLIENT
#define SP_PROT_SSL2_CLIENT 0x00000008
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;
return CURLE_OK;
}
+/*longest is 26, buffer is slightly bigger*/
+#define LONGEST_ALG_ID 32
+#define CIPHEROPTION(X) \
+if(strcmp(#X, tmp) == 0) \
+ return X
+
+static int
+get_alg_id_by_name(char *name)
+{
+ char tmp[LONGEST_ALG_ID] = { 0 };
+ char *nameEnd = strchr(name, ':');
+ size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \
+ min(strlen(name), LONGEST_ALG_ID - 1);
+ strncpy(tmp, name, n);
+ tmp[n] = 0;
+ CIPHEROPTION(CALG_MD2);
+ CIPHEROPTION(CALG_MD4);
+ CIPHEROPTION(CALG_MD5);
+ CIPHEROPTION(CALG_SHA);
+ CIPHEROPTION(CALG_SHA1);
+ CIPHEROPTION(CALG_MAC);
+ CIPHEROPTION(CALG_RSA_SIGN);
+ CIPHEROPTION(CALG_DSS_SIGN);
+/*ifdefs for the options that are defined conditionally in wincrypt.h*/
+#ifdef CALG_NO_SIGN
+ CIPHEROPTION(CALG_NO_SIGN);
+#endif
+ CIPHEROPTION(CALG_RSA_KEYX);
+ CIPHEROPTION(CALG_DES);
+#ifdef CALG_3DES_112
+ CIPHEROPTION(CALG_3DES_112);
+#endif
+ CIPHEROPTION(CALG_3DES);
+ CIPHEROPTION(CALG_DESX);
+ CIPHEROPTION(CALG_RC2);
+ CIPHEROPTION(CALG_RC4);
+ CIPHEROPTION(CALG_SEAL);
+#ifdef CALG_DH_SF
+ CIPHEROPTION(CALG_DH_SF);
+#endif
+ CIPHEROPTION(CALG_DH_EPHEM);
+#ifdef CALG_AGREEDKEY_ANY
+ CIPHEROPTION(CALG_AGREEDKEY_ANY);
+#endif
+#ifdef CALG_HUGHES_MD5
+ CIPHEROPTION(CALG_HUGHES_MD5);
+#endif
+ CIPHEROPTION(CALG_SKIPJACK);
+#ifdef CALG_TEK
+ CIPHEROPTION(CALG_TEK);
+#endif
+ CIPHEROPTION(CALG_CYLINK_MEK);
+ CIPHEROPTION(CALG_SSL3_SHAMD5);
+#ifdef CALG_SSL3_MASTER
+ CIPHEROPTION(CALG_SSL3_MASTER);
+#endif
+#ifdef CALG_SCHANNEL_MASTER_HASH
+ CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH);
+#endif
+#ifdef CALG_SCHANNEL_MAC_KEY
+ CIPHEROPTION(CALG_SCHANNEL_MAC_KEY);
+#endif
+#ifdef CALG_SCHANNEL_ENC_KEY
+ CIPHEROPTION(CALG_SCHANNEL_ENC_KEY);
+#endif
+#ifdef CALG_PCT1_MASTER
+ CIPHEROPTION(CALG_PCT1_MASTER);
+#endif
+#ifdef CALG_SSL2_MASTER
+ CIPHEROPTION(CALG_SSL2_MASTER);
+#endif
+#ifdef CALG_TLS1_MASTER
+ CIPHEROPTION(CALG_TLS1_MASTER);
+#endif
+#ifdef CALG_RC5
+ CIPHEROPTION(CALG_RC5);
+#endif
+#ifdef CALG_HMAC
+ CIPHEROPTION(CALG_HMAC);
+#endif
+#if !defined(__W32API_MAJOR_VERSION) || \
+ !defined(__W32API_MINOR_VERSION) || \
+ defined(__MINGW64_VERSION_MAJOR) || \
+ (__W32API_MAJOR_VERSION > 5) || \
+ ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
+ /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0,
+ see https://osdn.net/projects/mingw/ticket/38391 */
+ CIPHEROPTION(CALG_TLS1PRF);
+#endif
+#ifdef CALG_HASH_REPLACE_OWF
+ CIPHEROPTION(CALG_HASH_REPLACE_OWF);
+#endif
+#ifdef CALG_AES_128
+ CIPHEROPTION(CALG_AES_128);
+#endif
+#ifdef CALG_AES_192
+ CIPHEROPTION(CALG_AES_192);
+#endif
+#ifdef CALG_AES_256
+ CIPHEROPTION(CALG_AES_256);
+#endif
+#ifdef CALG_AES
+ CIPHEROPTION(CALG_AES);
+#endif
+#ifdef CALG_SHA_256
+ CIPHEROPTION(CALG_SHA_256);
+#endif
+#ifdef CALG_SHA_384
+ CIPHEROPTION(CALG_SHA_384);
+#endif
+#ifdef CALG_SHA_512
+ CIPHEROPTION(CALG_SHA_512);
+#endif
+#ifdef CALG_ECDH
+ CIPHEROPTION(CALG_ECDH);
+#endif
+#ifdef CALG_ECMQV
+ CIPHEROPTION(CALG_ECMQV);
+#endif
+#ifdef CALG_ECDSA
+ CIPHEROPTION(CALG_ECDSA);
+#endif
+ return 0;
+}
+
+static CURLcode
+set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
+{
+ char *startCur = ciphers;
+ int algCount = 0;
+ static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/
+ while(startCur && (0 != *startCur) && (algCount < 45)) {
+ long alg = strtol(startCur, 0, 0);
+ if(!alg)
+ alg = get_alg_id_by_name(startCur);
+ if(alg)
+ algIds[algCount++] = alg;
+ else
+ return CURLE_SSL_CIPHER;
+ startCur = strchr(startCur, ':');
+ if(startCur)
+ startCur++;
+ }
+ schannel_cred->palgSupportedAlgs = algIds;
+ schannel_cred->cSupportedAlgs = algCount;
+ return CURLE_OK;
+}
+
+#ifdef HAS_CLIENT_CERT_PATH
static CURLcode
get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
TCHAR **thumbprint)
sep = _tcschr(path, TEXT('\\'));
if(sep == NULL)
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
store_name_len = sep - path;
store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
else
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
*store_path = sep + 1;
sep = _tcschr(*store_path, TEXT('\\'));
if(sep == NULL)
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
*sep = 0;
*thumbprint = sep + 1;
if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
return CURLE_OK;
}
+#endif
static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)
#endif
#ifdef _WIN32_WCE
+#ifdef HAS_MANUAL_VERIFY_API
/* certificate validation on CE doesn't seem to work right; we'll
* do it following a more manual process. */
BACKEND->use_manual_cred_validation = true;
#else
+#error "compiler too old to support requisite manual cert verify for Win CE"
+#endif
+#else
+#ifdef HAS_MANUAL_VERIFY_API
if(SSL_CONN_CONFIG(CAfile)) {
if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL)) {
}
else
BACKEND->use_manual_cred_validation = false;
+#else
+ if(SSL_CONN_CONFIG(CAfile)) {
+ failf(data, "schannel: CA cert support not built in");
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
#endif
BACKEND->cred = NULL;
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
if(conn->ssl_config.verifypeer) {
+#ifdef HAS_MANUAL_VERIFY_API
if(BACKEND->use_manual_cred_validation)
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
else
+#endif
schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
/* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
return CURLE_SSL_CONNECT_ERROR;
}
+ if(SSL_CONN_CONFIG(cipher_list)) {
+ result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list));
+ if(CURLE_OK != result) {
+ failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
+ return result;
+ }
+ }
+
+
+#ifdef HAS_CLIENT_CERT_PATH
/* client certificate */
if(data->set.ssl.cert) {
DWORD cert_store_name;
result = get_cert_location(cert_path, &cert_store_name,
&cert_store_path, &cert_thumbprint_str);
if(result != CURLE_OK) {
+ failf(data, "schannel: Failed to get certificate location for %s",
+ cert_path);
Curl_unicodefree(cert_path);
return result;
}
- cert_store = CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
- (HCRYPTPROV)NULL,
- cert_store_name, cert_store_path);
+ cert_store =
+ CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
+ cert_store_path);
if(!cert_store) {
+ failf(data, "schannel: Failed to open cert store %x %s, "
+ "last error is %x",
+ cert_store_name, cert_store_path, GetLastError());
Curl_unicodefree(cert_path);
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
}
cert_thumbprint.pbData = cert_thumbprint_data;
cert_thumbprint_data, &cert_thumbprint.cbData,
NULL, NULL)) {
Curl_unicodefree(cert_path);
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_SSL_CERTPROBLEM;
}
client_certs[0] = CertFindCertificateInStore(
schannel_cred.cCreds = 1;
schannel_cred.paCred = client_certs;
}
+ else {
+ /* CRYPT_E_NOT_FOUND / E_INVALIDARG */
+ return CURLE_SSL_CERTPROBLEM;
+ }
CertCloseStore(cert_store, 0);
}
+#else
+ if(data->set.ssl.cert) {
+ failf(data, "schannel: client cert support not built in");
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
/* allocate memory for the re-usable credential handle */
BACKEND->cred = (struct curl_schannel_cred *)
CertFreeCertificateContext(client_certs[0]);
if(sspi_status != SEC_E_OK) {
- if(sspi_status == SEC_E_WRONG_PRINCIPAL)
- failf(data, "schannel: SNI or certificate check failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
- else
- failf(data, "schannel: AcquireCredentialsHandle failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
+ failf(data, "schannel: AcquireCredentialsHandle failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(BACKEND->cred);
- return CURLE_SSL_CONNECT_ERROR;
+ switch(sspi_status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_SECPKG_NOT_FOUND:
+ case SEC_E_NOT_OWNER:
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ case SEC_E_INTERNAL_ERROR:
+ default:
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
}
Curl_unicodefree(host_name);
if(sspi_status != SEC_I_CONTINUE_NEEDED) {
- if(sspi_status == SEC_E_WRONG_PRINCIPAL)
- failf(data, "schannel: SNI or certificate check failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
- else
- failf(data, "schannel: initial InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(BACKEND->ctxt);
- return CURLE_SSL_CONNECT_ERROR;
+ switch(sspi_status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_WRONG_PRINCIPAL:
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_PEER_FAILED_VERIFICATION;
+ /*
+ case SEC_E_INVALID_HANDLE:
+ case SEC_E_INVALID_TOKEN:
+ case SEC_E_LOGON_DENIED:
+ case SEC_E_TARGET_UNKNOWN:
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ case SEC_E_INTERNAL_ERROR:
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
+ */
+ default:
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
infof(data, "schannel: sending initial handshake data: "
}
}
else {
- if(sspi_status == SEC_E_WRONG_PRINCIPAL)
- failf(data, "schannel: SNI or certificate check failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
- else
- failf(data, "schannel: next InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(conn, sspi_status));
- return sspi_status == SEC_E_UNTRUSTED_ROOT ?
- CURLE_SSL_CACERT : CURLE_SSL_CONNECT_ERROR;
+ switch(sspi_status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_WRONG_PRINCIPAL:
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_PEER_FAILED_VERIFICATION;
+ /*
+ case SEC_E_INVALID_HANDLE:
+ case SEC_E_INVALID_TOKEN:
+ case SEC_E_LOGON_DENIED:
+ case SEC_E_TARGET_UNKNOWN:
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ case SEC_E_INTERNAL_ERROR:
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
+ */
+ default:
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(conn, sspi_status));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
}
/* check if there was additional remaining encrypted data */
}
}
+#ifdef HAS_MANUAL_VERIFY_API
if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
return verify_certificate(conn, sockindex);
}
+#endif
return CURLE_OK;
}
if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
failf(data, "schannel: failed to retrieve remote cert context");
- return CURLE_SSL_CONNECT_ERROR;
+ return CURLE_PEER_FAILED_VERIFICATION;
}
result = Curl_ssl_init_certinfo(data, 1);
x509_der = (const char *)pCertContextServer->pbCertEncoded;
x509_der_len = pCertContextServer->cbCertEncoded;
- memset(&x509_parsed, 0, sizeof x509_parsed);
+ memset(&x509_parsed, 0, sizeof(x509_parsed));
if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
break;
if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
break; /* failed */
- if(!CryptHashData(hHash, (const BYTE*)input, (DWORD)inputlen, 0))
+ /* workaround for original MinGW, should be (const BYTE*) */
+ if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
break; /* failed */
/* get hash size */
#include "urldata.h"
+/* <wincrypt.h> has been included via the above <schnlsp.h>.
+ * Or in case of ldap.c, it was included via <winldap.h>.
+ * And since <wincrypt.h> has this:
+ * #define X509_NAME ((LPCSTR) 7)
+ *
+ * And in BoringSSL's <openssl/base.h> there is:
+ * typedef struct X509_name_st X509_NAME;
+ * etc.
+ *
+ * this will cause all kinds of C-preprocessing paste errors in
+ * BoringSSL's <openssl/x509.h>: So just undefine those defines here
+ * (and only here).
+ */
+#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL)
+# undef X509_NAME
+# undef X509_CERT_PAIR
+# undef X509_EXTENSIONS
+#endif
+
extern const struct Curl_ssl Curl_ssl_schannel;
CURLcode verify_certificate(struct connectdata *conn, int sockindex);
/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
+#ifdef __MINGW32__
+#include <_mingw.h>
+#ifdef __MINGW64_VERSION_MAJOR
+#define HAS_MANUAL_VERIFY_API
+#endif
+#else
+#include <wincrypt.h>
+#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
+#define HAS_MANUAL_VERIFY_API
+#endif
+#endif
+
struct curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
bool recv_connection_closed; /* true if connection closed, regardless how */
bool use_alpn; /* true if ALPN is used for this connection */
+#ifdef HAS_MANUAL_VERIFY_API
bool use_manual_cred_validation; /* true if manual cred validation is used */
+#endif
};
#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
#include "curl_setup.h"
#ifdef USE_SCHANNEL
-
-#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
-
#ifndef USE_WINDOWS_SSPI
# error "Can't compile SCHANNEL support without SSPI."
#endif
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
#include "schannel.h"
+
+#ifdef HAS_MANUAL_VERIFY_API
+
#include "vtls.h"
#include "sendf.h"
#include "strerror.h"
#define BACKEND connssl->backend
#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
-#define BEGIN_CERT "-----BEGIN CERTIFICATE-----\n"
+#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
#define END_CERT "\n-----END CERTIFICATE-----"
typedef struct {
HCERTSTORE hExclusiveTrustedPeople;
} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7;
+static int is_cr_or_lf(char c)
+{
+ return c == '\r' || c == '\n';
+}
static CURLcode add_certs_to_store(HCERTSTORE trust_store,
const char *ca_file,
failf(data,
"schannel: CA file exceeds max size of %u bytes",
MAX_CAFILE_SIZE);
- result = CURLE_OUT_OF_MEMORY;
+ result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
current_ca_file_ptr = ca_file_buffer;
while(more_certs && *current_ca_file_ptr != '\0') {
char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT);
- if(!begin_cert_ptr) {
+ if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[strlen(BEGIN_CERT)])) {
more_certs = 0;
}
else {
NULL,
NULL,
NULL,
- &cert_context)) {
+ (const void **)&cert_context)) {
failf(data,
"schannel: failed to extract certificate from CA file "
CertFreeCertificateContext(cert_context);
if(!add_cert_result) {
failf(data,
- "schannel: failed to add certificate from CA file '%s'"
+ "schannel: failed to add certificate from CA file '%s' "
"to certificate store: %s",
ca_file, Curl_strerror(conn, GetLastError()));
result = CURLE_SSL_CACERT_BADFILE;
* embedded null bytes. This appears to be undocumented behavior.
*/
cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR));
+ if(!cert_hostname_buff) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
actual_len = CertGetNameString(pCertContextServer,
CERT_NAME_DNS_TYPE,
name_flags,
return result;
}
+#endif /* HAS_MANUAL_VERIFY_API */
#endif /* USE_SCHANNEL */
Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
- Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
+ Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
+ Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13))
return TRUE;
return FALSE;
CLONE_STRING(random_file);
CLONE_STRING(egdsocket);
CLONE_STRING(cipher_list);
+ CLONE_STRING(cipher_list13);
return TRUE;
}
Curl_safefree(sslc->random_file);
Curl_safefree(sslc->egdsocket);
Curl_safefree(sslc->cipher_list);
+ Curl_safefree(sslc->cipher_list13);
}
#ifdef USE_SSL
}
/*
+ * Check whether the SSL backend supports setting TLS 1.3 cipher suites
+ */
+bool Curl_ssl_tls13_ciphersuites(void)
+{
+ return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES;
+}
+
+/*
* Default implementations for unsupported functions.
*/
&Curl_ssl_polarssl;
#elif defined(USE_SCHANNEL)
&Curl_ssl_schannel;
+#elif defined(USE_MESALINK)
+ &Curl_ssl_mesalink;
#else
#error "Missing struct Curl_ssl for selected SSL backend"
#endif
#if defined(USE_SCHANNEL)
&Curl_ssl_schannel,
#endif
+#if defined(USE_MESALINK)
+ &Curl_ssl_mesalink,
+#endif
NULL
};
#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */
#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */
#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */
+#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */
struct Curl_ssl {
/*
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
+bool Curl_ssl_tls13_ciphersuites(void);
CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
unsigned char *md5sum, size_t md5len);
#include "schannel.h" /* Schannel SSPI version */
#include "darwinssl.h" /* SecureTransport (Darwin) version */
#include "mbedtls.h" /* mbedTLS versions */
+#include "mesalink.h" /* MesaLink versions */
#ifndef MAX_PINNED_PUBKEY_SIZE
#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
-#else
+#else /* if not USE_SSL */
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
#define Curl_ssl_cert_status_request() FALSE
#define Curl_ssl_false_start() FALSE
+#define Curl_ssl_tls13_ciphersuites() FALSE
#endif
#endif /* HEADER_CURL_VTLS_H */
#include <curl/curl.h> /* for curl_socket_t */
#endif
+#define CURLX_FUNCTION_CAST(target_type, func) \
+ (target_type)(void (*) (void))(func)
+
unsigned short curlx_ultous(unsigned long ulnum);
unsigned char curlx_ultouc(unsigned long ulnum);
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#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. */
static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */
* Please note there is no pretention here to rewrite a full SSL library.
*/
+static const char *getASN1Element(curl_asn1Element *elem,
+ const char *beg, const char *end)
+ WARN_UNUSED_RESULT;
-const char *Curl_getASN1Element(curl_asn1Element *elem,
- const char *beg, const char *end)
+static const char *getASN1Element(curl_asn1Element *elem,
+ const char *beg, const char *end)
{
unsigned char b;
unsigned long len;
return (const char *) NULL;
elem->beg = beg;
while(beg < end && *beg) {
- beg = Curl_getASN1Element(&lelem, beg, end);
+ beg = getASN1Element(&lelem, beg, end);
if(!beg)
return (const char *) NULL;
}
/* Convert an ASN.1 octet string to a printable string.
Return the dynamically allocated string, or NULL if an error occurs. */
- if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
+ if(n <= (SIZE_T_MAX - 1) / 3) {
buf = malloc(3 * n + 1);
if(buf)
for(n = 0; beg < end; n += 3)
static const char *int2str(const char *beg, const char *end)
{
- long val = 0;
+ unsigned long val = 0;
size_t n = end - beg;
/* Convert an ASN.1 integer value into its string representation.
do
val = (val << 8) | *(const unsigned char *) beg++;
while(beg < end);
- return curl_maprintf("%s%lx", (val < 0 || val >= 10)? "0x": "", val);
+ return curl_maprintf("%s%lx", val >= 10? "0x": "", val);
}
static ssize_t
if(inlength % size)
return -1; /* Length inconsistent with character size. */
- if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4)
+ if(inlength / size > (SIZE_T_MAX - 1) / 4)
return -1; /* Too big. */
buf = malloc(4 * (inlength / size) + 1);
if(!buf)
case 4:
wc = (wc << 8) | *(const unsigned char *) from++;
wc = (wc << 8) | *(const unsigned char *) from++;
- /* fallthrough */
+ /* FALLTHROUGH */
case 2:
wc = (wc << 8) | *(const unsigned char *) from++;
- /* fallthrough */
+ /* FALLTHROUGH */
default: /* case 1: */
wc = (wc << 8) | *(const unsigned char *) from++;
}
tzl, tzp);
}
-const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
+static const char *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. */
Return the total string length, even if larger than `n'. */
for(p1 = dn->beg; p1 < dn->end;) {
- p1 = Curl_getASN1Element(&rdn, p1, dn->end);
+ p1 = getASN1Element(&rdn, p1, dn->end);
+ if(!p1)
+ return -1;
for(p2 = rdn.beg; p2 < rdn.end;) {
- p2 = Curl_getASN1Element(&atv, p2, rdn.end);
- p3 = Curl_getASN1Element(&oid, atv.beg, atv.end);
- Curl_getASN1Element(&value, p3, atv.end);
- str = Curl_ASN1tostr(&oid, 0);
+ p2 = getASN1Element(&atv, p2, rdn.end);
+ if(!p2)
+ return -1;
+ p3 = getASN1Element(&oid, atv.beg, atv.end);
+ if(!p3)
+ return -1;
+ if(!getASN1Element(&value, p3, atv.end))
+ return -1;
+ str = ASN1tostr(&oid, 0);
if(!str)
return -1;
l++;
/* Generate value. */
- str = Curl_ASN1tostr(&value, 0);
+ str = ASN1tostr(&value, 0);
if(!str)
return -1;
for(p3 = str; *p3; p3++) {
return l;
}
-const char *Curl_DNtostr(curl_asn1Element *dn)
+static const char *DNtostr(curl_asn1Element *dn)
{
char *buf = (char *) NULL;
ssize_t n = encodeDN(buf, 0, dn);
cert->certificate.end = end;
/* Get the sequence content. */
- if(!Curl_getASN1Element(&elem, beg, end))
+ if(!getASN1Element(&elem, beg, end))
return -1; /* Invalid bounds/size. */
beg = elem.beg;
end = elem.end;
/* Get tbsCertificate. */
- beg = Curl_getASN1Element(&tbsCertificate, beg, end);
+ beg = getASN1Element(&tbsCertificate, beg, end);
+ if(!beg)
+ return -1;
/* Skip the signatureAlgorithm. */
- beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
+ if(!beg)
+ return -1;
/* Get the signatureValue. */
- Curl_getASN1Element(&cert->signature, beg, end);
+ if(!getASN1Element(&cert->signature, beg, end))
+ return -1;
/* Parse TBSCertificate. */
beg = tbsCertificate.beg;
/* Get optional version, get serialNumber. */
cert->version.header = NULL;
cert->version.beg = &defaultVersion;
- cert->version.end = &defaultVersion + sizeof defaultVersion;;
- beg = Curl_getASN1Element(&elem, beg, end);
+ cert->version.end = &defaultVersion + sizeof(defaultVersion);
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
if(elem.tag == 0) {
- Curl_getASN1Element(&cert->version, elem.beg, elem.end);
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(!getASN1Element(&cert->version, elem.beg, elem.end))
+ return -1;
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
}
cert->serialNumber = elem;
/* Get signature algorithm. */
- beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+ beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
/* Get issuer. */
- beg = Curl_getASN1Element(&cert->issuer, beg, end);
+ beg = getASN1Element(&cert->issuer, beg, end);
+ if(!beg)
+ return -1;
/* Get notBefore and notAfter. */
- beg = Curl_getASN1Element(&elem, beg, end);
- ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end);
- Curl_getASN1Element(&cert->notAfter, ccp, elem.end);
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ ccp = getASN1Element(&cert->notBefore, elem.beg, elem.end);
+ if(!ccp)
+ return -1;
+ if(!getASN1Element(&cert->notAfter, ccp, elem.end))
+ return -1;
/* Get subject. */
- beg = Curl_getASN1Element(&cert->subject, beg, end);
+ beg = getASN1Element(&cert->subject, beg, end);
+ if(!beg)
+ return -1;
/* Get subjectPublicKeyAlgorithm and subjectPublicKey. */
- beg = Curl_getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
- ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm,
- cert->subjectPublicKeyInfo.beg,
- cert->subjectPublicKeyInfo.end);
- Curl_getASN1Element(&cert->subjectPublicKey, ccp,
- cert->subjectPublicKeyInfo.end);
+ beg = getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
+ if(!beg)
+ return -1;
+ ccp = getASN1Element(&cert->subjectPublicKeyAlgorithm,
+ cert->subjectPublicKeyInfo.beg,
+ cert->subjectPublicKeyInfo.end);
+ if(!ccp)
+ return -1;
+ if(!getASN1Element(&cert->subjectPublicKey, ccp,
+ cert->subjectPublicKeyInfo.end))
+ return -1;
/* Get optional issuerUiqueID, subjectUniqueID and extensions. */
cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
cert->extensions.tag = elem.tag = 0;
cert->subjectUniqueID.beg = cert->subjectUniqueID.end = "";
cert->extensions.header = NULL;
cert->extensions.beg = cert->extensions.end = "";
- if(beg < end)
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(beg < end) {
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ }
if(elem.tag == 1) {
cert->issuerUniqueID = elem;
- if(beg < end)
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(beg < end) {
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ }
}
if(elem.tag == 2) {
cert->subjectUniqueID = elem;
- if(beg < end)
- beg = Curl_getASN1Element(&elem, beg, end);
+ if(beg < end) {
+ beg = getASN1Element(&elem, beg, end);
+ if(!beg)
+ return -1;
+ }
}
if(elem.tag == 3)
- Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+ if(!getASN1Element(&cert->extensions, elem.beg, elem.end))
+ return -1;
return 0;
}
/* Get algorithm parameters and return algorithm name. */
- beg = Curl_getASN1Element(&oid, beg, end);
+ beg = getASN1Element(&oid, beg, end);
+ if(!beg)
+ return NULL;
param->header = NULL;
param->tag = 0;
param->beg = param->end = end;
if(beg < end)
- Curl_getASN1Element(param, beg, end);
+ if(!getASN1Element(param, beg, end))
+ return NULL;
return OID2str(oid.beg, oid.end, TRUE);
}
/* Generate a certificate information record for the public key. */
- output = Curl_ASN1tostr(elem, 0);
+ output = ASN1tostr(elem, 0);
if(output) {
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, label, output);
/* Generate all information records for the public key. */
/* Get the public key (single element). */
- Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
+ if(!getASN1Element(&pk, pubkey->beg + 1, pubkey->end))
+ return;
if(strcasecompare(algo, "rsaEncryption")) {
- p = Curl_getASN1Element(&elem, pk.beg, pk.end);
+ p = getASN1Element(&elem, pk.beg, pk.end);
+ if(!p)
+ return;
+
/* Compute key length. */
for(q = elem.beg; !*q && q < elem.end; q++)
;
}
/* Generate coefficients. */
do_pubkey_field(data, certnum, "rsa(n)", &elem);
- Curl_getASN1Element(&elem, p, pk.end);
+ if(!getASN1Element(&elem, p, pk.end))
+ return;
do_pubkey_field(data, certnum, "rsa(e)", &elem);
}
else if(strcasecompare(algo, "dsa")) {
- p = Curl_getASN1Element(&elem, param->beg, param->end);
- do_pubkey_field(data, certnum, "dsa(p)", &elem);
- p = Curl_getASN1Element(&elem, p, param->end);
- do_pubkey_field(data, certnum, "dsa(q)", &elem);
- Curl_getASN1Element(&elem, p, param->end);
- do_pubkey_field(data, certnum, "dsa(g)", &elem);
- do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
+ p = getASN1Element(&elem, param->beg, param->end);
+ if(p) {
+ do_pubkey_field(data, certnum, "dsa(p)", &elem);
+ p = getASN1Element(&elem, p, param->end);
+ if(p) {
+ do_pubkey_field(data, certnum, "dsa(q)", &elem);
+ if(getASN1Element(&elem, p, param->end)) {
+ do_pubkey_field(data, certnum, "dsa(g)", &elem);
+ do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
+ }
+ }
+ }
}
else if(strcasecompare(algo, "dhpublicnumber")) {
- p = Curl_getASN1Element(&elem, param->beg, param->end);
- do_pubkey_field(data, certnum, "dh(p)", &elem);
- Curl_getASN1Element(&elem, param->beg, param->end);
- do_pubkey_field(data, certnum, "dh(g)", &elem);
- do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
- }
-#if 0 /* Patent-encumbered. */
- else if(strcasecompare(algo, "ecPublicKey")) {
- /* Left TODO. */
+ p = getASN1Element(&elem, param->beg, param->end);
+ if(p) {
+ do_pubkey_field(data, certnum, "dh(p)", &elem);
+ if(getASN1Element(&elem, param->beg, param->end)) {
+ do_pubkey_field(data, certnum, "dh(g)", &elem);
+ do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
+ }
+ }
}
-#endif
}
CURLcode Curl_extract_certinfo(struct connectdata *conn,
/* Extract the certificate ASN.1 elements. */
if(Curl_parseX509(&cert, beg, end))
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_PEER_FAILED_VERIFICATION;
/* Subject. */
- ccp = Curl_DNtostr(&cert.subject);
+ ccp = DNtostr(&cert.subject);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
free((char *) ccp);
/* Issuer. */
- ccp = Curl_DNtostr(&cert.issuer);
+ ccp = DNtostr(&cert.issuer);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
/* Serial number. */
- ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
+ ccp = ASN1tostr(&cert.serialNumber, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
free((char *) ccp);
/* Start Date. */
- ccp = Curl_ASN1tostr(&cert.notBefore, 0);
+ ccp = ASN1tostr(&cert.notBefore, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
free((char *) ccp);
/* Expire Date. */
- ccp = Curl_ASN1tostr(&cert.notAfter, 0);
+ ccp = ASN1tostr(&cert.notAfter, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
/* TODO: extensions. */
/* Signature. */
- ccp = Curl_ASN1tostr(&cert.signature, 0);
+ ccp = ASN1tostr(&cert.signature, 0);
if(!ccp)
return CURLE_OUT_OF_MEMORY;
if(data->set.ssl.certinfo)
/* Check if first ASN.1 element at `beg' is the given OID.
Return a pointer in the source after the OID if found, else NULL. */
- ccp = Curl_getASN1Element(&e, beg, end);
+ ccp = getASN1Element(&e, beg, end);
if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
return (const char *) NULL;
/* Process extensions. */
for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
- p = Curl_getASN1Element(&ext, p, cert.extensions.end);
+ p = getASN1Element(&ext, p, cert.extensions.end);
+ if(!p)
+ return CURLE_PEER_FAILED_VERIFICATION;
+
/* Check if extension is a subjectAlternativeName. */
ext.beg = checkOID(ext.beg, ext.end, sanOID);
if(ext.beg) {
- ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ ext.beg = getASN1Element(&elem, ext.beg, ext.end);
+ if(!ext.beg)
+ return CURLE_PEER_FAILED_VERIFICATION;
/* Skip critical if present. */
- if(elem.tag == CURL_ASN1_BOOLEAN)
- ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+ if(elem.tag == CURL_ASN1_BOOLEAN) {
+ ext.beg = getASN1Element(&elem, ext.beg, ext.end);
+ if(!ext.beg)
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
/* Parse the octet string contents: is a single sequence. */
- Curl_getASN1Element(&elem, elem.beg, elem.end);
+ if(!getASN1Element(&elem, elem.beg, elem.end))
+ return CURLE_PEER_FAILED_VERIFICATION;
/* Check all GeneralNames. */
for(q = elem.beg; matched != 1 && q < elem.end;) {
- q = Curl_getASN1Element(&name, q, elem.end);
+ q = getASN1Element(&name, q, elem.end);
+ if(!q)
+ break;
switch(name.tag) {
case 2: /* DNS name. */
len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
break;
case 7: /* IP address. */
- matched = (size_t) (name.end - q) == addrlen &&
- !memcmp(&addr, q, addrlen);
+ matched = (size_t) (name.end - name.beg) == addrlen &&
+ !memcmp(&addr, name.beg, addrlen);
break;
}
}
/* we have to look to the last occurrence of a commonName in the
distinguished one to get the most significant one. */
while(q < cert.subject.end) {
- q = Curl_getASN1Element(&dn, q, cert.subject.end);
+ q = getASN1Element(&dn, q, cert.subject.end);
+ if(!q)
+ break;
for(p = dn.beg; p < dn.end;) {
- p = Curl_getASN1Element(&elem, p, dn.end);
+ p = getASN1Element(&elem, p, dn.end);
+ if(!p)
+ return CURLE_PEER_FAILED_VERIFICATION;
/* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
elem.beg = checkOID(elem.beg, elem.end, cnOID);
if(elem.beg)
}
/* Check the CN if found. */
- if(!Curl_getASN1Element(&elem, name.beg, name.end))
+ if(!getASN1Element(&elem, name.beg, name.end))
failf(data, "SSL: unable to obtain common name from peer certificate");
else {
len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
+OPTION(ENABLE_LZ4 "Enable the use of the system LZ4 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)
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
+ SET(LZO2_FOUND FALSE) # Override cached value
ENDIF(ENABLE_LZO)
IF(LZO2_FOUND)
SET(HAVE_LIBLZO2 1)
#
# Find LZ4
#
-IF (LZ4_INCLUDE_DIR)
- # Already in cache, be silent
- SET(LZ4_FIND_QUIETLY TRUE)
-ENDIF (LZ4_INCLUDE_DIR)
+IF(ENABLE_LZ4)
+ IF (LZ4_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZ4_FIND_QUIETLY TRUE)
+ ENDIF (LZ4_INCLUDE_DIR)
-FIND_PATH(LZ4_INCLUDE_DIR lz4.h)
-FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4)
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR)
+ FIND_PATH(LZ4_INCLUDE_DIR lz4.h)
+ FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4)
+ INCLUDE(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR)
+ELSE(ENABLE_LZ4)
+ SET(LZ4_FOUND FALSE) # Override cached value
+ENDIF(ENABLE_LZ4)
IF(LZ4_FOUND)
SET(HAVE_LIBLZ4 1)
SET(HAVE_LZ4_H 1)
ENDIF(LZ4_FOUND)
MARK_AS_ADVANCED(CLEAR LZ4_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR LZ4_LIBRARY)
+#
+# Find Zstd
+#
+IF (ZSTD_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(ZSTD_FIND_QUIETLY TRUE)
+ENDIF (ZSTD_INCLUDE_DIR)
+
+FIND_PATH(ZSTD_INCLUDE_DIR zstd.h)
+FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd)
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
+IF(ZSTD_FOUND)
+ SET(HAVE_ZSTD_H 1)
+ INCLUDE_DIRECTORIES(${ZSTD_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${ZSTD_LIBRARY})
+ SET(CMAKE_REQUIRED_LIBRARIES ${ZSTD_LIBRARY})
+ SET(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
+ CHECK_FUNCTION_EXISTS(ZSTD_compressStream HAVE_LIBZSTD)
+ #
+ # TODO: test for static library.
+ #
+ENDIF(ZSTD_FOUND)
+MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY)
ENDIF()
#
LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H)
+LA_CHECK_INCLUDE_FILE("sys/sysmacros.h" HAVE_SYS_SYSMACROS_H)
LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H)
LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H)
LA_CHECK_INCLUDE_FILE("sys/utsname.h" HAVE_SYS_UTSNAME_H)
/* Define to 1 if you have the `z' library (-lz). */
#cmakedefine HAVE_LIBZ 1
+/* Define to 1 if you have the `zstd' library (-lzstd). */
+#cmakedefine HAVE_LIBZSTD 1
+
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#cmakedefine HAVE_SYS_SYSMACROS_H 1
+
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <zlib.h> header file. */
#cmakedefine HAVE_ZLIB_H 1
+/* Define to 1 if you have the <zstd.h> header file. */
+#cmakedefine HAVE_ZSTD_H 1
+
/* Define to 1 if you have the `_ctime64_s' function. */
#cmakedefine HAVE__CTIME64_S 1
Description: library that can create and read several streaming archive formats
Version: @VERSION@
Cflags: -I${includedir}
+Cflags.private: -DLIBARCHIVE_STATIC
Libs: -L${libdir} -larchive
Libs.private: @LIBS@
archive_read_support_filter_rpm.c
archive_read_support_filter_uu.c
archive_read_support_filter_xz.c
+ archive_read_support_filter_zstd.c
archive_read_support_format_7zip.c
archive_read_support_format_all.c
archive_read_support_format_ar.c
archive_write_add_filter_program.c
archive_write_add_filter_uuencode.c
archive_write_add_filter_xz.c
+ archive_write_add_filter_zstd.c
archive_write_set_format.c
archive_write_set_format_7zip.c
archive_write_set_format_ar.c
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3003002
+#define ARCHIVE_VERSION_NUMBER 3003003
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.3.2"
+#define ARCHIVE_VERSION_ONLY_STRING "3.3.3"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
__LA_DECL const char * archive_liblzma_version(void);
__LA_DECL const char * archive_bzlib_version(void);
__LA_DECL const char * archive_liblz4_version(void);
+__LA_DECL const char * archive_libzstd_version(void);
/* Declare our basic types. */
struct archive;
#define ARCHIVE_FILTER_LZOP 11
#define ARCHIVE_FILTER_GRZIP 12
#define ARCHIVE_FILTER_LZ4 13
+#define ARCHIVE_FILTER_ZSTD 14
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
__LA_DECL int archive_read_support_filter_uu(struct archive *);
__LA_DECL int archive_read_support_filter_xz(struct archive *);
+__LA_DECL int archive_read_support_filter_zstd(struct archive *);
__LA_DECL int archive_read_support_format_7zip(struct archive *);
__LA_DECL int archive_read_support_format_all(struct archive *);
const char *cmd);
__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
__LA_DECL int archive_write_add_filter_xz(struct archive *);
+__LA_DECL int archive_write_add_filter_zstd(struct archive *);
/* A convenience function to set the format based on the code or name. */
switch (want_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ __LA_FALLTHROUGH;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
numfields = 5;
switch (want_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+ __LA_FALLTHROUGH;
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
numfields = 5;
/*
* Set up command line arguments.
- * Returns ARChIVE_OK if everything okey.
- * Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
+ * Returns ARCHIVE_OK if everything okey.
+ * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an
* empty command line.
- * Returns ARChIVE_FATAL if no memory.
+ * Returns ARCHIVE_FATAL if no memory.
*/
int
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
CCCryptorStatus r;
r = CCCryptorReset(ref, NULL);
- if (r != kCCSuccess)
+ if (r != kCCSuccess && r != kCCUnimplemented)
return -1;
r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
AES_BLOCK_SIZE, NULL);
} archive_crypto_ctx;
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
-#include <Bcrypt.h>
+#include <bcrypt.h>
/* Common in other bcrypt implementations, but missing from VS2008. */
#ifndef BCRYPT_SUCCESS
{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},
+#ifdef ACL_ENTRY_INHERITED
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif
};
static const int acl_nfs4_flag_map_size =
* the style of the generated ACL.
*/
wchar_t *
-archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
+archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,
int flags)
{
return (archive_acl_to_text_w(&entry->acl, len, flags,
}
char *
-archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
+archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
int flags)
{
return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3003002
+#define ARCHIVE_VERSION_NUMBER 3003003
/*
* Note: archive_entry.h is for use outside of libarchive; the
#include <sys/types.h>
#include <stddef.h> /* for wchar_t */
+#include <stdint.h>
#include <time.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
*/
int
-archive_match_include_uid(struct archive *_a, int64_t uid)
+archive_match_include_uid(struct archive *_a, la_int64_t uid)
{
struct archive_match *a;
}
int
-archive_match_include_gid(struct archive *_a, int64_t gid)
+archive_match_include_gid(struct archive *_a, la_int64_t gid)
{
struct archive_match *a;
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
+#ifdef HAVE_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#define ARCHIVE_ERRNO_MISC (-1)
#endif
+#if defined(__GNUC__) && (__GNUC__ >= 7)
+#define __LA_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define __LA_FALLTHROUGH
+#endif
+
#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
}
-static void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
+static void Ppmd7_Free(CPpmd7 *p)
{
- alloc->Free(alloc, p->Base);
+ free(p->Base);
p->Size = 0;
p->Base = 0;
}
-static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
+static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size)
{
if (p->Base == 0 || p->Size != size)
{
if (size < UNIT_SIZE) {
return False;
}
- Ppmd7_Free(p, alloc);
+ Ppmd7_Free(p);
p->AlignOffset =
#ifdef PPMD_32BIT
(4 - size) & 3;
#else
4 - (size & 3);
#endif
- if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
+ if ((p->Base = (Byte *)malloc(p->AlignOffset + size
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
{
/* Base Functions */
void (*Ppmd7_Construct)(CPpmd7 *p);
- Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
- void (*Ppmd7_Free)(CPpmd7 *p, ISzAlloc *alloc);
+ Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size);
+ void (*Ppmd7_Free)(CPpmd7 *p);
void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
void (*Write)(void *p, Byte b);
} IByteOut;
-
-typedef struct
-{
- void *(*Alloc)(void *p, size_t size);
- void (*Free)(void *p, void *address); /* address can be 0 */
-} ISzAlloc;
-
/*** End defined in Types.h ***/
/*** Begin defined in CpuArch.h ***/
* Record the do-not-extract-to file. This belongs in archive_read_extract.c.
*/
void
-archive_read_extract_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_read_extract_set_skip_file(struct archive *_a, la_int64_t d,
+ la_int64_t i)
{
struct archive_read *a = (struct archive_read *)_a;
* Return the file offset (within the uncompressed data stream) where
* the last header started.
*/
-int64_t
+la_int64_t
archive_read_header_position(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
* DO NOT intermingle calls to this function and archive_read_data_block
* to read a single entry body.
*/
-ssize_t
+la_ssize_t
archive_read_data(struct archive *_a, void *buff, size_t s)
{
struct archive *a = (struct archive *)_a;
return (r);
}
-int64_t
+la_int64_t
archive_seek_data(struct archive *_a, int64_t offset, int whence)
{
struct archive_read *a = (struct archive_read *)_a;
switch (whence) {
case SEEK_CUR:
/* Adjust the offset and use SEEK_SET instead */
- offset += filter->position;
+ offset += filter->position;
+ __LA_FALLTHROUGH;
case SEEK_SET:
cursor = 0;
while (1)
strcpy(str, "lz4");
r1 = archive_read_support_filter_lz4(_a);
break;
+ case ARCHIVE_FILTER_ZSTD:
+ strcpy(str, "zstd");
+ r1 = archive_read_support_filter_zstd(_a);
+ break;
case ARCHIVE_FILTER_LZIP:
strcpy(str, "lzip");
r1 = archive_read_support_filter_lzip(_a);
/*
* Enter working directory and return working pathname of archive_entry.
* If a pointer to an integer is provided and its value is below zero
- * open a file descriptor on this pahtname.
+ * open a file descriptor on this pathname.
*/
const char *
archive_read_disk_entry_setup_path(struct archive_read_disk *a,
}
const char *
-archive_read_disk_gname(struct archive *_a, int64_t gid)
+archive_read_disk_gname(struct archive *_a, la_int64_t gid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
}
const char *
-archive_read_disk_uname(struct archive *_a, int64_t uid)
+archive_read_disk_uname(struct archive *_a, la_int64_t uid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
int
archive_read_disk_set_gname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_gname)(void *private, int64_t gid),
+ const char * (*lookup_gname)(void *private, la_int64_t gid),
void (*cleanup_gname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
int
archive_read_disk_set_uname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_uname)(void *private, int64_t uid),
+ const char * (*lookup_uname)(void *private, la_int64_t uid),
void (*cleanup_uname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
*/
#define MAX_OVERLAPPED 8
-#define BUFFER_SIZE (1024 * 8)
+#define READ_BUFFER_SIZE (1024 * 64) /* Default to 64KB per https://technet.microsoft.com/en-us/library/cc938632.aspx */
#define DIRECT_IO 0/* Disabled */
#define ASYNC_IO 1/* Enabled */
}
const char *
-archive_read_disk_gname(struct archive *_a, int64_t gid)
+archive_read_disk_gname(struct archive *_a, la_int64_t gid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
}
const char *
-archive_read_disk_uname(struct archive *_a, int64_t uid)
+archive_read_disk_uname(struct archive *_a, la_int64_t uid)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
int
archive_read_disk_set_gname_lookup(struct archive *_a,
void *private_data,
- const char * (*lookup_gname)(void *private, int64_t gid),
+ const char * (*lookup_gname)(void *private, la_int64_t gid),
void (*cleanup_gname)(void *private))
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
/* Allocate read buffer. */
if (olp->buff == NULL) {
void *p;
- size_t s = (size_t)align_num_per_sector(t, BUFFER_SIZE);
+ size_t s = (size_t)align_num_per_sector(t, READ_BUFFER_SIZE);
p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE);
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
break;
} while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED);
} else {
- if (start_next_async_read(a, t) == ARCHIVE_FATAL)
+ if ((r = start_next_async_read(a, t)) == ARCHIVE_FATAL)
goto abort_read_data;
}
t->entry_fh = CreateFileW(tree_current_access_path(t),
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
if (t->entry_fh == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
"Couldn't open %ls", tree_current_path(a->tree));
return (ARCHIVE_FAILED);
if (range.Length.QuadPart > 0)
continue;
} else {
- /* The remaining data is hole. */
+ /* The entire file is a hole. Add one data block of size 0 at the end. */
archive_entry_sparse_add_entry(entry,
- range.FileOffset.QuadPart,
- range.Length.QuadPart);
+ entry_size,
+ 0);
}
break;
} else {
.Nm archive_read_support_filter_rpm ,
.Nm archive_read_support_filter_uu ,
.Nm archive_read_support_filter_xz ,
+.Nm archive_read_support_filter_zstd ,
.Nm archive_read_support_filter_program ,
.Nm archive_read_support_filter_program_signature
.Nd functions for reading streaming archives
.Ft int
.Fn archive_read_support_filter_xz "struct archive *"
.Ft int
+.Fn archive_read_support_filter_zstd "struct archive *"
+.Ft int
.Fo archive_read_support_filter_program
.Fa "struct archive *"
.Fa "const char *cmd"
.Fn archive_read_support_filter_none ,
.Fn archive_read_support_filter_rpm ,
.Fn archive_read_support_filter_uu ,
-.Fn archive_read_support_filter_xz
+.Fn archive_read_support_filter_xz ,
+.Fn archive_read_support_filter_zstd ,
.Xc
Enables auto-detection code and decompression support for the
specified compression.
archive_read_support_filter_grzip(a);
/* Lz4 falls back to "lz4 -d" command-line program. */
archive_read_support_filter_lz4(a);
+ /* Zstd falls back to "zstd -d" command-line program. */
+ archive_read_support_filter_zstd(a);
/* Note: We always return ARCHIVE_OK here, even if some of the
* above return ARCHIVE_WARN. The intent here is to enable
--- /dev/null
+/*-
+ * Copyright (c) 2009-2011 Sean Purcell
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ZSTD_H
+#include <zstd.h>
+#endif
+
+#include "archive.h"
+#include "archive_endian.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+
+struct private_data {
+ ZSTD_DStream *dstream;
+ unsigned char *out_block;
+ size_t out_block_size;
+ int64_t total_out;
+ char in_frame; /* True = in the middle of a zstd frame. */
+ char eof; /* True = found end of compressed data. */
+};
+
+/* Zstd Filter. */
+static ssize_t zstd_filter_read(struct archive_read_filter *, const void**);
+static int zstd_filter_close(struct archive_read_filter *);
+#endif
+
+/*
+ * Note that we can detect zstd compressed files even if we can't decompress
+ * them. (In fact, we like detecting them because we can give better error
+ * messages.) So the bid framework here gets compiled even if no zstd library
+ * is available.
+ */
+static int zstd_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int zstd_bidder_init(struct archive_read_filter *);
+
+int
+archive_read_support_filter_zstd(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *bidder;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_zstd");
+
+ if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ bidder->data = NULL;
+ bidder->name = "zstd";
+ bidder->bid = zstd_bidder_bid;
+ bidder->init = zstd_bidder_init;
+ bidder->options = NULL;
+ bidder->free = NULL;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ return (ARCHIVE_OK);
+#else
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external zstd program for zstd decompression");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+/*
+ * Test whether we can handle this data.
+ */
+static int
+zstd_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *buffer;
+ ssize_t avail;
+ unsigned prefix;
+
+ /* Zstd frame magic values */
+ const unsigned zstd_magic = 0xFD2FB528U;
+
+ (void) self; /* UNUSED */
+
+ buffer = __archive_read_filter_ahead(filter, 4, &avail);
+ if (buffer == NULL)
+ return (0);
+
+ prefix = archive_le32dec(buffer);
+ if (prefix == zstd_magic)
+ return (32);
+
+ return (0);
+}
+
+#if !(HAVE_ZSTD_H && HAVE_LIBZSTD)
+
+/*
+ * If we don't have the library on this system, we can't do the
+ * decompression directly. We can, however, try to run "zstd -d"
+ * in case that's available.
+ */
+static int
+zstd_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "zstd -d -qq");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_ZSTD;
+ self->name = "zstd";
+ return (r);
+}
+
+#else
+
+/*
+ * Initialize the filter object
+ */
+static int
+zstd_bidder_init(struct archive_read_filter *self)
+{
+ struct private_data *state;
+ const size_t out_block_size = ZSTD_DStreamOutSize();
+ void *out_block;
+ ZSTD_DStream *dstream;
+
+ self->code = ARCHIVE_FILTER_ZSTD;
+ self->name = "zstd";
+
+ state = (struct private_data *)calloc(sizeof(*state), 1);
+ out_block = (unsigned char *)malloc(out_block_size);
+ dstream = ZSTD_createDStream();
+
+ if (state == NULL || out_block == NULL || dstream == NULL) {
+ free(out_block);
+ free(state);
+ ZSTD_freeDStream(dstream); /* supports free on NULL */
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for zstd decompression");
+ return (ARCHIVE_FATAL);
+ }
+
+ self->data = state;
+
+ state->out_block_size = out_block_size;
+ state->out_block = out_block;
+ state->dstream = dstream;
+ self->read = zstd_filter_read;
+ self->skip = NULL; /* not supported */
+ self->close = zstd_filter_close;
+
+ state->eof = 0;
+ state->in_frame = 0;
+
+ return (ARCHIVE_OK);
+}
+
+static ssize_t
+zstd_filter_read(struct archive_read_filter *self, const void **p)
+{
+ struct private_data *state;
+ size_t decompressed;
+ ssize_t avail_in;
+ ZSTD_outBuffer out;
+ ZSTD_inBuffer in;
+
+ state = (struct private_data *)self->data;
+
+ out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };
+
+ /* Try to fill the output buffer. */
+ while (out.pos < out.size && !state->eof) {
+ if (!state->in_frame) {
+ const size_t ret = ZSTD_initDStream(state->dstream);
+ if (ZSTD_isError(ret)) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Error initializing zstd decompressor: %s",
+ ZSTD_getErrorName(ret));
+ return (ARCHIVE_FATAL);
+ }
+ }
+ in.src = __archive_read_filter_ahead(self->upstream, 1,
+ &avail_in);
+ if (avail_in < 0) {
+ return avail_in;
+ }
+ if (in.src == NULL && avail_in == 0) {
+ if (!state->in_frame) {
+ /* end of stream */
+ state->eof = 1;
+ break;
+ } else {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Truncated zstd input");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ in.size = avail_in;
+ in.pos = 0;
+
+ {
+ const size_t ret =
+ ZSTD_decompressStream(state->dstream, &out, &in);
+
+ if (ZSTD_isError(ret)) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Zstd decompression failed: %s",
+ ZSTD_getErrorName(ret));
+ return (ARCHIVE_FATAL);
+ }
+
+ /* Decompressor made some progress */
+ __archive_read_filter_consume(self->upstream, in.pos);
+
+ /* ret guaranteed to be > 0 if frame isn't done yet */
+ state->in_frame = (ret != 0);
+ }
+ }
+
+ decompressed = out.pos;
+ state->total_out += decompressed;
+ if (decompressed == 0)
+ *p = NULL;
+ else
+ *p = state->out_block;
+ return (decompressed);
+}
+
+/*
+ * Clean up the decompressor.
+ */
+static int
+zstd_filter_close(struct archive_read_filter *self)
+{
+ struct private_data *state;
+
+ state = (struct private_data *)self->data;
+
+ ZSTD_freeDStream(state->dstream);
+ free(state->out_block);
+ free(state);
+
+ return (ARCHIVE_OK);
+}
+
+#endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */
return (id);
}
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
static Byte
ppmd_read(void *p)
{
return (b);
}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
-
static int
init_decompression(struct archive_read *a, struct _7zip *zip,
const struct _7z_coder *coder1, const struct _7z_coder *coder2)
if (zip->ppmd7_valid) {
__archive_ppmd7_functions.Ppmd7_Free(
- &zip->ppmd7_context, &g_szalloc);
+ &zip->ppmd7_context);
zip->ppmd7_valid = 0;
}
}
__archive_ppmd7_functions.Ppmd7_Construct(&zip->ppmd7_context);
r = __archive_ppmd7_functions.Ppmd7_Alloc(
- &zip->ppmd7_context, msize, &g_szalloc);
+ &zip->ppmd7_context, msize);
if (r == 0) {
archive_set_error(&a->archive, ENOMEM,
"Coludn't allocate memory for PPMd");
#endif
if (zip->ppmd7_valid) {
__archive_ppmd7_functions.Ppmd7_Free(
- &zip->ppmd7_context, &g_szalloc);
+ &zip->ppmd7_context);
zip->ppmd7_valid = 0;
}
return (r);
case kDummy:
if (ll == 0)
break;
+ __LA_FALLTHROUGH;
default:
if (header_bytes(a, ll) == NULL)
return (-1);
/* Pad name to 2 more than a multiple of 4. */
*name_pad = (2 - *namelength) & 3;
+ /* Make sure that the padded name length fits into size_t. */
+ if (*name_pad > SIZE_MAX - *namelength) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "cpio archive has invalid namelength");
+ return (ARCHIVE_FATAL);
+ }
+
/*
* Note: entry_bytes_remaining is at least 64 bits and
* therefore guaranteed to be big enough for a 33-bit file
struct file_info **);
static struct file_info *
parse_file_info(struct archive_read *a,
- struct file_info *parent, const unsigned char *isodirrec);
+ struct file_info *parent, const unsigned char *isodirrec,
+ size_t reclen);
static int parse_rockridge(struct archive_read *a,
struct file_info *file, const unsigned char *start,
const unsigned char *end);
if (*(p + DR_name_len_offset) == 1
&& *(p + DR_name_offset) == '\001')
continue;
- child = parse_file_info(a, parent, p);
+ child = parse_file_info(a, parent, p, b - p);
if (child == NULL) {
__archive_read_consume(a, skip_size);
return (ARCHIVE_FATAL);
*/
seenJoliet = iso9660->seenJoliet;/* Save flag. */
iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
+ file = parse_file_info(a, NULL, block, vd->size);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
return (ARCHIVE_FATAL);
}
iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
+ file = parse_file_info(a, NULL, block, vd->size);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
*/
static struct file_info *
parse_file_info(struct archive_read *a, struct file_info *parent,
- const unsigned char *isodirrec)
+ const unsigned char *isodirrec, size_t reclen)
{
struct iso9660 *iso9660;
struct file_info *file, *filep;
iso9660 = (struct iso9660 *)(a->format->data);
- dr_len = (size_t)isodirrec[DR_length_offset];
- name_len = (size_t)isodirrec[DR_name_len_offset];
- location = archive_le32dec(isodirrec + DR_extent_offset);
- fsize = toi(isodirrec + DR_size_offset, DR_size_size);
- /* Sanity check that dr_len needs at least 34. */
- if (dr_len < 34) {
+ if (reclen != 0)
+ dr_len = (size_t)isodirrec[DR_length_offset];
+ /*
+ * Sanity check that reclen is not zero and dr_len is greater than
+ * reclen but at least 34
+ */
+ if (reclen == 0 || reclen < dr_len || dr_len < 34) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Invalid length of directory record");
+ "Invalid length of directory record");
return (NULL);
}
+ name_len = (size_t)isodirrec[DR_name_len_offset];
+ location = archive_le32dec(isodirrec + DR_extent_offset);
+ fsize = toi(isodirrec + DR_size_offset, DR_size_size);
/* Sanity check that name_len doesn't exceed dr_len. */
if (dr_len - 33 < name_len || name_len == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
* Prepare variables used to read a file content.
*/
lha->entry_bytes_remaining = lha->compsize;
+ if (lha->entry_bytes_remaining < 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid LHa entry size");
+ return (ARCHIVE_FATAL);
+ }
lha->entry_offset = 0;
lha->entry_crc_calculated = 0;
#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
+#include "archive_rb.h"
#include "archive_read_private.h"
#include "archive_string.h"
#include "archive_pack_dev.h"
#define MTREE_HAS_OPTIONAL 0x0800
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
-#define MTREE_HASHTABLE_SIZE 1024
+#define MAX_LINE_LEN (1024 * 1024)
struct mtree_option {
struct mtree_option *next;
};
struct mtree_entry {
+ struct archive_rb_node rbnode;
+ struct mtree_entry *next_dup;
struct mtree_entry *next;
struct mtree_option *options;
char *name;
char full;
char used;
- unsigned int name_hash;
- struct mtree_entry *hashtable_next;
};
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_rb_tree entry_rbtree;
struct archive_string current_dir;
struct archive_string contents_name;
struct archive_entry_linkresolver *resolver;
+ struct archive_rb_tree rbtree;
int64_t cur_size;
char checkfs;
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 *);
}
}
+static int
+mtree_cmp_node(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
+ const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
+
+ return (strcmp(e1->name, e2->name));
+}
+
+static int
+mtree_cmp_key(const struct archive_rb_node *n, const void *key)
+{
+ const struct mtree_entry *e = (const struct mtree_entry *)n;
+
+ return (strcmp(e->name, key));
+}
+
int
archive_read_support_format_mtree(struct archive *_a)
{
+ static const struct archive_rb_tree_ops rb_ops = {
+ mtree_cmp_node, mtree_cmp_key,
+ };
struct archive_read *a = (struct archive_read *)_a;
struct mtree *mtree;
int r;
}
mtree->fd = -1;
+ __archive_rb_tree_init(&mtree->rbtree, &rb_ops);
+
r = __archive_read_register_format(a, mtree, "mtree",
mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
size_t nbytes_req = (*ravail+1023) & ~1023U;
ssize_t tested;
+ /*
+ * Place an arbitrary limit on the line length.
+ * mtree is almost free-form input and without line length limits,
+ * it can consume a lot of memory.
+ */
+ if (len >= MAX_LINE_LEN)
+ return (-1);
+
/* Increase reading bytes if it is not enough to at least
* new two lines. */
if (nbytes_req < (size_t)*ravail + 160)
struct mtree_option **global, const char *line, ssize_t line_len,
struct mtree_entry **last_entry, int is_form_d)
{
- struct mtree_entry *entry, *ht_iter;
+ struct mtree_entry *entry;
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");
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)
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;
+ entry->next_dup = NULL;
+ if (entry->full) {
+ if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
+ struct mtree_entry *alt;
+ alt = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &mtree->rbtree, entry->name);
+ while (alt->next_dup)
+ alt = alt->next_dup;
+ alt->next_dup = entry;
+ }
}
for (iter = *global; iter != NULL; iter = iter->next) {
* with pathname canonicalization, which is a very
* tricky subject.)
*/
- for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
- if (mp->full && !mp->used
- && mentry->name_hash == mp->name_hash
- && strcmp(mentry->name, mp->name) == 0) {
+ mp = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &mtree->rbtree, mentry->name);
+ for (; mp; mp = mp->next_dup) {
+ if (mp->full && !mp->used) {
/* Later lines override earlier ones. */
mp->used = 1;
- r1 = parse_line(a, entry, mtree, mp,
- &parsed_kws);
+ r1 = parse_line(a, entry, mtree, mp, &parsed_kws);
if (r1 < r)
r = r1;
}
}
if (strcmp(key, "cksum") == 0)
break;
+ __LA_FALLTHROUGH;
case 'd':
if (strcmp(key, "device") == 0) {
/* stat(2) st_rdev field, e.g. the major/minor IDs
archive_entry_set_rdev(entry, dev);
return r;
}
+ __LA_FALLTHROUGH;
case 'f':
if (strcmp(key, "flags") == 0) {
*parsed_kws |= MTREE_HAS_FFLAGS;
archive_entry_copy_fflags_text(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'g':
if (strcmp(key, "gid") == 0) {
*parsed_kws |= MTREE_HAS_GID;
archive_entry_copy_gname(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'i':
if (strcmp(key, "inode") == 0) {
archive_entry_set_ino(entry, mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 'l':
if (strcmp(key, "link") == 0) {
archive_entry_copy_symlink(entry, val);
break;
}
+ __LA_FALLTHROUGH;
case 'm':
if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
break;
}
break;
}
+ __LA_FALLTHROUGH;
case 'n':
if (strcmp(key, "nlink") == 0) {
*parsed_kws |= MTREE_HAS_NLINK;
(unsigned int)mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 'r':
if (strcmp(key, "resdevice") == 0) {
/* stat(2) st_dev field, e.g. the device ID where the
if (strcmp(key, "rmd160") == 0 ||
strcmp(key, "rmd160digest") == 0)
break;
+ __LA_FALLTHROUGH;
case 's':
if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
break;
archive_entry_set_size(entry, mtree_atol(&val, 10));
break;
}
+ __LA_FALLTHROUGH;
case 't':
if (strcmp(key, "tags") == 0) {
/*
archive_entry_set_filetype(entry, AE_IFBLK);
break;
}
+ __LA_FALLTHROUGH;
case 'c':
if (strcmp(val, "char") == 0) {
archive_entry_set_filetype(entry,
AE_IFCHR);
break;
}
+ __LA_FALLTHROUGH;
case 'd':
if (strcmp(val, "dir") == 0) {
archive_entry_set_filetype(entry,
AE_IFDIR);
break;
}
+ __LA_FALLTHROUGH;
case 'f':
if (strcmp(val, "fifo") == 0) {
archive_entry_set_filetype(entry,
AE_IFREG);
break;
}
+ __LA_FALLTHROUGH;
case 'l':
if (strcmp(val, "link") == 0) {
archive_entry_set_filetype(entry,
AE_IFLNK);
break;
}
+ __LA_FALLTHROUGH;
default:
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
*parsed_kws |= MTREE_HAS_TYPE;
break;
}
+ __LA_FALLTHROUGH;
case 'u':
if (strcmp(key, "uid") == 0) {
*parsed_kws |= MTREE_HAS_UID;
archive_entry_copy_uname(entry, val);
break;
}
+ __LA_FALLTHROUGH;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unrecognized key %s=%s", key, val);
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;
-}
rar->lzss.position += length;
}
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
-
static Byte
ppmd_read(void *p)
{
case COMPRESS_METHOD_BEST:
ret = read_data_compressed(a, buff, size, offset);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
break;
default:
free(rar->dbo);
free(rar->unp_buffer);
free(rar->lzss.window);
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
free(rar);
(a->format->data) = NULL;
return (ARCHIVE_OK);
return (ARCHIVE_FATAL);
}
filename[filename_size++] = '\0';
- filename[filename_size++] = '\0';
+ /*
+ * Do not increment filename_size here as the computations below
+ * add the space for the terminating NUL explicitly.
+ */
+ filename[filename_size] = '\0';
/* Decoded unicode form is UTF-16BE, so we have to update a string
* conversion object for it. */
rar->unp_offset = 0;
rar->unp_buffer_size = UNP_BUFFER_SIZE;
memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->ppmd_valid = rar->ppmd_eod = 0;
/* Don't set any archive entries for non-file header types */
/* Make sure ppmd7_contest is freed before Ppmd7_Construct
* because reading a broken file cause this abnormal sequence. */
- __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->bytein.a = a;
rar->bytein.Read = &ppmd_read;
}
if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
- rar->dictionary_size, &g_szalloc))
+ rar->dictionary_size))
{
archive_set_error(&a->archive, ENOMEM,
"Out of memory");
ARCHIVE_STATE_NEW, "archive_read_support_format_tar");
tar = (struct tar *)calloc(1, sizeof(*tar));
-#ifdef HAVE_COPYFILE_H
- /* Set this by default on Mac OS. */
- tar->process_mac_extensions = 1;
-#endif
if (tar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
+#ifdef HAVE_COPYFILE_H
+ /* Set this by default on Mac OS. */
+ tar->process_mac_extensions = 1;
+#endif
r = __archive_read_register_format(a, tar, "tar",
archive_read_format_tar_bid,
else
tar->sparse_list = p;
tar->sparse_last = p;
- if (remaining < 0 || offset < 0) {
+ if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data");
return (ARCHIVE_FATAL);
}
uint64_t l;
int digit;
+ if (char_cnt == 0)
+ return (0);
+
l = 0;
digit = *p - '0';
while (digit >= 0 && digit < 10 && char_cnt-- > 0) {
{
int64_t l;
int digit;
-
+
+ if (char_cnt == 0)
+ return (0);
+
l = 0;
while (char_cnt-- > 0) {
if (*p >= '0' && *p <= '7')
archive_strncat(as, (const char *)buff, len);
}
+static int
+is_string(const char *known, const char *data, size_t len)
+{
+ if (strlen(known) != len)
+ return -1;
+ return memcmp(data, known, len);
+}
+
static void
xml_data(void *userData, const char *s, int len)
{
archive_strncpy(&(xar->file->symlink), s, len);
break;
case FILE_TYPE:
- if (strncmp("file", s, len) == 0 ||
- strncmp("hardlink", s, len) == 0)
+ if (is_string("file", s, len) == 0 ||
+ is_string("hardlink", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFREG;
- if (strncmp("directory", s, len) == 0)
+ if (is_string("directory", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFDIR;
- if (strncmp("symlink", s, len) == 0)
+ if (is_string("symlink", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFLNK;
- if (strncmp("character special", s, len) == 0)
+ if (is_string("character special", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFCHR;
- if (strncmp("block special", s, len) == 0)
+ if (is_string("block special", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFBLK;
- if (strncmp("socket", s, len) == 0)
+ if (is_string("socket", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFSOCK;
- if (strncmp("fifo", s, len) == 0)
+ if (is_string("fifo", s, len) == 0)
xar->file->mode =
(xar->file->mode & ~AE_IFMT) | AE_IFIFO;
xar->file->has |= HAS_TYPE;
case 0x5455:
{
/* Extended time field "UT". */
- int flags = p[offset];
+ int flags;
+ if (datasize == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Incomplete extended time field");
+ return ARCHIVE_FAILED;
+ }
+ flags = p[offset];
offset++;
datasize--;
/* Flag bits indicate which dates are present. */
}
case 0x9901:
/* WinZip AES extra data field. */
+ if (datasize < 6) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Incomplete AES field");
+ return ARCHIVE_FAILED;
+ }
if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
/* Vendor version. */
zip_entry->aes_extra.vendor =
zip_entry->mode |= 0664;
}
+ /* Windows archivers sometimes use backslash as the directory separator.
+ Normalize to slash. */
+ if (zip_entry->system == 0 &&
+ (wp = archive_entry_pathname_w(entry)) != NULL) {
+ if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) {
+ size_t i;
+ struct archive_wstring s;
+ archive_string_init(&s);
+ archive_wstrcpy(&s, wp);
+ for (i = 0; i < archive_strlen(&s); i++) {
+ if (s.s[i] == '\\')
+ s.s[i] = '/';
+ }
+ archive_entry_copy_pathname_w(entry, s.s);
+ archive_wstring_free(&s);
+ }
+ }
+
/* Make sure that entries with a trailing '/' are marked as directories
* even if the External File Attributes contains bogus values. If this
* is not a directory and there is no type, assume regularfile. */
zip->end_of_entry = 1;
/* Set up a more descriptive format name. */
+ archive_string_empty(&zip->format_name);
archive_string_sprintf(&zip->format_name, "ZIP %d.%d (%s)",
version / 10, version % 10,
compression_name(zip->entry->compression));
{
if (archive_wstring_ensure(as, as->length + s + 1) == NULL)
return (NULL);
- wmemmove(as->s + as->length, p, s);
+ if (s)
+ wmemmove(as->s + as->length, p, s);
as->length += s;
as->s[as->length] = 0;
return (as);
/*
* Return a count of the number of compressed bytes processed.
*/
-int64_t
+la_int64_t
archive_position_compressed(struct archive *a)
{
return archive_filter_bytes(a, -1);
/*
* Return a count of the number of uncompressed bytes processed.
*/
-int64_t
+la_int64_t
archive_position_uncompressed(struct archive *a)
{
return archive_filter_bytes(a, 0);
#ifdef HAVE_LZ4_H
#include <lz4.h>
#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
#include "archive.h"
#include "archive_private.h"
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
+ const char *libzstd = archive_libzstd_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
+ if (libzstd) {
+ archive_strcat(&str, " libzstd/");
+ archive_strcat(&str, libzstd);
+ }
}
return str.s;
}
return NULL;
#endif
}
+
+const char *
+archive_libzstd_version(void)
+{
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ return ZSTD_VERSION_STRING;
+#else
+ return NULL;
+#endif
+}
return ((a->vtable->archive_filter_name)(a, n));
}
-int64_t
+la_int64_t
archive_filter_bytes(struct archive *a, int n)
{
return ((a->vtable->archive_filter_bytes)(a, n));
return ((a->vtable->archive_write_finish_entry)(a));
}
-ssize_t
+la_ssize_t
archive_write_data(struct archive *a, const void *buff, size_t s)
{
return ((a->vtable->archive_write_data)(a, buff, s));
}
-ssize_t
-archive_write_data_block(struct archive *a, const void *buff, size_t s, int64_t o)
+la_ssize_t
+archive_write_data_block(struct archive *a, const void *buff, size_t s,
+ la_int64_t o)
{
if (a->vtable->archive_write_data_block == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
int
archive_read_data_block(struct archive *a,
- const void **buff, size_t *s, int64_t *o)
+ const void **buff, size_t *s, la_int64_t *o)
{
return ((a->vtable->archive_read_data_block)(a, buff, s, o));
}
.\"
.Ss Set options
See
-.Xr archive_read_set_options 3 .
+.Xr archive_write_set_options 3 .
.\"
.Ss Open archive
See
* an archive to itself recursively.
*/
int
-archive_write_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write *a = (struct archive_write *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
{ ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip },
{ ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
+ { ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd },
{ -1, NULL }
};
{ "lzop", archive_write_add_filter_lzop },
{ "uuencode", archive_write_add_filter_uuencode },
{ "xz", archive_write_add_filter_xz },
+ { "zstd", archive_write_add_filter_zstd },
{ NULL, NULL }
};
data->compressed[7] = (uint8_t)(t>>24)&0xff;
} else
memset(&data->compressed[4], 0, 4);
- data->compressed[8] = 0; /* No deflate options */
+ if (data->compression_level == 9)
+ data->compressed[8] = 2;
+ else if(data->compression_level == 1)
+ data->compressed[8] = 4;
+ else
+ data->compressed[8] = 0;
data->compressed[9] = 3; /* OS=Unix */
data->stream.next_out += 10;
data->stream.avail_out -= 10;
--- /dev/null
+/*-
+ * Copyright (c) 2017 Sean Purcell
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+/* Don't compile this if we don't have zstd.h */
+
+struct private_data {
+ int compression_level;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ ZSTD_CStream *cstream;
+ int64_t total_in;
+ ZSTD_outBuffer out;
+#else
+ struct archive_write_program_data *pdata;
+#endif
+};
+
+static int archive_compressor_zstd_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_compressor_zstd_open(struct archive_write_filter *);
+static int archive_compressor_zstd_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_compressor_zstd_close(struct archive_write_filter *);
+static int archive_compressor_zstd_free(struct archive_write_filter *);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+static int drive_compressor(struct archive_write_filter *,
+ struct private_data *, int, const void *, size_t);
+#endif
+
+
+/*
+ * Add a zstd compression filter to this write handle.
+ */
+int
+archive_write_add_filter_zstd(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct private_data *data;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_zstd");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ f->data = data;
+ f->open = &archive_compressor_zstd_open;
+ f->options = &archive_compressor_zstd_options;
+ f->close = &archive_compressor_zstd_close;
+ f->free = &archive_compressor_zstd_free;
+ f->code = ARCHIVE_FILTER_ZSTD;
+ f->name = "zstd";
+ data->compression_level = 3; /* Default level used by the zstd CLI */
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ data->cstream = ZSTD_createCStream();
+ if (data->cstream == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM,
+ "Failed to allocate zstd compressor object");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate("zstd");
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external zstd program");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+static int
+archive_compressor_zstd_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ ZSTD_freeCStream(data->cstream);
+ free(data->out.dst);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
+ free(data);
+ f->data = NULL;
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ int level = atoi(value);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ if (level < 1 || level > ZSTD_maxCLevel()) {
+#else
+ /* If we don't have the library, hard-code the max level */
+ if (level < 1 || level > 22) {
+#endif
+ return (ARCHIVE_WARN);
+ }
+ data->compression_level = level;
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+/*
+ * Setup callback.
+ */
+static int
+archive_compressor_zstd_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (data->out.dst == NULL) {
+ size_t bs = ZSTD_CStreamOutSize(), bpb;
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of
+ * the of bytes per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+ data->out.size = bs;
+ data->out.pos = 0;
+ data->out.dst
+ = (unsigned char *)malloc(data->out.size);
+ if (data->out.dst == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ }
+
+ f->write = archive_compressor_zstd_write;
+
+ if (ZSTD_isError(ZSTD_initCStream(data->cstream,
+ data->compression_level))) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "Internal error initializing zstd compressor object");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Write data to the compressed stream.
+ */
+static int
+archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int ret;
+
+ /* Update statistics */
+ data->total_in += length;
+
+ if ((ret = drive_compressor(f, data, 0, buff, length)) != ARCHIVE_OK)
+ return (ret);
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Finish the compression...
+ */
+static int
+archive_compressor_zstd_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ int r1, r2;
+
+ /* Finish zstd frame */
+ r1 = drive_compressor(f, data, 1, NULL, 0);
+
+ r2 = __archive_write_close_filter(f->next_filter);
+
+ return r1 < r2 ? r1 : r2;
+}
+
+/*
+ * Utility function to push input data through compressor,
+ * writing full output blocks as necessary.
+ *
+ * Note that this handles both the regular write case (finishing ==
+ * false) and the end-of-archive case (finishing == true).
+ */
+static int
+drive_compressor(struct archive_write_filter *f,
+ struct private_data *data, int finishing, const void *src, size_t length)
+{
+ ZSTD_inBuffer in = (ZSTD_inBuffer) { src, length, 0 };
+
+ for (;;) {
+ if (data->out.pos == data->out.size) {
+ const int ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.size);
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ data->out.pos = 0;
+ }
+
+ /* If there's nothing to do, we're done. */
+ if (!finishing && in.pos == in.size)
+ return (ARCHIVE_OK);
+
+ {
+ const size_t zstdret = !finishing ?
+ ZSTD_compressStream(data->cstream, &data->out, &in)
+ : ZSTD_endStream(data->cstream, &data->out);
+
+ if (ZSTD_isError(zstdret)) {
+ archive_set_error(f->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Zstd compression failed: %s",
+ ZSTD_getErrorName(zstdret));
+ return (ARCHIVE_FATAL);
+ }
+
+ /* If we're finishing, 0 means nothing left to flush */
+ if (finishing && zstdret == 0) {
+ const int ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.pos);
+ return (ret);
+ }
+ }
+ }
+}
+
+#else /* HAVE_ZSTD_H && HAVE_LIBZSTD */
+
+static int
+archive_compressor_zstd_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_string_sprintf(&as, "zstd -%d", data->compression_level);
+
+ f->write = archive_compressor_zstd_write;
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_zstd_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD */
}
int
-archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
int
archive_write_disk_set_group_lookup(struct archive *_a,
void *private_data,
- int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid),
+ la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
void (*cleanup_gid)(void *private))
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
}
int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
}
int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
if ((en == EISDIR || en == EEXIST)
&& (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
/* If we're not overwriting, we're done. */
+ if (S_ISDIR(a->mode)) {
+ /* Don't overwrite any settings on existing directories. */
+ a->todo = 0;
+ }
archive_entry_unset_size(a->entry);
return (ARCHIVE_OK);
}
}
int
-archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
int
archive_write_disk_set_group_lookup(struct archive *_a,
void *private_data,
- int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid),
+ la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
void (*cleanup_gid)(void *private))
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
}
int64_t
-archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
}
int64_t
-archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
}
}
+ if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
+ archive_set_error(&a->archive, en,
+ "Hard-link target '%s' does not exist.",
+ archive_entry_hardlink(a->entry));
+ return (ARCHIVE_FAILED);
+ }
+
if ((en == EISDIR || en == EEXIST)
&& (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
/* If we're not overwriting, we're done. */
+ if (S_ISDIR(a->mode)) {
+ /* Don't overwrite any settings on existing directories. */
+ a->todo = 0;
+ }
archive_entry_unset_size(a->entry);
return (ARCHIVE_OK);
}
.Nm archive_write_add_filter_none ,
.Nm archive_write_add_filter_program ,
.Nm archive_write_add_filter_uuencode ,
-.Nm archive_write_add_filter_xz
+.Nm archive_write_add_filter_xz ,
+.Nm archive_write_add_filter_zstd ,
.Nd functions enabling output filters
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Fn archive_write_add_filter_uuencode "struct archive *"
.Ft int
.Fn archive_write_add_filter_xz "struct archive *"
+.Ft int
+.Fn archive_write_add_filter_zstd "struct archive *"
.Sh DESCRIPTION
.Bl -tag -width indent
.It Xo
.Fn archive_write_add_filter_lzma ,
.Fn archive_write_add_filter_lzop ,
.Fn archive_write_add_filter_xz ,
+.Fn archive_write_add_filter_zstd ,
.Xc
The resulting archive will be compressed as specified.
Note that the compressed output is always properly blocked.
/*
* _7_PPMD compressor.
*/
-static void *
-ppmd_alloc(void *p, size_t size)
-{
- (void)p;
- return malloc(size);
-}
-static void
-ppmd_free(void *p, void *address)
-{
- (void)p;
- free(address);
-}
-static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
static void
ppmd_write(void *p, Byte b)
{
archive_le32enc(props+1, msize);
__archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
r = __archive_ppmd7_functions.Ppmd7_Alloc(
- &strm->ppmd7_context, msize, &g_szalloc);
+ &strm->ppmd7_context, msize);
if (r == 0) {
free(strm->buff);
free(strm);
(void)a; /* UNUSED */
strm = (struct ppmd_stream *)lastrm->real_stream;
- __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc);
+ __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context);
free(strm->buff);
free(strm);
lastrm->real_stream = NULL;
}
memset(buff, ' ', 60);
- strncpy(&buff[AR_fmag_offset], "`\n", 2);
+ memcpy(&buff[AR_fmag_offset], "`\n", 2);
if (strcmp(pathname, "/") == 0 ) {
/* Entry is archive symbol table in GNU format */
}
if (strcmp(pathname, "__.SYMDEF") == 0) {
/* Entry is archive symbol table in BSD format */
- strncpy(buff + AR_name_offset, "__.SYMDEF", 9);
+ memcpy(buff + AR_name_offset, "__.SYMDEF", 9);
goto stat;
}
if (strcmp(pathname, "//") == 0) {
* actually 15 bytes.
*/
if (strlen(filename) <= 15) {
- strncpy(&buff[AR_name_offset],
+ memcpy(&buff[AR_name_offset],
filename, strlen(filename));
buff[AR_name_offset + strlen(filename)] = '/';
} else {
return (ARCHIVE_FATAL);
}
- strncpy(se, filename, strlen(filename));
+ memcpy(se, filename, strlen(filename));
strcpy(se + strlen(filename), "/\n");
ss = strstr(ar->strtab, se);
* archive header.
*/
if (strlen(filename) <= 16 && strchr(filename, ' ') == NULL) {
- strncpy(&buff[AR_name_offset], filename, strlen(filename));
+ memcpy(&buff[AR_name_offset], filename, strlen(filename));
buff[AR_name_offset + strlen(filename)] = ' ';
}
else {
- strncpy(buff + AR_name_offset, "#1/", 3);
+ memcpy(buff + AR_name_offset, "#1/", 3);
if (format_decimal(strlen(filename),
buff + AR_name_offset + 3,
AR_name_size - 3)) {
return (ARCHIVE_WARN);
}
- ar->strtab = (char *)malloc(s);
+ ar->strtab = (char *)malloc(s + 1);
if (ar->strtab == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate strtab buffer");
return (ARCHIVE_FATAL);
}
- strncpy(ar->strtab, buff, s);
+ memcpy(ar->strtab, buff, s);
+ ar->strtab[s] = '\0';
ar->has_strtab = 1;
}
* GNU PAX Format 1.0 requires the special name, which pattern is:
* <dir>/GNUSparseFile.<pid>/<original file name>
*
- * Since reproducable archives are more important, use 0 as pid.
+ * Since reproducible archives are more important, use 0 as pid.
*
* This function is used for only Sparse file, a file type of which
* is regular file.
include(CheckTypeSize)
include(TestBigEndian)
-CHECK_C_SOURCE_COMPILES(
- "int test (void *restrict x);\nint main (void) {return 0;}"
- HAVE_RESTRICT)
-
-CHECK_C_SOURCE_COMPILES(
-"typedef struct abc *d;\nint test (d __restrict x);\nint main (void) {return 0;}"
- HAVE___RESTRICT)
-
-CHECK_C_SOURCE_COMPILES(
- "static inline int test (void) {return 0;}\nint main (void) {return test();}"
- HAVE_INLINE)
-
-CHECK_C_SOURCE_COMPILES (
- "static __inline int test (void) {return 0;}\nint main (void) {return test();}"
- HAVE___INLINE)
-
CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H)
CHECK_INCLUDE_FILE(inttypes.h HAVE_INTTYPES_H)
CHECK_INCLUDE_FILE(limits.h HAVE_LIMITS_H)
CHECK_TYPE_SIZE("unsigned" SIZE_OF_UNSIGNED)
CHECK_TYPE_SIZE("unsigned long" SIZE_OF_UNSIGNED_LONG)
CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG)
-CHECK_TYPE_SIZE("size_t" SIZE_OF_SIZE_T)
+CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
CHECK_TYPE_SIZE("__int64" __INT64)
CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64)
naturally it is not legally required. Here is an example of a good
notice to put into "about box" or into documentation:
- This software includes code from XZ Utils <http://tukaani.org/xz/>.
+ This software includes code from XZ Utils <https://tukaani.org/xz/>.
The following license texts are included in the following files:
- COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
#define MY_VERSION LZMA_VERSION_MAJOR,LZMA_VERSION_MINOR,LZMA_VERSION_PATCH,MY_BUILD
#define MY_FILENAME MY_NAME MY_SUFFIX
-#define MY_COMPANY "The Tukaani Project <http://tukaani.org/>"
+#define MY_COMPANY "The Tukaani Project <https://tukaani.org/>"
#define MY_PRODUCT PACKAGE_NAME " <" PACKAGE_URL ">"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#if defined(_MSC_VER)
# pragma warning(push,1)
+# pragma warning(disable: 4028) /* formal parameter different from decl */
# pragma warning(disable: 4142) /* benign redefinition of type */
# pragma warning(disable: 4761) /* integral size mismatch in argument */
#endif
// The code currently assumes that size_t is either 32-bit or 64-bit.
#ifndef SIZE_MAX
-# if SIZE_OF_SIZE_T == 4
+# if SIZEOF_SIZE_T == 4
# define SIZE_MAX UINT32_MAX
-# elif SIZE_OF_SIZE_T == 8
+# elif SIZEOF_SIZE_T == 8
# define SIZE_MAX UINT64_MAX
# else
# error size_t is not 32-bit or 64-bit
# include <memory.h>
#endif
+// As of MSVC 2013, inline and restrict are supported with
+// non-standard keywords.
+#if defined(_WIN32) && defined(_MSC_VER)
+# ifndef inline
+# define inline __inline
+# endif
+# ifndef restrict
+# define restrict __restrict
+# endif
+#endif
////////////
// Macros //
#endif
+////////////////////////////////
+// Compiler-specific features //
+////////////////////////////////
+
+// Newer Intel C compilers require immintrin.h for _bit_scan_reverse()
+// and such functions.
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
+# include <immintrin.h>
+#endif
+
+
///////////////////
// Byte swapping //
///////////////////
static inline void
unaligned_write16be(uint8_t *buf, uint16_t num)
{
- buf[0] = num >> 8;
- buf[1] = num;
+ buf[0] = (uint8_t)(num >> 8);
+ buf[1] = (uint8_t)num;
return;
}
static inline void
unaligned_write16le(uint8_t *buf, uint16_t num)
{
- buf[0] = num;
- buf[1] = num >> 8;
+ buf[0] = (uint8_t)num;
+ buf[1] = (uint8_t)(num >> 8);
return;
}
static inline void
unaligned_write32be(uint8_t *buf, uint32_t num)
{
- buf[0] = num >> 24;
- buf[1] = num >> 16;
- buf[2] = num >> 8;
- buf[3] = num;
+ buf[0] = (uint8_t)(num >> 24);
+ buf[1] = (uint8_t)(num >> 16);
+ buf[2] = (uint8_t)(num >> 8);
+ buf[3] = (uint8_t)num;
return;
}
static inline void
unaligned_write32le(uint8_t *buf, uint32_t num)
{
- buf[0] = num;
- buf[1] = num >> 8;
- buf[2] = num >> 16;
- buf[3] = num >> 24;
+ buf[0] = (uint8_t)num;
+ buf[1] = (uint8_t)(num >> 8);
+ buf[2] = (uint8_t)(num >> 16);
+ buf[3] = (uint8_t)(num >> 24);
return;
}
@SIZE_OF_UNSIGNED_CODE@
@SIZE_OF_UNSIGNED_LONG_CODE@
@SIZE_OF_UNSIGNED_LONG_LONG_CODE@
-@SIZE_OF_SIZE_T_CODE@
+@SIZEOF_SIZE_T_CODE@
/*
* If we lack int64_t, define it to the first of __int64, int, long, and long long
#cmakedefine uintptr_t @uintptr_t@
-
-#cmakedefine HAVE_RESTRICT
-#cmakedefine HAVE___RESTRICT
-
-#cmakedefine HAVE_INLINE
-#cmakedefine HAVE___INLINE
-
-#ifndef HAVE_RESTRICT
-# ifdef HAVE___RESTRICT
-# define LZMA_RESTRICT __restrict
-# else
-# define LZMA_RESTRICT
-# endif
-#else
-# define LZMA_RESTRICT restrict
-#endif /* HAVE_RESTRICT */
-
-#ifndef HAVE_INLINE
-# ifdef HAVE___INLINE
-# define inline __inline
-# else
-# define inline
-# endif
-#endif /* HAVE_INLINE */
-
-
#cmakedefine WORDS_BIGENDIAN 1
#cmakedefine HAVE_BYTESWAP_H 1
# if !defined(UINT32_C) || !defined(UINT64_C) \
|| !defined(UINT32_MAX) || !defined(UINT64_MAX)
/*
- * MSVC has no C99 support, and thus it cannot be used to
- * compile liblzma. The liblzma API has to still be usable
- * from MSVC, so we need to define the required standard
- * integer types here.
+ * MSVC versions older than 2013 have no C99 support, and
+ * thus they cannot be used to compile liblzma. Using an
+ * existing liblzma.dll with old MSVC can work though(*),
+ * but we need to define the required standard integer
+ * types here in a MSVC-specific way.
+ *
+ * (*) If you do this, the existing liblzma.dll probably uses
+ * a different runtime library than your MSVC-built
+ * application. Mixing runtimes is generally bad, but
+ * in this case it should work as long as you avoid
+ * the few rarely-needed liblzma functions that allocate
+ * memory and expect the caller to free it using free().
*/
-# if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1800
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
*/
#ifndef lzma_nothrow
# if defined(__cplusplus)
-# define lzma_nothrow throw()
+# if __cplusplus >= 201103L
+# define lzma_nothrow noexcept
+# else
+# define lzma_nothrow throw()
+# endif
# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
# define lzma_nothrow __attribute__((__nothrow__))
# else
#include "lzma/filter.h"
#include "lzma/bcj.h"
#include "lzma/delta.h"
-#include "lzma/lzma.h"
+#include "lzma/lzma12.h"
/* Container formats */
#include "lzma/container.h"
/**
* \brief The `action' argument for lzma_code()
*
- * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or LZMA_FINISH,
- * the same `action' must is used until lzma_code() returns LZMA_STREAM_END.
- * Also, the amount of input (that is, strm->avail_in) must not be modified
- * by the application until lzma_code() returns LZMA_STREAM_END. Changing the
- * `action' or modifying the amount of input will make lzma_code() return
- * LZMA_PROG_ERROR.
+ * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER,
+ * or LZMA_FINISH, the same `action' must is used until lzma_code() returns
+ * LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must
+ * not be modified by the application until lzma_code() returns
+ * LZMA_STREAM_END. Changing the `action' or modifying the amount of input
+ * will make lzma_code() return LZMA_PROG_ERROR.
*/
typedef enum {
LZMA_RUN = 0,
*
* All the input data going to the current Block must have
* been given to the encoder (the last bytes can still be
- * pending in* next_in). Call lzma_code() with LZMA_FULL_FLUSH
+ * pending in *next_in). Call lzma_code() with LZMA_FULL_FLUSH
* until it returns LZMA_STREAM_END. Then continue normally
* with LZMA_RUN or finish the Stream with LZMA_FINISH.
*
* no unfinished Block, no empty Block is created.
*/
+ LZMA_FULL_BARRIER = 4,
+ /**<
+ * \brief Finish encoding of the current Block
+ *
+ * This is like LZMA_FULL_FLUSH except that this doesn't
+ * necessarily wait until all the input has been made
+ * available via the output buffer. That is, lzma_code()
+ * might return LZMA_STREAM_END as soon as all the input
+ * has been consumed (avail_in == 0).
+ *
+ * LZMA_FULL_BARRIER is useful with a threaded encoder if
+ * one wants to split the .xz Stream into Blocks at specific
+ * offsets but doesn't care if the output isn't flushed
+ * immediately. Using LZMA_FULL_BARRIER allows keeping
+ * the threads busy while LZMA_FULL_FLUSH would make
+ * lzma_code() wait until all the threads have finished
+ * until more data could be passed to the encoder.
+ *
+ * With a lzma_stream initialized with the single-threaded
+ * lzma_stream_encoder() or lzma_easy_encoder(),
+ * LZMA_FULL_BARRIER is an alias for LZMA_FULL_FLUSH.
+ */
+
LZMA_FINISH = 3
/**<
* \brief Finish the coding operation
* malloc() and free(). C++ users should note that the custom memory
* handling functions must not throw exceptions.
*
- * liblzma doesn't make an internal copy of lzma_allocator. Thus, it is
- * OK to change these function pointers in the middle of the coding
- * process, but obviously it must be done carefully to make sure that the
- * replacement `free' can deallocate memory allocated by the earlier
- * `alloc' function(s).
+ * Single-threaded mode only: liblzma doesn't make an internal copy of
+ * lzma_allocator. Thus, it is OK to change these function pointers in
+ * the middle of the coding process, but obviously it must be done
+ * carefully to make sure that the replacement `free' can deallocate
+ * memory allocated by the earlier `alloc' function(s).
+ *
+ * Multithreaded mode: liblzma might internally store pointers to the
+ * lzma_allocator given via the lzma_stream structure. The application
+ * must not change the allocator pointer in lzma_stream or the contents
+ * of the pointed lzma_allocator structure until lzma_end() has been used
+ * to free the memory associated with that lzma_stream. The allocation
+ * functions might be called simultaneously from multiple threads, and
+ * thus they must be thread safe.
*/
typedef struct {
/**
*
* Application may modify the values of total_in and total_out as it wants.
* They are updated by liblzma to match the amount of data read and
- * written, but aren't used for anything else.
+ * written but aren't used for anything else except as a possible return
+ * values from lzma_get_progress().
*/
typedef struct {
const uint8_t *next_in; /**< Pointer to the next input byte. */
*
* In most cases this is NULL which makes liblzma use
* the standard malloc() and free().
+ *
+ * \note In 5.0.x this is not a const pointer.
*/
- lzma_allocator *allocator;
+ const lzma_allocator *allocator;
/** Internal state is not visible to applications. */
lzma_internal *internal;
/**
+ * \brief Get progress information
+ *
+ * In single-threaded mode, applications can get progress information from
+ * strm->total_in and strm->total_out. In multi-threaded mode this is less
+ * useful because a significant amount of both input and output data gets
+ * buffered internally by liblzma. This makes total_in and total_out give
+ * misleading information and also makes the progress indicator updates
+ * non-smooth.
+ *
+ * This function gives realistic progress information also in multi-threaded
+ * mode by taking into account the progress made by each thread. In
+ * single-threaded mode *progress_in and *progress_out are set to
+ * strm->total_in and strm->total_out, respectively.
+ */
+extern LZMA_API(void) lzma_get_progress(lzma_stream *strm,
+ uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow;
+
+
+/**
* \brief Get the memory usage of decoder filter chain
*
* This function is currently supported only when *strm has been initialized
* This function is supported only when *strm has been initialized with
* a function that takes a memlimit argument.
*
+ * liblzma 5.2.3 and earlier has a bug where memlimit value of 0 causes
+ * this function to do nothing (leaving the limit unchanged) and still
+ * return LZMA_OK. Later versions treat 0 as if 1 had been specified (so
+ * lzma_memlimit_get() will return 1 even if you specify 0 here).
+ *
* \return - LZMA_OK: New memory usage limit successfully set.
* - LZMA_MEMLIMIT_ERROR: The new limit is too small.
* The limit was not changed.
* - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
- * support memory usage limit or memlimit was zero.
+ * support memory usage limit.
*/
extern LZMA_API(lzma_ret) lzma_memlimit_set(
lzma_stream *strm, uint64_t memlimit) lzma_nothrow;
/**
* \brief Block format version
*
- * To prevent API and ABI breakages if new features are needed in
- * the Block field, a version number is used to indicate which
- * fields in this structure are in use. For now, version must always
- * be zero. With non-zero version, most Block related functions will
- * return LZMA_OPTIONS_ERROR.
+ * To prevent API and ABI breakages when new features are needed,
+ * a version number is used to indicate which fields in this
+ * structure are in use:
+ * - liblzma >= 5.0.0: version = 0 is supported.
+ * - liblzma >= 5.1.4beta: Support for version = 1 was added,
+ * which adds the ignore_check field.
+ *
+ * If version is greater than one, most Block related functions
+ * will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works
+ * with any version value).
*
* Read by:
* - All functions that take pointer to lzma_block as argument,
lzma_reserved_enum reserved_enum2;
lzma_reserved_enum reserved_enum3;
lzma_reserved_enum reserved_enum4;
- lzma_bool reserved_bool1;
+
+ /**
+ * \brief A flag to Block decoder to not verify the Check field
+ *
+ * This field is supported by liblzma >= 5.1.4beta if .version >= 1.
+ *
+ * If this is set to true, the integrity check won't be calculated
+ * and verified. Unless you know what you are doing, you should
+ * leave this to false. (A reason to set this to true is when the
+ * file integrity is verified externally anyway and you want to
+ * speed up the decompression, which matters mostly when using
+ * SHA-256 as the integrity check.)
+ *
+ * If .version >= 1, read by:
+ * - lzma_block_decoder()
+ * - lzma_block_buffer_decode()
+ *
+ * Written by (.version is ignored):
+ * - lzma_block_header_decode() always sets this to false
+ */
+ lzma_bool ignore_check;
+
lzma_bool reserved_bool2;
lzma_bool reserved_bool3;
lzma_bool reserved_bool4;
/**
* \brief Decode Block Header
*
- * block->version should be set to the highest value supported by the
- * application; currently the only possible version is zero. This function
- * will set version to the lowest value that still supports all the features
- * required by the Block Header.
+ * block->version should (usually) be set to the highest value supported
+ * by the application. If the application sets block->version to a value
+ * higher than supported by the current liblzma version, this function will
+ * downgrade block->version to the highest value supported by it. Thus one
+ * should check the value of block->version after calling this function if
+ * block->version was set to a non-zero value and the application doesn't
+ * otherwise know that the liblzma version being used is new enough to
+ * support the specified block->version.
*
* The size of the Block Header must have already been decoded with
* lzma_block_header_size_decode() macro and stored to block->header_size.
* block->header_size is invalid or block->filters is NULL.
*/
extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
- lzma_allocator *allocator, const uint8_t *in)
+ const lzma_allocator *allocator, const uint8_t *in)
lzma_nothrow lzma_attr_warn_unused_result;
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
- lzma_block *block, lzma_allocator *allocator,
+ lzma_block *block, const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
+ lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief Single-call uncompressed .xz Block encoder
+ *
+ * This is like lzma_block_buffer_encode() except this doesn't try to
+ * compress the data and instead encodes the data using LZMA2 uncompressed
+ * chunks. The required output buffer size can be determined with
+ * lzma_block_buffer_bound().
+ *
+ * Since the data won't be compressed, this function ignores block->filters.
+ * This function doesn't take lzma_allocator because this function doesn't
+ * allocate any memory from the heap.
+ */
+extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_buffer_decode(
- lzma_block *block, lzma_allocator *allocator,
+ lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow;
/**
+ * \brief Multithreading options
+ */
+typedef struct {
+ /**
+ * \brief Flags
+ *
+ * Set this to zero if no flags are wanted.
+ *
+ * No flags are currently supported.
+ */
+ uint32_t flags;
+
+ /**
+ * \brief Number of worker threads to use
+ */
+ uint32_t threads;
+
+ /**
+ * \brief Maximum uncompressed size of a Block
+ *
+ * The encoder will start a new .xz Block every block_size bytes.
+ * Using LZMA_FULL_FLUSH or LZMA_FULL_BARRIER with lzma_code()
+ * the caller may tell liblzma to start a new Block earlier.
+ *
+ * With LZMA2, a recommended block size is 2-4 times the LZMA2
+ * dictionary size. With very small dictionaries, it is recommended
+ * to use at least 1 MiB block size for good compression ratio, even
+ * if this is more than four times the dictionary size. Note that
+ * these are only recommendations for typical use cases; feel free
+ * to use other values. Just keep in mind that using a block size
+ * less than the LZMA2 dictionary size is waste of RAM.
+ *
+ * Set this to 0 to let liblzma choose the block size depending
+ * on the compression options. For LZMA2 it will be 3*dict_size
+ * or 1 MiB, whichever is more.
+ *
+ * For each thread, about 3 * block_size bytes of memory will be
+ * allocated. This may change in later liblzma versions. If so,
+ * the memory usage will probably be reduced, not increased.
+ */
+ uint64_t block_size;
+
+ /**
+ * \brief Timeout to allow lzma_code() to return early
+ *
+ * Multithreading can make liblzma to consume input and produce
+ * output in a very bursty way: it may first read a lot of input
+ * to fill internal buffers, then no input or output occurs for
+ * a while.
+ *
+ * In single-threaded mode, lzma_code() won't return until it has
+ * either consumed all the input or filled the output buffer. If
+ * this is done in multithreaded mode, it may cause a call
+ * lzma_code() to take even tens of seconds, which isn't acceptable
+ * in all applications.
+ *
+ * To avoid very long blocking times in lzma_code(), a timeout
+ * (in milliseconds) may be set here. If lzma_code() would block
+ * longer than this number of milliseconds, it will return with
+ * LZMA_OK. Reasonable values are 100 ms or more. The xz command
+ * line tool uses 300 ms.
+ *
+ * If long blocking times are fine for you, set timeout to a special
+ * value of 0, which will disable the timeout mechanism and will make
+ * lzma_code() block until all the input is consumed or the output
+ * buffer has been filled.
+ *
+ * \note Even with a timeout, lzma_code() might sometimes take
+ * somewhat long time to return. No timing guarantees
+ * are made.
+ */
+ uint32_t timeout;
+
+ /**
+ * \brief Compression preset (level and possible flags)
+ *
+ * The preset is set just like with lzma_easy_encoder().
+ * The preset is ignored if filters below is non-NULL.
+ */
+ uint32_t preset;
+
+ /**
+ * \brief Filter chain (alternative to a preset)
+ *
+ * If this is NULL, the preset above is used. Otherwise the preset
+ * is ignored and the filter chain specified here is used.
+ */
+ const lzma_filter *filters;
+
+ /**
+ * \brief Integrity check type
+ *
+ * See check.h for available checks. The xz command line tool
+ * defaults to LZMA_CHECK_CRC64, which is a good choice if you
+ * are unsure.
+ */
+ lzma_check check;
+
+ /*
+ * Reserved space to allow possible future extensions without
+ * breaking the ABI. You should not touch these, because the names
+ * of these variables may change. These are and will never be used
+ * with the currently supported options, so it is safe to leave these
+ * uninitialized.
+ */
+ lzma_reserved_enum reserved_enum1;
+ lzma_reserved_enum reserved_enum2;
+ lzma_reserved_enum reserved_enum3;
+ uint32_t reserved_int1;
+ uint32_t reserved_int2;
+ uint32_t reserved_int3;
+ uint32_t reserved_int4;
+ uint64_t reserved_int5;
+ uint64_t reserved_int6;
+ uint64_t reserved_int7;
+ uint64_t reserved_int8;
+ void *reserved_ptr1;
+ void *reserved_ptr2;
+ void *reserved_ptr3;
+ void *reserved_ptr4;
+
+} lzma_mt;
+
+
+/**
* \brief Calculate approximate memory usage of easy encoder
*
* This function is a wrapper for lzma_raw_encoder_memusage().
*/
extern LZMA_API(lzma_ret) lzma_easy_buffer_encode(
uint32_t preset, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+ const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
/**
+ * \brief Calculate approximate memory usage of multithreaded .xz encoder
+ *
+ * Since doing the encoding in threaded mode doesn't affect the memory
+ * requirements of single-threaded decompressor, you can use
+ * lzma_easy_decoder_memusage(options->preset) or
+ * lzma_raw_decoder_memusage(options->filters) to calculate
+ * the decompressor memory requirements.
+ *
+ * \param options Compression options
+ *
+ * \return Number of bytes of memory required for encoding with the
+ * given options. If an error occurs, for example due to
+ * unsupported preset or filter chain, UINT64_MAX is returned.
+ */
+extern LZMA_API(uint64_t) lzma_stream_encoder_mt_memusage(
+ const lzma_mt *options) lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief Initialize multithreaded .xz Stream encoder
+ *
+ * This provides the functionality of lzma_easy_encoder() and
+ * lzma_stream_encoder() as a single function for multithreaded use.
+ *
+ * The supported actions for lzma_code() are LZMA_RUN, LZMA_FULL_FLUSH,
+ * LZMA_FULL_BARRIER, and LZMA_FINISH. Support for LZMA_SYNC_FLUSH might be
+ * added in the future.
+ *
+ * \param strm Pointer to properly prepared lzma_stream
+ * \param options Pointer to multithreaded compression options
+ *
+ * \return - LZMA_OK
+ * - LZMA_MEM_ERROR
+ * - LZMA_UNSUPPORTED_CHECK
+ * - LZMA_OPTIONS_ERROR
+ * - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_encoder_mt(
+ lzma_stream *strm, const lzma_mt *options)
+ lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
* \brief Initialize .lzma encoder (legacy file format)
*
* The .lzma format is sometimes called the LZMA_Alone format, which is the
*/
extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
lzma_filter *filters, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+ const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
/**
+ * This flag makes lzma_code() not calculate and verify the integrity check
+ * of the compressed data in .xz files. This means that invalid integrity
+ * check values won't be detected and LZMA_DATA_ERROR won't be returned in
+ * such cases.
+ *
+ * This flag only affects the checks of the compressed data itself; the CRC32
+ * values in the .xz headers will still be verified normally.
+ *
+ * Don't use this flag unless you know what you are doing. Possible reasons
+ * to use this flag:
+ *
+ * - Trying to recover data from a corrupt .xz file.
+ *
+ * - Speeding up decompression, which matters mostly with SHA-256
+ * or with files that have compressed extremely well. It's recommended
+ * to not use this flag for this purpose unless the file integrity is
+ * verified externally in some other way.
+ *
+ * Support for this flag was added in liblzma 5.1.4beta.
+ */
+#define LZMA_IGNORE_CHECK UINT32_C(0x10)
+
+
+/**
* This flag enables decoding of concatenated files with file formats that
* allow concatenating compressed files as is. From the formats currently
* supported by liblzma, only the .xz format allows concatenated files.
*
* \param strm Pointer to properly prepared lzma_stream
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
- * to effectively disable the limiter.
+ * to effectively disable the limiter. liblzma
+ * 5.2.3 and earlier don't allow 0 here and return
+ * LZMA_PROG_ERROR; later versions treat 0 as if 1
+ * had been specified.
* \param flags Bitwise-or of zero or more of the decoder flags:
* LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
* LZMA_TELL_ANY_CHECK, LZMA_CONCATENATED
*
* \param strm Pointer to properly prepared lzma_stream
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
- * to effectively disable the limiter.
+ * to effectively disable the limiter. liblzma
+ * 5.2.3 and earlier don't allow 0 here and return
+ * LZMA_PROG_ERROR; later versions treat 0 as if 1
+ * had been specified.
* \param flags Bitwise-or of flags, or zero for no flags.
*
* \return - LZMA_OK: Initialization was successful.
/**
* \brief Initialize .lzma decoder (legacy file format)
*
+ * \param strm Pointer to properly prepared lzma_stream
+ * \param memlimit Memory usage limit as bytes. Use UINT64_MAX
+ * to effectively disable the limiter. liblzma
+ * 5.2.3 and earlier don't allow 0 here and return
+ * LZMA_PROG_ERROR; later versions treat 0 as if 1
+ * had been specified.
+ *
* Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
- * There is no need to use LZMA_FINISH, but allowing it may simplify
- * certain types of applications.
+ * There is no need to use LZMA_FINISH, but it's allowed because it may
+ * simplify certain types of applications.
*
* \return - LZMA_OK
* - LZMA_MEM_ERROR
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
- uint64_t *memlimit, uint32_t flags, lzma_allocator *allocator,
+ uint64_t *memlimit, uint32_t flags,
+ const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
* is not NULL.
* - LZMA_PROG_ERROR: src or dest is NULL.
*/
-extern LZMA_API(lzma_ret) lzma_filters_copy(const lzma_filter *src,
- lzma_filter *dest, lzma_allocator *allocator) lzma_nothrow;
+extern LZMA_API(lzma_ret) lzma_filters_copy(
+ const lzma_filter *src, lzma_filter *dest,
+ const lzma_allocator *allocator) lzma_nothrow;
/**
* won't necessarily meet that bound.)
*/
extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
- const lzma_filter *filters, lzma_allocator *allocator,
+ const lzma_filter *filters, const lzma_allocator *allocator,
const uint8_t *in, size_t in_size, uint8_t *out,
size_t *out_pos, size_t out_size) lzma_nothrow;
* which no data is written to is out[out_size].
*/
extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
- const lzma_filter *filters, lzma_allocator *allocator,
+ const lzma_filter *filters, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
* - LZMA_MEM_ERROR
*/
extern LZMA_API(lzma_ret) lzma_properties_decode(
- lzma_filter *filter, lzma_allocator *allocator,
+ lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size) lzma_nothrow;
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
- lzma_filter *filter, lzma_allocator *allocator,
+ lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
lzma_nothrow lzma_attr_warn_unused_result;
* of RAM on the specific operating system.
*/
extern LZMA_API(uint64_t) lzma_physmem(void) lzma_nothrow;
+
+
+/**
+ * \brief Get the number of processor cores or threads
+ *
+ * This function may be useful when determining how many threads to use.
+ * If the hardware supports more than one thread per CPU core, the number
+ * of hardware threads is returned if that information is available.
+ *
+ * \brief On success, the number of available CPU threads or cores is
+ * returned. If this information isn't available or an error
+ * occurs, zero is returned.
+ */
+extern LZMA_API(uint32_t) lzma_cputhreads(void) lzma_nothrow;
* \return On success, a pointer to an empty initialized lzma_index is
* returned. If allocation fails, NULL is returned.
*/
-extern LZMA_API(lzma_index *) lzma_index_init(lzma_allocator *allocator)
+extern LZMA_API(lzma_index *) lzma_index_init(const lzma_allocator *allocator)
lzma_nothrow;
*
* If i is NULL, this does nothing.
*/
-extern LZMA_API(void) lzma_index_end(lzma_index *i, lzma_allocator *allocator)
- lzma_nothrow;
+extern LZMA_API(void) lzma_index_end(
+ lzma_index *i, const lzma_allocator *allocator) lzma_nothrow;
/**
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_index_append(
- lzma_index *i, lzma_allocator *allocator,
+ lzma_index *i, const lzma_allocator *allocator,
lzma_vli unpadded_size, lzma_vli uncompressed_size)
lzma_nothrow lzma_attr_warn_unused_result;
* - LZMA_MEM_ERROR
* - LZMA_PROG_ERROR
*/
-extern LZMA_API(lzma_ret) lzma_index_cat(
- lzma_index *dest, lzma_index *src, lzma_allocator *allocator)
+extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *dest, lzma_index *src,
+ const lzma_allocator *allocator)
lzma_nothrow lzma_attr_warn_unused_result;
* \return A copy of the lzma_index, or NULL if memory allocation failed.
*/
extern LZMA_API(lzma_index *) lzma_index_dup(
- const lzma_index *i, lzma_allocator *allocator)
+ const lzma_index *i, const lzma_allocator *allocator)
lzma_nothrow lzma_attr_warn_unused_result;
* \param i Pointer to lzma_index which should be encoded.
*
* The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
- * It is enough to use only one of them (you can choose freely; use LZMA_RUN
- * to support liblzma versions older than 5.0.0).
+ * It is enough to use only one of them (you can choose freely).
*
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
* - LZMA_MEM_ERROR
* to a new lzma_index, which the application
* has to later free with lzma_index_end().
* \param memlimit How much memory the resulting lzma_index is
- * allowed to require.
+ * allowed to require. liblzma 5.2.3 and earlier
+ * don't allow 0 here and return LZMA_PROG_ERROR;
+ * later versions treat 0 as if 1 had been specified.
*
- * The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
- * It is enough to use only one of them (you can choose freely; use LZMA_RUN
- * to support liblzma versions older than 5.0.0).
+ * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * There is no need to use LZMA_FINISH, but it's allowed because it may
+ * simplify certain types of applications.
*
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
* - LZMA_MEM_ERROR
- * - LZMA_MEMLIMIT_ERROR
* - LZMA_PROG_ERROR
+ *
+ * liblzma 5.2.3 and older list also LZMA_MEMLIMIT_ERROR here
+ * but that error code has never been possible from this
+ * initialization function.
*/
extern LZMA_API(lzma_ret) lzma_index_decoder(
lzma_stream *strm, lzma_index **i, uint64_t memlimit)
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i,
- uint64_t *memlimit, lzma_allocator *allocator,
+ uint64_t *memlimit, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
lzma_nothrow;
* pointer than the index_hash that was given as an argument.
*/
extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
- lzma_index_hash *index_hash, lzma_allocator *allocator)
+ lzma_index_hash *index_hash, const lzma_allocator *allocator)
lzma_nothrow lzma_attr_warn_unused_result;
* \brief Deallocate lzma_index_hash structure
*/
extern LZMA_API(void) lzma_index_hash_end(
- lzma_index_hash *index_hash, lzma_allocator *allocator)
+ lzma_index_hash *index_hash, const lzma_allocator *allocator)
lzma_nothrow;
/**
- * \file lzma/lzma.h
+ * \file lzma/lzma12.h
* \brief LZMA1 and LZMA2 filters
*/
* Version number split into components
*/
#define LZMA_VERSION_MAJOR 5
-#define LZMA_VERSION_MINOR 0
-#define LZMA_VERSION_PATCH 8
+#define LZMA_VERSION_MINOR 2
+#define LZMA_VERSION_PATCH 4
#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
#ifndef LZMA_VERSION_COMMIT
extern LZMA_API(lzma_bool)
lzma_check_is_supported(lzma_check type)
{
+ if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
+ return false;
+
static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = {
true, // LZMA_CHECK_NONE
false, // Reserved
};
- if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
- return false;
-
return available_checks[(unsigned int)(type)];
}
extern LZMA_API(uint32_t)
lzma_check_size(lzma_check type)
{
+ if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
+ return UINT32_MAX;
+
// See file-format.txt section 2.1.1.2.
static const uint8_t check_sizes[LZMA_CHECK_ID_MAX + 1] = {
0,
64, 64, 64
};
- if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
- return UINT32_MAX;
-
return check_sizes[(unsigned int)(type)];
}
#include "common.h"
+// If the function for external SHA-256 is missing, use the internal SHA-256
+// code. Due to how configure works, these defines can only get defined when
+// both a usable header and a type have already been found.
+#if !(defined(HAVE_CC_SHA256_INIT) \
+ || defined(HAVE_SHA256_INIT) \
+ || defined(HAVE_SHA256INIT))
+# define HAVE_INTERNAL_SHA256 1
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+// Nothing
+#elif defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
+# include <CommonCrypto/CommonDigest.h>
+#elif defined(HAVE_SHA256_H)
+# include <sys/types.h>
+# include <sha256.h>
+#elif defined(HAVE_SHA2_H)
+# include <sys/types.h>
+# include <sha2.h>
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+/// State for the internal SHA-256 implementation
+typedef struct {
+ /// Internal state
+ uint32_t state[8];
+
+ /// Size of the message excluding padding
+ uint64_t size;
+} lzma_sha256_state;
+#elif defined(HAVE_CC_SHA256_CTX)
+typedef CC_SHA256_CTX lzma_sha256_state;
+#elif defined(HAVE_SHA256_CTX)
+typedef SHA256_CTX lzma_sha256_state;
+#elif defined(HAVE_SHA2_CTX)
+typedef SHA2_CTX lzma_sha256_state;
+#endif
+
+#if defined(HAVE_INTERNAL_SHA256)
+// Nothing
+#elif defined(HAVE_CC_SHA256_INIT)
+# define LZMA_SHA256FUNC(x) CC_SHA256_ ## x
+#elif defined(HAVE_SHA256_INIT)
+# define LZMA_SHA256FUNC(x) SHA256_ ## x
+#elif defined(HAVE_SHA256INIT)
+# define LZMA_SHA256FUNC(x) SHA256 ## x
+#endif
// Index hashing needs the best possible hash function (preferably
// a cryptographic hash) for maximum reliability.
union {
uint32_t crc32;
uint64_t crc64;
-
- struct {
- /// Internal state
- uint32_t state[8];
-
- /// Size of the message excluding padding
- uint64_t size;
- } sha256;
+ lzma_sha256_state sha256;
} state;
} lzma_check_state;
extern void lzma_check_finish(lzma_check_state *check, lzma_check type);
+#ifndef LZMA_SHA256FUNC
+
/// Prepare SHA-256 state for new input.
extern void lzma_sha256_init(lzma_check_state *check);
/// Finish the SHA-256 calculation and store the result to check->buffer.u8.
extern void lzma_sha256_finish(lzma_check_state *check);
+
+#else
+
+static inline void
+lzma_sha256_init(lzma_check_state *check)
+{
+ LZMA_SHA256FUNC(Init)(&check->state.sha256);
+}
+
+
+static inline void
+lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
+{
+#if defined(HAVE_CC_SHA256_INIT) && SIZE_MAX > UINT32_MAX
+ // Darwin's CC_SHA256_Update takes uint32_t as the buffer size,
+ // so use a loop to support size_t.
+ while (size > UINT32_MAX) {
+ LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, UINT32_MAX);
+ buf += UINT32_MAX;
+ size -= UINT32_MAX;
+ }
+#endif
+
+ LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, size);
+}
+
+
+static inline void
+lzma_sha256_finish(lzma_check_state *check)
+{
+ LZMA_SHA256FUNC(Final)(check->buffer.u8, &check->state.sha256);
+}
+
+#endif
+
#endif
#endif
if (size > 8) {
- const uint8_t * limit;
-
// Fix the alignment, if needed. The if statement above
// ensures that this won't read past the end of buf[].
while ((uintptr_t)(buf) & 7) {
}
// Calculate the position where to stop.
- limit = buf + (size & ~(size_t)(7));
+ const uint8_t *const limit = buf + (size & ~(size_t)(7));
// Calculate how many bytes must be calculated separately
// before returning the result.
// Calculate the CRC32 using the slice-by-eight algorithm.
while (buf < limit) {
- uint32_t tmp;
-
crc ^= *(const uint32_t *)(buf);
buf += 4;
^ lzma_crc32_table[5][C(crc)]
^ lzma_crc32_table[4][D(crc)];
- tmp = *(const uint32_t *)(buf);
+ const uint32_t tmp = *(const uint32_t *)(buf);
buf += 4;
// At least with some compilers, it is critical for
#endif
if (size > 4) {
- const uint8_t *limit;
-
while ((uintptr_t)(buf) & 3) {
crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
--size;
}
- limit = buf + (size & ~(size_t)(3));
+ const uint8_t *const limit = buf + (size & ~(size_t)(3));
size &= (size_t)(3);
while (buf < limit) {
//
///////////////////////////////////////////////////////////////////////////////
-// Avoid bogus warnings in transform().
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __GNUC__ > 4
-# pragma GCC diagnostic ignored "-Wuninitialized"
-#endif
-
#include "check.h"
-// At least on x86, GCC is able to optimize this to a rotate instruction.
-#define rotr_32(num, amount) ((num) >> (amount) | (num) << (32 - (amount)))
+// Rotate a uint32_t. GCC can optimize this to a rotate instruction
+// at least on x86.
+static inline uint32_t
+rotr_32(uint32_t num, unsigned amount)
+{
+ return (num >> amount) | (num << (32 - amount));
+}
-#define blk0(i) (W[i] = data[i])
+#define blk0(i) (W[i] = conv32be(data[i]))
#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
+ s0(W[(i - 15) & 15]))
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
-#define Maj(x, y, z) ((x & y) | (z & (x | y)))
+#define Maj(x, y, z) ((x & (y ^ z)) + (y & z))
#define a(i) T[(0 - i) & 7]
#define b(i) T[(1 - i) & 7]
#define g(i) T[(6 - i) & 7]
#define h(i) T[(7 - i) & 7]
-#define R(i) \
- h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] \
- + (j ? blk2(i) : blk0(i)); \
+#define R(i, j, blk) \
+ h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] + blk; \
d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
+#define R0(i) R(i, 0, blk0(i))
+#define R2(i) R(i, j, blk2(i))
-#define S0(x) (rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22))
-#define S1(x) (rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25))
-#define s0(x) (rotr_32(x, 7) ^ rotr_32(x, 18) ^ (x >> 3))
-#define s1(x) (rotr_32(x, 17) ^ rotr_32(x, 19) ^ (x >> 10))
+#define S0(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 9), 11), 2)
+#define S1(x) rotr_32(x ^ rotr_32(x ^ rotr_32(x, 14), 5), 6)
+#define s0(x) (rotr_32(x ^ rotr_32(x, 11), 7) ^ (x >> 3))
+#define s1(x) (rotr_32(x ^ rotr_32(x, 2), 17) ^ (x >> 10))
static const uint32_t SHA256_K[64] = {
{
uint32_t W[16];
uint32_t T[8];
- unsigned int j;
// Copy state[] to working vars.
memcpy(T, state, sizeof(T));
- // 64 operations, partially loop unrolled
- for (j = 0; j < 64; j += 16) {
- R( 0); R( 1); R( 2); R( 3);
- R( 4); R( 5); R( 6); R( 7);
- R( 8); R( 9); R(10); R(11);
- R(12); R(13); R(14); R(15);
+ // The first 16 operations unrolled
+ R0( 0); R0( 1); R0( 2); R0( 3);
+ R0( 4); R0( 5); R0( 6); R0( 7);
+ R0( 8); R0( 9); R0(10); R0(11);
+ R0(12); R0(13); R0(14); R0(15);
+
+ // The remaining 48 operations partially unrolled
+ for (unsigned int j = 16; j < 64; j += 16) {
+ R2( 0); R2( 1); R2( 2); R2( 3);
+ R2( 4); R2( 5); R2( 6); R2( 7);
+ R2( 8); R2( 9); R2(10); R2(11);
+ R2(12); R2(13); R2(14); R2(15);
}
// Add the working vars back into state[].
static void
process(lzma_check_state *check)
{
-#ifdef WORDS_BIGENDIAN
transform(check->state.sha256.state, check->buffer.u32);
-
-#else
- uint32_t data[16];
- size_t i;
-
- for (i = 0; i < 16; ++i)
- data[i] = bswap32(check->buffer.u32[i]);
-
- transform(check->state.sha256.state, data);
-#endif
-
return;
}
extern void
lzma_sha256_finish(lzma_check_state *check)
{
- size_t i;
-
// Add padding as described in RFC 3174 (it describes SHA-1 but
// the same padding style is used for SHA-256 too).
size_t pos = check->state.sha256.size & 0x3F;
process(check);
- for (i = 0; i < 8; ++i)
+ for (size_t i = 0; i < 8; ++i)
check->buffer.u32[i] = conv32be(check->state.sha256.state[i]);
return;
#include "lz_decoder.h"
-struct lzma_coder_s {
+typedef struct {
lzma_next_coder next;
enum {
/// Options decoded from the header needed to initialize
/// the LZMA decoder
lzma_options_lzma options;
-};
+} lzma_alone_coder;
static lzma_ret
-alone_decode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+alone_decode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action)
{
+ lzma_alone_coder *coder = coder_ptr;
+
while (*out_pos < out_size
&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
switch (coder->sequence) {
// Fall through
case SEQ_CODER_INIT: {
- lzma_ret ret;
+ if (coder->memusage > coder->memlimit)
+ return LZMA_MEMLIMIT_ERROR;
lzma_filter_info filters[2] = {
- { 0, &lzma_lzma_decoder_init, &coder->options },
- { 0, NULL, NULL }
+ {
+ .init = &lzma_lzma_decoder_init,
+ .options = &coder->options,
+ }, {
+ .init = NULL,
+ }
};
- if (coder->memusage > coder->memlimit)
- return LZMA_MEMLIMIT_ERROR;
-
- ret = lzma_next_filter_init(&coder->next,
+ const lzma_ret ret = lzma_next_filter_init(&coder->next,
allocator, filters);
if (ret != LZMA_OK)
return ret;
static void
-alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+alone_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_alone_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
static lzma_ret
-alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+alone_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_alone_coder *coder = coder_ptr;
+
*memusage = coder->memusage;
*old_memlimit = coder->memlimit;
extern lzma_ret
-lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_alone_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, bool picky)
{
lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator);
- if (memlimit == 0)
- return LZMA_PROG_ERROR;
+ lzma_alone_coder *coder = next->coder;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &alone_decode;
next->end = &alone_decoder_end;
next->memconfig = &alone_decoder_memconfig;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
- next->coder->sequence = SEQ_PROPERTIES;
- next->coder->picky = picky;
- next->coder->pos = 0;
- next->coder->options.dict_size = 0;
- next->coder->options.preset_dict = NULL;
- next->coder->options.preset_dict_size = 0;
- next->coder->uncompressed_size = 0;
- next->coder->memlimit = memlimit;
- next->coder->memusage = LZMA_MEMUSAGE_BASE;
+ coder->sequence = SEQ_PROPERTIES;
+ coder->picky = picky;
+ coder->pos = 0;
+ coder->options.dict_size = 0;
+ coder->options.preset_dict = NULL;
+ coder->options.preset_dict_size = 0;
+ coder->uncompressed_size = 0;
+ coder->memlimit = my_max(1, memlimit);
+ coder->memusage = LZMA_MEMUSAGE_BASE;
return LZMA_OK;
}
extern LZMA_API(lzma_ret)
lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
{
- lzma_next_strm_init2(lzma_alone_decoder_init, strm, memlimit, false);
+ lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit, false);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
extern lzma_ret lzma_alone_decoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, bool picky);
#endif
#define ALONE_HEADER_SIZE (1 + 4 + 8)
-struct lzma_coder_s {
+typedef struct {
lzma_next_coder next;
enum {
size_t header_pos;
uint8_t header[ALONE_HEADER_SIZE];
-};
+} lzma_alone_coder;
static lzma_ret
-alone_encode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+alone_encode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action)
{
+ lzma_alone_coder *coder = coder_ptr;
+
while (*out_pos < out_size)
switch (coder->sequence) {
case SEQ_HEADER:
static void
-alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_alone_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
// At least for now, this is not used by any internal function.
static lzma_ret
-alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_options_lzma *options)
{
- uint32_t d;
-
- // Initialize the LZMA encoder.
- const lzma_filter_info filters[2] = {
- { 0, &lzma_lzma_encoder_init, (void *)(options) },
- { 0, NULL, NULL }
- };
-
lzma_next_coder_init(&alone_encoder_init, next, allocator);
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_alone_coder *coder = next->coder;
+
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &alone_encode;
next->end = &alone_encoder_end;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Basic initializations
- next->coder->sequence = SEQ_HEADER;
- next->coder->header_pos = 0;
+ coder->sequence = SEQ_HEADER;
+ coder->header_pos = 0;
// Encode the header:
// - Properties (1 byte)
- if (lzma_lzma_lclppb_encode(options, next->coder->header))
+ if (lzma_lzma_lclppb_encode(options, coder->header))
return LZMA_OPTIONS_ERROR;
// - Dictionary size (4 bytes)
// one is the next unless it is UINT32_MAX. While the header would
// allow any 32-bit integer, we do this to keep the decoder of liblzma
// accepting the resulting files.
- d = options->dict_size - 1;
+ uint32_t d = options->dict_size - 1;
d |= d >> 2;
d |= d >> 3;
d |= d >> 4;
if (d != UINT32_MAX)
++d;
- unaligned_write32le(next->coder->header + 1, d);
+ unaligned_write32le(coder->header + 1, d);
// - Uncompressed size (always unknown and using EOPM)
- memset(next->coder->header + 1 + 4, 0xFF, 8);
+ memset(coder->header + 1 + 4, 0xFF, 8);
+
+ // Initialize the LZMA encoder.
+ const lzma_filter_info filters[2] = {
+ {
+ .init = &lzma_lzma_encoder_init,
+ .options = (void *)(options),
+ }, {
+ .init = NULL,
+ }
+ };
- return lzma_next_filter_init(&next->coder->next, allocator, filters);
+ return lzma_next_filter_init(&coder->next, allocator, filters);
}
/*
extern lzma_ret
-lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_options_alone *options)
{
lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
extern LZMA_API(lzma_ret)
lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
{
- lzma_next_strm_init1(alone_encoder_init, strm, options);
+ lzma_next_strm_init(alone_encoder_init, strm, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
#include "alone_decoder.h"
-struct lzma_coder_s {
+typedef struct {
/// Stream decoder or LZMA_Alone decoder
lzma_next_coder next;
SEQ_CODE,
SEQ_FINISH,
} sequence;
-};
+} lzma_auto_coder;
static lzma_ret
-auto_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+auto_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_auto_coder *coder = coder_ptr;
+
switch (coder->sequence) {
case SEQ_INIT:
if (*in_pos >= in_size)
static void
-auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+auto_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_auto_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
static lzma_check
-auto_decoder_get_check(const lzma_coder *coder)
+auto_decoder_get_check(const void *coder_ptr)
{
+ const lzma_auto_coder *coder = coder_ptr;
+
// It is LZMA_Alone if get_check is NULL.
return coder->next.get_check == NULL ? LZMA_CHECK_NONE
: coder->next.get_check(coder->next.coder);
static lzma_ret
-auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+auto_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_auto_coder *coder = coder_ptr;
+
lzma_ret ret;
if (coder->next.memconfig != NULL) {
// the current memory usage.
*memusage = LZMA_MEMUSAGE_BASE;
*old_memlimit = coder->memlimit;
+
ret = LZMA_OK;
+ if (new_memlimit != 0 && new_memlimit < *memusage)
+ ret = LZMA_MEMLIMIT_ERROR;
}
if (ret == LZMA_OK && new_memlimit != 0)
static lzma_ret
-auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+auto_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, uint32_t flags)
{
lzma_next_coder_init(&auto_decoder_init, next, allocator);
- if (memlimit == 0)
- return LZMA_PROG_ERROR;
-
if (flags & ~LZMA_SUPPORTED_FLAGS)
return LZMA_OPTIONS_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_auto_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_auto_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &auto_decode;
next->end = &auto_decoder_end;
next->get_check = &auto_decoder_get_check;
next->memconfig = &auto_decoder_memconfig;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
- next->coder->memlimit = memlimit;
- next->coder->flags = flags;
- next->coder->sequence = SEQ_INIT;
+ coder->memlimit = my_max(1, memlimit);
+ coder->flags = flags;
+ coder->sequence = SEQ_INIT;
return LZMA_OK;
}
extern LZMA_API(lzma_ret)
lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{
- lzma_next_strm_init2(auto_decoder_init, strm, memlimit, flags);
+ lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
extern LZMA_API(lzma_ret)
-lzma_block_buffer_decode(lzma_block *block, lzma_allocator *allocator,
+lzma_block_buffer_decode(lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder block_decoder;
- lzma_ret ret;
-
if (in_pos == NULL || (in == NULL && *in_pos != in_size)
|| *in_pos > in_size || out_pos == NULL
|| (out == NULL && *out_pos != out_size)
return LZMA_PROG_ERROR;
// Initialize the Block decoder.
- block_decoder = LZMA_NEXT_CODER_INIT;
- ret = lzma_block_decoder_init(&block_decoder, allocator, block);
+ lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT;
+ lzma_ret ret = lzma_block_decoder_init(
+ &block_decoder, allocator, block);
if (ret == LZMA_OK) {
// Save the positions so that we can restore them in case
//
///////////////////////////////////////////////////////////////////////////////
+#include "block_buffer_encoder.h"
#include "block_encoder.h"
#include "filter_encoder.h"
#include "lzma2_encoder.h"
+ LZMA_CHECK_SIZE_MAX + 3) & ~3)
-static lzma_vli
-lzma2_bound(lzma_vli uncompressed_size)
+static uint64_t
+lzma2_bound(uint64_t uncompressed_size)
{
- lzma_vli overhead;
-
// Prevent integer overflow in overhead calculation.
if (uncompressed_size > COMPRESSED_SIZE_MAX)
return 0;
// uncompressed_size up to the next multiple of LZMA2_CHUNK_MAX,
// multiply by the size of per-chunk header, and add one byte for
// the end marker.
- overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
+ const uint64_t overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
/ LZMA2_CHUNK_MAX)
* LZMA2_HEADER_UNCOMPRESSED + 1;
}
-extern LZMA_API(size_t)
-lzma_block_buffer_bound(size_t uncompressed_size)
+extern uint64_t
+lzma_block_buffer_bound64(uint64_t uncompressed_size)
{
- // For now, if the data doesn't compress, we always use uncompressed
- // chunks of LZMA2. In future we may use Subblock filter too, but
- // but for simplicity we probably will still use the same bound
- // calculation even though Subblock filter would have slightly less
- // overhead.
- lzma_vli lzma2_size = lzma2_bound(uncompressed_size);
+ // If the data doesn't compress, we always use uncompressed
+ // LZMA2 chunks.
+ uint64_t lzma2_size = lzma2_bound(uncompressed_size);
if (lzma2_size == 0)
return 0;
// Take Block Padding into account.
- lzma2_size = (lzma2_size + 3) & ~LZMA_VLI_C(3);
+ lzma2_size = (lzma2_size + 3) & ~UINT64_C(3);
-#if SIZE_MAX < LZMA_VLI_MAX
- // Catch the possible integer overflow on 32-bit systems. There's no
- // overflow on 64-bit systems, because lzma2_bound() already takes
+ // No risk of integer overflow because lzma2_bound() already takes
// into account the size of the headers in the Block.
- if (SIZE_MAX - HEADERS_BOUND < lzma2_size)
+ return HEADERS_BOUND + lzma2_size;
+}
+
+
+extern LZMA_API(size_t)
+lzma_block_buffer_bound(size_t uncompressed_size)
+{
+ uint64_t ret = lzma_block_buffer_bound64(uncompressed_size);
+
+#if SIZE_MAX < UINT64_MAX
+ // Catch the possible integer overflow on 32-bit systems.
+ if (ret > SIZE_MAX)
return 0;
#endif
- return HEADERS_BOUND + lzma2_size;
+ return ret;
}
block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- size_t in_pos = 0;
- uint8_t control = 0x01; // Dictionary reset
- lzma_filter *filters_orig;
-
- // TODO: Figure out if the last filter is LZMA2 or Subblock and use
- // that filter to encode the uncompressed chunks.
-
// Use LZMA2 uncompressed chunks. We wouldn't need a dictionary at
// all, but LZMA2 always requires a dictionary, so use the minimum
// value to minimize memory usage of the decoder.
- lzma_options_lzma lzma2 = { LZMA_DICT_SIZE_MIN };
+ lzma_options_lzma lzma2 = {
+ .dict_size = LZMA_DICT_SIZE_MIN,
+ };
lzma_filter filters[2];
filters[0].id = LZMA_FILTER_LZMA2;
// Set the above filter options to *block temporarily so that we can
// encode the Block Header.
- filters_orig = block->filters;
+ lzma_filter *filters_orig = block->filters;
block->filters = filters;
if (lzma_block_header_size(block) != LZMA_OK) {
*out_pos += block->header_size;
// Encode the data using LZMA2 uncompressed chunks.
+ size_t in_pos = 0;
+ uint8_t control = 0x01; // Dictionary reset
while (in_pos < in_size) {
- size_t copy_size;
-
// Control byte: Indicate uncompressed chunk, of which
// the first resets the dictionary.
out[(*out_pos)++] = control;
control = 0x02; // No dictionary reset
// Size of the uncompressed chunk
- copy_size = my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
+ const size_t copy_size
+ = my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
out[(*out_pos)++] = (copy_size - 1) >> 8;
out[(*out_pos)++] = (copy_size - 1) & 0xFF;
static lzma_ret
-block_encode_normal(lzma_block *block, lzma_allocator *allocator,
+block_encode_normal(lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- size_t out_start;
- lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT;
- lzma_ret ret;
-
// Find out the size of the Block Header.
- block->compressed_size = lzma2_bound(in_size);
- if (block->compressed_size == 0)
- return LZMA_DATA_ERROR;
-
- block->uncompressed_size = in_size;
return_if_error(lzma_block_header_size(block));
// Reserve space for the Block Header and skip it for now.
if (out_size - *out_pos <= block->header_size)
return LZMA_BUF_ERROR;
- out_start = *out_pos;
+ const size_t out_start = *out_pos;
*out_pos += block->header_size;
// Limit out_size so that we stop encoding if the output would grow
// TODO: In many common cases this could be optimized to use
// significantly less memory.
- ret = lzma_raw_encoder_init(
+ lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT;
+ lzma_ret ret = lzma_raw_encoder_init(
&raw_encoder, allocator, block->filters);
if (ret == LZMA_OK) {
}
-extern LZMA_API(lzma_ret)
-lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
+static lzma_ret
+block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t in_size,
- uint8_t *out, size_t *out_pos, size_t out_size)
+ uint8_t *out, size_t *out_pos, size_t out_size,
+ bool try_to_compress)
{
- size_t check_size;
- lzma_ret ret;
- size_t i;
-
// Validate the arguments.
if (block == NULL || (in == NULL && in_size != 0) || out == NULL
|| out_pos == NULL || *out_pos > out_size)
// The contents of the structure may depend on the version so
// check the version before validating the contents of *block.
- if (block->version != 0)
+ if (block->version > 1)
return LZMA_OPTIONS_ERROR;
if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX
- || block->filters == NULL)
+ || (try_to_compress && block->filters == NULL))
return LZMA_PROG_ERROR;
if (!lzma_check_is_supported(block->check))
out_size -= (out_size - *out_pos) & 3;
// Get the size of the Check field.
- check_size = lzma_check_size(block->check);
+ const size_t check_size = lzma_check_size(block->check);
assert(check_size != UINT32_MAX);
// Reserve space for the Check field.
out_size -= check_size;
+ // Initialize block->uncompressed_size and calculate the worst-case
+ // value for block->compressed_size.
+ block->uncompressed_size = in_size;
+ block->compressed_size = lzma2_bound(in_size);
+ if (block->compressed_size == 0)
+ return LZMA_DATA_ERROR;
+
// Do the actual compression.
- ret = block_encode_normal(block, allocator,
- in, in_size, out, out_pos, out_size);
+ lzma_ret ret = LZMA_BUF_ERROR;
+ if (try_to_compress)
+ ret = block_encode_normal(block, allocator,
+ in, in_size, out, out_pos, out_size);
+
if (ret != LZMA_OK) {
// If the error was something else than output buffer
// becoming full, return the error now.
// Block Padding. No buffer overflow here, because we already adjusted
// out_size so that (out_size - out_start) is a multiple of four.
// Thus, if the buffer is full, the loop body can never run.
- for (i = (size_t)(block->compressed_size); i & 3; ++i) {
+ for (size_t i = (size_t)(block->compressed_size); i & 3; ++i) {
assert(*out_pos < out_size);
out[(*out_pos)++] = 0x00;
}
return LZMA_OK;
}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
+{
+ return block_buffer_encode(block, allocator,
+ in, in_size, out, out_pos, out_size, true);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_uncomp_encode(lzma_block *block,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
+{
+ // It won't allocate any memory from heap so no need
+ // for lzma_allocator.
+ return block_buffer_encode(block, NULL,
+ in, in_size, out, out_pos, out_size, false);
+}
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file block_buffer_encoder.h
+/// \brief Single-call .xz Block encoder
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BLOCK_BUFFER_ENCODER_H
+#define LZMA_BLOCK_BUFFER_ENCODER_H
+
+#include "common.h"
+
+
+/// uint64_t version of lzma_block_buffer_bound(). It is used by
+/// stream_encoder_mt.c. Probably the original lzma_block_buffer_bound()
+/// should have been 64-bit, but fixing it would break the ABI.
+extern uint64_t lzma_block_buffer_bound64(uint64_t uncompressed_size);
+
+#endif
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_CODE,
SEQ_PADDING,
/// Check of the uncompressed data
lzma_check_state check;
-};
+
+ /// True if the integrity check won't be calculated and verified.
+ bool ignore_check;
+} lzma_block_coder;
static inline bool
static lzma_ret
-block_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+block_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_block_coder *coder = coder_ptr;
+
switch (coder->sequence) {
case SEQ_CODE: {
const size_t in_start = *in_pos;
coder->block->uncompressed_size))
return LZMA_DATA_ERROR;
- lzma_check_update(&coder->check, coder->block->check,
- out + out_start, out_used);
+ if (!coder->ignore_check)
+ lzma_check_update(&coder->check, coder->block->check,
+ out + out_start, out_used);
if (ret != LZMA_STREAM_END)
return ret;
if (coder->block->check == LZMA_CHECK_NONE)
return LZMA_STREAM_END;
- lzma_check_finish(&coder->check, coder->block->check);
+ if (!coder->ignore_check)
+ lzma_check_finish(&coder->check, coder->block->check);
+
coder->sequence = SEQ_CHECK;
// Fall through
// Validate the Check only if we support it.
// coder->check.buffer may be uninitialized
// when the Check ID is not supported.
- if (lzma_check_is_supported(coder->block->check)
+ if (!coder->ignore_check
+ && lzma_check_is_supported(coder->block->check)
&& memcmp(coder->block->raw_check,
coder->check.buffer.u8,
check_size) != 0)
static void
-block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+block_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_block_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
extern lzma_ret
-lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
lzma_block *block)
{
lzma_next_coder_init(&lzma_block_decoder_init, next, allocator);
|| !lzma_vli_is_valid(block->uncompressed_size))
return LZMA_PROG_ERROR;
- // Allocate and initialize *next->coder if needed.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ // Allocate *next->coder if needed.
+ lzma_block_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_block_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &block_decode;
next->end = &block_decoder_end;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Basic initializations
- next->coder->sequence = SEQ_CODE;
- next->coder->block = block;
- next->coder->compressed_size = 0;
- next->coder->uncompressed_size = 0;
+ coder->sequence = SEQ_CODE;
+ coder->block = block;
+ coder->compressed_size = 0;
+ coder->uncompressed_size = 0;
// If Compressed Size is not known, we calculate the maximum allowed
// value so that encoded size of the Block (including Block Padding)
// is still a valid VLI and a multiple of four.
- next->coder->compressed_limit
+ coder->compressed_limit
= block->compressed_size == LZMA_VLI_UNKNOWN
? (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
- block->header_size
// Initialize the check. It's caller's problem if the Check ID is not
// supported, and the Block decoder cannot verify the Check field.
// Caller can test lzma_check_is_supported(block->check).
- next->coder->check_pos = 0;
- lzma_check_init(&next->coder->check, block->check);
+ coder->check_pos = 0;
+ lzma_check_init(&coder->check, block->check);
+
+ coder->ignore_check = block->version >= 1
+ ? block->ignore_check : false;
// Initialize the filter chain.
- return lzma_raw_decoder_init(&next->coder->next, allocator,
+ return lzma_raw_decoder_init(&coder->next, allocator,
block->filters);
}
extern LZMA_API(lzma_ret)
lzma_block_decoder(lzma_stream *strm, lzma_block *block)
{
- lzma_next_strm_init1(lzma_block_decoder_init, strm, block);
+ lzma_next_strm_init(lzma_block_decoder_init, strm, block);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_block *block);
+ const lzma_allocator *allocator, lzma_block *block);
#endif
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
/// The filters in the chain; initialized with lzma_raw_decoder_init().
lzma_next_coder next;
/// Check of the uncompressed data
lzma_check_state check;
-};
+} lzma_block_coder;
static lzma_ret
-block_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+block_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_block_coder *coder = coder_ptr;
+
// Check that our amount of input stays in proper limits.
if (LZMA_VLI_MAX - coder->uncompressed_size < in_size - *in_pos)
return LZMA_DATA_ERROR;
static void
-block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+block_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_block_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
static lzma_ret
-block_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+block_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_block_coder *coder = coder_ptr;
+
if (coder->sequence != SEQ_CODE)
return LZMA_PROG_ERROR;
extern lzma_ret
-lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_block_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
lzma_block *block)
{
lzma_next_coder_init(&lzma_block_encoder_init, next, allocator);
// The contents of the structure may depend on the version so
// check the version first.
- if (block->version != 0)
+ if (block->version > 1)
return LZMA_OPTIONS_ERROR;
// If the Check ID is not supported, we cannot calculate the check and
return LZMA_UNSUPPORTED_CHECK;
// Allocate and initialize *next->coder if needed.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_block_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_block_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &block_encode;
next->end = &block_encoder_end;
next->update = &block_encoder_update;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Basic initializations
- next->coder->sequence = SEQ_CODE;
- next->coder->block = block;
- next->coder->compressed_size = 0;
- next->coder->uncompressed_size = 0;
- next->coder->pos = 0;
+ coder->sequence = SEQ_CODE;
+ coder->block = block;
+ coder->compressed_size = 0;
+ coder->uncompressed_size = 0;
+ coder->pos = 0;
// Initialize the check
- lzma_check_init(&next->coder->check, block->check);
+ lzma_check_init(&coder->check, block->check);
// Initialize the requested filters.
- return lzma_raw_encoder_init(&next->coder->next, allocator,
- block->filters);
+ return lzma_raw_encoder_init(&coder->next, allocator, block->filters);
}
extern LZMA_API(lzma_ret)
lzma_block_encoder(lzma_stream *strm, lzma_block *block)
{
- lzma_next_strm_init1(lzma_block_encoder_init, strm, block);
+ lzma_next_strm_init(lzma_block_encoder_init, strm, block);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_block *block);
+ const lzma_allocator *allocator, lzma_block *block);
#endif
static void
-free_properties(lzma_block *block, lzma_allocator *allocator)
+free_properties(lzma_block *block, const lzma_allocator *allocator)
{
- size_t i;
-
// Free allocated filter options. The last array member is not
// touched after the initialization in the beginning of
// lzma_block_header_decode(), so we don't need to touch that here.
- for (i = 0; i < LZMA_FILTERS_MAX; ++i) {
+ for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) {
lzma_free(block->filters[i].options, allocator);
block->filters[i].id = LZMA_VLI_UNKNOWN;
block->filters[i].options = NULL;
extern LZMA_API(lzma_ret)
lzma_block_header_decode(lzma_block *block,
- lzma_allocator *allocator, const uint8_t *in)
+ const lzma_allocator *allocator, const uint8_t *in)
{
- const size_t filter_count = (in[1] & 3) + 1;
- size_t in_size;
- size_t i;
-
- // Start after the Block Header Size and Block Flags fields.
- size_t in_pos = 2;
-
// NOTE: We consider the header to be corrupt not only when the
// CRC32 doesn't match, but also when variable-length integers
// are invalid or over 63 bits, or if the header is too small
// Initialize the filter options array. This way the caller can
// safely free() the options even if an error occurs in this function.
- for (i = 0; i <= LZMA_FILTERS_MAX; ++i) {
+ for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
block->filters[i].id = LZMA_VLI_UNKNOWN;
block->filters[i].options = NULL;
}
- // Always zero for now.
- block->version = 0;
+ // Versions 0 and 1 are supported. If a newer version was specified,
+ // we need to downgrade it.
+ if (block->version > 1)
+ block->version = 1;
+
+ // This isn't a Block Header option, but since the decompressor will
+ // read it if version >= 1, it's better to initialize it here than
+ // to expect the caller to do it since in almost all cases this
+ // should be false.
+ block->ignore_check = false;
// Validate Block Header Size and Check type. The caller must have
// already set these, so it is a programming error if this test fails.
return LZMA_PROG_ERROR;
// Exclude the CRC32 field.
- in_size = block->header_size - 4;
+ const size_t in_size = block->header_size - 4;
// Verify CRC32
if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size))
if (in[1] & 0x3C)
return LZMA_OPTIONS_ERROR;
+ // Start after the Block Header Size and Block Flags fields.
+ size_t in_pos = 2;
+
// Compressed Size
if (in[1] & 0x40) {
return_if_error(lzma_vli_decode(&block->compressed_size,
block->uncompressed_size = LZMA_VLI_UNKNOWN;
// Filter Flags
- for (i = 0; i < filter_count; ++i) {
+ const size_t filter_count = (in[1] & 3) + 1;
+ for (size_t i = 0; i < filter_count; ++i) {
const lzma_ret ret = lzma_filter_flags_decode(
&block->filters[i], allocator,
in, &in_pos, in_size);
extern LZMA_API(lzma_ret)
lzma_block_header_size(lzma_block *block)
{
- size_t i;
+ if (block->version > 1)
+ return LZMA_OPTIONS_ERROR;
// Block Header Size + Block Flags + CRC32.
uint32_t size = 1 + 1 + 4;
- if (block->version != 0)
- return LZMA_OPTIONS_ERROR;
-
// Compressed Size
if (block->compressed_size != LZMA_VLI_UNKNOWN) {
const uint32_t add = lzma_vli_size(block->compressed_size);
if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
return LZMA_PROG_ERROR;
- for (i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
- uint32_t add;
-
+ for (size_t i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
// Don't allow too many filters.
if (i == LZMA_FILTERS_MAX)
return LZMA_PROG_ERROR;
+ uint32_t add;
return_if_error(lzma_filter_flags_size(&add,
block->filters + i));
extern LZMA_API(lzma_ret)
lzma_block_header_encode(const lzma_block *block, uint8_t *out)
{
- size_t out_size;
- size_t out_pos = 2;
- size_t filter_count = 0;
-
// Validate everything but filters.
if (lzma_block_unpadded_size(block) == 0
|| !lzma_vli_is_valid(block->uncompressed_size))
return LZMA_PROG_ERROR;
// Indicate the size of the buffer _excluding_ the CRC32 field.
- out_size = block->header_size - 4;
+ const size_t out_size = block->header_size - 4;
// Store the Block Header Size.
out[0] = out_size / 4;
// We write Block Flags in pieces.
out[1] = 0x00;
+ size_t out_pos = 2;
// Compressed Size
if (block->compressed_size != LZMA_VLI_UNKNOWN) {
if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
return LZMA_PROG_ERROR;
+ size_t filter_count = 0;
do {
// There can be a maximum of four filters.
if (filter_count == LZMA_FILTERS_MAX)
extern LZMA_API(lzma_ret)
lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
{
- uint32_t container_size;
- lzma_vli compressed_size;
-
// Validate everything but Uncompressed Size and filters.
if (lzma_block_unpadded_size(block) == 0)
return LZMA_PROG_ERROR;
- container_size = block->header_size
+ const uint32_t container_size = block->header_size
+ lzma_check_size(block->check);
// Validate that Compressed Size will be greater than zero.
// Calculate what Compressed Size is supposed to be.
// If Compressed Size was present in Block Header,
// compare that the new value matches it.
- compressed_size = unpadded_size - container_size;
+ const lzma_vli compressed_size = unpadded_size - container_size;
if (block->compressed_size != LZMA_VLI_UNKNOWN
&& block->compressed_size != compressed_size)
return LZMA_DATA_ERROR;
extern LZMA_API(lzma_vli)
lzma_block_unpadded_size(const lzma_block *block)
{
- lzma_vli unpadded_size;
-
// Validate the values that we are interested in i.e. all but
// Uncompressed Size and the filters.
//
// NOTE: This function is used for validation too, so it is
// essential that these checks are always done even if
// Compressed Size is unknown.
- if (block == NULL || block->version != 0
+ if (block == NULL || block->version > 1
|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
|| (block->header_size & 3)
return LZMA_VLI_UNKNOWN;
// Calculate Unpadded Size and validate it.
- unpadded_size = block->compressed_size
+ const lzma_vli unpadded_size = block->compressed_size
+ block->header_size
+ lzma_check_size(block->check);
///////////////////////
extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
-lzma_alloc(size_t size, lzma_allocator *allocator)
+lzma_alloc(size_t size, const lzma_allocator *allocator)
{
- void *ptr;
-
// Some malloc() variants return NULL if called with size == 0.
if (size == 0)
size = 1;
+ void *ptr;
+
if (allocator != NULL && allocator->alloc != NULL)
ptr = allocator->alloc(allocator->opaque, 1, size);
else
}
+extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
+lzma_alloc_zero(size_t size, const lzma_allocator *allocator)
+{
+ // Some calloc() variants return NULL if called with size == 0.
+ if (size == 0)
+ size = 1;
+
+ void *ptr;
+
+ if (allocator != NULL && allocator->alloc != NULL) {
+ ptr = allocator->alloc(allocator->opaque, 1, size);
+ if (ptr != NULL)
+ memzero(ptr, size);
+ } else {
+ ptr = calloc(1, size);
+ }
+
+ return ptr;
+}
+
+
extern void
-lzma_free(void *ptr, lzma_allocator *allocator)
+lzma_free(void *ptr, const lzma_allocator *allocator)
{
if (allocator != NULL && allocator->free != NULL)
allocator->free(allocator->opaque, ptr);
//////////
extern size_t
-lzma_bufcpy(const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size)
+lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size)
{
const size_t in_avail = in_size - *in_pos;
const size_t out_avail = out_size - *out_pos;
extern lzma_ret
-lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
lzma_next_coder_init(filters[0].init, next, allocator);
extern lzma_ret
-lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *reversed_filters)
{
// Check that the application isn't trying to change the Filter ID.
extern void
-lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
+lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
{
if (next->init != (uintptr_t)(NULL)) {
// To avoid tiny end functions that simply call
strm->internal->next = LZMA_NEXT_CODER_INIT;
}
- strm->internal->supported_actions[LZMA_RUN] = false;
- strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false;
- strm->internal->supported_actions[LZMA_FULL_FLUSH] = false;
- strm->internal->supported_actions[LZMA_FINISH] = false;
+ memzero(strm->internal->supported_actions,
+ sizeof(strm->internal->supported_actions));
strm->internal->sequence = ISEQ_RUN;
strm->internal->allow_buf_error = false;
extern LZMA_API(lzma_ret)
lzma_code(lzma_stream *strm, lzma_action action)
{
- size_t in_pos = 0;
- size_t out_pos = 0;
- lzma_ret ret;
-
// Sanity checks
if ((strm->next_in == NULL && strm->avail_in != 0)
|| (strm->next_out == NULL && strm->avail_out != 0)
|| strm->internal == NULL
|| strm->internal->next.code == NULL
- || (unsigned int)(action) > LZMA_FINISH
+ || (unsigned int)(action) > LZMA_ACTION_MAX
|| !strm->internal->supported_actions[action])
return LZMA_PROG_ERROR;
case LZMA_FINISH:
strm->internal->sequence = ISEQ_FINISH;
break;
+
+ case LZMA_FULL_BARRIER:
+ strm->internal->sequence = ISEQ_FULL_BARRIER;
+ break;
}
break;
break;
+ case ISEQ_FULL_BARRIER:
+ if (action != LZMA_FULL_BARRIER
+ || strm->internal->avail_in != strm->avail_in)
+ return LZMA_PROG_ERROR;
+
+ break;
+
case ISEQ_END:
return LZMA_STREAM_END;
return LZMA_PROG_ERROR;
}
- ret = strm->internal->next.code(
+ size_t in_pos = 0;
+ size_t out_pos = 0;
+ lzma_ret ret = strm->internal->next.code(
strm->internal->next.coder, strm->allocator,
strm->next_in, &in_pos, strm->avail_in,
strm->next_out, &out_pos, strm->avail_out, action);
strm->internal->avail_in = strm->avail_in;
- switch (ret) {
+ // Cast is needed to silence a warning about LZMA_TIMED_OUT, which
+ // isn't part of lzma_ret enumeration.
+ switch ((unsigned int)(ret)) {
case LZMA_OK:
// Don't return LZMA_BUF_ERROR when it happens the first time.
// This is to avoid returning LZMA_BUF_ERROR when avail_out
}
break;
+ case LZMA_TIMED_OUT:
+ strm->internal->allow_buf_error = false;
+ ret = LZMA_OK;
+ break;
+
case LZMA_STREAM_END:
if (strm->internal->sequence == ISEQ_SYNC_FLUSH
- || strm->internal->sequence == ISEQ_FULL_FLUSH)
+ || strm->internal->sequence == ISEQ_FULL_FLUSH
+ || strm->internal->sequence
+ == ISEQ_FULL_BARRIER)
strm->internal->sequence = ISEQ_RUN;
else
strm->internal->sequence = ISEQ_END;
}
+extern LZMA_API(void)
+lzma_get_progress(lzma_stream *strm,
+ uint64_t *progress_in, uint64_t *progress_out)
+{
+ if (strm->internal->next.get_progress != NULL) {
+ strm->internal->next.get_progress(strm->internal->next.coder,
+ progress_in, progress_out);
+ } else {
+ *progress_in = strm->total_in;
+ *progress_out = strm->total_out;
+ }
+
+ return;
+}
+
+
extern LZMA_API(lzma_check)
lzma_get_check(const lzma_stream *strm)
{
|| strm->internal->next.memconfig == NULL)
return LZMA_PROG_ERROR;
- if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
- return LZMA_MEMLIMIT_ERROR;
+ // Zero is a special value that cannot be used as an actual limit.
+ // If 0 was specified, use 1 instead.
+ if (new_memlimit == 0)
+ new_memlimit = 1;
return strm->internal->next.memconfig(strm->internal->next.coder,
&memusage, &old_memlimit, new_memlimit);
#define LZMA_BUFFER_SIZE 4096
+/// Maximum number of worker threads within one multithreaded component.
+/// The limit exists solely to make it simpler to prevent integer overflows
+/// when allocating structures etc. This should be big enough for now...
+/// the code won't scale anywhere close to this number anyway.
+#define LZMA_THREADS_MAX 16384
+
+
/// Starting value for memory usage estimates. Instead of calculating size
/// of _every_ structure and taking into account malloc() overhead etc., we
/// add a base size to all memory usage estimates. It's not very accurate
( LZMA_TELL_NO_CHECK \
| LZMA_TELL_UNSUPPORTED_CHECK \
| LZMA_TELL_ANY_CHECK \
+ | LZMA_IGNORE_CHECK \
| LZMA_CONCATENATED )
-/// Type of encoder/decoder specific data; the actual structure is defined
-/// differently in different coders.
-typedef struct lzma_coder_s lzma_coder;
+/// Largest valid lzma_action value as unsigned integer.
+#define LZMA_ACTION_MAX ((unsigned int)(LZMA_FULL_BARRIER))
+
+
+/// Special return value (lzma_ret) to indicate that a timeout was reached
+/// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to
+/// LZMA_OK in lzma_code(). This is not in the lzma_ret enumeration because
+/// there's no need to have it in the public API.
+#define LZMA_TIMED_OUT 32
+
typedef struct lzma_next_coder_s lzma_next_coder;
/// Type of a function used to initialize a filter encoder or decoder
typedef lzma_ret (*lzma_init_function)(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters);
/// Type of a function to do some kind of coding work (filters, Stream,
/// input and output buffers, but for simplicity they still use this same
/// function prototype.
typedef lzma_ret (*lzma_code_function)(
- lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+ void *coder, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action);
/// Type of a function to free the memory allocated for the coder
typedef void (*lzma_end_function)(
- lzma_coder *coder, lzma_allocator *allocator);
+ void *coder, const lzma_allocator *allocator);
/// Raw coder validates and converts an array of lzma_filter structures to
/// Hold data and function pointers of the next filter in the chain.
struct lzma_next_coder_s {
/// Pointer to coder-specific data
- lzma_coder *coder;
+ void *coder;
/// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't
/// point to a filter coder.
/// lzma_next_coder.coder.
lzma_end_function end;
+ /// Pointer to a function to get progress information. If this is NULL,
+ /// lzma_stream.total_in and .total_out are used instead.
+ void (*get_progress)(void *coder,
+ uint64_t *progress_in, uint64_t *progress_out);
+
/// Pointer to function to return the type of the integrity check.
/// Most coders won't support this.
- lzma_check (*get_check)(const lzma_coder *coder);
+ lzma_check (*get_check)(const void *coder);
/// Pointer to function to get and/or change the memory usage limit.
/// If new_memlimit == 0, the limit is not changed.
- lzma_ret (*memconfig)(lzma_coder *coder, uint64_t *memusage,
+ lzma_ret (*memconfig)(void *coder, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit);
/// Update the filter-specific options or the whole filter chain
/// in the encoder.
- lzma_ret (*update)(lzma_coder *coder, lzma_allocator *allocator,
+ lzma_ret (*update)(void *coder, const lzma_allocator *allocator,
const lzma_filter *filters,
const lzma_filter *reversed_filters);
};
-/// Constant to initialize lzma_next_coder structure
-static const lzma_next_coder LZMA_NEXT_CODER_INIT =
- {
- NULL,
- LZMA_VLI_UNKNOWN,
- (uintptr_t)(NULL),
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- };
+/// Macro to initialize lzma_next_coder structure
+#define LZMA_NEXT_CODER_INIT \
+ (lzma_next_coder){ \
+ .coder = NULL, \
+ .init = (uintptr_t)(NULL), \
+ .id = LZMA_VLI_UNKNOWN, \
+ .code = NULL, \
+ .end = NULL, \
+ .get_progress = NULL, \
+ .get_check = NULL, \
+ .memconfig = NULL, \
+ .update = NULL, \
+ }
/// Internal data for lzma_strm_init, lzma_code, and lzma_end. A pointer to
ISEQ_SYNC_FLUSH,
ISEQ_FULL_FLUSH,
ISEQ_FINISH,
+ ISEQ_FULL_BARRIER,
ISEQ_END,
ISEQ_ERROR,
} sequence;
size_t avail_in;
/// Indicates which lzma_action values are allowed by next.code.
- bool supported_actions[4];
+ bool supported_actions[LZMA_ACTION_MAX + 1];
/// If true, lzma_code will return LZMA_BUF_ERROR if no progress was
/// made (no input consumed and no output produced by next.code).
/// Allocates memory
-extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
+extern void *lzma_alloc(size_t size, const lzma_allocator *allocator)
lzma_attribute((__malloc__)) lzma_attr_alloc_size(1);
+/// Allocates memory and zeroes it (like calloc()). This can be faster
+/// than lzma_alloc() + memzero() while being backward compatible with
+/// custom allocators.
+extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
+ lzma_alloc_zero(size_t size, const lzma_allocator *allocator);
+
/// Frees memory
-extern void lzma_free(void *ptr, lzma_allocator *allocator);
+extern void lzma_free(void *ptr, const lzma_allocator *allocator);
/// Allocates strm->internal if it is NULL, and initializes *strm and
-/// strm->internal. This function is only called via lzma_next_strm_init2 macro.
+/// strm->internal. This function is only called via lzma_next_strm_init macro.
extern lzma_ret lzma_strm_init(lzma_stream *strm);
/// Initializes the next filter in the chain, if any. This takes care of
/// than the filter being initialized now. This way the actual filter
/// initialization functions don't need to use lzma_next_coder_init macro.
extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
/// Update the next filter in the chain, if any. This checks that
/// the application is not trying to change the Filter IDs.
extern lzma_ret lzma_next_filter_update(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *reversed_filters);
/// Frees the memory allocated for next->coder either using next->end or,
/// if next->end is NULL, using lzma_free.
-extern void lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator);
+extern void lzma_next_end(lzma_next_coder *next,
+ const lzma_allocator *allocator);
/// Copy as much data as possible from in[] to out[] and update *in_pos
/// and *out_pos accordingly. Returns the number of bytes copied.
-extern size_t lzma_bufcpy(const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size);
+extern size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size);
/// \brief Return if expression doesn't evaluate to LZMA_OK
/// (The function being called will use lzma_next_coder_init()). If
/// initialization fails, memory that wasn't freed by func() is freed
/// along strm->internal.
-#define lzma_next_strm_init1(func, strm, arg1) \
+#define lzma_next_strm_init(func, strm, ...) \
do { \
- lzma_ret ret_; \
- return_if_error(lzma_strm_init(strm)); \
- ret_ = func(&(strm)->internal->next, (strm)->allocator, arg1); \
- if (ret_ != LZMA_OK) { \
- lzma_end(strm); \
- return ret_; \
- } \
-} while (0)
-
-#define lzma_next_strm_init2(func, strm, arg1, arg2) \
-do { \
- lzma_ret ret_; \
- return_if_error(lzma_strm_init(strm)); \
- ret_ = func(&(strm)->internal->next, (strm)->allocator, arg1, arg2); \
- if (ret_ != LZMA_OK) { \
- lzma_end(strm); \
- return ret_; \
- } \
-} while (0)
-
-#define lzma_next_strm_init3(func, strm, arg1, arg2, arg3) \
-do { \
- lzma_ret ret_; \
- return_if_error(lzma_strm_init(strm)); \
- ret_ = func(&(strm)->internal->next, (strm)->allocator, arg1, arg2, arg3); \
- if (ret_ != LZMA_OK) { \
- lzma_end(strm); \
- return ret_; \
- } \
+ return_if_error(lzma_strm_init(strm)); \
+ const lzma_ret ret_ = func(&(strm)->internal->next, \
+ (strm)->allocator, __VA_ARGS__); \
+ if (ret_ != LZMA_OK) { \
+ lzma_end(strm); \
+ return ret_; \
+ } \
} while (0)
#endif
extern LZMA_API(lzma_ret)
lzma_easy_buffer_encode(uint32_t preset, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
- uint8_t *out, size_t *out_pos, size_t out_size)
+ const lzma_allocator *allocator, const uint8_t *in,
+ size_t in_size, uint8_t *out, size_t *out_pos, size_t out_size)
{
lzma_options_easy opt_easy;
if (lzma_easy_preset(&opt_easy, preset))
///////////////////////////////////////////////////////////////////////////////
#include "easy_preset.h"
-#include "stream_encoder.h"
extern LZMA_API(lzma_ret)
extern LZMA_API(lzma_ret)
-lzma_raw_buffer_decode(const lzma_filter *filters, lzma_allocator *allocator,
+lzma_raw_buffer_decode(
+ const lzma_filter *filters, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder next = LZMA_NEXT_CODER_INIT;
- size_t in_start;
- size_t out_start;
- lzma_ret ret;
-
// Validate what isn't validated later in filter_common.c.
if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL
|| out_pos == NULL || *out_pos > out_size)
return LZMA_PROG_ERROR;
// Initialize the decoer.
+ lzma_next_coder next = LZMA_NEXT_CODER_INIT;
return_if_error(lzma_raw_decoder_init(&next, allocator, filters));
// Store the positions so that we can restore them if something
// goes wrong.
- in_start = *in_pos;
- out_start = *out_pos;
+ const size_t in_start = *in_pos;
+ const size_t out_start = *out_pos;
// Do the actual decoding and free decoder's memory.
- ret = next.code(next.coder, allocator, in, in_pos, in_size,
+ lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size,
out, out_pos, out_size, LZMA_FINISH);
if (ret == LZMA_STREAM_END) {
extern LZMA_API(lzma_ret)
-lzma_raw_buffer_encode(const lzma_filter *filters, lzma_allocator *allocator,
- const uint8_t *in, size_t in_size, uint8_t *out,
- size_t *out_pos, size_t out_size)
+lzma_raw_buffer_encode(
+ const lzma_filter *filters, const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
+ uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder next = LZMA_NEXT_CODER_INIT;
- size_t out_start;
- size_t in_pos = 0;
- lzma_ret ret;
-
// Validate what isn't validated later in filter_common.c.
if ((in == NULL && in_size != 0) || out == NULL
|| out_pos == NULL || *out_pos > out_size)
return LZMA_PROG_ERROR;
// Initialize the encoder
+ lzma_next_coder next = LZMA_NEXT_CODER_INIT;
return_if_error(lzma_raw_encoder_init(&next, allocator, filters));
// Store the output position so that we can restore it if
// something goes wrong.
- out_start = *out_pos;
+ const size_t out_start = *out_pos;
// Do the actual encoding and free coder's memory.
- ret = next.code(next.coder, allocator, in, &in_pos, in_size,
+ size_t in_pos = 0;
+ lzma_ret ret = next.code(next.coder, allocator, in, &in_pos, in_size,
out, out_pos, out_size, LZMA_FINISH);
lzma_next_end(&next, allocator);
} features[] = {
#if defined (HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1)
{
- LZMA_FILTER_LZMA1,
- sizeof(lzma_options_lzma),
- false,
- true,
- true,
+ .id = LZMA_FILTER_LZMA1,
+ .options_size = sizeof(lzma_options_lzma),
+ .non_last_ok = false,
+ .last_ok = true,
+ .changes_size = true,
},
#endif
#if defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
{
- LZMA_FILTER_LZMA2,
- sizeof(lzma_options_lzma),
- false,
- true,
- true,
+ .id = LZMA_FILTER_LZMA2,
+ .options_size = sizeof(lzma_options_lzma),
+ .non_last_ok = false,
+ .last_ok = true,
+ .changes_size = true,
},
#endif
#if defined(HAVE_ENCODER_X86) || defined(HAVE_DECODER_X86)
{
- LZMA_FILTER_X86,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_X86,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
{
- LZMA_FILTER_POWERPC,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_POWERPC,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_IA64) || defined(HAVE_DECODER_IA64)
{
- LZMA_FILTER_IA64,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_IA64,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
{
- LZMA_FILTER_ARM,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_ARM,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
{
- LZMA_FILTER_ARMTHUMB,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_ARMTHUMB,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
{
- LZMA_FILTER_SPARC,
- sizeof(lzma_options_bcj),
- true,
- false,
- false,
+ .id = LZMA_FILTER_SPARC,
+ .options_size = sizeof(lzma_options_bcj),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
{
- LZMA_FILTER_DELTA,
- sizeof(lzma_options_delta),
- true,
- false,
- false,
+ .id = LZMA_FILTER_DELTA,
+ .options_size = sizeof(lzma_options_delta),
+ .non_last_ok = true,
+ .last_ok = false,
+ .changes_size = false,
},
#endif
{
- LZMA_VLI_UNKNOWN
+ .id = LZMA_VLI_UNKNOWN
}
};
extern LZMA_API(lzma_ret)
lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
- lzma_allocator *allocator)
+ const lzma_allocator *allocator)
{
- size_t i;
- lzma_ret ret;
-
if (src == NULL || dest == NULL)
return LZMA_PROG_ERROR;
+ lzma_ret ret;
+ size_t i;
for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
// There must be a maximum of four filters plus
// the array terminator.
static lzma_ret
validate_chain(const lzma_filter *filters, size_t *count)
{
+ // There must be at least one filter.
+ if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
+ return LZMA_PROG_ERROR;
+
// Number of non-last filters that may change the size of the data
// significantly (that is, more than 1-2 % or so).
size_t changes_size_count = 0;
bool last_ok = false;
size_t i = 0;
-
- // There must be at least one filter.
- if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
- return LZMA_PROG_ERROR;
-
do {
size_t j;
for (j = 0; filters[i].id != features[j].id; ++j)
extern lzma_ret
-lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_raw_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options,
lzma_filter_find coder_find, bool is_encoder)
{
- lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
- size_t count;
- size_t i;
- lzma_ret ret;
-
// Do some basic validation and get the number of filters.
+ size_t count;
return_if_error(validate_chain(options, &count));
// Set the filter functions and copy the options pointer.
+ lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
if (is_encoder) {
- for (i = 0; i < count; ++i) {
+ for (size_t i = 0; i < count; ++i) {
// The order of the filters is reversed in the
// encoder. It allows more efficient handling
// of the uncompressed data.
filters[j].options = options[i].options;
}
} else {
- for (i = 0; i < count; ++i) {
+ for (size_t i = 0; i < count; ++i) {
const lzma_filter_coder *const fc
= coder_find(options[i].id);
if (fc == NULL || fc->init == NULL)
filters[count].init = NULL;
// Initialize the filters.
- ret = lzma_next_filter_init(next, allocator, filters);
+ const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
if (ret != LZMA_OK)
lzma_next_end(next, allocator);
lzma_raw_coder_memusage(lzma_filter_find coder_find,
const lzma_filter *filters)
{
- uint64_t total = 0;
- size_t i = 0;
-
// The chain has to have at least one filter.
{
size_t tmp;
return UINT64_MAX;
}
+ uint64_t total = 0;
+ size_t i = 0;
+
do {
const lzma_filter_coder *const fc
= coder_find(filters[i].id);
extern lzma_ret lzma_raw_coder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *filters,
lzma_filter_find coder_find, bool is_encoder);
/// \return - LZMA_OK: Properties decoded successfully.
/// - LZMA_OPTIONS_ERROR: Unsupported properties
/// - LZMA_MEM_ERROR: Memory allocation failed.
- lzma_ret (*props_decode)(void **options, lzma_allocator *allocator,
+ lzma_ret (*props_decode)(
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
} lzma_filter_decoder;
static const lzma_filter_decoder decoders[] = {
#ifdef HAVE_DECODER_LZMA1
{
- LZMA_FILTER_LZMA1,
- &lzma_lzma_decoder_init,
- &lzma_lzma_decoder_memusage,
- &lzma_lzma_props_decode,
+ .id = LZMA_FILTER_LZMA1,
+ .init = &lzma_lzma_decoder_init,
+ .memusage = &lzma_lzma_decoder_memusage,
+ .props_decode = &lzma_lzma_props_decode,
},
#endif
#ifdef HAVE_DECODER_LZMA2
{
- LZMA_FILTER_LZMA2,
- &lzma_lzma2_decoder_init,
- &lzma_lzma2_decoder_memusage,
- &lzma_lzma2_props_decode,
+ .id = LZMA_FILTER_LZMA2,
+ .init = &lzma_lzma2_decoder_init,
+ .memusage = &lzma_lzma2_decoder_memusage,
+ .props_decode = &lzma_lzma2_props_decode,
},
#endif
#ifdef HAVE_DECODER_X86
{
- LZMA_FILTER_X86,
- &lzma_simple_x86_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_X86,
+ .init = &lzma_simple_x86_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_POWERPC
{
- LZMA_FILTER_POWERPC,
- &lzma_simple_powerpc_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_POWERPC,
+ .init = &lzma_simple_powerpc_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_IA64
{
- LZMA_FILTER_IA64,
- &lzma_simple_ia64_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_IA64,
+ .init = &lzma_simple_ia64_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_ARM
{
- LZMA_FILTER_ARM,
- &lzma_simple_arm_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_ARM,
+ .init = &lzma_simple_arm_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_ARMTHUMB
{
- LZMA_FILTER_ARMTHUMB,
- &lzma_simple_armthumb_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_ARMTHUMB,
+ .init = &lzma_simple_armthumb_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_SPARC
{
- LZMA_FILTER_SPARC,
- &lzma_simple_sparc_decoder_init,
- NULL,
- &lzma_simple_props_decode,
+ .id = LZMA_FILTER_SPARC,
+ .init = &lzma_simple_sparc_decoder_init,
+ .memusage = NULL,
+ .props_decode = &lzma_simple_props_decode,
},
#endif
#ifdef HAVE_DECODER_DELTA
{
- LZMA_FILTER_DELTA,
- &lzma_delta_decoder_init,
- &lzma_delta_coder_memusage,
- &lzma_delta_props_decode,
+ .id = LZMA_FILTER_DELTA,
+ .init = &lzma_delta_decoder_init,
+ .memusage = &lzma_delta_coder_memusage,
+ .props_decode = &lzma_delta_props_decode,
},
#endif
};
static const lzma_filter_decoder *
decoder_find(lzma_vli id)
{
- size_t i;
- for (i = 0; i < ARRAY_SIZE(decoders); ++i)
+ for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
if (decoders[i].id == id)
return decoders + i;
extern lzma_ret
-lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options)
{
return lzma_raw_coder_init(next, allocator,
extern LZMA_API(lzma_ret)
lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
{
- lzma_next_strm_init1(lzma_raw_decoder_init, strm, options);
+ lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
extern LZMA_API(lzma_ret)
-lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator,
+lzma_properties_decode(lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- const lzma_filter_decoder *const fd = decoder_find(filter->id);
-
// Make it always NULL so that the caller can always safely free() it.
filter->options = NULL;
+ const lzma_filter_decoder *const fd = decoder_find(filter->id);
if (fd == NULL)
return LZMA_OPTIONS_ERROR;
extern lzma_ret lzma_raw_decoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options);
#endif
/// invalid, UINT64_MAX is returned.
uint64_t (*memusage)(const void *options);
- /// Calculates the minimum sane size for Blocks (or other types of
- /// chunks) to which the input data can be split to make
- /// multithreaded encoding possible. If this is NULL, it is assumed
- /// that the encoder is fast enough with single thread.
- lzma_vli (*chunk_size)(const void *options);
+ /// Calculates the recommended Uncompressed Size for .xz Blocks to
+ /// which the input data can be split to make multithreaded
+ /// encoding possible. If this is NULL, it is assumed that
+ /// the encoder is fast enough with single thread.
+ uint64_t (*block_size)(const void *options);
/// Tells the size of the Filter Properties field. If options are
/// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed
static const lzma_filter_encoder encoders[] = {
#ifdef HAVE_ENCODER_LZMA1
{
- LZMA_FILTER_LZMA1,
- &lzma_lzma_encoder_init,
- &lzma_lzma_encoder_memusage,
- NULL, // FIXME
- NULL,
- 5,
- &lzma_lzma_props_encode,
+ .id = LZMA_FILTER_LZMA1,
+ .init = &lzma_lzma_encoder_init,
+ .memusage = &lzma_lzma_encoder_memusage,
+ .block_size = NULL, // FIXME
+ .props_size_get = NULL,
+ .props_size_fixed = 5,
+ .props_encode = &lzma_lzma_props_encode,
},
#endif
#ifdef HAVE_ENCODER_LZMA2
{
- LZMA_FILTER_LZMA2,
- &lzma_lzma2_encoder_init,
- &lzma_lzma2_encoder_memusage,
- NULL, // FIXME
- NULL,
- 1,
- &lzma_lzma2_props_encode,
+ .id = LZMA_FILTER_LZMA2,
+ .init = &lzma_lzma2_encoder_init,
+ .memusage = &lzma_lzma2_encoder_memusage,
+ .block_size = &lzma_lzma2_block_size, // FIXME
+ .props_size_get = NULL,
+ .props_size_fixed = 1,
+ .props_encode = &lzma_lzma2_props_encode,
},
#endif
#ifdef HAVE_ENCODER_X86
{
- LZMA_FILTER_X86,
- &lzma_simple_x86_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_X86,
+ .init = &lzma_simple_x86_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_POWERPC
{
- LZMA_FILTER_POWERPC,
- &lzma_simple_powerpc_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_POWERPC,
+ .init = &lzma_simple_powerpc_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_IA64
{
- LZMA_FILTER_IA64,
- &lzma_simple_ia64_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_IA64,
+ .init = &lzma_simple_ia64_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_ARM
{
- LZMA_FILTER_ARM,
- &lzma_simple_arm_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_ARM,
+ .init = &lzma_simple_arm_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_ARMTHUMB
{
- LZMA_FILTER_ARMTHUMB,
- &lzma_simple_armthumb_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_ARMTHUMB,
+ .init = &lzma_simple_armthumb_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_SPARC
{
- LZMA_FILTER_SPARC,
- &lzma_simple_sparc_encoder_init,
- NULL,
- NULL,
- &lzma_simple_props_size,
- 0,
- &lzma_simple_props_encode,
+ .id = LZMA_FILTER_SPARC,
+ .init = &lzma_simple_sparc_encoder_init,
+ .memusage = NULL,
+ .block_size = NULL,
+ .props_size_get = &lzma_simple_props_size,
+ .props_encode = &lzma_simple_props_encode,
},
#endif
#ifdef HAVE_ENCODER_DELTA
{
- LZMA_FILTER_DELTA,
- &lzma_delta_encoder_init,
- &lzma_delta_coder_memusage,
- NULL,
- NULL,
- 1,
- &lzma_delta_props_encode,
+ .id = LZMA_FILTER_DELTA,
+ .init = &lzma_delta_encoder_init,
+ .memusage = &lzma_delta_coder_memusage,
+ .block_size = NULL,
+ .props_size_get = NULL,
+ .props_size_fixed = 1,
+ .props_encode = &lzma_delta_props_encode,
},
#endif
};
static const lzma_filter_encoder *
encoder_find(lzma_vli id)
{
- size_t i;
- for (i = 0; i < ARRAY_SIZE(encoders); ++i)
+ for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i)
if (encoders[i].id == id)
return encoders + i;
extern LZMA_API(lzma_ret)
lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
{
- size_t i;
- size_t count = 1;
- lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1];
-
if (strm->internal->next.update == NULL)
return LZMA_PROG_ERROR;
// The actual filter chain in the encoder is reversed. Some things
// still want the normal order chain, so we provide both.
+ size_t count = 1;
while (filters[count].id != LZMA_VLI_UNKNOWN)
++count;
- for (i = 0; i < count; ++i)
+ lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1];
+ for (size_t i = 0; i < count; ++i)
reversed_filters[count - i - 1] = filters[i];
reversed_filters[count].id = LZMA_VLI_UNKNOWN;
extern lzma_ret
-lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *options)
{
return lzma_raw_coder_init(next, allocator,
extern LZMA_API(lzma_ret)
lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
{
- lzma_next_strm_init3(lzma_raw_coder_init, strm, options,
+ lzma_next_strm_init(lzma_raw_coder_init, strm, options,
(lzma_filter_find)(&encoder_find), true);
strm->internal->supported_actions[LZMA_RUN] = true;
}
-/*
-extern LZMA_API(lzma_vli)
-lzma_chunk_size(const lzma_filter *filters)
+extern uint64_t
+lzma_mt_block_size(const lzma_filter *filters)
{
- lzma_vli max = 0;
+ uint64_t max = 0;
for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
const lzma_filter_encoder *const fe
= encoder_find(filters[i].id);
- if (fe->chunk_size != NULL) {
- const lzma_vli size
- = fe->chunk_size(filters[i].options);
- if (size == LZMA_VLI_UNKNOWN)
- return LZMA_VLI_UNKNOWN;
+ if (fe->block_size != NULL) {
+ const uint64_t size
+ = fe->block_size(filters[i].options);
+ if (size == 0)
+ return 0;
if (size > max)
max = size;
return max;
}
-*/
extern LZMA_API(lzma_ret)
#include "common.h"
-// FIXME: Might become a part of the public API once finished.
-// extern lzma_vli lzma_chunk_size(const lzma_filter *filters);
+// FIXME: Might become a part of the public API.
+extern uint64_t lzma_mt_block_size(const lzma_filter *filters);
extern lzma_ret lzma_raw_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *filters);
#endif
extern LZMA_API(lzma_ret)
lzma_filter_flags_decode(
- lzma_filter *filter, lzma_allocator *allocator,
+ lzma_filter *filter, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
{
- lzma_vli props_size;
- lzma_ret ret;
-
// Set the pointer to NULL so the caller can always safely free it.
filter->options = NULL;
return LZMA_DATA_ERROR;
// Size of Properties
+ lzma_vli props_size;
return_if_error(lzma_vli_decode(&props_size, NULL,
in, in_pos, in_size));
if (in_size - *in_pos < props_size)
return LZMA_DATA_ERROR;
- ret = lzma_properties_decode(
+ const lzma_ret ret = lzma_properties_decode(
filter, allocator, in + *in_pos, props_size);
*in_pos += props_size;
lzma_filter_flags_encode(const lzma_filter *filter,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- uint32_t props_size;
-
// Filter ID
if (filter->id >= LZMA_FILTER_RESERVED_START)
return LZMA_PROG_ERROR;
out, out_pos, out_size));
// Size of Properties
+ uint32_t props_size;
return_if_error(lzma_properties_size(&props_size, filter));
return_if_error(lzma_vli_encode(props_size, NULL,
out, out_pos, out_size));
///////////////////////////////////////////////////////////////////////////////
//
-/// \file stream_encoder.h
-/// \brief Encodes .xz Streams
+/// \file hardware_cputhreads.c
+/// \brief Get the number of CPU threads or cores
//
// Author: Lasse Collin
//
//
///////////////////////////////////////////////////////////////////////////////
-#ifndef LZMA_STREAM_ENCODER_H
-#define LZMA_STREAM_ENCODER_H
-
#include "common.h"
+#include "tuklib_cpucores.h"
-extern lzma_ret lzma_stream_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter *filters, lzma_check check);
-#endif
+extern LZMA_API(uint32_t)
+lzma_cputhreads(void)
+{
+ return tuklib_cpucores();
+}
/// Helper for index_tree_end()
static void
-index_tree_node_end(index_tree_node *node, lzma_allocator *allocator,
- void (*free_func)(void *node, lzma_allocator *allocator))
+index_tree_node_end(index_tree_node *node, const lzma_allocator *allocator,
+ void (*free_func)(void *node, const lzma_allocator *allocator))
{
// The tree won't ever be very huge, so recursion should be fine.
// 20 levels in the tree is likely quite a lot already in practice.
if (node->right != NULL)
index_tree_node_end(node->right, allocator, free_func);
- if (free_func != NULL)
- free_func(node, allocator);
-
- lzma_free(node, allocator);
+ free_func(node, allocator);
return;
}
-/// Free the meory allocated for a tree. If free_func is not NULL,
-/// it is called on each node before freeing the node. This is used
-/// to free the Record groups from each index_stream before freeing
-/// the index_stream itself.
+/// Free the memory allocated for a tree. Each node is freed using the
+/// given free_func which is either &lzma_free or &index_stream_end.
+/// The latter is used to free the Record groups from each index_stream
+/// before freeing the index_stream itself.
static void
-index_tree_end(index_tree *tree, lzma_allocator *allocator,
- void (*free_func)(void *node, lzma_allocator *allocator))
+index_tree_end(index_tree *tree, const lzma_allocator *allocator,
+ void (*free_func)(void *node, const lzma_allocator *allocator))
{
+ assert(free_func != NULL);
+
if (tree->root != NULL)
index_tree_node_end(tree->root, allocator, free_func);
static void
index_tree_append(index_tree *tree, index_tree_node *node)
{
- uint32_t up;
node->parent = tree->rightmost;
node->left = NULL;
node->right = NULL;
// and thus know the state of the tree just by looking at the node
// count. From the node count we can calculate how many steps to go
// up in the tree to find the rotation root.
- up = tree->count ^ (UINT32_C(1) << bsr32(tree->count));
+ uint32_t up = tree->count ^ (UINT32_C(1) << bsr32(tree->count));
if (up != 0) {
- index_tree_node *pivot;
-
// Locate the root node for the rotation.
up = ctz32(tree->count) + 2;
do {
} while (--up > 0);
// Rotate left using node as the rotation root.
- pivot = node->right;
+ index_tree_node *pivot = node->right;
if (node->parent == NULL) {
tree->root = pivot;
/// Allocate and initialize a new Stream using the given base offsets.
static index_stream *
index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base,
- lzma_vli stream_number, lzma_vli block_number_base,
- lzma_allocator *allocator)
+ uint32_t stream_number, lzma_vli block_number_base,
+ const lzma_allocator *allocator)
{
index_stream *s = lzma_alloc(sizeof(index_stream), allocator);
if (s == NULL)
/// Free the memory allocated for a Stream and its Record groups.
static void
-index_stream_end(void *node, lzma_allocator *allocator)
+index_stream_end(void *node, const lzma_allocator *allocator)
{
index_stream *s = node;
- index_tree_end(&s->groups, allocator, NULL);
+ index_tree_end(&s->groups, allocator, &lzma_free);
+ lzma_free(s, allocator);
return;
}
static lzma_index *
-index_init_plain(lzma_allocator *allocator)
+index_init_plain(const lzma_allocator *allocator)
{
lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator);
if (i != NULL) {
extern LZMA_API(lzma_index *)
-lzma_index_init(lzma_allocator *allocator)
+lzma_index_init(const lzma_allocator *allocator)
{
- index_stream *s;
-
lzma_index *i = index_init_plain(allocator);
if (i == NULL)
return NULL;
- s = index_stream_init(0, 0, 1, 0, allocator);
+ index_stream *s = index_stream_init(0, 0, 1, 0, allocator);
if (s == NULL) {
lzma_free(i, allocator);
return NULL;
extern LZMA_API(void)
-lzma_index_end(lzma_index *i, lzma_allocator *allocator)
+lzma_index_end(lzma_index *i, const lzma_allocator *allocator)
{
// NOTE: If you modify this function, check also the bottom
// of lzma_index_cat().
extern LZMA_API(lzma_ret)
lzma_index_stream_flags(lzma_index *i, const lzma_stream_flags *stream_flags)
{
- index_stream *s;
-
if (i == NULL || stream_flags == NULL)
return LZMA_PROG_ERROR;
return_if_error(lzma_stream_flags_compare(
stream_flags, stream_flags));
- s = (index_stream *)(i->streams.rightmost);
+ index_stream *s = (index_stream *)(i->streams.rightmost);
s->stream_flags = *stream_flags;
return LZMA_OK;
extern LZMA_API(lzma_ret)
lzma_index_stream_padding(lzma_index *i, lzma_vli stream_padding)
{
- index_stream *s;
- lzma_vli old_stream_padding;
-
if (i == NULL || stream_padding > LZMA_VLI_MAX
|| (stream_padding & 3) != 0)
return LZMA_PROG_ERROR;
- s = (index_stream *)(i->streams.rightmost);
+ index_stream *s = (index_stream *)(i->streams.rightmost);
// Check that the new value won't make the file grow too big.
- old_stream_padding = s->stream_padding;
+ const lzma_vli old_stream_padding = s->stream_padding;
s->stream_padding = 0;
if (lzma_index_file_size(i) + stream_padding > LZMA_VLI_MAX) {
s->stream_padding = old_stream_padding;
extern LZMA_API(lzma_ret)
-lzma_index_append(lzma_index *i, lzma_allocator *allocator,
+lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
lzma_vli unpadded_size, lzma_vli uncompressed_size)
{
- index_stream *s;
- index_group *g;
- lzma_vli compressed_base;
- lzma_vli uncompressed_base;
- uint32_t index_list_size_add;
-
// Validate.
if (i == NULL || unpadded_size < UNPADDED_SIZE_MIN
|| unpadded_size > UNPADDED_SIZE_MAX
|| uncompressed_size > LZMA_VLI_MAX)
return LZMA_PROG_ERROR;
- s = (index_stream *)(i->streams.rightmost);
- g = (index_group *)(s->groups.rightmost);
+ index_stream *s = (index_stream *)(i->streams.rightmost);
+ index_group *g = (index_group *)(s->groups.rightmost);
- compressed_base = g == NULL ? 0
+ const lzma_vli compressed_base = g == NULL ? 0
: vli_ceil4(g->records[g->last].unpadded_sum);
- uncompressed_base = g == NULL ? 0
+ const lzma_vli uncompressed_base = g == NULL ? 0
: g->records[g->last].uncompressed_sum;
- index_list_size_add = lzma_vli_size(unpadded_size)
+ const uint32_t index_list_size_add = lzma_vli_size(unpadded_size)
+ lzma_vli_size(uncompressed_size);
// Check that the file size will stay within limits.
extern LZMA_API(lzma_ret)
-lzma_index_cat(lzma_index *LZMA_RESTRICT dest, lzma_index *LZMA_RESTRICT src,
- lzma_allocator *allocator)
+lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
+ const lzma_allocator *allocator)
{
- index_cat_info info;
const lzma_vli dest_file_size = lzma_index_file_size(dest);
// Check that we don't exceed the file size limits.
index_stream *s = (index_stream *)(dest->streams.rightmost);
index_group *g = (index_group *)(s->groups.rightmost);
if (g != NULL && g->last + 1 < g->allocated) {
- index_group *newg;
-
assert(g->node.left == NULL);
assert(g->node.right == NULL);
- newg = lzma_alloc(sizeof(index_group)
+ index_group *newg = lzma_alloc(sizeof(index_group)
+ (g->last + 1)
* sizeof(index_record),
allocator);
s->groups.rightmost = &newg->node;
lzma_free(g, allocator);
+
+ // NOTE: newg isn't leaked here because
+ // newg == (void *)&newg->node.
}
}
// Add all the Streams from src to dest. Update the base offsets
// of each Stream from src.
- info.uncompressed_size = dest->uncompressed_size;
- info.file_size = dest_file_size;
- info.stream_number_add = dest->streams.count;
- info.block_number_add = dest->record_count;
- info.streams = &dest->streams;
-
+ const index_cat_info info = {
+ .uncompressed_size = dest->uncompressed_size,
+ .file_size = dest_file_size,
+ .stream_number_add = dest->streams.count,
+ .block_number_add = dest->record_count,
+ .streams = &dest->streams,
+ };
index_cat_helper(&info, (index_stream *)(src->streams.root));
// Update info about all the combined Streams.
/// Duplicate an index_stream.
static index_stream *
-index_dup_stream(const index_stream *src, lzma_allocator *allocator)
+index_dup_stream(const index_stream *src, const lzma_allocator *allocator)
{
- index_stream *dest;
- index_group *destg;
- index_group *srcg;
- size_t i = 0;
-
// Catch a somewhat theoretical integer overflow.
if (src->record_count > PREALLOC_MAX)
return NULL;
// Allocate and initialize a new Stream.
- dest = index_stream_init(src->node.compressed_base,
+ index_stream *dest = index_stream_init(src->node.compressed_base,
src->node.uncompressed_base, src->number,
src->block_number_base, allocator);
-
- // Return immediately if allocation failed or if there are
- // no groups to duplicate.
- if (dest == NULL || src->groups.leftmost == NULL)
- return dest;
+ if (dest == NULL)
+ return NULL;
// Copy the overall information.
dest->record_count = src->record_count;
dest->stream_flags = src->stream_flags;
dest->stream_padding = src->stream_padding;
+ // Return if there are no groups to duplicate.
+ if (src->groups.leftmost == NULL)
+ return dest;
+
// Allocate memory for the Records. We put all the Records into
// a single group. It's simplest and also tends to make
// lzma_index_locate() a little bit faster with very big Indexes.
- destg = lzma_alloc(sizeof(index_group)
+ index_group *destg = lzma_alloc(sizeof(index_group)
+ src->record_count * sizeof(index_record),
allocator);
if (destg == NULL) {
destg->last = src->record_count - 1;
// Go through all the groups in src and copy the Records into destg.
- srcg = (index_group *)(src->groups.leftmost);
+ const index_group *srcg = (const index_group *)(src->groups.leftmost);
+ size_t i = 0;
do {
memcpy(destg->records + i, srcg->records,
(srcg->last + 1) * sizeof(index_record));
extern LZMA_API(lzma_index *)
-lzma_index_dup(const lzma_index *src, lzma_allocator *allocator)
+lzma_index_dup(const lzma_index *src, const lzma_allocator *allocator)
{
- index_stream *srcstream;
- index_stream *deststream;
-
// Allocate the base structure (no initial Stream).
lzma_index *dest = index_init_plain(allocator);
if (dest == NULL)
dest->index_list_size = src->index_list_size;
// Copy the Streams and the groups in them.
- srcstream = (index_stream *)(src->streams.leftmost);
+ const index_stream *srcstream
+ = (const index_stream *)(src->streams.leftmost);
do {
- deststream = index_dup_stream(srcstream, allocator);
+ index_stream *deststream = index_dup_stream(
+ srcstream, allocator);
if (deststream == NULL) {
lzma_index_end(dest, allocator);
return NULL;
iter->internal[ITER_GROUP].p = NULL;
}
+ // NOTE: lzma_index_iter.stream.number is lzma_vli but we use uint32_t
+ // internally.
iter->stream.number = stream->number;
iter->stream.block_count = stream->record_count;
iter->stream.compressed_offset = stream->node.compressed_base;
extern LZMA_API(lzma_bool)
lzma_index_iter_next(lzma_index_iter *iter, lzma_index_iter_mode mode)
{
- const lzma_index *i;
- const index_stream *stream;
- const index_group *group;
- size_t record;
-
// Catch unsupported mode values.
if ((unsigned int)(mode) > LZMA_INDEX_ITER_NONEMPTY_BLOCK)
return true;
- i = iter->internal[ITER_INDEX].p;
- stream = iter->internal[ITER_STREAM].p;
- group = NULL;
- record = iter->internal[ITER_RECORD].s;
+ const lzma_index *i = iter->internal[ITER_INDEX].p;
+ const index_stream *stream = iter->internal[ITER_STREAM].p;
+ const index_group *group = NULL;
+ size_t record = iter->internal[ITER_RECORD].s;
// If we are being asked for the next Stream, leave group to NULL
// so that the rest of the this function thinks that this Stream
extern LZMA_API(lzma_bool)
lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
{
- const index_stream *stream;
- const index_group *group;
- size_t left, right;
-
const lzma_index *i = iter->internal[ITER_INDEX].p;
// If the target is past the end of the file, return immediately.
return true;
// Locate the Stream containing the target offset.
- stream = index_tree_locate(&i->streams, target);
+ const index_stream *stream = index_tree_locate(&i->streams, target);
assert(stream != NULL);
target -= stream->node.uncompressed_base;
// Locate the group containing the target offset.
- group = index_tree_locate(&stream->groups, target);
+ const index_group *group = index_tree_locate(&stream->groups, target);
assert(group != NULL);
// Use binary search to locate the exact Record. It is the first
// This is because we want the rightmost Record that fullfills the
// search criterion. It is possible that there are empty Blocks;
// we don't want to return them.
- left = 0;
- right = group->last;
+ size_t left = 0;
+ size_t right = group->last;
while (left < right) {
const size_t pos = left + (right - left) / 2;
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_INDICATOR,
SEQ_COUNT,
/// CRC32 of the List of Records field
uint32_t crc32;
-};
+} lzma_index_coder;
static lzma_ret
-index_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+index_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size,
- uint8_t *LZMA_RESTRICT out lzma_attribute((__unused__)),
- size_t *LZMA_RESTRICT out_pos lzma_attribute((__unused__)),
+ uint8_t *restrict out lzma_attribute((__unused__)),
+ size_t *restrict out_pos lzma_attribute((__unused__)),
size_t out_size lzma_attribute((__unused__)),
lzma_action action lzma_attribute((__unused__)))
{
+ lzma_index_coder *coder = coder_ptr;
+
// Similar optimization as in index_encoder.c
const size_t in_start = *in_pos;
lzma_ret ret = LZMA_OK;
static void
-index_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+index_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_index_coder *coder = coder_ptr;
lzma_index_end(coder->index, allocator);
lzma_free(coder, allocator);
return;
static lzma_ret
-index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+index_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_index_coder *coder = coder_ptr;
+
*memusage = lzma_index_memusage(1, coder->count);
*old_memlimit = coder->memlimit;
static lzma_ret
-index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
+index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
lzma_index **i, uint64_t memlimit)
{
// Remember the pointer given by the application. We will set it
// Initialize the rest.
coder->sequence = SEQ_INDICATOR;
- coder->memlimit = memlimit;
+ coder->memlimit = my_max(1, memlimit);
coder->count = 0; // Needs to be initialized due to _memconfig().
coder->pos = 0;
coder->crc32 = 0;
static lzma_ret
-index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
lzma_index **i, uint64_t memlimit)
{
lzma_next_coder_init(&index_decoder_init, next, allocator);
- if (i == NULL || memlimit == 0)
+ if (i == NULL)
return LZMA_PROG_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_index_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &index_decode;
next->end = &index_decoder_end;
next->memconfig = &index_decoder_memconfig;
- next->coder->index = NULL;
+ coder->index = NULL;
} else {
- lzma_index_end(next->coder->index, allocator);
+ lzma_index_end(coder->index, allocator);
}
- return index_decoder_reset(next->coder, allocator, i, memlimit);
+ return index_decoder_reset(coder, allocator, i, memlimit);
}
extern LZMA_API(lzma_ret)
lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
{
- lzma_next_strm_init2(index_decoder_init, strm, i, memlimit);
+ lzma_next_strm_init(index_decoder_init, strm, i, memlimit);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
extern LZMA_API(lzma_ret)
-lzma_index_buffer_decode(
- lzma_index **i, uint64_t *memlimit, lzma_allocator *allocator,
+lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
+ const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size)
{
- lzma_coder coder;
- lzma_ret ret;
-
- // Store the input start position so that we can restore it in case
- // of an error.
- const size_t in_start = *in_pos;
-
// Sanity checks
if (i == NULL || memlimit == NULL
|| in == NULL || in_pos == NULL || *in_pos > in_size)
return LZMA_PROG_ERROR;
// Initialize the decoder.
+ lzma_index_coder coder;
return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit));
+ // Store the input start position so that we can restore it in case
+ // of an error.
+ const size_t in_start = *in_pos;
+
// Do the actual decoding.
- ret = index_decode(&coder, allocator, in, in_pos, in_size,
+ lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size,
NULL, NULL, 0, LZMA_RUN);
if (ret == LZMA_STREAM_END) {
#include "check.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_INDICATOR,
SEQ_COUNT,
/// CRC32 of the List of Records field
uint32_t crc32;
-};
+} lzma_index_coder;
static lzma_ret
-index_encode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in lzma_attribute((__unused__)),
- size_t *LZMA_RESTRICT in_pos lzma_attribute((__unused__)),
+index_encode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in lzma_attribute((__unused__)),
+ size_t *restrict in_pos lzma_attribute((__unused__)),
size_t in_size lzma_attribute((__unused__)),
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size,
lzma_action action lzma_attribute((__unused__)))
{
+ lzma_index_coder *coder = coder_ptr;
+
// Position where to start calculating CRC32. The idea is that we
// need to call lzma_crc32() only once per call to index_encode().
const size_t out_start = *out_pos;
static void
-index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+index_encoder_end(void *coder, const lzma_allocator *allocator)
{
lzma_free(coder, allocator);
return;
static void
-index_encoder_reset(lzma_coder *coder, const lzma_index *i)
+index_encoder_reset(lzma_index_coder *coder, const lzma_index *i)
{
lzma_index_iter_init(&coder->iter, i);
extern lzma_ret
-lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_index_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_index *i)
{
lzma_next_coder_init(&lzma_index_encoder_init, next, allocator);
return LZMA_PROG_ERROR;
if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ next->coder = lzma_alloc(sizeof(lzma_index_coder), allocator);
if (next->coder == NULL)
return LZMA_MEM_ERROR;
extern LZMA_API(lzma_ret)
lzma_index_encoder(lzma_stream *strm, const lzma_index *i)
{
- lzma_next_strm_init1(lzma_index_encoder_init, strm, i);
+ lzma_next_strm_init(lzma_index_encoder_init, strm, i);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
lzma_index_buffer_encode(const lzma_index *i,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_coder coder;
- size_t out_start;
- lzma_ret ret;
-
// Validate the arguments.
if (i == NULL || out == NULL || out_pos == NULL || *out_pos > out_size)
return LZMA_PROG_ERROR;
// The Index encoder needs just one small data structure so we can
// allocate it on stack.
+ lzma_index_coder coder;
index_encoder_reset(&coder, i);
// Do the actual encoding. This should never fail, but store
// the original *out_pos just in case.
- out_start = *out_pos;
- ret = index_encode(&coder, NULL, NULL, NULL, 0,
+ const size_t out_start = *out_pos;
+ lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0,
out, out_pos, out_size, LZMA_RUN);
if (ret == LZMA_STREAM_END) {
extern lzma_ret lzma_index_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_index *i);
+ const lzma_allocator *allocator, const lzma_index *i);
#endif
extern LZMA_API(lzma_index_hash *)
-lzma_index_hash_init(lzma_index_hash *index_hash, lzma_allocator *allocator)
+lzma_index_hash_init(lzma_index_hash *index_hash,
+ const lzma_allocator *allocator)
{
if (index_hash == NULL) {
index_hash = lzma_alloc(sizeof(lzma_index_hash), allocator);
extern LZMA_API(void)
-lzma_index_hash_end(lzma_index_hash *index_hash, lzma_allocator *allocator)
+lzma_index_hash_end(lzma_index_hash *index_hash,
+ const lzma_allocator *allocator)
{
lzma_free(index_hash, allocator);
return;
hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
lzma_vli uncompressed_size)
{
- const lzma_vli sizes[2] = { unpadded_size, uncompressed_size };
-
info->blocks_size += vli_ceil4(unpadded_size);
info->uncompressed_size += uncompressed_size;
info->index_list_size += lzma_vli_size(unpadded_size)
+ lzma_vli_size(uncompressed_size);
++info->count;
+ const lzma_vli sizes[2] = { unpadded_size, uncompressed_size };
lzma_check_update(&info->check, LZMA_CHECK_BEST,
(const uint8_t *)(sizes), sizeof(sizes));
lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
size_t *in_pos, size_t in_size)
{
- size_t in_start;
- lzma_ret ret;
-
// Catch zero input buffer here, because in contrast to Index encoder
// and decoder functions, applications call this function directly
// instead of via lzma_code(), which does the buffer checking.
// NOTE: This function has many similarities to index_encode() and
// index_decode() functions found from index_encoder.c and
// index_decoder.c. See the comments especially in index_encoder.c.
- in_start = *in_pos;
- ret = LZMA_OK;
+ const size_t in_start = *in_pos;
+ lzma_ret ret = LZMA_OK;
while (*in_pos < in_size)
switch (index_hash->sequence) {
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file memcmplen.h
+/// \brief Optimized comparison of two buffers
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_MEMCMPLEN_H
+#define LZMA_MEMCMPLEN_H
+
+#include "common.h"
+
+#ifdef HAVE_IMMINTRIN_H
+# include <immintrin.h>
+#endif
+
+
+/// Find out how many equal bytes the two buffers have.
+///
+/// \param buf1 First buffer
+/// \param buf2 Second buffer
+/// \param len How many bytes have already been compared and will
+/// be assumed to match
+/// \param limit How many bytes to compare at most, including the
+/// already-compared bytes. This must be significantly
+/// smaller than UINT32_MAX to avoid integer overflows.
+/// Up to LZMA_MEMCMPLEN_EXTRA bytes may be read past
+/// the specified limit from both buf1 and buf2.
+///
+/// \return Number of equal bytes in the buffers is returned.
+/// This is always at least len and at most limit.
+///
+/// \note LZMA_MEMCMPLEN_EXTRA defines how many extra bytes may be read.
+/// It's rounded up to 2^n. This extra amount needs to be
+/// allocated in the buffers being used. It needs to be
+/// initialized too to keep Valgrind quiet.
+static inline uint32_t lzma_attribute((__always_inline__))
+lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
+ uint32_t len, uint32_t limit)
+{
+ assert(len <= limit);
+ assert(limit <= UINT32_MAX / 2);
+
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && ((TUKLIB_GNUC_REQ(3, 4) && defined(__x86_64__)) \
+ || (defined(__INTEL_COMPILER) && defined(__x86_64__)) \
+ || (defined(__INTEL_COMPILER) && defined(_M_X64)) \
+ || (defined(_MSC_VER) && defined(_M_X64)))
+ // NOTE: This will use 64-bit unaligned access which
+ // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit, but
+ // it's convenient here at least as long as it's x86-64 only.
+ //
+ // I keep this x86-64 only for now since that's where I know this
+ // to be a good method. This may be fine on other 64-bit CPUs too.
+ // On big endian one should use xor instead of subtraction and switch
+ // to __builtin_clzll().
+#define LZMA_MEMCMPLEN_EXTRA 8
+ while (len < limit) {
+ const uint64_t x = *(const uint64_t *)(buf1 + len)
+ - *(const uint64_t *)(buf2 + len);
+ if (x != 0) {
+# if defined(_M_X64) // MSVC or Intel C compiler on Windows
+ unsigned long tmp;
+ _BitScanForward64(&tmp, x);
+ len += (uint32_t)tmp >> 3;
+# else // GCC, clang, or Intel C compiler
+ len += (uint32_t)__builtin_ctzll(x) >> 3;
+# endif
+ return my_min(len, limit);
+ }
+
+ len += 8;
+ }
+
+ return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+ && defined(HAVE__MM_MOVEMASK_EPI8) \
+ && ((defined(__GNUC__) && defined(__SSE2_MATH__)) \
+ || (defined(__INTEL_COMPILER) && defined(__SSE2__)) \
+ || (defined(_MSC_VER) && defined(_M_IX86_FP) \
+ && _M_IX86_FP >= 2))
+ // NOTE: Like above, this will use 128-bit unaligned access which
+ // TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit.
+ //
+ // SSE2 version for 32-bit and 64-bit x86. On x86-64 the above
+ // version is sometimes significantly faster and sometimes
+ // slightly slower than this SSE2 version, so this SSE2
+ // version isn't used on x86-64.
+# define LZMA_MEMCMPLEN_EXTRA 16
+ while (len < limit) {
+ const uint32_t x = 0xFFFF ^ _mm_movemask_epi8(_mm_cmpeq_epi8(
+ _mm_loadu_si128((const __m128i *)(buf1 + len)),
+ _mm_loadu_si128((const __m128i *)(buf2 + len))));
+
+ if (x != 0) {
+# if defined(__INTEL_COMPILER)
+ len += _bit_scan_forward(x);
+# elif defined(_MSC_VER)
+ unsigned long tmp;
+ _BitScanForward(&tmp, x);
+ len += tmp;
+# else
+ len += __builtin_ctz(x);
+# endif
+ return my_min(len, limit);
+ }
+
+ len += 16;
+ }
+
+ return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && !defined(WORDS_BIGENDIAN)
+ // Generic 32-bit little endian method
+# define LZMA_MEMCMPLEN_EXTRA 4
+ while (len < limit) {
+ uint32_t x = *(const uint32_t *)(buf1 + len)
+ - *(const uint32_t *)(buf2 + len);
+ if (x != 0) {
+ if ((x & 0xFFFF) == 0) {
+ len += 2;
+ x >>= 16;
+ }
+
+ if ((x & 0xFF) == 0)
+ ++len;
+
+ return my_min(len, limit);
+ }
+
+ len += 4;
+ }
+
+ return limit;
+
+#elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) && defined(WORDS_BIGENDIAN)
+ // Generic 32-bit big endian method
+# define LZMA_MEMCMPLEN_EXTRA 4
+ while (len < limit) {
+ uint32_t x = *(const uint32_t *)(buf1 + len)
+ ^ *(const uint32_t *)(buf2 + len);
+ if (x != 0) {
+ if ((x & 0xFFFF0000) == 0) {
+ len += 2;
+ x <<= 16;
+ }
+
+ if ((x & 0xFF000000) == 0)
+ ++len;
+
+ return my_min(len, limit);
+ }
+
+ len += 4;
+ }
+
+ return limit;
+
+#else
+ // Simple portable version that doesn't use unaligned access.
+# define LZMA_MEMCMPLEN_EXTRA 0
+ while (len < limit && buf1[len] == buf2[len])
+ ++len;
+
+ return len;
+#endif
+}
+
+#endif
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file outqueue.c
+/// \brief Output queue handling in multithreaded coding
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "outqueue.h"
+
+
+/// This is to ease integer overflow checking: We may allocate up to
+/// 2 * LZMA_THREADS_MAX buffers and we need some extra memory for other
+/// data structures (that's the second /2).
+#define BUF_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX / 2 / 2)
+
+
+static lzma_ret
+get_options(uint64_t *bufs_alloc_size, uint32_t *bufs_count,
+ uint64_t buf_size_max, uint32_t threads)
+{
+ if (threads > LZMA_THREADS_MAX || buf_size_max > BUF_SIZE_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ // The number of buffers is twice the number of threads.
+ // This wastes RAM but keeps the threads busy when buffers
+ // finish out of order.
+ //
+ // NOTE: If this is changed, update BUF_SIZE_MAX too.
+ *bufs_count = threads * 2;
+ *bufs_alloc_size = *bufs_count * buf_size_max;
+
+ return LZMA_OK;
+}
+
+
+extern uint64_t
+lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads)
+{
+ uint64_t bufs_alloc_size;
+ uint32_t bufs_count;
+
+ if (get_options(&bufs_alloc_size, &bufs_count, buf_size_max, threads)
+ != LZMA_OK)
+ return UINT64_MAX;
+
+ return sizeof(lzma_outq) + bufs_count * sizeof(lzma_outbuf)
+ + bufs_alloc_size;
+}
+
+
+extern lzma_ret
+lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator,
+ uint64_t buf_size_max, uint32_t threads)
+{
+ uint64_t bufs_alloc_size;
+ uint32_t bufs_count;
+
+ // Set bufs_count and bufs_alloc_size.
+ return_if_error(get_options(&bufs_alloc_size, &bufs_count,
+ buf_size_max, threads));
+
+ // Allocate memory if needed.
+ if (outq->buf_size_max != buf_size_max
+ || outq->bufs_allocated != bufs_count) {
+ lzma_outq_end(outq, allocator);
+
+#if SIZE_MAX < UINT64_MAX
+ if (bufs_alloc_size > SIZE_MAX)
+ return LZMA_MEM_ERROR;
+#endif
+
+ outq->bufs = lzma_alloc(bufs_count * sizeof(lzma_outbuf),
+ allocator);
+ outq->bufs_mem = lzma_alloc((size_t)(bufs_alloc_size),
+ allocator);
+
+ if (outq->bufs == NULL || outq->bufs_mem == NULL) {
+ lzma_outq_end(outq, allocator);
+ return LZMA_MEM_ERROR;
+ }
+ }
+
+ // Initialize the rest of the main structure. Initialization of
+ // outq->bufs[] is done when they are actually needed.
+ outq->buf_size_max = (size_t)(buf_size_max);
+ outq->bufs_allocated = bufs_count;
+ outq->bufs_pos = 0;
+ outq->bufs_used = 0;
+ outq->read_pos = 0;
+
+ return LZMA_OK;
+}
+
+
+extern void
+lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator)
+{
+ lzma_free(outq->bufs, allocator);
+ outq->bufs = NULL;
+
+ lzma_free(outq->bufs_mem, allocator);
+ outq->bufs_mem = NULL;
+
+ return;
+}
+
+
+extern lzma_outbuf *
+lzma_outq_get_buf(lzma_outq *outq)
+{
+ // Caller must have checked it with lzma_outq_has_buf().
+ assert(outq->bufs_used < outq->bufs_allocated);
+
+ // Initialize the new buffer.
+ lzma_outbuf *buf = &outq->bufs[outq->bufs_pos];
+ buf->buf = outq->bufs_mem + outq->bufs_pos * outq->buf_size_max;
+ buf->size = 0;
+ buf->finished = false;
+
+ // Update the queue state.
+ if (++outq->bufs_pos == outq->bufs_allocated)
+ outq->bufs_pos = 0;
+
+ ++outq->bufs_used;
+
+ return buf;
+}
+
+
+extern bool
+lzma_outq_is_readable(const lzma_outq *outq)
+{
+ uint32_t i = outq->bufs_pos - outq->bufs_used;
+ if (outq->bufs_pos < outq->bufs_used)
+ i += outq->bufs_allocated;
+
+ return outq->bufs[i].finished;
+}
+
+
+extern lzma_ret
+lzma_outq_read(lzma_outq *restrict outq, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
+ lzma_vli *restrict unpadded_size,
+ lzma_vli *restrict uncompressed_size)
+{
+ // There must be at least one buffer from which to read.
+ if (outq->bufs_used == 0)
+ return LZMA_OK;
+
+ // Get the buffer.
+ uint32_t i = outq->bufs_pos - outq->bufs_used;
+ if (outq->bufs_pos < outq->bufs_used)
+ i += outq->bufs_allocated;
+
+ lzma_outbuf *buf = &outq->bufs[i];
+
+ // If it isn't finished yet, we cannot read from it.
+ if (!buf->finished)
+ return LZMA_OK;
+
+ // Copy from the buffer to output.
+ lzma_bufcpy(buf->buf, &outq->read_pos, buf->size,
+ out, out_pos, out_size);
+
+ // Return if we didn't get all the data from the buffer.
+ if (outq->read_pos < buf->size)
+ return LZMA_OK;
+
+ // The buffer was finished. Tell the caller its size information.
+ *unpadded_size = buf->unpadded_size;
+ *uncompressed_size = buf->uncompressed_size;
+
+ // Free this buffer for further use.
+ --outq->bufs_used;
+ outq->read_pos = 0;
+
+ return LZMA_STREAM_END;
+}
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file outqueue.h
+/// \brief Output queue handling in multithreaded coding
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+/// Output buffer for a single thread
+typedef struct {
+ /// Pointer to the output buffer of lzma_outq.buf_size_max bytes
+ uint8_t *buf;
+
+ /// Amount of data written to buf
+ size_t size;
+
+ /// Additional size information
+ lzma_vli unpadded_size;
+ lzma_vli uncompressed_size;
+
+ /// True when no more data will be written into this buffer.
+ ///
+ /// \note This is read by another thread and thus access
+ /// to this variable needs a mutex.
+ bool finished;
+
+} lzma_outbuf;
+
+
+typedef struct {
+ /// Array of buffers that are used cyclically.
+ lzma_outbuf *bufs;
+
+ /// Memory allocated for all the buffers
+ uint8_t *bufs_mem;
+
+ /// Amount of buffer space available in each buffer
+ size_t buf_size_max;
+
+ /// Number of buffers allocated
+ uint32_t bufs_allocated;
+
+ /// Position in the bufs array. The next buffer to be taken
+ /// into use is bufs[bufs_pos].
+ uint32_t bufs_pos;
+
+ /// Number of buffers in use
+ uint32_t bufs_used;
+
+ /// Position in the buffer in lzma_outq_read()
+ size_t read_pos;
+
+} lzma_outq;
+
+
+/**
+ * \brief Calculate the memory usage of an output queue
+ *
+ * \return Approximate memory usage in bytes or UINT64_MAX on error.
+ */
+extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief Initialize an output queue
+///
+/// \param outq Pointer to an output queue. Before calling
+/// this function the first time, *outq should
+/// have been zeroed with memzero() so that this
+/// function knows that there are no previous
+/// allocations to free.
+/// \param allocator Pointer to allocator or NULL
+/// \param buf_size_max Maximum amount of data that a single buffer
+/// in the queue may need to store.
+/// \param threads Number of buffers that may be in use
+/// concurrently. Note that more than this number
+/// of buffers will actually get allocated to
+/// improve performance when buffers finish
+/// out of order.
+///
+/// \return - LZMA_OK
+/// - LZMA_MEM_ERROR
+///
+extern lzma_ret lzma_outq_init(
+ lzma_outq *outq, const lzma_allocator *allocator,
+ uint64_t buf_size_max, uint32_t threads);
+
+
+/// \brief Free the memory associated with the output queue
+extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
+
+
+/// \brief Get a new buffer
+///
+/// lzma_outq_has_buf() must be used to check that there is a buffer
+/// available before calling lzma_outq_get_buf().
+///
+extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
+
+
+/// \brief Test if there is data ready to be read
+///
+/// Call to this function must be protected with the same mutex that
+/// is used to protect lzma_outbuf.finished.
+///
+extern bool lzma_outq_is_readable(const lzma_outq *outq);
+
+
+/// \brief Read finished data
+///
+/// \param outq Pointer to an output queue
+/// \param out Beginning of the output buffer
+/// \param out_pos The next byte will be written to
+/// out[*out_pos].
+/// \param out_size Size of the out buffer; the first byte into
+/// which no data is written to is out[out_size].
+/// \param unpadded_size Unpadded Size from the Block encoder
+/// \param uncompressed_size Uncompressed Size from the Block encoder
+///
+/// \return - LZMA: All OK. Either no data was available or the buffer
+/// being read didn't become empty yet.
+/// - LZMA_STREAM_END: The buffer being read was finished.
+/// *unpadded_size and *uncompressed_size were set.
+///
+/// \note This reads lzma_outbuf.finished variables and thus call
+/// to this function needs to be protected with a mutex.
+///
+extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
+ uint8_t *restrict out, size_t *restrict out_pos,
+ size_t out_size, lzma_vli *restrict unpadded_size,
+ lzma_vli *restrict uncompressed_size);
+
+
+/// \brief Test if there is at least one buffer free
+///
+/// This must be used before getting a new buffer with lzma_outq_get_buf().
+///
+static inline bool
+lzma_outq_has_buf(const lzma_outq *outq)
+{
+ return outq->bufs_used < outq->bufs_allocated;
+}
+
+
+/// \brief Test if the queue is completely empty
+static inline bool
+lzma_outq_is_empty(const lzma_outq *outq)
+{
+ return outq->bufs_used == 0;
+}
extern LZMA_API(lzma_ret)
lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
- lzma_allocator *allocator,
+ const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
{
- lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
- lzma_ret ret;
-
// Sanity checks
if (in_pos == NULL || (in == NULL && *in_pos != in_size)
|| *in_pos > in_size || out_pos == NULL
// Initialize the Stream decoder.
// TODO: We need something to tell the decoder that it can use the
// output buffer as workspace, and thus save significant amount of RAM.
- ret = lzma_stream_decoder_init(
+ lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
+ lzma_ret ret = lzma_stream_decoder_init(
&stream_decoder, allocator, *memlimit, flags);
if (ret == LZMA_OK) {
extern LZMA_API(lzma_ret)
lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
- lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+ const lzma_allocator *allocator,
+ const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos_ptr, size_t out_size)
{
- lzma_stream_flags stream_flags = { 0 };
- lzma_block block = { 0 };
- size_t out_pos;
-
// Sanity checks
if (filters == NULL || (unsigned int)(check) > LZMA_CHECK_ID_MAX
|| (in == NULL && in_size != 0) || out == NULL
// Use a local copy. We update *out_pos_ptr only if everything
// succeeds.
- out_pos = *out_pos_ptr;
+ size_t out_pos = *out_pos_ptr;
// Check that there's enough space for both Stream Header and
// Stream Footer.
out_size -= LZMA_STREAM_HEADER_SIZE;
// Encode the Stream Header.
- stream_flags.check = check;
+ lzma_stream_flags stream_flags = {
+ .version = 0,
+ .check = check,
+ };
if (lzma_stream_header_encode(&stream_flags, out + out_pos)
!= LZMA_OK)
out_pos += LZMA_STREAM_HEADER_SIZE;
// Encode a Block but only if there is at least one byte of input.
- block.check = check;
- block.filters = filters;
+ lzma_block block = {
+ .version = 0,
+ .check = check,
+ .filters = filters,
+ };
if (in_size > 0)
return_if_error(lzma_block_buffer_encode(&block, allocator,
// Index
{
- lzma_ret ret;
-
// Create an Index. It will have one Record if there was
// at least one byte of input to encode. Otherwise the
// Index will be empty.
if (i == NULL)
return LZMA_MEM_ERROR;
- ret = LZMA_OK;
+ lzma_ret ret = LZMA_OK;
if (in_size > 0)
ret = lzma_index_append(i, allocator,
#include "block_decoder.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_STREAM_HEADER,
SEQ_BLOCK_HEADER,
/// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
bool tell_any_check;
+ /// If true, we will tell the Block decoder to skip calculating
+ /// and verifying the integrity check.
+ bool ignore_check;
+
/// If true, we will decode concatenated Streams that possibly have
/// Stream Padding between or after them. LZMA_STREAM_END is returned
/// once the application isn't giving us any new input, and we aren't
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
/// Block Header has biggest maximum size.
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
-};
+} lzma_stream_coder;
static lzma_ret
-stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
+stream_decoder_reset(lzma_stream_coder *coder, const lzma_allocator *allocator)
{
// Initialize the Index hash used to verify the Index.
coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
static lzma_ret
-stream_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+stream_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_stream_coder *coder = coder_ptr;
+
// When decoding the actual Block, it may be able to produce more
// output even if we don't give it any new input.
while (true)
switch (coder->sequence) {
case SEQ_STREAM_HEADER: {
- lzma_ret ret;
-
// Copy the Stream Header to the internal buffer.
lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE);
coder->pos = 0;
// Decode the Stream Header.
- ret = lzma_stream_header_decode(
+ const lzma_ret ret = lzma_stream_header_decode(
&coder->stream_flags, coder->buffer);
if (ret != LZMA_OK)
return ret == LZMA_FORMAT_ERROR && !coder->first_stream
// Fall through
case SEQ_BLOCK_HEADER: {
- lzma_filter filters[LZMA_FILTERS_MAX + 1];
- uint64_t memusage;
- lzma_ret ret;
- size_t i;
-
if (*in_pos >= in_size)
return LZMA_OK;
coder->pos = 0;
- // Version 0 is currently the only possible version.
- coder->block_options.version = 0;
+ // Version 1 is needed to support the .ignore_check option.
+ coder->block_options.version = 1;
// Set up a buffer to hold the filter chain. Block Header
// decoder will initialize all members of this array so
// we don't need to do it here.
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
coder->block_options.filters = filters;
// Decode the Block Header.
return_if_error(lzma_block_header_decode(&coder->block_options,
allocator, coder->buffer));
+ // If LZMA_IGNORE_CHECK was used, this flag needs to be set.
+ // It has to be set after lzma_block_header_decode() because
+ // it always resets this to false.
+ coder->block_options.ignore_check = coder->ignore_check;
+
// Check the memory usage limit.
- memusage = lzma_raw_decoder_memusage(filters);
+ const uint64_t memusage = lzma_raw_decoder_memusage(filters);
+ lzma_ret ret;
+
if (memusage == UINT64_MAX) {
// One or more unknown Filter IDs.
ret = LZMA_OPTIONS_ERROR;
// Free the allocated filter options since they are needed
// only to initialize the Block decoder.
- for (i = 0; i < LZMA_FILTERS_MAX; ++i)
+ for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
lzma_free(filters[i].options, allocator);
coder->block_options.filters = NULL;
}
case SEQ_INDEX: {
- lzma_ret ret;
-
// If we don't have any input, don't call
// lzma_index_hash_decode() since it would return
// LZMA_BUF_ERROR, which we must not do here.
// Decode the Index and compare it to the hash calculated
// from the sizes of the Blocks (if any).
- ret = lzma_index_hash_decode(coder->index_hash,
+ const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
in, in_pos, in_size);
if (ret != LZMA_STREAM_END)
return ret;
// Fall through
case SEQ_STREAM_FOOTER: {
- lzma_stream_flags footer_flags;
- lzma_ret ret;
-
// Copy the Stream Footer to the internal buffer.
lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
LZMA_STREAM_HEADER_SIZE);
// Decode the Stream Footer. The decoder gives
// LZMA_FORMAT_ERROR if the magic bytes don't match,
// so convert that return code to LZMA_DATA_ERROR.
- ret = lzma_stream_footer_decode(
+ lzma_stream_flags footer_flags;
+ const lzma_ret ret = lzma_stream_footer_decode(
&footer_flags, coder->buffer);
if (ret != LZMA_OK)
return ret == LZMA_FORMAT_ERROR
static void
-stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+stream_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_stream_coder *coder = coder_ptr;
lzma_next_end(&coder->block_decoder, allocator);
lzma_index_hash_end(coder->index_hash, allocator);
lzma_free(coder, allocator);
static lzma_check
-stream_decoder_get_check(const lzma_coder *coder)
+stream_decoder_get_check(const void *coder_ptr)
{
+ const lzma_stream_coder *coder = coder_ptr;
return coder->stream_flags.check;
}
static lzma_ret
-stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+stream_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
uint64_t *old_memlimit, uint64_t new_memlimit)
{
+ lzma_stream_coder *coder = coder_ptr;
+
*memusage = coder->memusage;
*old_memlimit = coder->memlimit;
extern lzma_ret
-lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_stream_decoder_init(
+ lzma_next_coder *next, const lzma_allocator *allocator,
uint64_t memlimit, uint32_t flags)
{
lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator);
- if (memlimit == 0)
- return LZMA_PROG_ERROR;
-
if (flags & ~LZMA_SUPPORTED_FLAGS)
return LZMA_OPTIONS_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_stream_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &stream_decode;
next->end = &stream_decoder_end;
next->get_check = &stream_decoder_get_check;
next->memconfig = &stream_decoder_memconfig;
- next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
- next->coder->index_hash = NULL;
+ coder->block_decoder = LZMA_NEXT_CODER_INIT;
+ coder->index_hash = NULL;
}
- next->coder->memlimit = memlimit;
- next->coder->memusage = LZMA_MEMUSAGE_BASE;
- next->coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
- next->coder->tell_unsupported_check
+ coder->memlimit = my_max(1, memlimit);
+ coder->memusage = LZMA_MEMUSAGE_BASE;
+ coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
+ coder->tell_unsupported_check
= (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
- next->coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
- next->coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
- next->coder->first_stream = true;
+ coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
+ coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
+ coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
+ coder->first_stream = true;
- return stream_decoder_reset(next->coder, allocator);
+ return stream_decoder_reset(coder, allocator);
}
extern LZMA_API(lzma_ret)
lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
{
- lzma_next_strm_init2(lzma_stream_decoder_init, strm, memlimit, flags);
+ lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
#include "common.h"
-extern lzma_ret lzma_stream_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, uint64_t memlimit, uint32_t flags);
+extern lzma_ret lzma_stream_decoder_init(
+ lzma_next_coder *next, const lzma_allocator *allocator,
+ uint64_t memlimit, uint32_t flags);
#endif
//
///////////////////////////////////////////////////////////////////////////////
-#include "stream_encoder.h"
#include "block_encoder.h"
#include "index_encoder.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_STREAM_HEADER,
SEQ_BLOCK_INIT,
} sequence;
/// True if Block encoder has been initialized by
- /// lzma_stream_encoder_init() or stream_encoder_update()
+ /// stream_encoder_init() or stream_encoder_update()
/// and thus doesn't need to be initialized in stream_encode().
bool block_encoder_is_initialized;
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
/// Block Header has biggest maximum size.
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
-};
+} lzma_stream_coder;
static lzma_ret
-block_encoder_init(lzma_coder *coder, lzma_allocator *allocator)
+block_encoder_init(lzma_stream_coder *coder, const lzma_allocator *allocator)
{
// Prepare the Block options. Even though Block encoder doesn't need
// compressed_size, uncompressed_size, and header_size to be
static lzma_ret
-stream_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+stream_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_stream_coder *coder = coder_ptr;
+
// Main loop
while (*out_pos < out_size)
switch (coder->sequence) {
}
// Initialize the Block encoder unless it was already
- // initialized by lzma_stream_encoder_init() or
+ // initialized by stream_encoder_init() or
// stream_encoder_update().
if (!coder->block_encoder_is_initialized)
return_if_error(block_encoder_init(coder, allocator));
}
case SEQ_BLOCK_ENCODE: {
- lzma_vli unpadded_size;
-
- static const lzma_action convert[4] = {
+ static const lzma_action convert[LZMA_ACTION_MAX + 1] = {
LZMA_RUN,
LZMA_SYNC_FLUSH,
LZMA_FINISH,
LZMA_FINISH,
+ LZMA_FINISH,
};
const lzma_ret ret = coder->block_encoder.code(
return ret;
// Add a new Index Record.
- unpadded_size = lzma_block_unpadded_size(
+ const lzma_vli unpadded_size = lzma_block_unpadded_size(
&coder->block_options);
assert(unpadded_size != 0);
return_if_error(lzma_index_append(coder->index, allocator,
}
case SEQ_INDEX_ENCODE: {
- const lzma_stream_flags stream_flags = {
- 0,
- lzma_index_size(coder->index),
- coder->block_options.check,
- };
-
// Call the Index encoder. It doesn't take any input, so
// those pointers can be NULL.
const lzma_ret ret = coder->index_encoder.code(
return ret;
// Encode the Stream Footer into coder->buffer.
+ const lzma_stream_flags stream_flags = {
+ .version = 0,
+ .backward_size = lzma_index_size(coder->index),
+ .check = coder->block_options.check,
+ };
if (lzma_stream_footer_encode(&stream_flags, coder->buffer)
!= LZMA_OK)
static void
-stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+stream_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
- size_t i;
+ lzma_stream_coder *coder = coder_ptr;
lzma_next_end(&coder->block_encoder, allocator);
lzma_next_end(&coder->index_encoder, allocator);
lzma_index_end(coder->index, allocator);
- for (i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
lzma_free(coder->filters[i].options, allocator);
lzma_free(coder, allocator);
static lzma_ret
-stream_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters,
const lzma_filter *reversed_filters)
{
- size_t i;
+ lzma_stream_coder *coder = coder_ptr;
if (coder->sequence <= SEQ_BLOCK_INIT) {
- lzma_ret ret;
-
// There is no incomplete Block waiting to be finished,
// thus we can change the whole filter chain. Start by
// trying to initialize the Block encoder with the new
// chain. This way we detect if the chain is valid.
coder->block_encoder_is_initialized = false;
coder->block_options.filters = (lzma_filter *)(filters);
- ret = block_encoder_init(coder, allocator);
+ const lzma_ret ret = block_encoder_init(coder, allocator);
coder->block_options.filters = coder->filters;
if (ret != LZMA_OK)
return ret;
}
// Free the copy of the old chain and make a copy of the new chain.
- for (i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
lzma_free(coder->filters[i].options, allocator);
return lzma_filters_copy(filters, coder->filters, allocator);
}
-extern lzma_ret
-lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+static lzma_ret
+stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter *filters, lzma_check check)
{
- lzma_stream_flags stream_flags = { 0, 0, check };
-
- lzma_next_coder_init(&lzma_stream_encoder_init, next, allocator);
+ lzma_next_coder_init(&stream_encoder_init, next, allocator);
if (filters == NULL)
return LZMA_PROG_ERROR;
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_stream_coder *coder = next->coder;
+
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &stream_encode;
next->end = &stream_encoder_end;
next->update = &stream_encoder_update;
- next->coder->filters[0].id = LZMA_VLI_UNKNOWN;
- next->coder->block_encoder = LZMA_NEXT_CODER_INIT;
- next->coder->index_encoder = LZMA_NEXT_CODER_INIT;
- next->coder->index = NULL;
+ coder->filters[0].id = LZMA_VLI_UNKNOWN;
+ coder->block_encoder = LZMA_NEXT_CODER_INIT;
+ coder->index_encoder = LZMA_NEXT_CODER_INIT;
+ coder->index = NULL;
}
// Basic initializations
- next->coder->sequence = SEQ_STREAM_HEADER;
- next->coder->block_options.version = 0;
- next->coder->block_options.check = check;
+ coder->sequence = SEQ_STREAM_HEADER;
+ coder->block_options.version = 0;
+ coder->block_options.check = check;
// Initialize the Index
- lzma_index_end(next->coder->index, allocator);
- next->coder->index = lzma_index_init(allocator);
- if (next->coder->index == NULL)
+ lzma_index_end(coder->index, allocator);
+ coder->index = lzma_index_init(allocator);
+ if (coder->index == NULL)
return LZMA_MEM_ERROR;
// Encode the Stream Header
+ lzma_stream_flags stream_flags = {
+ .version = 0,
+ .check = check,
+ };
return_if_error(lzma_stream_header_encode(
- &stream_flags, next->coder->buffer));
+ &stream_flags, coder->buffer));
- next->coder->buffer_pos = 0;
- next->coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
+ coder->buffer_pos = 0;
+ coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
// Initialize the Block encoder. This way we detect unsupported
// filter chains when initializing the Stream encoder instead of
// giving an error after Stream Header has already written out.
- return stream_encoder_update(
- next->coder, allocator, filters, NULL);
+ return stream_encoder_update(coder, allocator, filters, NULL);
}
lzma_stream_encoder(lzma_stream *strm,
const lzma_filter *filters, lzma_check check)
{
- lzma_next_strm_init2(lzma_stream_encoder_init, strm, filters, check);
+ lzma_next_strm_init(stream_encoder_init, strm, filters, check);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
+ strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK;
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file stream_encoder_mt.c
+/// \brief Multithreaded .xz Stream encoder
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+#include "easy_preset.h"
+#include "block_encoder.h"
+#include "block_buffer_encoder.h"
+#include "index_encoder.h"
+#include "outqueue.h"
+
+
+/// Maximum supported block size. This makes it simpler to prevent integer
+/// overflows if we are given unusually large block size.
+#define BLOCK_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX)
+
+
+typedef enum {
+ /// Waiting for work.
+ THR_IDLE,
+
+ /// Encoding is in progress.
+ THR_RUN,
+
+ /// Encoding is in progress but no more input data will
+ /// be read.
+ THR_FINISH,
+
+ /// The main thread wants the thread to stop whatever it was doing
+ /// but not exit.
+ THR_STOP,
+
+ /// The main thread wants the thread to exit. We could use
+ /// cancellation but since there's stopped anyway, this is lazier.
+ THR_EXIT,
+
+} worker_state;
+
+typedef struct lzma_stream_coder_s lzma_stream_coder;
+
+typedef struct worker_thread_s worker_thread;
+struct worker_thread_s {
+ worker_state state;
+
+ /// Input buffer of coder->block_size bytes. The main thread will
+ /// put new input into this and update in_size accordingly. Once
+ /// no more input is coming, state will be set to THR_FINISH.
+ uint8_t *in;
+
+ /// Amount of data available in the input buffer. This is modified
+ /// only by the main thread.
+ size_t in_size;
+
+ /// Output buffer for this thread. This is set by the main
+ /// thread every time a new Block is started with this thread
+ /// structure.
+ lzma_outbuf *outbuf;
+
+ /// Pointer to the main structure is needed when putting this
+ /// thread back to the stack of free threads.
+ lzma_stream_coder *coder;
+
+ /// The allocator is set by the main thread. Since a copy of the
+ /// pointer is kept here, the application must not change the
+ /// allocator before calling lzma_end().
+ const lzma_allocator *allocator;
+
+ /// Amount of uncompressed data that has already been compressed.
+ uint64_t progress_in;
+
+ /// Amount of compressed data that is ready.
+ uint64_t progress_out;
+
+ /// Block encoder
+ lzma_next_coder block_encoder;
+
+ /// Compression options for this Block
+ lzma_block block_options;
+
+ /// Next structure in the stack of free worker threads.
+ worker_thread *next;
+
+ mythread_mutex mutex;
+ mythread_cond cond;
+
+ /// The ID of this thread is used to join the thread
+ /// when it's not needed anymore.
+ mythread thread_id;
+};
+
+
+struct lzma_stream_coder_s {
+ enum {
+ SEQ_STREAM_HEADER,
+ SEQ_BLOCK,
+ SEQ_INDEX,
+ SEQ_STREAM_FOOTER,
+ } sequence;
+
+ /// Start a new Block every block_size bytes of input unless
+ /// LZMA_FULL_FLUSH or LZMA_FULL_BARRIER is used earlier.
+ size_t block_size;
+
+ /// The filter chain currently in use
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+
+ /// Index to hold sizes of the Blocks
+ lzma_index *index;
+
+ /// Index encoder
+ lzma_next_coder index_encoder;
+
+
+ /// Stream Flags for encoding the Stream Header and Stream Footer.
+ lzma_stream_flags stream_flags;
+
+ /// Buffer to hold Stream Header and Stream Footer.
+ uint8_t header[LZMA_STREAM_HEADER_SIZE];
+
+ /// Read position in header[]
+ size_t header_pos;
+
+
+ /// Output buffer queue for compressed data
+ lzma_outq outq;
+
+
+ /// Maximum wait time if cannot use all the input and cannot
+ /// fill the output buffer. This is in milliseconds.
+ uint32_t timeout;
+
+
+ /// Error code from a worker thread
+ lzma_ret thread_error;
+
+ /// Array of allocated thread-specific structures
+ worker_thread *threads;
+
+ /// Number of structures in "threads" above. This is also the
+ /// number of threads that will be created at maximum.
+ uint32_t threads_max;
+
+ /// Number of thread structures that have been initialized, and
+ /// thus the number of worker threads actually created so far.
+ uint32_t threads_initialized;
+
+ /// Stack of free threads. When a thread finishes, it puts itself
+ /// back into this stack. This starts as empty because threads
+ /// are created only when actually needed.
+ worker_thread *threads_free;
+
+ /// The most recent worker thread to which the main thread writes
+ /// the new input from the application.
+ worker_thread *thr;
+
+
+ /// Amount of uncompressed data in Blocks that have already
+ /// been finished.
+ uint64_t progress_in;
+
+ /// Amount of compressed data in Stream Header + Blocks that
+ /// have already been finished.
+ uint64_t progress_out;
+
+
+ mythread_mutex mutex;
+ mythread_cond cond;
+};
+
+
+/// Tell the main thread that something has gone wrong.
+static void
+worker_error(worker_thread *thr, lzma_ret ret)
+{
+ assert(ret != LZMA_OK);
+ assert(ret != LZMA_STREAM_END);
+
+ mythread_sync(thr->coder->mutex) {
+ if (thr->coder->thread_error == LZMA_OK)
+ thr->coder->thread_error = ret;
+
+ mythread_cond_signal(&thr->coder->cond);
+ }
+
+ return;
+}
+
+
+static worker_state
+worker_encode(worker_thread *thr, worker_state state)
+{
+ assert(thr->progress_in == 0);
+ assert(thr->progress_out == 0);
+
+ // Set the Block options.
+ thr->block_options = (lzma_block){
+ .version = 0,
+ .check = thr->coder->stream_flags.check,
+ .compressed_size = thr->coder->outq.buf_size_max,
+ .uncompressed_size = thr->coder->block_size,
+
+ // TODO: To allow changing the filter chain, the filters
+ // array must be copied to each worker_thread.
+ .filters = thr->coder->filters,
+ };
+
+ // Calculate maximum size of the Block Header. This amount is
+ // reserved in the beginning of the buffer so that Block Header
+ // along with Compressed Size and Uncompressed Size can be
+ // written there.
+ lzma_ret ret = lzma_block_header_size(&thr->block_options);
+ if (ret != LZMA_OK) {
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ // Initialize the Block encoder.
+ ret = lzma_block_encoder_init(&thr->block_encoder,
+ thr->allocator, &thr->block_options);
+ if (ret != LZMA_OK) {
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ size_t in_pos = 0;
+ size_t in_size = 0;
+
+ thr->outbuf->size = thr->block_options.header_size;
+ const size_t out_size = thr->coder->outq.buf_size_max;
+
+ do {
+ mythread_sync(thr->mutex) {
+ // Store in_pos and out_pos into *thr so that
+ // an application may read them via
+ // lzma_get_progress() to get progress information.
+ //
+ // NOTE: These aren't updated when the encoding
+ // finishes. Instead, the final values are taken
+ // later from thr->outbuf.
+ thr->progress_in = in_pos;
+ thr->progress_out = thr->outbuf->size;
+
+ while (in_size == thr->in_size
+ && thr->state == THR_RUN)
+ mythread_cond_wait(&thr->cond, &thr->mutex);
+
+ state = thr->state;
+ in_size = thr->in_size;
+ }
+
+ // Return if we were asked to stop or exit.
+ if (state >= THR_STOP)
+ return state;
+
+ lzma_action action = state == THR_FINISH
+ ? LZMA_FINISH : LZMA_RUN;
+
+ // Limit the amount of input given to the Block encoder
+ // at once. This way this thread can react fairly quickly
+ // if the main thread wants us to stop or exit.
+ static const size_t in_chunk_max = 16384;
+ size_t in_limit = in_size;
+ if (in_size - in_pos > in_chunk_max) {
+ in_limit = in_pos + in_chunk_max;
+ action = LZMA_RUN;
+ }
+
+ ret = thr->block_encoder.code(
+ thr->block_encoder.coder, thr->allocator,
+ thr->in, &in_pos, in_limit, thr->outbuf->buf,
+ &thr->outbuf->size, out_size, action);
+ } while (ret == LZMA_OK && thr->outbuf->size < out_size);
+
+ switch (ret) {
+ case LZMA_STREAM_END:
+ assert(state == THR_FINISH);
+
+ // Encode the Block Header. By doing it after
+ // the compression, we can store the Compressed Size
+ // and Uncompressed Size fields.
+ ret = lzma_block_header_encode(&thr->block_options,
+ thr->outbuf->buf);
+ if (ret != LZMA_OK) {
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ break;
+
+ case LZMA_OK:
+ // The data was incompressible. Encode it using uncompressed
+ // LZMA2 chunks.
+ //
+ // First wait that we have gotten all the input.
+ mythread_sync(thr->mutex) {
+ while (thr->state == THR_RUN)
+ mythread_cond_wait(&thr->cond, &thr->mutex);
+
+ state = thr->state;
+ in_size = thr->in_size;
+ }
+
+ if (state >= THR_STOP)
+ return state;
+
+ // Do the encoding. This takes care of the Block Header too.
+ thr->outbuf->size = 0;
+ ret = lzma_block_uncomp_encode(&thr->block_options,
+ thr->in, in_size, thr->outbuf->buf,
+ &thr->outbuf->size, out_size);
+
+ // It shouldn't fail.
+ if (ret != LZMA_OK) {
+ worker_error(thr, LZMA_PROG_ERROR);
+ return THR_STOP;
+ }
+
+ break;
+
+ default:
+ worker_error(thr, ret);
+ return THR_STOP;
+ }
+
+ // Set the size information that will be read by the main thread
+ // to write the Index field.
+ thr->outbuf->unpadded_size
+ = lzma_block_unpadded_size(&thr->block_options);
+ assert(thr->outbuf->unpadded_size != 0);
+ thr->outbuf->uncompressed_size = thr->block_options.uncompressed_size;
+
+ return THR_FINISH;
+}
+
+
+static MYTHREAD_RET_TYPE
+worker_start(void *thr_ptr)
+{
+ worker_thread *thr = thr_ptr;
+ worker_state state = THR_IDLE; // Init to silence a warning
+
+ while (true) {
+ // Wait for work.
+ mythread_sync(thr->mutex) {
+ while (true) {
+ // The thread is already idle so if we are
+ // requested to stop, just set the state.
+ if (thr->state == THR_STOP) {
+ thr->state = THR_IDLE;
+ mythread_cond_signal(&thr->cond);
+ }
+
+ state = thr->state;
+ if (state != THR_IDLE)
+ break;
+
+ mythread_cond_wait(&thr->cond, &thr->mutex);
+ }
+ }
+
+ assert(state != THR_IDLE);
+ assert(state != THR_STOP);
+
+ if (state <= THR_FINISH)
+ state = worker_encode(thr, state);
+
+ if (state == THR_EXIT)
+ break;
+
+ // Mark the thread as idle unless the main thread has
+ // told us to exit. Signal is needed for the case
+ // where the main thread is waiting for the threads to stop.
+ mythread_sync(thr->mutex) {
+ if (thr->state != THR_EXIT) {
+ thr->state = THR_IDLE;
+ mythread_cond_signal(&thr->cond);
+ }
+ }
+
+ mythread_sync(thr->coder->mutex) {
+ // Mark the output buffer as finished if
+ // no errors occurred.
+ thr->outbuf->finished = state == THR_FINISH;
+
+ // Update the main progress info.
+ thr->coder->progress_in
+ += thr->outbuf->uncompressed_size;
+ thr->coder->progress_out += thr->outbuf->size;
+ thr->progress_in = 0;
+ thr->progress_out = 0;
+
+ // Return this thread to the stack of free threads.
+ thr->next = thr->coder->threads_free;
+ thr->coder->threads_free = thr;
+
+ mythread_cond_signal(&thr->coder->cond);
+ }
+ }
+
+ // Exiting, free the resources.
+ mythread_mutex_destroy(&thr->mutex);
+ mythread_cond_destroy(&thr->cond);
+
+ lzma_next_end(&thr->block_encoder, thr->allocator);
+ lzma_free(thr->in, thr->allocator);
+ return MYTHREAD_RET_VALUE;
+}
+
+
+/// Make the threads stop but not exit. Optionally wait for them to stop.
+static void
+threads_stop(lzma_stream_coder *coder, bool wait_for_threads)
+{
+ // Tell the threads to stop.
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ coder->threads[i].state = THR_STOP;
+ mythread_cond_signal(&coder->threads[i].cond);
+ }
+ }
+
+ if (!wait_for_threads)
+ return;
+
+ // Wait for the threads to settle in the idle state.
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ while (coder->threads[i].state != THR_IDLE)
+ mythread_cond_wait(&coder->threads[i].cond,
+ &coder->threads[i].mutex);
+ }
+ }
+
+ return;
+}
+
+
+/// Stop the threads and free the resources associated with them.
+/// Wait until the threads have exited.
+static void
+threads_end(lzma_stream_coder *coder, const lzma_allocator *allocator)
+{
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ coder->threads[i].state = THR_EXIT;
+ mythread_cond_signal(&coder->threads[i].cond);
+ }
+ }
+
+ for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+ int ret = mythread_join(coder->threads[i].thread_id);
+ assert(ret == 0);
+ (void)ret;
+ }
+
+ lzma_free(coder->threads, allocator);
+ return;
+}
+
+
+/// Initialize a new worker_thread structure and create a new thread.
+static lzma_ret
+initialize_new_thread(lzma_stream_coder *coder,
+ const lzma_allocator *allocator)
+{
+ worker_thread *thr = &coder->threads[coder->threads_initialized];
+
+ thr->in = lzma_alloc(coder->block_size, allocator);
+ if (thr->in == NULL)
+ return LZMA_MEM_ERROR;
+
+ if (mythread_mutex_init(&thr->mutex))
+ goto error_mutex;
+
+ if (mythread_cond_init(&thr->cond))
+ goto error_cond;
+
+ thr->state = THR_IDLE;
+ thr->allocator = allocator;
+ thr->coder = coder;
+ thr->progress_in = 0;
+ thr->progress_out = 0;
+ thr->block_encoder = LZMA_NEXT_CODER_INIT;
+
+ if (mythread_create(&thr->thread_id, &worker_start, thr))
+ goto error_thread;
+
+ ++coder->threads_initialized;
+ coder->thr = thr;
+
+ return LZMA_OK;
+
+error_thread:
+ mythread_cond_destroy(&thr->cond);
+
+error_cond:
+ mythread_mutex_destroy(&thr->mutex);
+
+error_mutex:
+ lzma_free(thr->in, allocator);
+ return LZMA_MEM_ERROR;
+}
+
+
+static lzma_ret
+get_thread(lzma_stream_coder *coder, const lzma_allocator *allocator)
+{
+ // If there are no free output subqueues, there is no
+ // point to try getting a thread.
+ if (!lzma_outq_has_buf(&coder->outq))
+ return LZMA_OK;
+
+ // If there is a free structure on the stack, use it.
+ mythread_sync(coder->mutex) {
+ if (coder->threads_free != NULL) {
+ coder->thr = coder->threads_free;
+ coder->threads_free = coder->threads_free->next;
+ }
+ }
+
+ if (coder->thr == NULL) {
+ // If there are no uninitialized structures left, return.
+ if (coder->threads_initialized == coder->threads_max)
+ return LZMA_OK;
+
+ // Initialize a new thread.
+ return_if_error(initialize_new_thread(coder, allocator));
+ }
+
+ // Reset the parts of the thread state that have to be done
+ // in the main thread.
+ mythread_sync(coder->thr->mutex) {
+ coder->thr->state = THR_RUN;
+ coder->thr->in_size = 0;
+ coder->thr->outbuf = lzma_outq_get_buf(&coder->outq);
+ mythread_cond_signal(&coder->thr->cond);
+ }
+
+ return LZMA_OK;
+}
+
+
+static lzma_ret
+stream_encode_in(lzma_stream_coder *coder, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, lzma_action action)
+{
+ while (*in_pos < in_size
+ || (coder->thr != NULL && action != LZMA_RUN)) {
+ if (coder->thr == NULL) {
+ // Get a new thread.
+ const lzma_ret ret = get_thread(coder, allocator);
+ if (coder->thr == NULL)
+ return ret;
+ }
+
+ // Copy the input data to thread's buffer.
+ size_t thr_in_size = coder->thr->in_size;
+ lzma_bufcpy(in, in_pos, in_size, coder->thr->in,
+ &thr_in_size, coder->block_size);
+
+ // Tell the Block encoder to finish if
+ // - it has got block_size bytes of input; or
+ // - all input was used and LZMA_FINISH, LZMA_FULL_FLUSH,
+ // or LZMA_FULL_BARRIER was used.
+ //
+ // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER.
+ const bool finish = thr_in_size == coder->block_size
+ || (*in_pos == in_size && action != LZMA_RUN);
+
+ bool block_error = false;
+
+ mythread_sync(coder->thr->mutex) {
+ if (coder->thr->state == THR_IDLE) {
+ // Something has gone wrong with the Block
+ // encoder. It has set coder->thread_error
+ // which we will read a few lines later.
+ block_error = true;
+ } else {
+ // Tell the Block encoder its new amount
+ // of input and update the state if needed.
+ coder->thr->in_size = thr_in_size;
+
+ if (finish)
+ coder->thr->state = THR_FINISH;
+
+ mythread_cond_signal(&coder->thr->cond);
+ }
+ }
+
+ if (block_error) {
+ lzma_ret ret;
+
+ mythread_sync(coder->mutex) {
+ ret = coder->thread_error;
+ }
+
+ return ret;
+ }
+
+ if (finish)
+ coder->thr = NULL;
+ }
+
+ return LZMA_OK;
+}
+
+
+/// Wait until more input can be consumed, more output can be read, or
+/// an optional timeout is reached.
+static bool
+wait_for_work(lzma_stream_coder *coder, mythread_condtime *wait_abs,
+ bool *has_blocked, bool has_input)
+{
+ if (coder->timeout != 0 && !*has_blocked) {
+ // Every time when stream_encode_mt() is called via
+ // lzma_code(), *has_blocked starts as false. We set it
+ // to true here and calculate the absolute time when
+ // we must return if there's nothing to do.
+ //
+ // The idea of *has_blocked is to avoid unneeded calls
+ // to mythread_condtime_set(), which may do a syscall
+ // depending on the operating system.
+ *has_blocked = true;
+ mythread_condtime_set(wait_abs, &coder->cond, coder->timeout);
+ }
+
+ bool timed_out = false;
+
+ mythread_sync(coder->mutex) {
+ // There are four things that we wait. If one of them
+ // becomes possible, we return.
+ // - If there is input left, we need to get a free
+ // worker thread and an output buffer for it.
+ // - Data ready to be read from the output queue.
+ // - A worker thread indicates an error.
+ // - Time out occurs.
+ while ((!has_input || coder->threads_free == NULL
+ || !lzma_outq_has_buf(&coder->outq))
+ && !lzma_outq_is_readable(&coder->outq)
+ && coder->thread_error == LZMA_OK
+ && !timed_out) {
+ if (coder->timeout != 0)
+ timed_out = mythread_cond_timedwait(
+ &coder->cond, &coder->mutex,
+ wait_abs) != 0;
+ else
+ mythread_cond_wait(&coder->cond,
+ &coder->mutex);
+ }
+ }
+
+ return timed_out;
+}
+
+
+static lzma_ret
+stream_encode_mt(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+ lzma_stream_coder *coder = coder_ptr;
+
+ switch (coder->sequence) {
+ case SEQ_STREAM_HEADER:
+ lzma_bufcpy(coder->header, &coder->header_pos,
+ sizeof(coder->header),
+ out, out_pos, out_size);
+ if (coder->header_pos < sizeof(coder->header))
+ return LZMA_OK;
+
+ coder->header_pos = 0;
+ coder->sequence = SEQ_BLOCK;
+
+ // Fall through
+
+ case SEQ_BLOCK: {
+ // Initialized to silence warnings.
+ lzma_vli unpadded_size = 0;
+ lzma_vli uncompressed_size = 0;
+ lzma_ret ret = LZMA_OK;
+
+ // These are for wait_for_work().
+ bool has_blocked = false;
+ mythread_condtime wait_abs;
+
+ while (true) {
+ mythread_sync(coder->mutex) {
+ // Check for Block encoder errors.
+ ret = coder->thread_error;
+ if (ret != LZMA_OK) {
+ assert(ret != LZMA_STREAM_END);
+ break;
+ }
+
+ // Try to read compressed data to out[].
+ ret = lzma_outq_read(&coder->outq,
+ out, out_pos, out_size,
+ &unpadded_size,
+ &uncompressed_size);
+ }
+
+ if (ret == LZMA_STREAM_END) {
+ // End of Block. Add it to the Index.
+ ret = lzma_index_append(coder->index,
+ allocator, unpadded_size,
+ uncompressed_size);
+
+ // If we didn't fill the output buffer yet,
+ // try to read more data. Maybe the next
+ // outbuf has been finished already too.
+ if (*out_pos < out_size)
+ continue;
+ }
+
+ if (ret != LZMA_OK) {
+ // coder->thread_error was set or
+ // lzma_index_append() failed.
+ threads_stop(coder, false);
+ return ret;
+ }
+
+ // Try to give uncompressed data to a worker thread.
+ ret = stream_encode_in(coder, allocator,
+ in, in_pos, in_size, action);
+ if (ret != LZMA_OK) {
+ threads_stop(coder, false);
+ return ret;
+ }
+
+ // See if we should wait or return.
+ //
+ // TODO: LZMA_SYNC_FLUSH and LZMA_SYNC_BARRIER.
+ if (*in_pos == in_size) {
+ // LZMA_RUN: More data is probably coming
+ // so return to let the caller fill the
+ // input buffer.
+ if (action == LZMA_RUN)
+ return LZMA_OK;
+
+ // LZMA_FULL_BARRIER: The same as with
+ // LZMA_RUN but tell the caller that the
+ // barrier was completed.
+ if (action == LZMA_FULL_BARRIER)
+ return LZMA_STREAM_END;
+
+ // Finishing or flushing isn't completed until
+ // all input data has been encoded and copied
+ // to the output buffer.
+ if (lzma_outq_is_empty(&coder->outq)) {
+ // LZMA_FINISH: Continue to encode
+ // the Index field.
+ if (action == LZMA_FINISH)
+ break;
+
+ // LZMA_FULL_FLUSH: Return to tell
+ // the caller that flushing was
+ // completed.
+ if (action == LZMA_FULL_FLUSH)
+ return LZMA_STREAM_END;
+ }
+ }
+
+ // Return if there is no output space left.
+ // This check must be done after testing the input
+ // buffer, because we might want to use a different
+ // return code.
+ if (*out_pos == out_size)
+ return LZMA_OK;
+
+ // Neither in nor out has been used completely.
+ // Wait until there's something we can do.
+ if (wait_for_work(coder, &wait_abs, &has_blocked,
+ *in_pos < in_size))
+ return LZMA_TIMED_OUT;
+ }
+
+ // All Blocks have been encoded and the threads have stopped.
+ // Prepare to encode the Index field.
+ return_if_error(lzma_index_encoder_init(
+ &coder->index_encoder, allocator,
+ coder->index));
+ coder->sequence = SEQ_INDEX;
+
+ // Update the progress info to take the Index and
+ // Stream Footer into account. Those are very fast to encode
+ // so in terms of progress information they can be thought
+ // to be ready to be copied out.
+ coder->progress_out += lzma_index_size(coder->index)
+ + LZMA_STREAM_HEADER_SIZE;
+ }
+
+ // Fall through
+
+ case SEQ_INDEX: {
+ // Call the Index encoder. It doesn't take any input, so
+ // those pointers can be NULL.
+ const lzma_ret ret = coder->index_encoder.code(
+ coder->index_encoder.coder, allocator,
+ NULL, NULL, 0,
+ out, out_pos, out_size, LZMA_RUN);
+ if (ret != LZMA_STREAM_END)
+ return ret;
+
+ // Encode the Stream Footer into coder->buffer.
+ coder->stream_flags.backward_size
+ = lzma_index_size(coder->index);
+ if (lzma_stream_footer_encode(&coder->stream_flags,
+ coder->header) != LZMA_OK)
+ return LZMA_PROG_ERROR;
+
+ coder->sequence = SEQ_STREAM_FOOTER;
+ }
+
+ // Fall through
+
+ case SEQ_STREAM_FOOTER:
+ lzma_bufcpy(coder->header, &coder->header_pos,
+ sizeof(coder->header),
+ out, out_pos, out_size);
+ return coder->header_pos < sizeof(coder->header)
+ ? LZMA_OK : LZMA_STREAM_END;
+ }
+
+ assert(0);
+ return LZMA_PROG_ERROR;
+}
+
+
+static void
+stream_encoder_mt_end(void *coder_ptr, const lzma_allocator *allocator)
+{
+ lzma_stream_coder *coder = coder_ptr;
+
+ // Threads must be killed before the output queue can be freed.
+ threads_end(coder, allocator);
+ lzma_outq_end(&coder->outq, allocator);
+
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ lzma_free(coder->filters[i].options, allocator);
+
+ lzma_next_end(&coder->index_encoder, allocator);
+ lzma_index_end(coder->index, allocator);
+
+ mythread_cond_destroy(&coder->cond);
+ mythread_mutex_destroy(&coder->mutex);
+
+ lzma_free(coder, allocator);
+ return;
+}
+
+
+/// Options handling for lzma_stream_encoder_mt_init() and
+/// lzma_stream_encoder_mt_memusage()
+static lzma_ret
+get_options(const lzma_mt *options, lzma_options_easy *opt_easy,
+ const lzma_filter **filters, uint64_t *block_size,
+ uint64_t *outbuf_size_max)
+{
+ // Validate some of the options.
+ if (options == NULL)
+ return LZMA_PROG_ERROR;
+
+ if (options->flags != 0 || options->threads == 0
+ || options->threads > LZMA_THREADS_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ if (options->filters != NULL) {
+ // Filter chain was given, use it as is.
+ *filters = options->filters;
+ } else {
+ // Use a preset.
+ if (lzma_easy_preset(opt_easy, options->preset))
+ return LZMA_OPTIONS_ERROR;
+
+ *filters = opt_easy->filters;
+ }
+
+ // Block size
+ if (options->block_size > 0) {
+ if (options->block_size > BLOCK_SIZE_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ *block_size = options->block_size;
+ } else {
+ // Determine the Block size from the filter chain.
+ *block_size = lzma_mt_block_size(*filters);
+ if (*block_size == 0)
+ return LZMA_OPTIONS_ERROR;
+
+ assert(*block_size <= BLOCK_SIZE_MAX);
+ }
+
+ // Calculate the maximum amount output that a single output buffer
+ // may need to hold. This is the same as the maximum total size of
+ // a Block.
+ *outbuf_size_max = lzma_block_buffer_bound64(*block_size);
+ if (*outbuf_size_max == 0)
+ return LZMA_MEM_ERROR;
+
+ return LZMA_OK;
+}
+
+
+static void
+get_progress(void *coder_ptr, uint64_t *progress_in, uint64_t *progress_out)
+{
+ lzma_stream_coder *coder = coder_ptr;
+
+ // Lock coder->mutex to prevent finishing threads from moving their
+ // progress info from the worker_thread structure to lzma_stream_coder.
+ mythread_sync(coder->mutex) {
+ *progress_in = coder->progress_in;
+ *progress_out = coder->progress_out;
+
+ for (size_t i = 0; i < coder->threads_initialized; ++i) {
+ mythread_sync(coder->threads[i].mutex) {
+ *progress_in += coder->threads[i].progress_in;
+ *progress_out += coder->threads[i]
+ .progress_out;
+ }
+ }
+ }
+
+ return;
+}
+
+
+static lzma_ret
+stream_encoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator,
+ const lzma_mt *options)
+{
+ lzma_next_coder_init(&stream_encoder_mt_init, next, allocator);
+
+ // Get the filter chain.
+ lzma_options_easy easy;
+ const lzma_filter *filters;
+ uint64_t block_size;
+ uint64_t outbuf_size_max;
+ return_if_error(get_options(options, &easy, &filters,
+ &block_size, &outbuf_size_max));
+
+#if SIZE_MAX < UINT64_MAX
+ if (block_size > SIZE_MAX)
+ return LZMA_MEM_ERROR;
+#endif
+
+ // Validate the filter chain so that we can give an error in this
+ // function instead of delaying it to the first call to lzma_code().
+ // The memory usage calculation verifies the filter chain as
+ // a side effect so we take advatange of that.
+ if (lzma_raw_encoder_memusage(filters) == UINT64_MAX)
+ return LZMA_OPTIONS_ERROR;
+
+ // Validate the Check ID.
+ if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX)
+ return LZMA_PROG_ERROR;
+
+ if (!lzma_check_is_supported(options->check))
+ return LZMA_UNSUPPORTED_CHECK;
+
+ // Allocate and initialize the base structure if needed.
+ lzma_stream_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
+ if (coder == NULL)
+ return LZMA_MEM_ERROR;
+
+ next->coder = coder;
+
+ // For the mutex and condition variable initializations
+ // the error handling has to be done here because
+ // stream_encoder_mt_end() doesn't know if they have
+ // already been initialized or not.
+ if (mythread_mutex_init(&coder->mutex)) {
+ lzma_free(coder, allocator);
+ next->coder = NULL;
+ return LZMA_MEM_ERROR;
+ }
+
+ if (mythread_cond_init(&coder->cond)) {
+ mythread_mutex_destroy(&coder->mutex);
+ lzma_free(coder, allocator);
+ next->coder = NULL;
+ return LZMA_MEM_ERROR;
+ }
+
+ next->code = &stream_encode_mt;
+ next->end = &stream_encoder_mt_end;
+ next->get_progress = &get_progress;
+// next->update = &stream_encoder_mt_update;
+
+ coder->filters[0].id = LZMA_VLI_UNKNOWN;
+ coder->index_encoder = LZMA_NEXT_CODER_INIT;
+ coder->index = NULL;
+ memzero(&coder->outq, sizeof(coder->outq));
+ coder->threads = NULL;
+ coder->threads_max = 0;
+ coder->threads_initialized = 0;
+ }
+
+ // Basic initializations
+ coder->sequence = SEQ_STREAM_HEADER;
+ coder->block_size = (size_t)(block_size);
+ coder->thread_error = LZMA_OK;
+ coder->thr = NULL;
+
+ // Allocate the thread-specific base structures.
+ assert(options->threads > 0);
+ if (coder->threads_max != options->threads) {
+ threads_end(coder, allocator);
+
+ coder->threads = NULL;
+ coder->threads_max = 0;
+
+ coder->threads_initialized = 0;
+ coder->threads_free = NULL;
+
+ coder->threads = lzma_alloc(
+ options->threads * sizeof(worker_thread),
+ allocator);
+ if (coder->threads == NULL)
+ return LZMA_MEM_ERROR;
+
+ coder->threads_max = options->threads;
+ } else {
+ // Reuse the old structures and threads. Tell the running
+ // threads to stop and wait until they have stopped.
+ threads_stop(coder, true);
+ }
+
+ // Output queue
+ return_if_error(lzma_outq_init(&coder->outq, allocator,
+ outbuf_size_max, options->threads));
+
+ // Timeout
+ coder->timeout = options->timeout;
+
+ // Free the old filter chain and copy the new one.
+ for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ lzma_free(coder->filters[i].options, allocator);
+
+ return_if_error(lzma_filters_copy(
+ filters, coder->filters, allocator));
+
+ // Index
+ lzma_index_end(coder->index, allocator);
+ coder->index = lzma_index_init(allocator);
+ if (coder->index == NULL)
+ return LZMA_MEM_ERROR;
+
+ // Stream Header
+ coder->stream_flags.version = 0;
+ coder->stream_flags.check = options->check;
+ return_if_error(lzma_stream_header_encode(
+ &coder->stream_flags, coder->header));
+
+ coder->header_pos = 0;
+
+ // Progress info
+ coder->progress_in = 0;
+ coder->progress_out = LZMA_STREAM_HEADER_SIZE;
+
+ return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_encoder_mt(lzma_stream *strm, const lzma_mt *options)
+{
+ lzma_next_strm_init(stream_encoder_mt_init, strm, options);
+
+ strm->internal->supported_actions[LZMA_RUN] = true;
+// strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+ strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
+ strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
+ strm->internal->supported_actions[LZMA_FINISH] = true;
+
+ return LZMA_OK;
+}
+
+
+// This function name is a monster but it's consistent with the older
+// monster names. :-( 31 chars is the max that C99 requires so in that
+// sense it's not too long. ;-)
+extern LZMA_API(uint64_t)
+lzma_stream_encoder_mt_memusage(const lzma_mt *options)
+{
+ lzma_options_easy easy;
+ const lzma_filter *filters;
+ uint64_t block_size;
+ uint64_t outbuf_size_max;
+
+ if (get_options(options, &easy, &filters, &block_size,
+ &outbuf_size_max) != LZMA_OK)
+ return UINT64_MAX;
+
+ // Memory usage of the input buffers
+ const uint64_t inbuf_memusage = options->threads * block_size;
+
+ // Memory usage of the filter encoders
+ uint64_t filters_memusage = lzma_raw_encoder_memusage(filters);
+ if (filters_memusage == UINT64_MAX)
+ return UINT64_MAX;
+
+ filters_memusage *= options->threads;
+
+ // Memory usage of the output queue
+ const uint64_t outq_memusage = lzma_outq_memusage(
+ outbuf_size_max, options->threads);
+ if (outq_memusage == UINT64_MAX)
+ return UINT64_MAX;
+
+ // Sum them with overflow checking.
+ uint64_t total_memusage = LZMA_MEMUSAGE_BASE
+ + sizeof(lzma_stream_coder)
+ + options->threads * sizeof(worker_thread);
+
+ if (UINT64_MAX - total_memusage < inbuf_memusage)
+ return UINT64_MAX;
+
+ total_memusage += inbuf_memusage;
+
+ if (UINT64_MAX - total_memusage < filters_memusage)
+ return UINT64_MAX;
+
+ total_memusage += filters_memusage;
+
+ if (UINT64_MAX - total_memusage < outq_memusage)
+ return UINT64_MAX;
+
+ return total_memusage + outq_memusage;
+}
extern LZMA_API(lzma_ret)
lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
{
- uint32_t crc;
-
// Magic
if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0)
return LZMA_FORMAT_ERROR;
// Verify the CRC32 so we can distinguish between corrupt
// and unsupported files.
- crc = lzma_crc32(in + sizeof(lzma_header_magic),
+ const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
LZMA_STREAM_FLAGS_SIZE, 0);
if (crc != unaligned_read32le(in + sizeof(lzma_header_magic)
+ LZMA_STREAM_FLAGS_SIZE))
extern LZMA_API(lzma_ret)
lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
{
- uint32_t crc;
-
// Magic
if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE,
lzma_footer_magic, sizeof(lzma_footer_magic)) != 0)
return LZMA_FORMAT_ERROR;
// CRC32
- crc = lzma_crc32(in + sizeof(uint32_t),
+ const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
if (crc != unaligned_read32le(in))
return LZMA_DATA_ERROR;
extern LZMA_API(lzma_ret)
lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
{
- uint32_t crc;
-
assert(sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE
+ 4 == LZMA_STREAM_HEADER_SIZE);
return LZMA_PROG_ERROR;
// CRC32 of the Stream Header
- crc = lzma_crc32(out + sizeof(lzma_header_magic),
+ const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic),
LZMA_STREAM_FLAGS_SIZE, 0);
unaligned_write32le(out + sizeof(lzma_header_magic)
extern LZMA_API(lzma_ret)
lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
{
- uint32_t crc;
-
assert(2 * 4 + LZMA_STREAM_FLAGS_SIZE + sizeof(lzma_footer_magic)
== LZMA_STREAM_HEADER_SIZE);
return LZMA_PROG_ERROR;
// CRC32
- crc = lzma_crc32(
+ const uint32_t crc = lzma_crc32(
out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0);
unaligned_write32le(out, crc);
extern LZMA_API(lzma_ret)
-lzma_vli_decode(lzma_vli *LZMA_RESTRICT vli, size_t *vli_pos,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size)
{
// If we haven't been given vli_pos, work in single-call mode.
extern LZMA_API(lzma_ret)
lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size)
{
// If we haven't been given vli_pos, work in single-call mode.
extern LZMA_API(uint32_t)
lzma_vli_size(lzma_vli vli)
{
- uint32_t i = 0;
-
if (vli > LZMA_VLI_MAX)
return 0;
+ uint32_t i = 0;
do {
vli >>= 7;
++i;
static void
-delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
+delta_coder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_delta_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
extern lzma_ret
-lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_delta_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
- const lzma_options_delta *opt;
-
// Allocate memory for the decoder if needed.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_delta_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_delta_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
+
// End function is the same for encoder and decoder.
next->end = &delta_coder_end;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Validate the options.
return LZMA_OPTIONS_ERROR;
// Set the delta distance.
- opt = filters[0].options;
- next->coder->distance = opt->dist;
+ const lzma_options_delta *opt = filters[0].options;
+ coder->distance = opt->dist;
// Initialize the rest of the variables.
- next->coder->pos = 0;
- memzero(next->coder->history, LZMA_DELTA_DIST_MAX);
+ coder->pos = 0;
+ memzero(coder->history, LZMA_DELTA_DIST_MAX);
// Initialize the next decoder in the chain, if any.
- return lzma_next_filter_init(&next->coder->next,
- allocator, filters + 1);
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
|| opt->dist > LZMA_DELTA_DIST_MAX)
return UINT64_MAX;
- return sizeof(lzma_coder);
+ return sizeof(lzma_delta_coder);
}
static void
-decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
+decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
{
- size_t i;
const size_t distance = coder->distance;
- for (i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = buffer[i];
}
static lzma_ret
-delta_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+delta_decode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
- const size_t out_start = *out_pos;
- lzma_ret ret;
+ lzma_delta_coder *coder = coder_ptr;
assert(coder->next.code != NULL);
- ret = coder->next.code(coder->next.coder, allocator,
+ const size_t out_start = *out_pos;
+
+ const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
extern lzma_ret
-lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
next->code = &delta_decode;
extern lzma_ret
-lzma_delta_props_decode(void **options, lzma_allocator *allocator,
+lzma_delta_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_delta *opt;
-
if (props_size != 1)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_delta), allocator);
+ lzma_options_delta *opt
+ = lzma_alloc(sizeof(lzma_options_delta), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
#include "delta_common.h"
extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_delta_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
#endif
/// is the first filter in the chain (and thus the last filter in the
/// encoder's filter stack).
static void
-copy_and_encode(lzma_coder *coder,
- const uint8_t *LZMA_RESTRICT in, uint8_t *LZMA_RESTRICT out, size_t size)
+copy_and_encode(lzma_delta_coder *coder,
+ const uint8_t *restrict in, uint8_t *restrict out, size_t size)
{
- size_t i;
const size_t distance = coder->distance;
- for (i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
const uint8_t tmp = coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = in[i];
/// Encodes the data in place. This is used when we are the last filter
/// in the chain (and thus non-last filter in the encoder's filter stack).
static void
-encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
+encode_in_place(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
{
- size_t i;
const size_t distance = coder->distance;
- for (i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
const uint8_t tmp = coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = buffer[i];
static lzma_ret
-delta_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+delta_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
+ lzma_delta_coder *coder = coder_ptr;
+
lzma_ret ret;
if (coder->next.code == NULL) {
static lzma_ret
-delta_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+delta_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters_null lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_delta_coder *coder = coder_ptr;
+
// Delta doesn't and will never support changing the options in
// the middle of encoding. If the app tries to change them, we
// simply ignore them.
extern lzma_ret
-lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_delta_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
next->code = &delta_encode;
extern lzma_ret
lzma_delta_props_encode(const void *options, uint8_t *out)
{
- const lzma_options_delta *opt = options;
-
// The caller must have already validated the options, so it's
// LZMA_PROG_ERROR if they are invalid.
if (lzma_delta_coder_memusage(options) == UINT64_MAX)
return LZMA_PROG_ERROR;
+ const lzma_options_delta *opt = options;
out[0] = opt->dist - LZMA_DELTA_DIST_MIN;
return LZMA_OK;
#include "delta_common.h"
extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_delta_props_encode(const void *options, uint8_t *out);
#include "delta_common.h"
-struct lzma_coder_s {
+typedef struct {
/// Next coder in the chain
lzma_next_coder next;
/// Buffer to hold history of the original data
uint8_t history[LZMA_DELTA_DIST_MAX];
-};
+} lzma_delta_coder;
extern lzma_ret lzma_delta_coder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters);
#endif
Version: @PACKAGE_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -llzma
-Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
+Libs.private: @PTHREAD_CFLAGS@ @LIBS@
#include "lz_decoder.h"
-struct lzma_coder_s {
+typedef struct {
/// Dictionary (history buffer)
lzma_dict dict;
size_t size;
uint8_t buffer[LZMA_BUFFER_SIZE];
} temp;
-};
+} lzma_coder;
static void
static lzma_ret
decode_buffer(lzma_coder *coder,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size)
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size)
{
while (true) {
- size_t copy_size;
- size_t dict_start;
- lzma_ret ret;
-
// Wrap the dictionary if needed.
if (coder->dict.pos == coder->dict.size)
coder->dict.pos = 0;
// Store the current dictionary position. It is needed to know
// where to start copying to the out[] buffer.
- dict_start = coder->dict.pos;
+ const size_t dict_start = coder->dict.pos;
// Calculate how much we allow coder->lz.code() to decode.
// It must not decode past the end of the dictionary
coder->dict.size - coder->dict.pos);
// Call the coder->lz.code() to do the actual decoding.
- ret = coder->lz.code(
+ const lzma_ret ret = coder->lz.code(
coder->lz.coder, &coder->dict,
in, in_pos, in_size);
// Copy the decoded data from the dictionary to the out[]
// buffer.
- copy_size = coder->dict.pos - dict_start;
+ const size_t copy_size = coder->dict.pos - dict_start;
assert(copy_size <= out_size - *out_pos);
memcpy(out + *out_pos, coder->dict.buf + dict_start,
copy_size);
static lzma_ret
-lz_decode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((__unused__)),
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+lz_decode(void *coder_ptr,
+ const lzma_allocator *allocator lzma_attribute((__unused__)),
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
lzma_action action)
{
+ lzma_coder *coder = coder_ptr;
+
if (coder->next.code == NULL)
return decode_buffer(coder, in, in_pos, in_size,
out, out_pos, out_size);
// We aren't the last coder in the chain, we need to decode
// our input to a temporary buffer.
while (*out_pos < out_size) {
- lzma_ret ret;
-
// Fill the temporary buffer if it is empty.
if (!coder->next_finished
&& coder->temp.pos == coder->temp.size) {
coder->temp.pos = 0;
coder->temp.size = 0;
- ret = coder->next.code(
+ const lzma_ret ret = coder->next.code(
coder->next.coder,
allocator, in, in_pos, in_size,
coder->temp.buffer, &coder->temp.size,
return LZMA_OK;
}
- ret = decode_buffer(coder, coder->temp.buffer,
+ const lzma_ret ret = decode_buffer(coder, coder->temp.buffer,
&coder->temp.pos, coder->temp.size,
out, out_pos, out_size);
static void
-lz_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lz_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_coder *coder = coder_ptr;
+
lzma_next_end(&coder->next, allocator);
lzma_free(coder->dict.buf, allocator);
extern lzma_ret
-lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_decoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options))
{
- lzma_lz_options lz_options;
-
// Allocate the base structure if it isn't already allocated.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &lz_decode;
next->end = &lz_decoder_end;
- next->coder->dict.buf = NULL;
- next->coder->dict.size = 0;
- next->coder->lz = LZMA_LZ_DECODER_INIT;
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->dict.buf = NULL;
+ coder->dict.size = 0;
+ coder->lz = LZMA_LZ_DECODER_INIT;
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Allocate and initialize the LZ-based decoder. It will also give
// us the dictionary size.
- return_if_error(lz_init(&next->coder->lz, allocator,
+ lzma_lz_options lz_options;
+ return_if_error(lz_init(&coder->lz, allocator,
filters[0].options, &lz_options));
// If the dictionary size is very small, increase it to 4096 bytes.
lz_options.dict_size = (lz_options.dict_size + 15) & ~((size_t)(15));
// Allocate and initialize the dictionary.
- if (next->coder->dict.size != lz_options.dict_size) {
- lzma_free(next->coder->dict.buf, allocator);
- next->coder->dict.buf
+ if (coder->dict.size != lz_options.dict_size) {
+ lzma_free(coder->dict.buf, allocator);
+ coder->dict.buf
= lzma_alloc(lz_options.dict_size, allocator);
- if (next->coder->dict.buf == NULL)
+ if (coder->dict.buf == NULL)
return LZMA_MEM_ERROR;
- next->coder->dict.size = lz_options.dict_size;
+ coder->dict.size = lz_options.dict_size;
}
lz_decoder_reset(next->coder);
const size_t copy_size = my_min(lz_options.preset_dict_size,
lz_options.dict_size);
const size_t offset = lz_options.preset_dict_size - copy_size;
- memcpy(next->coder->dict.buf, lz_options.preset_dict + offset,
+ memcpy(coder->dict.buf, lz_options.preset_dict + offset,
copy_size);
- next->coder->dict.pos = copy_size;
- next->coder->dict.full = copy_size;
+ coder->dict.pos = copy_size;
+ coder->dict.full = copy_size;
}
// Miscellaneous initializations
- next->coder->next_finished = false;
- next->coder->this_finished = false;
- next->coder->temp.pos = 0;
- next->coder->temp.size = 0;
+ coder->next_finished = false;
+ coder->this_finished = false;
+ coder->temp.pos = 0;
+ coder->temp.size = 0;
// Initialize the next filter in the chain, if any.
- return lzma_next_filter_init(&next->coder->next, allocator,
- filters + 1);
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
extern void
-lzma_lz_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+lzma_lz_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
{
+ lzma_coder *coder = coder_ptr;
coder->lz.set_uncompressed(coder->lz.coder, uncompressed_size);
}
typedef struct {
/// Data specific to the LZ-based decoder
- lzma_coder *coder;
+ void *coder;
/// Function to decode from in[] to *dict
- lzma_ret (*code)(lzma_coder *LZMA_RESTRICT coder,
- lzma_dict *LZMA_RESTRICT dict, const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size);
+ lzma_ret (*code)(void *coder,
+ lzma_dict *restrict dict, const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size);
- void (*reset)(lzma_coder *coder, const void *options);
+ void (*reset)(void *coder, const void *options);
/// Set the uncompressed size
- void (*set_uncompressed)(lzma_coder *coder,
- lzma_vli uncompressed_size);
+ void (*set_uncompressed)(void *coder, lzma_vli uncompressed_size);
/// Free allocated resources
- void (*end)(lzma_coder *coder, lzma_allocator *allocator);
+ void (*end)(void *coder, const lzma_allocator *allocator);
} lzma_lz_decoder;
-static const lzma_lz_decoder LZMA_LZ_DECODER_INIT =
- {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- };
+#define LZMA_LZ_DECODER_INIT \
+ (lzma_lz_decoder){ \
+ .coder = NULL, \
+ .code = NULL, \
+ .reset = NULL, \
+ .set_uncompressed = NULL, \
+ .end = NULL, \
+ }
extern lzma_ret lzma_lz_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters,
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_decoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options));
extern uint64_t lzma_lz_decoder_memusage(size_t dictionary_size);
extern void lzma_lz_decoder_uncompressed(
- lzma_coder *coder, lzma_vli uncompressed_size);
+ void *coder, lzma_vli uncompressed_size);
//////////////////////
dict->pos += left;
} else {
- uint32_t copy_pos;
- uint32_t copy_size;
-
// The bigger the dictionary, the more rare this
// case occurs. We need to "wrap" the dict, thus
// we might need two memcpy() to copy all the data.
assert(dict->full == dict->size);
- copy_pos = dict->pos - distance - 1 + dict->size;
- copy_size = dict->size - copy_pos;
+ const uint32_t copy_pos
+ = dict->pos - distance - 1 + dict->size;
+ uint32_t copy_size = dict->size - copy_pos;
if (copy_size < left) {
memmove(dict->buf + dict->pos, dict->buf + copy_pos,
/// Copies arbitrary amount of data into the dictionary.
static inline void
-dict_write(lzma_dict *LZMA_RESTRICT dict, const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size,
- size_t *LZMA_RESTRICT left)
+dict_write(lzma_dict *restrict dict, const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size,
+ size_t *restrict left)
{
// NOTE: If we are being given more data than the size of the
// dictionary, it could be possible to optimize the LZ decoder
# include "lz_encoder_hash_table.h"
#endif
+#include "memcmplen.h"
-struct lzma_coder_s {
+
+typedef struct {
/// LZ-based encoder e.g. LZMA
lzma_lz_encoder lz;
/// Next coder in the chain
lzma_next_coder next;
-};
+} lzma_coder;
/// \brief Moves the data in the input window to free space for new data
static void
move_window(lzma_mf *mf)
{
- uint32_t move_offset;
- size_t move_size;
-
// Align the move to a multiple of 16 bytes. Some LZ-based encoders
// like LZMA use the lowest bits of mf->read_pos to know the
// alignment of the uncompressed data. We also get better speed
// for memmove() with aligned buffers.
assert(mf->read_pos > mf->keep_size_before);
- move_offset = (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
+ const uint32_t move_offset
+ = (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
assert(mf->write_pos > move_offset);
- move_size = mf->write_pos - move_offset;
+ const size_t move_size = mf->write_pos - move_offset;
assert(move_offset + move_size <= mf->size);
/// This function must not be called once it has returned LZMA_STREAM_END.
///
static lzma_ret
-fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
- size_t *in_pos, size_t in_size, lzma_action action)
+fill_window(lzma_coder *coder, const lzma_allocator *allocator,
+ const uint8_t *in, size_t *in_pos, size_t in_size,
+ lzma_action action)
{
- size_t write_pos;
- lzma_ret ret;
-
assert(coder->mf.read_pos <= coder->mf.write_pos);
// Move the sliding window if needed.
// Maybe this is ugly, but lzma_mf uses uint32_t for most things
// (which I find cleanest), but we need size_t here when filling
// the history window.
- write_pos = coder->mf.write_pos;
+ size_t write_pos = coder->mf.write_pos;
+ lzma_ret ret;
if (coder->next.code == NULL) {
// Not using a filter, simply memcpy() as much as possible.
lzma_bufcpy(in, in_pos, in_size, coder->mf.buffer,
coder->mf.write_pos = write_pos;
+ // Silence Valgrind. lzma_memcmplen() can read extra bytes
+ // and Valgrind will give warnings if those bytes are uninitialized
+ // because Valgrind cannot see that the values of the uninitialized
+ // bytes are eventually ignored.
+ memzero(coder->mf.buffer + write_pos, LZMA_MEMCMPLEN_EXTRA);
+
// If end of stream has been reached or flushing completed, we allow
// the encoder to process all the input (that is, read_pos is allowed
// to reach write_pos). Otherwise we keep keep_size_after bytes
&& coder->mf.read_pos < coder->mf.read_limit) {
// Match finder may update coder->pending and expects it to
// start from zero, so use a temporary variable.
- const size_t pending = coder->mf.pending;
+ const uint32_t pending = coder->mf.pending;
coder->mf.pending = 0;
// Rewind read_pos so that the match finder can hash
static lzma_ret
-lz_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+lz_encode(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size, lzma_action action)
{
+ lzma_coder *coder = coder_ptr;
+
while (*out_pos < out_size
&& (*in_pos < in_size || action != LZMA_RUN)) {
- lzma_ret ret;
-
// Read more data to coder->mf.buffer if needed.
if (coder->mf.action == LZMA_RUN && coder->mf.read_pos
>= coder->mf.read_limit)
in, in_pos, in_size, action));
// Encode
- ret = coder->lz.code(coder->lz.coder,
+ const lzma_ret ret = coder->lz.code(coder->lz.coder,
&coder->mf, out, out_pos, out_size);
if (ret != LZMA_OK) {
// Setting this to LZMA_RUN for cases when we are
static bool
-lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
+lz_encoder_prepare(lzma_mf *mf, const lzma_allocator *allocator,
const lzma_lz_options *lz_options)
{
- bool is_bt;
- uint32_t new_count;
- uint32_t reserve;
- uint32_t old_size;
- uint32_t hash_bytes;
- uint32_t hs;
- uint32_t old_count;
-
// For now, the dictionary size is limited to 1.5 GiB. This may grow
// in the future if needed, but it needs a little more work than just
// changing this check.
// to size_t.
// - Memory usage calculation needs something too, e.g. use uint64_t
// for mf->size.
- reserve = lz_options->dict_size / 2;
+ uint32_t reserve = lz_options->dict_size / 2;
if (reserve > (UINT32_C(1) << 30))
reserve /= 2;
reserve += (lz_options->before_size + lz_options->match_len_max
+ lz_options->after_size) / 2 + (UINT32_C(1) << 19);
- old_size = mf->size;
+ const uint32_t old_size = mf->size;
mf->size = mf->keep_size_before + reserve + mf->keep_size_after;
// Deallocate the old history buffer if it exists but has different
// Calculate the sizes of mf->hash and mf->son and check that
// nice_len is big enough for the selected match finder.
- hash_bytes = lz_options->match_finder & 0x0F;
+ const uint32_t hash_bytes = lz_options->match_finder & 0x0F;
if (hash_bytes > mf->nice_len)
return true;
- is_bt = (lz_options->match_finder & 0x10) != 0;
+ const bool is_bt = (lz_options->match_finder & 0x10) != 0;
+ uint32_t hs;
if (hash_bytes == 2) {
hs = 0xFFFF;
hs += HASH_4_SIZE;
*/
- // If the above code calculating hs is modified, make sure that
- // this assertion stays valid (UINT32_MAX / 5 is not strictly the
- // exact limit). If it doesn't, you need to calculate that
- // hash_size_sum + sons_count cannot overflow.
- assert(hs < UINT32_MAX / 5);
-
- old_count = mf->hash_size_sum + mf->sons_count;
- mf->hash_size_sum = hs;
+ const uint32_t old_hash_count = mf->hash_count;
+ const uint32_t old_sons_count = mf->sons_count;
+ mf->hash_count = hs;
mf->sons_count = mf->cyclic_size;
if (is_bt)
mf->sons_count *= 2;
- new_count = mf->hash_size_sum + mf->sons_count;
-
// Deallocate the old hash array if it exists and has different size
// than what is needed now.
- if (old_count != new_count) {
+ if (old_hash_count != mf->hash_count
+ || old_sons_count != mf->sons_count) {
lzma_free(mf->hash, allocator);
mf->hash = NULL;
+
+ lzma_free(mf->son, allocator);
+ mf->son = NULL;
}
// Maximum number of match finder cycles
static bool
-lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
+lz_encoder_init(lzma_mf *mf, const lzma_allocator *allocator,
const lzma_lz_options *lz_options)
{
- size_t alloc_count;
-
// Allocate the history buffer.
if (mf->buffer == NULL) {
- mf->buffer = lzma_alloc(mf->size, allocator);
+ // lzma_memcmplen() is used for the dictionary buffer
+ // so we need to allocate a few extra bytes to prevent
+ // it from reading past the end of the buffer.
+ mf->buffer = lzma_alloc(mf->size + LZMA_MEMCMPLEN_EXTRA,
+ allocator);
if (mf->buffer == NULL)
return true;
+
+ // Keep Valgrind happy with lzma_memcmplen() and initialize
+ // the extra bytes whose value may get read but which will
+ // effectively get ignored.
+ memzero(mf->buffer + mf->size, LZMA_MEMCMPLEN_EXTRA);
}
// Use cyclic_size as initial mf->offset. This allows
mf->write_pos = 0;
mf->pending = 0;
- // Allocate match finder's hash array.
- alloc_count = mf->hash_size_sum + mf->sons_count;
-
#if UINT32_MAX >= SIZE_MAX / 4
// Check for integer overflow. (Huge dictionaries are not
// possible on 32-bit CPU.)
- if (alloc_count > SIZE_MAX / sizeof(uint32_t))
+ if (mf->hash_count > SIZE_MAX / sizeof(uint32_t)
+ || mf->sons_count > SIZE_MAX / sizeof(uint32_t))
return true;
#endif
+ // Allocate and initialize the hash table. Since EMPTY_HASH_VALUE
+ // is zero, we can use lzma_alloc_zero() or memzero() for mf->hash.
+ //
+ // We don't need to initialize mf->son, but not doing that may
+ // make Valgrind complain in normalization (see normalize() in
+ // lz_encoder_mf.c). Skipping the initialization is *very* good
+ // when big dictionary is used but only small amount of data gets
+ // actually compressed: most of the mf->son won't get actually
+ // allocated by the kernel, so we avoid wasting RAM and improve
+ // initialization speed a lot.
if (mf->hash == NULL) {
- mf->hash = lzma_alloc(alloc_count * sizeof(uint32_t),
+ mf->hash = lzma_alloc_zero(mf->hash_count * sizeof(uint32_t),
+ allocator);
+ mf->son = lzma_alloc(mf->sons_count * sizeof(uint32_t),
allocator);
- if (mf->hash == NULL)
- return true;
- }
- mf->son = mf->hash + mf->hash_size_sum;
- mf->cyclic_pos = 0;
+ if (mf->hash == NULL || mf->son == NULL) {
+ lzma_free(mf->hash, allocator);
+ mf->hash = NULL;
+
+ lzma_free(mf->son, allocator);
+ mf->son = NULL;
- // Initialize the hash table. Since EMPTY_HASH_VALUE is zero, we
- // can use memset().
+ return true;
+ }
+ } else {
/*
- for (uint32_t i = 0; i < hash_size_sum; ++i)
- mf->hash[i] = EMPTY_HASH_VALUE;
+ for (uint32_t i = 0; i < mf->hash_count; ++i)
+ mf->hash[i] = EMPTY_HASH_VALUE;
*/
- memzero(mf->hash, (size_t)(mf->hash_size_sum) * sizeof(uint32_t));
+ memzero(mf->hash, mf->hash_count * sizeof(uint32_t));
+ }
- // We don't need to initialize mf->son, but not doing that will
- // make Valgrind complain in normalization (see normalize() in
- // lz_encoder_mf.c).
- //
- // Skipping this initialization is *very* good when big dictionary is
- // used but only small amount of data gets actually compressed: most
- // of the mf->hash won't get actually allocated by the kernel, so
- // we avoid wasting RAM and improve initialization speed a lot.
- //memzero(mf->son, (size_t)(mf->sons_count) * sizeof(uint32_t));
+ mf->cyclic_pos = 0;
// Handle preset dictionary.
if (lz_options->preset_dict != NULL
lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
{
// Old buffers must not exist when calling lz_encoder_prepare().
- lzma_mf mf = { NULL };
+ lzma_mf mf = {
+ .buffer = NULL,
+ .hash = NULL,
+ .son = NULL,
+ .hash_count = 0,
+ .sons_count = 0,
+ };
// Setup the size information into mf.
if (lz_encoder_prepare(&mf, NULL, lz_options))
return UINT64_MAX;
// Calculate the memory usage.
- return (uint64_t)(mf.hash_size_sum + mf.sons_count)
- * sizeof(uint32_t)
- + (uint64_t)(mf.size) + sizeof(lzma_coder);
+ return ((uint64_t)(mf.hash_count) + mf.sons_count) * sizeof(uint32_t)
+ + mf.size + sizeof(lzma_coder);
}
static void
-lz_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lz_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_coder *coder = coder_ptr;
+
lzma_next_end(&coder->next, allocator);
+ lzma_free(coder->mf.son, allocator);
lzma_free(coder->mf.hash, allocator);
lzma_free(coder->mf.buffer, allocator);
static lzma_ret
-lz_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+lz_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters_null lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_coder *coder = coder_ptr;
+
if (coder->lz.options_update == NULL)
return LZMA_PROG_ERROR;
extern lzma_ret
-lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lz_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_encoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options))
{
- lzma_lz_options lz_options;
-
#ifdef HAVE_SMALL
// We need that the CRC32 table has been initialized.
lzma_crc32_init();
#endif
// Allocate and initialize the base data structure.
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
+ lzma_coder *coder = next->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &lz_encode;
next->end = &lz_encoder_end;
next->update = &lz_encoder_update;
- next->coder->lz.coder = NULL;
- next->coder->lz.code = NULL;
- next->coder->lz.end = NULL;
-
- next->coder->mf.buffer = NULL;
- next->coder->mf.hash = NULL;
- next->coder->mf.hash_size_sum = 0;
- next->coder->mf.sons_count = 0;
-
- next->coder->next = LZMA_NEXT_CODER_INIT;
+ coder->lz.coder = NULL;
+ coder->lz.code = NULL;
+ coder->lz.end = NULL;
+
+ // mf.size is initialized to silence Valgrind
+ // when used on optimized binaries (GCC may reorder
+ // code in a way that Valgrind gets unhappy).
+ coder->mf.buffer = NULL;
+ coder->mf.size = 0;
+ coder->mf.hash = NULL;
+ coder->mf.son = NULL;
+ coder->mf.hash_count = 0;
+ coder->mf.sons_count = 0;
+
+ coder->next = LZMA_NEXT_CODER_INIT;
}
// Initialize the LZ-based encoder.
- return_if_error(lz_init(&next->coder->lz, allocator,
+ lzma_lz_options lz_options;
+ return_if_error(lz_init(&coder->lz, allocator,
filters[0].options, &lz_options));
- // Setup the size information into next->coder->mf and deallocate
+ // Setup the size information into coder->mf and deallocate
// old buffers if they have wrong size.
- if (lz_encoder_prepare(&next->coder->mf, allocator, &lz_options))
+ if (lz_encoder_prepare(&coder->mf, allocator, &lz_options))
return LZMA_OPTIONS_ERROR;
// Allocate new buffers if needed, and do the rest of
// the initialization.
- if (lz_encoder_init(&next->coder->mf, allocator, &lz_options))
+ if (lz_encoder_init(&coder->mf, allocator, &lz_options))
return LZMA_MEM_ERROR;
// Initialize the next filter in the chain, if any.
- return lzma_next_filter_init(&next->coder->next, allocator,
- filters + 1);
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
lzma_action action;
/// Number of elements in hash[]
- uint32_t hash_size_sum;
+ uint32_t hash_count;
/// Number of elements in son[]
uint32_t sons_count;
typedef struct {
/// Data specific to the LZ-based encoder
- lzma_coder *coder;
+ void *coder;
/// Function to encode from *dict to out[]
- lzma_ret (*code)(lzma_coder *LZMA_RESTRICT coder,
- lzma_mf *LZMA_RESTRICT mf, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size);
+ lzma_ret (*code)(void *coder,
+ lzma_mf *restrict mf, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size);
/// Free allocated resources
- void (*end)(lzma_coder *coder, lzma_allocator *allocator);
+ void (*end)(void *coder, const lzma_allocator *allocator);
/// Update the options in the middle of the encoding.
- lzma_ret (*options_update)(lzma_coder *coder,
- const lzma_filter *filter);
+ lzma_ret (*options_update)(void *coder, const lzma_filter *filter);
} lzma_lz_encoder;
/// Get pointer to the first byte not ran through the match finder
-static inline uint8_t *
+static inline const uint8_t *
mf_ptr(const lzma_mf *mf)
{
return mf->buffer + mf->read_pos;
extern lzma_ret lzma_lz_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
lzma_ret (*lz_init)(lzma_lz_encoder *lz,
- lzma_allocator *allocator, const void *options,
+ const lzma_allocator *allocator, const void *options,
lzma_lz_options *lz_options));
// Endianness doesn't matter in hash_2_calc() (no effect on the output).
#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
# define hash_2_calc() \
- hash_value = *(const uint16_t *)(cur)
+ const uint32_t hash_value = *(const uint16_t *)(cur)
#else
# define hash_2_calc() \
- hash_value = (uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)
+ const uint32_t hash_value \
+ = (uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)
#endif
#define hash_3_calc() \
- temp = hash_table[cur[0]] ^ cur[1]; \
- hash_2_value = temp & HASH_2_MASK; \
- hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask
+ const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+ const uint32_t hash_2_value = temp & HASH_2_MASK; \
+ const uint32_t hash_value \
+ = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask
#define hash_4_calc() \
- temp = hash_table[cur[0]] ^ cur[1]; \
- hash_2_value = temp & HASH_2_MASK; \
- hash_3_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
- hash_value = (temp ^ ((uint32_t)(cur[2]) << 8) \
+ const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+ const uint32_t hash_2_value = temp & HASH_2_MASK; \
+ const uint32_t hash_3_value \
+ = (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+ const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8) \
^ (hash_table[cur[3]] << 5)) & mf->hash_mask
#include "lz_encoder.h"
#include "lz_encoder_hash.h"
+#include "memcmplen.h"
/// \brief Find matches starting from the current byte
if (count > 0) {
#ifndef NDEBUG
- uint32_t i;
// Validate the matches.
- for (i = 0; i < count; ++i) {
+ for (uint32_t i = 0; i < count; ++i) {
assert(matches[i].len <= mf->nice_len);
assert(matches[i].dist < mf->read_pos);
assert(memcmp(mf_ptr(mf) - 1,
// If a match of maximum search length was found, try to
// extend the match to maximum possible length.
if (len_best == mf->nice_len) {
- uint8_t *p1;
- uint8_t *p2;
-
// The limit for the match length is either the
// maximum match length supported by the LZ-based
// encoder or the number of bytes left in the
// Pointer to the byte we just ran through
// the match finder.
- p1 = mf_ptr(mf) - 1;
+ const uint8_t *p1 = mf_ptr(mf) - 1;
// Pointer to the beginning of the match. We need -1
// here because the match distances are zero based.
- p2 = p1 - matches[count - 1].dist - 1;
+ const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
- while (len_best < limit
- && p1[len_best] == p2[len_best])
- ++len_best;
+ len_best = lzma_memcmplen(p1, p2, len_best, limit);
}
}
static void
normalize(lzma_mf *mf)
{
- uint32_t i;
- uint32_t subvalue;
- uint32_t count;
- uint32_t *hash;
-
assert(mf->read_pos + mf->offset == MUST_NORMALIZE_POS);
// In future we may not want to touch the lowest bits, because there
// may be match finders that use larger resolution than one byte.
- subvalue = (MUST_NORMALIZE_POS - mf->cyclic_size);
+ const uint32_t subvalue
+ = (MUST_NORMALIZE_POS - mf->cyclic_size);
// & (~(UINT32_C(1) << 10) - 1);
- count = mf->hash_size_sum + mf->sons_count;
- hash = mf->hash;
-
- for (i = 0; i < count; ++i) {
+ for (uint32_t i = 0; i < mf->hash_count; ++i) {
// If the distance is greater than the dictionary size,
// we can simply mark the hash element as empty.
+ if (mf->hash[i] <= subvalue)
+ mf->hash[i] = EMPTY_HASH_VALUE;
+ else
+ mf->hash[i] -= subvalue;
+ }
+
+ for (uint32_t i = 0; i < mf->sons_count; ++i) {
+ // Do the same for mf->son.
//
- // NOTE: Only the first mf->hash_size_sum elements are
- // initialized for sure. There may be uninitialized elements
- // in mf->son. Since we go through both mf->hash and
- // mf->son here in normalization, Valgrind may complain
- // that the "if" below depends on uninitialized value. In
- // this case it is safe to ignore the warning. See also the
- // comments in lz_encoder_init() in lz_encoder.c.
- if (hash[i] <= subvalue)
- hash[i] = EMPTY_HASH_VALUE;
+ // NOTE: There may be uninitialized elements in mf->son.
+ // Valgrind may complain that the "if" below depends on
+ // an uninitialized value. In this case it is safe to ignore
+ // the warning. See also the comments in lz_encoder_init()
+ // in lz_encoder.c.
+ if (mf->son[i] <= subvalue)
+ mf->son[i] = EMPTY_HASH_VALUE;
else
- hash[i] -= subvalue;
+ mf->son[i] -= subvalue;
}
// Update offset to match the new locations.
move_pending(mf); \
ret_op; \
} \
- cur = mf_ptr(mf); \
- pos = mf->read_pos + mf->offset
+ const uint8_t *cur = mf_ptr(mf); \
+ const uint32_t pos = mf->read_pos + mf->offset
/// Header for find functions. "return 0" indicates that zero matches
/// were found.
#define header_find(is_bt, len_min) \
- header(is_bt, len_min, return 0)
+ header(is_bt, len_min, return 0); \
+ uint32_t matches_count = 0
/// Header for a loop in a skip function. "continue" tells to skip the rest
while (true) {
const uint32_t delta = pos - cur_match;
- const uint8_t *pb;
if (depth-- == 0 || delta >= cyclic_size)
return matches;
- pb = cur - delta;
+ const uint8_t *const pb = cur - delta;
cur_match = son[cyclic_pos - delta
+ (delta > cyclic_pos ? cyclic_size : 0)];
if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
- uint32_t len = 0;
- while (++len != len_limit)
- if (pb[len] != cur[len])
- break;
+ uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit);
if (len_best < len) {
len_best = len;
extern uint32_t
lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t delta2, cur_match;
- uint32_t len_best = 2;
- uint32_t matches_count = 0;
-
header_find(false, 3);
hash_3_calc();
- delta2 = pos - mf->hash[hash_2_value];
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 2;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(cur - delta2, cur,
+ len_best, len_limit);
matches[0].len = len_best;
matches[0].dist = delta2 - 1;
lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t cur_match;
-
if (mf_avail(mf) < 3) {
move_pending(mf);
continue;
}
- cur = mf_ptr(mf);
- pos = mf->read_pos + mf->offset;
+ const uint8_t *cur = mf_ptr(mf);
+ const uint32_t pos = mf->read_pos + mf->offset;
hash_3_calc();
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
extern uint32_t
lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t delta2, delta3, cur_match;
- uint32_t len_best = 1;
- uint32_t matches_count = 0;
-
header_find(false, 4);
hash_4_calc();
- delta2 = pos - mf->hash[hash_2_value];
- delta3 = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t delta3
+ = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+ const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value ] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 1;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
len_best = 2;
matches[0].len = 2;
}
if (matches_count != 0) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(cur - delta2, cur,
+ len_best, len_limit);
matches[matches_count - 1].len = len_best;
lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t cur_match;
-
if (mf_avail(mf) < 4) {
move_pending(mf);
continue;
}
- cur = mf_ptr(mf);
- pos = mf->read_pos + mf->offset;
+ const uint8_t *cur = mf_ptr(mf);
+ const uint32_t pos = mf->read_pos + mf->offset;
hash_4_calc();
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
uint32_t len1 = 0;
while (true) {
- uint32_t *pair;
- const uint8_t *pb;
- uint32_t len;
-
const uint32_t delta = pos - cur_match;
if (depth-- == 0 || delta >= cyclic_size) {
*ptr0 = EMPTY_HASH_VALUE;
return matches;
}
- pair = son + ((cyclic_pos - delta
+ uint32_t *const pair = son + ((cyclic_pos - delta
+ (delta > cyclic_pos ? cyclic_size : 0))
<< 1);
- pb = cur - delta;
- len = my_min(len0, len1);
+ const uint8_t *const pb = cur - delta;
+ uint32_t len = my_min(len0, len1);
if (pb[len] == cur[len]) {
- while (++len != len_limit)
- if (pb[len] != cur[len])
- break;
+ len = lzma_memcmplen(pb, cur, len + 1, len_limit);
if (len_best < len) {
len_best = len;
uint32_t len1 = 0;
while (true) {
- uint32_t *pair;
- const uint8_t *pb;
- uint32_t len;
-
const uint32_t delta = pos - cur_match;
if (depth-- == 0 || delta >= cyclic_size) {
*ptr0 = EMPTY_HASH_VALUE;
return;
}
- pair = son + ((cyclic_pos - delta
+ uint32_t *pair = son + ((cyclic_pos - delta
+ (delta > cyclic_pos ? cyclic_size : 0))
<< 1);
- pb = cur - delta;
- len = my_min(len0, len1);
+ const uint8_t *pb = cur - delta;
+ uint32_t len = my_min(len0, len1);
if (pb[len] == cur[len]) {
- while (++len != len_limit)
- if (pb[len] != cur[len])
- break;
+ len = lzma_memcmplen(pb, cur, len + 1, len_limit);
if (len == len_limit) {
*ptr1 = pair[0];
extern uint32_t
lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t hash_value; /* hash_2_calc */
- uint32_t cur_match;
- uint32_t matches_count = 0;
-
header_find(true, 2);
hash_2_calc();
- cur_match = mf->hash[hash_value];
+ const uint32_t cur_match = mf->hash[hash_value];
mf->hash[hash_value] = pos;
bt_find(1);
lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t hash_value; /* hash_2_calc */
- uint32_t cur_match;
-
header_skip(true, 2);
hash_2_calc();
- cur_match = mf->hash[hash_value];
+ const uint32_t cur_match = mf->hash[hash_value];
mf->hash[hash_value] = pos;
bt_skip();
extern uint32_t
lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t delta2, cur_match;
- uint32_t len_best = 2;
- uint32_t matches_count = 0;
-
header_find(true, 3);
hash_3_calc();
- delta2 = pos - mf->hash[hash_2_value];
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 2;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(
+ cur, cur - delta2, len_best, len_limit);
matches[0].len = len_best;
matches[0].dist = delta2 - 1;
lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value; /* hash_3_calc */
- uint32_t cur_match;
-
header_skip(true, 3);
hash_3_calc();
- cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_3_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
extern uint32_t
lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
{
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t delta2, delta3, cur_match;
- uint32_t len_best = 1;
- uint32_t matches_count = 0;
-
header_find(true, 4);
hash_4_calc();
- delta2 = pos - mf->hash[hash_2_value];
- delta3 = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ uint32_t delta2 = pos - mf->hash[hash_2_value];
+ const uint32_t delta3
+ = pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+ const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+ uint32_t len_best = 1;
+
if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
len_best = 2;
matches[0].len = 2;
}
if (matches_count != 0) {
- for ( ; len_best != len_limit; ++len_best)
- if (*(cur + len_best - delta2) != cur[len_best])
- break;
+ len_best = lzma_memcmplen(
+ cur, cur - delta2, len_best, len_limit);
matches[matches_count - 1].len = len_best;
lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount)
{
do {
- const uint8_t *cur;
- uint32_t pos;
- uint32_t temp, hash_value, hash_2_value, hash_3_value; /* hash_4_calc */
- uint32_t cur_match;
-
header_skip(true, 4);
hash_4_calc();
- cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+ const uint32_t cur_match
+ = mf->hash[FIX_4_HASH_SIZE + hash_value];
mf->hash[hash_2_value] = pos;
mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
#ifndef LZMA_FASTPOS_H
#define LZMA_FASTPOS_H
-// LZMA encodes match distances (positions) by storing the highest two
-// bits using a six-bit value [0, 63], and then the missing lower bits.
-// Dictionary size is also stored using this encoding in the new .lzma
+// LZMA encodes match distances by storing the highest two bits using
+// a six-bit value [0, 63], and then the missing lower bits.
+// Dictionary size is also stored using this encoding in the .xz
// file format header.
//
// fastpos.h provides a way to quickly find out the correct six-bit
// values. The following table gives some examples of this encoding:
//
-// pos return
+// dist return
// 0 0
// 1 1
// 2 2
// Provided functions or macros
// ----------------------------
//
-// get_pos_slot(pos) is the basic version. get_pos_slot_2(pos)
-// assumes that pos >= FULL_DISTANCES, thus the result is at least
-// FULL_DISTANCES_BITS * 2. Using get_pos_slot(pos) instead of
-// get_pos_slot_2(pos) would give the same result, but get_pos_slot_2(pos)
+// get_dist_slot(dist) is the basic version. get_dist_slot_2(dist)
+// assumes that dist >= FULL_DISTANCES, thus the result is at least
+// FULL_DISTANCES_BITS * 2. Using get_dist_slot(dist) instead of
+// get_dist_slot_2(dist) would give the same result, but get_dist_slot_2(dist)
// should be tiny bit faster due to the assumption being made.
//
//
// on all systems I have tried. The size optimized version is sometimes
// slightly faster, but sometimes it is a lot slower.
-#include "config.h"
-
#ifdef HAVE_SMALL
-# define get_pos_slot(pos) ((pos) <= 4 ? (pos) : get_pos_slot_2(pos))
+# define get_dist_slot(dist) \
+ ((dist) <= 4 ? (dist) : get_dist_slot_2(dist))
static inline uint32_t
-get_pos_slot_2(uint32_t pos)
+get_dist_slot_2(uint32_t dist)
{
- const uint32_t i = bsr32(pos);
- return (i + i) + ((pos >> (i - 1)) & 1);
+ const uint32_t i = bsr32(dist);
+ return (i + i) + ((dist >> (i - 1)) & 1);
}
#define fastpos_limit(extra, n) \
(UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n)))
-#define fastpos_result(pos, extra, n) \
- lzma_fastpos[(pos) >> fastpos_shift(extra, n)] \
+#define fastpos_result(dist, extra, n) \
+ lzma_fastpos[(dist) >> fastpos_shift(extra, n)] \
+ 2 * fastpos_shift(extra, n)
static inline uint32_t
-get_pos_slot(uint32_t pos)
+get_dist_slot(uint32_t dist)
{
// If it is small enough, we can pick the result directly from
// the precalculated table.
- if (pos < fastpos_limit(0, 0))
- return lzma_fastpos[pos];
+ if (dist < fastpos_limit(0, 0))
+ return lzma_fastpos[dist];
- if (pos < fastpos_limit(0, 1))
- return fastpos_result(pos, 0, 1);
+ if (dist < fastpos_limit(0, 1))
+ return fastpos_result(dist, 0, 1);
- return fastpos_result(pos, 0, 2);
+ return fastpos_result(dist, 0, 2);
}
#ifdef FULL_DISTANCES_BITS
static inline uint32_t
-get_pos_slot_2(uint32_t pos)
+get_dist_slot_2(uint32_t dist)
{
- assert(pos >= FULL_DISTANCES);
+ assert(dist >= FULL_DISTANCES);
- if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
- return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 0);
+ if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
+ return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 0);
- if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
- return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 1);
+ if (dist < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
+ return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 1);
- return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 2);
+ return fastpos_result(dist, FULL_DISTANCES_BITS - 1, 2);
}
#endif
#include "lzma_decoder.h"
-struct lzma_coder_s {
+typedef struct {
enum sequence {
SEQ_CONTROL,
SEQ_UNCOMPRESSED_1,
bool need_dictionary_reset;
lzma_options_lzma options;
-};
+} lzma_lzma2_coder;
static lzma_ret
-lzma2_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dict,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
+lzma2_decode(void *coder_ptr, lzma_dict *restrict dict,
+ const uint8_t *restrict in, size_t *restrict in_pos,
size_t in_size)
{
+ lzma_lzma2_coder *restrict coder = coder_ptr;
+
// With SEQ_LZMA it is possible that no new input is needed to do
// some progress. The rest of the sequences assume that there is
// at least one byte of input.
static void
-lzma2_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lzma2_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_lzma2_coder *coder = coder_ptr;
+
assert(coder->lzma.end == NULL);
lzma_free(coder->lzma.coder, allocator);
static lzma_ret
-lzma2_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
+lzma2_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *opt, lzma_lz_options *lz_options)
{
- const lzma_options_lzma *options = opt;
-
- if (lz->coder == NULL) {
- lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (lz->coder == NULL)
+ lzma_lzma2_coder *coder = lz->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ lz->coder = coder;
lz->code = &lzma2_decode;
lz->end = &lzma2_decoder_end;
- lz->coder->lzma = LZMA_LZ_DECODER_INIT;
+ coder->lzma = LZMA_LZ_DECODER_INIT;
}
- lz->coder->sequence = SEQ_CONTROL;
- lz->coder->need_properties = true;
- lz->coder->need_dictionary_reset = options->preset_dict == NULL
+ const lzma_options_lzma *options = opt;
+
+ coder->sequence = SEQ_CONTROL;
+ coder->need_properties = true;
+ coder->need_dictionary_reset = options->preset_dict == NULL
|| options->preset_dict_size == 0;
- return lzma_lzma_decoder_create(&lz->coder->lzma,
+ return lzma_lzma_decoder_create(&coder->lzma,
allocator, options, lz_options);
}
extern lzma_ret
-lzma_lzma2_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma2_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
// LZMA2 can only be the last filter in the chain. This is enforced
extern uint64_t
lzma_lzma2_decoder_memusage(const void *options)
{
- return sizeof(lzma_coder)
+ return sizeof(lzma_lzma2_coder)
+ lzma_lzma_decoder_memusage_nocheck(options);
}
extern lzma_ret
-lzma_lzma2_props_decode(void **options, lzma_allocator *allocator,
+lzma_lzma2_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_lzma *opt;
-
if (props_size != 1)
return LZMA_OPTIONS_ERROR;
if (props[0] > 40)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_lzma), allocator);
+ lzma_options_lzma *opt = lzma_alloc(
+ sizeof(lzma_options_lzma), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
#include "common.h"
extern lzma_ret lzma_lzma2_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern uint64_t lzma_lzma2_decoder_memusage(const void *options);
extern lzma_ret lzma_lzma2_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
#endif
#include "lzma2_encoder.h"
-struct lzma_coder_s {
+typedef struct {
enum {
SEQ_INIT,
SEQ_LZMA_ENCODE,
} sequence;
/// LZMA encoder
- lzma_coder *lzma;
+ void *lzma;
/// LZMA options currently in use.
lzma_options_lzma opt_cur;
/// Buffer to hold the chunk header and LZMA compressed data
uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX];
-};
+} lzma_lzma2_coder;
static void
-lzma2_header_lzma(lzma_coder *coder)
+lzma2_header_lzma(lzma_lzma2_coder *coder)
{
- size_t pos;
- size_t size;
-
assert(coder->uncompressed_size > 0);
assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX);
assert(coder->compressed_size > 0);
assert(coder->compressed_size <= LZMA2_CHUNK_MAX);
+ size_t pos;
+
if (coder->need_properties) {
pos = 0;
coder->buf_pos = pos;
// Uncompressed size
- size = coder->uncompressed_size - 1;
+ size_t size = coder->uncompressed_size - 1;
coder->buf[pos++] += size >> 16;
coder->buf[pos++] = (size >> 8) & 0xFF;
coder->buf[pos++] = size & 0xFF;
static void
-lzma2_header_uncompressed(lzma_coder *coder)
+lzma2_header_uncompressed(lzma_lzma2_coder *coder)
{
assert(coder->uncompressed_size > 0);
assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX);
static lzma_ret
-lzma2_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+lzma2_encode(void *coder_ptr, lzma_mf *restrict mf,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size)
{
+ lzma_lzma2_coder *restrict coder = coder_ptr;
+
while (*out_pos < out_size)
switch (coder->sequence) {
case SEQ_INIT:
// Fall through
case SEQ_LZMA_ENCODE: {
- uint32_t read_start;
- lzma_ret ret;
-
// Calculate how much more uncompressed data this chunk
// could accept.
const uint32_t left = LZMA2_UNCOMPRESSED_MAX
// Save the start position so that we can update
// coder->uncompressed_size.
- read_start = mf->read_pos - mf->read_ahead;
+ const uint32_t read_start = mf->read_pos - mf->read_ahead;
// Call the LZMA encoder until the chunk is finished.
- ret = lzma_lzma_encode(coder->lzma, mf,
+ const lzma_ret ret = lzma_lzma_encode(coder->lzma, mf,
coder->buf + LZMA2_HEADER_MAX,
&coder->compressed_size,
LZMA2_CHUNK_MAX, limit);
static void
-lzma2_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+lzma2_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_lzma2_coder *coder = coder_ptr;
lzma_free(coder->lzma, allocator);
lzma_free(coder, allocator);
return;
static lzma_ret
-lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
+lzma2_encoder_options_update(void *coder_ptr, const lzma_filter *filter)
{
- lzma_options_lzma *opt;
+ lzma_lzma2_coder *coder = coder_ptr;
// New options can be set only when there is no incomplete chunk.
// This is the case at the beginning of the raw stream and right
// Look if there are new options. At least for now,
// only lc/lp/pb can be changed.
- opt = filter->options;
+ const lzma_options_lzma *opt = filter->options;
if (coder->opt_cur.lc != opt->lc || coder->opt_cur.lp != opt->lp
|| coder->opt_cur.pb != opt->pb) {
// Validate the options.
static lzma_ret
-lzma2_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
+lzma2_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator,
const void *options, lzma_lz_options *lz_options)
{
if (options == NULL)
return LZMA_PROG_ERROR;
- if (lz->coder == NULL) {
- lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (lz->coder == NULL)
+ lzma_lzma2_coder *coder = lz->coder;
+ if (coder == NULL) {
+ coder = lzma_alloc(sizeof(lzma_lzma2_coder), allocator);
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ lz->coder = coder;
lz->code = &lzma2_encode;
lz->end = &lzma2_encoder_end;
lz->options_update = &lzma2_encoder_options_update;
- lz->coder->lzma = NULL;
+ coder->lzma = NULL;
}
- lz->coder->opt_cur = *(const lzma_options_lzma *)(options);
+ coder->opt_cur = *(const lzma_options_lzma *)(options);
- lz->coder->sequence = SEQ_INIT;
- lz->coder->need_properties = true;
- lz->coder->need_state_reset = false;
- lz->coder->need_dictionary_reset
- = lz->coder->opt_cur.preset_dict == NULL
- || lz->coder->opt_cur.preset_dict_size == 0;
+ coder->sequence = SEQ_INIT;
+ coder->need_properties = true;
+ coder->need_state_reset = false;
+ coder->need_dictionary_reset
+ = coder->opt_cur.preset_dict == NULL
+ || coder->opt_cur.preset_dict_size == 0;
// Initialize LZMA encoder
- return_if_error(lzma_lzma_encoder_create(&lz->coder->lzma, allocator,
- &lz->coder->opt_cur, lz_options));
+ return_if_error(lzma_lzma_encoder_create(&coder->lzma, allocator,
+ &coder->opt_cur, lz_options));
// Make sure that we will always have enough history available in
// case we need to use uncompressed chunks. They are used when the
extern lzma_ret
-lzma_lzma2_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma2_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return lzma_lz_encoder_init(
if (lzma_mem == UINT64_MAX)
return UINT64_MAX;
- return sizeof(lzma_coder) + lzma_mem;
+ return sizeof(lzma_lzma2_coder) + lzma_mem;
}
if (d == UINT32_MAX)
out[0] = 40;
else
- out[0] = get_pos_slot(d + 1) - 24;
+ out[0] = get_dist_slot(d + 1) - 24;
return LZMA_OK;
}
+
+
+extern uint64_t
+lzma_lzma2_block_size(const void *options)
+{
+ const lzma_options_lzma *const opt = options;
+
+ // Use at least 1 MiB to keep compression ratio better.
+ return my_max((uint64_t)(opt->dict_size) * 3, UINT64_C(1) << 20);
+}
extern lzma_ret lzma_lzma2_encoder_init(
- lzma_next_coder *next, lzma_allocator *allocator,
+ lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters);
extern uint64_t lzma_lzma2_encoder_memusage(const void *options);
extern lzma_ret lzma_lzma2_props_encode(const void *options, uint8_t *out);
+extern uint64_t lzma_lzma2_block_size(const void *options);
+
#endif
literal_init(probability (*probs)[LITERAL_CODER_SIZE],
uint32_t lc, uint32_t lp)
{
- uint32_t coders;
- uint32_t i, j;
-
assert(lc + lp <= LZMA_LCLP_MAX);
- coders = 1U << (lc + lp);
+ const uint32_t coders = 1U << (lc + lp);
- for (i = 0; i < coders; ++i)
- for (j = 0; j < LITERAL_CODER_SIZE; ++j)
+ for (uint32_t i = 0; i < coders; ++i)
+ for (uint32_t j = 0; j < LITERAL_CODER_SIZE; ++j)
bit_reset(probs[i][j]);
return;
// Match distance //
////////////////////
-// Different set of probabilities is used for match distances that have very
+// Different sets of probabilities are used for match distances that have very
// short match length: Lengths of 2, 3, and 4 bytes have a separate set of
// probabilities for each length. The matches with longer length use a shared
// set of probabilities.
-#define LEN_TO_POS_STATES 4
+#define DIST_STATES 4
// Macro to get the index of the appropriate probability array.
-#define get_len_to_pos_state(len) \
- ((len) < LEN_TO_POS_STATES + MATCH_LEN_MIN \
+#define get_dist_state(len) \
+ ((len) < DIST_STATES + MATCH_LEN_MIN \
? (len) - MATCH_LEN_MIN \
- : LEN_TO_POS_STATES - 1)
+ : DIST_STATES - 1)
-// The highest two bits of a match distance (pos slot) are encoded using six
-// bits. See fastpos.h for more explanation.
-#define POS_SLOT_BITS 6
-#define POS_SLOTS (1 << POS_SLOT_BITS)
+// The highest two bits of a match distance (distance slot) are encoded
+// using six bits. See fastpos.h for more explanation.
+#define DIST_SLOT_BITS 6
+#define DIST_SLOTS (1 << DIST_SLOT_BITS)
// Match distances up to 127 are fully encoded using probabilities. Since
-// the highest two bits (pos slot) are always encoded using six bits, the
-// distances 0-3 don't need any additional bits to encode, since the pos
-// slot itself is the same as the actual distance. START_POS_MODEL_INDEX
-// indicates the first pos slot where at least one additional bit is needed.
-#define START_POS_MODEL_INDEX 4
+// the highest two bits (distance slot) are always encoded using six bits,
+// the distances 0-3 don't need any additional bits to encode, since the
+// distance slot itself is the same as the actual distance. DIST_MODEL_START
+// indicates the first distance slot where at least one additional bit is
+// needed.
+#define DIST_MODEL_START 4
// Match distances greater than 127 are encoded in three pieces:
-// - pos slot: the highest two bits
+// - distance slot: the highest two bits
// - direct bits: 2-26 bits below the highest two bits
// - alignment bits: four lowest bits
//
// Direct bits don't use any probabilities.
//
-// The pos slot value of 14 is for distances 128-191 (see the table in
+// The distance slot value of 14 is for distances 128-191 (see the table in
// fastpos.h to understand why).
-#define END_POS_MODEL_INDEX 14
+#define DIST_MODEL_END 14
-// Pos slots that indicate a distance <= 127.
-#define FULL_DISTANCES_BITS (END_POS_MODEL_INDEX / 2)
+// Distance slots that indicate a distance <= 127.
+#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
// For match distances greater than 127, only the highest two bits and the
// lowest four bits (alignment) is encoded using probabilities.
#define ALIGN_BITS 4
-#define ALIGN_TABLE_SIZE (1 << ALIGN_BITS)
-#define ALIGN_MASK (ALIGN_TABLE_SIZE - 1)
+#define ALIGN_SIZE (1 << ALIGN_BITS)
+#define ALIGN_MASK (ALIGN_SIZE - 1)
// LZMA remembers the four most recent match distances. Reusing these distances
// tends to take less space than re-encoding the actual distance value.
-#define REP_DISTANCES 4
+#define REPS 4
#endif
#include "lzma_decoder.h"
#include "range_decoder.h"
+// The macros unroll loops with switch statements.
+// Silence warnings about missing fall-through comments.
+#if TUKLIB_GNUC_REQ(7, 0)
+# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#endif
+
#ifdef HAVE_SMALL
case seq ## _CHOICE: \
rc_if_0(ld.choice, seq ## _CHOICE) { \
rc_update_0(ld.choice); \
- rc_bit_case(ld.low[pos_state][symbol], 0, 0, seq ## _LOW0); \
- rc_bit_case(ld.low[pos_state][symbol], 0, 0, seq ## _LOW1); \
- rc_bit_case(ld.low[pos_state][symbol], 0, 0, seq ## _LOW2); \
+ rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW0); \
+ rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW1); \
+ rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW2); \
target = symbol - LEN_LOW_SYMBOLS + MATCH_LEN_MIN; \
} else { \
rc_update_1(ld.choice); \
case seq ## _CHOICE2: \
rc_if_0(ld.choice2, seq ## _CHOICE2) { \
rc_update_0(ld.choice2); \
- rc_bit_case(ld.mid[pos_state][symbol], 0, 0, \
+ rc_bit_case(ld.mid[pos_state][symbol], , , \
seq ## _MID0); \
- rc_bit_case(ld.mid[pos_state][symbol], 0, 0, \
+ rc_bit_case(ld.mid[pos_state][symbol], , , \
seq ## _MID1); \
- rc_bit_case(ld.mid[pos_state][symbol], 0, 0, \
+ rc_bit_case(ld.mid[pos_state][symbol], , , \
seq ## _MID2); \
target = symbol - LEN_MID_SYMBOLS \
+ MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \
} else { \
rc_update_1(ld.choice2); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH0); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH1); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH2); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH3); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH4); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH5); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH6); \
- rc_bit_case(ld.high[symbol], 0, 0, seq ## _HIGH7); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH0); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH1); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH2); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH3); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH4); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH5); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH6); \
+ rc_bit_case(ld.high[symbol], , , seq ## _HIGH7); \
target = symbol - LEN_HIGH_SYMBOLS \
+ MATCH_LEN_MIN \
+ LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; \
} lzma_length_decoder;
-struct lzma_coder_s {
+typedef struct {
///////////////////
// Probabilities //
///////////////////
/// Probability tree for the highest two bits of the match distance.
/// There is a separate probability tree for match lengths of
/// 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
- probability pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
+ probability dist_slot[DIST_STATES][DIST_SLOTS];
/// Probability trees for additional bits for match distance when the
/// distance is in the range [4, 127].
- probability pos_special[FULL_DISTANCES - END_POS_MODEL_INDEX];
+ probability pos_special[FULL_DISTANCES - DIST_MODEL_END];
/// Probability tree for the lowest four bits of a match distance
/// that is equal to or greater than 128.
- probability pos_align[ALIGN_TABLE_SIZE];
+ probability pos_align[ALIGN_SIZE];
/// Length of a normal match
lzma_length_decoder match_len_decoder;
SEQ_LITERAL_WRITE,
SEQ_IS_REP,
seq_len(SEQ_MATCH_LEN),
- seq_6(SEQ_POS_SLOT),
- SEQ_POS_MODEL,
+ seq_6(SEQ_DIST_SLOT),
+ SEQ_DIST_MODEL,
SEQ_DIRECT,
seq_4(SEQ_ALIGN),
SEQ_EOPM,
/// If decoding a literal: match byte.
/// If decoding a match: length of the match.
uint32_t len;
-};
+} lzma_lzma1_decoder;
static lzma_ret
-lzma_decode(lzma_coder *LZMA_RESTRICT coder, lzma_dict *LZMA_RESTRICT dictptr,
- const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size)
+lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
+ const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size)
{
+ lzma_lzma1_decoder *restrict coder = coder_ptr;
+
+ ////////////////////
+ // Initialization //
+ ////////////////////
+
+ {
+ const lzma_ret ret = rc_read_init(
+ &coder->rc, in, in_pos, in_size);
+ if (ret != LZMA_STREAM_END)
+ return ret;
+ }
+
///////////////
// Variables //
///////////////
if (no_eopm && coder->uncompressed_size < dict.limit - dict.pos)
dict.limit = dict.pos + (size_t)(coder->uncompressed_size);
- ////////////////////
- // Initialization //
- ////////////////////
-
- if (!rc_read_init(&coder->rc, in, in_pos, in_size))
- return LZMA_OK;
-
- rc = coder->rc;
- rc_in_pos = *in_pos;
-
// The main decoder loop. The "switch" is used to restart the decoder at
// correct location. Once restarted, the "switch" is no longer used.
switch (coder->sequence)
break;
rc_if_0(coder->is_match[state][pos_state], SEQ_IS_MATCH) {
- static const lzma_lzma_state next_state[] = {
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_LIT_LIT,
- STATE_MATCH_LIT_LIT,
- STATE_REP_LIT_LIT,
- STATE_SHORTREP_LIT_LIT,
- STATE_MATCH_LIT,
- STATE_REP_LIT,
- STATE_SHORTREP_LIT,
- STATE_MATCH_LIT,
- STATE_REP_LIT
- };
-
rc_update_0(coder->is_match[state][pos_state]);
// It's a literal i.e. a single 8-bit byte.
rc_bit(probs[symbol], , , SEQ_LITERAL);
} while (symbol < (1 << 8));
#else
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL0);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL1);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL2);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL3);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL4);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL5);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL6);
- rc_bit_case(probs[symbol], 0, 0, SEQ_LITERAL7);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL0);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL1);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL2);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL3);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL4);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL5);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL6);
+ rc_bit_case(probs[symbol], , , SEQ_LITERAL7);
#endif
} else {
-#ifndef HAVE_SMALL
- uint32_t match_bit;
- uint32_t subcoder_index;
-#endif
-
// Decode literal with match byte.
//
// We store the byte we compare against
} while (symbol < (1 << 8));
#else
// Unroll the loop.
+ uint32_t match_bit;
+ uint32_t subcoder_index;
# define d(seq) \
case seq: \
// Use a lookup table to update to literal state,
// since compared to other state updates, this would
// need two branches.
+ static const lzma_lzma_state next_state[] = {
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_LIT_LIT,
+ STATE_MATCH_LIT_LIT,
+ STATE_REP_LIT_LIT,
+ STATE_SHORTREP_LIT_LIT,
+ STATE_MATCH_LIT,
+ STATE_REP_LIT,
+ STATE_SHORTREP_LIT,
+ STATE_MATCH_LIT,
+ STATE_REP_LIT
+ };
state = next_state[state];
case SEQ_LITERAL_WRITE:
// Prepare to decode the highest two bits of the
// match distance.
- probs = coder->pos_slot[get_len_to_pos_state(len)];
+ probs = coder->dist_slot[get_dist_state(len)];
symbol = 1;
#ifdef HAVE_SMALL
- case SEQ_POS_SLOT:
+ case SEQ_DIST_SLOT:
do {
- rc_bit(probs[symbol], , , SEQ_POS_SLOT);
- } while (symbol < POS_SLOTS);
+ rc_bit(probs[symbol], , , SEQ_DIST_SLOT);
+ } while (symbol < DIST_SLOTS);
#else
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT0);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT1);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT2);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT3);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT4);
- rc_bit_case(probs[symbol], 0, 0, SEQ_POS_SLOT5);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT0);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT1);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT2);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT3);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT4);
+ rc_bit_case(probs[symbol], , , SEQ_DIST_SLOT5);
#endif
// Get rid of the highest bit that was needed for
// indexing of the probability array.
- symbol -= POS_SLOTS;
+ symbol -= DIST_SLOTS;
assert(symbol <= 63);
- if (symbol < START_POS_MODEL_INDEX) {
+ if (symbol < DIST_MODEL_START) {
// Match distances [0, 3] have only two bits.
rep0 = symbol;
} else {
assert(limit >= 1 && limit <= 30);
rep0 = 2 + (symbol & 1);
- if (symbol < END_POS_MODEL_INDEX) {
+ if (symbol < DIST_MODEL_END) {
// Prepare to decode the low bits for
// a distance of [4, 127].
assert(limit <= 5);
- symbol - 1;
symbol = 1;
offset = 0;
- case SEQ_POS_MODEL:
+ case SEQ_DIST_MODEL:
#ifdef HAVE_SMALL
do {
rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
} while (++offset < limit);
#else
switch (limit) {
case 5:
assert(offset == 0);
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 4:
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 3:
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 2:
- rc_bit(probs[symbol], 0,
+ rc_bit(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
++offset;
--limit;
case 1:
// rc_bit_last() here to omit
// the unneeded updating of
// "symbol".
- rc_bit_last(probs[symbol], 0,
+ rc_bit_last(probs[symbol], ,
rep0 += 1 << offset,
- SEQ_POS_MODEL);
+ SEQ_DIST_MODEL);
}
#endif
} else {
} while (++offset < ALIGN_BITS);
#else
case SEQ_ALIGN0:
- rc_bit(coder->pos_align[symbol], 0,
+ rc_bit(coder->pos_align[symbol], ,
rep0 += 1, SEQ_ALIGN0);
case SEQ_ALIGN1:
- rc_bit(coder->pos_align[symbol], 0,
+ rc_bit(coder->pos_align[symbol], ,
rep0 += 2, SEQ_ALIGN1);
case SEQ_ALIGN2:
- rc_bit(coder->pos_align[symbol], 0,
+ rc_bit(coder->pos_align[symbol], ,
rep0 += 4, SEQ_ALIGN2);
case SEQ_ALIGN3:
- // Like in SEQ_POS_MODEL, we don't
+ // Like in SEQ_DIST_MODEL, we don't
// need "symbol" for anything else
// than indexing the probability array.
- rc_bit_last(coder->pos_align[symbol], 0,
+ rc_bit_last(coder->pos_align[symbol], ,
rep0 += 8, SEQ_ALIGN3);
#endif
// is stored to rep0 and rep1, rep2 and rep3
// are updated accordingly.
rc_if_0(coder->is_rep1[state], SEQ_IS_REP1) {
- uint32_t distance;
-
rc_update_0(coder->is_rep1[state]);
- distance = rep1;
+ const uint32_t distance = rep1;
rep1 = rep0;
rep0 = distance;
case SEQ_IS_REP2:
rc_if_0(coder->is_rep2[state],
SEQ_IS_REP2) {
- uint32_t distance;
-
rc_update_0(coder->is_rep2[
state]);
- distance = rep2;
+ const uint32_t distance = rep2;
rep2 = rep1;
rep1 = rep0;
rep0 = distance;
} else {
- uint32_t distance;
-
rc_update_1(coder->is_rep2[
state]);
- distance = rep3;
+ const uint32_t distance = rep3;
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
static void
-lzma_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
{
+ lzma_lzma1_decoder *coder = coder_ptr;
coder->uncompressed_size = uncompressed_size;
}
-/*
-extern void
-lzma_lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
-{
- // This is hack.
- (*(lzma_coder **)(coder))->uncompressed_size = uncompressed_size;
-}
-*/
static void
-lzma_decoder_reset(lzma_coder *coder, const void *opt)
+lzma_decoder_reset(void *coder_ptr, const void *opt)
{
- uint32_t i, j, pos_state;
- uint32_t num_pos_states;
-
+ lzma_lzma1_decoder *coder = coder_ptr;
const lzma_options_lzma *options = opt;
// NOTE: We assume that lc/lp/pb are valid since they were
rc_reset(coder->rc);
// Bit and bittree decoders
- for (i = 0; i < STATES; ++i) {
- for (j = 0; j <= coder->pos_mask; ++j) {
+ for (uint32_t i = 0; i < STATES; ++i) {
+ for (uint32_t j = 0; j <= coder->pos_mask; ++j) {
bit_reset(coder->is_match[i][j]);
bit_reset(coder->is_rep0_long[i][j]);
}
bit_reset(coder->is_rep2[i]);
}
- for (i = 0; i < LEN_TO_POS_STATES; ++i)
- bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
+ for (uint32_t i = 0; i < DIST_STATES; ++i)
+ bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);
- for (i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
+ for (uint32_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i)
bit_reset(coder->pos_special[i]);
bittree_reset(coder->pos_align, ALIGN_BITS);
// Len decoders (also bit/bittree)
- num_pos_states = 1U << options->pb;
+ const uint32_t num_pos_states = 1U << options->pb;
bit_reset(coder->match_len_decoder.choice);
bit_reset(coder->match_len_decoder.choice2);
bit_reset(coder->rep_len_decoder.choice);
bit_reset(coder->rep_len_decoder.choice2);
- for (pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+ for (uint32_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
bittree_reset(coder->match_len_decoder.low[pos_state],
LEN_LOW_BITS);
bittree_reset(coder->match_len_decoder.mid[pos_state],
extern lzma_ret
-lzma_lzma_decoder_create(lzma_lz_decoder *lz, lzma_allocator *allocator,
+lzma_lzma_decoder_create(lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *opt, lzma_lz_options *lz_options)
{
- const lzma_options_lzma *options = opt;
-
if (lz->coder == NULL) {
- lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+ lz->coder = lzma_alloc(sizeof(lzma_lzma1_decoder), allocator);
if (lz->coder == NULL)
return LZMA_MEM_ERROR;
// All dictionary sizes are OK here. LZ decoder will take care of
// the special cases.
+ const lzma_options_lzma *options = opt;
lz_options->dict_size = options->dict_size;
lz_options->preset_dict = options->preset_dict;
lz_options->preset_dict_size = options->preset_dict_size;
/// initialization (lzma_lzma_decoder_init() passes function pointer to
/// the LZ initialization).
static lzma_ret
-lzma_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
+lzma_decoder_init(lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *options, lzma_lz_options *lz_options)
{
if (!is_lclppb_valid(options))
extern lzma_ret
-lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
// LZMA can only be the last filter in the chain. This is enforced
lzma_lzma_decoder_memusage_nocheck(const void *options)
{
const lzma_options_lzma *const opt = options;
- return sizeof(lzma_coder) + lzma_lz_decoder_memusage(opt->dict_size);
+ return sizeof(lzma_lzma1_decoder)
+ + lzma_lz_decoder_memusage(opt->dict_size);
}
extern lzma_ret
-lzma_lzma_props_decode(void **options, lzma_allocator *allocator,
+lzma_lzma_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_lzma *opt;
-
if (props_size != 5)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_lzma), allocator);
+ lzma_options_lzma *opt
+ = lzma_alloc(sizeof(lzma_options_lzma), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
/// Allocates and initializes LZMA decoder
extern lzma_ret lzma_lzma_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern uint64_t lzma_lzma_decoder_memusage(const void *options);
extern lzma_ret lzma_lzma_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
/// Allocate and setup function pointers only. This is used by LZMA1 and
/// LZMA2 decoders.
extern lzma_ret lzma_lzma_decoder_create(
- lzma_lz_decoder *lz, lzma_allocator *allocator,
+ lzma_lz_decoder *lz, const lzma_allocator *allocator,
const void *opt, lzma_lz_options *lz_options);
/// Gets memory usage without validating lc/lp/pb. This is used by LZMA2
symbol += UINT32_C(1) << 8;
do {
- uint32_t match_bit;
- uint32_t subcoder_index;
- uint32_t bit;
-
match_byte <<= 1;
- match_bit = match_byte & offset;
- subcoder_index = offset + match_bit + (symbol >> 8);
- bit = (symbol >> 7) & 1;
+ const uint32_t match_bit = match_byte & offset;
+ const uint32_t subcoder_index
+ = offset + match_bit + (symbol >> 8);
+ const uint32_t bit = (symbol >> 7) & 1;
rc_bit(rc, &subcoder[subcoder_index], bit);
symbol <<= 1;
static inline void
-literal(lzma_coder *coder, lzma_mf *mf, uint32_t position)
+literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position)
{
// Locate the literal byte to be encoded and the subcoder.
const uint8_t cur_byte = mf->buffer[
static void
length_update_prices(lzma_length_encoder *lc, const uint32_t pos_state)
{
- uint32_t a0, a1, b0, b1;
- uint32_t *prices;
- uint32_t i;
-
const uint32_t table_size = lc->table_size;
lc->counters[pos_state] = table_size;
- a0 = rc_bit_0_price(lc->choice);
- a1 = rc_bit_1_price(lc->choice);
- b0 = a1 + rc_bit_0_price(lc->choice2);
- b1 = a1 + rc_bit_1_price(lc->choice2);
- prices = lc->prices[pos_state];
+ const uint32_t a0 = rc_bit_0_price(lc->choice);
+ const uint32_t a1 = rc_bit_1_price(lc->choice);
+ const uint32_t b0 = a1 + rc_bit_0_price(lc->choice2);
+ const uint32_t b1 = a1 + rc_bit_1_price(lc->choice2);
+ uint32_t *const prices = lc->prices[pos_state];
+ uint32_t i;
for (i = 0; i < table_size && i < LEN_LOW_SYMBOLS; ++i)
prices[i] = a0 + rc_bittree_price(lc->low[pos_state],
LEN_LOW_BITS, i);
///////////
static inline void
-match(lzma_coder *coder, const uint32_t pos_state,
+match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
const uint32_t distance, const uint32_t len)
{
- uint32_t pos_slot;
- uint32_t len_to_pos_state;
-
update_match(coder->state);
length(&coder->rc, &coder->match_len_encoder, pos_state, len,
coder->fast_mode);
- pos_slot = get_pos_slot(distance);
- len_to_pos_state = get_len_to_pos_state(len);
- rc_bittree(&coder->rc, coder->pos_slot[len_to_pos_state],
- POS_SLOT_BITS, pos_slot);
+ const uint32_t dist_slot = get_dist_slot(distance);
+ const uint32_t dist_state = get_dist_state(len);
+ rc_bittree(&coder->rc, coder->dist_slot[dist_state],
+ DIST_SLOT_BITS, dist_slot);
- if (pos_slot >= START_POS_MODEL_INDEX) {
- const uint32_t footer_bits = (pos_slot >> 1) - 1;
- const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
- const uint32_t pos_reduced = distance - base;
+ if (dist_slot >= DIST_MODEL_START) {
+ const uint32_t footer_bits = (dist_slot >> 1) - 1;
+ const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
+ const uint32_t dist_reduced = distance - base;
- if (pos_slot < END_POS_MODEL_INDEX) {
- // Careful here: base - pos_slot - 1 can be -1, but
+ if (dist_slot < DIST_MODEL_END) {
+ // Careful here: base - dist_slot - 1 can be -1, but
// rc_bittree_reverse starts at probs[1], not probs[0].
rc_bittree_reverse(&coder->rc,
- coder->pos_special + base - pos_slot - 1,
- footer_bits, pos_reduced);
+ coder->dist_special + base - dist_slot - 1,
+ footer_bits, dist_reduced);
} else {
- rc_direct(&coder->rc, pos_reduced >> ALIGN_BITS,
+ rc_direct(&coder->rc, dist_reduced >> ALIGN_BITS,
footer_bits - ALIGN_BITS);
rc_bittree_reverse(
- &coder->rc, coder->pos_align,
- ALIGN_BITS, pos_reduced & ALIGN_MASK);
+ &coder->rc, coder->dist_align,
+ ALIGN_BITS, dist_reduced & ALIGN_MASK);
++coder->align_price_count;
}
}
////////////////////
static inline void
-rep_match(lzma_coder *coder, const uint32_t pos_state,
+rep_match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
const uint32_t rep, const uint32_t len)
{
if (rep == 0) {
//////////
static void
-encode_symbol(lzma_coder *coder, lzma_mf *mf,
+encode_symbol(lzma_lzma1_encoder *coder, lzma_mf *mf,
uint32_t back, uint32_t len, uint32_t position)
{
const uint32_t pos_state = position & coder->pos_mask;
rc_bit(&coder->rc,
&coder->is_match[coder->state][pos_state], 1);
- if (back < REP_DISTANCES) {
+ if (back < REPS) {
// It's a repeated match i.e. the same distance
// has been used earlier.
rc_bit(&coder->rc, &coder->is_rep[coder->state], 1);
} else {
// Normal match
rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
- match(coder, pos_state, back - REP_DISTANCES, len);
+ match(coder, pos_state, back - REPS, len);
}
}
static bool
-encode_init(lzma_coder *coder, lzma_mf *mf)
+encode_init(lzma_lzma1_encoder *coder, lzma_mf *mf)
{
assert(mf_position(mf) == 0);
static void
-encode_eopm(lzma_coder *coder, uint32_t position)
+encode_eopm(lzma_lzma1_encoder *coder, uint32_t position)
{
const uint32_t pos_state = position & coder->pos_mask;
rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1);
extern lzma_ret
-lzma_lzma_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size, uint32_t limit)
{
- uint32_t position;
-
// Initialize the stream if no data has been encoded yet.
if (!coder->is_initialized && !encode_init(coder, mf))
return LZMA_OK;
// Get the lowest bits of the uncompressed offset from the LZ layer.
- position = mf_position(mf);
+ uint32_t position = mf_position(mf);
while (true) {
- uint32_t len;
- uint32_t back;
-
// Encode pending bits, if any. Calling this before encoding
// the next symbol is needed only with plain LZMA, since
// LZMA2 always provides big enough buffer to flush
// Get optimal match (repeat position and length).
// Value ranges for pos:
- // - [0, REP_DISTANCES): repeated match
- // - [REP_DISTANCES, UINT32_MAX):
- // match at (pos - REP_DISTANCES)
+ // - [0, REPS): repeated match
+ // - [REPS, UINT32_MAX):
+ // match at (pos - REPS)
// - UINT32_MAX: not a match but a literal
// Value ranges for len:
// - [MATCH_LEN_MIN, MATCH_LEN_MAX]
+ uint32_t len;
+ uint32_t back;
if (coder->fast_mode)
lzma_lzma_optimum_fast(coder, mf, &back, &len);
static lzma_ret
-lzma_encode(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint8_t *LZMA_RESTRICT out, size_t *LZMA_RESTRICT out_pos,
+lzma_encode(void *coder, lzma_mf *restrict mf,
+ uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size)
{
// Plain LZMA has no support for sync-flushing.
length_encoder_reset(lzma_length_encoder *lencoder,
const uint32_t num_pos_states, const bool fast_mode)
{
- size_t pos_state;
-
bit_reset(lencoder->choice);
bit_reset(lencoder->choice2);
- for (pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+ for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
bittree_reset(lencoder->low[pos_state], LEN_LOW_BITS);
bittree_reset(lencoder->mid[pos_state], LEN_MID_BITS);
}
bittree_reset(lencoder->high, LEN_HIGH_BITS);
if (!fast_mode)
- for (pos_state = 0; pos_state < num_pos_states;
+ for (uint32_t pos_state = 0; pos_state < num_pos_states;
++pos_state)
length_update_prices(lencoder, pos_state);
extern lzma_ret
-lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
+lzma_lzma_encoder_reset(lzma_lzma1_encoder *coder,
+ const lzma_options_lzma *options)
{
- size_t i, j;
-
if (!is_options_valid(options))
return LZMA_OPTIONS_ERROR;
// State
coder->state = STATE_LIT_LIT;
- for (i = 0; i < REP_DISTANCES; ++i)
+ for (size_t i = 0; i < REPS; ++i)
coder->reps[i] = 0;
literal_init(coder->literal, options->lc, options->lp);
// Bit encoders
- for (i = 0; i < STATES; ++i) {
- for (j = 0; j <= coder->pos_mask; ++j) {
+ for (size_t i = 0; i < STATES; ++i) {
+ for (size_t j = 0; j <= coder->pos_mask; ++j) {
bit_reset(coder->is_match[i][j]);
bit_reset(coder->is_rep0_long[i][j]);
}
bit_reset(coder->is_rep2[i]);
}
- for (i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
- bit_reset(coder->pos_special[i]);
+ for (size_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i)
+ bit_reset(coder->dist_special[i]);
// Bit tree encoders
- for (i = 0; i < LEN_TO_POS_STATES; ++i)
- bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
+ for (size_t i = 0; i < DIST_STATES; ++i)
+ bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS);
- bittree_reset(coder->pos_align, ALIGN_BITS);
+ bittree_reset(coder->dist_align, ALIGN_BITS);
// Length encoders
length_encoder_reset(&coder->match_len_encoder,
extern lzma_ret
-lzma_lzma_encoder_create(lzma_coder **coder_ptr, lzma_allocator *allocator,
+lzma_lzma_encoder_create(void **coder_ptr,
+ const lzma_allocator *allocator,
const lzma_options_lzma *options, lzma_lz_options *lz_options)
{
- lzma_coder *coder;
- uint32_t log_size = 0;
-
- // Allocate lzma_coder if it wasn't already allocated.
+ // Allocate lzma_lzma1_encoder if it wasn't already allocated.
if (*coder_ptr == NULL) {
- *coder_ptr = lzma_alloc(sizeof(lzma_coder), allocator);
+ *coder_ptr = lzma_alloc(sizeof(lzma_lzma1_encoder), allocator);
if (*coder_ptr == NULL)
return LZMA_MEM_ERROR;
}
- coder = *coder_ptr;
+ lzma_lzma1_encoder *coder = *coder_ptr;
// Set compression mode. We haven't validates the options yet,
// but it's OK here, since nothing bad happens with invalid
// Set dist_table_size.
// Round the dictionary size up to next 2^n.
+ uint32_t log_size = 0;
while ((UINT32_C(1) << log_size) < options->dict_size)
++log_size;
static lzma_ret
-lzma_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
+lzma_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator,
const void *options, lzma_lz_options *lz_options)
{
lz->code = &lzma_encode;
extern lzma_ret
-lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_lzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return lzma_lz_encoder_init(
extern uint64_t
lzma_lzma_encoder_memusage(const void *options)
{
- lzma_lz_options lz_options;
- uint64_t lz_memusage;
-
if (!is_options_valid(options))
return UINT64_MAX;
+ lzma_lz_options lz_options;
set_lz_options(&lz_options, options);
- lz_memusage = lzma_lz_encoder_memusage(&lz_options);
+ const uint64_t lz_memusage = lzma_lz_encoder_memusage(&lz_options);
if (lz_memusage == UINT64_MAX)
return UINT64_MAX;
- return (uint64_t)(sizeof(lzma_coder)) + lz_memusage;
+ return (uint64_t)(sizeof(lzma_lzma1_encoder)) + lz_memusage;
}
#include "common.h"
+typedef struct lzma_lzma1_encoder_s lzma_lzma1_encoder;
+
+
extern lzma_ret lzma_lzma_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern uint64_t lzma_lzma_encoder_memusage(const void *options);
/// Initializes raw LZMA encoder; this is used by LZMA2.
extern lzma_ret lzma_lzma_encoder_create(
- lzma_coder **coder_ptr, lzma_allocator *allocator,
+ void **coder_ptr, const lzma_allocator *allocator,
const lzma_options_lzma *options, lzma_lz_options *lz_options);
/// Resets an already initialized LZMA encoder; this is used by LZMA2.
extern lzma_ret lzma_lzma_encoder_reset(
- lzma_coder *coder, const lzma_options_lzma *options);
+ lzma_lzma1_encoder *coder, const lzma_options_lzma *options);
-extern lzma_ret lzma_lzma_encode(lzma_coder *LZMA_RESTRICT coder,
- lzma_mf *LZMA_RESTRICT mf, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size,
+extern lzma_ret lzma_lzma_encode(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size,
uint32_t read_limit);
#endif
///////////////////////////////////////////////////////////////////////////////
#include "lzma_encoder_private.h"
+#include "memcmplen.h"
#define change_pair(small_dist, big_dist) \
extern void
-lzma_lzma_optimum_fast(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res)
+lzma_lzma_optimum_fast(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res)
{
- const uint8_t *buf;
- uint32_t buf_avail;
- uint32_t i;
- uint32_t rep_len = 0;
- uint32_t rep_index = 0;
- uint32_t back_main = 0;
- uint32_t limit;
-
const uint32_t nice_len = mf->nice_len;
uint32_t len_main;
matches_count = coder->matches_count;
}
- buf = mf_ptr(mf) - 1;
- buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
+ const uint8_t *buf = mf_ptr(mf) - 1;
+ const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
if (buf_avail < 2) {
// There's not enough input left to encode a match.
}
// Look for repeated matches; scan the previous four match distances
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t len;
+ uint32_t rep_len = 0;
+ uint32_t rep_index = 0;
+ for (uint32_t i = 0; i < REPS; ++i) {
// Pointer to the beginning of the match candidate
const uint8_t *const buf_back = buf - coder->reps[i] - 1;
// The first two bytes matched.
// Calculate the length of the match.
- for (len = 2; len < buf_avail
- && buf[len] == buf_back[len]; ++len) ;
+ const uint32_t len = lzma_memcmplen(
+ buf, buf_back, 2, buf_avail);
// If we have found a repeated match that is at least
// nice_len long, return it immediately.
// We didn't find a long enough repeated match. Encode it as a normal
// match if the match length is at least nice_len.
if (len_main >= nice_len) {
- *back_res = coder->matches[matches_count - 1].dist
- + REP_DISTANCES;
+ *back_res = coder->matches[matches_count - 1].dist + REPS;
*len_res = len_main;
mf_skip(mf, len_main - 1);
return;
}
+ uint32_t back_main = 0;
if (len_main >= 2) {
back_main = coder->matches[matches_count - 1].dist;
// the old buf pointer instead of recalculating it with mf_ptr().
++buf;
- limit = len_main - 1;
-
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t len;
-
- const uint8_t *const buf_back = buf - coder->reps[i] - 1;
-
- if (not_equal_16(buf, buf_back))
- continue;
-
- for (len = 2; len < limit
- && buf[len] == buf_back[len]; ++len) ;
+ const uint32_t limit = my_max(2, len_main - 1);
- if (len >= limit) {
+ for (uint32_t i = 0; i < REPS; ++i) {
+ if (memcmp(buf, buf - coder->reps[i] - 1, limit) == 0) {
*back_res = UINT32_MAX;
*len_res = 1;
return;
}
}
- *back_res = back_main + REP_DISTANCES;
+ *back_res = back_main + REPS;
*len_res = len_main;
mf_skip(mf, len_main - 2);
return;
#include "lzma_encoder_private.h"
#include "fastpos.h"
+#include "memcmplen.h"
////////////
////////////
static uint32_t
-get_literal_price(const lzma_coder *const coder, const uint32_t pos,
+get_literal_price(const lzma_lzma1_encoder *const coder, const uint32_t pos,
const uint32_t prev_byte, const bool match_mode,
uint32_t match_byte, uint32_t symbol)
{
symbol += UINT32_C(1) << 8;
do {
- uint32_t match_bit;
- uint32_t subcoder_index;
- uint32_t bit;
-
match_byte <<= 1;
- match_bit = match_byte & offset;
- subcoder_index = offset + match_bit + (symbol >> 8);
- bit = (symbol >> 7) & 1;
+ const uint32_t match_bit = match_byte & offset;
+ const uint32_t subcoder_index
+ = offset + match_bit + (symbol >> 8);
+ const uint32_t bit = (symbol >> 7) & 1;
price += rc_bit_price(subcoder[subcoder_index], bit);
symbol <<= 1;
static inline uint32_t
-get_short_rep_price(const lzma_coder *const coder,
+get_short_rep_price(const lzma_lzma1_encoder *const coder,
const lzma_lzma_state state, const uint32_t pos_state)
{
return rc_bit_0_price(coder->is_rep0[state])
static inline uint32_t
-get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+get_pure_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
const lzma_lzma_state state, uint32_t pos_state)
{
uint32_t price;
static inline uint32_t
-get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+get_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
const uint32_t len, const lzma_lzma_state state,
const uint32_t pos_state)
{
static inline uint32_t
-get_pos_len_price(const lzma_coder *const coder, const uint32_t pos,
+get_dist_len_price(const lzma_lzma1_encoder *const coder, const uint32_t dist,
const uint32_t len, const uint32_t pos_state)
{
- const uint32_t len_to_pos_state = get_len_to_pos_state(len);
+ const uint32_t dist_state = get_dist_state(len);
uint32_t price;
- if (pos < FULL_DISTANCES) {
- price = coder->distances_prices[len_to_pos_state][pos];
+ if (dist < FULL_DISTANCES) {
+ price = coder->dist_prices[dist_state][dist];
} else {
- const uint32_t pos_slot = get_pos_slot_2(pos);
- price = coder->pos_slot_prices[len_to_pos_state][pos_slot]
- + coder->align_prices[pos & ALIGN_MASK];
+ const uint32_t dist_slot = get_dist_slot_2(dist);
+ price = coder->dist_slot_prices[dist_state][dist_slot]
+ + coder->align_prices[dist & ALIGN_MASK];
}
price += get_len_price(&coder->match_len_encoder, len, pos_state);
static void
-fill_distances_prices(lzma_coder *coder)
+fill_dist_prices(lzma_lzma1_encoder *coder)
{
- uint32_t len_to_pos_state;
- uint32_t pos_slot;
- uint32_t i;
-
- for (len_to_pos_state = 0;
- len_to_pos_state < LEN_TO_POS_STATES;
- ++len_to_pos_state) {
+ for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) {
- uint32_t *const pos_slot_prices
- = coder->pos_slot_prices[len_to_pos_state];
+ uint32_t *const dist_slot_prices
+ = coder->dist_slot_prices[dist_state];
- // Price to encode the pos_slot.
- for (pos_slot = 0;
- pos_slot < coder->dist_table_size; ++pos_slot)
- pos_slot_prices[pos_slot] = rc_bittree_price(
- coder->pos_slot[len_to_pos_state],
- POS_SLOT_BITS, pos_slot);
+ // Price to encode the dist_slot.
+ for (uint32_t dist_slot = 0;
+ dist_slot < coder->dist_table_size; ++dist_slot)
+ dist_slot_prices[dist_slot] = rc_bittree_price(
+ coder->dist_slot[dist_state],
+ DIST_SLOT_BITS, dist_slot);
// For matches with distance >= FULL_DISTANCES, add the price
// of the direct bits part of the match distance. (Align bits
// are handled by fill_align_prices()).
- for (pos_slot = END_POS_MODEL_INDEX;
- pos_slot < coder->dist_table_size; ++pos_slot)
- pos_slot_prices[pos_slot] += rc_direct_price(
- ((pos_slot >> 1) - 1) - ALIGN_BITS);
+ for (uint32_t dist_slot = DIST_MODEL_END;
+ dist_slot < coder->dist_table_size;
+ ++dist_slot)
+ dist_slot_prices[dist_slot] += rc_direct_price(
+ ((dist_slot >> 1) - 1) - ALIGN_BITS);
// Distances in the range [0, 3] are fully encoded with
- // pos_slot, so they are used for coder->distances_prices
+ // dist_slot, so they are used for coder->dist_prices
// as is.
- for (i = 0; i < START_POS_MODEL_INDEX; ++i)
- coder->distances_prices[len_to_pos_state][i]
- = pos_slot_prices[i];
+ for (uint32_t i = 0; i < DIST_MODEL_START; ++i)
+ coder->dist_prices[dist_state][i]
+ = dist_slot_prices[i];
}
- // Distances in the range [4, 127] depend on pos_slot and pos_special.
- // We do this in a loop separate from the above loop to avoid
- // redundant calls to get_pos_slot().
- for (i = START_POS_MODEL_INDEX; i < FULL_DISTANCES; ++i) {
- const uint32_t pos_slot = get_pos_slot(i);
- const uint32_t footer_bits = ((pos_slot >> 1) - 1);
- const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
+ // Distances in the range [4, 127] depend on dist_slot and
+ // dist_special. We do this in a loop separate from the above
+ // loop to avoid redundant calls to get_dist_slot().
+ for (uint32_t i = DIST_MODEL_START; i < FULL_DISTANCES; ++i) {
+ const uint32_t dist_slot = get_dist_slot(i);
+ const uint32_t footer_bits = ((dist_slot >> 1) - 1);
+ const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
const uint32_t price = rc_bittree_reverse_price(
- coder->pos_special + base - pos_slot - 1,
+ coder->dist_special + base - dist_slot - 1,
footer_bits, i - base);
- for (len_to_pos_state = 0;
- len_to_pos_state < LEN_TO_POS_STATES;
- ++len_to_pos_state)
- coder->distances_prices[len_to_pos_state][i]
- = price + coder->pos_slot_prices[
- len_to_pos_state][pos_slot];
+ for (uint32_t dist_state = 0; dist_state < DIST_STATES;
+ ++dist_state)
+ coder->dist_prices[dist_state][i]
+ = price + coder->dist_slot_prices[
+ dist_state][dist_slot];
}
coder->match_price_count = 0;
static void
-fill_align_prices(lzma_coder *coder)
+fill_align_prices(lzma_lzma1_encoder *coder)
{
- uint32_t i;
- for (i = 0; i < ALIGN_TABLE_SIZE; ++i)
+ for (uint32_t i = 0; i < ALIGN_SIZE; ++i)
coder->align_prices[i] = rc_bittree_reverse_price(
- coder->pos_align, ALIGN_BITS, i);
+ coder->dist_align, ALIGN_BITS, i);
coder->align_price_count = 0;
return;
static void
-backward(lzma_coder *LZMA_RESTRICT coder, uint32_t *LZMA_RESTRICT len_res,
- uint32_t *LZMA_RESTRICT back_res, uint32_t cur)
+backward(lzma_lzma1_encoder *restrict coder, uint32_t *restrict len_res,
+ uint32_t *restrict back_res, uint32_t cur)
{
+ coder->opts_end_index = cur;
+
uint32_t pos_mem = coder->opts[cur].pos_prev;
uint32_t back_mem = coder->opts[cur].back_prev;
- coder->opts_end_index = cur;
-
do {
- const uint32_t pos_prev = pos_mem;
- const uint32_t back_cur = back_mem;
-
if (coder->opts[cur].prev_1_is_literal) {
make_literal(&coder->opts[pos_mem]);
coder->opts[pos_mem].pos_prev = pos_mem - 1;
}
}
+ const uint32_t pos_prev = pos_mem;
+ const uint32_t back_cur = back_mem;
+
back_mem = coder->opts[pos_prev].back_prev;
pos_mem = coder->opts[pos_prev].pos_prev;
//////////
static inline uint32_t
-helper1(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res,
+helper1(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res,
uint32_t position)
{
- uint32_t buf_avail;
- const uint8_t *buf;
- uint32_t rep_lens[REP_DISTANCES];
- uint32_t rep_max_index = 0;
- uint32_t i;
-
- uint8_t current_byte;
- uint8_t match_byte;
-
- uint32_t pos_state;
- uint32_t match_price;
- uint32_t rep_match_price;
- uint32_t len_end;
- uint32_t len;
-
- uint32_t normal_match_price;
-
const uint32_t nice_len = mf->nice_len;
uint32_t len_main;
matches_count = coder->matches_count;
}
- buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
+ const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
if (buf_avail < 2) {
*back_res = UINT32_MAX;
*len_res = 1;
return UINT32_MAX;
}
- buf = mf_ptr(mf) - 1;
+ const uint8_t *const buf = mf_ptr(mf) - 1;
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t len_test;
+ uint32_t rep_lens[REPS];
+ uint32_t rep_max_index = 0;
+ for (uint32_t i = 0; i < REPS; ++i) {
const uint8_t *const buf_back = buf - coder->reps[i] - 1;
if (not_equal_16(buf, buf_back)) {
continue;
}
- for (len_test = 2; len_test < buf_avail
- && buf[len_test] == buf_back[len_test];
- ++len_test) ;
+ rep_lens[i] = lzma_memcmplen(buf, buf_back, 2, buf_avail);
- rep_lens[i] = len_test;
- if (len_test > rep_lens[rep_max_index])
+ if (rep_lens[i] > rep_lens[rep_max_index])
rep_max_index = i;
}
if (len_main >= nice_len) {
- *back_res = coder->matches[matches_count - 1].dist
- + REP_DISTANCES;
+ *back_res = coder->matches[matches_count - 1].dist + REPS;
*len_res = len_main;
mf_skip(mf, len_main - 1);
return UINT32_MAX;
}
- current_byte = *buf;
- match_byte = *(buf - coder->reps[0] - 1);
+ const uint8_t current_byte = *buf;
+ const uint8_t match_byte = *(buf - coder->reps[0] - 1);
if (len_main < 2 && current_byte != match_byte
&& rep_lens[rep_max_index] < 2) {
coder->opts[0].state = coder->state;
- pos_state = position & coder->pos_mask;
+ const uint32_t pos_state = position & coder->pos_mask;
coder->opts[1].price = rc_bit_0_price(
coder->is_match[coder->state][pos_state])
make_literal(&coder->opts[1]);
- match_price = rc_bit_1_price(
+ const uint32_t match_price = rc_bit_1_price(
coder->is_match[coder->state][pos_state]);
- rep_match_price = match_price
+ const uint32_t rep_match_price = match_price
+ rc_bit_1_price(coder->is_rep[coder->state]);
if (match_byte == current_byte) {
}
}
- len_end = my_max(len_main, rep_lens[rep_max_index]);
+ const uint32_t len_end = my_max(len_main, rep_lens[rep_max_index]);
if (len_end < 2) {
*back_res = coder->opts[1].back_prev;
coder->opts[1].pos_prev = 0;
- for (i = 0; i < REP_DISTANCES; ++i)
+ for (uint32_t i = 0; i < REPS; ++i)
coder->opts[0].backs[i] = coder->reps[i];
- len = len_end;
+ uint32_t len = len_end;
do {
coder->opts[len].price = RC_INFINITY_PRICE;
} while (--len >= 2);
- for (i = 0; i < REP_DISTANCES; ++i) {
- uint32_t price;
-
+ for (uint32_t i = 0; i < REPS; ++i) {
uint32_t rep_len = rep_lens[i];
if (rep_len < 2)
continue;
- price = rep_match_price + get_pure_rep_price(
+ const uint32_t price = rep_match_price + get_pure_rep_price(
coder, i, coder->state, pos_state);
do {
}
- normal_match_price = match_price
+ const uint32_t normal_match_price = match_price
+ rc_bit_0_price(coder->is_rep[coder->state]);
len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2;
for(; ; ++len) {
const uint32_t dist = coder->matches[i].dist;
const uint32_t cur_and_len_price = normal_match_price
- + get_pos_len_price(coder,
+ + get_dist_len_price(coder,
dist, len, pos_state);
if (cur_and_len_price < coder->opts[len].price) {
coder->opts[len].price = cur_and_len_price;
coder->opts[len].pos_prev = 0;
- coder->opts[len].back_prev
- = dist + REP_DISTANCES;
+ coder->opts[len].back_prev = dist + REPS;
coder->opts[len].prev_1_is_literal = false;
}
static inline uint32_t
-helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
+helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf,
uint32_t len_end, uint32_t position, const uint32_t cur,
const uint32_t nice_len, const uint32_t buf_avail_full)
{
uint32_t new_len = coder->longest_match_length;
uint32_t pos_prev = coder->opts[cur].pos_prev;
lzma_lzma_state state;
- uint32_t buf_avail;
- uint32_t rep_index;
- uint32_t i;
-
- uint32_t cur_price;
- uint8_t current_byte;
- uint8_t match_byte;
- uint32_t pos_state;
- uint32_t cur_and_1_price;
- bool next_is_literal = false;
- uint32_t match_price;
- uint32_t rep_match_price;
- uint32_t start_len = 2;
if (coder->opts[cur].prev_1_is_literal) {
--pos_prev;
if (coder->opts[cur].prev_2) {
state = coder->opts[coder->opts[cur].pos_prev_2].state;
- if (coder->opts[cur].back_prev_2 < REP_DISTANCES)
+ if (coder->opts[cur].back_prev_2 < REPS)
update_long_rep(state);
else
update_match(state);
update_long_rep(state);
} else {
pos = coder->opts[cur].back_prev;
- if (pos < REP_DISTANCES)
+ if (pos < REPS)
update_long_rep(state);
else
update_match(state);
}
- if (pos < REP_DISTANCES) {
- uint32_t i;
-
+ if (pos < REPS) {
reps[0] = coder->opts[pos_prev].backs[pos];
+ uint32_t i;
for (i = 1; i <= pos; ++i)
reps[i] = coder->opts[pos_prev].backs[i - 1];
- for (; i < REP_DISTANCES; ++i)
+ for (; i < REPS; ++i)
reps[i] = coder->opts[pos_prev].backs[i];
} else {
- reps[0] = pos - REP_DISTANCES;
+ reps[0] = pos - REPS;
- for (i = 1; i < REP_DISTANCES; ++i)
+ for (uint32_t i = 1; i < REPS; ++i)
reps[i] = coder->opts[pos_prev].backs[i - 1];
}
}
coder->opts[cur].state = state;
- for (i = 0; i < REP_DISTANCES; ++i)
+ for (uint32_t i = 0; i < REPS; ++i)
coder->opts[cur].backs[i] = reps[i];
- cur_price = coder->opts[cur].price;
+ const uint32_t cur_price = coder->opts[cur].price;
- current_byte = *buf;
- match_byte = *(buf - reps[0] - 1);
+ const uint8_t current_byte = *buf;
+ const uint8_t match_byte = *(buf - reps[0] - 1);
- pos_state = position & coder->pos_mask;
+ const uint32_t pos_state = position & coder->pos_mask;
- cur_and_1_price = cur_price
+ const uint32_t cur_and_1_price = cur_price
+ rc_bit_0_price(coder->is_match[state][pos_state])
+ get_literal_price(coder, position, buf[-1],
!is_literal_state(state), match_byte, current_byte);
+ bool next_is_literal = false;
+
if (cur_and_1_price < coder->opts[cur + 1].price) {
coder->opts[cur + 1].price = cur_and_1_price;
coder->opts[cur + 1].pos_prev = cur;
next_is_literal = true;
}
- match_price = cur_price
+ const uint32_t match_price = cur_price
+ rc_bit_1_price(coder->is_match[state][pos_state]);
- rep_match_price = match_price
+ const uint32_t rep_match_price = match_price
+ rc_bit_1_price(coder->is_rep[state]);
if (match_byte == current_byte
if (buf_avail_full < 2)
return len_end;
- buf_avail = my_min(buf_avail_full, nice_len);
+ const uint32_t buf_avail = my_min(buf_avail_full, nice_len);
if (!next_is_literal && match_byte != current_byte) { // speed optimization
// try literal + rep0
const uint8_t *const buf_back = buf - reps[0] - 1;
const uint32_t limit = my_min(buf_avail_full, nice_len + 1);
- uint32_t len_test = 1;
- while (len_test < limit && buf[len_test] == buf_back[len_test])
- ++len_test;
-
- --len_test;
+ const uint32_t len_test = lzma_memcmplen(buf, buf_back, 1, limit) - 1;
if (len_test >= 2) {
- uint32_t pos_state_next;
- uint32_t next_rep_match_price;
- uint32_t offset;
- uint32_t cur_and_len_price;
-
lzma_lzma_state state_2 = state;
update_literal(state_2);
- pos_state_next = (position + 1) & coder->pos_mask;
- next_rep_match_price = cur_and_1_price
+ const uint32_t pos_state_next = (position + 1) & coder->pos_mask;
+ const uint32_t next_rep_match_price = cur_and_1_price
+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+ rc_bit_1_price(coder->is_rep[state_2]);
//for (; len_test >= 2; --len_test) {
- offset = cur + 1 + len_test;
+ const uint32_t offset = cur + 1 + len_test;
while (len_end < offset)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
- cur_and_len_price = next_rep_match_price
+ const uint32_t cur_and_len_price = next_rep_match_price
+ get_rep_price(coder, 0, len_test,
state_2, pos_state_next);
}
- for (rep_index = 0; rep_index < REP_DISTANCES; ++rep_index) {
- uint32_t len_test, len_test_2, len_test_temp;
- uint32_t price, limit;
+ uint32_t start_len = 2; // speed optimization
+ for (uint32_t rep_index = 0; rep_index < REPS; ++rep_index) {
const uint8_t *const buf_back = buf - reps[rep_index] - 1;
if (not_equal_16(buf, buf_back))
continue;
- for (len_test = 2; len_test < buf_avail
- && buf[len_test] == buf_back[len_test];
- ++len_test) ;
+ uint32_t len_test = lzma_memcmplen(buf, buf_back, 2, buf_avail);
while (len_end < cur + len_test)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
- len_test_temp = len_test;
- price = rep_match_price + get_pure_rep_price(
+ const uint32_t len_test_temp = len_test;
+ const uint32_t price = rep_match_price + get_pure_rep_price(
coder, rep_index, state, pos_state);
do {
start_len = len_test + 1;
- len_test_2 = len_test + 1;
- limit = my_min(buf_avail_full,
+ uint32_t len_test_2 = len_test + 1;
+ const uint32_t limit = my_min(buf_avail_full,
len_test_2 + nice_len);
for (; len_test_2 < limit
&& buf[len_test_2] == buf_back[len_test_2];
len_test_2 -= len_test + 1;
if (len_test_2 >= 2) {
- uint32_t pos_state_next;
- uint32_t cur_and_len_literal_price;
- uint32_t next_rep_match_price;
- uint32_t offset;
- uint32_t cur_and_len_price;
-
lzma_lzma_state state_2 = state;
update_long_rep(state_2);
- pos_state_next = (position + len_test) & coder->pos_mask;
+ uint32_t pos_state_next = (position + len_test) & coder->pos_mask;
- cur_and_len_literal_price = price
+ const uint32_t cur_and_len_literal_price = price
+ get_len_price(&coder->rep_len_encoder,
len_test, pos_state)
+ rc_bit_0_price(coder->is_match[state_2][pos_state_next])
pos_state_next = (position + len_test + 1) & coder->pos_mask;
- next_rep_match_price = cur_and_len_literal_price
+ const uint32_t next_rep_match_price = cur_and_len_literal_price
+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+ rc_bit_1_price(coder->is_rep[state_2]);
//for(; len_test_2 >= 2; len_test_2--) {
- offset = cur + len_test + 1 + len_test_2;
+ const uint32_t offset = cur + len_test + 1 + len_test_2;
while (len_end < offset)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
- cur_and_len_price = next_rep_match_price
+ const uint32_t cur_and_len_price = next_rep_match_price
+ get_rep_price(coder, 0, len_test_2,
state_2, pos_state_next);
if (new_len >= start_len) {
- uint32_t len_test;
- uint32_t i = 0;
-
const uint32_t normal_match_price = match_price
+ rc_bit_0_price(coder->is_rep[state]);
while (len_end < cur + new_len)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
+ uint32_t i = 0;
while (start_len > coder->matches[i].len)
++i;
- for (len_test = start_len; ; ++len_test) {
+ for (uint32_t len_test = start_len; ; ++len_test) {
const uint32_t cur_back = coder->matches[i].dist;
uint32_t cur_and_len_price = normal_match_price
- + get_pos_len_price(coder,
+ + get_dist_len_price(coder,
cur_back, len_test, pos_state);
if (cur_and_len_price < coder->opts[cur + len_test].price) {
coder->opts[cur + len_test].price = cur_and_len_price;
coder->opts[cur + len_test].pos_prev = cur;
coder->opts[cur + len_test].back_prev
- = cur_back + REP_DISTANCES;
+ = cur_back + REPS;
coder->opts[cur + len_test].prev_1_is_literal = false;
}
len_test_2 -= len_test + 1;
if (len_test_2 >= 2) {
- uint32_t pos_state_next;
- uint32_t cur_and_len_literal_price;
- uint32_t next_rep_match_price;
- uint32_t offset;
-
lzma_lzma_state state_2 = state;
update_match(state_2);
- pos_state_next = (position + len_test) & coder->pos_mask;
+ uint32_t pos_state_next
+ = (position + len_test) & coder->pos_mask;
- cur_and_len_literal_price = cur_and_len_price
+ const uint32_t cur_and_len_literal_price = cur_and_len_price
+ rc_bit_0_price(
coder->is_match[state_2][pos_state_next])
+ get_literal_price(coder,
update_literal(state_2);
pos_state_next = (pos_state_next + 1) & coder->pos_mask;
- next_rep_match_price
+ const uint32_t next_rep_match_price
= cur_and_len_literal_price
+ rc_bit_1_price(
coder->is_match[state_2][pos_state_next])
+ rc_bit_1_price(coder->is_rep[state_2]);
// for(; len_test_2 >= 2; --len_test_2) {
- offset = cur + len_test + 1 + len_test_2;
+ const uint32_t offset = cur + len_test + 1 + len_test_2;
while (len_end < offset)
coder->opts[++len_end].price = RC_INFINITY_PRICE;
coder->opts[offset].prev_2 = true;
coder->opts[offset].pos_prev_2 = cur;
coder->opts[offset].back_prev_2
- = cur_back + REP_DISTANCES;
+ = cur_back + REPS;
}
//}
}
extern void
-lzma_lzma_optimum_normal(lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res,
+lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res,
uint32_t position)
{
- uint32_t reps[REP_DISTANCES];
- uint32_t len_end;
- uint32_t cur;
-
// If we have symbols pending, return the next pending symbol.
if (coder->opts_end_index != coder->opts_current_index) {
assert(mf->read_ahead > 0);
// In liblzma they were moved into this single place.
if (mf->read_ahead == 0) {
if (coder->match_price_count >= (1 << 7))
- fill_distances_prices(coder);
+ fill_dist_prices(coder);
- if (coder->align_price_count >= ALIGN_TABLE_SIZE)
+ if (coder->align_price_count >= ALIGN_SIZE)
fill_align_prices(coder);
}
// the original function into two pieces makes it at least a little
// more readable, since those two parts don't share many variables.
- len_end = helper1(coder, mf, back_res, len_res, position);
+ uint32_t len_end = helper1(coder, mf, back_res, len_res, position);
if (len_end == UINT32_MAX)
return;
-
+ uint32_t reps[REPS];
memcpy(reps, coder->reps, sizeof(reps));
+ uint32_t cur;
for (cur = 1; cur < len_end; ++cur) {
assert(cur < OPTS);
//
/// \file lzma_encoder_presets.c
/// \brief Encoder presets
+/// \note xz needs this even when only decoding is enabled.
//
// Author: Lasse Collin
//
extern LZMA_API(lzma_bool)
lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
{
- static const uint8_t dict_pow2[]
- = { 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 };
- static const uint8_t depths[] = { 4, 8, 24, 48 };
-
const uint32_t level = preset & LZMA_PRESET_LEVEL_MASK;
const uint32_t flags = preset & ~LZMA_PRESET_LEVEL_MASK;
const uint32_t supported_flags = LZMA_PRESET_EXTREME;
options->lp = LZMA_LP_DEFAULT;
options->pb = LZMA_PB_DEFAULT;
+ static const uint8_t dict_pow2[]
+ = { 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 };
options->dict_size = UINT32_C(1) << dict_pow2[level];
if (level <= 3) {
options->mode = LZMA_MODE_FAST;
options->mf = level == 0 ? LZMA_MF_HC3 : LZMA_MF_HC4;
options->nice_len = level <= 1 ? 128 : 273;
+ static const uint8_t depths[] = { 4, 8, 24, 48 };
options->depth = depths[level];
} else {
options->mode = LZMA_MODE_NORMAL;
uint32_t pos_prev; // pos_next;
uint32_t back_prev;
- uint32_t backs[REP_DISTANCES];
+ uint32_t backs[REPS];
} lzma_optimal;
-struct lzma_coder_s {
+struct lzma_lzma1_encoder_s {
/// Range encoder
lzma_range_encoder rc;
lzma_lzma_state state;
/// The four most recent match distances
- uint32_t reps[REP_DISTANCES];
+ uint32_t reps[REPS];
/// Array of match candidates
lzma_match matches[MATCH_LEN_MAX + 1];
probability is_rep1[STATES];
probability is_rep2[STATES];
probability is_rep0_long[STATES][POS_STATES_MAX];
- probability pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
- probability pos_special[FULL_DISTANCES - END_POS_MODEL_INDEX];
- probability pos_align[ALIGN_TABLE_SIZE];
+ probability dist_slot[DIST_STATES][DIST_SLOTS];
+ probability dist_special[FULL_DISTANCES - DIST_MODEL_END];
+ probability dist_align[ALIGN_SIZE];
// These are the same as in lzma_decoder.c except that the encoders
// include also price tables.
lzma_length_encoder rep_len_encoder;
// Price tables
- uint32_t pos_slot_prices[LEN_TO_POS_STATES][POS_SLOTS];
- uint32_t distances_prices[LEN_TO_POS_STATES][FULL_DISTANCES];
+ uint32_t dist_slot_prices[DIST_STATES][DIST_SLOTS];
+ uint32_t dist_prices[DIST_STATES][FULL_DISTANCES];
uint32_t dist_table_size;
uint32_t match_price_count;
- uint32_t align_prices[ALIGN_TABLE_SIZE];
+ uint32_t align_prices[ALIGN_SIZE];
uint32_t align_price_count;
// Optimal
extern void lzma_lzma_optimum_fast(
- lzma_coder *LZMA_RESTRICT coder, lzma_mf *LZMA_RESTRICT mf,
- uint32_t *LZMA_RESTRICT back_res, uint32_t *LZMA_RESTRICT len_res);
+ lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
+ uint32_t *restrict back_res, uint32_t *restrict len_res);
-extern void lzma_lzma_optimum_normal(lzma_coder *LZMA_RESTRICT coder,
- lzma_mf *LZMA_RESTRICT mf, uint32_t *LZMA_RESTRICT back_res,
- uint32_t *LZMA_RESTRICT len_res, uint32_t position);
+extern void lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
+ lzma_mf *restrict mf, uint32_t *restrict back_res,
+ uint32_t *restrict len_res, uint32_t position);
#endif
// This does the same for a complete bit tree.
// (A tree represented as an array.)
#define bittree_reset(probs, bit_levels) \
- do { \
- uint32_t bt_i; \
- for (bt_i = 0; bt_i < (1 << (bit_levels)); ++bt_i) \
- bit_reset((probs)[bt_i]); \
- } while (0)
+ for (uint32_t bt_i = 0; bt_i < (1 << (bit_levels)); ++bt_i) \
+ bit_reset((probs)[bt_i])
//////////////////////
/// Reads the first five bytes to initialize the range decoder.
-static inline bool
-rc_read_init(lzma_range_decoder *rc, const uint8_t *LZMA_RESTRICT in,
- size_t *LZMA_RESTRICT in_pos, size_t in_size)
+static inline lzma_ret
+rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in,
+ size_t *restrict in_pos, size_t in_size)
{
while (rc->init_bytes_left > 0) {
if (*in_pos == in_size)
- return false;
+ return LZMA_OK;
+
+ // The first byte is always 0x00. It could have been omitted
+ // in LZMA2 but it wasn't, so one byte is wasted in every
+ // LZMA2 chunk.
+ if (rc->init_bytes_left == 5 && in[*in_pos] != 0x00)
+ return LZMA_DATA_ERROR;
rc->code = (rc->code << 8) | in[*in_pos];
++*in_pos;
--rc->init_bytes_left;
}
- return true;
+ return LZMA_STREAM_END;
}
static inline void
rc_flush(lzma_range_encoder *rc)
{
- size_t i;
- for (i = 0; i < 5; ++i)
+ for (size_t i = 0; i < 5; ++i)
rc->symbols[rc->count++] = RC_FLUSH;
}
static size_t
-arm_code(lzma_simple *simple lzma_attribute((__unused__)),
+arm_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
size_t i;
for (i = 0; i + 4 <= size; i += 4) {
if (buffer[i + 3] == 0xEB) {
- uint32_t dest;
uint32_t src = (buffer[i + 2] << 16)
| (buffer[i + 1] << 8)
| (buffer[i + 0]);
src <<= 2;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + 8 + src;
else
static lzma_ret
-arm_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+arm_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
extern lzma_ret
-lzma_simple_arm_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_arm_encoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return arm_coder_init(next, allocator, filters, true);
extern lzma_ret
-lzma_simple_arm_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_arm_decoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return arm_coder_init(next, allocator, filters, false);
static size_t
-armthumb_code(lzma_simple *simple lzma_attribute((__unused__)),
+armthumb_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
for (i = 0; i + 4 <= size; i += 2) {
if ((buffer[i + 1] & 0xF8) == 0xF0
&& (buffer[i + 3] & 0xF8) == 0xF8) {
- uint32_t dest;
uint32_t src = ((buffer[i + 1] & 0x7) << 19)
| (buffer[i + 0] << 11)
| ((buffer[i + 3] & 0x7) << 8)
src <<= 1;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + 4 + src;
else
static lzma_ret
-armthumb_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+armthumb_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
extern lzma_ret
lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return armthumb_coder_init(next, allocator, filters, true);
}
extern lzma_ret
lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return armthumb_coder_init(next, allocator, filters, false);
}
static size_t
-ia64_code(lzma_simple *simple lzma_attribute((__unused__)),
+ia64_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
size_t i;
for (i = 0; i + 16 <= size; i += 16) {
- size_t slot;
-
const uint32_t instr_template = buffer[i] & 0x1F;
const uint32_t mask = BRANCH_TABLE[instr_template];
uint32_t bit_pos = 5;
- for (slot = 0; slot < 3; ++slot, bit_pos += 41) {
+ for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) {
+ if (((mask >> slot) & 1) == 0)
+ continue;
+
const size_t byte_pos = (bit_pos >> 3);
const uint32_t bit_res = bit_pos & 0x7;
uint64_t instruction = 0;
- uint64_t inst_norm;
- size_t j;
-
- if (((mask >> slot) & 1) == 0)
- continue;
- for (j = 0; j < 6; ++j)
+ for (size_t j = 0; j < 6; ++j)
instruction += (uint64_t)(
buffer[i + j + byte_pos])
<< (8 * j);
- inst_norm = instruction >> bit_res;
+ uint64_t inst_norm = instruction >> bit_res;
if (((inst_norm >> 37) & 0xF) == 0x5
&& ((inst_norm >> 9) & 0x7) == 0
/* && (inst_norm & 0x3F)== 0 */
) {
- uint32_t dest;
- size_t j;
-
uint32_t src = (uint32_t)(
(inst_norm >> 13) & 0xFFFFF);
src |= ((inst_norm >> 36) & 1) << 20;
src <<= 4;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + src;
else
instruction &= (1 << bit_res) - 1;
instruction |= (inst_norm << bit_res);
- for (j = 0; j < 6; j++)
+ for (size_t j = 0; j < 6; j++)
buffer[i + j + byte_pos] = (uint8_t)(
instruction
>> (8 * j));
static lzma_ret
-ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+ia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
extern lzma_ret
lzma_simple_ia64_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return ia64_coder_init(next, allocator, filters, true);
}
extern lzma_ret
lzma_simple_ia64_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return ia64_coder_init(next, allocator, filters, false);
}
static size_t
-powerpc_code(lzma_simple *simple lzma_attribute((__unused__)),
+powerpc_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
static lzma_ret
-powerpc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+powerpc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
extern lzma_ret
lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return powerpc_coder_init(next, allocator, filters, true);
}
extern lzma_ret
lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return powerpc_coder_init(next, allocator, filters, false);
}
/// Copied or encodes/decodes more data to out[].
static lzma_ret
-copy_or_code(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+copy_or_code(lzma_simple_coder *coder, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
assert(!coder->end_was_reached);
static size_t
-call_filter(lzma_coder *coder, uint8_t *buffer, size_t size)
+call_filter(lzma_simple_coder *coder, uint8_t *buffer, size_t size)
{
const size_t filtered = coder->filter(coder->simple,
coder->now_pos, coder->is_encoder,
static lzma_ret
-simple_code(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
- size_t in_size, uint8_t *LZMA_RESTRICT out,
- size_t *LZMA_RESTRICT out_pos, size_t out_size, lzma_action action)
+simple_code(void *coder_ptr, const lzma_allocator *allocator,
+ const uint8_t *restrict in, size_t *restrict in_pos,
+ size_t in_size, uint8_t *restrict out,
+ size_t *restrict out_pos, size_t out_size, lzma_action action)
{
- size_t out_avail;
- size_t buf_avail;
+ lzma_simple_coder *coder = coder_ptr;
// TODO: Add partial support for LZMA_SYNC_FLUSH. We can support it
// in cases when the filter is able to filter everything. With most
// more data to out[] hopefully filling it completely. Then filter
// the data in out[]. This step is where most of the data gets
// filtered if the buffer sizes used by the application are reasonable.
- out_avail = out_size - *out_pos;
- buf_avail = coder->size - coder->pos;
+ const size_t out_avail = out_size - *out_pos;
+ const size_t buf_avail = coder->size - coder->pos;
if (out_avail > buf_avail || buf_avail == 0) {
- size_t size;
- size_t filtered;
- size_t unfiltered;
-
// Store the old position so that we know from which byte
// to start filtering.
const size_t out_start = *out_pos;
}
// Filter out[].
- size = *out_pos - out_start;
- filtered = call_filter(coder, out + out_start, size);
+ const size_t size = *out_pos - out_start;
+ const size_t filtered = call_filter(
+ coder, out + out_start, size);
- unfiltered = size - filtered;
+ const size_t unfiltered = size - filtered;
assert(unfiltered <= coder->allocated / 2);
// Now we can update coder->pos and coder->size, because
static void
-simple_coder_end(lzma_coder *coder, lzma_allocator *allocator)
+simple_coder_end(void *coder_ptr, const lzma_allocator *allocator)
{
+ lzma_simple_coder *coder = coder_ptr;
lzma_next_end(&coder->next, allocator);
lzma_free(coder->simple, allocator);
lzma_free(coder, allocator);
static lzma_ret
-simple_coder_update(lzma_coder *coder, lzma_allocator *allocator,
+simple_coder_update(void *coder_ptr, const lzma_allocator *allocator,
const lzma_filter *filters_null lzma_attribute((__unused__)),
const lzma_filter *reversed_filters)
{
+ lzma_simple_coder *coder = coder_ptr;
+
// No update support, just call the next filter in the chain.
return lzma_next_filter_update(
&coder->next, allocator, reversed_filters + 1);
extern lzma_ret
-lzma_simple_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters,
- size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+ size_t (*filter)(void *simple, uint32_t now_pos,
bool is_encoder, uint8_t *buffer, size_t size),
size_t simple_size, size_t unfiltered_max,
uint32_t alignment, bool is_encoder)
{
- // Allocate memory for the lzma_coder structure if needed.
- if (next->coder == NULL) {
+ // Allocate memory for the lzma_simple_coder structure if needed.
+ lzma_simple_coder *coder = next->coder;
+ if (coder == NULL) {
// Here we allocate space also for the temporary buffer. We
// need twice the size of unfiltered_max, because then it
// is always possible to filter at least unfiltered_max bytes
// more data in coder->buffer[] if it can be filled completely.
- next->coder = lzma_alloc(sizeof(lzma_coder)
+ coder = lzma_alloc(sizeof(lzma_simple_coder)
+ 2 * unfiltered_max, allocator);
- if (next->coder == NULL)
+ if (coder == NULL)
return LZMA_MEM_ERROR;
+ next->coder = coder;
next->code = &simple_code;
next->end = &simple_coder_end;
next->update = &simple_coder_update;
- next->coder->next = LZMA_NEXT_CODER_INIT;
- next->coder->filter = filter;
- next->coder->allocated = 2 * unfiltered_max;
+ coder->next = LZMA_NEXT_CODER_INIT;
+ coder->filter = filter;
+ coder->allocated = 2 * unfiltered_max;
// Allocate memory for filter-specific data structure.
if (simple_size > 0) {
- next->coder->simple = lzma_alloc(
- simple_size, allocator);
- if (next->coder->simple == NULL)
+ coder->simple = lzma_alloc(simple_size, allocator);
+ if (coder->simple == NULL)
return LZMA_MEM_ERROR;
} else {
- next->coder->simple = NULL;
+ coder->simple = NULL;
}
}
if (filters[0].options != NULL) {
const lzma_options_bcj *simple = filters[0].options;
- next->coder->now_pos = simple->start_offset;
- if (next->coder->now_pos & (alignment - 1))
+ coder->now_pos = simple->start_offset;
+ if (coder->now_pos & (alignment - 1))
return LZMA_OPTIONS_ERROR;
} else {
- next->coder->now_pos = 0;
+ coder->now_pos = 0;
}
// Reset variables.
- next->coder->is_encoder = is_encoder;
- next->coder->end_was_reached = false;
- next->coder->pos = 0;
- next->coder->filtered = 0;
- next->coder->size = 0;
-
- return lzma_next_filter_init(
- &next->coder->next, allocator, filters + 1);
+ coder->is_encoder = is_encoder;
+ coder->end_was_reached = false;
+ coder->pos = 0;
+ coder->filtered = 0;
+ coder->size = 0;
+
+ return lzma_next_filter_init(&coder->next, allocator, filters + 1);
}
extern lzma_ret lzma_simple_x86_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_x86_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_ia64_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_ia64_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_arm_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_arm_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_sparc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
extern lzma_ret lzma_simple_sparc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters);
#endif
extern lzma_ret
-lzma_simple_props_decode(void **options, lzma_allocator *allocator,
+lzma_simple_props_decode(void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size)
{
- lzma_options_bcj *opt;
-
if (props_size == 0)
return LZMA_OK;
if (props_size != 4)
return LZMA_OPTIONS_ERROR;
- opt = lzma_alloc(sizeof(lzma_options_bcj), allocator);
+ lzma_options_bcj *opt = lzma_alloc(
+ sizeof(lzma_options_bcj), allocator);
if (opt == NULL)
return LZMA_MEM_ERROR;
#include "simple_coder.h"
extern lzma_ret lzma_simple_props_decode(
- void **options, lzma_allocator *allocator,
+ void **options, const lzma_allocator *allocator,
const uint8_t *props, size_t props_size);
#endif
#include "simple_coder.h"
-typedef struct lzma_simple_s lzma_simple;
-
-struct lzma_coder_s {
+typedef struct {
/// Next filter in the chain
lzma_next_coder next;
/// Pointer to filter-specific function, which does
/// the actual filtering.
- size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+ size_t (*filter)(void *simple, uint32_t now_pos,
bool is_encoder, uint8_t *buffer, size_t size);
/// Pointer to filter-specific data, or NULL if filter doesn't need
/// any extra data.
- lzma_simple *simple;
+ void *simple;
/// The lowest 32 bits of the current position in the data. Most
/// filters need this to do conversions between absolute and relative
/// Temporary buffer
uint8_t buffer[];
-};
+} lzma_simple_coder;
extern lzma_ret lzma_simple_coder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters,
- size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters,
+ size_t (*filter)(void *simple, uint32_t now_pos,
bool is_encoder, uint8_t *buffer, size_t size),
size_t simple_size, size_t unfiltered_max,
uint32_t alignment, bool is_encoder);
static size_t
-sparc_code(lzma_simple *simple lzma_attribute((__unused__)),
+sparc_code(void *simple lzma_attribute((__unused__)),
uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
|| (buffer[i] == 0x7F
&& (buffer[i + 1] & 0xC0) == 0xC0)) {
- uint32_t dest;
-
uint32_t src = ((uint32_t)buffer[i + 0] << 24)
| ((uint32_t)buffer[i + 1] << 16)
| ((uint32_t)buffer[i + 2] << 8)
src <<= 2;
+ uint32_t dest;
if (is_encoder)
dest = now_pos + (uint32_t)(i) + src;
else
static lzma_ret
-sparc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+sparc_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
extern lzma_ret
lzma_simple_sparc_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return sparc_coder_init(next, allocator, filters, true);
}
extern lzma_ret
lzma_simple_sparc_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
+ const lzma_allocator *allocator,
+ const lzma_filter_info *filters)
{
return sparc_coder_init(next, allocator, filters, false);
}
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
-struct lzma_simple_s {
+typedef struct {
uint32_t prev_mask;
uint32_t prev_pos;
-};
+} lzma_simple_x86;
static size_t
-x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
+x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder,
uint8_t *buffer, size_t size)
{
static const bool MASK_TO_ALLOWED_STATUS[8]
static const uint32_t MASK_TO_BIT_NUMBER[8]
= { 0, 1, 2, 2, 3, 3, 3, 3 };
+ lzma_simple_x86 *simple = simple_ptr;
uint32_t prev_mask = simple->prev_mask;
uint32_t prev_pos = simple->prev_pos;
- size_t limit;
- size_t buffer_pos;
-
if (size < 5)
return 0;
if (now_pos - prev_pos > 5)
prev_pos = now_pos - 5;
- limit = size - 5;
- buffer_pos = 0;
+ const size_t limit = size - 5;
+ size_t buffer_pos = 0;
while (buffer_pos <= limit) {
- uint32_t offset;
- uint32_t i;
-
uint8_t b = buffer[buffer_pos];
if (b != 0xE8 && b != 0xE9) {
++buffer_pos;
continue;
}
- offset = now_pos + (uint32_t)(buffer_pos)
+ const uint32_t offset = now_pos + (uint32_t)(buffer_pos)
- prev_pos;
prev_pos = now_pos + (uint32_t)(buffer_pos);
if (offset > 5) {
prev_mask = 0;
} else {
- for (i = 0; i < offset; ++i) {
+ for (uint32_t i = 0; i < offset; ++i) {
prev_mask &= 0x77;
prev_mask <<= 1;
}
uint32_t dest;
while (true) {
- uint32_t i;
-
if (is_encoder)
dest = src + (now_pos + (uint32_t)(
buffer_pos) + 5);
if (prev_mask == 0)
break;
- i = MASK_TO_BIT_NUMBER[prev_mask >> 1];
+ const uint32_t i = MASK_TO_BIT_NUMBER[
+ prev_mask >> 1];
b = (uint8_t)(dest >> (24 - i * 8));
static lzma_ret
-x86_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters,
- &x86_code, sizeof(lzma_simple), 5, 1, is_encoder);
+ &x86_code, sizeof(lzma_simple_x86), 5, 1, is_encoder);
if (ret == LZMA_OK) {
- next->coder->simple->prev_mask = 0;
- next->coder->simple->prev_pos = (uint32_t)(-5);
+ lzma_simple_coder *coder = next->coder;
+ lzma_simple_x86 *simple = coder->simple;
+ simple->prev_mask = 0;
+ simple->prev_pos = (uint32_t)(-5);
}
return ret;
extern lzma_ret
-lzma_simple_x86_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_x86_encoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return x86_coder_init(next, allocator, filters, true);
extern lzma_ret
-lzma_simple_x86_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+lzma_simple_x86_decoder_init(lzma_next_coder *next,
+ const lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return x86_coder_init(next, allocator, filters, false);
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
+#include "ustd.h" /* Need this first within CMake. */
+
#include <string.h> /* memset() */
#include <stdlib.h> /* free() */
#include <stddef.h> /* ptrdiff_t */
)
endif()
+if(CMAKE_SYSTEM_NAME STREQUAL "kFreeBSD")
+ list(APPEND uv_libraries
+ freebsd-glue
+ kvm
+ )
+ list(APPEND uv_headers
+ 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()
+
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
list(APPEND uv_libraries
kvm
cmInstallTargetsCommand \
cmInstalledFile \
cmLinkDirectoriesCommand \
+ cmLinkItem \
cmLinkLineComputer \
cmListCommand \
cmListFileCache \
uv_c_flags="${uv_c_flags} -D_GNU_SOURCE"
libs="${libs} -ldl -lrt"
;;
+ *kFreeBSD*)
+ libs="${libs} -lkvm -lfreebsd-glue"
+ ;;
*BSD*)
libs="${libs} -lkvm"
;;