diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml deleted file mode 100644 index b5a6b99..0000000 --- a/.azure-pipelines.yml +++ /dev/null @@ -1,92 +0,0 @@ -resources: - repositories: - - repository: templates - type: github - name: Tereius/conan-azure-templates - endpoint: Tereius - -jobs: -- job: Android - strategy: - matrix: - armv7Linux: - imageName: "ubuntu-18.04" - buildProfile: "androidArmv7LinuxHost" - armv7Windows: - imageName: "windows-2019" - buildProfile: "androidArmv7WinHost" - pool: - vmImage: '$(imageName)' - timeoutInMinutes: 0 - steps: - - template: buildConanRecipe.yml@templates - parameters: - conanEnv: { - CONAN_USERNAME: "tereius", - CONAN_CHANNEL: "stable", - CONAN_REMOTES: "https://conan.privatehive.de/artifactory/api/conan/public-conan", - CONAN_BASE_PROFILE_PATH: "./buildProfiles/$(buildProfile).profile", - CONAN_BUILD_PROFILE: "default" - } - -- job: Linux - pool: - vmImage: "ubuntu-18.04" - timeoutInMinutes: 0 - steps: - - template: buildConanRecipe.yml@templates - parameters: - conanEnv: { - CONAN_USERNAME: "tereius", - CONAN_CHANNEL: "stable", - CONAN_REMOTES: "https://conan.privatehive.de/artifactory/api/conan/public-conan", - CONAN_BASE_PROFILE: "default" - } - -- job: Windows - pool: - vmImage: "vs2017-win2016" - timeoutInMinutes: 0 - steps: - - template: buildConanRecipe.yml@templates - parameters: - conanEnv: { - CONAN_USERNAME: "tereius", - CONAN_CHANNEL: "stable", - CONAN_REMOTES: "https://conan.privatehive.de/artifactory/api/conan/public-conan", - CONAN_BASE_PROFILE: "default" - } - -- job: Macos - pool: - vmImage: "macOS-10.14" - timeoutInMinutes: 0 - steps: - - template: buildConanRecipe.yml@templates - parameters: - conanEnv: { - CONAN_USERNAME: "tereius", - CONAN_CHANNEL: "stable", - CONAN_REMOTES: "https://conan.privatehive.de/artifactory/api/conan/public-conan", - CONAN_BASE_PROFILE: "default" - } - -- job: Upload - dependsOn: - - Android - - Linux - - Windows - - Macos - condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI')) - pool: - vmImage: "ubuntu-latest" - steps: - - template: uploadConanRecipe.yml@templates - parameters: - conanEnv: { - CONAN_USERNAME: "tereius", - CONAN_CHANNEL: "stable", - CONAN_UPLOAD: "https://conan.privatehive.de/artifactory/api/conan/public-conan", - CONAN_LOGIN_USERNAME: "ci", - CONAN_PASSWORD: "$(secret)", - } diff --git a/.clang-format b/.clang-format index 75e78d5..ff60a94 100644 --- a/.clang-format +++ b/.clang-format @@ -70,7 +70,7 @@ IncludeCategories: IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: true IndentPPDirectives: None -IndentWidth: 1 +IndentWidth: 2 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave JavaScriptWrapImports: true @@ -90,12 +90,12 @@ PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right -#RawStringFormats: +#RawStringFormats: # - Delimiter: pb # Language: TextProto # BasedOnStyle: google ReflowComments: true -SortIncludes: false +SortIncludes: true SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: false @@ -109,7 +109,7 @@ SpacesInContainerLiterals: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 -TabWidth: 1 +TabWidth: 2 UseTab: ForIndentation ... diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..9af7c8a --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,71 @@ +name: "Create Conan Package" +on: push + +jobs: + build_linux_x86_64: + name: "Linux" + uses: Privatehive/conan-workflows/.github/workflows/createPackage.yml@master + with: + image: "ubuntu-20.04" + conan_remotes: https://conan.privatehive.de/artifactory/api/conan/public-conan + + build_windows_x86_64: + name: "Windows" + uses: Privatehive/conan-workflows/.github/workflows/createPackage.yml@master + with: + image: "windows-2022" + conan_host_profile: "windowsMinGW" + conan_remotes: https://conan.privatehive.de/artifactory/api/conan/public-conan + + build_macos_armv8: + name: "Macos" + uses: Privatehive/conan-workflows/.github/workflows/createPackage.yml@master + with: + image: "macos-14" + conan_remotes: https://conan.privatehive.de/artifactory/api/conan/public-conan + + build_android_x86: + name: "Android" + uses: Privatehive/conan-workflows/.github/workflows/createPackageGcpRunner.yml@master + with: + docker_image: "ghcr.io/privatehive/conan-ubuntu:latest" + machine_type: c2d-standard-8 + conan_host_profile: "androidx86" + conan_remotes: https://conan.privatehive.de/artifactory/api/conan/public-conan + + build_android_x86_64: + name: "Android" + uses: Privatehive/conan-workflows/.github/workflows/createPackageGcpRunner.yml@master + with: + docker_image: "ghcr.io/privatehive/conan-ubuntu:latest" + machine_type: c2d-standard-8 + conan_host_profile: "androidx86_64" + conan_remotes: https://conan.privatehive.de/artifactory/api/conan/public-conan + + build_android_armv7: + name: "Android" + uses: Privatehive/conan-workflows/.github/workflows/createPackageGcpRunner.yml@master + with: + docker_image: "ghcr.io/privatehive/conan-ubuntu:latest" + machine_type: c2d-standard-8 + conan_host_profile: "androidArmv7" + conan_remotes: https://conan.privatehive.de/artifactory/api/conan/public-conan + + build_android_armv8: + name: "Android" + uses: Privatehive/conan-workflows/.github/workflows/createPackageGcpRunner.yml@master + with: + docker_image: "ghcr.io/privatehive/conan-ubuntu:latest" + machine_type: c2d-standard-8 + conan_host_profile: "androidArmv8" + conan_remotes: https://conan.privatehive.de/artifactory/api/conan/public-conan + + upload_recipe: + name: "Finalize" + uses: Privatehive/conan-workflows/.github/workflows/uploadRecipe.yml@master + needs: [ build_linux_x86_64, build_windows_x86_64, build_macos_armv8, build_android_x86, build_android_x86_64, build_android_armv7, build_android_armv8 ] + if: ${{ success() }} + secrets: inherit + with: + publish_property: ${{ github.ref == 'refs/heads/master' }} + conan_upload_remote: https://conan.privatehive.de/artifactory/api/conan/public-conan diff --git a/.gitignore b/.gitignore index c128d34..c2119f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +CMakeUserPresets.json +build-* +.idea # Created by https://www.toptal.com/developers/gitignore/api/vscode,clion,conan,qt # Edit at https://www.toptal.com/developers/gitignore?templates=vscode,clion,conan,qt diff --git a/CMake/JSONParser.cmake b/CMake/JSONParser.cmake deleted file mode 100644 index f26f73c..0000000 --- a/CMake/JSONParser.cmake +++ /dev/null @@ -1,298 +0,0 @@ -cmake_minimum_required(VERSION 3.1) - -if (DEFINED JSonParserGuard) - return() -endif() - -set(JSonParserGuard yes) - -macro(sbeParseJson prefix jsonString) - cmake_policy(PUSH) - - set(json_string "${${jsonString}}") - string(LENGTH "${json_string}" json_jsonLen) - set(json_index 0) - set(json_AllVariables ${prefix}) - set(json_ArrayNestingLevel 0) - set(json_MaxArrayNestingLevel 0) - - _sbeParse(${prefix}) - - unset(json_index) - unset(json_AllVariables) - unset(json_jsonLen) - unset(json_string) - unset(json_value) - unset(json_inValue) - unset(json_name) - unset(json_inName) - unset(json_newPrefix) - unset(json_reservedWord) - unset(json_arrayIndex) - unset(json_char) - unset(json_end) - unset(json_ArrayNestingLevel) - foreach(json_nestingLevel RANGE ${json_MaxArrayNestingLevel}) - unset(json_${json_nestingLevel}_arrayIndex) - endforeach() - unset(json_nestingLevel) - unset(json_MaxArrayNestingLevel) - - cmake_policy(POP) -endmacro() - -macro(sbeClearJson prefix) - foreach(json_var ${${prefix}}) - unset(${json_var}) - endforeach() - - unset(${prefix}) - unset(json_var) -endmacro() - -macro(sbePrintJson prefix) - foreach(json_var ${${prefix}}) - message("${json_var} = ${${json_var}}") - endforeach() -endmacro() - -macro(_sbeParse prefix) - - while(${json_index} LESS ${json_jsonLen}) - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - - if("\"" STREQUAL "${json_char}") - _sbeParseNameValue(${prefix}) - elseif("{" STREQUAL "${json_char}") - _sbeMoveToNextNonEmptyCharacter() - _sbeParseObject(${prefix}) - elseif("[" STREQUAL "${json_char}") - _sbeMoveToNextNonEmptyCharacter() - _sbeParseArray(${prefix}) - endif() - - if(${json_index} LESS ${json_jsonLen}) - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - else() - break() - endif() - - if ("}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}") - break() - endif() - - _sbeMoveToNextNonEmptyCharacter() - endwhile() -endmacro() - -macro(_sbeParseNameValue prefix) - set(json_name "") - set(json_inName no) - - while(${json_index} LESS ${json_jsonLen}) - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - - # check if name ends - if("\"" STREQUAL "${json_char}" AND json_inName) - set(json_inName no) - _sbeMoveToNextNonEmptyCharacter() - if(NOT ${json_index} LESS ${json_jsonLen}) - break() - endif() - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - set(json_newPrefix ${prefix}.${json_name}) - set(json_name "") - - if(":" STREQUAL "${json_char}") - _sbeMoveToNextNonEmptyCharacter() - if(NOT ${json_index} LESS ${json_jsonLen}) - break() - endif() - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - - if("\"" STREQUAL "${json_char}") - _sbeParseValue(${json_newPrefix}) - break() - elseif("{" STREQUAL "${json_char}") - _sbeMoveToNextNonEmptyCharacter() - _sbeParseObject(${json_newPrefix}) - break() - elseif("[" STREQUAL "${json_char}") - _sbeMoveToNextNonEmptyCharacter() - _sbeParseArray(${json_newPrefix}) - break() - else() - # reserved word starts - _sbeParseReservedWord(${json_newPrefix}) - break() - endif() - else() - # name without value - list(APPEND ${json_AllVariables} ${json_newPrefix}) - set(${json_newPrefix} "") - break() - endif() - endif() - - if(json_inName) - # remove escapes - if("\\" STREQUAL "${json_char}") - math(EXPR json_index "${json_index} + 1") - if(NOT ${json_index} LESS ${json_jsonLen}) - break() - endif() - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - endif() - - set(json_name "${json_name}${json_char}") - endif() - - # check if name starts - if("\"" STREQUAL "${json_char}" AND NOT json_inName) - set(json_inName yes) - endif() - - _sbeMoveToNextNonEmptyCharacter() - endwhile() -endmacro() - -macro(_sbeParseReservedWord prefix) - set(json_reservedWord "") - set(json_end no) - while(${json_index} LESS ${json_jsonLen} AND NOT json_end) - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - - if("," STREQUAL "${json_char}" OR "}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}") - set(json_end yes) - else() - set(json_reservedWord "${json_reservedWord}${json_char}") - math(EXPR json_index "${json_index} + 1") - endif() - endwhile() - - list(APPEND ${json_AllVariables} ${prefix}) - string(STRIP "${json_reservedWord}" json_reservedWord) - set(${prefix} ${json_reservedWord}) -endmacro() - -macro(_sbeParseValue prefix) - cmake_policy(SET CMP0054 NEW) # turn off implicit expansions in if statement - - set(json_value "") - set(json_inValue no) - - while(${json_index} LESS ${json_jsonLen}) - # fast path for copying strings - if (json_inValue) - # attempt to gobble up to 128 bytes of string - string(SUBSTRING "${json_string}" ${json_index} 128 try_gobble) - # consume a piece of string we can just straight copy before encountering \ or " - string(REGEX MATCH "^[^\"\\\\]+" simple_copy "${try_gobble}") - string(CONCAT json_value "${json_value}" "${simple_copy}") - string(LENGTH "${simple_copy}" copy_length) - math(EXPR json_index "${json_index} + ${copy_length}") - endif() - - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - - # check if json_value ends, it is ended by " - if("\"" STREQUAL "${json_char}" AND json_inValue) - set(json_inValue no) - - set(${prefix} ${json_value}) - list(APPEND ${json_AllVariables} ${prefix}) - _sbeMoveToNextNonEmptyCharacter() - break() - endif() - - if(json_inValue) - # if " is escaped consume - if("\\" STREQUAL "${json_char}") - math(EXPR json_index "${json_index} + 1") - if(NOT ${json_index} LESS ${json_jsonLen}) - break() - endif() - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - if(NOT "\"" STREQUAL "${json_char}") - # if it is not " then copy also escape character - set(json_char "\\${json_char}") - endif() - endif() - - _sbeAddEscapedCharacter("${json_char}") - endif() - - # check if value starts - if("\"" STREQUAL "${json_char}" AND NOT json_inValue) - set(json_inValue yes) - endif() - - math(EXPR json_index "${json_index} + 1") - endwhile() -endmacro() - -macro(_sbeAddEscapedCharacter char) - string(CONCAT json_value "${json_value}" "${char}") -endmacro() - -macro(_sbeParseObject prefix) - _sbeParse(${prefix}) - _sbeMoveToNextNonEmptyCharacter() -endmacro() - -macro(_sbeParseArray prefix) - math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} + 1") - set(json_${json_ArrayNestingLevel}_arrayIndex 0) - - set(${prefix} "") - list(APPEND ${json_AllVariables} ${prefix}) - - while(${json_index} LESS ${json_jsonLen}) - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - - if("\"" STREQUAL "${json_char}") - # simple value - list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) - _sbeParseValue(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) - elseif("{" STREQUAL "${json_char}") - # object - _sbeMoveToNextNonEmptyCharacter() - list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) - _sbeParseObject(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) - else() - list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex}) - _sbeParseReservedWord(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex}) - endif() - - if(NOT ${json_index} LESS ${json_jsonLen}) - break() - endif() - - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - - if("]" STREQUAL "${json_char}") - _sbeMoveToNextNonEmptyCharacter() - break() - elseif("," STREQUAL "${json_char}") - math(EXPR json_${json_ArrayNestingLevel}_arrayIndex "${json_${json_ArrayNestingLevel}_arrayIndex} + 1") - endif() - - _sbeMoveToNextNonEmptyCharacter() - endwhile() - - if(${json_MaxArrayNestingLevel} LESS ${json_ArrayNestingLevel}) - set(json_MaxArrayNestingLevel ${json_ArrayNestingLevel}) - endif() - math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} - 1") -endmacro() - -macro(_sbeMoveToNextNonEmptyCharacter) - math(EXPR json_index "${json_index} + 1") - if(${json_index} LESS ${json_jsonLen}) - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - while(${json_char} MATCHES "[ \t\n\r]" AND ${json_index} LESS ${json_jsonLen}) - math(EXPR json_index "${json_index} + 1") - string(SUBSTRING "${json_string}" ${json_index} 1 json_char) - endwhile() - endif() -endmacro() diff --git a/CMake/cotire.cmake b/CMake/cotire.cmake deleted file mode 100644 index 948ac15..0000000 --- a/CMake/cotire.cmake +++ /dev/null @@ -1,4212 +0,0 @@ -# - cotire (compile time reducer) -# -# See the cotire manual for usage hints. -# -#============================================================================= -# Copyright 2012-2018 Sascha Kratky -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -#============================================================================= - -if(__COTIRE_INCLUDED) - return() -endif() -set(__COTIRE_INCLUDED TRUE) - -# call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode -# cmake_minimum_required also sets the policy version as a side effect, which we have to avoid -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(PUSH) -endif() -cmake_minimum_required(VERSION 2.8.12) -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(POP) -endif() - -set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") -set (COTIRE_CMAKE_MODULE_VERSION "1.8.1") - -# activate select policies -if (POLICY CMP0025) - # Compiler id for Apple Clang is now AppleClang - cmake_policy(SET CMP0025 NEW) -endif() - -if (POLICY CMP0026) - # disallow use of the LOCATION target property - cmake_policy(SET CMP0026 NEW) -endif() - -if (POLICY CMP0038) - # targets may not link directly to themselves - cmake_policy(SET CMP0038 NEW) -endif() - -if (POLICY CMP0039) - # utility targets may not have link dependencies - cmake_policy(SET CMP0039 NEW) -endif() - -if (POLICY CMP0040) - # target in the TARGET signature of add_custom_command() must exist - cmake_policy(SET CMP0040 NEW) -endif() - -if (POLICY CMP0045) - # error on non-existent target in get_target_property - cmake_policy(SET CMP0045 NEW) -endif() - -if (POLICY CMP0046) - # error on non-existent dependency in add_dependencies - cmake_policy(SET CMP0046 NEW) -endif() - -if (POLICY CMP0049) - # do not expand variables in target source entries - cmake_policy(SET CMP0049 NEW) -endif() - -if (POLICY CMP0050) - # disallow add_custom_command SOURCE signatures - cmake_policy(SET CMP0050 NEW) -endif() - -if (POLICY CMP0051) - # include TARGET_OBJECTS expressions in a target's SOURCES property - cmake_policy(SET CMP0051 NEW) -endif() - -if (POLICY CMP0053) - # simplify variable reference and escape sequence evaluation - cmake_policy(SET CMP0053 NEW) -endif() - -if (POLICY CMP0054) - # only interpret if() arguments as variables or keywords when unquoted - cmake_policy(SET CMP0054 NEW) -endif() - -if (POLICY CMP0055) - # strict checking for break() command - cmake_policy(SET CMP0055 NEW) -endif() - -include(CMakeParseArguments) -include(ProcessorCount) - -function (cotire_get_configuration_types _configsVar) - set (_configs "") - if (CMAKE_CONFIGURATION_TYPES) - list (APPEND _configs ${CMAKE_CONFIGURATION_TYPES}) - endif() - if (CMAKE_BUILD_TYPE) - list (APPEND _configs "${CMAKE_BUILD_TYPE}") - endif() - if (_configs) - list (REMOVE_DUPLICATES _configs) - set (${_configsVar} ${_configs} PARENT_SCOPE) - else() - set (${_configsVar} "None" PARENT_SCOPE) - endif() -endfunction() - -function (cotire_get_source_file_extension _sourceFile _extVar) - # get_filename_component returns extension from first occurrence of . in file name - # this function computes the extension from last occurrence of . in file name - string (FIND "${_sourceFile}" "." _index REVERSE) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) - else() - set (_sourceExt "") - endif() - set (${_extVar} "${_sourceExt}" PARENT_SCOPE) -endfunction() - -macro (cotire_check_is_path_relative_to _path _isRelativeVar) - set (${_isRelativeVar} FALSE) - if (IS_ABSOLUTE "${_path}") - foreach (_dir ${ARGN}) - file (RELATIVE_PATH _relPath "${_dir}" "${_path}") - if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) - set (${_isRelativeVar} TRUE) - break() - endif() - endforeach() - endif() -endmacro() - -function (cotire_filter_language_source_files _language _target _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) - if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") - else() - set (_languageExtensions "") - endif() - if (CMAKE_${_language}_IGNORE_EXTENSIONS) - set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") - else() - set (_ignoreExtensions "") - endif() - if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS) - set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}") - else() - set (_excludeExtensions "") - endif() - if (COTIRE_DEBUG AND _languageExtensions) - message (STATUS "${_language} source file extensions: ${_languageExtensions}") - endif() - if (COTIRE_DEBUG AND _ignoreExtensions) - message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") - endif() - if (COTIRE_DEBUG AND _excludeExtensions) - message (STATUS "${_language} exclude extensions: ${_excludeExtensions}") - endif() - if (CMAKE_VERSION VERSION_LESS "3.1.0") - set (_allSourceFiles ${ARGN}) - else() - # as of CMake 3.1 target sources may contain generator expressions - # since we cannot obtain required property information about source files added - # through generator expressions at configure time, we filter them out - string (GENEX_STRIP "${ARGN}" _allSourceFiles) - endif() - set (_filteredSourceFiles "") - set (_excludedSourceFiles "") - foreach (_sourceFile ${_allSourceFiles}) - get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) - get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) - get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) - if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) - cotire_get_source_file_extension("${_sourceFile}" _sourceExt) - if (_sourceExt) - list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) - if (_ignoreIndex LESS 0) - list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex) - if (_excludeIndex GREATER -1) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) - if (_sourceIndex GREATER -1) - # consider source file unless it is excluded explicitly - get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) - if (_sourceIsExcluded) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (APPEND _filteredSourceFiles "${_sourceFile}") - endif() - else() - get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) - if ("${_sourceLanguage}" STREQUAL "${_language}") - # add to excluded sources, if file is not ignored and has correct language without having the correct extension - list (APPEND _excludedSourceFiles "${_sourceFile}") - endif() - endif() - endif() - endif() - endif() - endif() - endforeach() - # separate filtered source files from already cotired ones - # the COTIRE_TARGET property of a source file may be set while a target is being processed by cotire - set (_sourceFiles "") - set (_cotiredSourceFiles "") - foreach (_sourceFile ${_filteredSourceFiles}) - get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) - if (_sourceIsCotired) - list (APPEND _cotiredSourceFiles "${_sourceFile}") - else() - get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) - if (_sourceCompileFlags) - # add to excluded sources, if file has custom compile flags - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - get_source_file_property(_sourceCompileOptions "${_sourceFile}" COMPILE_OPTIONS) - if (_sourceCompileOptions) - # add to excluded sources, if file has list of custom compile options - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (APPEND _sourceFiles "${_sourceFile}") - endif() - endif() - endif() - endforeach() - if (COTIRE_DEBUG) - if (_sourceFiles) - message (STATUS "Filtered ${_target} ${_language} sources: ${_sourceFiles}") - endif() - if (_excludedSourceFiles) - message (STATUS "Excluded ${_target} ${_language} sources: ${_excludedSourceFiles}") - endif() - if (_cotiredSourceFiles) - message (STATUS "Cotired ${_target} ${_language} sources: ${_cotiredSourceFiles}") - endif() - endif() - set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) - set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) - set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (NOT _propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_file_property_values _valuesVar _property) - set (_values "") - foreach (_sourceFile ${ARGN}) - get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) - if (_propertyValue) - list (APPEND _values "${_propertyValue}") - endif() - endforeach() - set (${_valuesVar} ${_values} PARENT_SCOPE) -endfunction() - -function (cotire_resolve_config_properties _configurations _propertiesVar) - set (_properties "") - foreach (_property ${ARGN}) - if ("${_property}" MATCHES "") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") - list (APPEND _properties ${_configProperty}) - endforeach() - else() - list (APPEND _properties ${_property}) - endif() - endforeach() - set (${_propertiesVar} ${_properties} PARENT_SCOPE) -endfunction() - -function (cotire_copy_set_properties _configurations _type _source _target) - cotire_resolve_config_properties("${_configurations}" _properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) - set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") - endif() - endforeach() -endfunction() - -function (cotire_get_target_usage_requirements _target _config _targetRequirementsVar) - set (_targetRequirements "") - get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES) - while (_librariesToProcess) - # remove from head - list (GET _librariesToProcess 0 _library) - list (REMOVE_AT _librariesToProcess 0) - if (_library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") - set (_library "${CMAKE_MATCH_1}") - elseif (_config STREQUAL "None" AND _library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") - set (_library "${CMAKE_MATCH_1}") - endif() - if (TARGET ${_library}) - list (FIND _targetRequirements ${_library} _index) - if (_index LESS 0) - list (APPEND _targetRequirements ${_library}) - # BFS traversal of transitive libraries - get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES) - if (_libraries) - list (APPEND _librariesToProcess ${_libraries}) - list (REMOVE_DUPLICATES _librariesToProcess) - endif() - endif() - endif() - endwhile() - set (${_targetRequirementsVar} ${_targetRequirements} PARENT_SCOPE) -endfunction() - -function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - set (_flagPrefix "[/-]") - else() - set (_flagPrefix "--?") - endif() - set (_optionFlag "") - set (_matchedOptions "") - set (_unmatchedOptions "") - foreach (_compileFlag ${ARGN}) - if (_compileFlag) - if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") - # option with separate argument - list (APPEND _matchedOptions "${_compileFlag}") - set (_optionFlag "") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") - # remember option - set (_optionFlag "${CMAKE_MATCH_2}") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") - # option with joined argument - list (APPEND _matchedOptions "${CMAKE_MATCH_3}") - set (_optionFlag "") - else() - # flush remembered option - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - set (_optionFlag "") - endif() - # add to unfiltered options - list (APPEND _unmatchedOptions "${_compileFlag}") - endif() - endif() - endforeach() - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - endif() - if (COTIRE_DEBUG AND _matchedOptions) - message (STATUS "Filter ${_flagFilter} matched: ${_matchedOptions}") - endif() - if (COTIRE_DEBUG AND _unmatchedOptions) - message (STATUS "Filter ${_flagFilter} unmatched: ${_unmatchedOptions}") - endif() - set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) - set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) -endfunction() - -function (cotire_is_target_supported _target _isSupportedVar) - if (NOT TARGET "${_target}") - set (${_isSupportedVar} FALSE PARENT_SCOPE) - return() - endif() - get_target_property(_imported ${_target} IMPORTED) - if (_imported) - set (${_isSupportedVar} FALSE PARENT_SCOPE) - return() - endif() - get_target_property(_targetType ${_target} TYPE) - if (NOT _targetType MATCHES "EXECUTABLE|(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - set (${_isSupportedVar} FALSE PARENT_SCOPE) - return() - endif() - set (${_isSupportedVar} TRUE PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_flags _config _language _target _flagsVar) - string (TOUPPER "${_config}" _upperConfig) - # collect options from CMake language variables - set (_compileFlags "") - if (CMAKE_${_language}_FLAGS) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") - endif() - if (CMAKE_${_language}_FLAGS_${_upperConfig}) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") - endif() - if (_target) - # add target compile flags - get_target_property(_targetflags ${_target} COMPILE_FLAGS) - if (_targetflags) - set (_compileFlags "${_compileFlags} ${_targetflags}") - endif() - endif() - if (UNIX) - separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") - elseif(WIN32) - separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") - else() - separate_arguments(_compileFlags) - endif() - # target compile options - if (_target) - get_target_property(_targetOptions ${_target} COMPILE_OPTIONS) - if (_targetOptions) - list (APPEND _compileFlags ${_targetOptions}) - endif() - endif() - # interface compile options from linked library targets - if (_target) - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_targetOptions ${_linkedTarget} INTERFACE_COMPILE_OPTIONS) - if (_targetOptions) - list (APPEND _compileFlags ${_targetOptions}) - endif() - endforeach() - endif() - # handle language standard properties - if (CMAKE_${_language}_STANDARD_DEFAULT) - # used compiler supports language standard levels - if (_target) - get_target_property(_targetLanguageStandard ${_target} ${_language}_STANDARD) - if (_targetLanguageStandard) - set (_type "EXTENSION") - get_property(_isSet TARGET ${_target} PROPERTY ${_language}_EXTENSIONS SET) - if (_isSet) - get_target_property(_targetUseLanguageExtensions ${_target} ${_language}_EXTENSIONS) - if (NOT _targetUseLanguageExtensions) - set (_type "STANDARD") - endif() - endif() - if (CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION) - list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION}") - endif() - endif() - endif() - endif() - # handle the POSITION_INDEPENDENT_CODE target property - if (_target) - get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE) - if (_targetPIC) - get_target_property(_targetType ${_target} TYPE) - if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIE}") - elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIC}") - endif() - endif() - endif() - # handle visibility target properties - if (_target) - get_target_property(_targetVisibility ${_target} ${_language}_VISIBILITY_PRESET) - if (_targetVisibility AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY}${_targetVisibility}") - endif() - get_target_property(_targetVisibilityInlines ${_target} VISIBILITY_INLINES_HIDDEN) - if (_targetVisibilityInlines AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN}") - endif() - endif() - # platform specific flags - if (APPLE) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) - if (NOT _architectures) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES) - endif() - if (_architectures) - foreach (_arch ${_architectures}) - list (APPEND _compileFlags "-arch" "${_arch}") - endforeach() - endif() - if (CMAKE_OSX_SYSROOT) - if (CMAKE_${_language}_SYSROOT_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}") - else() - list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") - endif() - endif() - if (CMAKE_OSX_DEPLOYMENT_TARGET) - if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") - else() - list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - endif() - endif() - endif() - if (COTIRE_DEBUG AND _compileFlags) - message (STATUS "Target ${_target} compile flags: ${_compileFlags}") - endif() - set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_include_directories _config _language _target _includeDirsVar _systemIncludeDirsVar) - set (_includeDirs "") - set (_systemIncludeDirs "") - # default include dirs - if (CMAKE_INCLUDE_CURRENT_DIR) - list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}") - list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}") - endif() - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - # parse additional include directories from target compile flags - if (CMAKE_INCLUDE_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_dirs "") - cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) - if (_dirs) - list (APPEND _includeDirs ${_dirs}) - endif() - endif() - endif() - # parse additional system include directories from target compile flags - if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_dirs "") - cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) - if (_dirs) - list (APPEND _systemIncludeDirs ${_dirs}) - endif() - endif() - endif() - # target include directories - get_directory_property(_dirs DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" INCLUDE_DIRECTORIES) - if (_target) - get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - endif() - # interface include directories from linked library targets - if (_target) - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_linkedTargetType ${_linkedTarget} TYPE) - if (CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE AND NOT CMAKE_VERSION VERSION_LESS "3.4.0" AND - _linkedTargetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - # CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE refers to CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR - # at the time, when the target was created. These correspond to the target properties BINARY_DIR and SOURCE_DIR - # which are only available with CMake 3.4 or later. - get_target_property(_targetDirs ${_linkedTarget} BINARY_DIR) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_linkedTarget} SOURCE_DIR) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - endif() - get_target_property(_targetDirs ${_linkedTarget} INTERFACE_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_linkedTarget} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - endforeach() - endif() - if (dirs) - list (REMOVE_DUPLICATES _dirs) - endif() - list (LENGTH _includeDirs _projectInsertIndex) - foreach (_dir ${_dirs}) - if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) - cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") - if (_isRelative) - list (LENGTH _includeDirs _len) - if (_len EQUAL _projectInsertIndex) - list (APPEND _includeDirs "${_dir}") - else() - list (INSERT _includeDirs _projectInsertIndex "${_dir}") - endif() - math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") - else() - list (APPEND _includeDirs "${_dir}") - endif() - else() - list (APPEND _includeDirs "${_dir}") - endif() - endforeach() - list (REMOVE_DUPLICATES _includeDirs) - list (REMOVE_DUPLICATES _systemIncludeDirs) - if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) - list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) - endif() - if (WIN32 AND NOT MINGW) - # convert Windows paths in include directories to CMake paths - if (_includeDirs) - set (_paths "") - foreach (_dir ${_includeDirs}) - file (TO_CMAKE_PATH "${_dir}" _path) - list (APPEND _paths "${_path}") - endforeach() - set (_includeDirs ${_paths}) - endif() - if (_systemIncludeDirs) - set (_paths "") - foreach (_dir ${_systemIncludeDirs}) - file (TO_CMAKE_PATH "${_dir}" _path) - list (APPEND _paths "${_path}") - endforeach() - set (_systemIncludeDirs ${_paths}) - endif() - endif() - if (COTIRE_DEBUG AND _includeDirs) - message (STATUS "Target ${_target} include dirs: ${_includeDirs}") - endif() - set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) - if (COTIRE_DEBUG AND _systemIncludeDirs) - message (STATUS "Target ${_target} system include dirs: ${_systemIncludeDirs}") - endif() - set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_export_symbol _target _exportSymbolVar) - set (_exportSymbol "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_enableExports ${_target} ENABLE_EXPORTS) - if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR - (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) - get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) - if (NOT _exportSymbol) - set (_exportSymbol "${_target}_EXPORTS") - endif() - string (MAKE_C_IDENTIFIER "${_exportSymbol}" _exportSymbol) - endif() - set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_definitions _config _language _target _definitionsVar) - string (TOUPPER "${_config}" _upperConfig) - set (_configDefinitions "") - # CMAKE_INTDIR for multi-configuration build systems - if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") - list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") - endif() - # target export define symbol - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - list (APPEND _configDefinitions "${_defineSymbol}") - endif() - # directory compile definitions - get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # target compile definitions - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # interface compile definitions from linked library targets - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_definitions ${_linkedTarget} INTERFACE_COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - endforeach() - # parse additional compile definitions from target compile flags - # and do not look at directory compile definitions, which we already handled - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - list (REMOVE_DUPLICATES _configDefinitions) - if (COTIRE_DEBUG AND _configDefinitions) - message (STATUS "Target ${_target} compile definitions: ${_configDefinitions}") - endif() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compiler_flags _config _language _target _compilerFlagsVar) - # parse target compile flags omitting compile definitions and include directives - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - set (_flagFilter "D") - if (CMAKE_INCLUDE_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_flagFilter "${_flagFilter}|${_includeFlag}") - endif() - endif() - if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_flagFilter "${_flagFilter}|${_includeFlag}") - endif() - endif() - set (_compilerFlags "") - cotire_filter_compile_flags("${_language}" "${_flagFilter}" _ignore _compilerFlags ${_targetFlags}) - if (COTIRE_DEBUG AND _compilerFlags) - message (STATUS "Target ${_target} compiler flags: ${_compilerFlags}") - endif() - set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) -endfunction() - -function (cotire_add_sys_root_paths _pathsVar) - if (APPLE) - if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) - foreach (_path IN LISTS ${_pathsVar}) - if (IS_ABSOLUTE "${_path}") - get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) - if (EXISTS "${_path}") - list (APPEND ${_pathsVar} "${_path}") - endif() - endif() - endforeach() - endif() - endif() - set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) - set (_extraProperties ${ARGN}) - set (_result "") - if (_extraProperties) - list (FIND _extraProperties "${_sourceFile}" _index) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - list (LENGTH _extraProperties _len) - math (EXPR _len "${_len} - 1") - foreach (_index RANGE ${_index} ${_len}) - list (GET _extraProperties ${_index} _value) - if (_value MATCHES "${_pattern}") - list (APPEND _result "${_value}") - else() - break() - endif() - endforeach() - endif() - endif() - set (${_resultVar} ${_result} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) - set (_compileDefinitions "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - string (TOUPPER "${_config}" _upperConfig) - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - if (COTIRE_DEBUG AND _compileDefinitions) - message (STATUS "Source ${_sourceFile} compile definitions: ${_compileDefinitions}") - endif() - set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) - set (_configDefinitions "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) - if (_sourceDefinitions) - list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") - endif() - endforeach() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) - set (_sourceUndefs "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - get_source_file_property(_undefs "${_sourceFile}" ${_property}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - if (COTIRE_DEBUG AND _sourceUndefs) - message (STATUS "Source ${_sourceFile} ${_property} undefs: ${_sourceUndefs}") - endif() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_undefs _property _sourceUndefsVar) - set (_sourceUndefs "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) - if (_undefs) - list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") - endif() - endforeach() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -macro (cotire_set_cmd_to_prologue _cmdVar) - set (${_cmdVar} "${CMAKE_COMMAND}") - if (COTIRE_DEBUG) - list (APPEND ${_cmdVar} "--warn-uninitialized") - endif() - list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") - if (XCODE) - list (APPEND ${_cmdVar} "-DXCODE:BOOL=TRUE") - endif() - if (COTIRE_VERBOSE) - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") - elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") - endif() -endmacro() - -function (cotire_init_compile_cmd _cmdVar _language _compilerLauncher _compilerExe _compilerArg1) - if (NOT _compilerLauncher) - set (_compilerLauncher ${CMAKE_${_language}_COMPILER_LAUNCHER}) - endif() - if (NOT _compilerExe) - set (_compilerExe "${CMAKE_${_language}_COMPILER}") - endif() - if (NOT _compilerArg1) - set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) - endif() - if (WIN32) - file (TO_NATIVE_PATH "${_compilerExe}" _compilerExe) - endif() - string (STRIP "${_compilerArg1}" _compilerArg1) - if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # compiler launcher is only supported for Makefile and Ninja - set (${_cmdVar} ${_compilerLauncher} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) - else() - set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_add_definitions_to_cmd _cmdVar _language) - foreach (_definition ${ARGN}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - list (APPEND ${_cmdVar} "/D${_definition}") - else() - list (APPEND ${_cmdVar} "-D${_definition}") - endif() - endforeach() -endmacro() - -function (cotire_add_includes_to_cmd _cmdVar _language _includesVar _systemIncludesVar) - set (_includeDirs ${${_includesVar}} ${${_systemIncludesVar}}) - if (_includeDirs) - list (REMOVE_DUPLICATES _includeDirs) - foreach (_include ${_includeDirs}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - file (TO_NATIVE_PATH "${_include}" _include) - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") - else() - set (_index -1) - if ("${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" MATCHES ".+") - list (FIND ${_systemIncludesVar} "${_include}" _index) - endif() - if (_index GREATER -1) - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") - else() - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") - endif() - endif() - endforeach() - endif() - set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) -endfunction() - -function (cotire_add_frameworks_to_cmd _cmdVar _language _includesVar _systemIncludesVar) - if (APPLE) - set (_frameworkDirs "") - foreach (_include ${${_includesVar}}) - if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") - get_filename_component(_frameworkDir "${_include}" DIRECTORY) - list (APPEND _frameworkDirs "${_frameworkDir}") - endif() - endforeach() - set (_systemFrameworkDirs "") - foreach (_include ${${_systemIncludesVar}}) - if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") - get_filename_component(_frameworkDir "${_include}" DIRECTORY) - list (APPEND _systemFrameworkDirs "${_frameworkDir}") - endif() - endforeach() - if (_systemFrameworkDirs) - list (APPEND _frameworkDirs ${_systemFrameworkDirs}) - endif() - if (_frameworkDirs) - list (REMOVE_DUPLICATES _frameworkDirs) - foreach (_frameworkDir ${_frameworkDirs}) - set (_index -1) - if ("${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}" MATCHES ".+") - list (FIND _systemFrameworkDirs "${_frameworkDir}" _index) - endif() - if (_index GREATER -1) - list (APPEND ${_cmdVar} "${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") - else() - list (APPEND ${_cmdVar} "${CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") - endif() - endforeach() - endif() - endif() - set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) -endfunction() - -macro (cotire_add_compile_flags_to_cmd _cmdVar) - foreach (_flag ${ARGN}) - list (APPEND ${_cmdVar} "${_flag}") - endforeach() -endmacro() - -function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) - if (EXISTS "${_file}") - set (_triggerFile "") - foreach (_dependencyFile ${ARGN}) - if (EXISTS "${_dependencyFile}") - # IS_NEWER_THAN returns TRUE if both files have the same timestamp - # thus we do the comparison in both directions to exclude ties - if ("${_dependencyFile}" IS_NEWER_THAN "${_file}" AND - NOT "${_file}" IS_NEWER_THAN "${_dependencyFile}") - set (_triggerFile "${_dependencyFile}") - break() - endif() - endif() - endforeach() - if (_triggerFile) - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") - endif() - set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) - else() - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} is up-to-date.") - endif() - set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) - endif() - else() - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} does not exist yet.") - endif() - set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) - set (${_relPathVar} "") - foreach (_includeDir ${_includeDirs}) - if (IS_DIRECTORY "${_includeDir}") - file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") - if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") - string (LENGTH "${${_relPathVar}}" _closestLen) - string (LENGTH "${_relPath}" _relLen) - if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) - set (${_relPathVar} "${_relPath}") - endif() - endif() - elseif ("${_includeDir}" STREQUAL "${_headerFile}") - # if path matches exactly, return short non-empty string - set (${_relPathVar} "1") - break() - endif() - endforeach() -endmacro() - -macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside) - # check header path against ignored and honored include directories - cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath) - if (_insideRelPath) - # header is inside, but could be become outside if there is a shorter outside match - cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath) - if (_outsideRelPath) - string (LENGTH "${_insideRelPath}" _insideRelPathLen) - string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) - if (_outsideRelPathLen LESS _insideRelPathLen) - set (${_headerIsInside} FALSE) - else() - set (${_headerIsInside} TRUE) - endif() - else() - set (${_headerIsInside} TRUE) - endif() - else() - # header is outside - set (${_headerIsInside} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) - if (NOT EXISTS "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif (IS_DIRECTORY "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed") - # heuristic: ignore headers with embedded parent directory references or "-fixed" or "_fixed" in path - # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation - # with the error message "error: no include path in which to search for header" - set (${_headerIsIgnoredVar} TRUE) - else() - set (${_headerIsIgnoredVar} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) - # check header file extension - cotire_get_source_file_extension("${_headerFile}" _headerFileExt) - set (${_headerIsIgnoredVar} FALSE) - if (_headerFileExt) - list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) - if (_index GREATER -1) - set (${_headerIsIgnoredVar} TRUE) - endif() - endif() -endmacro() - -macro (cotire_parse_line _line _headerFileVar _headerDepthVar) - if (MSVC) - # cl.exe /showIncludes produces different output, depending on the language pack used, e.g.: - # English: "Note: including file: C:\directory\file" - # German: "Hinweis: Einlesen der Datei: C:\directory\file" - # We use a very general regular expression, relying on the presence of the : characters - if (_line MATCHES "( +)([a-zA-Z]:[^:]+)$") - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - else() - if (_line MATCHES "^(\\.+) (.*)$") - # GCC like output - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - if (IS_ABSOLUTE "${CMAKE_MATCH_2}") - set (${_headerFileVar} "${CMAKE_MATCH_2}") - else() - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) - endif() - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - endif() -endmacro() - -function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) - if (WIN32) - # prevent CMake macro invocation errors due to backslash characters in Windows paths - string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") - endif() - # canonize slashes - string (REPLACE "//" "/" _scanOutput "${_scanOutput}") - # prevent semicolon from being interpreted as a line separator - string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") - # then separate lines - string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") - list (LENGTH _scanOutput _len) - # remove duplicate lines to speed up parsing - list (REMOVE_DUPLICATES _scanOutput) - list (LENGTH _scanOutput _uniqueLen) - if (COTIRE_VERBOSE OR COTIRE_DEBUG) - message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") - if (_ignoredExtensions) - message (STATUS "Ignored extensions: ${_ignoredExtensions}") - endif() - if (_ignoredIncludeDirs) - message (STATUS "Ignored paths: ${_ignoredIncludeDirs}") - endif() - if (_honoredIncludeDirs) - message (STATUS "Included paths: ${_honoredIncludeDirs}") - endif() - endif() - set (_sourceFiles ${ARGN}) - set (_selectedIncludes "") - set (_unparsedLines "") - # stack keeps track of inside/outside project status of processed header files - set (_headerIsInsideStack "") - foreach (_line IN LISTS _scanOutput) - if (_line) - cotire_parse_line("${_line}" _headerFile _headerDepth) - if (_headerFile) - cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside) - if (COTIRE_DEBUG) - message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") - endif() - # update stack - list (LENGTH _headerIsInsideStack _stackLen) - if (_headerDepth GREATER _stackLen) - math (EXPR _stackLen "${_stackLen} + 1") - foreach (_index RANGE ${_stackLen} ${_headerDepth}) - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endforeach() - else() - foreach (_index RANGE ${_headerDepth} ${_stackLen}) - list (REMOVE_AT _headerIsInsideStack -1) - endforeach() - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerIsInsideStack}") - endif() - # header is a candidate if it is outside project - if (NOT _headerIsInside) - # get parent header file's inside/outside status - if (_headerDepth GREATER 1) - math (EXPR _index "${_headerDepth} - 2") - list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) - else() - set (_parentHeaderIsInside TRUE) - endif() - # select header file if parent header file is inside project - # (e.g., a project header file that includes a standard header file) - if (_parentHeaderIsInside) - cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) - if (NOT _headerIsIgnored) - cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) - if (NOT _headerIsIgnored) - list (APPEND _selectedIncludes "${_headerFile}") - else() - # fix header's inside status on stack, it is ignored by extension now - list (REMOVE_AT _headerIsInsideStack -1) - list (APPEND _headerIsInsideStack TRUE) - endif() - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") - endif() - endif() - endif() - else() - if (MSVC) - # for cl.exe do not keep unparsed lines which solely consist of a source file name - string (FIND "${_sourceFiles}" "${_line}" _index) - if (_index LESS 0) - list (APPEND _unparsedLines "${_line}") - endif() - else() - list (APPEND _unparsedLines "${_line}") - endif() - endif() - endif() - endforeach() - list (REMOVE_DUPLICATES _selectedIncludes) - set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) - set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) -endfunction() - -function (cotire_scan_includes _includesVar) - set(_options "") - set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_VERSION LANGUAGE UNPARSED_LINES SCAN_RESULT) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES - IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) - # only consider existing source files for scanning - set (_existingSourceFiles "") - foreach (_sourceFile ${_sourceFiles}) - if (EXISTS "${_sourceFile}") - list (APPEND _existingSourceFiles "${_sourceFile}") - endif() - endforeach() - if (NOT _existingSourceFiles) - set (${_includesVar} "" PARENT_SCOPE) - return() - endif() - # add source files to be scanned - if (WIN32) - foreach (_sourceFile ${_existingSourceFiles}) - file (TO_NATIVE_PATH "${_sourceFile}" _sourceFileNative) - list (APPEND _cmd "${_sourceFileNative}") - endforeach() - else() - list (APPEND _cmd ${_existingSourceFiles}) - endif() - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - endif() - execute_process( - COMMAND ${_cmd} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result - OUTPUT_QUIET - ERROR_VARIABLE _output) - if (_result) - message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.") - endif() - cotire_parse_includes( - "${_option_LANGUAGE}" "${_output}" - "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" - "${_option_IGNORE_EXTENSIONS}" - _includes _unparsedLines - ${_sourceFiles}) - if (_option_INCLUDE_PRIORITY_PATH) - set (_sortedIncludes "") - foreach (_priorityPath ${_option_INCLUDE_PRIORITY_PATH}) - foreach (_include ${_includes}) - string (FIND ${_include} ${_priorityPath} _position) - if (_position GREATER -1) - list (APPEND _sortedIncludes ${_include}) - endif() - endforeach() - endforeach() - if (_sortedIncludes) - list (INSERT _includes 0 ${_sortedIncludes}) - list (REMOVE_DUPLICATES _includes) - endif() - endif() - set (${_includesVar} ${_includes} PARENT_SCOPE) - if (_option_UNPARSED_LINES) - set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) - endif() - if (_option_SCAN_RESULT) - set (${_option_SCAN_RESULT} ${_result} PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_append_undefs _contentsVar) - set (_undefs ${ARGN}) - if (_undefs) - list (REMOVE_DUPLICATES _undefs) - foreach (_definition ${_undefs}) - list (APPEND ${_contentsVar} "#undef ${_definition}") - endforeach() - endif() -endmacro() - -macro (cotire_comment_str _language _commentText _commentVar) - if ("${_language}" STREQUAL "CMAKE") - set (${_commentVar} "# ${_commentText}") - else() - set (${_commentVar} "/* ${_commentText} */") - endif() -endmacro() - -function (cotire_write_file _language _file _contents _force) - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) - cotire_comment_str("${_language}" "${_file}" _header2) - set (_contents "${_header1}\n${_header2}\n${_contents}") - if (COTIRE_DEBUG) - message (STATUS "${_contents}") - endif() - if (_force OR NOT EXISTS "${_file}") - file (WRITE "${_file}" "${_contents}") - else() - file (READ "${_file}" _oldContents) - if (NOT "${_oldContents}" STREQUAL "${_contents}") - file (WRITE "${_file}" "${_contents}") - else() - if (COTIRE_DEBUG) - message (STATUS "${_file} unchanged") - endif() - endif() - endif() -endfunction() - -function (cotire_generate_unity_source _unityFile) - set(_options "") - set(_oneValueArgs LANGUAGE) - set(_multiValueArgs - DEPENDS SOURCES_COMPILE_DEFINITIONS - PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (_option_DEPENDS) - cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) - if (_unityFileIsUpToDate) - return() - endif() - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_PRE_UNDEFS) - set (_option_PRE_UNDEFS "") - endif() - if (NOT _option_SOURCES_PRE_UNDEFS) - set (_option_SOURCES_PRE_UNDEFS "") - endif() - if (NOT _option_POST_UNDEFS) - set (_option_POST_UNDEFS "") - endif() - if (NOT _option_SOURCES_POST_UNDEFS) - set (_option_SOURCES_POST_UNDEFS "") - endif() - set (_contents "") - if (_option_PROLOGUE) - list (APPEND _contents ${_option_PROLOGUE}) - endif() - if (_option_LANGUAGE AND _sourceFiles) - if ("${_option_LANGUAGE}" STREQUAL "CXX") - list (APPEND _contents "#ifdef __cplusplus") - elseif ("${_option_LANGUAGE}" STREQUAL "C") - list (APPEND _contents "#ifndef __cplusplus") - endif() - endif() - set (_compileUndefinitions "") - foreach (_sourceFile ${_sourceFiles}) - cotire_get_source_compile_definitions( - "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions - ${_option_SOURCES_COMPILE_DEFINITIONS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) - if (_option_PRE_UNDEFS) - list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) - endif() - if (_sourcePreUndefs) - list (APPEND _compileUndefinitions ${_sourcePreUndefs}) - endif() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_sourcePostUndefs) - list (APPEND _compileUndefinitions ${_sourcePostUndefs}) - endif() - if (_option_POST_UNDEFS) - list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) - endif() - foreach (_definition ${_compileDefinitions}) - if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$") - list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") - list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") - else() - list (APPEND _contents "#define ${_definition}") - list (INSERT _compileUndefinitions 0 "${_definition}") - endif() - endforeach() - # use absolute path as source file location - get_filename_component(_sourceFileLocation "${_sourceFile}" ABSOLUTE) - if (WIN32) - file (TO_NATIVE_PATH "${_sourceFileLocation}" _sourceFileLocation) - endif() - list (APPEND _contents "#include \"${_sourceFileLocation}\"") - endforeach() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_option_LANGUAGE AND _sourceFiles) - list (APPEND _contents "#endif") - endif() - if (_option_EPILOGUE) - list (APPEND _contents ${_option_EPILOGUE}) - endif() - list (APPEND _contents "") - string (REPLACE ";" "\n" _contents "${_contents}") - if (COTIRE_VERBOSE) - message ("${_contents}") - endif() - cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) -endfunction() - -function (cotire_generate_prefix_header _prefixFile) - set(_options "") - set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION) - set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS - INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH - IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - if (_option_DEPENDS) - cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) - if (_prefixFileIsUpToDate) - # create empty log file - set (_unparsedLinesFile "${_prefixFile}.log") - file (WRITE "${_unparsedLinesFile}" "") - return() - endif() - endif() - set (_prologue "") - set (_epilogue "") - if (_option_COMPILER_ID MATCHES "Clang") - set (_prologue "#pragma clang system_header") - elseif (_option_COMPILER_ID MATCHES "GNU") - set (_prologue "#pragma GCC system_header") - elseif (_option_COMPILER_ID MATCHES "MSVC") - set (_prologue "#pragma warning(push, 0)") - set (_epilogue "#pragma warning(pop)") - elseif (_option_COMPILER_ID MATCHES "Intel") - # Intel compiler requires hdrstop pragma to stop generating PCH file - set (_epilogue "#pragma hdrstop") - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - cotire_scan_includes(_selectedHeaders ${_sourceFiles} - LANGUAGE "${_option_LANGUAGE}" - COMPILER_LAUNCHER "${_option_COMPILER_LAUNCHER}" - COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" - COMPILER_ARG1 "${_option_COMPILER_ARG1}" - COMPILER_ID "${_option_COMPILER_ID}" - COMPILER_VERSION "${_option_COMPILER_VERSION}" - COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} - COMPILE_FLAGS ${_option_COMPILE_FLAGS} - INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} - SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES} - IGNORE_PATH ${_option_IGNORE_PATH} - INCLUDE_PATH ${_option_INCLUDE_PATH} - IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} - INCLUDE_PRIORITY_PATH ${_option_INCLUDE_PRIORITY_PATH} - UNPARSED_LINES _unparsedLines - SCAN_RESULT _scanResult) - cotire_generate_unity_source("${_prefixFile}" - PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) - set (_unparsedLinesFile "${_prefixFile}.log") - if (_unparsedLines) - if (COTIRE_VERBOSE OR _scanResult OR NOT _selectedHeaders) - list (LENGTH _unparsedLines _skippedLineCount) - if (WIN32) - file (TO_NATIVE_PATH "${_unparsedLinesFile}" _unparsedLinesLogPath) - else() - set (_unparsedLinesLogPath "${_unparsedLinesFile}") - endif() - message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesLogPath}") - endif() - string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") - endif() - file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}\n") -endfunction() - -function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - # cl.exe options used - # /nologo suppresses display of sign-on banner - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /EP preprocess to stdout without #line directives - # /showIncludes list include files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /showIncludes") - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -H print the name of each header file used - # -E invoke preprocessor - # -fdirectives-only do not expand macros, requires GCC >= 4.3 - if (_flags) - # append to list - list (APPEND _flags -H -E) - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - list (APPEND _flags -fdirectives-only) - endif() - else() - # return as a flag string - set (_flags "-H -E") - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - set (_flags "${_flags} -fdirectives-only") - endif() - endif() - elseif (_compilerID MATCHES "Clang") - if (UNIX) - # Clang options used - # -H print the name of each header file used - # -E invoke preprocessor - # -fno-color-diagnostics do not print diagnostics in color - # -Eonly just run preprocessor, no output - if (_flags) - # append to list - list (APPEND _flags -H -E -fno-color-diagnostics -Xclang -Eonly) - else() - # return as a flag string - set (_flags "-H -E -fno-color-diagnostics -Xclang -Eonly") - endif() - elseif (WIN32) - # Clang-cl.exe options used - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /EP preprocess to stdout without #line directives - # -H print the name of each header file used - # -fno-color-diagnostics do not print diagnostics in color - # -Eonly just run preprocessor, no output - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags "${_sourceFileType${_language}}" /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly") - endif() - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - # Windows Intel options used - # /nologo do not display compiler version information - # /QH display the include file order - # /EP preprocess to stdout, omitting #line directives - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /QH") - endif() - else() - # Linux / Mac OS X Intel options used - # -H print the name of each header file used - # -EP preprocess to stdout, omitting #line directives - # -Kc++ process all source or unrecognized file types as C++ source files - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags -H -EP) - else() - # return as a flag string - if ("${_language}" STREQUAL "CXX") - set (_flags "-Kc++ ") - endif() - set (_flags "${_flags}-H -EP") - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # cl.exe options used - # /Yc creates a precompiled header file - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /Zs syntax check only - # /Zm precompiled header memory allocation scaling factor - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - else() - # return as a flag string - set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -x specify the source language - # -c compile but do not link - # -o place output in file - # note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may - # alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") - else() - # return as a flag string - set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") - endif() - elseif (_compilerID MATCHES "Clang") - if (UNIX) - # Clang options used - # -x specify the source language - # -c compile but do not link - # -o place output in file - # -fno-pch-timestamp disable inclusion of timestamp in precompiled headers (clang 4.0.0+) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") - if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") - list (APPEND _flags -Xclang -fno-pch-timestamp) - endif() - else() - # return as a flag string - set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") - set (_flags "${_flags} -Xclang -fno-pch-timestamp") - endif() - endif() - elseif (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # Clang-cl.exe options used - # /Yc creates a precompiled header file - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /Zs syntax check only - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags "${_sourceFileType${_language}}" - "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - else() - # return as a flag string - set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - endif() - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # Windows Intel options used - # /nologo do not display compiler version information - # /Yc create a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - # /Zs syntax check only - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-create name of the precompiled header (PCH) to create - # -Kc++ process all source or unrecognized file types as C++ source files - # -fsyntax-only check only for correct syntax - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - get_filename_component(_pchDir "${_pchFile}" DIRECTORY) - get_filename_component(_pchName "${_pchFile}" NAME) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - set (_pchSuppressMessages FALSE) - if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") - set(_pchSuppressMessages TRUE) - endif() - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-create "${_pchName}" -fsyntax-only "${_hostFile}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - list (APPEND _flags -Wpch-messages) - endif() - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # cl.exe options used - # /Yu uses a precompiled header file during build - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /Zm precompiled header memory allocation scaling factor - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - else() - # return as a flag string - set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -include process include file as the first line of the primary source file - # -Winvalid-pch warns if precompiled header is found but cannot be used - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags -Winvalid-pch -include "${_prefixFile}") - else() - # return as a flag string - set (_flags "-Winvalid-pch -include \"${_prefixFile}\"") - endif() - elseif (_compilerID MATCHES "Clang") - if (UNIX) - # Clang options used - # -include process include file as the first line of the primary source file - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags -include "${_prefixFile}") - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\"") - endif() - elseif (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # Clang-cl.exe options used - # /Yu uses a precompiled header file during build - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # Windows Intel options used - # /Yu use a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-use name of the precompiled header (PCH) to use - # -include process include file as the first line of the primary source file - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - get_filename_component(_pchDir "${_pchFile}" DIRECTORY) - get_filename_component(_pchName "${_pchFile}" NAME) - set (_pchSuppressMessages FALSE) - if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") - set(_pchSuppressMessages TRUE) - endif() - if (_flags) - # append to list - list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-use "${_pchName}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - list (APPEND _flags -Wpch-messages) - endif() - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags -include "${_prefixFile}") - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\"") - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) - set(_options "") - set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION LANGUAGE) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS COMPILER_LAUNCHER) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_pch_compilation_flags( - "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - elseif (_option_COMPILER_ID MATCHES "Clang" AND _option_COMPILER_VERSION VERSION_LESS "4.0.0") - if (_option_COMPILER_LAUNCHER MATCHES "ccache" OR - _option_COMPILER_EXECUTABLE MATCHES "ccache") - # Newer versions of Clang embed a compilation timestamp into the precompiled header binary, - # which results in "file has been modified since the precompiled header was built" errors if ccache is used. - # We work around the problem by disabling ccache upon pre-compiling the prefix header. - set (ENV{CCACHE_DISABLE} "true") - endif() - endif() - execute_process( - COMMAND ${_cmd} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result) - if (_result) - message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.") - endif() -endfunction() - -function (cotire_check_precompiled_header_support _language _target _msgVar) - set (_unsupportedCompiler - "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}") - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # PCH supported since Visual Studio C++ 6.0 - # and CMake does not support an earlier version - set (${_msgVar} "" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC PCH support requires version >= 3.4 - if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - if (UNIX) - # all Unix Clang versions have PCH support - set (${_msgVar} "" PARENT_SCOPE) - elseif (WIN32) - # only clang-cl is supported under Windows - get_filename_component(_compilerName "${CMAKE_${_language}_COMPILER}" NAME_WE) - if (NOT _compilerName MATCHES "cl$") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}. Use clang-cl instead." PARENT_SCOPE) - endif() - endif() - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel PCH support requires version >= 8.0.0 - if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - else() - set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE) - endif() - # check if ccache is used as a compiler launcher - get_target_property(_launcher ${_target} ${_language}_COMPILER_LAUNCHER) - get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" REALPATH) - if (_realCompilerExe MATCHES "ccache" OR _launcher MATCHES "ccache") - # verify that ccache configuration is compatible with precompiled headers - # always check environment variable CCACHE_SLOPPINESS, because earlier versions of ccache - # do not report the "sloppiness" setting correctly upon printing ccache configuration - if (DEFINED ENV{CCACHE_SLOPPINESS}) - if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "pch_defines" OR - NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros") - set (${_msgVar} - "ccache requires the environment variable CCACHE_SLOPPINESS to be set to \"pch_defines,time_macros\"." - PARENT_SCOPE) - endif() - else() - if (_realCompilerExe MATCHES "ccache") - set (_ccacheExe "${_realCompilerExe}") - else() - set (_ccacheExe "${_launcher}") - endif() - # ccache 3.7.0 replaced --print-config with --show-config - # use -p instead, which seems to work for all version for now, sigh - execute_process( - COMMAND "${_ccacheExe}" "-p" - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - RESULT_VARIABLE _result - OUTPUT_VARIABLE _ccacheConfig OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET) - if (_result) - set (${_msgVar} "ccache configuration cannot be determined." PARENT_SCOPE) - elseif (NOT _ccacheConfig MATCHES "sloppiness.*=.*time_macros" OR - NOT _ccacheConfig MATCHES "sloppiness.*=.*pch_defines") - set (${_msgVar} - "ccache requires configuration setting \"sloppiness\" to be set to \"pch_defines,time_macros\"." - PARENT_SCOPE) - endif() - endif() - endif() - if (APPLE) - # PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64) - cotire_get_configuration_types(_configs) - foreach (_config ${_configs}) - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags}) - list (LENGTH _architectures _numberOfArchitectures) - if (_numberOfArchitectures GREATER 1) - string (REPLACE ";" ", " _architectureStr "${_architectures}") - set (${_msgVar} - "Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})." - PARENT_SCOPE) - break() - endif() - endforeach() - endif() -endfunction() - -macro (cotire_get_intermediate_dir _cotireDir) - # ${CMAKE_CFG_INTDIR} may reference a build-time variable when using a generator which supports configuration types - get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) -endmacro() - -macro (cotire_setup_file_extension_variables) - set (_unityFileExt_C ".c") - set (_unityFileExt_CXX ".cxx") - set (_prefixFileExt_C ".h") - set (_prefixFileExt_CXX ".hxx") - set (_prefixSourceFileExt_C ".c") - set (_prefixSourceFileExt_CXX ".cxx") -endmacro() - -function (cotire_make_single_unity_source_file_path _language _target _unityFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") - cotire_get_intermediate_dir(_baseDir) - set (_unityFile "${_baseDir}/${_unityFileName}") - set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE) -endfunction() - -function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - cotire_get_intermediate_dir(_baseDir) - set (_startIndex 0) - set (_index 0) - set (_unityFiles "") - set (_sourceFiles ${ARGN}) - foreach (_sourceFile ${_sourceFiles}) - get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) - math (EXPR _unityFileCount "${_index} - ${_startIndex}") - if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) - if (_index GREATER 0) - # start new unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (_startIndex ${_index}) - endif() - math (EXPR _index "${_index} + 1") - endforeach() - list (LENGTH _sourceFiles _numberOfSources) - if (_startIndex EQUAL 0) - # there is only a single unity file - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles) - elseif (_startIndex LESS _numberOfSources) - # end with final unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) - if (COTIRE_DEBUG AND _unityFiles) - message (STATUS "unity files: ${_unityFiles}") - endif() -endfunction() - -function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_prefixFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}") - string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}") - set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE) -endfunction() - -function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _prefixSourceFileExt_${_language}) - set (${_prefixSourceFileVar} "" PARENT_SCOPE) - return() - endif() - string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}") - set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) - cotire_setup_file_extension_variables() - if (NOT _language) - set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") - elseif (DEFINED _prefixFileExt_${_language}) - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") - else() - set (_prefixFileBaseName "") - set (_prefixFileName "") - endif() - set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) - set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_path _language _target _prefixFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_prefixFileVar} "" PARENT_SCOPE) - if (_prefixFileName) - if (NOT _language) - set (_language "C") - endif() - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel|MSVC") - cotire_get_intermediate_dir(_baseDir) - set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) - endif() - endif() -endfunction() - -function (cotire_make_pch_file_path _language _target _pchFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_pchFileVar} "" PARENT_SCOPE) - if (_prefixFileBaseName AND _prefixFileName) - cotire_check_precompiled_header_support("${_language}" "${_target}" _msg) - if (NOT _msg) - if (XCODE) - # For Xcode, we completely hand off the compilation of the prefix header to the IDE - return() - endif() - cotire_get_intermediate_dir(_baseDir) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # MSVC uses the extension .pch added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - # Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel uses the extension .pchi added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - -function (cotire_select_unity_source_files _unityFile _sourcesVar) - set (_sourceFiles ${ARGN}) - if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") - set (_startIndex ${CMAKE_MATCH_1}) - set (_endIndex ${CMAKE_MATCH_2}) - list (LENGTH _sourceFiles _numberOfSources) - if (NOT _startIndex LESS _numberOfSources) - math (EXPR _startIndex "${_numberOfSources} - 1") - endif() - if (NOT _endIndex LESS _numberOfSources) - math (EXPR _endIndex "${_numberOfSources} - 1") - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${_endIndex}) - list (GET _sourceFiles ${_index} _file) - list (APPEND _files "${_file}") - endforeach() - else() - set (_files ${_sourceFiles}) - endif() - set (${_sourcesVar} ${_files} PARENT_SCOPE) -endfunction() - -function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) - set (_dependencySources "") - # depend on target's generated source files - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) - if (_generatedSources) - # but omit all generated source files that have the COTIRE_EXCLUDED property set to true - cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) - if (_excludedGeneratedSources) - list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) - endif() - # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly - cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) - if (_excludedNonDependencySources) - list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) - endif() - if (_generatedSources) - list (APPEND _dependencySources ${_generatedSources}) - endif() - endif() - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} unity source dependencies: ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) - set (_dependencySources "") - # depend on target source files marked with custom COTIRE_DEPENDENCY property - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles}) - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} prefix header dependencies: ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_generate_target_script _language _configurations _target _targetScriptVar _targetConfigScriptVar) - set (_targetSources ${ARGN}) - cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${_targetSources}) - cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${_targetSources}) - # set up variables to be configured - set (COTIRE_TARGET_LANGUAGE "${_language}") - get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) - get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) - get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) - get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) - get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - get_target_property(COTIRE_TARGET_INCLUDE_PRIORITY_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${_targetSources}) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${_targetSources}) - set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - cotire_get_target_include_directories( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}) - cotire_get_target_compile_definitions( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) - cotire_get_target_compiler_flags( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) - cotire_get_source_files_compile_definitions( - "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${_targetSources}) - endforeach() - get_target_property(COTIRE_TARGET_${_language}_COMPILER_LAUNCHER ${_target} ${_language}_COMPILER_LAUNCHER) - # set up COTIRE_TARGET_SOURCES - set (COTIRE_TARGET_SOURCES "") - foreach (_sourceFile ${_targetSources}) - get_source_file_property(_generated "${_sourceFile}" GENERATED) - if (_generated) - # use absolute paths for generated files only, retrieving the LOCATION property is an expensive operation - get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) - list (APPEND COTIRE_TARGET_SOURCES "${_sourceLocation}") - else() - list (APPEND COTIRE_TARGET_SOURCES "${_sourceFile}") - endif() - endforeach() - # copy variable definitions to cotire target script - get_cmake_property(_vars VARIABLES) - string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") - # omit COTIRE_*_INIT variables - string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+_INIT" _initVars "${_matchVars}") - if (_initVars) - list (REMOVE_ITEM _matchVars ${_initVars}) - endif() - # omit COTIRE_VERBOSE which is passed as a CMake define on command line - list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) - set (_contents "") - set (_contentsHasGeneratorExpressions FALSE) - foreach (_var IN LISTS _matchVars ITEMS - XCODE MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES - CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER_VERSION - CMAKE_${_language}_COMPILER_LAUNCHER CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 - CMAKE_INCLUDE_FLAG_${_language} CMAKE_INCLUDE_FLAG_SEP_${_language} - CMAKE_INCLUDE_SYSTEM_FLAG_${_language} - CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG - CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG - CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - if (DEFINED ${_var}) - string (REPLACE "\"" "\\\"" _value "${${_var}}") - set (_contents "${_contents}set (${_var} \"${_value}\")\n") - if (NOT _contentsHasGeneratorExpressions) - if ("${_value}" MATCHES "\\$<.*>") - set (_contentsHasGeneratorExpressions TRUE) - endif() - endif() - endif() - endforeach() - # generate target script file - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") - cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) - if (_contentsHasGeneratorExpressions) - # use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time - set (_configNameOrNoneGeneratorExpression "$<$:None>$<$>:$>") - set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}") - file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}") - else() - set (_targetCotireConfigScript "${_targetCotireScript}") - endif() - set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) - set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE) -endfunction() - -function (cotire_setup_pch_file_compilation _language _target _targetScript _prefixFile _pchFile _hostFile) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - # for MSVC, Intel and Clang-cl, we attach the precompiled header compilation to the host file - # the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion - if (_sourceFiles) - set (_flags "") - cotire_add_pch_compilation_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) - set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - if (COTIRE_DEBUG) - message (STATUS "set_property: SOURCE ${_hostFile} APPEND_STRING COMPILE_FLAGS ${_flags}") - endif() - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") - # make object file generated from host file depend on prefix header - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") - # mark host file as cotired to prevent it from being used in another cotired target - set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generator, we add a custom command to precompile the prefix header - if (_targetScript) - cotire_set_cmd_to_prologue(_cmds) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileLogPath) - else() - file (RELATIVE_PATH _pchFileLogPath "${CMAKE_BINARY_DIR}" "${_pchFile}") - endif() - # make precompiled header compilation depend on the actual compiler executable used to force - # re-compilation when the compiler executable is updated. This prevents "created by a different GCC executable" - # warnings when the precompiled header is included. - get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} ${_realCompilerExe} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") - endif() - set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) - add_custom_command( - OUTPUT "${_pchFile}" - COMMAND ${_cmds} - DEPENDS "${_prefixFile}" "${_realCompilerExe}" - IMPLICIT_DEPENDS ${_language} "${_prefixFile}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Building ${_language} precompiled header ${_pchFileLogPath}" - VERBATIM) - endif() - endif() -endfunction() - -function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile _hostFile) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - # for MSVC, Intel and clang-cl, we include the precompiled header in all but the host file - # the host file does the precompiled header compilation, see cotire_setup_pch_file_compilation - set (_sourceFiles ${ARGN}) - list (LENGTH _sourceFiles _numberOfSourceFiles) - if (_numberOfSourceFiles GREATER 0) - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - set (_flags "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - if (COTIRE_DEBUG) - message (STATUS "set_property: SOURCE ${_sourceFiles} APPEND_STRING COMPILE_FLAGS ${_flags}") - endif() - # make object files generated from source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - set (_sourceFiles ${_hostFile} ${ARGN}) - if (NOT _wholeTarget) - # for makefile based generator, we force the inclusion of the prefix header for a subset - # of the source files, if this is a multi-language target or has excluded files - set (_flags "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - if (COTIRE_DEBUG) - message (STATUS "set_property: SOURCE ${_sourceFiles} APPEND_STRING COMPILE_FLAGS ${_flags}") - endif() - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - endif() - # make object files generated from source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() -endfunction() - -function (cotire_setup_prefix_file_inclusion _language _target _prefixFile) - set (_sourceFiles ${ARGN}) - # force the inclusion of the prefix header for the given source files - set (_flags "") - set (_pchFile "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - if (COTIRE_DEBUG) - message (STATUS "set_property: SOURCE ${_sourceFiles} APPEND_STRING COMPILE_FLAGS ${_flags}") - endif() - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - # make object files generated from source files depend on prefix header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") -endfunction() - -function (cotire_get_first_set_property_value _propertyValueVar _type _object) - set (_properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) - return() - endif() - endforeach() - set (${_propertyValueVar} "" PARENT_SCOPE) -endfunction() - -function (cotire_setup_combine_command _language _targetScript _joinedFile _cmdsVar) - set (_files ${ARGN}) - set (_filesPaths "") - foreach (_file ${_files}) - get_filename_component(_filePath "${_file}" ABSOLUTE) - list (APPEND _filesPaths "${_filePath}") - endforeach() - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine") - if (_targetScript) - list (APPEND _prefixCmd "${_targetScript}") - endif() - list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths}) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") - endif() - set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_joinedFile}" _joinedFileLogPath) - else() - file (RELATIVE_PATH _joinedFileLogPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") - endif() - get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE) - get_filename_component(_joinedFileExt "${_joinedFile}" EXT) - if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$") - set (_comment "Generating ${_language} unity source ${_joinedFileLogPath}") - elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$") - if (_joinedFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_joinedFileLogPath}") - else() - set (_comment "Generating ${_language} prefix header ${_joinedFileLogPath}") - endif() - else() - set (_comment "Generating ${_joinedFileLogPath}") - endif() - add_custom_command( - OUTPUT "${_joinedFile}" - COMMAND ${_prefixCmd} - DEPENDS ${_files} - COMMENT "${_comment}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_target_pch_usage _languages _target _wholeTarget) - if (XCODE) - # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers - set (_prefixFiles "") - foreach (_language ${_languages}) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_prefixFile) - list (APPEND _prefixFiles "${_prefixFile}") - endif() - endforeach() - set (_cmds ${ARGN}) - list (LENGTH _prefixFiles _numberOfPrefixFiles) - if (_numberOfPrefixFiles GREATER 1) - # we also generate a generic, single prefix header which includes all language specific prefix headers - set (_language "") - set (_targetScript "") - cotire_make_prefix_file_path("${_language}" ${_target} _prefixHeader) - cotire_setup_combine_command("${_language}" "${_targetScript}" "${_prefixHeader}" _cmds ${_prefixFiles}) - else() - set (_prefixHeader "${_prefixFiles}") - endif() - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") - endif() - # because CMake PRE_BUILD command does not support dependencies, - # we check dependencies explicity in cotire script mode when the pre-build action is run - add_custom_command( - TARGET "${_target}" - PRE_BUILD ${_cmds} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Updating target ${_target} prefix headers" - VERBATIM) - # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generator, we force inclusion of the prefix header for all target source files - # if this is a single-language target without any excluded files - if (_wholeTarget) - set (_language "${_languages}") - # for MSVC, Intel and clang-cl, precompiled header inclusion is always done on the source file level - # see cotire_setup_pch_file_inclusion - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_prefixFile) - get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) - set (_options COMPILE_OPTIONS) - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _options) - set_property(TARGET ${_target} APPEND PROPERTY ${_options}) - if (COTIRE_DEBUG) - message (STATUS "set_property: TARGET ${_target} APPEND PROPERTY ${_options}") - endif() - endif() - endif() - endif() - endif() -endfunction() - -function (cotire_setup_unity_generation_commands _language _target _targetScript _targetConfigScript _unityFiles _cmdsVar) - set (_dependencySources "") - cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) - foreach (_unityFile ${_unityFiles}) - set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) - # set up compiled unity source dependencies via OBJECT_DEPENDS - # this ensures that missing source files are generated before the unity file is compiled - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}") - endif() - if (_dependencySources) - # the OBJECT_DEPENDS property requires a list of full paths - set (_objectDependsPaths "") - foreach (_sourceFile ${_dependencySources}) - get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) - list (APPEND _objectDependsPaths "${_sourceLocation}") - endforeach() - set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_objectDependsPaths}) - endif() - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # unity file compilation results in potentially huge object file, - # thus use /bigobj by default unter cl.exe and Windows Intel - set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj") - endif() - cotire_set_cmd_to_prologue(_unityCmd) - list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}") - if (CMAKE_VERSION VERSION_LESS "3.1.0") - set (_unityCmdDepends "${_targetScript}") - else() - # CMake 3.1.0 supports generator expressions in arguments to DEPENDS - set (_unityCmdDepends "${_targetConfigScript}") - endif() - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_unityFile}" _unityFileLogPath) - else() - file (RELATIVE_PATH _unityFileLogPath "${CMAKE_BINARY_DIR}" "${_unityFile}") - endif() - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_unityCmdDepends}") - endif() - add_custom_command( - OUTPUT "${_unityFile}" - COMMAND ${_unityCmd} - DEPENDS ${_unityCmdDepends} - COMMENT "Generating ${_language} unity source ${_unityFileLogPath}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) - endforeach() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) - set (_sourceFiles ${ARGN}) - set (_dependencySources "") - cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" ${_unityFiles}) - set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) - # make prefix header generation depend on the actual compiler executable used to force - # re-generation when the compiler executable is updated. This prevents "file not found" - # errors for compiler version specific system header files. - get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources} ${_realCompilerExe}") - endif() - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileLogPath) - else() - file (RELATIVE_PATH _prefixFileLogPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") - endif() - get_filename_component(_prefixFileExt "${_prefixFile}" EXT) - if (_prefixFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_prefixFileLogPath}") - else() - set (_comment "Generating ${_language} prefix header ${_prefixFileLogPath}") - endif() - # prevent pre-processing errors upon generating the prefix header when a target's generated include file does not yet exist - # we do not add a file-level dependency for the target's generated files though, because we only want to depend on their existence - # thus we make the prefix header generation depend on a custom helper target which triggers the generation of the files - set (_preTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}_pre") - if (TARGET ${_preTargetName}) - # custom helper target has already been generated while processing a different language - list (APPEND _dependencySources ${_preTargetName}) - else() - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) - if (_generatedSources) - add_custom_target("${_preTargetName}" DEPENDS ${_generatedSources}) - cotire_init_target("${_preTargetName}") - list (APPEND _dependencySources ${_preTargetName}) - endif() - endif() - add_custom_command( - OUTPUT "${_prefixFile}" "${_prefixFile}.log" - COMMAND ${_prefixCmd} - DEPENDS ${_unityFiles} ${_dependencySources} "${_realCompilerExe}" - COMMENT "${_comment}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_unity_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - cotire_setup_prefix_generation_command( - ${_language} ${_target} "${_targetScript}" - "${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # set up generation of a prefix source file which includes the prefix header - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_provided_command _language _target _targetScript _prefixFile _cmdsVar) - set (_prefixHeaderFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # set up generation of a prefix source file which includes the prefix header - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_init_cotire_target_properties _target) - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") - cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") - if (NOT _isRelative) - set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") - endif() - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY_UNITY") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) - if (NOT _isSet) - if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") - else() - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") - endif() - endif() -endfunction() - -function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - string (REPLACE ";" " " _languagesStr "${_languages}") - math (EXPR _numberOfExcludedFiles "${ARGC} - 4") - if (_numberOfExcludedFiles EQUAL 0) - set (_excludedStr "") - elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4) - string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}") - else() - set (_excludedStr "excluding ${_numberOfExcludedFiles} files") - endif() - set (_targetMsg "") - if (NOT _languages) - set (_targetMsg "Target ${_target} cannot be cotired.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH AND NOT _targetAddSCU) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") - endif() - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetAddSCU) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") - endif() - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - else() - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired.") - endif() - endif() - set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) -endfunction() - -function (cotire_choose_target_languages _target _targetLanguagesVar _wholeTargetVar) - set (_languages ${ARGN}) - set (_allSourceFiles "") - set (_allExcludedSourceFiles "") - set (_allCotiredSourceFiles "") - set (_targetLanguages "") - set (_pchEligibleTargetLanguages "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - set (_disableMsg "") - foreach (_language ${_languages}) - get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) - get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) - if (_prefixHeader OR _unityBuildFile) - message (STATUS "cotire: target ${_target} has already been cotired.") - set (${_targetLanguagesVar} "" PARENT_SCOPE) - return() - endif() - if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$" AND DEFINED CMAKE_${_language}_COMPILER_ID) - if (CMAKE_${_language}_COMPILER_ID) - cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg) - if (_disableMsg) - set (_targetUsePCH FALSE) - endif() - endif() - endif() - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _excludedSources OR _cotiredSources) - list (APPEND _targetLanguages ${_language}) - endif() - if (_sourceFiles) - list (APPEND _allSourceFiles ${_sourceFiles}) - endif() - list (LENGTH _sourceFiles _numberOfSources) - if (NOT _numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - list (APPEND _pchEligibleTargetLanguages ${_language}) - endif() - if (_excludedSources) - list (APPEND _allExcludedSourceFiles ${_excludedSources}) - endif() - if (_cotiredSources) - list (APPEND _allCotiredSourceFiles ${_cotiredSources}) - endif() - endforeach() - set (_targetMsgLevel STATUS) - if (NOT _targetLanguages) - string (REPLACE ";" " or " _languagesStr "${_languages}") - set (_disableMsg "No ${_languagesStr} source files.") - set (_targetUsePCH FALSE) - set (_targetAddSCU FALSE) - endif() - if (_targetUsePCH) - if (_allCotiredSourceFiles) - cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) - list (REMOVE_DUPLICATES _cotireTargets) - string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") - set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") - set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") - set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") - set (_targetMsgLevel SEND_ERROR) - set (_targetUsePCH FALSE) - elseif (NOT _pchEligibleTargetLanguages) - set (_disableMsg "Too few applicable sources.") - set (_targetUsePCH FALSE) - elseif (XCODE AND _allExcludedSourceFiles) - # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target - set (_disableMsg "Exclusion of source files not supported for generator Xcode.") - set (_targetUsePCH FALSE) - elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") - # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target - set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") - set (_targetUsePCH FALSE) - endif() - endif() - if (_targetAddSCU) - # disable unity builds if automatic Qt processing is used - get_target_property(_targetAutoMoc ${_target} AUTOMOC) - get_target_property(_targetAutoUic ${_target} AUTOUIC) - get_target_property(_targetAutoRcc ${_target} AUTORCC) - if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) - if (_disableMsg) - set (_disableMsg "${_disableMsg} Target uses automatic CMake Qt processing.") - else() - set (_disableMsg "Target uses automatic CMake Qt processing.") - endif() - set (_targetAddSCU FALSE) - endif() - endif() - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) - cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) - if (_targetMsg) - if (NOT DEFINED COTIREMSG_${_target}) - set (COTIREMSG_${_target} "") - endif() - if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR - NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") - # cache message to avoid redundant messages on re-configure - set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") - message (${_targetMsgLevel} "${_targetMsg}") - endif() - endif() - list (LENGTH _targetLanguages _numberOfLanguages) - if (_numberOfLanguages GREATER 1 OR _allExcludedSourceFiles) - set (${_wholeTargetVar} FALSE PARENT_SCOPE) - else() - set (${_wholeTargetVar} TRUE PARENT_SCOPE) - endif() - set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) -endfunction() - -function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar) - set (_sourceFiles ${ARGN}) - get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)") - if (DEFINED CMAKE_MATCH_2) - set (_numberOfThreads "${CMAKE_MATCH_2}") - else() - set (_numberOfThreads "") - endif() - if (NOT _numberOfThreads) - # use all available cores - ProcessorCount(_numberOfThreads) - endif() - list (LENGTH _sourceFiles _numberOfSources) - math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}") - elseif (NOT _maxIncludes MATCHES "[0-9]+") - set (_maxIncludes 0) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_target} unity source max includes: ${_maxIncludes}") - endif() - set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE) -endfunction() - -function (cotire_process_target_language _language _configurations _target _wholeTarget _cmdsVar) - set (${_cmdsVar} "" PARENT_SCOPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (NOT _sourceFiles AND NOT _cotiredSources) - return() - endif() - set (_cmds "") - # check for user provided unity source file list - get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT) - if (NOT _unitySourceFiles) - set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources}) - endif() - cotire_generate_target_script( - ${_language} "${_configurations}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles}) - # set up unity files for parallel compilation - cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles}) - cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles}) - list (LENGTH _unityFiles _numberOfUnityFiles) - if (_numberOfUnityFiles EQUAL 0) - return() - elseif (_numberOfUnityFiles GREATER 1) - cotire_setup_unity_generation_commands( - ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles}) - endif() - # set up single unity file for prefix header generation - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) - cotire_setup_unity_generation_commands( - ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFile}" _cmds ${_unitySourceFiles}) - cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) - # set up prefix header - if (_prefixFile) - # check for user provided prefix header files - get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) - if (_prefixHeaderFiles) - cotire_setup_prefix_generation_from_provided_command( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles}) - else() - cotire_setup_prefix_generation_from_unity_command( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_unityFile}" _cmds ${_unitySourceFiles}) - endif() - # check if selected language has enough sources at all - list (LENGTH _sourceFiles _numberOfSources) - if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - set (_targetUsePCH FALSE) - else() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - endif() - if (_targetUsePCH) - cotire_make_pch_file_path(${_language} ${_target} _pchFile) - if (_pchFile) - # first file in _sourceFiles is passed as the host file - cotire_setup_pch_file_compilation( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - cotire_setup_pch_file_inclusion( - ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - endif() - elseif (_prefixHeaderFiles) - # user provided prefix header must be included unconditionally - cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_sourceFiles}) - endif() - endif() - # mark target as cotired for language - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") - if (_prefixFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") - if (_targetUsePCH AND _pchFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") - endif() - endif() - set (${_cmdsVar} ${_cmds} PARENT_SCOPE) -endfunction() - -function (cotire_setup_clean_target _target) - set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") - if (NOT TARGET "${_cleanTargetName}") - cotire_set_cmd_to_prologue(_cmds) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") - add_custom_target(${_cleanTargetName} - COMMAND ${_cmds} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "Cleaning up target ${_target} cotire generated files" - VERBATIM) - cotire_init_target("${_cleanTargetName}") - endif() -endfunction() - -function (cotire_setup_pch_target _languages _configurations _target) - if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generators, we add a custom target to trigger the generation of the cotire related files - set (_dependsFiles "") - foreach (_language ${_languages}) - set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - # MSVC, Intel and clang-cl only create precompiled header as a side effect - list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) - endif() - cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) - if (_dependsFile) - list (APPEND _dependsFiles "${_dependsFile}") - endif() - endforeach() - if (_dependsFiles) - set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") - add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) - cotire_init_target("${_pchTargetName}") - cotire_add_to_pch_all_target(${_pchTargetName}) - endif() - else() - # for other generators, we add the "clean all" target to clean up the precompiled header - cotire_setup_clean_all_target() - endif() -endfunction() - -function (cotire_filter_object_libraries _target _objectLibrariesVar) - set (_objectLibraries "") - foreach (_source ${ARGN}) - if (_source MATCHES "^\\$$") - list (APPEND _objectLibraries "${_source}") - endif() - endforeach() - set (${_objectLibrariesVar} ${_objectLibraries} PARENT_SCOPE) -endfunction() - -function (cotire_collect_unity_target_sources _target _languages _unityTargetSourcesVar) - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_unityTargetSources ${_targetSourceFiles}) - foreach (_language ${_languages}) - get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) - if (_unityFiles) - # remove source files that are included in the unity source - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _cotiredSources) - list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) - endif() - # add unity source files instead - list (APPEND _unityTargetSources ${_unityFiles}) - endif() - endforeach() - # handle object libraries which are part of the target's sources - get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) - if ("${_linkLibrariesStrategy}" MATCHES "^COPY_UNITY$") - cotire_filter_object_libraries(${_target} _objectLibraries ${_targetSourceFiles}) - if (_objectLibraries) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityObjectLibraries ${_objectLibraries}) - list (REMOVE_ITEM _unityTargetSources ${_objectLibraries}) - list (APPEND _unityTargetSources ${_unityObjectLibraries}) - endif() - endif() - set (${_unityTargetSourcesVar} ${_unityTargetSources} PARENT_SCOPE) -endfunction() - -function (cotire_setup_unity_target_pch_usage _languages _target) - foreach (_language ${_languages}) - get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) - if (_unityFiles) - get_property(_userPrefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_userPrefixFile AND _prefixFile) - # user provided prefix header must be included unconditionally by unity sources - cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_unityFiles}) - endif() - endif() - endforeach() -endfunction() - -function (cotire_setup_unity_build_target _languages _configurations _target) - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (NOT _unityTargetName) - set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") - endif() - # determine unity target sub type - get_target_property(_targetType ${_target} TYPE) - if ("${_targetType}" STREQUAL "EXECUTABLE") - set (_unityTargetSubType "") - elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - set (_unityTargetSubType "${CMAKE_MATCH_1}") - else() - message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.") - return() - endif() - # determine unity target sources - set (_unityTargetSources "") - cotire_collect_unity_target_sources(${_target} "${_languages}" _unityTargetSources) - # prevent AUTOMOC, AUTOUIC and AUTORCC properties from being set when the unity target is created - set (CMAKE_AUTOMOC OFF) - set (CMAKE_AUTOUIC OFF) - set (CMAKE_AUTORCC OFF) - if (COTIRE_DEBUG) - message (STATUS "add target ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") - endif() - # generate unity target - if ("${_targetType}" STREQUAL "EXECUTABLE") - add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - else() - add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - endif() - # copy output location properties - set (_outputDirProperties - ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ - LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ - RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) - if (COTIRE_UNITY_OUTPUT_DIRECTORY) - set (_setDefaultOutputDir TRUE) - if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - else() - # append relative COTIRE_UNITY_OUTPUT_DIRECTORY to target's actual output directory - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) - cotire_resolve_config_properties("${_configurations}" _properties ${_outputDirProperties}) - foreach (_property ${_properties}) - get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) - if (_outputDir) - get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}") - set (_setDefaultOutputDir FALSE) - endif() - endforeach() - if (_setDefaultOutputDir) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - endif() - endif() - if (_setDefaultOutputDir) - set_target_properties(${_unityTargetName} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" - LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" - RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") - endif() - else() - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - ${_outputDirProperties}) - endif() - # copy output name - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ - LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ - OUTPUT_NAME OUTPUT_NAME_ - RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ - PREFIX _POSTFIX SUFFIX - IMPORT_PREFIX IMPORT_SUFFIX) - # copy compile stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ - COMPILE_FLAGS COMPILE_OPTIONS - Fortran_FORMAT Fortran_MODULE_DIRECTORY - INCLUDE_DIRECTORIES - INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_ - POSITION_INDEPENDENT_CODE - C_COMPILER_LAUNCHER CXX_COMPILER_LAUNCHER - C_INCLUDE_WHAT_YOU_USE CXX_INCLUDE_WHAT_YOU_USE - C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN - C_CLANG_TIDY CXX_CLANG_TIDY) - # copy compile features - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED - CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED - COMPILE_FEATURES) - # copy interface stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN - COMPATIBLE_INTERFACE_STRING - INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS - INTERFACE_INCLUDE_DIRECTORIES INTERFACE_SOURCES - INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES - INTERFACE_AUTOUIC_OPTIONS NO_SYSTEM_FROM_IMPORTED) - # copy link stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUILD_WITH_INSTALL_RPATH BUILD_WITH_INSTALL_NAME_DIR - INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH - LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED - LINK_FLAGS LINK_FLAGS_ - LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ - LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ - LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC - STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ - NO_SONAME SOVERSION VERSION - LINK_WHAT_YOU_USE BUILD_RPATH) - # copy cmake stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) - # copy Apple platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUNDLE BUNDLE_EXTENSION FRAMEWORK FRAMEWORK_VERSION INSTALL_NAME_DIR - MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_RPATH - OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE XCTEST - IOS_INSTALL_COMBINED XCODE_EXPLICIT_FILE_TYPE XCODE_PRODUCT_TYPE) - # copy Windows platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - GNUtoMS - COMPILE_PDB_NAME COMPILE_PDB_NAME_ - COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_ - PDB_NAME PDB_NAME_ PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_ - VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION - VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE - VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK - VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION - VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER - VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION - VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES - WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS - DEPLOYMENT_REMOTE_DIRECTORY VS_CONFIGURATION_TYPE - VS_SDK_REFERENCES VS_USER_PROPS VS_DEBUGGER_WORKING_DIRECTORY) - # copy Android platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - ANDROID_API ANDROID_API_MIN ANDROID_GUI - ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES - 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) - # copy CUDA platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - CUDA_PTX_COMPILATION CUDA_SEPARABLE_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS - CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED) - # use output name from original target - get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) - if (NOT _targetOutputName) - set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") - endif() - # use export symbol from original target - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") - if ("${_targetType}" STREQUAL "EXECUTABLE") - set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) - endif() - endif() - # enable parallel compilation for MSVC - if (MSVC AND "${CMAKE_GENERATOR}" MATCHES "Visual Studio") - list (LENGTH _unityTargetSources _numberOfUnityTargetSources) - if (_numberOfUnityTargetSources GREATER 1) - set_property(TARGET ${_unityTargetName} APPEND PROPERTY COMPILE_OPTIONS "/MP") - endif() - endif() - cotire_init_target(${_unityTargetName}) - cotire_add_to_unity_all_target(${_unityTargetName}) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") -endfunction(cotire_setup_unity_build_target) - -function (cotire_target _target) - set(_options "") - set(_oneValueArgs "") - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_LANGUAGES) - get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) - endif() - if (NOT _option_CONFIGURATIONS) - cotire_get_configuration_types(_option_CONFIGURATIONS) - endif() - # check if cotire can be applied to target at all - cotire_is_target_supported(${_target} _isSupported) - if (NOT _isSupported) - get_target_property(_imported ${_target} IMPORTED) - get_target_property(_targetType ${_target} TYPE) - if (_imported) - message (WARNING "cotire: imported ${_targetType} target ${_target} cannot be cotired.") - else() - message (STATUS "cotire: ${_targetType} target ${_target} cannot be cotired.") - endif() - return() - endif() - # resolve alias - get_target_property(_aliasName ${_target} ALIASED_TARGET) - if (_aliasName) - if (COTIRE_DEBUG) - message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.") - endif() - set (_target ${_aliasName}) - endif() - # check if target needs to be cotired for build type - # when using configuration types, the test is performed at build time - cotire_init_cotire_target_properties(${_target}) - if (NOT CMAKE_CONFIGURATION_TYPES) - if (CMAKE_BUILD_TYPE) - list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) - else() - list (FIND _option_CONFIGURATIONS "None" _index) - endif() - if (_index EQUAL -1) - if (COTIRE_DEBUG) - message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") - endif() - return() - endif() - endif() - # when not using configuration types, immediately create cotire intermediate dir - if (NOT CMAKE_CONFIGURATION_TYPES) - cotire_get_intermediate_dir(_baseDir) - file (MAKE_DIRECTORY "${_baseDir}") - endif() - # choose languages that apply to the target - cotire_choose_target_languages("${_target}" _targetLanguages _wholeTarget ${_option_LANGUAGES}) - if (NOT _targetLanguages) - return() - endif() - set (_cmds "") - foreach (_language ${_targetLanguages}) - cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} ${_wholeTarget} _cmd) - if (_cmd) - list (APPEND _cmds ${_cmd}) - endif() - endforeach() - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - if (_targetAddSCU) - cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) - endif() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - if (_targetUsePCH) - cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds}) - cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) - if (_targetAddSCU) - cotire_setup_unity_target_pch_usage("${_targetLanguages}" ${_target}) - endif() - endif() - get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) - if (_targetAddCleanTarget) - cotire_setup_clean_target(${_target}) - endif() -endfunction(cotire_target) - -function (cotire_map_libraries _strategy _mappedLibrariesVar) - set (_mappedLibraries "") - foreach (_library ${ARGN}) - if (_library MATCHES "^\\$$") - set (_libraryName "${CMAKE_MATCH_1}") - set (_linkOnly TRUE) - set (_objectLibrary FALSE) - elseif (_library MATCHES "^\\$$") - set (_libraryName "${CMAKE_MATCH_1}") - set (_linkOnly FALSE) - set (_objectLibrary TRUE) - else() - set (_libraryName "${_library}") - set (_linkOnly FALSE) - set (_objectLibrary FALSE) - endif() - if ("${_strategy}" MATCHES "COPY_UNITY") - cotire_is_target_supported(${_libraryName} _isSupported) - if (_isSupported) - # use target's corresponding unity target, if available - get_target_property(_libraryUnityTargetName ${_libraryName} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_libraryUnityTargetName}") - if (_linkOnly) - list (APPEND _mappedLibraries "$") - elseif (_objectLibrary) - list (APPEND _mappedLibraries "$") - else() - list (APPEND _mappedLibraries "${_libraryUnityTargetName}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - endforeach() - list (REMOVE_DUPLICATES _mappedLibraries) - set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE) -endfunction() - -function (cotire_target_link_libraries _target) - cotire_is_target_supported(${_target} _isSupported) - if (NOT _isSupported) - return() - endif() - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_unityTargetName}") - get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}") - endif() - if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$") - get_target_property(_linkLibraries ${_target} LINK_LIBRARIES) - if (_linkLibraries) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_linkLibraries}) - set_target_properties(${_unityTargetName} PROPERTIES LINK_LIBRARIES "${_unityLinkLibraries}") - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} link libraries: ${_unityLinkLibraries}") - endif() - endif() - get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES) - if (_interfaceLinkLibraries) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkInterfaceLibraries ${_interfaceLinkLibraries}) - set_target_properties(${_unityTargetName} PROPERTIES INTERFACE_LINK_LIBRARIES "${_unityLinkInterfaceLibraries}") - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} interface link libraries: ${_unityLinkInterfaceLibraries}") - endif() - endif() - get_target_property(_manualDependencies ${_target} MANUALLY_ADDED_DEPENDENCIES) - if (_manualDependencies) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityManualDependencies ${_manualDependencies}) - if (_unityManualDependencies) - add_dependencies("${_unityTargetName}" ${_unityManualDependencies}) - endif() - endif() - endif() - endif() -endfunction(cotire_target_link_libraries) - -function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) - if (_targetName) - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") - else() - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") - endif() - # filter files in intermediate directory - set (_filesToRemove "") - foreach (_file ${_cotireFiles}) - get_filename_component(_dir "${_file}" DIRECTORY) - get_filename_component(_dirName "${_dir}" NAME) - if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") - list (APPEND _filesToRemove "${_file}") - endif() - endforeach() - if (_filesToRemove) - if (COTIRE_VERBOSE) - message (STATUS "cleaning up ${_filesToRemove}") - endif() - file (REMOVE ${_filesToRemove}) - endif() -endfunction() - -function (cotire_init_target _targetName) - if (COTIRE_TARGETS_FOLDER) - set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") - endif() - set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_ALL TRUE) - if (MSVC_IDE) - set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) - endif() -endfunction() - -function (cotire_add_to_pch_all_target _pchTargetName) - set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_pchTargetName}) -endfunction() - -function (cotire_add_to_unity_all_target _unityTargetName) - set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_unityTargetName}) -endfunction() - -function (cotire_setup_clean_all_target) - set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - cotire_set_cmd_to_prologue(_cmds) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") - add_custom_target(${_targetName} - COMMAND ${_cmds} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "Cleaning up all cotire generated files" - VERBATIM) - cotire_init_target("${_targetName}") - endif() -endfunction() - -function (cotire) - set(_options "") - set(_oneValueArgs "") - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_targets ${_option_UNPARSED_ARGUMENTS}) - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS}) - else() - message (WARNING "cotire: ${_target} is not a target.") - endif() - endforeach() - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target_link_libraries(${_target}) - endif() - endforeach() -endfunction() - -if (CMAKE_SCRIPT_MODE_FILE) - - # cotire is being run in script mode - # locate -P on command args - set (COTIRE_ARGC -1) - foreach (_index RANGE ${CMAKE_ARGC}) - if (COTIRE_ARGC GREATER -1) - set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") - math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") - elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") - set (COTIRE_ARGC 0) - endif() - endforeach() - - # include target script if available - if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") - # the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES) - include("${COTIRE_ARGV2}") - endif() - - if (COTIRE_DEBUG) - message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") - endif() - - if (NOT COTIRE_BUILD_TYPE) - set (COTIRE_BUILD_TYPE "None") - endif() - string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) - set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) - set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) - # check if target has been cotired for actual build type COTIRE_BUILD_TYPE - list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) - if (_index GREATER -1) - set (_sources ${COTIRE_TARGET_SOURCES}) - set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) - else() - if (COTIRE_DEBUG) - message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") - endif() - set (_sources "") - set (_sourcesDefinitions "") - endif() - set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) - set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) - set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) - set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) - - if ("${COTIRE_ARGV1}" STREQUAL "unity") - - if (XCODE) - # executing pre-build action under Xcode, check dependency on target script - set (_dependsOption DEPENDS "${COTIRE_ARGV2}") - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) - - cotire_generate_unity_source( - "${COTIRE_ARGV3}" ${_sources} - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} - PRE_UNDEFS ${_targetPreUndefs} - POST_UNDEFS ${_targetPostUndefs} - SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} - SOURCES_POST_UNDEFS ${_sourcesPostUndefs} - ${_dependsOption}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") - - if (XCODE) - # executing pre-build action under Xcode, check dependency on unity file and prefix dependencies - set (_dependsOption DEPENDS "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS}) - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - set (_files "") - foreach (_index RANGE 4 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_generate_prefix_header( - "${COTIRE_ARGV3}" ${_files} - COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" - INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH} - IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" - INCLUDE_PRIORITY_PATH ${COTIRE_TARGET_INCLUDE_PRIORITY_PATH} - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags} - ${_dependsOption}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") - - set (_files "") - foreach (_index RANGE 5 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_precompile_prefix_header( - "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" - COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "combine") - - if (COTIRE_TARGET_LANGUAGE) - set (_combinedFile "${COTIRE_ARGV3}") - set (_startIndex 4) - else() - set (_combinedFile "${COTIRE_ARGV2}") - set (_startIndex 3) - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - if (XCODE) - # executing pre-build action under Xcode, check dependency on files to be combined - set (_dependsOption DEPENDS ${_files}) - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - if (COTIRE_TARGET_LANGUAGE) - cotire_generate_unity_source( - "${_combinedFile}" ${_files} - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - ${_dependsOption}) - else() - cotire_generate_unity_source("${_combinedFile}" ${_files} ${_dependsOption}) - endif() - - elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") - - cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") - - else() - message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".") - endif() - -else() - - # cotire is being run in include mode - # set up all variable and property definitions - - if (NOT DEFINED COTIRE_DEBUG_INIT) - if (DEFINED COTIRE_DEBUG) - set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) - else() - set (COTIRE_DEBUG_INIT FALSE) - endif() - endif() - option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) - - if (NOT DEFINED COTIRE_VERBOSE_INIT) - if (DEFINED COTIRE_VERBOSE) - set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) - else() - set (COTIRE_VERBOSE_INIT FALSE) - endif() - endif() - option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING - "Ignore headers with the listed file extensions from the generated prefix header.") - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING - "Ignore headers from these directories when generating the prefix header.") - - set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING - "Ignore sources with the listed file extensions from the generated unity source.") - - set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "2" CACHE STRING - "Minimum number of sources in target required to enable use of precompiled header.") - - if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT) - if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}) - elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio") - # enable parallelization for generators that run multiple jobs by default - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j") - else() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0") - endif() - endif() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING - "Maximum number of source files to include in a single unity source file.") - - if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) - set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") - endif() - if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) - set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") - endif() - if (NOT COTIRE_INTDIR) - set (COTIRE_INTDIR "cotire") - endif() - if (NOT COTIRE_PCH_ALL_TARGET_NAME) - set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") - endif() - if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) - set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") - endif() - if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) - set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") - endif() - if (NOT COTIRE_CLEAN_TARGET_SUFFIX) - set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") - endif() - if (NOT COTIRE_PCH_TARGET_SUFFIX) - set (COTIRE_PCH_TARGET_SUFFIX "_pch") - endif() - if (MSVC) - # MSVC default PCH memory scaling factor of 100 percent (75 MB) is too small for template heavy C++ code - # use a bigger default factor of 170 percent (128 MB) - if (NOT DEFINED COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (COTIRE_PCH_MEMORY_SCALING_FACTOR "170") - endif() - endif() - if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) - set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") - endif() - if (NOT DEFINED COTIRE_TARGETS_FOLDER) - set (COTIRE_TARGETS_FOLDER "cotire") - endif() - if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) - if ("${CMAKE_GENERATOR}" MATCHES "Ninja") - # generated Ninja build files do not work if the unity target produces the same output file as the cotired target - set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") - else() - set (COTIRE_UNITY_OUTPUT_DIRECTORY "") - endif() - endif() - - # define cotire cache variables - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of include directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "If not defined, defaults to empty list." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" - BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a header file extension matches one in the list, it will be excluded from the generated prefix header." - "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." - "If not defined, defaults to inc;inl;ipp." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS" - BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a source file extension matches one in the list, it will be excluded from the generated unity source file." - "Source files with an extension in CMAKE__IGNORE_EXTENSIONS are always excluded." - "If not defined, defaults to m;mm." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" - BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." - FULL_DOCS - "The variable can be set to an integer > 0." - "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." - "If not defined, defaults to 2." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer >= 0." - "If 0, cotire will only create a single unity source file." - "If a target contains more than that number of source files, cotire will create multiple unity source files for it." - "Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores." - "Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs." - "Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - "Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise." - ) - - # define cotire directory properties - - define_property( - DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" - BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." - FULL_DOCS - "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" - BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_UNITY_BUILD." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" - BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_CLEAN." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" - BRIEF_DOCS "Header paths matching one of these directories are put at the top of the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" - BRIEF_DOCS "Define strategy for setting up the unity target's link libraries." - FULL_DOCS - "See target property COTIRE_UNITY_LINK_LIBRARIES_INIT." - ) - - # define cotire target properties - - define_property( - TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED - BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." - FULL_DOCS - "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." - "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." - "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." - "The target name will be set to this target's name with the suffix _pch appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED - BRIEF_DOCS "Add a new target that performs a unity build for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." - "Most of the relevant target properties will be copied from this target to the new unity build target." - "Target dependencies and linked libraries have to be manually set up for the new unity build target." - "The unity target name will be set to this target's name with the suffix _unity appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED - BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." - "The clean target name will be set to this target's name with the suffix _clean_cotire appended." - "Inherited from directory." - "Defaults to FALSE." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "Inherited from directory." - "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." - "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," - "the option which yields the closer relative path match wins." - "Inherited from directory." - "If not set, this property is initialized to the empty list." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" INHERITED - BRIEF_DOCS "Header paths matching one of these directories are put at the top of prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "Header file paths matching one of these directories will be inserted at the beginning of the generated prefix header." - "Header files are sorted according to the order of the directories in the property." - "If not set, this property is initialized to the empty list." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer > 0." - "If a target contains more than that number of source files, cotire will create multiple unity build files for it." - "If not set, cotire will only create a single unity source file." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE_INIT" - BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will only add the given file(s) to the generated unity source file." - "If not set, cotire will add all the target source files to the generated unity source file." - "The property can be set to a user provided unity source file." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER_INIT" - BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will add the given header file(s) to the generated prefix header file." - "If not set, cotire will generate a prefix header by tracking the header files included by the unity source file." - "The property can be set to a user provided prefix header file (e.g., stdafx.h)." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED - BRIEF_DOCS "Define strategy for setting up unity target's link libraries." - FULL_DOCS - "If this property is empty or set to NONE, the generated unity target's link libraries have to be set up manually." - "If this property is set to COPY, the unity target's link libraries will be copied from this target." - "If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE" - BRIEF_DOCS "Read-only property. The generated unity source file(s)." - FULL_DOCS - "cotire sets this property to the path of the generated single computation unit source file for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER" - BRIEF_DOCS "Read-only property. The generated prefix header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language prefix header for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" - BRIEF_DOCS "Read-only property. The generated precompiled header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language precompiled header binary for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" - BRIEF_DOCS "The name of the generated unity build target corresponding to this target." - FULL_DOCS - "This property can be set to the desired name of the unity target that will be created by cotire." - "If not set, the unity target name will be set to this target's name with the suffix _unity appended." - "After this target has been processed by cotire, the property is set to the actual name of the generated unity target." - "Defaults to empty string." - ) - - # define cotire source properties - - define_property( - SOURCE PROPERTY "COTIRE_EXCLUDED" - BRIEF_DOCS "Do not modify source file's build command." - FULL_DOCS - "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." - "The source file will also be excluded from the generated unity source file." - "Source files that have their COMPILE_FLAGS property set will be excluded by default." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_DEPENDENCY" - BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." - FULL_DOCS - "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." - "If the file is modified, cotire will re-generate the prefix header source upon build." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" - BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." - FULL_DOCS - "If this property is set to TRUE, cotire will complete the current unity file and start a new one." - "The new unity source file will include this source file as the first one." - "This property essentially works as a separator for unity source files." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_TARGET" - BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." - FULL_DOCS - "cotire sets this property to the name of target, that the source file's build command has been altered for." - "Defaults to empty string." - ) - - message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.") - -endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f3160a..0dbfc88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,103 +1,13 @@ -cmake_minimum_required(VERSION 2.8.12) -# Set a default search path for CMake modules -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") -include(JSONParser) +cmake_minimum_required(VERSION 3.21.1) +project(QtAppBase) +include(QtAppBase) -# Parse the info.json and write a info.h file -file(READ info.json jsonInfo) -sbeParseJson(info jsonInfo) +qt_app_project_setup(PROJECT_SETUP_INFO) +project(${PROJECT_SETUP_INFO}) -project(${info.projectName}) - -# Configure a header file to pass some of the CMake settings to the source code. -include_directories("${CMAKE_CURRENT_BINARY_DIR}/src") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/src/info.h" "") -foreach(var ${info}) - string(TOUPPER "${var}" UPPER_VAR) - string(REPLACE "." "_" UPPER_VAR "${UPPER_VAR}") - if(${${var}} MATCHES "^[0-9]+$") - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/src/info.h" "#define ${UPPER_VAR} ${${var}}\n") - else() - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/src/info.h" "#define ${UPPER_VAR} \"${${var}}\"\n") - endif() -endforeach() - -# Check if we use conan -if(EXISTS "${PROJECT_BINARY_DIR}/conanbuildinfo.cmake") - include("${PROJECT_BINARY_DIR}/conanbuildinfo.cmake") - conan_basic_setup() -elseif(EXISTS "${PROJECT_SOURCE_DIR}/conanbuildinfo.cmake") - include("${PROJECT_SOURCE_DIR}/conanbuildinfo.cmake") - conan_basic_setup() -endif() - -# If build type is empty and there is no multi-configuration generator (like Visual Studio) choose release build. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) -endif() - -set_property(GLOBAL PROPERTY USE_FOLDERS ON) -set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "Default Targets") - -# Handle RPATH stuff -if(UNIX) - set(RPATH_ORIGIN false CACHE BOOL "Set the RPATH to $ORIGIN? Helpful for bundles") - - # Use, i.e. don't skip the full RPATH for the build tree - set(CMAKE_SKIP_BUILD_RPATH OFF) - # When building, don't use the install RPATH already - # (but later on when installing) - set(CMAKE_BUILD_WITH_INSTALL_RPATH OFF) - if(RPATH_ORIGIN) - set(CMAKE_INSTALL_RPATH "$ORIGIN/") - else() - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") - endif() - # Add the automatically determined parts of the RPATH - # which point to directories outside the build tree to the install RPATH - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) - # The RPATH to be used when installing, but only if it's not a system directory - if(NOT RPATH_ORIGIN) - list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) - if("${isSystemDir}" STREQUAL "-1") - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") - endif() - endif() -endif() - -add_subdirectory(doc doxygen EXCLUDE_FROM_ALL) - -# Handle precompiled header stuff -set(USE_PRECOMPILED_HEADERS false CACHE BOOL "Use precompiled headers?") -if(USE_PRECOMPILED_HEADERS) - include(cotire) - if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") - endif() -endif() +qt_app_setup() +include_directories("${PROJECT_BINARY_DIR}") add_subdirectory(src) -# Handle CPack stuff -if(WIN32) - set(CPACK_GENERATOR ZIP) -elseif(UNIX AND NOT APPLE) - set(CPACK_GENERATOR TGZ) -elseif(APPLE) - set(CPACK_GENERATOR STGZ;TGZ) -elseif(ANDROID) - set(CPACK_GENERATOR STGZ;TGZ) -else() -endif() -set(CPACK_PACKAGE_NAME "${info.projectName}") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${info.projectDescription}") -set(CPACK_PACKAGE_VENDOR "${info.vendor}") -set(CPACK_PACKAGE_CONTACT "${info.contact}") -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") -set(CPACK_PACKAGE_VERSION_MAJOR ${info.version.major}) -set(CPACK_PACKAGE_VERSION_MINOR ${info.version.minor}) -set(CPACK_PACKAGE_VERSION_PATCH ${info.version.patch}) -set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) -set(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROJECT_NAME}{CTL_MAJOR_VERSION}.${CTL_MINOR_VERSION}) -set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME}) -include(CPack) +add_subdirectory(doc doxygen EXCLUDE_FROM_ALL) diff --git a/INSTALL_CH b/INSTALL_CH index 9887646..ac844db 100644 --- a/INSTALL_CH +++ b/INSTALL_CH @@ -3,11 +3,11 @@ 本项目使用 CMake(参见 www.cmake.org)。请确保 cmake 已正确安装。 -您可能需要使用 conan.io (https://conan.io/) 来构建依赖项(OpenSSL、Qt5)。这一步是可选的:你可以自己通过 conan(建议在 Windows 环境下使用)或使用软件包管理器(如 apt 或 yum)构建依赖项。 +您可能需要使用 conan.io (https://conan.io/) 来构建依赖项(OpenSSL、Qt)。这一步是可选的:你可以自己通过 conan(建议在 Windows 环境下使用)或使用软件包管理器(如 apt 或 yum)构建依赖项。 要自行构建依赖项,必须先添加一个 conan 软件源: conan remote add tereius https://conan.privatehive.de/artifactory/api/conan/public-conan - + 之后,只需在 git 根目录(conanfile.py 所在位置)下运行以下命令即可: conan install ./ -s build_type=Release --build missing @@ -23,11 +23,11 @@ conan remote add tereius https://conan.privatehive.de/artifactory/api/conan/publ 如果 CMake 缺少一个依赖项(如果使用 conan 就不会出现这种情况),则必须手动设置变量(指向路径),例如 OpenSSL: cmake -G "Unix Makefiles" -DOpenSSL_cryptro_PATH="/usr/lib/x86_64-linux-gnu/libcrypto.so" -DOpenSSL_ssl_PATH="usr/lib/x86_64-linux-gnu/libssl.so" -DOpenSSL_include_DIR="/usr/include" - + 要更改 CMake 安装 lib/include 文件的路径,只需设置 CMAKE_INSTALL_PREFIX: cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/install/here" - + 要打印您可能需要更改的所有相关变量,请使用 cmake -LH @@ -38,10 +38,10 @@ cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/install/here" cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release cmake --build ./ cmake --build ./ --target install - -要交叉编译 Android 版 libONVIF,请使用 "buildProfiles "中与您的主机和目标版本相匹配的 conan 配置文件。 -例如 要在 Linux 主机上编译 Android Armv8 版本的 libONVIF,请在 git 根目录下运行以下命令: - conan create ./ -pr:h ./buildProfiles/androidArmv8LinuxHost.profile -pr:b default --build missing +要交叉编译 Android 版 libONVIF,请使用 "hostProfiles "中与主机和架构版本相匹配的 conan 配置文件。 +例如,要编译 Android Armv7 版本的 libONVIF,请在 git 根目录下运行以下命令: + + conan create ./ -pr:h ./hostProfiles/androidArmv7.profile -pr:b default --build missing lib/include 文件位于您的 conan 缓存中(~/.conan/data/libONVIF/<版本>/tereius/stable/package/)。 diff --git a/INSTALL_EN b/INSTALL_EN index 9f4322d..4099a66 100644 --- a/INSTALL_EN +++ b/INSTALL_EN @@ -3,11 +3,11 @@ How to build and install libONVIF binaries This projects uses CMake (see www.cmake.org). Make sure that cmake is properly installed. -You may want to use conan.io (https://conan.io/) to build the dependencies (OpenSSL, Qt5). This step is optional: You can build the dependencies via conan yourself (recommended for Windows) or obtain them using a package manager (like apt or yum). +You may want to use conan.io (https://conan.io/) to build the dependencies (OpenSSL, Qt). This step is optional: You can build the dependencies via conan yourself (recommended for Windows) or obtain them using a package manager (like apt or yum). To build the dependencies yourself you have to add one conan repositories first: conan remote add tereius https://conan.privatehive.de/artifactory/api/conan/public-conan - + After that just run following command in the git root dir (where the conanfile.py is located): conan install ./ -s build_type=Release --build missing @@ -22,11 +22,11 @@ Then create a (build) directory (preferably outside the git root dir). To compil If CMake is missing a dependency (this should not happen if you use conan) you have to set the variable (pointing to a path) manually e.g. for OpenSSL: cmake -G "Unix Makefiles" -DOpenSSL_cryptro_PATH="/usr/lib/x86_64-linux-gnu/libcrypto.so" -DOpenSSL_ssl_PATH="usr/lib/x86_64-linux-gnu/libssl.so" -DOpenSSL_include_DIR="/usr/include" - + To change the path where CMake installs the lib/include files just set CMAKE_INSTALL_PREFIX: cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/install/here" - + To print all the relevant variables you may want to change use: cmake -LH @@ -37,10 +37,10 @@ For Windows use a CMake generator like "NMake Makefiles" or "Visual Studio [...] cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release cmake --build ./ cmake --build ./ --target install - -To cross compile libONVIF for Android use one of the conan profiles from "buildProfiles" matching your host machine and target arch. -E.g.: To compile libONVIF for Android Armv8 arch on a Linux host run the following command in your git root dir: - conan create ./ -pr:h ./buildProfiles/androidArmv8LinuxHost.profile -pr:b default --build missing +To cross compile libONVIF for Android use one of the conan profiles from "hostProfiles" matching your machine and arch. +E.g.: To compile libONVIF for Android Armv7 arch run the following command in your git root dir: + + conan create ./ -pr:h ./hostProfiles/androidArmv7.profile -pr:b default --build missing The lib/include files are located in your conan cache (~/.conan/data/libONVIF//tereius/stable/package/) diff --git a/README.md b/README.md index 01f9d79..d0277a0 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,30 @@ # libONVIF -| os | os_build | Status | -| ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Android | Linux | [![Build Status](https://dev.azure.com/bjoernstresing/bjoernstresing/_apis/build/status/Tereius.libONVIF?repoName=Tereius%2FlibONVIF&branchName=master&jobName=Android&configuration=Android%20armv7Linux)](https://dev.azure.com/bjoernstresing/bjoernstresing/_build/latest?definitionId=7&repoName=Tereius%2FlibONVIF&branchName=master) | -| Android | Windows | [![Build Status](https://dev.azure.com/bjoernstresing/bjoernstresing/_apis/build/status/Tereius.libONVIF?repoName=Tereius%2FlibONVIF&branchName=master&jobName=Android&configuration=Android%20armv7Windows)](https://dev.azure.com/bjoernstresing/bjoernstresing/_build/latest?definitionId=7&repoName=Tereius%2FlibONVIF&branchName=master) | -| Linux | Linux | [![Build Status](https://dev.azure.com/bjoernstresing/bjoernstresing/_apis/build/status/Tereius.libONVIF?repoName=Tereius%2FlibONVIF&branchName=master&jobName=Linux)](https://dev.azure.com/bjoernstresing/bjoernstresing/_build/latest?definitionId=7&repoName=Tereius%2FlibONVIF&branchName=master) | -| Windows | Windows | [![Build Status](https://dev.azure.com/bjoernstresing/bjoernstresing/_apis/build/status/Tereius.libONVIF?repoName=Tereius%2FlibONVIF&branchName=master&jobName=Windows)](https://dev.azure.com/bjoernstresing/bjoernstresing/_build/latest?definitionId=7&repoName=Tereius%2FlibONVIF&branchName=master) | -| Macos | Macos | [![Build Status](https://dev.azure.com/bjoernstresing/bjoernstresing/_apis/build/status/Tereius.libONVIF?repoName=Tereius%2FlibONVIF&branchName=master&jobName=Macos)](https://dev.azure.com/bjoernstresing/bjoernstresing/_build/latest?definitionId=7&repoName=Tereius%2FlibONVIF&branchName=master) | +[![Conan Remote Recipe](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.github.com%2Frepos%2FPrivatehive%2FlibONVIF%2Fproperties%2Fvalues&query=%24%5B0%5D.value&style=flat&logo=conan&label=conan&color=%232980b9)](https://conan.privatehive.de/ui/repos/tree/General/public-conan/de.privatehive/libonvif) ### Yet another ONVIF library +--- + +| os | arch | CI Status | +|-----------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Linux` | `x86_64` | [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Privatehive/libONVIF/main.yml?branch=master&style=flat&logo=github&label=create+package)](https://github.com/Privatehive/libONVIF/actions?query=branch%3Amaster) | +| `Windows` | `x86_64` | [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Privatehive/libONVIF/main.yml?branch=master&style=flat&logo=github&label=create+package)](https://github.com/Privatehive/libONVIF/actions?query=branch%3Amaster) | +| `Macos` | `armv8` | [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Privatehive/libONVIF/main.yml?branch=master&style=flat&logo=github&label=create+package)](https://github.com/Privatehive/libONVIF/actions?query=branch%3Amaster) | +| `Android` | `x86` | [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Privatehive/libONVIF/main.yml?branch=master&style=flat&logo=github&label=create+package)](https://github.com/Privatehive/libONVIF/actions?query=branch%3Amaster) | +| `Android` | `x86_64` | [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Privatehive/libONVIF/main.yml?branch=master&style=flat&logo=github&label=create+package)](https://github.com/Privatehive/libONVIF/actions?query=branch%3Amaster) | +| `Android` | `armv7` | [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Privatehive/libONVIF/main.yml?branch=master&style=flat&logo=github&label=create+package)](https://github.com/Privatehive/libONVIF/actions?query=branch%3Amaster) | +| `Android` | `armv8` | [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Privatehive/libONVIF/main.yml?branch=master&style=flat&logo=github&label=create+package)](https://github.com/Privatehive/libONVIF/actions?query=branch%3Amaster) | + What does ONVIF stand for: -> ONVIF (Open Network Video Interface Forum) is a global and open industry forum with the goal of facilitating the development and use of a global open standard for the interface of physical IP-based security products – or, in other words, to create a standard for how IP products within video surveillance and other physical security areas can communicate with each other. [Wikipedia](https://en.wikipedia.org/wiki/ONVIF) +> ONVIF (Open Network Video Interface Forum) is a global and open industry forum with the goal of facilitating the +> development and use of a global open standard for the interface of physical IP-based security products – or, in other +> words, to create a standard for how IP products within video surveillance and other physical security areas can +> communicate with each other. [Wikipedia](https://en.wikipedia.org/wiki/ONVIF) -The idea behind this library is to hide some complexity of gsoap and to provide 'high level' classes including QT5 goodness. Currently there are eleven client side service methods implemented: +The idea behind this library is to hide some complexity of gsoap and to provide 'high level' classes including QT +goodness. Currently there are eleven client side service methods implemented: - ONVIF analytics http://www.onvif.org/ver20/analytics/wsdl - ONVIF device http://www.onvif.org/ver10/device/wsdl @@ -28,7 +38,9 @@ The idea behind this library is to hide some complexity of gsoap and to provide - ONVIF recording http://www.onvif.org/ver10/recording/wsdl - ONVIF replay http://www.onvif.org/ver10/replay/wsdl -For every service exists a class following the naming scheme `Onvif*Client` (\* matches service name). These classes handle the RPCs. For the convenience of WS discovery and ONVIF (pull point) event handling there are two more classes: `OnvifDiscovery` and `OnvifPullPoint`. +For every service exists a class following the naming scheme `Onvif*Client` (\* matches service name). These classes +handle the RPCs. For the convenience of WS discovery and ONVIF (pullpoint) event handling there are two more +classes: `OnvifDiscovery` and `OnvifPullPoint`. Design thoughts: @@ -38,6 +50,10 @@ Design thoughts: ### Further reading -- The library comes with a small application (named ovifinfo) that does some device-discovery, inspection. You may want to look at the [source code](https://github.com/Tereius/libONVIF/blob/master/src/main.cpp). -- If you want to learn more about how to use libONVIF in a qml app take a look at the following project [ONVIFMonitor](https://github.com/Tereius/ONVIFMonitor). -- It is always advisable to look at the [ONVIF programmers guide](https://www.onvif.org/wp-content/uploads/2016/12/ONVIF_WG-APG-Application_Programmers_Guide-1.pdf) to learn more about ONVIF. +- The library comes with a small application (named ovifinfo) that does some device-discovery, inspection. You may want + to look at the [source code](https://github.com/Tereius/libONVIF/blob/master/src/main.cpp). +- If you want to learn more about how to use libONVIF in a qml app take a look at the following + project [ONVIFMonitor](https://github.com/Tereius/ONVIFMonitor). +- It is always advisable to look at + the [ONVIF programmers guide](https://www.onvif.org/wp-content/uploads/2016/12/ONVIF_WG-APG-Application_Programmers_Guide-1.pdf) + to learn more about ONVIF. diff --git a/buildProfiles/androidArmv7LinuxHost.profile b/buildProfiles/androidArmv7LinuxHost.profile deleted file mode 100644 index c53d952..0000000 --- a/buildProfiles/androidArmv7LinuxHost.profile +++ /dev/null @@ -1,17 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Linux -arch=armv7 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -[env] - diff --git a/buildProfiles/androidArmv7WinHost.profile b/buildProfiles/androidArmv7WinHost.profile deleted file mode 100644 index 0e82cef..0000000 --- a/buildProfiles/androidArmv7WinHost.profile +++ /dev/null @@ -1,18 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Windows -arch=armv7 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -msys2/20210228@tereius/stable -[env] - diff --git a/buildProfiles/androidArmv8LinuxHost.profile b/buildProfiles/androidArmv8LinuxHost.profile deleted file mode 100644 index a850418..0000000 --- a/buildProfiles/androidArmv8LinuxHost.profile +++ /dev/null @@ -1,17 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Linux -arch=armv8 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -[env] - diff --git a/buildProfiles/androidArmv8WinHost.profile b/buildProfiles/androidArmv8WinHost.profile deleted file mode 100644 index 386fdab..0000000 --- a/buildProfiles/androidArmv8WinHost.profile +++ /dev/null @@ -1,18 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Windows -arch=armv8 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -msys2/20210228@tereius/stable -[env] - diff --git a/buildProfiles/androidx86LinuxHost.profile b/buildProfiles/androidx86LinuxHost.profile deleted file mode 100644 index 18b6056..0000000 --- a/buildProfiles/androidx86LinuxHost.profile +++ /dev/null @@ -1,17 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Linux -arch=x86 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -[env] - diff --git a/buildProfiles/androidx86WinHost.profile b/buildProfiles/androidx86WinHost.profile deleted file mode 100644 index 7389bab..0000000 --- a/buildProfiles/androidx86WinHost.profile +++ /dev/null @@ -1,18 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Linux -arch=x86 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -msys2/20210228@tereius/stable -[env] - diff --git a/buildProfiles/androidx86_64LinuxHost.profile b/buildProfiles/androidx86_64LinuxHost.profile deleted file mode 100644 index c1edb9c..0000000 --- a/buildProfiles/androidx86_64LinuxHost.profile +++ /dev/null @@ -1,17 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Linux -arch=x86_64 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -[env] - diff --git a/buildProfiles/androidx86_64WinHost.profile b/buildProfiles/androidx86_64WinHost.profile deleted file mode 100644 index 2664ed9..0000000 --- a/buildProfiles/androidx86_64WinHost.profile +++ /dev/null @@ -1,18 +0,0 @@ -[settings] -os=Android -os.api_level=24 -os_build=Linux -arch=x86_64 -arch_build=x86_64 -compiler=clang -compiler.version=9 -compiler.libcxx=libc++ -build_type=Release -[options] -android-sdk:platformVersion=28 -[build_requires] -android-ndk/r21e@tereius/stable -android-sdk/latest@tereius/stable -msys2/20210228@tereius/stable -[env] - diff --git a/conanfile.py b/conanfile.py index 813f6ab..0df0983 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,47 +1,75 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import json, os +from conan import ConanFile +from conan.tools.cmake import CMake, CMakeToolchain +from conan.tools.files import copy +from conan.tools.build import cross_building +from conan.tools.env import VirtualBuildEnv -import json -from conans import ConanFile, CMake, tools +required_conan_version = ">=2.0" class LibonvifConan(ConanFile): - jsonInfo = json.loads(tools.load("info.json")) - name = jsonInfo["projectName"] - version = "%u.%u.%u%s" % (jsonInfo["version"]["major"], jsonInfo["version"]["minor"], jsonInfo["version"]["patch"], - "-SNAPSHOT" if jsonInfo["version"]["snapshot"] else "") - license = jsonInfo["license"] - url = jsonInfo["repository"] + jsonInfo = json.load(open("info.json", 'r')) + # ---Package reference--- + name = jsonInfo["projectName"].lower() + version = "%u.%u.%u" % (jsonInfo["version"]["major"], jsonInfo["version"]["minor"], jsonInfo["version"]["patch"]) + user = jsonInfo["domain"] + channel = "%s" % ("snapshot" if jsonInfo["version"]["snapshot"] else "stable") + # ---Metadata--- description = jsonInfo["projectDescription"] + license = jsonInfo["license"] author = jsonInfo["vendor"] - homepage = jsonInfo["repository"] - requires = "Qt/[^5.12]@tereius/stable" - settings = {"os": ["Windows", "Linux", "Android", "Macos"], "compiler": None, "build_type": None, "arch": None} + topics = jsonInfo["topics"] + homepage = jsonInfo["homepage"] + url = jsonInfo["repository"] + # ---Requirements--- + requires = ["qt/[>=6.5.0]@%s/stable" % user] + tool_requires = ["cmake/[>=3.23.5]", "ninja/[>=1.11.1]", "qtappbase/[~1]@%s/stable" % user] + # ---Sources--- + exports = ["info.json", "LICENSE"] + exports_sources = ["info.json", "src/*", "doc/*", "CMake/*", "CMakeLists.txt"] + # ---Binary model--- + settings = "os", "compiler", "build_type", "arch" options = {"shared": [True, False], "openssl": [True, False]} - default_options = "shared=True", "openssl=True" - generators = "cmake" - exports = "info.json" - exports_sources = "*" - default_user = "tereius" - default_channel = "stable" + default_options = {"shared": True, + "openssl": True, + "qt/*:qtbase": True + } + # ---Build--- + generators = [] + # ---Folders--- + no_copy_source = False def requirements(self): if self.options.openssl: - self.requires("openssl/1.1.1l@tereius/stable") - self.options["openssl"].shared = True + self.requires("openssl/[~3]@%s/stable" % self.user) + + def configure(self): + if self.options.openssl: + self.options["openssl"].shared = self.options.shared + + def generate(self): + ms = VirtualBuildEnv(self) + tc = CMakeToolchain(self, generator="Ninja") + tc.variables["ENABLE_SSL"] = self.options.openssl + tc.generate() + ms.generate() def build(self): - if self.settings.os == 'Android': - cmake = CMake(self, generator="Unix Makefiles") - else: - cmake = CMake(self) + cmake = CMake(self) cmake.configure() cmake.build() + + def package(self): + cmake = CMake(self) cmake.install() def package_info(self): + self.cpp_info.set_property("cmake_find_mode", "none") self.cpp_info.builddirs = ['cmake'] - self.cpp_info.defines = ['WITH_SELF_PIPE'] + self.cpp_info.defines = ['WITH_SELF_PIPE', 'WITH_DOM'] if self.options.openssl: self.cpp_info.defines = ['WITH_OPENSSL'] diff --git a/hostProfiles/androidArmv7.profile b/hostProfiles/androidArmv7.profile new file mode 100644 index 0000000..ba5594d --- /dev/null +++ b/hostProfiles/androidArmv7.profile @@ -0,0 +1,14 @@ +[settings] +os=Android +os.api_level=28 +arch=armv7 +compiler=clang +compiler.version=17 +compiler.libcxx=c++_shared +build_type=Release +[options] +qt/*:opengl=es2 +[tool_requires] +android-ndk/r26b@de.privatehive/stable +android-sdk/latest@de.privatehive/stable +openjdk/19.0.2@de.privatehive/stable diff --git a/hostProfiles/androidArmv8.profile b/hostProfiles/androidArmv8.profile new file mode 100644 index 0000000..f20fda9 --- /dev/null +++ b/hostProfiles/androidArmv8.profile @@ -0,0 +1,14 @@ +[settings] +os=Android +os.api_level=28 +arch=armv8 +compiler=clang +compiler.version=17 +compiler.libcxx=c++_shared +build_type=Release +[options] +qt/*:opengl=es2 +[tool_requires] +android-ndk/r26b@de.privatehive/stable +android-sdk/latest@de.privatehive/stable +openjdk/19.0.2@de.privatehive/stable diff --git a/hostProfiles/androidx86.profile b/hostProfiles/androidx86.profile new file mode 100644 index 0000000..4d94afa --- /dev/null +++ b/hostProfiles/androidx86.profile @@ -0,0 +1,14 @@ +[settings] +os=Android +os.api_level=28 +arch=x86 +compiler=clang +compiler.version=17 +compiler.libcxx=c++_shared +build_type=Release +[options] +qt/*:opengl=es2 +[tool_requires] +android-ndk/r26b@de.privatehive/stable +android-sdk/latest@de.privatehive/stable +openjdk/19.0.2@de.privatehive/stable diff --git a/hostProfiles/androidx86_64.profile b/hostProfiles/androidx86_64.profile new file mode 100644 index 0000000..1c19ed4 --- /dev/null +++ b/hostProfiles/androidx86_64.profile @@ -0,0 +1,14 @@ +[settings] +os=Android +os.api_level=28 +arch=x86_64 +compiler=clang +compiler.version=17 +compiler.libcxx=c++_shared +build_type=Release +[options] +qt/*:opengl=es2 +[tool_requires] +android-ndk/r26b@de.privatehive/stable +android-sdk/latest@de.privatehive/stable +openjdk/19.0.2@de.privatehive/stable diff --git a/info.json b/info.json index 891b498..63bfe29 100644 --- a/info.json +++ b/info.json @@ -1,16 +1,21 @@ { - "version": { - "major": 2, - "minor": 0, - "patch": 1, - "snapshot": false - }, - "projectName": "libONVIF", - "projectDescription": "A client side ONVIF library", - "vendor": "Björn Stresing", - "contact": "bjoern.stresing@gmx.de", - "domain": "com.github.Tereius", - "copyrightYear": "2018", - "license": "GPLv3", - "repository": "https://github.com/Tereius/libONVIF" + "version": { + "major": 3, + "minor": 0, + "patch": 0, + "snapshot": false + }, + "projectName": "libONVIF", + "projectDescription": "A client side ONVIF library", + "vendor": "Björn Stresing", + "contact": "bjoern.stresing@gmx.de", + "domain": "de.privatehive", + "copyrightYear": "2018", + "repository": "https://github.com/Tereius/libONVIF", + "topics": [ + "Qt", + "ONVIF" + ], + "homepage": "https://github.com/Tereius/libONVIF", + "license": "GPLv3" } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cfc3a3a..b53fb93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,510 +1,526 @@ include(GenerateExportHeader) include(CMakePackageConfigHelpers) -find_package(CommonLibs QUIET) -find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(Qt6 COMPONENTS Core REQUIRED) find_library(OpenSSL_cryptro_PATH NAMES libeay libeay32 libcrypto libcrypto32 eay crypto PATH_SUFFIXES "lib") find_library(OpenSSL_ssl_PATH NAMES ssleay ssleay32 libssl libssl32 eay ssl PATH_SUFFIXES "lib") find_path(OpenSSL_include_DIR NAMES openssl/ssl.h PATH_SUFFIXES "include") -if(ENABLE_CODESYNTHESIS) - find_program(Gsoap_wsdl2h_PATH NAMES wsdl2h PATH_SUFFIXES "bin") - find_program(Gsoap_soapcpp2_PATH NAMES soapcpp2 PATH_SUFFIXES "bin") - find_path(Gsoap_import_DIR NAMES wsdd5.h PATH_SUFFIXES "share/gsoap/import" "share/gsoap" "share") -endif() +if (ENABLE_CODESYNTHESIS) + find_program(Gsoap_wsdl2h_PATH NAMES wsdl2h PATH_SUFFIXES "bin") + find_program(Gsoap_soapcpp2_PATH NAMES soapcpp2 PATH_SUFFIXES "bin") + find_path(Gsoap_import_DIR NAMES wsdd5.h PATH_SUFFIXES "gsoap/import" "share/gsoap/import" "share/gsoap") + find_path(Gsoap_plugin_DIR NAMES wsseapi.h PATH_SUFFIXES "gsoap/plugin" "share/gsoap/plugin" "share/gsoap") + find_path(Gsoap_custom_DIR NAMES struct_timeval.h PATH_SUFFIXES "gsoap/custom" "share/gsoap/custom" "share/gsoap") + find_file(Gsoap_stdsoap2cpp NAMES stdsoap2.cpp PATH_SUFFIXES "gsoap" REQUIRED) + find_file(Gsoap_stdsoap2h NAMES stdsoap2.h PATH_SUFFIXES "gsoap" REQUIRED) + find_file(Gsoap_domcpp NAMES dom.cpp PATH_SUFFIXES "gsoap" REQUIRED) +endif () -set(CMAKE_AUTOMOC ON) set(BUILD_SHARED_LIBS true CACHE BOOL "Build shared or static lib?") set(ENABLE_CODESYNTHESIS false CACHE BOOL "Run wsdl2h and soapcpp2?") -set(CMAKE_DEBUG_POSTFIX d) # Append "d" if debug lib. +set(ENABLE_SSL false CACHE BOOL "Enable ssl support?") + set(HAS_OPENSSL OFF) -if(OpenSSL_include_DIR AND OpenSSL_cryptro_PATH AND OpenSSL_ssl_PATH) - set(HAS_OPENSSL ON) -endif() +if (ENABLE_SSL AND OpenSSL_include_DIR AND OpenSSL_cryptro_PATH AND OpenSSL_ssl_PATH) + set(HAS_OPENSSL ON) +endif () -link_directories("${_qt5Core_install_prefix}/lib") include_directories("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/generated" "${CMAKE_CURRENT_SOURCE_DIR}/gsoap") -if(HAS_OPENSSL) - include_directories("${OpenSSL_include_DIR}") - add_definitions(-DWITH_OPENSSL) -else() - message(STATUS "SSL/TLS disabled because of missing OpenSSL library") -endif() - -if(WIN32) - add_definitions(-DOS_WIN32) -endif() +if (HAS_OPENSSL) + include_directories("${OpenSSL_include_DIR}") + add_definitions(-DWITH_OPENSSL) +else () + message(STATUS "SSL/TLS disabled because of missing OpenSSL library") +endif () -if(MSVC) - add_definitions(-DNOMINMAX) -endif() +if (WIN32) + add_definitions(-DOS_WIN32) +endif () -if(WIN32 AND BUILD_SHARED_LIBS) - add_definitions(-DSOAP_STD_EXPORTS) -endif() +if (MSVC) + add_definitions(-DNOMINMAX) +endif () +if (WIN32 AND BUILD_SHARED_LIBS) + add_definitions(-DSOAP_STD_EXPORTS) +endif () # -------------------------------GSOAP synthesis------------------------------- -set(GSOAP_DIRS "${Gsoap_import_DIR}:${Gsoap_import_DIR}/import:${CMAKE_CURRENT_SOURCE_DIR}/gsoap") -if(ENABLE_CODESYNTHESIS) - add_custom_target(Synthesis - COMMAND ${Gsoap_wsdl2h_PATH} -c++11 -z7 -d -p -j -t typemap.dat -o generated.h - http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl - http://www.onvif.org/onvif/ver10/replay.wsdl - http://www.onvif.org/onvif/ver10/search.wsdl - http://www.onvif.org/onvif/ver10/recording.wsdl - http://www.onvif.org/onvif/ver10/receiver.wsdl - http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl - http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl - http://www.onvif.org/onvif/ver20/media/wsdl/media.wsdl - http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl - http://www.onvif.org/onvif/ver10/display.wsdl - http://www.onvif.org/onvif/ver10/events/wsdl/event.wsdl - http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl - http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl - COMMAND ${Gsoap_soapcpp2_PATH} -Ed -Ec -c++11 -z4 -a -j -L -x -n -d ${CMAKE_CURRENT_SOURCE_DIR}/generated -I ${GSOAP_DIRS} generated.h - COMMAND $ generated.h - COMMAND ${CMAKE_COMMAND} -E copy GsoapResolver.h ${CMAKE_CURRENT_SOURCE_DIR}/generated - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/wsdl VERBATIM) - - add_dependencies(Synthesis headerParser) -endif() +set(GSOAP_DIRS "${Gsoap_import_DIR}/../:${Gsoap_import_DIR}:${Gsoap_custom_DIR}:${CMAKE_CURRENT_SOURCE_DIR}/gsoap") +if (ENABLE_CODESYNTHESIS) + message(STATUS "Using gsoap dirs: ${GSOAP_DIRS}") + add_custom_target(Synthesis + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/wsseapi.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/wsseapi.c ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/wsseapi-lite.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/wsseapi-lite.c ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/mecevp.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/mecevp.c ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/wsaapi.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/wsaapi.c ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/smdevp.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/smdevp.c ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/httpda.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_plugin_DIR}/httpda.c ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_custom_DIR}/qstring.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_custom_DIR}/qstring.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_custom_DIR}/qdatetime.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_custom_DIR}/qdatetime.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_custom_DIR}/duration.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_custom_DIR}/duration.c ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_import_DIR}/stlvector.h ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_stdsoap2cpp} ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_stdsoap2h} ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + COMMAND ${CMAKE_COMMAND} -E copy ${Gsoap_domcpp} ${CMAKE_CURRENT_SOURCE_DIR}/gsoap + + COMMAND ${Gsoap_wsdl2h_PATH} -c++11 -z7 -d -p -j -t typemap.dat -o generated.h + http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl + http://www.onvif.org/onvif/ver10/replay.wsdl + http://www.onvif.org/onvif/ver10/search.wsdl + http://www.onvif.org/onvif/ver10/recording.wsdl + http://www.onvif.org/onvif/ver10/receiver.wsdl + http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl + http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl + http://www.onvif.org/onvif/ver20/media/wsdl/media.wsdl + http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl + http://www.onvif.org/onvif/ver10/display.wsdl + http://www.onvif.org/onvif/ver10/events/wsdl/event.wsdl + http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl + http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl + COMMAND ${Gsoap_soapcpp2_PATH} -Ed -Ec -c++11 -z4 -a -j -L -x -n -d ${CMAKE_CURRENT_SOURCE_DIR}/generated -I ${GSOAP_DIRS} generated.h + COMMAND $ generated.h + COMMAND ${CMAKE_COMMAND} -E copy GsoapResolver.h ${CMAKE_CURRENT_SOURCE_DIR}/generated + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/wsdl VERBATIM) + + add_dependencies(Synthesis headerParserTool) +endif () # -------------------------------Header parser------------------------------- set(src_files - headerParser/main.cpp - ) + headerParser/main.cpp + ) -add_executable(headerParser ${src_files}) +add_executable(headerParserTool ${src_files}) # -------------------------------ONVIF Common------------------------------- set(src_files - generated/soapC.cpp - gsoap/duration.c - gsoap/qdatetime.cpp - gsoap/AbsoluteOrRelativeTimeType.cpp - gsoap/qstring.cpp - gsoap/stdsoap2.cpp - gsoap/dom.cpp - gsoap/wsaapi.c - gsoap/qstringCompare.cpp - SoapCtx.cpp - SoapAuthHandler.cpp - Client.cpp - SoapHelper.cpp - ) - -if(HAS_OPENSSL) - set(src_files ${src_files} gsoap/smdevp.c gsoap/httpda.c gsoap/mecevp.c gsoap/wsseapi.c) -else() - set(src_files ${src_files} gsoap/wsseapi-lite.c) -endif() + generated/soapC.cpp + gsoap/duration.c + gsoap/qdatetime.cpp + gsoap/AbsoluteOrRelativeTimeType.cpp + gsoap/qstring.cpp + gsoap/stdsoap2.cpp + gsoap/dom.cpp + gsoap/wsaapi.c + gsoap/qstringCompare.cpp + SoapCtx.cpp + SoapAuthHandler.cpp + Client.cpp + SoapHelper.cpp + ) + +if (HAS_OPENSSL) + set(src_files ${src_files} gsoap/smdevp.c gsoap/httpda.c gsoap/mecevp.c gsoap/wsseapi.c) +else () + set(src_files ${src_files} gsoap/wsseapi-lite.c) +endif () # private header set(private_header_files - gsoap/stlvector.h - ) + gsoap/stlvector.h + ) # public header set(public_header_files - generated/soapStub.h - generated/soapH.h - gsoap/stdsoap2.h - gsoap/wsaapi.h - gsoap/AbsoluteOrRelativeTime.h - gsoap/qstringCompare.h - SoapCtx.h - SoapAuthHandler.h - Request.h - Response.h - Client.h - global.h - SoapHelper.h - ) - -if(HAS_OPENSSL) - set(public_header_files ${public_header_files} gsoap/smdevp.h gsoap/httpda.h gsoap/threads.h gsoap/mecevp.h gsoap/wsseapi.h) -else() - set(public_header_files ${public_header_files} gsoap/wsseapi-lite.h) -endif() + generated/soapStub.h + generated/soapH.h + gsoap/stdsoap2.h + gsoap/wsaapi.h + gsoap/AbsoluteOrRelativeTime.h + gsoap/qstringCompare.h + SoapCtx.h + SoapAuthHandler.h + Request.h + Response.h + Client.h + global.h + SoapHelper.h + ) + +if (HAS_OPENSSL) + set(public_header_files ${public_header_files} gsoap/smdevp.h gsoap/httpda.h gsoap/threads.h gsoap/mecevp.h gsoap/wsseapi.h) +else () + set(public_header_files ${public_header_files} gsoap/wsseapi-lite.h) +endif () set_source_files_properties(${src_files} PROPERTIES LANGUAGE CXX) add_library(onvifcommon ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifcommon EXPORT_FILE_NAME OnvifCommonExport.h) target_include_directories(onvifcommon - PUBLIC $ $ - PUBLIC $ $ - PUBLIC $ $ - PUBLIC $) -target_link_libraries(onvifcommon Qt5::Core) -target_compile_definitions(onvifcommon PUBLIC WITH_SELF_PIPE) -if(HAS_OPENSSL) - target_link_libraries(onvifcommon "${OpenSSL_ssl_PATH}" "${OpenSSL_cryptro_PATH}") -endif() -if(WIN32 AND NOT BUILD_SHARED_LIBS) - target_link_libraries(onvifcommon qtpcre2.lib version.lib Winmm.lib Netapi32.lib Userenv.lib) -endif() + PUBLIC $ $ + PUBLIC $ $ + PUBLIC $ $ + PUBLIC $) +target_link_libraries(onvifcommon Qt6::Core) +target_compile_definitions(onvifcommon PUBLIC WITH_SELF_PIPE PUBLIC WITH_DOM) +if (HAS_OPENSSL) + target_link_libraries(onvifcommon "${OpenSSL_ssl_PATH}" "${OpenSSL_cryptro_PATH}") +endif () +if (WIN32) + target_link_libraries(onvifcommon ws2_32) + if (NOT BUILD_SHARED_LIBS) + target_link_libraries(onvifcommon version Winmm Netapi32 Userenv) + if (HAS_OPENSSL) + target_link_libraries(onvifcommon crypt32) + endif () + endif () +endif () target_compile_features(onvifcommon PUBLIC cxx_strong_enums cxx_auto_type cxx_nullptr cxx_long_long_type cxx_explicit_conversions) set_target_properties(onvifcommon PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifCommonExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifcommon) -endif() # -------------------------------ONVIF Analytics------------------------------- set(src_files - generated/soapAnalyticsDeviceBindingProxy.cpp - #generated/soapAnalyticsDeviceBindingService.cpp - OnvifAnalyticsClient.cpp - ) + generated/soapAnalyticsDeviceBindingProxy.cpp + #generated/soapAnalyticsDeviceBindingService.cpp + OnvifAnalyticsClient.cpp + ) # private header set(private_header_files - generated/soapAnalyticsDeviceBindingProxy.h - #generated/soapAnalyticsDeviceBindingService.h - ) + generated/soapAnalyticsDeviceBindingProxy.h + #generated/soapAnalyticsDeviceBindingService.h + ) # public header set(public_header_files - OnvifAnalyticsClient.h - ) + OnvifAnalyticsClient.h + ) add_library(onvifanalytics ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifanalytics EXPORT_FILE_NAME OnvifAnalyticsExport.h) target_link_libraries(onvifanalytics onvifcommon) set_target_properties(onvifanalytics PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifAnalyticsExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifanalytics) -endif() # -------------------------------ONVIF Device------------------------------- set(src_files - generated/soapDeviceBindingProxy.cpp - #generated/soapDeviceBindingService.cpp - OnvifDeviceClient.cpp - ) + generated/soapDeviceBindingProxy.cpp + #generated/soapDeviceBindingService.cpp + OnvifDeviceClient.cpp + ) # private header set(private_header_files - generated/soapDeviceBindingProxy.h - #generated/soapDeviceBindingService.h - ) + generated/soapDeviceBindingProxy.h + #generated/soapDeviceBindingService.h + ) # public header set(public_header_files - OnvifDeviceClient.h - ) + OnvifDeviceClient.h + ) add_library(onvifdevice ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifdevice EXPORT_FILE_NAME OnvifDeviceExport.h) target_link_libraries(onvifdevice onvifcommon) set_target_properties(onvifdevice PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifDeviceExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifdevice) -endif() # -------------------------------ONVIF Display------------------------------- set(src_files - generated/soapDisplayBindingProxy.cpp - #generated/soapDisplayBindingService.cpp - OnvifDisplayClient.cpp - ) + generated/soapDisplayBindingProxy.cpp + #generated/soapDisplayBindingService.cpp + OnvifDisplayClient.cpp + ) # private header set(private_header_files - generated/soapDisplayBindingProxy.h - #generated/soapDisplayBindingService.h - ) + generated/soapDisplayBindingProxy.h + #generated/soapDisplayBindingService.h + ) # public header set(public_header_files - OnvifDisplayClient.h - ) + OnvifDisplayClient.h + ) add_library(onvifdisplay ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifdisplay EXPORT_FILE_NAME OnvifDisplayExport.h) target_link_libraries(onvifdisplay onvifcommon) set_target_properties(onvifdisplay PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifDisplayExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifdisplay) -endif() # -------------------------------ONVIF Imaging------------------------------- set(src_files - generated/soapImagingBindingProxy.cpp - #generated/soapImagingBindingService.cpp - OnvifImagingClient.cpp - ) + generated/soapImagingBindingProxy.cpp + #generated/soapImagingBindingService.cpp + OnvifImagingClient.cpp + ) # private header set(private_header_files - generated/soapImagingBindingProxy.h - #generated/soapImagingBindingService.h - ) + generated/soapImagingBindingProxy.h + #generated/soapImagingBindingService.h + ) # public header set(public_header_files - OnvifImagingClient.h - ) + OnvifImagingClient.h + ) add_library(onvifimaging ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifimaging EXPORT_FILE_NAME OnvifImagingExport.h) target_link_libraries(onvifimaging onvifcommon) set_target_properties(onvifimaging PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifImagingExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifimaging) -endif() # -------------------------------ONVIF Media------------------------------- set(src_files - generated/soapMediaBindingProxy.cpp - #generated/soapMediaBindingService.cpp - OnvifMediaClient.cpp - ) + generated/soapMediaBindingProxy.cpp + #generated/soapMediaBindingService.cpp + OnvifMediaClient.cpp + ) # private header set(private_header_files - generated/soapMediaBindingProxy.h - #generated/soapMediaBindingService.h - ) + generated/soapMediaBindingProxy.h + #generated/soapMediaBindingService.h + ) # public header set(public_header_files - OnvifMediaClient.h - ) + OnvifMediaClient.h + ) add_library(onvifmedia ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifmedia EXPORT_FILE_NAME OnvifMediaExport.h) target_link_libraries(onvifmedia onvifcommon) set_target_properties(onvifmedia PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifMediaExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifmedia) -endif() # -------------------------------ONVIF Media2------------------------------- set(src_files - generated/soapMedia2BindingProxy.cpp - #generated/soapMedia2BindingService.cpp - OnvifMedia2Client.cpp - ) + generated/soapMedia2BindingProxy.cpp + #generated/soapMedia2BindingService.cpp + OnvifMedia2Client.cpp + ) # private header set(private_header_files - generated/soapMedia2BindingProxy.h - #generated/soapMedia2BindingService.h - ) + generated/soapMedia2BindingProxy.h + #generated/soapMedia2BindingService.h + ) # public header set(public_header_files - OnvifMedia2Client.h - ) + OnvifMedia2Client.h + ) add_library(onvifmedia2 ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifmedia2 EXPORT_FILE_NAME OnvifMedia2Export.h) target_link_libraries(onvifmedia2 onvifcommon) set_target_properties(onvifmedia2 PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifMedia2Export.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifmedia2) -endif() # -------------------------------ONVIF PTZ------------------------------- set(src_files - generated/soapPTZBindingProxy.cpp - #generated/soapPTZBindingService.cpp - OnvifPtzClient.cpp - ) + generated/soapPTZBindingProxy.cpp + #generated/soapPTZBindingService.cpp + OnvifPtzClient.cpp + ) # private header set(private_header_files - generated/soapPTZBindingProxy.h - #generated/soapPTZBindingService.h - ) + generated/soapPTZBindingProxy.h + #generated/soapPTZBindingService.h + ) # public header set(public_header_files - OnvifPtzClient.h - ) + OnvifPtzClient.h + ) add_library(onvifptz ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifptz EXPORT_FILE_NAME OnvifPtzExport.h) target_link_libraries(onvifptz onvifcommon) set_target_properties(onvifptz PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifPtzExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifptz) -endif() # -------------------------------ONVIF Event------------------------------- set(src_files - generated/soapPullPointSubscriptionBindingProxy.cpp - #generated/soapPullPointSubscriptionBindingService.cpp - OnvifEventClient.cpp - OnvifPullPoint.cpp - Topics.cpp - NotificationFilter.cpp - ) + generated/soapPullPointSubscriptionBindingProxy.cpp + #generated/soapPullPointSubscriptionBindingService.cpp + OnvifEventClient.cpp + OnvifPullPoint.cpp + Topics.cpp + NotificationFilter.cpp + ) # private header set(private_header_files - generated/soapPullPointSubscriptionBindingProxy.h - #generated/soapPullPointSubscriptionBindingService.h - ) + generated/soapPullPointSubscriptionBindingProxy.h + #generated/soapPullPointSubscriptionBindingService.h + ) # public header set(public_header_files - OnvifEventClient.h - OnvifPullPoint.h - Topics.h - NotificationFilter.h - ) + OnvifEventClient.h + OnvifPullPoint.h + Topics.h + NotificationFilter.h + ) add_library(onvifevent ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifevent EXPORT_FILE_NAME OnvifEventExport.h) target_link_libraries(onvifevent onvifcommon) set_target_properties(onvifevent PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifEventExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifevent) -endif() # -------------------------------ONVIF Receiver------------------------------- set(src_files - generated/soapReceiverBindingProxy.cpp - #generated/soapReceiverBindingService.cpp - OnvifReceiverClient.cpp - ) + generated/soapReceiverBindingProxy.cpp + #generated/soapReceiverBindingService.cpp + OnvifReceiverClient.cpp + ) # private header set(private_header_files - generated/soapReceiverBindingProxy.h - #generated/soapReceiverBindingService.h - ) + generated/soapReceiverBindingProxy.h + #generated/soapReceiverBindingService.h + ) # public header set(public_header_files - OnvifReceiverClient.h - ) + OnvifReceiverClient.h + ) add_library(onvifreceiver ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifreceiver EXPORT_FILE_NAME OnvifReceiverExport.h) target_link_libraries(onvifreceiver onvifcommon) set_target_properties(onvifreceiver PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifReceiverExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifreceiver) -endif() # -------------------------------ONVIF Recording------------------------------- set(src_files - generated/soapRecordingBindingProxy.cpp - #generated/soapRecordingBindingService.cpp - OnvifRecordingClient.cpp - ) + generated/soapRecordingBindingProxy.cpp + #generated/soapRecordingBindingService.cpp + OnvifRecordingClient.cpp + ) # private header set(private_header_files - generated/soapRecordingBindingProxy.h - #generated/soapRecordingBindingService.h - ) + generated/soapRecordingBindingProxy.h + #generated/soapRecordingBindingService.h + ) # public header set(public_header_files - OnvifRecordingClient.h - ) + OnvifRecordingClient.h + ) add_library(onvifrecording ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifrecording EXPORT_FILE_NAME OnvifRecordingExport.h) target_link_libraries(onvifrecording onvifcommon) set_target_properties(onvifrecording PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifRecordingExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifrecording) -endif() # -------------------------------ONVIF Discovery------------------------------- set(src_files - # generated/soapRemoteDiscoveryBindingProxy.cpp - # generated/soapRemoteDiscoveryBindingService.cpp - # gsoap/wsddapi.c - OnvifDiscoveryClient.cpp - # OnvifDiscover.cpp - OnvifDiscovery.cpp - DiscoveryMatch.cpp - generated/soapwsddProxy.cpp - ) + # generated/soapRemoteDiscoveryBindingProxy.cpp + # generated/soapRemoteDiscoveryBindingService.cpp + # gsoap/wsddapi.c + OnvifDiscoveryClient.cpp + # OnvifDiscover.cpp + OnvifDiscovery.cpp + DiscoveryMatch.cpp + generated/soapwsddProxy.cpp + ) set_source_files_properties(${src_files} PROPERTIES LANGUAGE CXX) # private header set(private_header_files - # generated/soapRemoteDiscoveryBindingProxy.h - # generated/soapRemoteDiscoveryBindingService.h - ) + # generated/soapRemoteDiscoveryBindingProxy.h + # generated/soapRemoteDiscoveryBindingService.h + ) # public header set(public_header_files - OnvifDiscoveryClient.h - DeleterDuplicator.h - # OnvifDiscover.h - generated/soapwsddProxy.h - OnvifDiscovery.h - DiscoveryMatch.h - ) + OnvifDiscoveryClient.h + DeleterDuplicator.h + # OnvifDiscover.h + generated/soapwsddProxy.h + OnvifDiscovery.h + DiscoveryMatch.h + ) add_library(onvifdiscovery ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifdiscovery EXPORT_FILE_NAME OnvifDiscoveryExport.h) target_link_libraries(onvifdiscovery onvifcommon) set_target_properties(onvifdiscovery PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifDiscoveryExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifdiscovery) -endif() # -------------------------------ONVIF Replay------------------------------- set(src_files - generated/soapReplayBindingProxy.cpp - #generated/soapReplayBindingService.cpp - OnvifReplayClient.cpp - ) + generated/soapReplayBindingProxy.cpp + #generated/soapReplayBindingService.cpp + OnvifReplayClient.cpp + ) # private header set(private_header_files - generated/soapReplayBindingProxy.h - #generated/soapReplayBindingService.h - ) + generated/soapReplayBindingProxy.h + #generated/soapReplayBindingService.h + ) # public header set(public_header_files - OnvifReplayClient.h - ) + OnvifReplayClient.h + ) add_library(onvifreplay ${src_files} ${private_header_files} ${public_header_files}) generate_export_header(onvifreplay EXPORT_FILE_NAME OnvifReplayExport.h) target_link_libraries(onvifreplay onvifcommon) set_target_properties(onvifreplay PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifReplayExport.h") -if(USE_PRECOMPILED_HEADERS) - cotire(onvifreplay) -endif() + +# -------------------------------Device Probe------------------------------- +set(src_files + DeviceProbe.cpp + ) + +# private header +set(private_header_files + ) + +# public header +set(public_header_files + DeviceProbe.h + ) + +add_library(onvifprobe ${src_files} ${private_header_files} ${public_header_files}) +generate_export_header(onvifprobe EXPORT_FILE_NAME OnvifProbeExport.h) +target_link_libraries(onvifprobe onvifcommon onvifdevice) +set_target_properties(onvifprobe PROPERTIES PUBLIC_HEADER "${public_header_files};${CMAKE_CURRENT_BINARY_DIR}/OnvifProbeExport.h") # ------------------------------------------------------------------------- # info tool set(src_files - main.cpp - CmdLineParser.cpp - OnvifDevice.cpp - ) + main.cpp + CmdLineParser.cpp + OnvifDevice.cpp + ) # private header set(private_header_files - CmdLineParser.h - OnvifDevice.h - ) + CmdLineParser.h + OnvifDevice.h + ) add_executable(onvifinfo ${src_files} ${private_header_files}) -target_link_libraries(onvifinfo onvifcommon onvifdevice onvifdiscovery onvifreplay onvifrecording onvifreceiver onvifptz onvifmedia onvifmedia2 onvifimaging onvifevent onvifdisplay onvifanalytics) -if(USE_PRECOMPILED_HEADERS) - cotire(onvifinfo) -endif() +target_link_libraries(onvifinfo onvifcommon onvifdevice onvifdiscovery onvifreplay onvifprobe onvifrecording onvifreceiver onvifptz onvifmedia onvifmedia2 onvifimaging onvifevent onvifdisplay onvifanalytics) + +if (MSVC) + set_target_properties(onvifinfo onvifcommon onvifdevice onvifdiscovery onvifreplay onvifprobe onvifrecording onvifreceiver onvifptz onvifmedia onvifmedia2 onvifimaging onvifevent onvifdisplay onvifanalytics PROPERTIES COMPILE_FLAGS "/bigobj") +endif () -if(MSVC) - set_target_properties(onvifinfo onvifcommon onvifdevice onvifdiscovery onvifreplay onvifrecording onvifreceiver onvifptz onvifmedia onvifmedia2 onvifimaging onvifevent onvifdisplay onvifanalytics PROPERTIES COMPILE_FLAGS "/bigobj") -endif() +if (ANDROID) + target_link_libraries(onvifinfo log.so z.so) +endif () set(install_root "${CMAKE_INSTALL_PREFIX}") set(install_include_dir "${install_root}/include") @@ -518,28 +534,29 @@ set(BIN_INSTALL_DIR "bin") set(LIB_INSTALL_DIR "lib") configure_package_config_file("${PROJECT_SOURCE_DIR}/CMake/libONVIFConfig.cmake.in" "${PROJECT_BINARY_DIR}/libONVIFConfig.cmake" INSTALL_DESTINATION cmake - PATH_VARS INCLUDE_INSTALL_DIR CMAKE_INSTALL_DIR BIN_INSTALL_DIR LIB_INSTALL_DIR) + PATH_VARS INCLUDE_INSTALL_DIR CMAKE_INSTALL_DIR BIN_INSTALL_DIR LIB_INSTALL_DIR) write_basic_package_version_file("${PROJECT_BINARY_DIR}/libONVIFVersion.cmake" VERSION "${info.version.major}.${info.version.minor}.${info.version.patch}" COMPATIBILITY SameMajorVersion) # add the install target install(TARGETS - onvifinfo - onvifcommon - onvifdevice - onvifdiscovery - onvifreplay - onvifrecording - onvifreceiver - onvifptz - onvifmedia - onvifmedia2 - onvifimaging - onvifevent - onvifdisplay - onvifanalytics - EXPORT libONVIFTargets RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib PUBLIC_HEADER DESTINATION include - ) + onvifinfo + onvifcommon + onvifdevice + onvifdiscovery + onvifreplay + onvifprobe + onvifrecording + onvifreceiver + onvifptz + onvifmedia + onvifmedia2 + onvifimaging + onvifevent + onvifdisplay + onvifanalytics + EXPORT libONVIFTargets RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib PUBLIC_HEADER DESTINATION include + ) install(EXPORT libONVIFTargets DESTINATION cmake) diff --git a/src/Client.cpp b/src/Client.cpp index d4a00c1..a7a8946 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -14,13 +14,13 @@ * along with this program.If not, see < http://www.gnu.org/licenses/>. */ #include "Client.h" -#include "soapH.h" #include "SoapAuthHandler.h" +#include "soapH.h" +#include #include +#include #include #include -#include -#include struct ClientPrivate { @@ -72,35 +72,6 @@ void Client::ReleaseCtx(soap *pCtx) { } } -void Client::DisableAuth() { - - mpD->mCtx->DisableAuth(); -} - -void Client::SetAuth(const QString &rUserName, const QString &rPassword, AuthMode mode /* = AUTO */) { - - auto authMode = AuthHandlerMode::AUTO; - switch(mode) { - case NO_AUTH: - authMode = AuthHandlerMode::NO_AUTH; - break; - case HTTP_DIGEST: - authMode = AuthHandlerMode::HTTP_DIGEST; - break; - case WS_USERNAME_TOKEN: - authMode = AuthHandlerMode::WS_USERNAME_TOKEN; - break; - case BOTH: - authMode = AuthHandlerMode::BOTH; - break; - case AUTO: - default: - authMode = AuthHandlerMode::AUTO; - break; - } - mpD->mCtx->SetAuth(rUserName, rPassword, authMode); -} - QString Client::GetFaultString() { return mpD->mCtx->GetFaultString(); diff --git a/src/Client.h b/src/Client.h index b5ef184..dddfb10 100644 --- a/src/Client.h +++ b/src/Client.h @@ -37,7 +37,7 @@ class ONVIFCOMMON_EXPORT Client : public QObject { Q_OBJECT -public: + public: /*! * * \brief Construct a new client @@ -52,16 +52,6 @@ class ONVIFCOMMON_EXPORT Client : public QObject { */ explicit Client(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); ~Client() override; - /*! - * \deprecated Use SoapCtx::SetAuth instead - */ - Q_DECL_DEPRECATED - virtual void SetAuth(const QString &rUserName, const QString &rPassword, AuthMode mode = AUTO); - /*! - * \deprecated Use SoapCtx::DisableAuth instead - */ - Q_DECL_DEPRECATED - virtual void DisableAuth(); /*! * * \brief Get the soap context which is used by the client. The context can be shared between multiple clients @@ -83,7 +73,7 @@ class ONVIFCOMMON_EXPORT Client : public QObject { //! If this client is currently doing a request it will be canceled immediately. Otherwise nothing happens. void CancelRequest(); -protected: + protected: //! Service implementations use this to acquire/init a raw soap context. releaseCtx must be called afterwards soap *AcquireCtx(); //! Service implementations use this to acquire/init a raw soap context. releaseCtx must be called afterwards if successful. @@ -95,7 +85,7 @@ class ONVIFCOMMON_EXPORT Client : public QObject { //! (needed because of HTTP digest authentication) int Retry(soap *pCtx) const; -private: + private: Q_DISABLE_COPY(Client); ClientPrivate *mpD; diff --git a/src/DeviceProbe.cpp b/src/DeviceProbe.cpp new file mode 100644 index 0000000..d35257c --- /dev/null +++ b/src/DeviceProbe.cpp @@ -0,0 +1,215 @@ +// +// Created by bjoern on 16.04.22. +// +#include "DeviceProbe.h" +#include "global.h" +#include +#include "OnvifDeviceClient.h" +#include +#include + +Q_LOGGING_CATEGORY(pr, "DeviceProbe") + +class DeviceProbePrivate { + +public: + explicit DeviceProbePrivate() : + mEndpoint(), + mError(), + mFirmwareVersion(), + mHardwareId(), + mManufacturer(), + mModel(), + mSerialNumber(), + mDateTimeOffset(0), + mEndpointReference(), + mServices() {} + + QUrl mEndpoint; + QString mError; + QString mFirmwareVersion; + QString mHardwareId; + QString mManufacturer; + QString mModel; + QString mSerialNumber; + qint64 mDateTimeOffset; + QUuid mEndpointReference; + QList mServices; +}; + +DeviceProbe::DeviceProbe() : mpD(new DeviceProbePrivate()) {} + +DeviceProbe::~DeviceProbe() { + + delete mpD; +} + +DeviceProbe::DeviceProbe(const DeviceProbe &rOther) : mpD(new DeviceProbePrivate()) { + + *mpD = *rOther.mpD; +} + +DeviceProbe &DeviceProbe::operator=(const DeviceProbe &rOther) { + + if(&rOther == this) { + return *this; + } + *this->mpD = *rOther.mpD; + return *this; +} + +DeviceProbe::DeviceProbe(const QUrl &rDeviceEndpoint) : DeviceProbe::DeviceProbe() { + + mpD->mEndpoint = rDeviceEndpoint; + QScopedPointer mpDeviceClient(new OnvifDeviceClient(rDeviceEndpoint)); + + if(mpDeviceClient->GetEndpoint().isValid()) { + Request<_tds__GetSystemDateAndTime> dateTimeRequest; + auto timestamp = QDateTime::currentMSecsSinceEpoch(); + auto dateTimeResponse = mpDeviceClient->GetSystemDateAndTime(dateTimeRequest); + if(dateTimeResponse) { + if(auto sysDateTime = dateTimeResponse.GetResultObject()->SystemDateAndTime) { + bool daylightSaving = sysDateTime->DaylightSavings; + if(sysDateTime->UTCDateTime && sysDateTime->UTCDateTime->Time && sysDateTime->UTCDateTime->Date) { + auto deviceTime = + QTime(sysDateTime->UTCDateTime->Time->Hour, sysDateTime->UTCDateTime->Time->Minute, sysDateTime->UTCDateTime->Time->Second); + auto deviceDate = + QDate(sysDateTime->UTCDateTime->Date->Year, sysDateTime->UTCDateTime->Date->Month, sysDateTime->UTCDateTime->Date->Day); + auto currentDateTime = QDateTime::currentDateTimeUtc(); + auto rtt = currentDateTime.toMSecsSinceEpoch() - timestamp; + mpD->mDateTimeOffset = currentDateTime.addMSecs(-std::llround(rtt / 2)).msecsTo(QDateTime(deviceDate, deviceTime, Qt::UTC)); + } else { + qWarning(pr) << "Couldn't extract device UTC date time"; + } + } else { + qWarning(pr) << "Couldn't extract device date time"; + } + + Request<_tds__GetDeviceInformation> deviceInfoRequest; + auto infoResponse = mpDeviceClient->GetDeviceInformation(deviceInfoRequest); + if(infoResponse) { + if(auto info = infoResponse.GetResultObject()) { + mpD->mModel = info->Model; + mpD->mManufacturer = info->Manufacturer; + mpD->mSerialNumber = info->SerialNumber; + } + + Request<_tds__GetServices> servicesRequest; + servicesRequest.IncludeCapability = false; + auto response = mpDeviceClient->GetServices(servicesRequest); + if(response) { + auto services = response.GetResultObject(); + for(auto service : services->Service) { + if(service->Namespace == SOAP_NAMESPACE_OF_tds) { + // Device Service + mpD->mServices.push_back(DeviceProbe::ONVIF_DEVICE); + } else if(service->Namespace == SOAP_NAMESPACE_OF_tev) { + // Event Service + mpD->mServices.push_back(DeviceProbe::ONVIF_EVENT); + } else if(service->Namespace == SOAP_NAMESPACE_OF_trt) { + // Media Service + mpD->mServices.push_back(DeviceProbe::ONVIF_MEDIA); + } else if(service->Namespace == SOAP_NAMESPACE_OF_tr2) { + // Media2 Service + mpD->mServices.push_back(DeviceProbe::ONVIF_MEDIA2); + } else if(service->Namespace == SOAP_NAMESPACE_OF_tan) { + // Analytics Service + mpD->mServices.push_back(DeviceProbe::ONVIF_ANALYTICS); + } else if(service->Namespace == SOAP_NAMESPACE_OF_tls) { + // Display Service + mpD->mServices.push_back(DeviceProbe::ONVIF_DISPLAY); + } else if(service->Namespace == SOAP_NAMESPACE_OF_timg) { + // Imaging Service + mpD->mServices.push_back(DeviceProbe::ONVIF_IMAGING); + } else if(service->Namespace == SOAP_NAMESPACE_OF_tptz) { + // Ptz Service + mpD->mServices.push_back(DeviceProbe::ONVIF_PTZ); + } else if(service->Namespace == SOAP_NAMESPACE_OF_trv) { + // Receiver Service + mpD->mServices.push_back(DeviceProbe::ONVIF_RECEIVER); + } else if(service->Namespace == SOAP_NAMESPACE_OF_trc) { + // Recording Service + mpD->mServices.push_back(DeviceProbe::ONVIF_RECORDING); + } else if(service->Namespace == SOAP_NAMESPACE_OF_trp) { + // Replay Service + mpD->mServices.push_back(DeviceProbe::ONVIF_REPLAY); + } else { + qInfo(pr) << "Skipping unsupported service:" << service->Namespace; + } + } + } else { + qWarning(pr) << "Couldn't get device services:" << response; + mpD->mError = response.GetCompleteFault(); + } + } else { + qWarning(pr) << "Couldn't get device info" << infoResponse; + mpD->mError = infoResponse.GetCompleteFault(); + } + } else { + qWarning(pr) << "Couldn't get device date and time:" << dateTimeResponse; + mpD->mError = dateTimeResponse.GetCompleteFault(); + } + } else { + qWarning(pr) << "Couldn't init device - invalid endpoint: " << mpDeviceClient->GetEndpoint(); + mpD->mError = QObject::tr("Invalid Endpoint url: %1").arg(mpDeviceClient->GetEndpoint().toString()); + } +} + +DeviceProbe DeviceProbe::create(const QUrl &rDeviceEndpoint) { + + return {rDeviceEndpoint}; +} + +bool DeviceProbe::IsValid() const { + + return GetDeviceEndpoint().isValid(); +} + +QUrl DeviceProbe::GetDeviceEndpoint() const { + + return mpD->mEndpoint; +} + +QString DeviceProbe::GetError() const { + + return mpD->mError; +} +QString DeviceProbe::GetFirmwareVersion() const { + + return mpD->mFirmwareVersion; +} + +QString DeviceProbe::GetHardwareId() const { + + return mpD->mHardwareId; +} + +QString DeviceProbe::GetManufacturer() const { + + return mpD->mManufacturer; +} + +QString DeviceProbe::GetModel() const { + + return mpD->mModel; +} + +QString DeviceProbe::GetSerialNumber() const { + + return mpD->mSerialNumber; +} + +qint64 DeviceProbe::GetDateTimeOffset() const { + + return mpD->mDateTimeOffset; +} + +QUuid DeviceProbe::GetEndpointReference() const { + + return mpD->mEndpointReference; +} + +QList DeviceProbe::GetServices() const { + + return mpD->mServices; +} diff --git a/src/DeviceProbe.h b/src/DeviceProbe.h new file mode 100644 index 0000000..c044f36 --- /dev/null +++ b/src/DeviceProbe.h @@ -0,0 +1,77 @@ +/* Copyright(C) 2022 Björn Stresing + * + * This program is free software : you can redistribute it and / or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.If not, see < http://www.gnu.org/licenses/>. + */ +#pragma once +#include "global.h" +#include +#include +#include "OnvifProbeExport.h" + +struct DeviceProbePrivate; + +class ONVIFPROBE_EXPORT DeviceProbe { + + Q_GADGET + Q_PROPERTY(QUrl deviceEndpoint READ GetDeviceEndpoint CONSTANT) + Q_PROPERTY(QString initializationError READ GetError CONSTANT) + Q_PROPERTY(QString firmwareVersion READ GetFirmwareVersion CONSTANT) + Q_PROPERTY(QString hardwareId READ GetHardwareId CONSTANT) + Q_PROPERTY(QString manufacturer READ GetManufacturer CONSTANT) + Q_PROPERTY(QString model READ GetModel CONSTANT) + Q_PROPERTY(QString serialNumber READ GetSerialNumber CONSTANT) + Q_PROPERTY(qint64 dateTimeOffset READ GetDateTimeOffset CONSTANT) + Q_PROPERTY(QUuid endpointReference READ GetEndpointReference CONSTANT) + Q_PROPERTY(QList services READ GetServices CONSTANT) + +public: + static DeviceProbe create(const QUrl &rDeviceEndpoint); + + DeviceProbe(); + ~DeviceProbe(); + DeviceProbe(const DeviceProbe &rOther); + DeviceProbe &operator=(const DeviceProbe &rOther); + + enum OnvifServicesTye { + ONVIF_DEVICE = 1 << 0, + ONVIF_EVENT = 1 << 1, + ONVIF_MEDIA = 1 << 2, + ONVIF_MEDIA2 = 1 << 3, + ONVIF_ANALYTICS = 1 << 4, + ONVIF_DISPLAY = 1 << 5, + ONVIF_IMAGING = 1 << 6, + ONVIF_PTZ = 1 << 7, + ONVIF_RECEIVER = 1 << 8, + ONVIF_RECORDING = 1 << 9, + ONVIF_REPLAY = 1 << 10 + }; + QML_ENUM(OnvifServicesTye) + + bool IsValid() const; + + QUrl GetDeviceEndpoint() const; + QString GetError() const; + QString GetFirmwareVersion() const; + QString GetHardwareId() const; + QString GetManufacturer() const; + QString GetModel() const; + QString GetSerialNumber() const; + qint64 GetDateTimeOffset() const; + QUuid GetEndpointReference() const; + QList GetServices() const; + +private: + DeviceProbe(const QUrl &rDeviceEndpoint); + DeviceProbePrivate *mpD; +}; diff --git a/src/DiscoveryMatch.cpp b/src/DiscoveryMatch.cpp index 01b2083..942ef82 100644 --- a/src/DiscoveryMatch.cpp +++ b/src/DiscoveryMatch.cpp @@ -21,16 +21,6 @@ DiscoveryMatch::DiscoveryMatch() : mDeviceEndpoints(), mTypes(), mScopes(), mEnd DiscoveryMatch::~DiscoveryMatch() = default; -QUrl DiscoveryMatch::GetDeviceEndpoint() const { - - return !mDeviceEndpoints.isEmpty() ? mDeviceEndpoints.first() : QUrl(); -} - -void DiscoveryMatch::SetDeviceEndpoint(const QUrl &rDeviceEndpoint) { - - mDeviceEndpoints = {rDeviceEndpoint}; -} - QList DiscoveryMatch::GetDeviceEndpoints() const { return mDeviceEndpoints; diff --git a/src/DiscoveryMatch.h b/src/DiscoveryMatch.h index b16dee8..73b99e9 100644 --- a/src/DiscoveryMatch.h +++ b/src/DiscoveryMatch.h @@ -15,10 +15,11 @@ */ #pragma once #include "OnvifDiscoveryExport.h" +#include "global.h" +#include #include #include #include -#include /*! @@ -28,36 +29,26 @@ */ class ONVIFDISCOVERY_EXPORT DiscoveryMatch { -public: + public: DiscoveryMatch(); virtual ~DiscoveryMatch(); - /*! - * \deprecated Use DiscoveryMatch::GetDeviceEndpoints instead - */ - Q_DECL_DEPRECATED - QUrl GetDeviceEndpoint() const; - /*! - * \deprecated Use DiscoveryMatch::SetDeviceEndpoints instead - */ - Q_DECL_DEPRECATED - void SetDeviceEndpoint(const QUrl &rDeviceEndpoint); QList GetDeviceEndpoints() const; void SetDeviceEndpoints(const QList &rDeviceEndpoint); QStringList GetTypes() const; void SetTypes(const QStringList &rTypes); - QStringList GetScopes() const; + QStringList GetScopes() const; // Can be url/percent encoded void SetScopes(const QStringList &rScopes); QUuid GetEndpointReference() const; void SetEndpointReference(const QUuid &rReference); bool operator==(const DiscoveryMatch &rOther) const; bool operator!=(const DiscoveryMatch &rOther) const; -private: + private: QList mDeviceEndpoints; QStringList mTypes; QStringList mScopes; QUuid mEndpointReference; }; -Q_DECLARE_METATYPE(DiscoveryMatch); +REGISTER_METATYPE(DiscoveryMatch) diff --git a/src/OnvifAnalyticsClient.h b/src/OnvifAnalyticsClient.h index 93be925..f315810 100644 --- a/src/OnvifAnalyticsClient.h +++ b/src/OnvifAnalyticsClient.h @@ -19,7 +19,6 @@ #include "Client.h" #include "OnvifAnalyticsExport.h" - struct OnvifAnalyticsClientPrivate; /*! @@ -32,10 +31,11 @@ class ONVIFANALYTICS_EXPORT OnvifAnalyticsClient : public Client { Q_OBJECT public: - OnvifAnalyticsClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); + OnvifAnalyticsClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); virtual ~OnvifAnalyticsClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver20/analytics/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_tan; } Response<_tad__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_tad__GetServiceCapabilities> &rRequest); Response<_tad__DeleteAnalyticsEngineControlResponse> DeleteAnalyticsEngineControl(Request<_tad__DeleteAnalyticsEngineControl> &rRequest); Response<_tad__CreateAnalyticsEngineControlResponse> CreateAnalyticsEngineControl(Request<_tad__CreateAnalyticsEngineControl> &rRequest); @@ -44,11 +44,13 @@ class ONVIFANALYTICS_EXPORT OnvifAnalyticsClient : public Client { Response<_tad__GetAnalyticsEngineControlsResponse> GetAnalyticsEngineControls(Request<_tad__GetAnalyticsEngineControls> &rRequest); Response<_tad__GetAnalyticsEngineResponse> GetAnalyticsEngine(Request<_tad__GetAnalyticsEngine> &rRequest); Response<_tad__GetAnalyticsEnginesResponse> GetAnalyticsEngines(Request<_tad__GetAnalyticsEngines> &rRequest); - Response<_tad__SetVideoAnalyticsConfigurationResponse> SetVideoAnalyticsConfiguration(Request<_tad__SetVideoAnalyticsConfiguration> &rRequest); + Response<_tad__SetVideoAnalyticsConfigurationResponse> + SetVideoAnalyticsConfiguration(Request<_tad__SetVideoAnalyticsConfiguration> &rRequest); Response<_tad__GetAnalyticsEngineInputResponse> GetAnalyticsEngineInput(Request<_tad__GetAnalyticsEngineInput> &rRequest); Response<_tad__GetAnalyticsEngineInputsResponse> GetAnalyticsEngineInputs(Request<_tad__GetAnalyticsEngineInputs> &rRequest); Response<_tad__GetAnalyticsDeviceStreamUriResponse> GetAnalyticsDeviceStreamUri(Request<_tad__GetAnalyticsDeviceStreamUri> &rRequest); - Response<_tad__GetVideoAnalyticsConfigurationResponse> GetVideoAnalyticsConfiguration(Request<_tad__GetVideoAnalyticsConfiguration> &rRequest); + Response<_tad__GetVideoAnalyticsConfigurationResponse> + GetVideoAnalyticsConfiguration(Request<_tad__GetVideoAnalyticsConfiguration> &rRequest); Response<_tad__CreateAnalyticsEngineInputsResponse> CreateAnalyticsEngineInputs(Request<_tad__CreateAnalyticsEngineInputs> &rRequest); Response<_tad__DeleteAnalyticsEngineInputsResponse> DeleteAnalyticsEngineInputs(Request<_tad__DeleteAnalyticsEngineInputs> &rRequest); Response<_tad__GetAnalyticsStateResponse> GetAnalyticsState(Request<_tad__GetAnalyticsState> &rRequest); diff --git a/src/OnvifDevice.cpp b/src/OnvifDevice.cpp index 0f1c223..8ea6d05 100644 --- a/src/OnvifDevice.cpp +++ b/src/OnvifDevice.cpp @@ -20,22 +20,20 @@ #include "OnvifDisplayClient.h" #include "OnvifEventClient.h" #include "OnvifImagingClient.h" -#include "OnvifMediaClient.h" #include "OnvifMedia2Client.h" -#include "OnvifEventClient.h" -#include "OnvifImagingClient.h" +#include "OnvifMediaClient.h" #include "OnvifPtzClient.h" +#include "OnvifPullPoint.h" #include "OnvifReceiverClient.h" #include "OnvifRecordingClient.h" #include "OnvifReplayClient.h" #include "SoapCtx.h" -#include "OnvifDeviceClient.h" #include struct OnvifDevicePrivate { - OnvifDevicePrivate(OnvifDevice *pQ) : + explicit OnvifDevicePrivate(OnvifDevice *pQ) : mpQ(pQ), mUserName(), mPassword(), @@ -61,7 +59,8 @@ struct OnvifDevicePrivate { mpOnvifPtzClient(nullptr), mpOnvifReceiverClient(nullptr), mpOnvifRecordingClient(nullptr), - mpOnvifReplayClient(nullptr) {} + mpOnvifReplayClient(nullptr), + mpOnvifPullPoint(nullptr) {} OnvifDevice *mpQ; QString mUserName; @@ -90,6 +89,7 @@ struct OnvifDevicePrivate { OnvifReceiverClient *mpOnvifReceiverClient; OnvifRecordingClient *mpOnvifRecordingClient; OnvifReplayClient *mpOnvifReplayClient; + OnvifPullPoint *mpOnvifPullPoint; }; OnvifDevice::OnvifDevice(const QUrl &rDeviceEndpoint, QObject *pParent /*= nullptr*/) : @@ -111,13 +111,12 @@ SimpleResponse OnvifDevice::Initialize() { //.EnableOMode(SOAP_XML_INDENT) #endif .Build(); - + if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { + ctx->SetAuth(mpD->mUserName, mpD->mPassword); + } qDebug() << "Using device endpoint: " << mpD->mDeviceEndpoint.toString(); auto device = mpD->mpOnvifDeviceClient = new OnvifDeviceClient(mpD->mDeviceEndpoint, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - device->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } OnvifEventClient *onvifEvent = nullptr; @@ -132,9 +131,6 @@ SimpleResponse OnvifDevice::Initialize() { auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifAnalyticsClient = new OnvifAnalyticsClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifAnalyticsClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } if(service->Namespace == OnvifDeviceClient::GetServiceNamespace()) { qDebug() << "ONVIF device service" @@ -142,90 +138,60 @@ SimpleResponse OnvifDevice::Initialize() { auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifDeviceClient = new OnvifDeviceClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifDeviceClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifDisplayClient::GetServiceNamespace()) { qDebug() << "ONVIF display service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifDisplayClient = new OnvifDisplayClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifDisplayClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifEventClient::GetServiceNamespace()) { qDebug() << "ONVIF event service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifEventClient = new OnvifEventClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifEventClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifImagingClient::GetServiceNamespace()) { qDebug() << "ONVIF imaging service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifImagingClient = new OnvifImagingClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifImagingClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifMediaClient::GetServiceNamespace()) { qDebug() << "ONVIF media service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifMediaClient = new OnvifMediaClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifMediaClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifMedia2Client::GetServiceNamespace()) { qDebug() << "ONVIF media2 service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifMedia2Client = new OnvifMedia2Client(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifMedia2Client->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifPtzClient::GetServiceNamespace()) { qDebug() << "ONVIF ptz service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifPtzClient = new OnvifPtzClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifPtzClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifReceiverClient::GetServiceNamespace()) { qDebug() << "ONVIF receiver service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifReceiverClient = new OnvifReceiverClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifReceiverClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifRecordingClient::GetServiceNamespace()) { qDebug() << "ONVIF recording service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifRecordingClient = new OnvifRecordingClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifRecordingClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else if(service->Namespace == OnvifReplayClient::GetServiceNamespace()) { qDebug() << "ONVIF replay service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); auto url = QUrl(qPrintable(service->XAddr)); url.setPort(mpD->mDeviceEndpoint.port()); mpD->mpOnvifReplayClient = new OnvifReplayClient(url, ctx, this); - if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { - mpD->mpOnvifReplayClient->SetAuth(mpD->mUserName, mpD->mPassword, AUTO); - } } else { qDebug() << "Unknown service" << "namespace:" << qPrintable(service->Namespace) << "Url:" << qPrintable(service->XAddr); @@ -311,3 +277,67 @@ void OnvifDevice::SetAuth(const QString &rUserName, const QString &rPassword, Au mpD->mUserName = rUserName; mpD->mPassword = rPassword; } + +void OnvifDevice::SubscribePullPoint() { + + if(mpD->mpOnvifEventClient) { + auto ctx = QSharedPointer::create(); + if(!mpD->mUserName.isNull() || !mpD->mPassword.isNull()) { + ctx->SetAuth(mpD->mUserName, mpD->mPassword); + } + mpD->mpOnvifPullPoint = new OnvifPullPoint(mpD->mpOnvifEventClient->GetEndpoint(), ctx, this); + connect(mpD->mpOnvifPullPoint, &OnvifPullPoint::LostPullPoint, this, &OnvifDevice::LostPullPoint); + connect(mpD->mpOnvifPullPoint, &OnvifPullPoint::UnsuccessfulPull, this, &OnvifDevice::UnsuccessfulPull); + connect(mpD->mpOnvifPullPoint, &OnvifPullPoint::MessageReceived, this, &OnvifDevice::MessageReceived); + connect(mpD->mpOnvifPullPoint, &OnvifPullPoint::ResumedPullPoint, this, &OnvifDevice::ResumedPullPoint); + mpD->mpOnvifPullPoint->Start(); + } else { + qWarning() << "Missing ONVIF event service - could not start pullpoint"; + } +} + +void OnvifDevice::UnsuccessfulPull(int unsuccessfulPullcount, const SimpleResponse &rCause) { + + qWarning() << "Unsuccessful pull" << rCause; +} + +void OnvifDevice::MessageReceived(const Response &rResponse) { + + if(auto result = rResponse.GetResultObject()) { + qDebug() << ""; + qDebug() << "pullpoint message"; + if(result->Topic) { + qDebug() << " Topic Dialect" << result->Topic->Dialect; + } + if(result->Message.Message) { + qDebug() << " Source"; + OnvifDevice::PrintItemList(result->Message.Message->Source); + qDebug() << " Key"; + OnvifDevice::PrintItemList(result->Message.Message->Key); + qDebug() << " Data"; + OnvifDevice::PrintItemList(result->Message.Message->Data); + } + } +} + +void OnvifDevice::LostPullPoint(const SimpleResponse &rCause) { + + qWarning() << "Lost pullpoint pull" << rCause; +} + +void OnvifDevice::ResumedPullPoint() { + + qWarning() << "Resumed pullpoint"; +} + +void OnvifDevice::PrintItemList(tt__ItemList *list) { + + if(list) { + for(const auto &entry : list->SimpleItem) { + qDebug() << " Name" << entry.Name << "Value" << entry.Value; + } + for(const auto &entry : list->ElementItem) { + qDebug() << " Name" << entry.Name; + } + } +} diff --git a/src/OnvifDevice.h b/src/OnvifDevice.h index e7361ef..581c50d 100644 --- a/src/OnvifDevice.h +++ b/src/OnvifDevice.h @@ -14,8 +14,8 @@ * along with this program.If not, see < http://www.gnu.org/licenses/>. */ #pragma once -#include "Response.h" #include "Client.h" +#include "Response.h" #include #include @@ -26,14 +26,21 @@ class OnvifDevice : public QObject { Q_OBJECT -public: - OnvifDevice(const QUrl &rDeviceEndpoint, QObject *pParent = nullptr); - virtual ~OnvifDevice(); + public: + explicit OnvifDevice(const QUrl &rDeviceEndpoint, QObject *pParent = nullptr); + ~OnvifDevice() override; void SetAuth(const QString &rUserName, const QString &rPassword, AuthMode mode = AUTO); SimpleResponse Initialize(); SimpleResponse InitializeTopicSet(); + void SubscribePullPoint(); + + private: + void UnsuccessfulPull(int unsuccessfulPullcount, const SimpleResponse &rCause); + void MessageReceived(const Response &rResponse); + void LostPullPoint(const SimpleResponse &rCause); + void ResumedPullPoint(); + static void PrintItemList(tt__ItemList *list); -private: OnvifDevicePrivate *mpD; }; \ No newline at end of file diff --git a/src/OnvifDeviceClient.h b/src/OnvifDeviceClient.h index 1d87f2d..962c9d8 100644 --- a/src/OnvifDeviceClient.h +++ b/src/OnvifDeviceClient.h @@ -19,23 +19,23 @@ #include "Client.h" #include "OnvifDeviceExport.h" - struct OnvifDeviceClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Device -* -*/ + * + * \brief Client side service implementations of Onvif Device + * + */ class ONVIFDEVICE_EXPORT OnvifDeviceClient : public Client { Q_OBJECT public: - OnvifDeviceClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); + OnvifDeviceClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); virtual ~OnvifDeviceClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver10/device/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_tds; } Response<_tds__GetServicesResponse> GetServices(Request<_tds__GetServices> &rRequest); Response<_tds__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_tds__GetServiceCapabilities> &rRequest); Response<_tds__GetDeviceInformationResponse> GetDeviceInformation(Request<_tds__GetDeviceInformation> &rRequest); @@ -104,7 +104,8 @@ class ONVIFDEVICE_EXPORT OnvifDeviceClient : public Client { Response<_tds__SetRelayOutputStateResponse> SetRelayOutputState(Request<_tds__SetRelayOutputState> &rRequest); Response<_tds__SendAuxiliaryCommandResponse> SendAuxiliaryCommand(Request<_tds__SendAuxiliaryCommand> &rRequest); Response<_tds__GetCACertificatesResponse> GetCACertificates(Request<_tds__GetCACertificates> &rRequest); - Response<_tds__LoadCertificateWithPrivateKeyResponse> LoadCertificateWithPrivateKey(Request<_tds__LoadCertificateWithPrivateKey> &rRequest); + Response<_tds__LoadCertificateWithPrivateKeyResponse> + LoadCertificateWithPrivateKey(Request<_tds__LoadCertificateWithPrivateKey> &rRequest); Response<_tds__GetCertificateInformationResponse> GetCertificateInformation(Request<_tds__GetCertificateInformation> &rRequest); Response<_tds__LoadCACertificatesResponse> LoadCACertificates(Request<_tds__LoadCACertificates> &rRequest); Response<_tds__CreateDot1XConfigurationResponse> CreateDot1XConfiguration(Request<_tds__CreateDot1XConfiguration> &rRequest); diff --git a/src/OnvifDisplayClient.h b/src/OnvifDisplayClient.h index 3d81b1a..0f7022e 100644 --- a/src/OnvifDisplayClient.h +++ b/src/OnvifDisplayClient.h @@ -19,33 +19,33 @@ #include "Client.h" #include "OnvifDisplayExport.h" - struct OnvifDisplayClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Display -* -*/ + * + * \brief Client side service implementations of Onvif Display + * + */ class ONVIFDISPLAY_EXPORT OnvifDisplayClient : public Client { Q_OBJECT public: - OnvifDisplayClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); + OnvifDisplayClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); virtual ~OnvifDisplayClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver10/display/wsdl"; } - Response<_tls__GetServiceCapabilitiesResponse>GetServiceCapabilities(Request<_tls__GetServiceCapabilities> &rRequest); - Response<_tls__GetLayoutResponse>GetLayout(Request<_tls__GetLayout> &rRequest); - Response<_tls__SetLayoutResponse>SetLayout(Request<_tls__SetLayout> &rRequest); - Response<_tls__GetDisplayOptionsResponse>GetDisplayOptions(Request<_tls__GetDisplayOptions> &rRequest); - Response<_tls__GetPaneConfigurationsResponse>GetPaneConfigurations(Request<_tls__GetPaneConfigurations> &rRequest); - Response<_tls__GetPaneConfigurationResponse>GetPaneConfiguration(Request<_tls__GetPaneConfiguration> &rRequest); - Response<_tls__SetPaneConfigurationsResponse>SetPaneConfigurations(Request<_tls__SetPaneConfigurations> &rRequest); - Response<_tls__SetPaneConfigurationResponse>SetPaneConfiguration(Request<_tls__SetPaneConfiguration> &rRequest); - Response<_tls__CreatePaneConfigurationResponse>CreatePaneConfiguration(Request<_tls__CreatePaneConfiguration> &rRequest); - Response<_tls__DeletePaneConfigurationResponse>DeletePaneConfiguration(Request<_tls__DeletePaneConfiguration> &rRequest); + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_tls; } + Response<_tls__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_tls__GetServiceCapabilities> &rRequest); + Response<_tls__GetLayoutResponse> GetLayout(Request<_tls__GetLayout> &rRequest); + Response<_tls__SetLayoutResponse> SetLayout(Request<_tls__SetLayout> &rRequest); + Response<_tls__GetDisplayOptionsResponse> GetDisplayOptions(Request<_tls__GetDisplayOptions> &rRequest); + Response<_tls__GetPaneConfigurationsResponse> GetPaneConfigurations(Request<_tls__GetPaneConfigurations> &rRequest); + Response<_tls__GetPaneConfigurationResponse> GetPaneConfiguration(Request<_tls__GetPaneConfiguration> &rRequest); + Response<_tls__SetPaneConfigurationsResponse> SetPaneConfigurations(Request<_tls__SetPaneConfigurations> &rRequest); + Response<_tls__SetPaneConfigurationResponse> SetPaneConfiguration(Request<_tls__SetPaneConfiguration> &rRequest); + Response<_tls__CreatePaneConfigurationResponse> CreatePaneConfiguration(Request<_tls__CreatePaneConfiguration> &rRequest); + Response<_tls__DeletePaneConfigurationResponse> DeletePaneConfiguration(Request<_tls__DeletePaneConfiguration> &rRequest); private: Q_DISABLE_COPY(OnvifDisplayClient); diff --git a/src/OnvifEventClient.cpp b/src/OnvifEventClient.cpp index 441a180..25e6392 100644 --- a/src/OnvifEventClient.cpp +++ b/src/OnvifEventClient.cpp @@ -101,7 +101,7 @@ Response<_tev__CreatePullPointSubscriptionResponse> OnvifEventClient::CreatePull auto pSoap = AcquireCtx(); do { soap_wsa_request(pSoap, soap_wsa_rand_uuid(pSoap), qPrintable(GetEndpointString()), action); - auto ret = mpD->mProxy.CreatePullPointSubscription(qPrintable(GetEndpointString()), !rRequest.GetSoapAction().isNull() ? qPrintable(rRequest.GetSoapAction()) : nullptr, &rRequest, responseObject); + ret = mpD->mProxy.CreatePullPointSubscription(qPrintable(GetEndpointString()), !rRequest.GetSoapAction().isNull() ? qPrintable(rRequest.GetSoapAction()) : nullptr, &rRequest, responseObject); } while(Retry(pSoap)); auto response = Response<_tev__CreatePullPointSubscriptionResponse>::Builder(); response.From(GetCtx(), &responseObject); diff --git a/src/OnvifEventClient.h b/src/OnvifEventClient.h index 72c92a0..1fe5b8f 100644 --- a/src/OnvifEventClient.h +++ b/src/OnvifEventClient.h @@ -21,14 +21,13 @@ #include "OnvifEventExport.h" #include "Topics.h" - struct OnvifEventClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Event -* -*/ + * + * \brief Client side service implementations of Onvif Event + * + */ class ONVIFEVENT_EXPORT OnvifEventClient : public Client { Q_OBJECT @@ -37,7 +36,7 @@ class ONVIFEVENT_EXPORT OnvifEventClient : public Client { OnvifEventClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); virtual ~OnvifEventClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver10/events/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_tev; } Response<_tev__CreatePullPointSubscriptionResponse> CreatePullPointSubscription(Request<_tev__CreatePullPointSubscription> &rRequest); Response<_tev__PullMessagesResponse> PullMessages(Request<_tev__PullMessages> &rRequest); Response<_wsnt__RenewResponse> Renew(Request<_wsnt__Renew> &rRequest); diff --git a/src/OnvifImagingClient.h b/src/OnvifImagingClient.h index 418f456..a9b4a33 100644 --- a/src/OnvifImagingClient.h +++ b/src/OnvifImagingClient.h @@ -19,23 +19,23 @@ #include "Client.h" #include "OnvifImagingExport.h" - struct OnvifImagingClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Imaging -* -*/ + * + * \brief Client side service implementations of Onvif Imaging + * + */ class ONVIFIMAGING_EXPORT OnvifImagingClient : public Client { Q_OBJECT public: - OnvifImagingClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); + OnvifImagingClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); virtual ~OnvifImagingClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver20/imaging/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_timg; } Response<_timg__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_timg__GetServiceCapabilities> &rRequest); Response<_timg__GetImagingSettingsResponse> GetImagingSettings(Request<_timg__GetImagingSettings> &rRequest); Response<_timg__SetImagingSettingsResponse> SetImagingSettings(Request<_timg__SetImagingSettings> &rRequest); diff --git a/src/OnvifMedia2Client.h b/src/OnvifMedia2Client.h index b2cbce8..74c346b 100644 --- a/src/OnvifMedia2Client.h +++ b/src/OnvifMedia2Client.h @@ -19,7 +19,6 @@ #include "Client.h" #include "OnvifMedia2Export.h" - struct OnvifMedia2ClientPrivate; /*! @@ -36,7 +35,7 @@ class ONVIFMEDIA2_EXPORT OnvifMedia2Client : public Client { QObject *pParent = nullptr); virtual ~OnvifMedia2Client(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver20/media/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_tr2; } Response<_tr2__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_tr2__GetServiceCapabilities> &rRequest); Response<_tr2__CreateProfileResponse> CreateProfile(Request<_tr2__CreateProfile> &rRequest); Response<_tr2__GetProfilesResponse> GetProfiles(Request<_tr2__GetProfiles> &rRequest); diff --git a/src/OnvifMediaClient.h b/src/OnvifMediaClient.h index f86cb4e..8f97e7c 100644 --- a/src/OnvifMediaClient.h +++ b/src/OnvifMediaClient.h @@ -19,14 +19,13 @@ #include "Client.h" #include "OnvifMediaExport.h" - struct OnvifMediaClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Media -* -*/ + * + * \brief Client side service implementations of Onvif Media + * + */ class ONVIFMEDIA_EXPORT OnvifMediaClient : public Client { Q_OBJECT @@ -35,7 +34,7 @@ class ONVIFMEDIA_EXPORT OnvifMediaClient : public Client { OnvifMediaClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); virtual ~OnvifMediaClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver10/media/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_trt; } Response<_trt__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_trt__GetServiceCapabilities> &rRequest); Response<_trt__GetVideoSourcesResponse> GetVideoSources(Request<_trt__GetVideoSources> &rRequest); Response<_trt__GetAudioSourcesResponse> GetAudioSources(Request<_trt__GetAudioSources> &rRequest); @@ -48,60 +47,90 @@ class ONVIFMEDIA_EXPORT OnvifMediaClient : public Client { Response<_trt__AddAudioEncoderConfigurationResponse> AddAudioEncoderConfiguration(Request<_trt__AddAudioEncoderConfiguration> &rRequest); Response<_trt__AddAudioSourceConfigurationResponse> AddAudioSourceConfiguration(Request<_trt__AddAudioSourceConfiguration> &rRequest); Response<_trt__AddPTZConfigurationResponse> AddPTZConfiguration(Request<_trt__AddPTZConfiguration> &rRequest); - Response<_trt__AddVideoAnalyticsConfigurationResponse> AddVideoAnalyticsConfiguration(Request<_trt__AddVideoAnalyticsConfiguration> &rRequest); + Response<_trt__AddVideoAnalyticsConfigurationResponse> + AddVideoAnalyticsConfiguration(Request<_trt__AddVideoAnalyticsConfiguration> &rRequest); Response<_trt__AddMetadataConfigurationResponse> AddMetadataConfiguration(Request<_trt__AddMetadataConfiguration> &rRequest); Response<_trt__AddAudioOutputConfigurationResponse> AddAudioOutputConfiguration(Request<_trt__AddAudioOutputConfiguration> &rRequest); Response<_trt__AddAudioDecoderConfigurationResponse> AddAudioDecoderConfiguration(Request<_trt__AddAudioDecoderConfiguration> &rRequest); - Response<_trt__RemoveVideoEncoderConfigurationResponse> RemoveVideoEncoderConfiguration(Request<_trt__RemoveVideoEncoderConfiguration> &rRequest); - Response<_trt__RemoveVideoSourceConfigurationResponse> RemoveVideoSourceConfiguration(Request<_trt__RemoveVideoSourceConfiguration> &rRequest); - Response<_trt__RemoveAudioEncoderConfigurationResponse> RemoveAudioEncoderConfiguration(Request<_trt__RemoveAudioEncoderConfiguration> &rRequest); - Response<_trt__RemoveAudioSourceConfigurationResponse> RemoveAudioSourceConfiguration(Request<_trt__RemoveAudioSourceConfiguration> &rRequest); + Response<_trt__RemoveVideoEncoderConfigurationResponse> + RemoveVideoEncoderConfiguration(Request<_trt__RemoveVideoEncoderConfiguration> &rRequest); + Response<_trt__RemoveVideoSourceConfigurationResponse> + RemoveVideoSourceConfiguration(Request<_trt__RemoveVideoSourceConfiguration> &rRequest); + Response<_trt__RemoveAudioEncoderConfigurationResponse> + RemoveAudioEncoderConfiguration(Request<_trt__RemoveAudioEncoderConfiguration> &rRequest); + Response<_trt__RemoveAudioSourceConfigurationResponse> + RemoveAudioSourceConfiguration(Request<_trt__RemoveAudioSourceConfiguration> &rRequest); Response<_trt__RemovePTZConfigurationResponse> RemovePTZConfiguration(Request<_trt__RemovePTZConfiguration> &rRequest); - Response<_trt__RemoveVideoAnalyticsConfigurationResponse> RemoveVideoAnalyticsConfiguration(Request<_trt__RemoveVideoAnalyticsConfiguration> &rRequest); + Response<_trt__RemoveVideoAnalyticsConfigurationResponse> + RemoveVideoAnalyticsConfiguration(Request<_trt__RemoveVideoAnalyticsConfiguration> &rRequest); Response<_trt__RemoveMetadataConfigurationResponse> RemoveMetadataConfiguration(Request<_trt__RemoveMetadataConfiguration> &rRequest); - Response<_trt__RemoveAudioOutputConfigurationResponse> RemoveAudioOutputConfiguration(Request<_trt__RemoveAudioOutputConfiguration> &rRequest); - Response<_trt__RemoveAudioDecoderConfigurationResponse> RemoveAudioDecoderConfiguration(Request<_trt__RemoveAudioDecoderConfiguration> &rRequest); + Response<_trt__RemoveAudioOutputConfigurationResponse> + RemoveAudioOutputConfiguration(Request<_trt__RemoveAudioOutputConfiguration> &rRequest); + Response<_trt__RemoveAudioDecoderConfigurationResponse> + RemoveAudioDecoderConfiguration(Request<_trt__RemoveAudioDecoderConfiguration> &rRequest); Response<_trt__DeleteProfileResponse> DeleteProfile(Request<_trt__DeleteProfile> &rRequest); Response<_trt__GetVideoSourceConfigurationsResponse> GetVideoSourceConfigurations(Request<_trt__GetVideoSourceConfigurations> &rRequest); - Response<_trt__GetVideoEncoderConfigurationsResponse> GetVideoEncoderConfigurations(Request<_trt__GetVideoEncoderConfigurations> &rRequest); + Response<_trt__GetVideoEncoderConfigurationsResponse> + GetVideoEncoderConfigurations(Request<_trt__GetVideoEncoderConfigurations> &rRequest); Response<_trt__GetAudioSourceConfigurationsResponse> GetAudioSourceConfigurations(Request<_trt__GetAudioSourceConfigurations> &rRequest); - Response<_trt__GetAudioEncoderConfigurationsResponse> GetAudioEncoderConfigurations(Request<_trt__GetAudioEncoderConfigurations> &rRequest); - Response<_trt__GetVideoAnalyticsConfigurationsResponse> GetVideoAnalyticsConfigurations(Request<_trt__GetVideoAnalyticsConfigurations> &rRequest); + Response<_trt__GetAudioEncoderConfigurationsResponse> + GetAudioEncoderConfigurations(Request<_trt__GetAudioEncoderConfigurations> &rRequest); + Response<_trt__GetVideoAnalyticsConfigurationsResponse> + GetVideoAnalyticsConfigurations(Request<_trt__GetVideoAnalyticsConfigurations> &rRequest); Response<_trt__GetMetadataConfigurationsResponse> GetMetadataConfigurations(Request<_trt__GetMetadataConfigurations> &rRequest); Response<_trt__GetAudioOutputConfigurationsResponse> GetAudioOutputConfigurations(Request<_trt__GetAudioOutputConfigurations> &rRequest); - Response<_trt__GetAudioDecoderConfigurationsResponse> GetAudioDecoderConfigurations(Request<_trt__GetAudioDecoderConfigurations> &rRequest); + Response<_trt__GetAudioDecoderConfigurationsResponse> + GetAudioDecoderConfigurations(Request<_trt__GetAudioDecoderConfigurations> &rRequest); Response<_trt__GetVideoSourceConfigurationResponse> GetVideoSourceConfiguration(Request<_trt__GetVideoSourceConfiguration> &rRequest); Response<_trt__GetVideoEncoderConfigurationResponse> GetVideoEncoderConfiguration(Request<_trt__GetVideoEncoderConfiguration> &rRequest); Response<_trt__GetAudioSourceConfigurationResponse> GetAudioSourceConfiguration(Request<_trt__GetAudioSourceConfiguration> &rRequest); Response<_trt__GetAudioEncoderConfigurationResponse> GetAudioEncoderConfiguration(Request<_trt__GetAudioEncoderConfiguration> &rRequest); - Response<_trt__GetVideoAnalyticsConfigurationResponse> GetVideoAnalyticsConfiguration(Request<_trt__GetVideoAnalyticsConfiguration> &rRequest); + Response<_trt__GetVideoAnalyticsConfigurationResponse> + GetVideoAnalyticsConfiguration(Request<_trt__GetVideoAnalyticsConfiguration> &rRequest); Response<_trt__GetMetadataConfigurationResponse> GetMetadataConfiguration(Request<_trt__GetMetadataConfiguration> &rRequest); Response<_trt__GetAudioOutputConfigurationResponse> GetAudioOutputConfiguration(Request<_trt__GetAudioOutputConfiguration> &rRequest); Response<_trt__GetAudioDecoderConfigurationResponse> GetAudioDecoderConfiguration(Request<_trt__GetAudioDecoderConfiguration> &rRequest); - Response<_trt__GetCompatibleVideoEncoderConfigurationsResponse> GetCompatibleVideoEncoderConfigurations(Request<_trt__GetCompatibleVideoEncoderConfigurations> &rRequest); - Response<_trt__GetCompatibleVideoSourceConfigurationsResponse> GetCompatibleVideoSourceConfigurations(Request<_trt__GetCompatibleVideoSourceConfigurations> &rRequest); - Response<_trt__GetCompatibleAudioEncoderConfigurationsResponse> GetCompatibleAudioEncoderConfigurations(Request<_trt__GetCompatibleAudioEncoderConfigurations> &rRequest); - Response<_trt__GetCompatibleAudioSourceConfigurationsResponse> GetCompatibleAudioSourceConfigurations(Request<_trt__GetCompatibleAudioSourceConfigurations> &rRequest); - Response<_trt__GetCompatibleVideoAnalyticsConfigurationsResponse> GetCompatibleVideoAnalyticsConfigurations(Request<_trt__GetCompatibleVideoAnalyticsConfigurations> &rRequest); - Response<_trt__GetCompatibleMetadataConfigurationsResponse> GetCompatibleMetadataConfigurations(Request<_trt__GetCompatibleMetadataConfigurations> &rRequest); - Response<_trt__GetCompatibleAudioOutputConfigurationsResponse> GetCompatibleAudioOutputConfigurations(Request<_trt__GetCompatibleAudioOutputConfigurations> &rRequest); - Response<_trt__GetCompatibleAudioDecoderConfigurationsResponse> GetCompatibleAudioDecoderConfigurations(Request<_trt__GetCompatibleAudioDecoderConfigurations> &rRequest); + Response<_trt__GetCompatibleVideoEncoderConfigurationsResponse> + GetCompatibleVideoEncoderConfigurations(Request<_trt__GetCompatibleVideoEncoderConfigurations> &rRequest); + Response<_trt__GetCompatibleVideoSourceConfigurationsResponse> + GetCompatibleVideoSourceConfigurations(Request<_trt__GetCompatibleVideoSourceConfigurations> &rRequest); + Response<_trt__GetCompatibleAudioEncoderConfigurationsResponse> + GetCompatibleAudioEncoderConfigurations(Request<_trt__GetCompatibleAudioEncoderConfigurations> &rRequest); + Response<_trt__GetCompatibleAudioSourceConfigurationsResponse> + GetCompatibleAudioSourceConfigurations(Request<_trt__GetCompatibleAudioSourceConfigurations> &rRequest); + Response<_trt__GetCompatibleVideoAnalyticsConfigurationsResponse> + GetCompatibleVideoAnalyticsConfigurations(Request<_trt__GetCompatibleVideoAnalyticsConfigurations> &rRequest); + Response<_trt__GetCompatibleMetadataConfigurationsResponse> + GetCompatibleMetadataConfigurations(Request<_trt__GetCompatibleMetadataConfigurations> &rRequest); + Response<_trt__GetCompatibleAudioOutputConfigurationsResponse> + GetCompatibleAudioOutputConfigurations(Request<_trt__GetCompatibleAudioOutputConfigurations> &rRequest); + Response<_trt__GetCompatibleAudioDecoderConfigurationsResponse> + GetCompatibleAudioDecoderConfigurations(Request<_trt__GetCompatibleAudioDecoderConfigurations> &rRequest); Response<_trt__SetVideoSourceConfigurationResponse> SetVideoSourceConfiguration(Request<_trt__SetVideoSourceConfiguration> &rRequest); Response<_trt__SetVideoEncoderConfigurationResponse> SetVideoEncoderConfiguration(Request<_trt__SetVideoEncoderConfiguration> &rRequest); Response<_trt__SetAudioSourceConfigurationResponse> SetAudioSourceConfiguration(Request<_trt__SetAudioSourceConfiguration> &rRequest); Response<_trt__SetAudioEncoderConfigurationResponse> SetAudioEncoderConfiguration(Request<_trt__SetAudioEncoderConfiguration> &rRequest); - Response<_trt__SetVideoAnalyticsConfigurationResponse> SetVideoAnalyticsConfiguration(Request<_trt__SetVideoAnalyticsConfiguration> &rRequest); + Response<_trt__SetVideoAnalyticsConfigurationResponse> + SetVideoAnalyticsConfiguration(Request<_trt__SetVideoAnalyticsConfiguration> &rRequest); Response<_trt__SetMetadataConfigurationResponse> SetMetadataConfiguration(Request<_trt__SetMetadataConfiguration> &rRequest); Response<_trt__SetAudioOutputConfigurationResponse> SetAudioOutputConfiguration(Request<_trt__SetAudioOutputConfiguration> &rRequest); Response<_trt__SetAudioDecoderConfigurationResponse> SetAudioDecoderConfiguration(Request<_trt__SetAudioDecoderConfiguration> &rRequest); - Response<_trt__GetVideoSourceConfigurationOptionsResponse> GetVideoSourceConfigurationOptions(Request<_trt__GetVideoSourceConfigurationOptions> &rRequest); - Response<_trt__GetVideoEncoderConfigurationOptionsResponse> GetVideoEncoderConfigurationOptions(Request<_trt__GetVideoEncoderConfigurationOptions> &rRequest); - Response<_trt__GetAudioSourceConfigurationOptionsResponse> GetAudioSourceConfigurationOptions(Request<_trt__GetAudioSourceConfigurationOptions> &rRequest); - Response<_trt__GetAudioEncoderConfigurationOptionsResponse> GetAudioEncoderConfigurationOptions(Request<_trt__GetAudioEncoderConfigurationOptions> &rRequest); - Response<_trt__GetMetadataConfigurationOptionsResponse> GetMetadataConfigurationOptions(Request<_trt__GetMetadataConfigurationOptions> &rRequest); - Response<_trt__GetAudioOutputConfigurationOptionsResponse> GetAudioOutputConfigurationOptions(Request<_trt__GetAudioOutputConfigurationOptions> &rRequest); - Response<_trt__GetAudioDecoderConfigurationOptionsResponse> GetAudioDecoderConfigurationOptions(Request<_trt__GetAudioDecoderConfigurationOptions> &rRequest); - Response<_trt__GetGuaranteedNumberOfVideoEncoderInstancesResponse> GetGuaranteedNumberOfVideoEncoderInstances(Request<_trt__GetGuaranteedNumberOfVideoEncoderInstances> &rRequest); + Response<_trt__GetVideoSourceConfigurationOptionsResponse> + GetVideoSourceConfigurationOptions(Request<_trt__GetVideoSourceConfigurationOptions> &rRequest); + Response<_trt__GetVideoEncoderConfigurationOptionsResponse> + GetVideoEncoderConfigurationOptions(Request<_trt__GetVideoEncoderConfigurationOptions> &rRequest); + Response<_trt__GetAudioSourceConfigurationOptionsResponse> + GetAudioSourceConfigurationOptions(Request<_trt__GetAudioSourceConfigurationOptions> &rRequest); + Response<_trt__GetAudioEncoderConfigurationOptionsResponse> + GetAudioEncoderConfigurationOptions(Request<_trt__GetAudioEncoderConfigurationOptions> &rRequest); + Response<_trt__GetMetadataConfigurationOptionsResponse> + GetMetadataConfigurationOptions(Request<_trt__GetMetadataConfigurationOptions> &rRequest); + Response<_trt__GetAudioOutputConfigurationOptionsResponse> + GetAudioOutputConfigurationOptions(Request<_trt__GetAudioOutputConfigurationOptions> &rRequest); + Response<_trt__GetAudioDecoderConfigurationOptionsResponse> + GetAudioDecoderConfigurationOptions(Request<_trt__GetAudioDecoderConfigurationOptions> &rRequest); + Response<_trt__GetGuaranteedNumberOfVideoEncoderInstancesResponse> + GetGuaranteedNumberOfVideoEncoderInstances(Request<_trt__GetGuaranteedNumberOfVideoEncoderInstances> &rRequest); Response<_trt__GetStreamUriResponse> GetStreamUri(Request<_trt__GetStreamUri> &rRequest); Response<_trt__StartMulticastStreamingResponse> StartMulticastStreaming(Request<_trt__StartMulticastStreaming> &rRequest); Response<_trt__StopMulticastStreamingResponse> StopMulticastStreaming(Request<_trt__StopMulticastStreaming> &rRequest); diff --git a/src/OnvifPtzClient.h b/src/OnvifPtzClient.h index 035a534..6cbff8c 100644 --- a/src/OnvifPtzClient.h +++ b/src/OnvifPtzClient.h @@ -22,10 +22,10 @@ struct OnvifPtzClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Ptz -* -*/ + * + * \brief Client side service implementations of Onvif Ptz + * + */ class ONVIFPTZ_EXPORT OnvifPtzClient : public Client { Q_OBJECT @@ -34,7 +34,7 @@ class ONVIFPTZ_EXPORT OnvifPtzClient : public Client { OnvifPtzClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); virtual ~OnvifPtzClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver20/ptz/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_tptz; } Response<_tptz__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_tptz__GetServiceCapabilities> &rRequest); Response<_tptz__GetConfigurationsResponse> GetConfigurations(Request<_tptz__GetConfigurations> &rRequest); Response<_tptz__GetPresetsResponse> GetPresets(Request<_tptz__GetPresets> &rRequest); diff --git a/src/OnvifPullPoint.cpp b/src/OnvifPullPoint.cpp index d7db8e5..64dd10a 100644 --- a/src/OnvifPullPoint.cpp +++ b/src/OnvifPullPoint.cpp @@ -14,10 +14,16 @@ * along with this program.If not, see < http://www.gnu.org/licenses/>. */ #include "OnvifPullPoint.h" -#include "Request.h" #include "OnvifEventClient.h" -#include +#include "Request.h" #include +#include +#include +#if(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) +#include +#else +#include +#endif #if(QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) #define HAS_QT_RECURSIVEMUTEX #include @@ -25,17 +31,12 @@ #include #endif - #define PULL_POINT_MAX_RETRIES 10 #define PULL_POINT_DEFAULT_TIMEOUT 3600000 #define PULL_POINT_DEFAULT_MSG_LIMIT 100 -OnvifPullPointWorker::OnvifPullPointWorker(const QUrl &rEndpoint, QObject *pParent) : - QThread(pParent), mEndpoint(rEndpoint), mpClient(new OnvifEventClient(mEndpoint, QSharedPointer::create(), this)) { - - mpClient->GetCtx()->EnableOModeFlags(SOAP_IO_KEEPALIVE); - mpClient->GetCtx()->EnableIModeFlags(SOAP_IO_KEEPALIVE); -} +OnvifPullPointWorker::OnvifPullPointWorker(const QUrl &rEndpoint, QSharedPointer sharedCtx, QObject *pParent) : + QThread(pParent), mEndpoint(rEndpoint), mpClient(new OnvifEventClient(mEndpoint, std::move(sharedCtx), this)) {} OnvifPullPointWorker::~OnvifPullPointWorker() { @@ -46,15 +47,17 @@ void OnvifPullPointWorker::run() { mpClient->GetCtx()->Save(); + mpClient->GetCtx()->EnableOModeFlags(SOAP_IO_KEEPALIVE); + mpClient->GetCtx()->EnableIModeFlags(SOAP_IO_KEEPALIVE); int messageLimit = PULL_POINT_DEFAULT_MSG_LIMIT; int timeoutLimit = PULL_POINT_DEFAULT_TIMEOUT; // 1 h int pullFaultCount = 0; bool failedPullHandled = false; bool shortPull = true; // The first pull should have a short timeout so we can check if it's working. - qDebug() << "Starting new Pull Point:" << mpClient->GetEndpointString(); + qDebug() << "Starting new pullpoint:" << mpClient->GetEndpointString(); - while(!isInterruptionRequested() /*&& pullFaultCount < PULL_POINT_MAX_RETRIES*/) { + while(!isInterruptionRequested() && pullFaultCount < PULL_POINT_MAX_RETRIES) { Request<_tev__PullMessages> request; if(shortPull) { @@ -69,8 +72,16 @@ void OnvifPullPointWorker::run() { if(resp && resp.GetResultObject()) { pullFaultCount = 0; shortPull = false; - qDebug() << "Received new messages from Pull Point:" << mpClient->GetEndpointString(); + qDebug() << "Received new messages from pullpoint:" << mpClient->GetEndpointString(); for(auto it : resp.GetResultObject()->wsnt__NotificationMessage) { + if(it->Message.__any) { + // We have a dom element we try to cast to _tt__Message + auto *message = + const_cast<_tt__Message *>(static_cast(it->Message.__any->get_node(SOAP_TYPE__tt__Message))); + if(message) { + it->Message.Message = message->soap_dup(); + } + } emit MessageReceived(Response(it)); } @@ -85,20 +96,19 @@ void OnvifPullPointWorker::run() { if(faultDetail) { if(faultDetail->MaxMessageLimit < messageLimit) { messageLimit = faultDetail->MaxMessageLimit; - qDebug() << "Got new message limit from Pull Point:" << messageLimit << ")"; + qDebug() << "Got new message limit from pullpoint:" << messageLimit << ")"; } if(faultDetail->MaxTimeout < timeoutLimit) { timeoutLimit = faultDetail->MaxTimeout; - qDebug() << "Got new timeout limit from Pull Point:" << timeoutLimit; + qDebug() << "Got new timeout limit from pullpoint:" << timeoutLimit; } } else { shortPull = true; - qWarning() << resp; + qWarning() << "Unknown pullpoint fault" << resp; // Sleeping for(auto i = 1; i <= 10 && !QThread::isInterruptionRequested(); ++i) QThread::msleep(1000); } - if(!failedPullHandled && pullFaultCount >= 2) { failedPullHandled = true; emit LostPullPoint(resp); @@ -110,7 +120,7 @@ void OnvifPullPointWorker::run() { Request<_wsnt__Unsubscribe> req; auto resp = mpClient->Unsubscribe(req); if(!resp) { - qWarning() << "Couldn't unsubscribe from Pull Point:" << mpClient->GetEndpointString(); + qWarning() << "Couldn't unsubscribe from pullpoint:" << mpClient->GetEndpointString(); } } @@ -124,14 +134,39 @@ Response<_tev__CreatePullPointSubscriptionResponse> OnvifPullPointWorker::Setup( bool OnvifPullPointWorker::StartListening() { if(!isRunning()) { - qDebug() << "Starting PullPoint worker"; + qDebug() << "Starting pullpoint worker"; auto response = Setup(); if(response) { + if(response.GetResultObject()) { + if(response.GetResultObject()->SubscriptionReference.Address) { + mpClient->SetEndpoint(QUrl::fromUserInput(QString::fromLocal8Bit(response.GetResultObject()->SubscriptionReference.Address))); + } else if(response.GetResultObject()->SubscriptionReference.__size > 0) { + // TODO: Don't know why gsop does not deserialize wsa5__EndpointReferenceType? As a workaround we parse it ourselves! + for(auto i = 0; i < response.GetResultObject()->SubscriptionReference.__size; i++) { + auto address = response.GetResultObject()->SubscriptionReference.__any[i]; +#if(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + QRegularExpression rx(".+Address>(.*)<\\/"); + QStringList addressList = rx.match(QString::fromLocal8Bit(address)).capturedTexts(); +#else + QRegExp rx(".+Address>(.*)<\\/"); + QStringList addressList = rx.capturedTexts(); +#endif + if(addressList.length() > 1) { + mpClient->SetEndpoint(addressList[1]); + break; + } + } + } else { + qWarning() << "Missing a valid pullpoint subscription reference"; + } + } else { + qWarning() << "Missing a valid pullpoint subscription response"; + } start(); - qDebug() << "PullPoint worker successfully started"; + qDebug() << "pullpoint worker successfully started"; return true; } - qWarning() << "Couldn't start PullPoint worker - initial setup failed:" << response.GetCompleteFault(); + qWarning() << "Couldn't start pullpoint worker - initial setup failed:" << response.GetCompleteFault(); return false; } return true; @@ -140,15 +175,15 @@ bool OnvifPullPointWorker::StartListening() { void OnvifPullPointWorker::StopListening() { if(!isInterruptionRequested() && isRunning()) { - qDebug() << "Stopping PullPoint worker"; + qDebug() << "Stopping pullpoint worker"; requestInterruption(); mpClient->GetCtx()->ForceSocketClose(); const auto waitTimespan = 20000UL; auto terminated = wait(waitTimespan); if(!terminated) - qWarning() << "PullPoint worker couldn't be terminated within time:" << waitTimespan << "ms"; + qWarning() << "pullpoint worker couldn't be terminated within time:" << waitTimespan << "ms"; else - qDebug() << "PullPoint worker successfully stopped"; + qDebug() << "pullpoint worker successfully stopped"; } } @@ -177,8 +212,9 @@ struct OnvifPullPointPrivate { bool mActive; }; -OnvifPullPoint::OnvifPullPoint(const QUrl &rEndpoint, QObject *pParent /*= nullptr*/) : - Client(rEndpoint, QSharedPointer::create(), pParent), mpD(new OnvifPullPointPrivate(this, rEndpoint)) {} +OnvifPullPoint::OnvifPullPoint(const QUrl &rEndpoint, QSharedPointer sharedCtx /*= QSharedPointer::create()*/, + QObject *pParent /*= nullptr*/) : + Client(rEndpoint, sharedCtx, pParent), mpD(new OnvifPullPointPrivate(this, rEndpoint)) {} OnvifPullPoint::~OnvifPullPoint() { @@ -191,10 +227,11 @@ void OnvifPullPoint::Start() { bool activeBackup = mpD->mActive; mpD->mMutex.lock(); if(!mpD->mpWorker) { - mpD->mpWorker = new OnvifPullPointWorker(mpD->mEndpoint, this); - connect(mpD->mpWorker, SIGNAL(UnsuccessfulPull(int, const SimpleResponse &)), this, SLOT(UnsuccessfulPull(int, const SimpleResponse &))); - connect(mpD->mpWorker, SIGNAL(LostPullPoint(const SimpleResponse &)), this, SLOT(LostPullPoint(const SimpleResponse &))); - connect(mpD->mpWorker, SIGNAL(ResumedPullPoint()), this, SLOT(ResumedPullPoint())); + mpD->mpWorker = new OnvifPullPointWorker(mpD->mEndpoint, GetCtx(), this); + connect(mpD->mpWorker, &OnvifPullPointWorker::MessageReceived, this, &OnvifPullPoint::MessageReceived); + connect(mpD->mpWorker, &OnvifPullPointWorker::UnsuccessfulPull, this, &OnvifPullPoint::UnsuccessfulPull); + connect(mpD->mpWorker, &OnvifPullPointWorker::LostPullPoint, this, &OnvifPullPoint::LostPullPoint); + connect(mpD->mpWorker, &OnvifPullPointWorker::ResumedPullPoint, this, &OnvifPullPoint::ResumedPullPoint); mpD->mActive = mpD->mpWorker->StartListening(); if(!mpD->mActive) { Stop(); diff --git a/src/OnvifPullPoint.h b/src/OnvifPullPoint.h index f3be31e..ff1a1bd 100644 --- a/src/OnvifPullPoint.h +++ b/src/OnvifPullPoint.h @@ -28,22 +28,22 @@ class OnvifPullPointWorker : public QThread { Q_OBJECT -public: - OnvifPullPointWorker(const QUrl &rEndpoint, QObject *pParent = nullptr); - virtual ~OnvifPullPointWorker(); + public: + OnvifPullPointWorker(const QUrl &rEndpoint, QSharedPointer sharedCtx, QObject *pParent = nullptr); + ~OnvifPullPointWorker() override; bool StartListening(); void StopListening(); -signals: + signals: void MessageReceived(const Response &rResponse); void LostPullPoint(const SimpleResponse &rCause); void ResumedPullPoint(); void UnsuccessfulPull(int unsuccessfulPullcount, const SimpleResponse &rCause); -protected: - void run(); + protected: + void run() override; -private: + private: Q_DISABLE_COPY(OnvifPullPointWorker); Response<_tev__CreatePullPointSubscriptionResponse> Setup(); @@ -55,32 +55,33 @@ class OnvifPullPointWorker : public QThread { /*! * - * \brief A Onvif pull point listener + * \brief A Onvif pullpoint listener * - * Use this class to listen (non blocking) for events generated by a pull point + * Use this class to listen (non blocking) for events generated by a pullpoint * */ class ONVIFEVENT_EXPORT OnvifPullPoint : public Client { Q_OBJECT -public: + public: /*! * - * \brief Construct a pull point listener + * \brief Construct a pullpoint listener * * \param rEndpoint The WS event endpoint this listener will use for its WS calls * \param pParent A QObject parent * */ - OnvifPullPoint(const QUrl &rEndpoint, QObject *pParent = nullptr); - virtual ~OnvifPullPoint(); - //! Check if the pull point is active and we listen for events + explicit OnvifPullPoint(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); + ~OnvifPullPoint() override; + //! Check if the pullpoint is active and we listen for events bool Active(); -signals: + signals: //! Emitted if a event occurs holding the message of the event - void MessageReceived(const Response<_tev__PullMessagesResponse> &rResponse); + void MessageReceived(const Response &rResponse); //! Emitted as soon as a pull failed void LostPullPoint(const SimpleResponse &rCause); //! Emitted as soon as a successful pull was received after a failed pull @@ -90,14 +91,16 @@ class ONVIFEVENT_EXPORT OnvifPullPoint : public Client { //! Emitted if the active state changes void ActiveChanged(bool isActive); -public slots: + public slots: //! Start listening for events. Non blocking void Start(); //! Stop listening for events void Stop(); -private: + private: Q_DISABLE_COPY(OnvifPullPoint); OnvifPullPointPrivate *mpD; }; + +REGISTER_METATYPE(Response) diff --git a/src/OnvifReceiverClient.h b/src/OnvifReceiverClient.h index 888380f..aa9f16a 100644 --- a/src/OnvifReceiverClient.h +++ b/src/OnvifReceiverClient.h @@ -22,19 +22,20 @@ struct OnvifReceiverClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Receiver -* -*/ + * + * \brief Client side service implementations of Onvif Receiver + * + */ class ONVIFRECEIVER_EXPORT OnvifReceiverClient : public Client { Q_OBJECT public: - OnvifReceiverClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); + OnvifReceiverClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); virtual ~OnvifReceiverClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver10/receiver/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_trv; } Response<_trv__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_trv__GetServiceCapabilities> &rRequest); Response<_trv__GetReceiversResponse> GetReceivers(Request<_trv__GetReceivers> &rRequest); Response<_trv__GetReceiverResponse> GetReceiver(Request<_trv__GetReceiver> &rRequest); diff --git a/src/OnvifRecordingClient.h b/src/OnvifRecordingClient.h index c0f40e1..b4dec69 100644 --- a/src/OnvifRecordingClient.h +++ b/src/OnvifRecordingClient.h @@ -22,19 +22,20 @@ struct OnvifRecordingClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Recording -* -*/ + * + * \brief Client side service implementations of Onvif Recording + * + */ class ONVIFRECORDING_EXPORT OnvifRecordingClient : public Client { Q_OBJECT public: - OnvifRecordingClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); + OnvifRecordingClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); virtual ~OnvifRecordingClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver10/recording/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_trc; } Response<_trc__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_trc__GetServiceCapabilities> &rRequest); Response<_trc__CreateRecordingResponse> CreateRecording(Request<_trc__CreateRecording> &rRequest); Response<_trc__DeleteRecordingResponse> DeleteRecording(Request<_trc__DeleteRecording> &rRequest); diff --git a/src/OnvifReplayClient.h b/src/OnvifReplayClient.h index 70245aa..8e25daa 100644 --- a/src/OnvifReplayClient.h +++ b/src/OnvifReplayClient.h @@ -19,23 +19,23 @@ #include "Client.h" #include "OnvifReplayExport.h" - struct OnvifReplayClientPrivate; /*! -* -* \brief Client side service implementations of Onvif Replay -* -*/ + * + * \brief Client side service implementations of Onvif Replay + * + */ class ONVIFREPLAY_EXPORT OnvifReplayClient : public Client { Q_OBJECT public: - OnvifReplayClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), QObject *pParent = nullptr); + OnvifReplayClient(const QUrl &rEndpoint, QSharedPointer sharedCtx = QSharedPointer::create(), + QObject *pParent = nullptr); virtual ~OnvifReplayClient(); - static QString GetServiceNamespace() { return "http://www.onvif.org/ver10/replay/wsdl"; } + static QString GetServiceNamespace() { return SOAP_NAMESPACE_OF_trp; } Response<_trp__GetServiceCapabilitiesResponse> GetServiceCapabilities(Request<_trp__GetServiceCapabilities> &rRequest); Response<_trp__GetReplayUriResponse> GetReplayUri(Request<_trp__GetReplayUri> &rRequest); Response<_trp__GetReplayConfigurationResponse> GetReplayConfiguration(Request<_trp__GetReplayConfiguration> &rRequest); diff --git a/src/Response.h b/src/Response.h index dc0277a..12b1ac9 100644 --- a/src/Response.h +++ b/src/Response.h @@ -15,6 +15,7 @@ */ #pragma once #include "SoapCtx.h" +#include "global.h" #include "soapH.h" #include #include @@ -48,7 +49,7 @@ struct SoapDuplicator { */ class SimpleResponse { -public: + public: /*! * * \brief Construct an errorless response @@ -166,7 +167,7 @@ class SimpleResponse { } } -private: + private: int mErrorCode; QString mFault; QString mFaultDetail; @@ -190,7 +191,7 @@ inline QDebug operator<<(QDebug debug, const SimpleResponse &rResponse) { */ class DetailedResponse : public SimpleResponse { -public: + public: /*! * * \brief Construct an errorless response @@ -319,7 +320,7 @@ class DetailedResponse : public SimpleResponse { } } -private: + private: SOAP_ENV__Detail *mpFaultResultObject; SOAP_ENV__Header *mpSoapHeader; }; @@ -334,13 +335,13 @@ class DetailedResponse : public SimpleResponse { template, class Duplicator = SoapDuplicator> class Response : public DetailedResponse { -public: + public: /*! * * \brief Construct an errorless response * */ - Response() : DetailedResponse(), mDeleter(), mDuplicator(), mpResultObject(nullptr) {} + Response() : DetailedResponse(), mDeleter(), mDuplicator(), mpResultObject(nullptr), mpDomElement(nullptr) {} /*! * @@ -352,18 +353,27 @@ class Response : public DetailedResponse { DetailedResponse(errorCode, rFault, rFaultDetail, pFaultObject), mDeleter(), mDuplicator(), - mpResultObject(pResultObject ? mDuplicator(pResultObject) : nullptr) {} + mpResultObject(pResultObject ? mDuplicator(pResultObject) : nullptr), + mpDomElement(nullptr) {} Response(const T *pResultObject) : - DetailedResponse(), mDeleter(), mDuplicator(), mpResultObject(pResultObject ? mDuplicator(pResultObject) : nullptr) {} + DetailedResponse(), + mDeleter(), + mDuplicator(), + mpResultObject(pResultObject ? mDuplicator(pResultObject) : nullptr), + mpDomElement(nullptr) {} - virtual ~Response() { mDeleter(mpResultObject); } + virtual ~Response() { + mDeleter(mpResultObject); + soap_del_xsd__anyType(mpDomElement); + } Response(const Response &rOther) : DetailedResponse(rOther), mDeleter(rOther.mDeleter), mDuplicator(rOther.mDuplicator), - mpResultObject(rOther.mpResultObject ? mDuplicator(rOther.mpResultObject) : nullptr) {} + mpResultObject(rOther.mpResultObject ? mDuplicator(rOther.mpResultObject) : nullptr), + mpDomElement(nullptr) {} Response &operator=(const Response &rOther) { @@ -373,12 +383,18 @@ class Response : public DetailedResponse { DetailedResponse::operator=(rOther); this->mDeleter(this->mpResultObject); this->mpResultObject = rOther.mpResultObject ? mDuplicator(rOther.mpResultObject) : nullptr; + this->mpDomElement = rOther.mpDomElement ? soap_dup_xsd__anyType(nullptr, nullptr, rOther.mpDomElement) : nullptr; return *this; } //! Get the result object of a WS response const T *GetResultObject() const { return mpResultObject; } +#ifdef WITH_DOM + //! Get the underlying dom tree (only available if SOAP_XML_DOM is set for soap_mode imode) + const soap_dom_element *GetDomTree() const { return mpDomElement; } +#endif + //! Set the result object of a WS response void SetResultObject(const T *pResultObject) { @@ -395,7 +411,7 @@ class Response : public DetailedResponse { */ class Builder { - public: + public: Builder() : mpResult() {} Builder &From(const QSharedPointer &rSoapCtx, const T *pResultObject = nullptr) { @@ -404,7 +420,11 @@ class Response : public DetailedResponse { auto errorCode = rSoapCtx->GetFaultCode(); if(errorCode != SOAP_OK) { mpResult.SetResultObject(nullptr); + mpResult.mpDomElement = nullptr; } else { + auto *pSoap = rSoapCtx->Acquire(); + if(pSoap->dom) mpResult.mpDomElement = soap_dup_xsd__anyType(nullptr, nullptr, pSoap->dom); + rSoapCtx->Release(); mpResult.SetResultObject(pResultObject); } return *this; @@ -412,14 +432,15 @@ class Response : public DetailedResponse { Response Build() const { return mpResult; } - private: + private: Response mpResult; }; -private: + private: Deleter mDeleter; Duplicator mDuplicator; T *mpResultObject; + soap_dom_element *mpDomElement; }; /*! @@ -432,7 +453,7 @@ class Response : public DetailedResponse { template class ArbitraryResponse : public DetailedResponse { -public: + public: /*! * * \brief Construct an errorless response @@ -485,7 +506,7 @@ class ArbitraryResponse : public DetailedResponse { */ class Builder { - public: + public: Builder() : mpResult() {} Builder &From(const QSharedPointer &rSoapCtx, const T &rResultObject) { @@ -506,10 +527,12 @@ class ArbitraryResponse : public DetailedResponse { ArbitraryResponse Build() const { return mpResult; } - private: + private: ArbitraryResponse mpResult; }; -private: + private: T mResultObject; }; + +REGISTER_METATYPE(SimpleResponse) diff --git a/src/SoapAuthHandler.cpp b/src/SoapAuthHandler.cpp index 2a2cb32..520b3fa 100644 --- a/src/SoapAuthHandler.cpp +++ b/src/SoapAuthHandler.cpp @@ -64,8 +64,8 @@ void DefaultAuthHandler::SetAuth(soap *pCtx, const QString &rUserName, const QSt FreeAuth(pCtx); mpD->mAuthProcessed = false; #ifndef WITH_OPENSSL - if(mode != NO_AUTH && mode != WS_USERNAME_TOKEN) { - mode = WS_USERNAME_TOKEN; + if(mode != AuthHandlerMode::NO_AUTH && mode != AuthHandlerMode::WS_USERNAME_TOKEN) { + mode = AuthHandlerMode::WS_USERNAME_TOKEN; qWarning() << "This build doesn't support http digest auth. Switching back to ws token"; } #endif // WITH_OPENSSL diff --git a/src/SoapCtx.cpp b/src/SoapCtx.cpp index a15e35c..3a0c065 100644 --- a/src/SoapCtx.cpp +++ b/src/SoapCtx.cpp @@ -19,7 +19,10 @@ #endif // WITH_OPENSSL #include "namespaces.nsmap" #include "wsaapi.h" +#include "info.h" #include +#include +#include #include #include #include @@ -34,8 +37,16 @@ struct arbData { bool enableDebug = false; + QString userAgent = QString("%1/%2.%3.%4 (%5; %6)") + .arg(INFO_PROJECTNAME) + .arg(INFO_VERSION_MAJOR) + .arg(INFO_VERSION_MINOR) + .arg(INFO_VERSION_PATCH) + .arg(QSysInfo::prettyProductName()) + .arg(QSysInfo::currentCpuArchitecture()); int (*fsend)(struct soap *, const char *, size_t) = nullptr; size_t (*frecv)(struct soap *, char *, size_t) = nullptr; + int (*fposthdr)(struct soap *soap, const char *key, const char *val) = nullptr; QPointer pObject = nullptr; }; @@ -49,6 +60,16 @@ int fsend(struct soap *soap, const char *s, size_t n) { return ret; } +int fposthdr(struct soap *soap, const char *key, const char *val) { + + auto latinKey = QLatin1String(key); + const auto latinUserAgent = QLatin1String("User-Agent"); + if(latinKey.size() == latinUserAgent.size() && QLatin1String(key).startsWith(QLatin1String("User-Agent"), Qt::CaseInsensitive)) { + return ((arbData *)soap->user)->fposthdr(soap, key, qPrintable(((arbData *)soap->user)->userAgent)); + } + return ((arbData *)soap->user)->fposthdr(soap, key, val); +} + size_t frecv(struct soap *soap, char *s, size_t n) { auto length = ((arbData *)soap->user)->frecv(soap, s, n); @@ -106,7 +127,7 @@ struct CtxPrivate { SoapCtx::SoapCtx() : mpD(new CtxPrivate(this)) { mpD->mpSoap = soap_new(); - soap_init2(mpD->mpSoap, SOAP_NEW_IO_DEFAULT, SOAP_NEW_IO_DEFAULT); + soap_init2(mpD->mpSoap, SOAP_NEW_I_DEFAULT, SOAP_NEW_O_DEFAULT); InitCtx(); } @@ -265,12 +286,16 @@ void SoapCtx::InitCtx() { pFsend = &fsend; size_t (*pFrecv)(struct soap * soap, char *s, size_t n); pFrecv = &frecv; + int (*pFposthdr)(struct soap * soap, const char *s, const char *v); + pFposthdr = &fposthdr; auto ud = new arbData(); ud->frecv = mpD->mpSoap->frecv; ud->fsend = mpD->mpSoap->fsend; + ud->fposthdr = mpD->mpSoap->fposthdr; mpD->mpSoap->user = ud; mpD->mpSoap->frecv = pFrecv; mpD->mpSoap->fsend = pFsend; + mpD->mpSoap->fposthdr = pFposthdr; SetSoapAuthHandler(std::unique_ptr(new DefaultAuthHandler())); } @@ -382,6 +407,12 @@ void SoapCtx::DisablePrintRawSoap() { ((arbData *)mpD->mpSoap->user)->enableDebug = false; } +void SoapCtx::SetUserAgent(const QString &rUserAgent) { + + QMutexLocker locker(&mpD->mMutex); + ((arbData *)mpD->mpSoap->user)->userAgent = rUserAgent; +} + void SoapCtx::SetSocketFlags(int soFlags) { QMutexLocker locker(&mpD->mMutex); diff --git a/src/SoapCtx.h b/src/SoapCtx.h index d5f1279..07747bf 100644 --- a/src/SoapCtx.h +++ b/src/SoapCtx.h @@ -23,7 +23,8 @@ #include -#define SOAP_NEW_IO_DEFAULT (SOAP_IO_DEFAULT | SOAP_C_UTFSTRING | SOAP_DOM_NODE | SOAP_XML_TREE) +#define SOAP_NEW_O_DEFAULT (SOAP_IO_DEFAULT | SOAP_C_UTFSTRING | SOAP_DOM_NODE | SOAP_XML_TREE) +#define SOAP_NEW_I_DEFAULT (SOAP_NEW_O_DEFAULT | SOAP_XML_DOM) #define SOAP_NEW_SSL_DEFAULT (SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_TLSv1 | SOAP_SSL_CLIENT) #define SOAP_DEFAULT_CONNECT_TIMEOUT 10000 #define SOAP_DEFAULT_RECEIVE_TIMEOUT 10000 @@ -77,6 +78,8 @@ class ONVIFCOMMON_EXPORT SoapCtx : public QObject { void EnablePrintRawSoap(); //! This context will not print the raw soap messages void DisablePrintRawSoap(); + //! Overwrite the default User-Agent + void SetUserAgent(const QString &rUserAgent); //! Get a informative fault message of the last WS call QString GetFaultString(); //! Get a detailed, informative fault message of the last WS call @@ -209,6 +212,11 @@ class ONVIFCOMMON_EXPORT SoapCtx : public QObject { return *this; } + Builder &SetUserAgent(const QString &rUserAgent) { + mpResult->SetUserAgent(rUserAgent); + return *this; + } + #ifdef WITH_OPENSSL Builder &EnableSsl() { mpResult->EnableSsl(); diff --git a/src/global.h b/src/global.h index 62ed1e4..a66b830 100644 --- a/src/global.h +++ b/src/global.h @@ -14,15 +14,16 @@ * along with this program.If not, see < http://www.gnu.org/licenses/>. */ #pragma once +#include #include -#if QT_VERSION < QT_VERSION_CHECK(5,5,0) +#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) #define QML_ENUM Q_ENUMS #else #define QML_ENUM Q_ENUM #endif -#if QT_VERSION < QT_VERSION_CHECK(5,4,0) +#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) #define qUtf8Printable(string) QString(string).toUtf8().constData() #endif @@ -85,3 +86,24 @@ #define HTTP_INSUFFICIENT_STORAGE 507 #define HTTP_LOOP_DETECTED 508 #define HTTP_NOT_EXTENDED 510 + + +// calls qRegisterMetaType once for your custom Type T - use like so: +// static QMetaTypeRegistrar RegisterMyType; +// or so: +// static QMetaTypeRegistrar RegisterMyType("MyTypesName"); +template +class QMetaTypeRegistrar { + public: + QMetaTypeRegistrar() { qRegisterMetaType(); }; + explicit QMetaTypeRegistrar(const char *metaTypeName) { qRegisterMetaType(metaTypeName); } +}; + +#define CONCAT_(x, y) x##y +#define CONCAT(x, y) CONCAT_(x, y) + +// combines Q_DECLARE_METATYPE and qRegisterMetaType in one macro +#define REGISTER_METATYPE(TYPE) REGISTER_METATYPE_IMPL(TYPE) // NOLINT +#define REGISTER_METATYPE_IMPL(TYPE) \ + Q_DECLARE_METATYPE(TYPE) \ + static QMetaTypeRegistrar CONCAT(Registrar_, __COUNTER__); // NOLINT diff --git a/src/main.cpp b/src/main.cpp index 258274f..848c409 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ #include "CmdLineParser.h" #include "OnvifDevice.h" #include "OnvifDiscoveryClient.h" +#include "Response.h" #include "SoapHelper.h" #include #include @@ -50,10 +51,10 @@ int main(int argc, char **argv) { ctxBuilder.SetReceiveTimeout(1000); auto discovery = new OnvifDiscoveryClient(QUrl("soap.udp://239.255.255.250:3702"), ctxBuilder.Build(), &app); ProbeTypeRequest request; - request.Types = "tds:Device"; + request.Types = (char *)"tds:Device"; auto uuidOne = QString("uuid:%1").arg(SoapHelper::GenerateUuid()); auto probeResponseTwo = discovery->Probe(request, uuidOne); - request.Types = "tdn:NetworkVideoTransmitter"; + request.Types = (char *)"tdn:NetworkVideoTransmitter"; auto uuidTwo = QString("uuid:%1").arg(SoapHelper::GenerateUuid()); auto probeResponseOne = discovery->Probe(request, uuidTwo); if(probeResponseOne && probeResponseTwo) { @@ -109,6 +110,7 @@ int main(int argc, char **argv) { auto device = new OnvifDevice(response.GetResultObject().endpointUrl, &app); device->SetAuth(response.GetResultObject().user, response.GetResultObject().pwd); device->Initialize(); + device->SubscribePullPoint(); } } else { qCritical() << response.GetCompleteFault(); @@ -142,9 +144,9 @@ int main(int argc, char **argv) { // if(auto topicSet = resObj->wstop__TopicSet) { // for(auto it : topicSet->__any) { // if(auto topicAtt = soap_att_get(it, "http://docs.oasis-open.org/wsn/t-1", "topic")) { - // for(auto itt = soap_elt_get(it, "http://www.onvif.org/ver10/schema", "MessageDescription"); itt; itt = soap_elt_get_next(itt)) { - // auto node = (tt__MessageDescription*)soap_elt_get_node(itt, SOAP_TYPE_tt__MessageDescription); - // bool property = node->IsProperty ? node->IsProperty : false; + // for(auto itt = soap_elt_get(it, "http://www.onvif.org/ver10/schema", "MessageDescription"); itt; itt = soap_elt_get_next(itt)) + // { auto node = (tt__MessageDescription*)soap_elt_get_node(itt, SOAP_TYPE_tt__MessageDescription); bool property = + // node->IsProperty ? node->IsProperty : false; // } // } // } @@ -163,5 +165,5 @@ int main(int argc, char **argv) { } } */ - return 0; + return QCoreApplication::exec(); }