From 96d7f404e7d15425ae69e364a816a40d9ad8001e Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Sun, 2 Feb 2025 14:12:30 +0100 Subject: [PATCH] cmake: make `libssh2-config` work with all TLS-backends CMake: - Find*: set `_FOUND` for compatibility when found via `pkg-config`. E.g. `MbedTLS_FOUND`. `find_package_handle_standard_args()` sets both `_FOUND` and `_FOUND` when detecting the dependency. Some CMake code relies on this and 3rd-party code may rely on it too. Make sure to set the latter variant when detecting the dependency via `pkg-config`, where we don't call `find_package_handle_standard_args()`. CMake sets these variable to `TRUE` (not `ON` or `1`). Replicate this for compatibility. - libssh2-config.cmake: inherit default `LIBSSH2_USE_PKGCONFIG`. Follow-up to a3aa6b4ca83bb8a3ed159612a44b25261dc9f537 #1525 - document variables consumed by `libssh2-config.cmake.in`. - `libssh2-config.cmake`: fix to link to non-OpenSSL crypto backends. This is most likely not how this is supposed to be done, but better than failing. What's the canonical way to do this, and how OpenSSL and zlib does it is yet to be figured out. - use `ZLIB::ZLIB` to reference zlib. - use `IN ITEMS` where missed. - harmonize variable dump output formats. CMake `find_package` integration tests: - extend to all crypto backends (was: OpenSSL). - show libssh2 variables set by `find_package()`. - stop building examples and tests for the consumed package. For performance. - enable zlib, for coverage. - be verbose when building the test targets. ci/GHA: - add packaged mbedTLS (2.x) build to Linux matrix. - alphasort some tests. Follow-up to d9c2e550caa4ad9052ad949d165ed85895ae5aee #1460 Follow-up to 82b09f9b3aae97f641fbcc2d746d2a6383abe857 #1322 Closes #1534 --- .github/workflows/ci.yml | 33 +++++++++++++++++++++------------ CMakeLists.txt | 11 ++++------- cmake/FindLibgcrypt.cmake | 1 + cmake/FindMbedTLS.cmake | 1 + cmake/FindWolfSSL.cmake | 1 + cmake/libssh2-config.cmake.in | 32 ++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 10 ++++++++-- tests/cmake/CMakeLists.txt | 18 ++++++++++++++---- tests/cmake/test.sh | 14 ++++++++------ 9 files changed, 90 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77345daf..25fd0678 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: MAKEFLAGS: -j5 steps: - name: 'install prereqs' - run: sudo apt-get -o Dpkg::Use-Pty=0 install libssl-dev + run: sudo apt-get -o Dpkg::Use-Pty=0 install libgcrypt-dev libssl-dev libmbedtls-dev libwolfssl-dev - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: persist-credentials: false @@ -66,8 +66,14 @@ jobs: run: ./tests/cmake/test.sh FetchContent - name: 'via add_subdirectory' run: ./tests/cmake/test.sh add_subdirectory - - name: 'via find_package' - run: ./tests/cmake/test.sh find_package + - name: 'via find_package OpenSSL' + run: ./tests/cmake/test.sh find_package OpenSSL + - name: 'via find_package Libgcrypt' + run: ./tests/cmake/test.sh find_package Libgcrypt + - name: 'via find_package mbedTLS' + run: ./tests/cmake/test.sh find_package mbedTLS + - name: 'via find_package wolfSSL' + run: ./tests/cmake/test.sh find_package wolfSSL build_linux: name: 'linux' @@ -78,7 +84,7 @@ jobs: matrix: compiler: [gcc, clang] arch: [amd64] - crypto: [OpenSSL, wolfSSL, Libgcrypt, mbedTLS] + crypto: [OpenSSL, Libgcrypt, mbedTLS, wolfSSL] build: [cmake] zlib: ['OFF', 'ON'] include: @@ -136,7 +142,7 @@ jobs: zlib: 'ON' - compiler: gcc arch: i386 - crypto: mbedTLS + crypto: mbedTLS-from-source build: cmake zlib: 'ON' - compiler: clang @@ -177,14 +183,15 @@ jobs: - name: 'install packages' run: | [ '${{ matrix.crypto }}' = 'OpenSSL' ] && pkg='libssl-dev' - [ '${{ matrix.crypto }}' = 'wolfSSL' ] && pkg='libwolfssl-dev' [ '${{ matrix.crypto }}' = 'Libgcrypt' ] && pkg='libgcrypt-dev' + [ '${{ matrix.crypto }}' = 'mbedTLS' ] && pkg='libmbedtls-dev' + [ '${{ matrix.crypto }}' = 'wolfSSL' ] && pkg='libwolfssl-dev' if [ -n "${pkg}" ]; then sudo apt-get -o Dpkg::Use-Pty=0 install "${pkg}:${{ matrix.arch }}" fi - name: 'cache mbedTLS' - if: ${{ matrix.crypto == 'mbedTLS' }} + if: ${{ matrix.crypto == 'mbedTLS-from-source' }} uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4 id: cache-mbedtls with: @@ -192,7 +199,7 @@ jobs: key: ${{ runner.os }}-mbedtls-${{ env.mbedtls-version }}-${{ matrix.arch }} - name: 'install mbedTLS from source' - if: ${{ matrix.crypto == 'mbedTLS' }} + if: ${{ matrix.crypto == 'mbedTLS-from-source' }} run: | if [ '${{ steps.cache-mbedtls.outputs.cache-hit }}' != 'true' ]; then curl -fsS -L https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${{ env.mbedtls-version }}/mbedtls-${{ env.mbedtls-version }}.tar.bz2 | tar -xjf - @@ -444,6 +451,8 @@ jobs: [ '${{ matrix.crypto }}' = 'LibreSSL' ] || \ [[ '${{ matrix.crypto }}' = 'OpenSSL-'* ]]; then crypto='OpenSSL' + elif [[ '${{ matrix.crypto }}' = 'mbedTLS-'* ]]; then + crypto='mbedTLS' elif [[ '${{ matrix.crypto }}' = 'wolfSSL-'* ]]; then crypto='wolfSSL' else @@ -753,10 +762,6 @@ jobs: install: libressl configure: --with-crypto=openssl --with-libssl-prefix="$(brew --prefix)/opt/libressl" cmake: -DCRYPTO_BACKEND=OpenSSL -DOPENSSL_ROOT_DIR="$(brew --prefix)/opt/libressl" - - name: 'wolfSSL' - install: wolfssl - configure: --with-crypto=wolfssl --with-libwolfssl-prefix="$(brew --prefix)" - cmake: -DCRYPTO_BACKEND=wolfSSL - name: 'Libgcrypt' install: libgcrypt configure: --with-crypto=libgcrypt --with-libgcrypt-prefix="$(brew --prefix)" @@ -765,6 +770,10 @@ jobs: install: mbedtls configure: --with-crypto=mbedtls --with-libmbedcrypto-prefix="$(brew --prefix)" cmake: -DCRYPTO_BACKEND=mbedTLS + - name: 'wolfSSL' + install: wolfssl + configure: --with-crypto=wolfssl --with-libwolfssl-prefix="$(brew --prefix)" + cmake: -DCRYPTO_BACKEND=wolfSSL steps: - name: 'install packages' run: brew install ${{ matrix.build == 'autotools' && 'automake libtool' || 'ninja' }} ${{ matrix.crypto.install }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dcdf603..e2d6c352 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,8 +55,8 @@ project(libssh2 C) function(libssh2_dumpvars) # Dump all defined variables with their values message("::group::CMake Variable Dump") get_cmake_property(_vars VARIABLES) - foreach(_var ${_vars}) - message("${_var} = ${${_var}}") + foreach(_var IN ITEMS ${_vars}) + message("${_var} = '${${_var}}'") endforeach() message("::endgroup::") endfunction() @@ -405,9 +405,8 @@ if(CRYPTO_BACKEND STREQUAL "OpenSSL" OR NOT CRYPTO_BACKEND) endif() find_package(ZLIB) - if(ZLIB_FOUND) - list(APPEND LIBSSH2_LIBS ${ZLIB_LIBRARIES}) + list(APPEND LIBSSH2_LIBS ZLIB::ZLIB) endif() endif() endif() @@ -433,10 +432,8 @@ if(CRYPTO_BACKEND STREQUAL "wolfSSL" OR NOT CRYPTO_BACKEND) endif() find_package(ZLIB) - if(ZLIB_FOUND) - list(APPEND CRYPTO_BACKEND_INCLUDE_DIR ${ZLIB_INCLUDE_DIR}) # Public wolfSSL headers require zlib headers - list(APPEND LIBSSH2_LIBS ${ZLIB_LIBRARIES}) + list(APPEND LIBSSH2_LIBS ZLIB::ZLIB) # Public wolfSSL headers require zlib headers endif() endif() endif() diff --git a/cmake/FindLibgcrypt.cmake b/cmake/FindLibgcrypt.cmake index 2ec3cfa2..b4ce1307 100644 --- a/cmake/FindLibgcrypt.cmake +++ b/cmake/FindLibgcrypt.cmake @@ -29,6 +29,7 @@ if(LIBSSH2_USE_PKGCONFIG AND endif() if(LIBGCRYPT_FOUND) + set(Libgcrypt_FOUND TRUE) string(REPLACE ";" " " LIBGCRYPT_CFLAGS "${LIBGCRYPT_CFLAGS}") message(STATUS "Found Libgcrypt (via pkg-config): ${LIBGCRYPT_INCLUDE_DIRS} (found version \"${LIBGCRYPT_VERSION}\")") else() diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index edfcec1f..e1f37c11 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -29,6 +29,7 @@ if(LIBSSH2_USE_PKGCONFIG AND endif() if(MBEDTLS_FOUND) + set(MbedTLS_FOUND TRUE) string(REPLACE ";" " " MBEDTLS_CFLAGS "${MBEDTLS_CFLAGS}") message(STATUS "Found MbedTLS (via pkg-config): ${MBEDTLS_INCLUDE_DIRS} (found version \"${MBEDTLS_VERSION}\")") else() diff --git a/cmake/FindWolfSSL.cmake b/cmake/FindWolfSSL.cmake index 9791b62c..64feac57 100644 --- a/cmake/FindWolfSSL.cmake +++ b/cmake/FindWolfSSL.cmake @@ -29,6 +29,7 @@ if(LIBSSH2_USE_PKGCONFIG AND endif() if(WOLFSSL_FOUND) + set(WolfSSL_FOUND TRUE) string(REPLACE ";" " " WOLFSSL_CFLAGS "${WOLFSSL_CFLAGS}") message(STATUS "Found WolfSSL (via pkg-config): ${WOLFSSL_INCLUDE_DIRS} (found version \"${WOLFSSL_VERSION}\")") else() diff --git a/cmake/libssh2-config.cmake.in b/cmake/libssh2-config.cmake.in index edc86d7c..ccee08b3 100644 --- a/cmake/libssh2-config.cmake.in +++ b/cmake/libssh2-config.cmake.in @@ -1,17 +1,34 @@ # Copyright (C) The libssh2 project and its contributors. # SPDX-License-Identifier: BSD-3-Clause +option(LIBSSH2_USE_PKGCONFIG "Enable pkg-config to detect @PROJECT_NAME@ dependencies. Default: @LIBSSH2_USE_PKGCONFIG@" "@LIBSSH2_USE_PKGCONFIG@") + include(CMakeFindDependencyMacro) list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +set(_libdirs "") +set(_libs "") + if("@CRYPTO_BACKEND@" STREQUAL "OpenSSL") find_dependency(OpenSSL) elseif("@CRYPTO_BACKEND@" STREQUAL "wolfSSL") find_dependency(WolfSSL) + if(WOLFSSL_FOUND) + list(APPEND _libdirs ${WOLFSSL_LIBRARY_DIRS}) + list(APPEND _libs ${WOLFSSL_LIBRARIES}) + endif() elseif("@CRYPTO_BACKEND@" STREQUAL "Libgcrypt") find_dependency(Libgcrypt) + if(LIBGCRYPT_FOUND) + list(APPEND _libdirs ${LIBGCRYPT_LIBRARY_DIRS}) + list(APPEND _libs ${LIBGCRYPT_LIBRARIES}) + endif() elseif("@CRYPTO_BACKEND@" STREQUAL "mbedTLS") find_dependency(MbedTLS) + if(MBEDTLS_FOUND) + list(APPEND _libdirs ${MBEDTLS_LIBRARY_DIRS}) + list(APPEND _libs ${MBEDTLS_LIBRARIES}) + endif() endif() if(@ZLIB_FOUND@) @@ -29,3 +46,18 @@ endif() if(NOT TARGET Libssh2::@LIB_NAME@) add_library(Libssh2::@LIB_NAME@ ALIAS @PROJECT_NAME@::@LIB_SELECTED@) endif() + +foreach(_target IN ITEMS @PROJECT_NAME@::@LIB_SHARED@ @PROJECT_NAME@::@LIB_STATIC@) + if(TARGET "${_target}") + if(_libdirs) + if(CMAKE_VERSION VERSION_LESS 3.13) + set_target_properties("${_target}" PROPERTIES INTERFACE_LINK_DIRECTORIES "${_libdirs}") + else() + target_link_directories("${_target}" INTERFACE ${_libdirs}) + endif() + endif() + if(_libs) + target_link_libraries("${_target}" INTERFACE ${_libs}) + endif() + endif() +endforeach() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ca4c4b5..739bc214 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -326,8 +326,14 @@ install( FILES "${CMAKE_CURRENT_BINARY_DIR}/libssh2.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") -# - +# Consumed variables: +# CRYPTO_BACKEND +# LIB_NAME +# LIB_SELECTED +# LIB_SHARED +# LIB_STATIC +# LIBSSH2_USE_PKGCONFIG +# ZLIB_FOUND include(CMakePackageConfigHelpers) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" diff --git a/tests/cmake/CMakeLists.txt b/tests/cmake/CMakeLists.txt index 2b9bd2b4..53669c0e 100644 --- a/tests/cmake/CMakeLists.txt +++ b/tests/cmake/CMakeLists.txt @@ -21,10 +21,20 @@ if(TEST_INTEGRATION_MODE STREQUAL "find_package") libssh2_FOUND libssh2_VERSION ) - if(${result_var}) - message(STATUS "${result_var}: |${${result_var}}|") - else() - message(FATAL_ERROR "'${result_var}' variable not set by the libssh2 package.") + if(NOT ${result_var}) + message(FATAL_ERROR "'${result_var}' variable expected, but not set by the libssh2 package.") + endif() + endforeach() + # Show variables set by find_package() + get_cmake_property(_vars VARIABLES) + foreach(_var IN ITEMS ${_vars}) + string(TOUPPER "${_var}" _var_upper) + if(_var_upper MATCHES "LIBSSH2") + get_property(_var_type CACHE ${_var} PROPERTY TYPE) + if(_var_type) + set(_var_type ":${_var_type}") + endif() + message("find_package() sets: ${_var}${_var_type} = '${${_var}}'") endif() endforeach() elseif(TEST_INTEGRATION_MODE STREQUAL "add_subdirectory") diff --git a/tests/cmake/test.sh b/tests/cmake/test.sh index b046f90c..b98f90a4 100755 --- a/tests/cmake/test.sh +++ b/tests/cmake/test.sh @@ -27,13 +27,15 @@ if [ "${mode}" = 'all' ] || [ "${mode}" = 'add_subdirectory' ]; then fi if [ "${mode}" = 'all' ] || [ "${mode}" = 'find_package' ]; then - rm -rf bld-libssh2 - cmake ../.. -B bld-libssh2 - cmake --build bld-libssh2 - cmake --install bld-libssh2 --prefix bld-libssh2/_pkg + crypto="${2:-OpenSSL}" + bld="bld-libssh2-${crypto}" + rm -rf "${bld}" + cmake ../.. -B "${bld}" -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DENABLE_ZLIB_COMPRESSION=ON -DCRYPTO_BACKEND="${crypto}" + cmake --build "${bld}" + cmake --install "${bld}" --prefix "${bld}/_pkg" rm -rf bld-find_package cmake -B bld-find_package \ -DTEST_INTEGRATION_MODE=find_package \ - -DCMAKE_PREFIX_PATH="${PWD}/bld-libssh2/_pkg/lib/cmake/libssh2" - cmake --build bld-find_package + -DCMAKE_PREFIX_PATH="${PWD}/${bld}/_pkg/lib/cmake/libssh2" + cmake --build bld-find_package --verbose fi