# Copyright (C) Alexander Lamaison # Copyright (C) Viktor Szakats # # Redistribution and use in source and binary forms, # with or without modification, are permitted provided # that the following conditions are met: # # Redistributions of source code must retain the above # copyright notice, this list of conditions and the # following disclaimer. # # 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. # # Neither the name of the copyright holder nor the names # of any other contributors may be used to endorse or # promote products derived from this software without # specific prior written permission. # # 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 OWNER 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. # # SPDX-License-Identifier: BSD-3-Clause set(_libssh2_soversion 1) set(_libssh2_libversion 1.0.1) if(CRYPTO_BACKEND) add_feature_info("Crypto backend" ON "${CRYPTO_BACKEND}") else() message(FATAL_ERROR "No suitable cryptography backend found.") endif() ## Options set(_libssh2_definitions "") option(CLEAR_MEMORY "Enable clearing of memory before being freed" ON) if(NOT CLEAR_MEMORY) list(APPEND _libssh2_definitions "LIBSSH2_NO_CLEAR_MEMORY") endif() option(ENABLE_ZLIB_COMPRESSION "Use zlib for compression" OFF) add_feature_info("Compression" ENABLE_ZLIB_COMPRESSION "using zlib for compression") if(ENABLE_ZLIB_COMPRESSION) find_package(ZLIB REQUIRED) list(APPEND LIBSSH2_LIBS ZLIB::ZLIB) list(APPEND _libssh2_definitions "LIBSSH2_HAVE_ZLIB") endif() list(APPEND LIBSSH2_LIBS ${LIBSSH2_LIBS_SOCKET}) if(MSVC) set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS "$<$:-Zi>") set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS "$<$:-Od>") if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) set_property(DIRECTORY APPEND PROPERTY LINK_OPTIONS "$<$:-DEBUG>") else() set_property(DIRECTORY APPEND PROPERTY LINK_FLAGS "$<$:-DEBUG>") endif() endif() ## Sources include(GNUInstallDirs) libssh2_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") # Get CSOURCES, HHEADERS, EXTRA_DIST variables include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") set(_sources ${CSOURCES} ${HHEADERS}) ## Library definition if(NOT DEFINED IMPORT_LIB_SUFFIX) set(IMPORT_LIB_SUFFIX "") endif() if(NOT DEFINED STATIC_LIB_SUFFIX) set(STATIC_LIB_SUFFIX "") endif() # Ensure that the static library and import library filenames are different, # when building both static and shared library. On Windows, with certain # toolchains (e.g. MSVC) these libraries get the same by default, overwriting # each other. MinGW is not affected. if(WIN32 AND (BUILD_STATIC_LIBS OR BUILD_STATIC_FOR_TESTS) AND BUILD_SHARED_LIBS AND NOT STATIC_LIB_SUFFIX AND NOT IMPORT_LIB_SUFFIX AND CMAKE_STATIC_LIBRARY_SUFFIX STREQUAL CMAKE_IMPORT_LIBRARY_SUFFIX) set(STATIC_LIB_SUFFIX "_static") endif() set(_libssh2_export "") # we want it to be called libssh2 on all platforms if(BUILD_STATIC_LIBS OR BUILD_STATIC_FOR_TESTS) if(NOT BUILD_STATIC_FOR_TESTS) list(APPEND _libssh2_export ${LIB_STATIC}) endif() add_library(${LIB_STATIC} STATIC ${_sources}) add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC}) target_compile_definitions(${LIB_STATIC} PRIVATE ${CRYPTO_BACKEND_DEFINE} ${_libssh2_definitions}) set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_OPTIONS "${LIBSSH2_PICKY_C_FLAGS}") target_link_libraries(${LIB_STATIC} PRIVATE ${LIBSSH2_LIBS}) set_target_properties(${LIB_STATIC} PROPERTIES PREFIX "" OUTPUT_NAME "libssh2" SOVERSION "${_libssh2_soversion}" VERSION "${_libssh2_libversion}" SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" INTERFACE_COMPILE_DEFINITIONS "LIBSSH2_API=") target_include_directories(${LIB_STATIC} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" # to find generated header "${PROJECT_SOURCE_DIR}/include" PUBLIC "$" "$/${CMAKE_INSTALL_INCLUDEDIR}>") # CMake before CMP0099 (CMake 3.17 2020-03-20) did not propagate libdirs to # targets. It expected libs to have an absolute filename. As a workaround, # manually apply dependency libdirs, for CMake consumers without this policy. if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17) cmake_policy(GET CMP0099 _has_CMP0099) # https://cmake.org/cmake/help/latest/policy/CMP0099.html endif() if(NOT _has_CMP0099 AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.13 AND LIBSSH2_LIBS) set(_libdirs "") foreach(_lib IN LISTS LIBSSH2_LIBS) if(TARGET "${_lib}") get_target_property(_libdir "${_lib}" INTERFACE_LINK_DIRECTORIES) if(_libdir) list(APPEND _libdirs "${_libdir}") endif() endif() endforeach() if(_libdirs) target_link_directories(${LIB_STATIC} INTERFACE ${_libdirs}) endif() endif() endif() if(BUILD_SHARED_LIBS) list(APPEND _libssh2_export ${LIB_SHARED}) add_library(${LIB_SHARED} SHARED ${_sources}) add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED}) if(WIN32) set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "libssh2.rc") endif() target_compile_definitions(${LIB_SHARED} PRIVATE ${CRYPTO_BACKEND_DEFINE} ${_libssh2_definitions} ${LIB_SHARED_DEFINITIONS}) set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_OPTIONS "${LIBSSH2_PICKY_C_FLAGS}" "${LIB_SHARED_C_FLAGS}") target_link_libraries(${LIB_SHARED} PRIVATE ${LIBSSH2_LIBS}) set_target_properties(${LIB_SHARED} PROPERTIES PREFIX "" OUTPUT_NAME "libssh2" SOVERSION "${_libssh2_soversion}" VERSION "${_libssh2_libversion}" IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}" POSITION_INDEPENDENT_CODE ON) target_include_directories(${LIB_SHARED} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" # to find generated header "${PROJECT_SOURCE_DIR}/include" PUBLIC "$" "$/${CMAKE_INSTALL_INCLUDEDIR}>") endif() add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED}) add_library(${LIB_NAME} ALIAS ${LIB_SELECTED}) ## Installation if(NOT LIBSSH2_DISABLE_INSTALL) install(FILES "${PROJECT_SOURCE_DIR}/include/libssh2.h" "${PROJECT_SOURCE_DIR}/include/libssh2_publickey.h" "${PROJECT_SOURCE_DIR}/include/libssh2_sftp.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) if(BUILD_STATIC_LIBS) install(TARGETS ${LIB_STATIC} EXPORT "${PROJECT_NAME}-targets" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() if(BUILD_SHARED_LIBS) install(TARGETS ${LIB_SHARED} EXPORT "${PROJECT_NAME}-targets" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) list(APPEND __runtime_dependencies $) endif() set(_runtime_dependencies ${__runtime_dependencies} CACHE INTERNAL "Files that must be in the same directory as the executables at runtime.") # Package config ## During package installation, install libssh2-targets.cmake install(EXPORT "${PROJECT_NAME}-targets" NAMESPACE "${PROJECT_NAME}::" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") ## During build, register directly from build tree # create libssh2-targets.cmake export(TARGETS ${_libssh2_export} NAMESPACE "${PROJECT_NAME}::" FILE "${PROJECT_NAME}-targets.cmake") export(PACKAGE ${PROJECT_NAME}) # register it # Generate libssh2-config.cmake into build tree and install it with dependencies configure_file("${PROJECT_SOURCE_DIR}/cmake/libssh2-config.in.cmake" "${PROJECT_NAME}-config.cmake" @ONLY) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" "${PROJECT_SOURCE_DIR}/cmake/FindLibgcrypt.cmake" "${PROJECT_SOURCE_DIR}/cmake/FindMbedTLS.cmake" "${PROJECT_SOURCE_DIR}/cmake/FindWolfSSL.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") # Calculate variables for pkg-config set(_ldflags "") set(LIBSSH2_PC_LIBS_PRIVATE "") # Avoid getting unnecessary -L options for known system directories. set(_sys_libdirs "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") foreach(_libdir IN LISTS CMAKE_SYSTEM_PREFIX_PATH) if(_libdir MATCHES "/$") string(APPEND _libdir "lib") else() string(APPEND _libdir "/lib") endif() if(IS_DIRECTORY "${_libdir}") list(APPEND _sys_libdirs "${_libdir}") endif() if(DEFINED CMAKE_LIBRARY_ARCHITECTURE) string(APPEND _libdir "/${CMAKE_LIBRARY_ARCHITECTURE}") if(IS_DIRECTORY "${_libdir}") list(APPEND _sys_libdirs "${_libdir}") endif() endif() endforeach() set(_implicit_libs "") if(NOT MINGW AND NOT UNIX) set(_implicit_libs "${CMAKE_C_IMPLICIT_LINK_LIBRARIES}") endif() set(_explicit_libdirs "") set(LIBSSH2_PC_REQUIRES_PRIVATE "") foreach(_lib IN LISTS LIBSSH2_LIBS _implicit_libs) if(TARGET "${_lib}") set(_explicit_libs "") get_target_property(_imported "${_lib}" IMPORTED) if(NOT _imported) # Reading the LOCATION property on non-imported target will error out. # Assume the user will not need this information in the .pc file. continue() endif() get_target_property(_libname "${_lib}" LOCATION) if(_libname) set(_explicit_libs "${_libname}") else() get_target_property(_libs "${_lib}" INTERFACE_LINK_LIBRARIES) if(_libs) set(_explicit_libs "${_libs}") endif() get_target_property(_libdirs "${_lib}" INTERFACE_LINK_DIRECTORIES) if(_libdirs) list(APPEND _explicit_libdirs "${_libdirs}") endif() endif() if(NOT _libname AND NOT _libs AND NOT _libdirs) message(WARNING "Bad lib in library list: ${_lib}") endif() if(_lib STREQUAL OpenSSL::Crypto) set(_modules "libcrypto") elseif(_lib STREQUAL ZLIB::ZLIB) set(_modules "zlib") else() get_target_property(_modules "${_lib}" INTERFACE_LIBSSH2_PC_MODULES) endif() if(_modules) list(APPEND LIBSSH2_PC_REQUIRES_PRIVATE "${_modules}") endif() foreach(_lib IN LISTS _explicit_libs) if(_lib MATCHES "/") # This gets a bit more complex, because we want to specify the # directory separately, and only once per directory if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) cmake_path(GET _lib PARENT_PATH _libdir) cmake_path(GET _lib STEM _libname) else() get_filename_component(_libdir "${_lib}" DIRECTORY) get_filename_component(_libname "${_lib}" NAME_WE) endif() if(_libname MATCHES "^lib") if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) cmake_path(SET _libdir NORMALIZE "${_libdir}") endif() list(FIND _sys_libdirs "${_libdir}" _libdir_index) if(_libdir_index LESS 0) list(APPEND _ldflags "-L${_libdir}") endif() string(REGEX REPLACE "^lib" "" _libname "${_libname}") list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-l${_libname}") else() list(APPEND LIBSSH2_PC_LIBS_PRIVATE "${_lib}") endif() else() list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-l${_lib}") endif() endforeach() elseif(_lib MATCHES "^-") # '-framework ' list(APPEND _ldflags "${_lib}") else() list(APPEND LIBSSH2_PC_LIBS_PRIVATE "-l${_lib}") endif() endforeach() foreach(_libdir IN LISTS _explicit_libdirs) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) cmake_path(SET _libdir NORMALIZE "${_libdir}") endif() list(FIND _sys_libdirs "${_libdir}" _libdir_index) if(_libdir_index LESS 0) list(APPEND _ldflags "-L${_libdir}") endif() endforeach() if(LIBSSH2_PC_REQUIRES_PRIVATE) list(REMOVE_DUPLICATES LIBSSH2_PC_REQUIRES_PRIVATE) string(REPLACE ";" "," LIBSSH2_PC_REQUIRES_PRIVATE "${LIBSSH2_PC_REQUIRES_PRIVATE}") endif() if(LIBSSH2_PC_LIBS_PRIVATE) # Remove duplicates listed next to each other set(_libs "") set(_prev "") foreach(_lib IN LISTS LIBSSH2_PC_LIBS_PRIVATE) if(NOT _prev STREQUAL _lib) list(APPEND _libs "${_lib}") set(_prev "${_lib}") endif() endforeach() set(LIBSSH2_PC_LIBS_PRIVATE "${_libs}") string(REPLACE ";" " " LIBSSH2_PC_LIBS_PRIVATE "${LIBSSH2_PC_LIBS_PRIVATE}") endif() if(_ldflags) list(REMOVE_DUPLICATES _ldflags) string(REPLACE ";" " " _ldflags "${_ldflags}") set(LIBSSH2_PC_LIBS_PRIVATE "${_ldflags} ${LIBSSH2_PC_LIBS_PRIVATE}") string(STRIP "${LIBSSH2_PC_LIBS_PRIVATE}" LIBSSH2_PC_LIBS_PRIVATE) endif() # Merge pkg-config private fields into public ones when static-only if(BUILD_SHARED_LIBS) set(LIBSSH2_PC_REQUIRES "") set(LIBSSH2_PC_LIBS "") else() set(LIBSSH2_PC_REQUIRES "${LIBSSH2_PC_REQUIRES_PRIVATE}") set(LIBSSH2_PC_LIBS "${LIBSSH2_PC_LIBS_PRIVATE}") endif() set(prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix "\${prefix}") if(IS_ABSOLUTE ${CMAKE_INSTALL_INCLUDEDIR}) set(includedir "${CMAKE_INSTALL_INCLUDEDIR}") else() set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") endif() if(IS_ABSOLUTE ${CMAKE_INSTALL_LIBDIR}) set(libdir "${CMAKE_INSTALL_LIBDIR}") else() set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") endif() # Generate a pkg-config file for client projects not using CMake. # Consumed variables: # exec_prefix # includedir # LIBSSH2_PC_LIBS # LIBSSH2_PC_LIBS_PRIVATE # LIBSSH2_PC_REQUIRES # LIBSSH2_PC_REQUIRES_PRIVATE # LIBSSH2_VERSION # libdir # prefix configure_file("${PROJECT_SOURCE_DIR}/libssh2.pc.in" "libssh2.pc" @ONLY) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/libssh2.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") # Consumed variables: # CMAKE_MINIMUM_REQUIRED_VERSION # 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" VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}" COMPATIBILITY SameMajorVersion) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") endif()