diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 03:32:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 03:32:49 +0000 |
commit | 8053187731ae8e3eb368d8360989cf5fd6eed9f7 (patch) | |
tree | 32bada84ff5d7460cdf3934fcbdbe770d6afe4cd /cmake | |
parent | Initial commit. (diff) | |
download | rnp-8053187731ae8e3eb368d8360989cf5fd6eed9f7.tar.xz rnp-8053187731ae8e3eb368d8360989cf5fd6eed9f7.zip |
Adding upstream version 0.17.0.upstream/0.17.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | cmake/CTestCostData.txt | 159 | ||||
-rw-r--r-- | cmake/Modules/AdocMan.cmake | 135 | ||||
-rw-r--r-- | cmake/Modules/FindBotan2.cmake | 131 | ||||
-rw-r--r-- | cmake/Modules/FindGnuPG.cmake | 137 | ||||
-rw-r--r-- | cmake/Modules/FindJSON-C.cmake | 123 | ||||
-rw-r--r-- | cmake/Modules/FindOpenSSLFeatures.cmake | 171 | ||||
-rw-r--r-- | cmake/Modules/FindWindowsSDK.cmake | 662 | ||||
-rw-r--r-- | cmake/Modules/findopensslfeatures.c | 101 | ||||
-rw-r--r-- | cmake/info.cmake | 41 | ||||
-rw-r--r-- | cmake/librnp.pc.in | 13 | ||||
-rw-r--r-- | cmake/packaging.cmake | 79 | ||||
-rw-r--r-- | cmake/rnp-config.cmake.in | 31 | ||||
-rw-r--r-- | cmake/rnp_tests_discover.cmake | 40 | ||||
-rw-r--r-- | cmake/version.cmake | 163 |
14 files changed, 1986 insertions, 0 deletions
diff --git a/cmake/CTestCostData.txt b/cmake/CTestCostData.txt new file mode 100644 index 0000000..1a00177 --- /dev/null +++ b/cmake/CTestCostData.txt @@ -0,0 +1,159 @@ +rnp_tests.hash_test_success 1 0.0138223 +rnp_tests.cipher_test_success 1 0.0120679 +rnp_tests.pkcs1_rsa_test_success 1 0.0714414 +rnp_tests.rnp_test_eddsa 1 0.014394 +rnp_tests.rnp_test_x25519 1 0.0197451 +rnp_tests.raw_elgamal_random_key_test_success 1 0.725944 +rnp_tests.ecdsa_signverify_success 1 0.0561304 +rnp_tests.ecdh_roundtrip 1 0.0383161 +rnp_tests.ecdh_decryptionNegativeCases 1 0.0201392 +rnp_tests.sm2_roundtrip 1 0.0214206 +rnp_tests.sm2_sm3_signature_test 1 0.027973 +rnp_tests.sm2_sha256_signature_test 1 0.0269801 +rnp_tests.test_dsa_roundtrip 1 24.2023 +rnp_tests.test_dsa_verify_negative 1 0.800061 +rnp_tests.s2k_iteration_tuning 1 0.515675 +rnp_tests.s2k_iteration_encode_decode 1 0.0134686 +rnp_tests.test_validate_key_material 1 1.68337 +rnp_tests.test_cli_rnp_keyfile 1 0.859851 +rnp_tests.test_cli_g10_operations 1 2.50301 +rnp_tests.test_cli_rnp 1 0.0972449 +rnp_tests.test_cli_examples 1 1.3149 +rnp_tests.test_cli_rnpkeys 1 0.115061 +rnp_tests.test_cli_dump 1 0.0361111 +rnp_tests.test_cli_logname 1 0.0116097 +rnp_tests.rnpkeys_exportkey_verifyUserId 1 0.118051 +rnp_tests.test_ffi_homedir 1 0.0241839 +rnp_tests.test_ffi_detect_key_format 1 0.0129409 +rnp_tests.test_ffi_load_keys 1 0.0493167 +rnp_tests.test_ffi_clear_keys 1 0.0259738 +rnp_tests.test_ffi_save_keys 1 0.0316757 +rnp_tests.test_ffi_keygen_json_pair 1 0.0736696 +rnp_tests.test_ffi_keygen_json_pair_dsa_elg 1 12.7012 +rnp_tests.test_ffi_keygen_json_primary 1 0.0194215 +rnp_tests.test_ffi_keygen_json_sub 1 0.0573184 +rnp_tests.test_ffi_key_generate_misc 1 0.985612 +rnp_tests.test_ffi_key_generate_rsa 1 0.342821 +rnp_tests.test_ffi_key_generate_dsa 1 2.13331 +rnp_tests.test_ffi_key_generate_ecdsa 1 0.0177323 +rnp_tests.test_ffi_key_generate_eddsa 1 0.0143182 +rnp_tests.test_ffi_key_generate_sm2 1 0.0175289 +rnp_tests.test_ffi_key_generate_ex 1 5.74498 +rnp_tests.test_ffi_key_generate_algnamecase 1 2.62221 +rnp_tests.test_ffi_key_generate_protection 1 1.40079 +rnp_tests.test_ffi_add_userid 1 0.0404918 +rnp_tests.test_ffi_keygen_json_sub_pass_required 1 0.382914 +rnp_tests.test_ffi_encrypt_pass 1 0.429726 +rnp_tests.test_ffi_encrypt_pass_provider 1 0.342456 +rnp_tests.test_ffi_encrypt_pk 1 0.0482677 +rnp_tests.test_ffi_encrypt_pk_key_provider 1 0.0339246 +rnp_tests.test_ffi_encrypt_and_sign 1 0.0917957 +rnp_tests.test_ffi_signatures_memory 1 0.0518454 +rnp_tests.test_ffi_signatures 1 0.0488163 +rnp_tests.test_ffi_signatures_detached_memory 1 0.0492941 +rnp_tests.test_ffi_signatures_detached 1 0.04846 +rnp_tests.test_ffi_signatures_dump 1 0.0168647 +rnp_tests.test_ffi_key_to_json 1 0.0164411 +rnp_tests.test_ffi_key_iter 1 0.0261607 +rnp_tests.test_ffi_locate_key 1 0.0161026 +rnp_tests.test_ffi_signatures_detached_memory_g10 1 0.0427063 +rnp_tests.test_ffi_enarmor_dearmor 1 0.0373763 +rnp_tests.test_ffi_version 1 0.0140884 +rnp_tests.test_ffi_key_export 1 0.0250205 +rnp_tests.test_ffi_key_dump 1 0.0256317 +rnp_tests.test_ffi_pkt_dump 1 0.0167862 +rnp_tests.test_ffi_rsa_v3_dump 1 0.0158175 +rnp_tests.test_ffi_load_userattr 1 0.0177854 +rnp_tests.test_ffi_revocations 1 0.0191412 +rnp_tests.test_ffi_file_output 1 0.0292883 +rnp_tests.test_ffi_key_signatures 1 0.0211163 +rnp_tests.test_ffi_keys_import 1 0.577245 +rnp_tests.test_ffi_import_keys_check_pktlen 1 0.0151679 +rnp_tests.test_ffi_calculate_iterations 1 0.0279029 +rnp_tests.test_ffi_supported_features 1 0.0149266 +rnp_tests.test_ffi_enable_debug 1 0.010948 +rnp_tests.test_ffi_rnp_key_get_primary_grip 1 0.0178161 +rnp_tests.test_ffi_output_to_armor 1 0.01893 +rnp_tests.test_ffi_rnp_guess_contents 1 0.0121287 +rnp_tests.test_ffi_literal_filename 1 0.0552985 +rnp_tests.test_ffi_op_set_hash 1 0.0528855 +rnp_tests.test_ffi_op_set_compression 1 0.0730627 +rnp_tests.test_ffi_aead_params 1 0.241513 +rnp_tests.test_ffi_detached_verify_input 1 0.0228228 +rnp_tests.test_ffi_op_verify_sig_count 1 0.0491328 +rnp_tests.rnpkeys_generatekey_testSignature 1 1.18378 +rnp_tests.rnpkeys_generatekey_testEncryption 1 0.275621 +rnp_tests.rnpkeys_generatekey_verifySupportedHashAlg 1 1.41153 +rnp_tests.rnpkeys_generatekey_verifyUserIdOption 1 0.616167 +rnp_tests.rnpkeys_generatekey_verifykeyHomeDirOption 1 0.188337 +rnp_tests.rnpkeys_generatekey_verifykeyKBXHomeDirOption 1 0.205113 +rnp_tests.rnpkeys_generatekey_verifykeyHomeDirNoPermission 1 0.149937 +rnp_tests.rnpkeys_generatekey_testExpertMode 1 2.63892 +rnp_tests.generatekeyECDSA_explicitlySetSmallOutputDigest_DigestAlgAdjusted 1 0.0200285 +rnp_tests.generatekey_multipleUserIds_ShouldFail 1 0.0110169 +rnp_tests.generatekeyECDSA_explicitlySetBiggerThanNeededDigest_ShouldSuceed 1 0.0187109 +rnp_tests.generatekeyECDSA_explicitlySetUnknownDigest_ShouldFail 1 0.0133541 +rnp_tests.test_generated_key_sigs 1 0.128008 +rnp_tests.test_kbx_nsigs 1 4.07201 +rnp_tests.test_key_add_userid 1 0.0324633 +rnp_tests.key_grip 1 0.0621873 +rnp_tests.test_key_prefs 1 0.0115654 +rnp_tests.test_key_protect_load_pgp 1 0.330786 +rnp_tests.test_key_store_search 1 0.0108802 +rnp_tests.test_key_store_search_by_name 1 0.0138023 +rnp_tests.test_key_unlock_pgp 1 0.0629279 +rnp_tests.test_key_validate 1 0.0313496 +rnp_tests.test_forged_key_validate 1 0.0350325 +rnp_tests.test_key_validity 1 0.0179677 +rnp_tests.test_large_packet 1 12.6562 +rnp_tests.test_load_g10 1 0.493759 +rnp_tests.test_load_v3_keyring_pgp 1 0.012287 +rnp_tests.test_load_v4_keyring_pgp 1 0.015202 +rnp_tests.test_load_keyring_and_count_pgp 1 0.0166739 +rnp_tests.test_load_check_bitfields_and_times 1 0.0145676 +rnp_tests.test_load_check_bitfields_and_times_v3 1 0.0141121 +rnp_tests.test_load_armored_pub_sec 1 0.0233942 +rnp_tests.test_load_merge 1 0.148499 +rnp_tests.test_load_public_from_secret 1 0.0321099 +rnp_tests.test_key_import 1 0.256372 +rnp_tests.test_load_subkey 1 0.0191733 +rnp_tests.test_partial_length_public_key 1 0.0120663 +rnp_tests.test_partial_length_signature 1 0.0141925 +rnp_tests.test_partial_length_first_packet_256 1 0.017635 +rnp_tests.test_partial_length_zero_last_chunk 1 0.0177394 +rnp_tests.test_partial_length_largest 1 3.20183 +rnp_tests.test_partial_length_first_packet_length 1 0.0300068 +rnp_tests.test_s2k_iterations 1 7.229982 +rnp_tests.test_stream_memory 1 0.0125394 +rnp_tests.test_stream_memory_discard 1 0.0111196 +rnp_tests.test_stream_file 1 0.0168583 +rnp_tests.test_stream_signatures 1 0.0373302 +rnp_tests.test_stream_signatures_revoked_key 1 0.012537 +rnp_tests.test_stream_key_load 1 0.0130797 +rnp_tests.test_stream_key_load_errors 1 0.727713 +rnp_tests.test_stream_key_decrypt 1 0.511516 +rnp_tests.test_stream_key_encrypt 1 0.487256 +rnp_tests.test_stream_key_signatures 1 0.0199383 +rnp_tests.test_stream_key_signature_validate 1 0.108001 +rnp_tests.test_stream_verify_no_key 1 0.0301321 +rnp_tests.test_stream_dumper 1 0.0180775 +rnp_tests.test_stream_z 1 21.1022 +rnp_tests.test_stream_814_dearmor_double_free 1 0.0119918 +rnp_tests.test_stream_825_dearmor_blank_line 1 0.0155773 +rnp_tests.test_stream_dearmor_edge_cases 1 0.0119838 +rnp_tests.test_load_user_prefs 1 0.0142821 +rnp_tests.test_utils_list 1 0.0107737 +rnp_tests.test_rnpcfg 1 0.0108745 +rnp_tests.issue_1030_rnpkeys_secret_keys_unprotected 1 0.31969 +setupTestData 1 0.0175373 +cli_tests-Keystore 1 5.56182 +cli_tests-SignECDSA 1 3.92326 +cli_tests-Compression 1 137.827 +cli_tests-Encryption 1 329.997 +cli_tests-Misc 1 35.6212 +cli_tests-SignDefault 1 16.0034 +cli_tests-EncryptEcdh 1 4.19268 +cli_tests-SignDSA 1 6.13993 +cli_tests-EncryptSignRSA 1 2.47967 +cli_tests-EncryptElgamal 1 11.2535 +--- diff --git a/cmake/Modules/AdocMan.cmake b/cmake/Modules/AdocMan.cmake new file mode 100644 index 0000000..96c5c93 --- /dev/null +++ b/cmake/Modules/AdocMan.cmake @@ -0,0 +1,135 @@ +# Copyright (c) 2021 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +#.adoc: +# add_adoc_man +# ----------- +# +# Convert adoc manual page to troff and install it via the custom target. +# +# Parameters +# ^^^^^^^^^^ +# Required parameter is source with markdown file. Must have md extension with man category prepended, i.e. something like ${CMAKE_SOURCE_DIR}/src/utility.1.adoc +# DST - optional parameter, which overrides where generated man will be stored. +# If not specified then will be automatically set to ${CMAKE_BINARY_DIR}/src/utility.1 +# +# Generated man page will be installed via the target, named man_utility +# + +set(ADOCCOMMAND_FOUND 0) +find_program(ADOCCOMMAND_PATH + NAMES asciidoctor + DOC "Path to AsciiDoc processor. Used to generate man pages from AsciiDoc." +) + +if(NOT EXISTS ${ADOCCOMMAND_PATH}) + set(ADOC_MISSING_MSG "AsciiDoc processor not found, man pages will not be generated. Install asciidoctor or use the CMAKE_PROGRAM_PATH variable.") + + string(TOLOWER "${ENABLE_DOC}" ENABLE_DOC) + if (ENABLE_DOC STREQUAL "auto") + message(WARNING ${ADOC_MISSING_MSG}) + elseif(ENABLE_DOC) + message(FATAL_ERROR ${ADOC_MISSING_MSG}) + endif() +else() + set(ADOCCOMMAND_FOUND 1) +endif() + +function(add_adoc_man SRC COMPONENT_VERSION) + if (NOT ${ADOCCOMMAND_FOUND}) + return() + endif() + + cmake_parse_arguments( + ARGS + "" + "DST" + "" + ${ARGN} + ) + + set(ADOC_EXT ".adoc") + get_filename_component(FILE_NAME ${SRC} NAME) + + # The following procedures check against the expected file name + # pattern: "{name}.{man-number}.adoc", and builds to a + # destination file "{name}.{man-number}". + + # Check SRC extension + get_filename_component(END_EXT ${SRC} LAST_EXT) + string(COMPARE EQUAL ${END_EXT} ${ADOC_EXT} _equal) + if (NOT _equal) + message(FATAL_ERROR "SRC must have ${ADOC_EXT} extension.") + endif() + + # Check man number + get_filename_component(EXTS ${SRC} EXT) + string(REGEX MATCH "^\.([1-9])\.+$" _matches ${EXTS}) + set(MAN_NUM ${CMAKE_MATCH_1}) + if (NOT _matches) + message(FATAL_ERROR "Man file with wrong name pattern: ${FILE_NAME} must be in format {name}.[0-9]${ADOC_EXT}.") + endif() + + # Set target name + get_filename_component(TARGET_NAME ${SRC} NAME_WE) + string(PREPEND TARGET_NAME "man_") + + # Build output path if not specified. + if(NOT DST) + get_filename_component(SRC_PREFIX ${SRC} DIRECTORY) + + # Ensure that SRC_PREFIX is within CMAKE_SOURCE_DIR + if(NOT(SRC_PREFIX MATCHES "^${CMAKE_SOURCE_DIR}")) + message(FATAL_ERROR "Cannot build DST path as SRC is outside of the CMake sources dir.") + endif() + STRING(REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" SUBDIR_PATH ${SRC}) + + # Strip '.adoc' from the output subpath + get_filename_component(SUBDIR_PATH_NAME_WLE ${SUBDIR_PATH} NAME_WLE) + get_filename_component(SUBDIR_PATH_DIRECTORY ${SUBDIR_PATH} DIRECTORY) + set(DST "${CMAKE_BINARY_DIR}/${SUBDIR_PATH_DIRECTORY}/${SUBDIR_PATH_NAME_WLE}") + endif() + + # Check conformance of destination file name to pattern + get_filename_component(FILE_NAME_WE ${SRC} NAME_WE) + get_filename_component(MAN_FILE_NAME ${DST} NAME) + if(NOT(MAN_FILE_NAME MATCHES "^${FILE_NAME_WE}.${MAN_NUM}$")) + message(FATAL_ERROR "File name of a man page must be in the format {name}.{man-number}${ADOC_EXT}.") + endif() + + add_custom_command( + OUTPUT ${DST} + COMMAND ${ADOCCOMMAND_PATH} -b manpage ${SRC} -o ${DST} -a component-version=${COMPONENT_VERSION} + DEPENDS ${SRC} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Generating man page ${SUBDIR_PATH_DIRECTORY}/${SUBDIR_PATH_NAME_WLE}" + VERBATIM + ) + + add_custom_target("${TARGET_NAME}" ALL DEPENDS ${DST}) + install(FILES ${DST} + DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man${MAN_NUM}" + COMPONENT doc + ) +endfunction(add_adoc_man) diff --git a/cmake/Modules/FindBotan2.cmake b/cmake/Modules/FindBotan2.cmake new file mode 100644 index 0000000..2708491 --- /dev/null +++ b/cmake/Modules/FindBotan2.cmake @@ -0,0 +1,131 @@ +# Copyright (c) 2018-2020 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +#.rst: +# FindBotan2 +# ----------- +# +# Find the botan-2 library. +# +# IMPORTED Targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines :prop_tgt:`IMPORTED` targets: +# +# ``Botan2::Botan2`` +# The botan-2 library, if found. +# +# Result variables +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following variables: +# +# :: +# +# BOTAN2_FOUND - true if the headers and library were found +# BOTAN2_INCLUDE_DIRS - where to find headers +# BOTAN2_LIBRARIES - list of libraries to link +# BOTAN2_VERSION - library version that was found, if any + +# use pkg-config to get the directories and then use these values +# in the find_path() and find_library() calls +find_package(PkgConfig QUIET) +pkg_check_modules(PC_BOTAN2 QUIET botan-2) + +# find the headers +find_path(BOTAN2_INCLUDE_DIR + NAMES botan/version.h + HINTS + ${PC_BOTAN2_INCLUDEDIR} + ${PC_BOTAN2_INCLUDE_DIRS} + PATH_SUFFIXES botan-2 +) + +# find the library +if(MSVC) + find_library(BOTAN2_LIBRARY + NAMES botan + HINTS + ${PC_BOTAN2_LIBDIR} + ${PC_BOTAN2_LIBRARY_DIRS} + ) +else() + find_library(BOTAN2_LIBRARY + NAMES botan-2 libbotan-2 + HINTS + ${PC_BOTAN2_LIBDIR} + ${PC_BOTAN2_LIBRARY_DIRS} + ) +endif() + +# determine the version +if(PC_BOTAN2_VERSION) + set(BOTAN2_VERSION ${PC_BOTAN2_VERSION}) +elseif(BOTAN2_INCLUDE_DIR AND EXISTS "${BOTAN2_INCLUDE_DIR}/botan/build.h") + file(STRINGS "${BOTAN2_INCLUDE_DIR}/botan/build.h" botan2_version_str + REGEX "^#define[\t ]+(BOTAN_VERSION_[A-Z]+)[\t ]+[0-9]+") + + string(REGEX REPLACE ".*#define[\t ]+BOTAN_VERSION_MAJOR[\t ]+([0-9]+).*" + "\\1" _botan2_version_major "${botan2_version_str}") + string(REGEX REPLACE ".*#define[\t ]+BOTAN_VERSION_MINOR[\t ]+([0-9]+).*" + "\\1" _botan2_version_minor "${botan2_version_str}") + string(REGEX REPLACE ".*#define[\t ]+BOTAN_VERSION_PATCH[\t ]+([0-9]+).*" + "\\1" _botan2_version_patch "${botan2_version_str}") + set(BOTAN2_VERSION "${_botan2_version_major}.${_botan2_version_minor}.${_botan2_version_patch}" + CACHE INTERNAL "The version of Botan which was detected") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Botan2 + REQUIRED_VARS BOTAN2_LIBRARY BOTAN2_INCLUDE_DIR + VERSION_VAR BOTAN2_VERSION +) + +if (BOTAN2_FOUND) + set(BOTAN2_INCLUDE_DIRS ${BOTAN2_INCLUDE_DIR} ${PC_BOTAN2_INCLUDE_DIRS}) + set(BOTAN2_LIBRARIES ${BOTAN2_LIBRARY}) +endif() + +if (BOTAN2_FOUND AND NOT TARGET Botan2::Botan2) + # create the new library target + add_library(Botan2::Botan2 UNKNOWN IMPORTED) + # set the required include dirs for the target + if (BOTAN2_INCLUDE_DIRS) + set_target_properties(Botan2::Botan2 + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${BOTAN2_INCLUDE_DIRS}" + ) + endif() + # set the required libraries for the target + if (EXISTS "${BOTAN2_LIBRARY}") + set_target_properties(Botan2::Botan2 + PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${BOTAN2_LIBRARY}" + ) + endif() +endif() + +mark_as_advanced(BOTAN2_INCLUDE_DIR BOTAN2_LIBRARY) + diff --git a/cmake/Modules/FindGnuPG.cmake b/cmake/Modules/FindGnuPG.cmake new file mode 100644 index 0000000..ed92027 --- /dev/null +++ b/cmake/Modules/FindGnuPG.cmake @@ -0,0 +1,137 @@ +# Copyright (c) 2018 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +#.rst: +# FindGnuPG +# ----------- +# +# Find GnuPG executables. +# +# Imported targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following :prop_tgt:`IMPORTED` targets: +# +# :: +# +# GnuPG::<COMPONENT> - the component executable that was requested (default is just 'gpg') +# +## Result variables +# ^^^^^^^^^^^^^^^^ +# +# This module always defines the following variables: +# +# :: +# +# GNUPG_VERSION - version that was found +# +# Depending on components requested, this module will also define variables like: +# +# :: +# +# GPG_EXECUTABLE - path to the gpg executable +# <COMPONENT>_EXECUTABLE - path to the component executable +# + +# helper that will call <utility_name> --version and extract the version string +function(_get_gpg_version utility_name exe_path var_prefix) + execute_process( + COMMAND "${exe_path}" --version + OUTPUT_VARIABLE version + RESULT_VARIABLE exit_code + ERROR_QUIET + ) + if (NOT exit_code) + string(REGEX MATCH "${utility_name} \\(GnuPG\\) (([0-9]+)\\.([0-9]+)\\.([0-9]+))" version "${version}") + if (CMAKE_MATCH_1) + set(${var_prefix}_VERSION "${CMAKE_MATCH_1}" PARENT_SCOPE) + endif() + endif() +endfunction() + +# default to finding gpg +if (NOT GnuPG_FIND_COMPONENTS) + set(GnuPG_FIND_COMPONENTS gpg) +endif() + +foreach(_comp IN LISTS GnuPG_FIND_COMPONENTS) + # we also check for an executable with the 2 suffix when appropriate + set(_names "${_comp}") + if (_comp STREQUAL "gpg" OR _comp STREQUAL "gpgv") + if (NOT ${GnuPG_FIND_VERSION}) + set(_names "${_comp}2" ${_comp}) + elseif (${GnuPG_FIND_VERSION} VERSION_GREATER_EQUAL 2.2) + # 2.2+ defaults to gpg/gpgv, but supports gpg2/gpgv2 + set(_names ${_comp} "${_comp}2") + elseif(${GnuPG_FIND_VERSION} VERSION_GREATER_EQUAL 2.0) + # 2.0-2.2 or so used a temporary naming of gpg2/gpgv2 + set(_names "${_comp}2" ${_comp}) + endif() + endif() + string(TOUPPER "${_comp}" _comp_upper) + find_program(${_comp_upper}_EXECUTABLE NAMES ${_names}) + unset(_names) + mark_as_advanced(${_comp_upper}_EXECUTABLE) + + # if we found an executable, check the version + if (${_comp_upper}_EXECUTABLE) + _get_gpg_version(${_comp} ${${_comp_upper}_EXECUTABLE} _${_comp}) + if (_${_comp}_VERSION) + if (NOT GNUPG_VERSION) + # this is the first component found, so set the version to match + set(GNUPG_VERSION ${_${_comp}_VERSION}) + endif() + # see if the version matches the previous components found + if(_${_comp}_VERSION VERSION_EQUAL ${GNUPG_VERSION} AND NOT TARGET GnuPG::${_comp}) + add_executable(GnuPG::${_comp} IMPORTED GLOBAL) + set_target_properties(GnuPG::${_comp} PROPERTIES + IMPORTED_LOCATION "${${_comp_upper}_EXECUTABLE}" + ) + endif() + endif() + unset(_${_comp}_VERSION) + endif() + + # mark our components as found or not found + if (TARGET GnuPG::${_comp}) + set(GnuPG_${_comp}_FOUND TRUE) + else() + set(GnuPG_${_comp}_FOUND FALSE) + unset(${_comp_upper}_EXECUTABLE) + endif() + + if (GnuPG_FIND_REQUIRED_${_comp}) + list(APPEND _GnuPG_REQUIRED_VARS ${_comp_upper}_EXECUTABLE) + endif() +endforeach() +unset(_comp) +unset(_comp_upper) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GnuPG + REQUIRED_VARS ${_GnuPG_REQUIRED_VARS} + VERSION_VAR GNUPG_VERSION + HANDLE_COMPONENTS +) + diff --git a/cmake/Modules/FindJSON-C.cmake b/cmake/Modules/FindJSON-C.cmake new file mode 100644 index 0000000..e66a011 --- /dev/null +++ b/cmake/Modules/FindJSON-C.cmake @@ -0,0 +1,123 @@ +# Copyright (c) 2018 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +#.rst: +# FindJSON-C +# ----------- +# +# Find the json-c library. +# +# IMPORTED Targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines :prop_tgt:`IMPORTED` targets: +# +# ``JSON-C::JSON-C`` +# The json-c library, if found. +# +# Result variables +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following variables: +# +# :: +# +# JSON-C_FOUND - true if the headers and library were found +# JSON-C_INCLUDE_DIRS - where to find headers +# JSON-C_LIBRARIES - list of libraries to link +# JSON-C_VERSION - library version that was found, if any + +# use pkg-config to get the directories and then use these values +# in the find_path() and find_library() calls +find_package(PkgConfig QUIET) +pkg_check_modules(PC_JSON-C QUIET json-c) + +# RHEL-based systems may have json-c12 +if (NOT PC_JSON-C_FOUND) + pkg_check_modules(PC_JSON-C QUIET json-c12) +endif() + +# find the headers +find_path(JSON-C_INCLUDE_DIR + NAMES json_c_version.h + HINTS + ${PC_JSON-C_INCLUDEDIR} + ${PC_JSON-C_INCLUDE_DIRS} + PATH_SUFFIXES json-c +) + +# find the library +find_library(JSON-C_LIBRARY + NAMES json-c libjson-c json-c12 libjson-c12 + HINTS + ${PC_JSON-C_LIBDIR} + ${PC_JSON-C_LIBRARY_DIRS} +) + +# determine the version +if(PC_JSON-C_VERSION) + set(JSON-C_VERSION ${PC_JSON-C_VERSION}) +elseif(JSON-C_INCLUDE_DIR AND EXISTS "${JSON-C_INCLUDE_DIR}/json_c_version.h") + file(STRINGS "${JSON-C_INCLUDE_DIR}/json_c_version.h" _json-c_version_h + REGEX "^#define[\t ]+JSON_C_VERSION[\t ]+\"[^\"]*\"$") + + string(REGEX REPLACE ".*#define[\t ]+JSON_C_VERSION[\t ]+\"([^\"]*)\".*" + "\\1" _json-c_version_str "${_json-c_version_h}") + set(JSON-C_VERSION "${_json-c_version_str}" + CACHE INTERNAL "The version of json-c which was detected") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(JSON-C + REQUIRED_VARS JSON-C_LIBRARY JSON-C_INCLUDE_DIR JSON-C_VERSION + VERSION_VAR JSON-C_VERSION +) + +if (JSON-C_FOUND) + set(JSON-C_INCLUDE_DIRS ${JSON-C_INCLUDE_DIR} ${PC_JSON-C_INCLUDE_DIRS}) + set(JSON-C_LIBRARIES ${JSON-C_LIBRARY}) +endif() + +if (JSON-C_FOUND AND NOT TARGET JSON-C::JSON-C) + # create the new library target + add_library(JSON-C::JSON-C UNKNOWN IMPORTED) + # set the required include dirs for the target + if (JSON-C_INCLUDE_DIRS) + set_target_properties(JSON-C::JSON-C + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${JSON-C_INCLUDE_DIRS}" + ) + endif() + # set the required libraries for the target + if (EXISTS "${JSON-C_LIBRARY}") + set_target_properties(JSON-C::JSON-C + PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${JSON-C_LIBRARY}" + ) + endif() +endif() + +mark_as_advanced(JSON-C_INCLUDE_DIR JSON-C_LIBRARY) + diff --git a/cmake/Modules/FindOpenSSLFeatures.cmake b/cmake/Modules/FindOpenSSLFeatures.cmake new file mode 100644 index 0000000..6967764 --- /dev/null +++ b/cmake/Modules/FindOpenSSLFeatures.cmake @@ -0,0 +1,171 @@ +# Copyright (c) 2021 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +#.rst: +# FindOpenSSLFeatures +# ----------- +# +# Find OpenSSL features: supported hashes, ciphers, curves and public-key algorithms. +# Requires FindOpenSSL to be included first, and C compiler to be set as module +# compiles and executes program which do checks against installed OpenSSL library. +# +# Result variables +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following variables: +# +# :: +# +# OPENSSL_SUPPORTED_HASHES - list of the supported hash algorithms +# OPENSSL_SUPPORTED_CIPHERS - list of the supported ciphers +# OPENSSL_SUPPORTED_CURVES - list of the supported elliptic curves +# OPENSSL_SUPPORTED_PUBLICKEY - list of the supported public-key algorithms +# OPENSSL_SUPPORTED_FEATURES - all previous lists, glued together +# +# Functions +# ^^^^^^^^^ +# OpenSSLHasFeature(FEATURE <VARIABLE>) +# Check whether OpenSSL has corresponding feature (hash/curve/public-key algorithm name, elliptic curve). +# Result is stored in VARIABLE as boolean value, i.e. TRUE or FALSE +# +if (NOT OPENSSL_FOUND) + message(FATAL_ERROR "OpenSSL is not found. Please make sure that you call find_package(OpenSSL) first.") +endif() + +message(STATUS "Querying OpenSSL features") + +# Copy and build findopensslfeatures.c in fossl-build subfolder. +set(_fossl_work_dir "${CMAKE_BINARY_DIR}/fossl") +file(MAKE_DIRECTORY "${_fossl_work_dir}") +file(COPY "${CMAKE_CURRENT_LIST_DIR}/findopensslfeatures.c" + DESTINATION "${_fossl_work_dir}" +) +# As it's short enough let's keep it here. +# Reuse OPENSSL parameters from the upstream project +# otherwise there is a good chance to find another instance of openssl +# We assume that OpenSSL root is one level up openssl include directory +# This does not look as a good solution, however it is the only one that +# works with all Windows configuration options + +message(STATUS "Using OpenSSL root directory at ${OPENSSL_INCLUDE_DIR}/..") + +file(WRITE "${_fossl_work_dir}/CMakeLists.txt" +"cmake_minimum_required(VERSION 3.18)\n\ +project(findopensslfeatures LANGUAGES C)\n\ +set(CMAKE_C_STANDARD 99)\n\ +include(FindOpenSSL)\n\ +find_package(OpenSSL REQUIRED)\n\ +add_executable(findopensslfeatures findopensslfeatures.c)\n\ +target_include_directories(findopensslfeatures PRIVATE ${OPENSSL_INCLUDE_DIR})\n\ +target_link_libraries(findopensslfeatures PRIVATE OpenSSL::Crypto)\n\ +if (OpenSSL::applink)\n\ + target_link_libraries(findopensslfeatures PRIVATE OpenSSL::applink)\n\ +endif(OpenSSL::applink)\n" +) + +set(MKF ${MKF} "-DCMAKE_BUILD_TYPE=Release" "-DOPENSSL_ROOT_DIR=${OPENSSL_INCLUDE_DIR}/..") + +if(CMAKE_PREFIX_PATH) + set(MKF ${MKF} "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}") +endif(CMAKE_PREFIX_PATH) + +if(CMAKE_TOOLCHAIN_FILE) + set(MKF ${MKF} "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}") +endif(CMAKE_TOOLCHAIN_FILE) + +if(CMAKE_GENERATOR_PLATFORM) + set(MKF ${MKF} "-A" "${CMAKE_GENERATOR_PLATFORM}") +endif(CMAKE_GENERATOR_PLATFORM) + +if(CMAKE_GENERATOR_TOOLSET) + set(MKF ${MKF} "-T" "${CMAKE_GENERATOR_TOOLSET}") +endif(CMAKE_GENERATOR_TOOLSET) + +execute_process( + COMMAND "${CMAKE_COMMAND}" "-Bbuild" ${MKF} "." + WORKING_DIRECTORY "${_fossl_work_dir}" + OUTPUT_VARIABLE output + ERROR_VARIABLE error + RESULT_VARIABLE result + COMMAND_ECHO STDOUT + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE +) + +if (NOT ${result} EQUAL 0) + message(FATAL_ERROR "Error configuring findopensslfeatures") +endif() + +execute_process( + COMMAND "${CMAKE_COMMAND}" "--build" "build" --config "Release" + WORKING_DIRECTORY "${_fossl_work_dir}" + OUTPUT_VARIABLE output + ERROR_VARIABLE error + RESULT_VARIABLE result + COMMAND_ECHO STDOUT + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE +) + +if (NOT ${result} EQUAL 0) + message(FATAL_ERROR "Error building findopensslfeatures") +endif() + +set(OPENSSL_SUPPORTED_FEATURES "") +if(WIN32 AND NOT MINGW) + set(FOF "build/Release/findopensslfeatures") +else(WIN32 AND NOT MINGW) + set(FOF "build/findopensslfeatures") +endif(WIN32 AND NOT MINGW) + +foreach(feature "hashes" "ciphers" "curves" "publickey") + execute_process( + COMMAND "${FOF}" "${feature}" + WORKING_DIRECTORY "${_fossl_work_dir}" + OUTPUT_VARIABLE feature_val + ERROR_VARIABLE error + RESULT_VARIABLE result + ) + + if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "Error getting supported OpenSSL ${feature}: ${result}\n${error}") + endif() + + string(TOUPPER ${feature} feature_up) + string(TOUPPER ${feature_val} feature_val) + string(REPLACE "\n" ";" feature_val ${feature_val}) + set(OPENSSL_SUPPORTED_${feature_up} ${feature_val}) + list(LENGTH OPENSSL_SUPPORTED_${feature_up} ${feature}_len) + list(APPEND OPENSSL_SUPPORTED_FEATURES ${OPENSSL_SUPPORTED_${feature_up}}) +endforeach() + +message(STATUS "Fetched OpenSSL features: ${hashes_len} hashes, ${ciphers_len} ciphers, ${curves_len} curves, ${publickey_len} publickey.") + +function(OpenSSLHasFeature FEATURE VARIABLE) + string(TOUPPER ${FEATURE} _feature_up) + set(${VARIABLE} FALSE PARENT_SCOPE) + if (${_feature_up} IN_LIST OPENSSL_SUPPORTED_FEATURES) + set(${VARIABLE} TRUE PARENT_SCOPE) + endif() +endfunction(OpenSSLHasFeature) diff --git a/cmake/Modules/FindWindowsSDK.cmake b/cmake/Modules/FindWindowsSDK.cmake new file mode 100644 index 0000000..d18e979 --- /dev/null +++ b/cmake/Modules/FindWindowsSDK.cmake @@ -0,0 +1,662 @@ +# - Find the Windows SDK aka Platform SDK +# taken from https://github.com/ampl/mp/blob/master/support/cmake/FindWindowsSDK.cmake +# +# Relevant Wikipedia article: http://en.wikipedia.org/wiki/Microsoft_Windows_SDK +# +# Pass "COMPONENTS tools" to ignore Visual Studio version checks: in case +# you just want the tool binaries to run, rather than the libraries and headers +# for compiling. +# +# Variables: +# WINDOWSSDK_FOUND - if any version of the windows or platform SDK was found that is usable with the current version of visual studio +# WINDOWSSDK_LATEST_DIR +# WINDOWSSDK_LATEST_NAME +# WINDOWSSDK_FOUND_PREFERENCE - if we found an entry indicating a "preferred" SDK listed for this visual studio version +# WINDOWSSDK_PREFERRED_DIR +# WINDOWSSDK_PREFERRED_NAME +# +# WINDOWSSDK_DIRS - contains no duplicates, ordered most recent first. +# WINDOWSSDK_PREFERRED_FIRST_DIRS - contains no duplicates, ordered with preferred first, followed by the rest in descending recency +# +# Functions: +# GetUMWindowsSDKLibraryDir(<output variable>) - Find the latest SDK user mode (um) library directory, +# architecture dependent +# GetUMWindowsSDKIncludeDir(<output variable>) - Find the latest SDK user mode (um) include directory +# +# windowssdk_name_lookup(<directory> <output variable>) - Find the name corresponding with the SDK directory you pass in, or +# NOTFOUND if not recognized. Your directory must be one of WINDOWSSDK_DIRS for this to work. +# +# windowssdk_build_lookup(<directory> <output variable>) - Find the build version number corresponding with the SDK directory you pass in, or +# NOTFOUND if not recognized. Your directory must be one of WINDOWSSDK_DIRS for this to work. +# +# get_windowssdk_from_component(<file or dir> <output variable>) - Given a library or include dir, +# find the Windows SDK root dir corresponding to it, or NOTFOUND if unrecognized. +# +# get_windowssdk_library_dirs(<directory> <output variable>) - Find the architecture-appropriate +# library directories corresponding to the SDK directory you pass in (or NOTFOUND if none) +# +# get_windowssdk_library_dirs_multiple(<output variable> <directory> ...) - Find the architecture-appropriate +# library directories corresponding to the SDK directories you pass in, in order, skipping those not found. NOTFOUND if none at all. +# Good for passing WINDOWSSDK_DIRS or WINDOWSSDK_DIRS to if you really just want a file and don't care where from. +# +# get_windowssdk_include_dirs(<directory> <output variable>) - Find the +# include directories corresponding to the SDK directory you pass in (or NOTFOUND if none) +# +# get_windowssdk_include_dirs_multiple(<output variable> <directory> ...) - Find the +# include directories corresponding to the SDK directories you pass in, in order, skipping those not found. NOTFOUND if none at all. +# Good for passing WINDOWSSDK_DIRS or WINDOWSSDK_DIRS to if you really just want a file and don't care where from. +# +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) +# +# Original Author: +# 2012 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net> +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(_preferred_sdk_dirs) # pre-output +set(_win_sdk_dirs) # pre-output +set(_win_sdk_versanddirs) # pre-output +set(_win_sdk_buildsanddirs) # pre-output +set(_winsdk_vistaonly) # search parameters +set(_winsdk_kits) # search parameters + + +set(_WINDOWSSDK_ANNOUNCE OFF) +if(NOT WINDOWSSDK_FOUND AND (NOT WindowsSDK_FIND_QUIETLY)) + set(_WINDOWSSDK_ANNOUNCE ON) +endif() +macro(_winsdk_announce) + if(_WINSDK_ANNOUNCE) + message(STATUS ${ARGN}) + endif() +endmacro() + + +set(_winsdk_win10vers + 10.0.18362.0 # Windows 10 SDK for 2019 Update + 10.0.17763.0 # Windows 10 SDK for October 2018 Update + 10.0.17133.0 # Redstone 4 aka Win10 1803 "April 1018 Update" + 10.0.16299.0 # Redstone 3 aka Win10 1709 "Fall Creators Update" + 10.0.15063.0 # Redstone 2 aka Win10 1703 "Creators Update" + 10.0.14393.0 # Redstone aka Win10 1607 "Anniversary Update" + 10.0.10586.0 # TH2 aka Win10 1511 + 10.0.10240.0 # Win10 RTM + 10.0.10150.0 # just ucrt + 10.0.10056.0 +) + +if(WindowsSDK_FIND_COMPONENTS MATCHES "tools") + set(_WINDOWSSDK_IGNOREMSVC ON) + _winsdk_announce("Checking for tools from Windows/Platform SDKs...") +else() + set(_WINDOWSSDK_IGNOREMSVC OFF) + _winsdk_announce("Checking for Windows/Platform SDKs...") +endif() + +# Appends to the three main pre-output lists used only if the path exists +# and is not already in the list. +function(_winsdk_conditional_append _vername _build _path) + if(("${_path}" MATCHES "registry") OR (NOT EXISTS "${_path}")) + # Path invalid - do not add + return() + endif() + list(FIND _win_sdk_dirs "${_path}" _win_sdk_idx) + if(_win_sdk_idx GREATER -1) + # Path already in list - do not add + return() + endif() + _winsdk_announce( " - ${_vername}, Build ${_build} @ ${_path}") + # Not yet in the list, so we'll add it + list(APPEND _win_sdk_dirs "${_path}") + set(_win_sdk_dirs "${_win_sdk_dirs}" CACHE INTERNAL "" FORCE) + list(APPEND + _win_sdk_versanddirs + "${_vername}" + "${_path}") + set(_win_sdk_versanddirs "${_win_sdk_versanddirs}" CACHE INTERNAL "" FORCE) + list(APPEND + _win_sdk_buildsanddirs + "${_build}" + "${_path}") + set(_win_sdk_buildsanddirs "${_win_sdk_buildsanddirs}" CACHE INTERNAL "" FORCE) +endfunction() + +# Appends to the "preferred SDK" lists only if the path exists +function(_winsdk_conditional_append_preferred _info _path) + if(("${_path}" MATCHES "registry") OR (NOT EXISTS "${_path}")) + # Path invalid - do not add + return() + endif() + + get_filename_component(_path "${_path}" ABSOLUTE) + + list(FIND _win_sdk_preferred_sdk_dirs "${_path}" _win_sdk_idx) + if(_win_sdk_idx GREATER -1) + # Path already in list - do not add + return() + endif() + _winsdk_announce( " - Found \"preferred\" SDK ${_info} @ ${_path}") + # Not yet in the list, so we'll add it + list(APPEND _win_sdk_preferred_sdk_dirs "${_path}") + set(_win_sdk_preferred_sdk_dirs "${_win_sdk_dirs}" CACHE INTERNAL "" FORCE) + + # Just in case we somehow missed it: + _winsdk_conditional_append("${_info}" "" "${_path}") +endfunction() + +# Given a version like v7.0A, looks for an SDK in the registry under "Microsoft SDKs". +# If the given version might be in both HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows +# and HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots aka "Windows Kits", +# use this macro first, since these registry keys usually have more information. +# +# Pass a "default" build number as an extra argument in case we can't find it. +function(_winsdk_check_microsoft_sdks_registry _winsdkver) + set(SDKKEY "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\${_winsdkver}") + get_filename_component(_sdkdir + "[${SDKKEY};InstallationFolder]" + ABSOLUTE) + + set(_sdkname "Windows SDK ${_winsdkver}") + + # Default build number passed as extra argument + set(_build ${ARGN}) + # See if the registry holds a Microsoft-mutilated, err, designated, product name + # (just using get_filename_component to execute the registry lookup) + get_filename_component(_sdkproductname + "[${SDKKEY};ProductName]" + NAME) + if(NOT "${_sdkproductname}" MATCHES "registry") + # Got a product name + set(_sdkname "${_sdkname} (${_sdkproductname})") + endif() + + # try for a version to augment our name + # (just using get_filename_component to execute the registry lookup) + get_filename_component(_sdkver + "[${SDKKEY};ProductVersion]" + NAME) + if(NOT "${_sdkver}" MATCHES "registry" AND NOT MATCHES) + # Got a version + if(NOT "${_sdkver}" MATCHES "\\.\\.") + # and it's not an invalid one with two dots in it: + # use to override the default build + set(_build ${_sdkver}) + if(NOT "${_sdkname}" MATCHES "${_sdkver}") + # Got a version that's not already in the name, let's use it to improve our name. + set(_sdkname "${_sdkname} (${_sdkver})") + endif() + endif() + endif() + _winsdk_conditional_append("${_sdkname}" "${_build}" "${_sdkdir}") +endfunction() + +# Given a name for identification purposes, the build number, and a key (technically a "value name") +# corresponding to a Windows SDK packaged as a "Windows Kit", look for it +# in HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots +# Note that the key or "value name" tends to be something weird like KitsRoot81 - +# no easy way to predict, just have to observe them in the wild. +# Doesn't hurt to also try _winsdk_check_microsoft_sdks_registry for these: +# sometimes you get keys in both parts of the registry (in the wow64 portion especially), +# and the non-"Windows Kits" location is often more descriptive. +function(_winsdk_check_windows_kits_registry _winkit_name _winkit_build _winkit_key) + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;${_winkit_key}]" + ABSOLUTE) + _winsdk_conditional_append("${_winkit_name}" "${_winkit_build}" "${_sdkdir}") +endfunction() + +# Given a name for identification purposes and the build number +# corresponding to a Windows 10 SDK packaged as a "Windows Kit", look for it +# in HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots +# Doesn't hurt to also try _winsdk_check_microsoft_sdks_registry for these: +# sometimes you get keys in both parts of the registry (in the wow64 portion especially), +# and the non-"Windows Kits" location is often more descriptive. +function(_winsdk_check_win10_kits _winkit_build) + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]" + ABSOLUTE) + if(("${_sdkdir}" MATCHES "registry") OR (NOT EXISTS "${_sdkdir}")) + return() # not found + endif() + if(EXISTS "${_sdkdir}/Include/${_winkit_build}/um") + _winsdk_conditional_append("Windows Kits 10 (Build ${_winkit_build})" "${_winkit_build}" "${_sdkdir}") + endif() +endfunction() + +# Given a name for identification purposes, the build number, and the associated package GUID, +# look in the registry under both HKLM and HKCU in \\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\ +# for that guid and the SDK it points to. +function(_winsdk_check_platformsdk_registry _platformsdkname _build _platformsdkguid) + foreach(_winsdk_hive HKEY_LOCAL_MACHINE HKEY_CURRENT_USER) + get_filename_component(_sdkdir + "[${_winsdk_hive}\\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\${_platformsdkguid};Install Dir]" + ABSOLUTE) + _winsdk_conditional_append("${_platformsdkname} (${_build})" "${_build}" "${_sdkdir}") + endforeach() +endfunction() + +### +# Detect toolchain information: to know whether it's OK to use Vista+ only SDKs +### +set(_winsdk_vistaonly_ok OFF) +if(MSVC AND NOT _WINDOWSSDK_IGNOREMSVC) + # VC 10 and older has broad target support + if(MSVC_VERSION LESS 1700) + # VC 11 by default targets Vista and later only, so we can add a few more SDKs that (might?) only work on vista+ + elseif("${CMAKE_VS_PLATFORM_TOOLSET}" MATCHES "_xp") + # This is the XP-compatible v110+ toolset + elseif("${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "v100" OR "${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "v90") + # This is the VS2010/VS2008 toolset + else() + # OK, we're VC11 or newer and not using a backlevel or XP-compatible toolset. + # These versions have no XP (and possibly Vista pre-SP1) support + set(_winsdk_vistaonly_ok ON) + if(_WINDOWSSDK_ANNOUNCE AND NOT _WINDOWSSDK_VISTAONLY_PESTERED) + set(_WINDOWSSDK_VISTAONLY_PESTERED ON CACHE INTERNAL "" FORCE) + message(STATUS "FindWindowsSDK: Detected Visual Studio 2012 or newer, not using the _xp toolset variant: including SDK versions that drop XP support in search!") + endif() + endif() +endif() +if(_WINDOWSSDK_IGNOREMSVC) + set(_winsdk_vistaonly_ok ON) +endif() + +### +# MSVC version checks - keeps messy conditionals in one place +# (messy because of _WINDOWSSDK_IGNOREMSVC) +### +set(_winsdk_msvc_greater_1200 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (MSVC_VERSION GREATER 1200))) + set(_winsdk_msvc_greater_1200 ON) +endif() +# Newer than VS .NET/VS Toolkit 2003 +set(_winsdk_msvc_greater_1310 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (MSVC_VERSION GREATER 1310))) + set(_winsdk_msvc_greater_1310 ON) +endif() + +# VS2005/2008 +set(_winsdk_msvc_less_1600 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (MSVC_VERSION LESS 1600))) + set(_winsdk_msvc_less_1600 ON) +endif() + +# VS2013+ +set(_winsdk_msvc_not_less_1800 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (NOT MSVC_VERSION LESS 1800))) + set(_winsdk_msvc_not_less_1800 ON) +endif() + +### +# START body of find module +### +if(_winsdk_msvc_greater_1310) # Newer than VS .NET/VS Toolkit 2003 + ### + # Look for "preferred" SDKs + ### + + # Environment variable for SDK dir + if(EXISTS "$ENV{WindowsSDKDir}" AND (NOT "$ENV{WindowsSDKDir}" STREQUAL "")) + _winsdk_conditional_append_preferred("WindowsSDKDir environment variable" "$ENV{WindowsSDKDir}") + endif() + + if(_winsdk_msvc_less_1600) + # Per-user current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("Per-user current Windows SDK" "${_sdkdir}") + + # System-wide current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("System-wide current Windows SDK" "${_sdkdir}") + endif() + + ### + # Begin the massive list of SDK searching! + ### + if(_winsdk_vistaonly_ok AND _winsdk_msvc_not_less_1800) + # These require at least Visual Studio 2013 (VC12) + + _winsdk_check_microsoft_sdks_registry(v10.0A) + + # Windows Software Development Kit (SDK) for Windows 10 + # Several different versions living in the same directory - if nothing else we can assume RTM (10240) + _winsdk_check_microsoft_sdks_registry(v10.0 10.0.10240.0) + foreach(_win10build ${_winsdk_win10vers}) + _winsdk_check_win10_kits(${_win10build}) + endforeach() + endif() # vista-only and 2013+ + + # Included in Visual Studio 2013 + # Includes the v120_xp toolset + _winsdk_check_microsoft_sdks_registry(v8.1A 8.1.51636) + + if(_winsdk_vistaonly_ok AND _winsdk_msvc_not_less_1800) + # Windows Software Development Kit (SDK) for Windows 8.1 + # http://msdn.microsoft.com/en-gb/windows/desktop/bg162891 + _winsdk_check_microsoft_sdks_registry(v8.1 8.1.25984.0) + _winsdk_check_windows_kits_registry("Windows Kits 8.1" 8.1.25984.0 KitsRoot81) + endif() # vista-only and 2013+ + + if(_winsdk_vistaonly_ok) + # Included in Visual Studio 2012 + _winsdk_check_microsoft_sdks_registry(v8.0A 8.0.50727) + + # Microsoft Windows SDK for Windows 8 and .NET Framework 4.5 + # This is the first version to also include the DirectX SDK + # http://msdn.microsoft.com/en-US/windows/desktop/hh852363.aspx + _winsdk_check_microsoft_sdks_registry(v8.0 6.2.9200.16384) + _winsdk_check_windows_kits_registry("Windows Kits 8.0" 6.2.9200.16384 KitsRoot) + endif() # vista-only + + # Included with VS 2012 Update 1 or later + # Introduces v110_xp toolset + _winsdk_check_microsoft_sdks_registry(v7.1A 7.1.51106) + if(_winsdk_vistaonly_ok) + # Microsoft Windows SDK for Windows 7 and .NET Framework 4 + # http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b + _winsdk_check_microsoft_sdks_registry(v7.1 7.1.7600.0.30514) + endif() # vista-only + + # Included with VS 2010 + _winsdk_check_microsoft_sdks_registry(v7.0A 6.1.7600.16385) + + # Windows SDK for Windows 7 and .NET Framework 3.5 SP1 + # Works with VC9 + # http://www.microsoft.com/en-us/download/details.aspx?id=18950 + _winsdk_check_microsoft_sdks_registry(v7.0 6.1.7600.16385) + + # Two versions call themselves "v6.1": + # Older: + # Windows Vista Update & .NET 3.0 SDK + # http://www.microsoft.com/en-us/download/details.aspx?id=14477 + + # Newer: + # Windows Server 2008 & .NET 3.5 SDK + # may have broken VS9SP1? they recommend v7.0 instead, or a KB... + # http://www.microsoft.com/en-us/download/details.aspx?id=24826 + _winsdk_check_microsoft_sdks_registry(v6.1 6.1.6000.16384.10) + + # Included in VS 2008 + _winsdk_check_microsoft_sdks_registry(v6.0A 6.1.6723.1) + + # Microsoft Windows Software Development Kit for Windows Vista and .NET Framework 3.0 Runtime Components + # http://blogs.msdn.com/b/stanley/archive/2006/11/08/microsoft-windows-software-development-kit-for-windows-vista-and-net-framework-3-0-runtime-components.aspx + _winsdk_check_microsoft_sdks_registry(v6.0 6.0.6000.16384) +endif() + +# Let's not forget the Platform SDKs, which sometimes are useful! +if(_winsdk_msvc_greater_1200) + _winsdk_check_platformsdk_registry("Microsoft Platform SDK for Windows Server 2003 R2" "5.2.3790.2075.51" "D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1") + _winsdk_check_platformsdk_registry("Microsoft Platform SDK for Windows Server 2003 SP1" "5.2.3790.1830.15" "8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3") +endif() +### +# Finally, look for "preferred" SDKs +### +if(_winsdk_msvc_greater_1310) # Newer than VS .NET/VS Toolkit 2003 + + + # Environment variable for SDK dir + if(EXISTS "$ENV{WindowsSDKDir}" AND (NOT "$ENV{WindowsSDKDir}" STREQUAL "")) + _winsdk_conditional_append_preferred("WindowsSDKDir environment variable" "$ENV{WindowsSDKDir}") + endif() + + if(_winsdk_msvc_less_1600) + # Per-user current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("Per-user current Windows SDK" "${_sdkdir}") + + # System-wide current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("System-wide current Windows SDK" "${_sdkdir}") + endif() +endif() + + +function(windowssdk_name_lookup _dir _outvar) + list(FIND _win_sdk_versanddirs "${_dir}" _diridx) + math(EXPR _idx "${_diridx} - 1") + if(${_idx} GREATER -1) + list(GET _win_sdk_versanddirs ${_idx} _ret) + else() + set(_ret "NOTFOUND") + endif() + set(${_outvar} "${_ret}" PARENT_SCOPE) +endfunction() + +function(windowssdk_build_lookup _dir _outvar) + list(FIND _win_sdk_buildsanddirs "${_dir}" _diridx) + math(EXPR _idx "${_diridx} - 1") + if(${_idx} GREATER -1) + list(GET _win_sdk_buildsanddirs ${_idx} _ret) + else() + set(_ret "NOTFOUND") + endif() + set(${_outvar} "${_ret}" PARENT_SCOPE) +endfunction() + +# If we found something... +if(_win_sdk_dirs) + list(GET _win_sdk_dirs 0 WINDOWSSDK_LATEST_DIR) + windowssdk_name_lookup("${WINDOWSSDK_LATEST_DIR}" + WINDOWSSDK_LATEST_NAME) + set(WINDOWSSDK_DIRS ${_win_sdk_dirs}) + + # Fallback, in case no preference found. + set(WINDOWSSDK_PREFERRED_DIR "${WINDOWSSDK_LATEST_DIR}") + set(WINDOWSSDK_PREFERRED_NAME "${WINDOWSSDK_LATEST_NAME}") + set(WINDOWSSDK_PREFERRED_FIRST_DIRS ${WINDOWSSDK_DIRS}) + set(WINDOWSSDK_FOUND_PREFERENCE OFF) +endif() + +# If we found indications of a user preference... +if(_win_sdk_preferred_sdk_dirs) + list(GET _win_sdk_preferred_sdk_dirs 0 WINDOWSSDK_PREFERRED_DIR) + windowssdk_name_lookup("${WINDOWSSDK_PREFERRED_DIR}" + WINDOWSSDK_PREFERRED_NAME) + set(WINDOWSSDK_PREFERRED_FIRST_DIRS + ${_win_sdk_preferred_sdk_dirs} + ${_win_sdk_dirs}) + list(REMOVE_DUPLICATES WINDOWSSDK_PREFERRED_FIRST_DIRS) + set(WINDOWSSDK_FOUND_PREFERENCE ON) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(WindowsSDK + "No compatible version of the Windows SDK or Platform SDK found." + WINDOWSSDK_DIRS) + +if(WINDOWSSDK_FOUND) + # Internal: Architecture-appropriate library directory names. + if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM") + if(CMAKE_SIZEOF_VOID_P MATCHES "8") + # Only supported in Win10 SDK and up. + set(_winsdk_arch8 arm64) # what the WDK for Win8+ calls this architecture + else() + set(_winsdk_archbare /arm) # what the architecture used to be called in oldest SDKs + set(_winsdk_arch arm) # what the architecture used to be called + set(_winsdk_arch8 arm) # what the WDK for Win8+ calls this architecture + endif() + else() + if(CMAKE_SIZEOF_VOID_P MATCHES "8") + set(_winsdk_archbare /x64) # what the architecture used to be called in oldest SDKs + set(_winsdk_arch amd64) # what the architecture used to be called + set(_winsdk_arch8 x64) # what the WDK for Win8+ calls this architecture + else() + set(_winsdk_archbare ) # what the architecture used to be called in oldest SDKs + set(_winsdk_arch i386) # what the architecture used to be called + set(_winsdk_arch8 x86) # what the WDK for Win8+ calls this architecture + endif() + endif() + + function(get_windowssdk_from_component _component _var) + get_filename_component(_component "${_component}" ABSOLUTE) + file(TO_CMAKE_PATH "${_component}" _component) + foreach(_sdkdir ${WINDOWSSDK_DIRS}) + get_filename_component(_sdkdir "${_sdkdir}" ABSOLUTE) + string(LENGTH "${_sdkdir}" _sdklen) + file(RELATIVE_PATH _rel "${_sdkdir}" "${_component}") + # If we don't have any "parent directory" items... + if(NOT "${_rel}" MATCHES "[.][.]") + set(${_var} "${_sdkdir}" PARENT_SCOPE) + return() + endif() + endforeach() + # Fail. + set(${_var} "NOTFOUND" PARENT_SCOPE) + endfunction() + function(get_windowssdk_library_dirs _winsdk_dir _var) + set(_dirs) + set(_suffixes + "lib${_winsdk_archbare}" # SDKs like 7.1A + "lib/${_winsdk_arch}" # just because some SDKs have x86 dir and root dir + "lib/w2k/${_winsdk_arch}" # Win2k min requirement + "lib/wxp/${_winsdk_arch}" # WinXP min requirement + "lib/wnet/${_winsdk_arch}" # Win Server 2003 min requirement + "lib/wlh/${_winsdk_arch}" + "lib/wlh/um/${_winsdk_arch8}" # Win Vista ("Long Horn") min requirement + "lib/win7/${_winsdk_arch}" + "lib/win7/um/${_winsdk_arch8}" # Win 7 min requirement + ) + foreach(_ver + wlh # Win Vista ("Long Horn") min requirement + win7 # Win 7 min requirement + win8 # Win 8 min requirement + winv6.3 # Win 8.1 min requirement + ) + + list(APPEND _suffixes + "lib/${_ver}/${_winsdk_arch}" + "lib/${_ver}/um/${_winsdk_arch8}" + "lib/${_ver}/km/${_winsdk_arch8}" + ) + endforeach() + + # Look for WDF libraries in Win10+ SDK + foreach(_mode umdf kmdf) + file(GLOB _wdfdirs RELATIVE "${_winsdk_dir}" "${_winsdk_dir}/lib/wdf/${_mode}/${_winsdk_arch8}/*") + if(_wdfdirs) + list(APPEND _suffixes ${_wdfdirs}) + endif() + endforeach() + + # Look in each Win10+ SDK version for the components + foreach(_win10ver ${_winsdk_win10vers}) + foreach(_component um km ucrt mmos) + list(APPEND _suffixes "lib/${_win10ver}/${_component}/${_winsdk_arch8}") + endforeach() + endforeach() + + foreach(_suffix ${_suffixes}) + # Check to see if a library actually exists here. + file(GLOB _libs "${_winsdk_dir}/${_suffix}/*.lib") + if(_libs) + list(APPEND _dirs "${_winsdk_dir}/${_suffix}") + endif() + endforeach() + if("${_dirs}" STREQUAL "") + set(_dirs NOTFOUND) + else() + list(REMOVE_DUPLICATES _dirs) + endif() + set(${_var} ${_dirs} PARENT_SCOPE) + endfunction() + function(get_windowssdk_include_dirs _winsdk_dir _var) + set(_dirs) + + set(_subdirs shared um winrt km wdf mmos ucrt) + set(_suffixes Include) + + foreach(_dir ${_subdirs}) + list(APPEND _suffixes "Include/${_dir}") + endforeach() + + foreach(_ver ${_winsdk_win10vers}) + foreach(_dir ${_subdirs}) + list(APPEND _suffixes "Include/${_ver}/${_dir}") + endforeach() + endforeach() + + foreach(_suffix ${_suffixes}) + # Check to see if a header file actually exists here. + file(GLOB _headers "${_winsdk_dir}/${_suffix}/*.h") + if(_headers) + list(APPEND _dirs "${_winsdk_dir}/${_suffix}") + endif() + endforeach() + if("${_dirs}" STREQUAL "") + set(_dirs NOTFOUND) + else() + list(REMOVE_DUPLICATES _dirs) + endif() + set(${_var} ${_dirs} PARENT_SCOPE) + endfunction() + + + + function(get_windowssdk_library_dirs_multiple _var) + set(_dirs) + foreach(_sdkdir ${ARGN}) + get_windowssdk_library_dirs("${_sdkdir}" _current_sdk_libdirs) + if(_current_sdk_libdirs) + list(APPEND _dirs ${_current_sdk_libdirs}) + endif() + endforeach() + if("${_dirs}" STREQUAL "") + set(_dirs NOTFOUND) + else() + list(REMOVE_DUPLICATES _dirs) + endif() + set(${_var} ${_dirs} PARENT_SCOPE) + endfunction() + function(get_windowssdk_include_dirs_multiple _var) + set(_dirs) + foreach(_sdkdir ${ARGN}) + get_windowssdk_include_dirs("${_sdkdir}" _current_sdk_incdirs) + if(_current_sdk_libdirs) + list(APPEND _dirs ${_current_sdk_incdirs}) + endif() + endforeach() + if("${_dirs}" STREQUAL "") + set(_dirs NOTFOUND) + else() + list(REMOVE_DUPLICATES _dirs) + endif() + set(${_var} ${_dirs} PARENT_SCOPE) + endfunction() +endif() + + +function(FindFirstStringMatching list reg matching) + foreach(l ${${list}}) + if(${l} MATCHES ${reg}) + set(${matching} ${l} PARENT_SCOPE) + break() + endif() + endforeach() +endfunction() + +function(GetUMWindowsSDKLibraryDir library_dir) + get_windowssdk_library_dirs(${WINDOWSSDK_LATEST_DIR} WIN_LIBRARY_DIRS) + FindFirstStringMatching(WIN_LIBRARY_DIRS "[\\/]um[\\/]" WINDOWSKIT_LIBRARY_DIR) + set(${library_dir} ${WINDOWSKIT_LIBRARY_DIR} PARENT_SCOPE) +endfunction() + +function(GetUMWindowsSDKIncludeDir include_dir) + get_windowssdk_include_dirs(${WINDOWSSDK_LATEST_DIR} WIN_INCLUDE_DIRS) + FindFirstStringMatching(WIN_INCLUDE_DIRS "[\\/]um[\\/]" WIN_INCLUDE_DIR) + set(${include_dir} ${WIN_INCLUDE_DIR} PARENT_SCOPE) +endfunction() diff --git a/cmake/Modules/findopensslfeatures.c b/cmake/Modules/findopensslfeatures.c new file mode 100644 index 0000000..390f1d2 --- /dev/null +++ b/cmake/Modules/findopensslfeatures.c @@ -0,0 +1,101 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <openssl/ec.h> +#include <openssl/objects.h> +#include <openssl/evp.h> + +int +list_curves() +{ + size_t len = EC_get_builtin_curves(NULL, 0); + EC_builtin_curve *curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * len); + if (!curves) { + fprintf(stderr, "Allocation failed.\n"); + return 1; + } + if (!EC_get_builtin_curves(curves, len)) { + OPENSSL_free(curves); + fprintf(stderr, "Failed to get curves.\n"); + return 1; + } + for (size_t i = 0; i < len; i++) { + const char *sname = OBJ_nid2sn(curves[i].nid); + if (!sname) { + continue; + } + printf("%s\n", sname); + } + OPENSSL_free(curves); + return 0; +} + +static void +print_hash(const EVP_MD *md, const char *from, const char *to, void *arg) +{ + if (!md) { + return; + } + if (strstr(from, "rsa") || strstr(from, "RSA")) { + return; + } + printf("%s\n", from); +} + +int +list_hashes() +{ + EVP_MD_do_all_sorted(print_hash, NULL); + return 0; +} + +static void +print_cipher(const EVP_CIPHER *cipher, const char *from, const char *to, void *x) +{ + if (!cipher) { + return; + } + printf("%s\n", from); +} + +int +list_ciphers() +{ + EVP_CIPHER_do_all_sorted(print_cipher, NULL); + return 0; +} + +int +list_publickey() +{ + for (size_t i = 0; i < EVP_PKEY_meth_get_count(); i++) { + const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i); + int id = 0; + EVP_PKEY_meth_get0_info(&id, NULL, pmeth); + printf("%s\n", OBJ_nid2ln(id)); + } + return 0; +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: opensslfeatures [curves|hashes|ciphers|publickey]\n"); + return 1; + } + if (!strcmp(argv[1], "hashes")) { + return list_hashes(); + } + if (!strcmp(argv[1], "ciphers")) { + return list_ciphers(); + } + if (!strcmp(argv[1], "curves")) { + return list_curves(); + } + if (!strcmp(argv[1], "publickey")) { + return list_publickey(); + } + fprintf(stderr, "Unknown command: %s\n", argv[1]); + return 1; +} diff --git a/cmake/info.cmake b/cmake/info.cmake new file mode 100644 index 0000000..21ea680 --- /dev/null +++ b/cmake/info.cmake @@ -0,0 +1,41 @@ +# Copyright (c) 2018 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# this file contains things that are likely to change occasionally +set(PACKAGE_VENDOR "Ribose Inc.") +set(PACKAGE_URL "https://github.com/rnpgp/rnp") + +set(PACKAGING_EMAIL "Ribose Inc. <rnpgp@ribose.com>") +set(BUGREPORT_EMAIL "${PACKAGING_EMAIL}") + +set(PACKAGE_DESCRIPTION [=[ +A set of OpenPGP tools for encrypting, decrypting, signing, and \ +verifying files. +]=] +) +set(PACKAGE_DESCRIPTION_SHORT "Freely-licensed OpenPGP library and command-line tools") +set(PACKAGE_LICENSE "BSD") + +set(RPM_RELEASE_NUM 1) +set(DEB_RELEASE_NUM 1) diff --git a/cmake/librnp.pc.in b/cmake/librnp.pc.in new file mode 100644 index 0000000..2eb84bf --- /dev/null +++ b/cmake/librnp.pc.in @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@PKGCONFIG_LIBDIR@ +includedir=@PKGCONFIG_INCLUDEDIR@ + +Name: rnp +Description: @PACKAGE_DESCRIPTION_SHORT@ +Version: @PROJECT_VERSION@ + +Libs: -L${libdir} -l@LIBRNP_OUTPUT_NAME@ +Libs.private: @LIBRNP_PRIVATE_LIBS@ +Cflags: -I${includedir} + diff --git a/cmake/packaging.cmake b/cmake/packaging.cmake new file mode 100644 index 0000000..2180845 --- /dev/null +++ b/cmake/packaging.cmake @@ -0,0 +1,79 @@ +# Copyright (c) 2018, 2023 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# this file contains packaging items that aren't likely to change much + +# general +set(CPACK_PACKAGE_VENDOR "${PACKAGE_VENDOR}") +set(CPACK_PACKAGE_CONTACT "${PACKAGING_EMAIL}") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE_DESCRIPTION_SHORT}") +set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") +set(CPACK_PACKAGE_FILE_NAME "rnp-${CPACK_PACKAGE_VERSION}") +set(CPACK_PACKAGE_NAME "rnp${PROJECT_VERSION_MAJOR}") + +set(CPACK_SOURCE_IGNORE_FILES "/installs/;/build/;/\\\\.git/;\\\\.#;/#") + +# deb-specific +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PACKAGE_URL}") +set(CPACK_DEBIAN_PACKAGE_RELEASE "${DEB_RELEASE_NUM}") +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + +# rpm-specific +set(CPACK_RPM_PACKAGE_LICENSE "${PACKAGE_LICENSE}") +set(CPACK_RPM_PACKAGE_URL "${PACKAGE_URL}") +set(CPACK_RPM_PACKAGE_RELEASE "${RPM_RELEASE_NUM}${RNP_VERSION_SUFFIX}") +set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) +set(CPACK_RPM_PACKAGE_GROUP "Applications/System") +set(CPACK_RPM_PACKAGE_DESCRIPTION "${PACKAGE_DESCRIPTION}") +set(CPACK_RPM_PACKAGE_AUTOREQPROV ON) +file(WRITE "${PROJECT_BINARY_DIR}/rpm-ldconfig" "/sbin/ldconfig") +set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${PROJECT_BINARY_DIR}/rpm-ldconfig") +set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${PROJECT_BINARY_DIR}/rpm-ldconfig") +# rnp - obsolete the original package name, now preferring to append the major ver +# rnp0 < [...] - obsolete the monolithic RPM generated by previous versions +set(CPACK_RPM_PACKAGE_OBSOLETES "rnp, rnp0 < %{version}-%{release}") +# rpm component packages +set(CPACK_RPM_COMPONENT_INSTALL ON) +set(CPACK_RPM_MAIN_COMPONENT "cli") +# runtime library +set(CPACK_RPM_RUNTIME_PACKAGE_NAME "librnp${PROJECT_VERSION_MAJOR}") +set(CPACK_RPM_RUNTIME_FILE_NAME "${CPACK_RPM_RUNTIME_PACKAGE_NAME}-%{version}-%{release}.rpm") +set(CPACK_RPM_RUNTIME_PACKAGE_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY} (runtime)") +# development files +set(CPACK_RPM_DEVELOPMENT_PACKAGE_NAME "${CPACK_RPM_RUNTIME_PACKAGE_NAME}-devel") +set(CPACK_RPM_DEVELOPMENT_FILE_NAME "${CPACK_RPM_DEVELOPMENT_PACKAGE_NAME}-%{version}-%{release}.rpm") +set(CPACK_RPM_DEVELOPMENT_PACKAGE_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY} (development files)") +set(CPACK_RPM_DEVELOPMENT_PACKAGE_DESCRIPTION "Development files for the rnp library") +set(CPACK_RPM_DEVELOPMENT_PACKAGE_REQUIRES "${CPACK_RPM_RUNTIME_PACKAGE_NAME}") +# cli utils +set(CPACK_RPM_CLI_FILE_NAME RPM-DEFAULT) +set(CPACK_RPM_CLI_PACKAGE_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY} (command-line utilities)") + +# bsd-specific +set(CPACK_FREEBSD_PACKAGE_MAINTAINER "${PACKAGING_EMAIL}") +set(CPACK_FREEBSD_PACKAGE_ORIGIN "security/rnp") +set(CPACK_FREEBSD_PACKAGE_CATEGORIES security) +set(CPACK_FREEBSD_PACKAGE_DEPS bzip2 json-c botan2) + +include(CPack) diff --git a/cmake/rnp-config.cmake.in b/cmake/rnp-config.cmake.in new file mode 100644 index 0000000..04f4f26 --- /dev/null +++ b/cmake/rnp-config.cmake.in @@ -0,0 +1,31 @@ +# Copyright (c) 2018 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +if(NOT TARGET rnp::librnp) + include("${CMAKE_CURRENT_LIST_DIR}/rnp-targets.cmake") +endif() diff --git a/cmake/rnp_tests_discover.cmake b/cmake/rnp_tests_discover.cmake new file mode 100644 index 0000000..9f05293 --- /dev/null +++ b/cmake/rnp_tests_discover.cmake @@ -0,0 +1,40 @@ +set(script) + +function(add_command NAME) + set(_args "") + foreach(_arg ${ARGN}) + set(_args "${_args} [==[${_arg}]==]") + endforeach() + set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) +endfunction() + +if(NOT EXISTS "${TEST_EXECUTABLE}") + message(FATAL_ERROR "Executable does not exist: ${TEST_EXECUTABE}") +endif() +execute_process( + COMMAND "${TEST_EXECUTABLE}" list-tests + WORKING_DIRECTORY "${TEST_WORKING_DIR}" + OUTPUT_VARIABLE output + RESULT_VARIABLE result +) +if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "Error running executable: ${TEST_EXECUTABE}") +endif() + +string(REPLACE "\n" ";" output "${output}") + +foreach(line ${output}) + set(test "${line}") + add_command(add_test + "rnp_tests-${test}" + "${TEST_EXECUTABLE}" + "${test}" + ) + add_command(set_tests_properties + "rnp_tests-${test}" + PROPERTIES ${TEST_PROPERTIES} + ) +endforeach() + +file(WRITE "${CTEST_FILE}" "${script}") + diff --git a/cmake/version.cmake b/cmake/version.cmake new file mode 100644 index 0000000..f74126e --- /dev/null +++ b/cmake/version.cmake @@ -0,0 +1,163 @@ +# Copyright (c) 2018-2021 Ribose Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# desired length of commit hash +set(GIT_REV_LEN 7) + +# call git, store output in var (can fail) +macro(_git var) + execute_process( + COMMAND "${GIT_EXECUTABLE}" ${ARGN} + WORKING_DIRECTORY "${source_dir}" + RESULT_VARIABLE _git_ec + OUTPUT_VARIABLE ${var} + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) +endmacro() + +function(extract_version_info version var_prefix) + # extract the main components + # v1.9.0-3-g5b92266+1546836556 + # v1.9.0-3-g5b92266-dirty+1546836556 + string(REGEX MATCH "^v?([0-9]+\\.[0-9]+\\.[0-9]+)(-([0-9]+)-g([0-9a-f]+)(-dirty)?)?(\\+([0-9]+))?$" matches "${version}") + if (NOT matches) + message(FATAL_ERROR "Failed to extract version components from ${version}.") + endif() + set(${var_prefix}_VERSION "${CMAKE_MATCH_1}" PARENT_SCOPE) # 1.9.0 + if (NOT CMAKE_MATCH_3) + set(CMAKE_MATCH_3 "0") + endif() + set(${var_prefix}_VERSION_NCOMMITS "${CMAKE_MATCH_3}" PARENT_SCOPE) # 3 + if (NOT CMAKE_MATCH_4) + set(CMAKE_MATCH_4 "0") + endif() + set(${var_prefix}_VERSION_GIT_REV "${CMAKE_MATCH_4}" PARENT_SCOPE) # 5b92266 + if (CMAKE_MATCH_5 STREQUAL "-dirty") + set(${var_prefix}_VERSION_IS_DIRTY TRUE PARENT_SCOPE) + else() + set(${var_prefix}_VERSION_IS_DIRTY FALSE PARENT_SCOPE) + endif() + # timestamp is optional, default to 0 + if (NOT CMAKE_MATCH_7) + set(CMAKE_MATCH_7 "0") + endif() + set(${var_prefix}_VERSION_COMMIT_TIMESTAMP "${CMAKE_MATCH_7}" PARENT_SCOPE) # 1546836556 +endfunction() + +function(determine_version source_dir var_prefix) + set(has_release_tag NO) + set(has_version_txt NO) + set(local_prefix "_determine_ver") + # find out base version via version.txt + set(base_version "0.0.0") + if (EXISTS "${source_dir}/version.txt") + set(has_version_txt YES) + file(STRINGS "${source_dir}/version.txt" version_file) + extract_version_info("${version_file}" "${local_prefix}") + set(base_version "${${local_prefix}_VERSION}") + message(STATUS "Found version.txt with ${version_file}") + else() + message(STATUS "Found no version.txt.") + endif() + # for GIT_EXECUTABLE + find_package(Git) + # get a description of the version, something like: + # v1.9.1-0-g38ffe82 (a tagged release) + # v1.9.1-0-g38ffe82-dirty (a tagged release with local modifications) + # v1.9.0-3-g5b92266 (post-release snapshot) + # v1.9.0-3-g5b92266-dirty (post-release snapshot with local modifications) + _git(version describe --abbrev=${GIT_REV_LEN} --match "v[0-9]*" --long --dirty) + if (NOT _git_ec EQUAL 0) + # no annotated tags, fake one + message(STATUS "Found no annotated tags.") + _git(revision rev-parse --short=${GIT_REV_LEN} --verify HEAD) + if (_git_ec EQUAL 0) + set(version "v${base_version}-0-g${revision}") + # check if dirty (this won't detect untracked files, but should be ok) + _git(changes diff-index --quiet HEAD --) + if (NOT _git_ec EQUAL 0) + string(APPEND version "-dirty") + endif() + # append the commit timestamp of the most recent commit (only + # in non-release branches -- typically master) + _git(commit_timestamp show -s --format=%ct) + if (_git_ec EQUAL 0) + string(APPEND version "+${commit_timestamp}") + endif() + elseif(has_version_txt) + # Nothing to get from git - so use version.txt completely + set(version "${version_file}") + else() + # Sad case - no git, no version.txt + set(version "v${base_version}") + endif() + else() + set(has_release_tag YES) + message(STATUS "Found annotated tag ${version}") + endif() + extract_version_info("${version}" "${local_prefix}") + if ("${has_version_txt}" AND NOT ${base_version} STREQUAL ${local_prefix}_VERSION) + message(WARNING "Tagged version ${${local_prefix}_VERSION} doesn't match one from the version.txt: ${base_version}") + if (${base_version} VERSION_GREATER ${local_prefix}_VERSION) + set(${local_prefix}_VERSION ${base_version}) + endif() + endif() + foreach(suffix VERSION VERSION_NCOMMITS VERSION_GIT_REV VERSION_IS_DIRTY VERSION_COMMIT_TIMESTAMP) + if (NOT DEFINED ${local_prefix}_${suffix}) + message(FATAL_ERROR "Unable to determine version.") + endif() + set(${var_prefix}_${suffix} "${${local_prefix}_${suffix}}" PARENT_SCOPE) + message(STATUS "${var_prefix}_${suffix}: ${${local_prefix}_${suffix}}") + endforeach() + # Set VERSION_SUFFIX and VERSION_FULL. When making changes, be aware that + # this is used in packaging as well and will affect ordering. + # | state | version_full | + # |-----------------------------------------------------| + # | exact tag | 0.9.0 | + # | exact tag, dirty | 0.9.0+git20180604 | + # | after tag | 0.9.0+git20180604.1.085039f | + # | no tag, version.txt | 0.9.0+git20180604.2ee02af | + # | no tag, no version.txt| 0.0.0+git20180604.2ee02af | + string(TIMESTAMP date "%Y%m%d" UTC) + set(version_suffix "") + if (NOT ${local_prefix}_VERSION_NCOMMITS EQUAL 0) + # 0.9.0+git20150604.4.289818b + string(APPEND version_suffix "+git${date}.${${local_prefix}_VERSION_NCOMMITS}.${${local_prefix}_VERSION_GIT_REV}") + elseif ((NOT has_release_tag) AND ((NOT has_version_txt) OR ("${base_version}" STREQUAL "0.0.0") OR (NOT "${revision}" STREQUAL ""))) + # 0.9.0+git20150604.289818b + string(APPEND version_suffix "+git${date}.${${local_prefix}_VERSION_GIT_REV}") + elseif(${local_prefix}_VERSION_IS_DIRTY) + # 0.9.0+git20150604 + string(APPEND version_suffix "+git${date}") + endif() + set(version_full "${${local_prefix}_VERSION}${version_suffix}") + # set the results + set(${var_prefix}_VERSION_SUFFIX "${version_suffix}" PARENT_SCOPE) + set(${var_prefix}_VERSION_FULL "${version_full}" PARENT_SCOPE) + # for informational purposes + message(STATUS "${var_prefix}_VERSION_SUFFIX: ${version_suffix}") + message(STATUS "${var_prefix}_VERSION_FULL: ${version_full}") +endfunction() + |