1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-07-31 00:03:08 +03:00

cmake: allow building static + shared libs in a single pass

- `BUILD_SHARED_LIBS=ON` no longer disables building static lib.

  When set, we build the static lib with PIC enabled.

  For shared lib only, set `BUILD_STATIC_LIBS=OFF`. For static lib
  without PIC, leave this option disabled.

- new setting: `BUILD_STATIC_LIBS`. `ON` by default.

  Force-enabled when building examples or tests (we build those in
  static mode always.)

- fix to exclude Windows Resource from the static lib.

- fix to not overwrite static lib with shared implib on Windows
  platforms using identical suffix for them (MSVS). By using
  `libssh2_imp<.ext>` implib filename.

- add support for `STATIC_LIB_SUFFIX` setting to set an optional suffix
  (e.g. `_static`) for the static lib. (experimental, not documented).
  Overrides the above when set.

- fix to set `dllexport` when building shared lib.

- set `TrackFileAccess=false` for MSVS.

  For faster builds, shorter verbose logs.

- tests: new test linking against shared libssh2: `test_warmup_shared`

- tests: simplify 'runner' lib by merging 3 libs into a single one.

- tests: drop hack from `test_keyboard_interactive_auth_info_request`
  build.

  We no longer need to compile `src/misc.c` because we always link
  libssh2 statically.

- tests: limit `FIXTURE_WORKDIR=` to the `runner` target.

TL;DR: Default behavior unchanged: static (no-PIC), no shared.
       Enabling shared unchanged, but now also builds a static (PIC)
       lib by default.

Based-on: b60dca8b64 #547 by berney on github
Fixes: #547
Fixes: #675
Closes: #863
This commit is contained in:
Viktor Szakats
2023-03-22 02:47:58 +00:00
parent b0cb0b1965
commit 4e2580628d
5 changed files with 122 additions and 55 deletions

View File

@ -44,6 +44,7 @@ project(libssh2 C)
set(PROJECT_URL "https://www.libssh2.org/")
set(PROJECT_DESCRIPTION "The SSH library")
option(BUILD_STATIC_LIBS "Build Static Libraries" ON)
option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
# Parse version
@ -77,6 +78,10 @@ install(
FILES docs/AUTHORS COPYING docs/HACKING README RELEASE-NOTES NEWS
DESTINATION ${CMAKE_INSTALL_DOCDIR})
if(MSVC)
set(CMAKE_VS_GLOBALS "TrackFileAccess=false") # faster builds
endif()
include(max_warnings)
include(FeatureSummary)
@ -107,12 +112,20 @@ if(BUILD_TESTING)
add_subdirectory(tests)
endif()
if(NOT BUILD_STATIC_LIBS AND (NOT BUILD_SHARED_LIBS OR BUILD_EXAMPLES OR BUILD_TESTING))
set(BUILD_STATIC_LIBS ON)
endif()
option(LINT "Check style while building" OFF)
if(LINT)
add_custom_target(lint ALL
./ci/checksrc.sh
WORKING_DIRECTORY ${libssh2_SOURCE_DIR})
add_dependencies(libssh2 lint)
if(BUILD_STATIC_LIBS)
add_dependencies(libssh2_static lint)
else()
add_dependencies(libssh2_shared lint)
endif()
endif()
add_subdirectory(docs)

View File

@ -47,11 +47,17 @@ The following options are available:
Enables running the source code linter when building. Can be `ON` or `OFF`.
* `BUILD_STATIC_LIBS=ON`
Determines whether to build a libssh2 static library.
Can be `ON` or `OFF`.
* `BUILD_SHARED_LIBS=OFF`
Determines whether libssh2 is built as a static library or as a
shared library (.dll/.so). Can be `ON` or `OFF`.
Determines whether to build a libssh2 shared library (.dll/.so).
Can be `ON` or `OFF`.
If enabled, the optional static lib is also built with PIC enabled.
* `CRYPTO_BACKEND=`

View File

@ -68,7 +68,7 @@ foreach(example ${EXAMPLES})
list(APPEND EXAMPLE_TARGETS example-${example})
# to find generated header
target_include_directories(example-${example} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(example-${example} libssh2 ${LIBRARIES})
target_link_libraries(example-${example} libssh2_static ${LIBRARIES})
endforeach()
add_target_to_copy_dependencies(
TARGET copy_example_dependencies

View File

@ -227,22 +227,52 @@ set(SOURCES
userauth.h
version.c)
if(WIN32 AND BUILD_SHARED_LIBS)
list(APPEND SOURCES ${PROJECT_SOURCE_DIR}/win32/libssh2.rc)
endif()
add_library(libssh2 ${SOURCES})
# we want it to be called libssh2 on all platforms
set_target_properties(libssh2 PROPERTIES PREFIX "")
set_target_properties(libssh2 PROPERTIES IMPORT_PREFIX "")
target_compile_definitions(libssh2 PRIVATE ${PRIVATE_COMPILE_DEFINITIONS})
target_include_directories(libssh2
add_library(libssh2_object OBJECT ${SOURCES})
target_compile_definitions(libssh2_object PRIVATE ${PRIVATE_COMPILE_DEFINITIONS})
target_include_directories(libssh2_object
PRIVATE "${PROJECT_SOURCE_DIR}/include/" ${PRIVATE_INCLUDE_DIRECTORIES}
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>)
if(BUILD_STATIC_LIBS)
list(APPEND libssh2_export libssh2_static)
add_library(libssh2_static STATIC $<TARGET_OBJECTS:libssh2_object>)
set_target_properties(libssh2_static PROPERTIES PREFIX "" OUTPUT_NAME "libssh2${STATIC_LIB_SUFFIX}")
target_include_directories(libssh2_static
PRIVATE "${PROJECT_SOURCE_DIR}/include/"
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>)
endif()
if(BUILD_SHARED_LIBS)
list(APPEND libssh2_export libssh2_shared)
add_library(libssh2_shared SHARED $<TARGET_OBJECTS:libssh2_object>)
if(WIN32)
add_library(libssh2_winres OBJECT ${PROJECT_SOURCE_DIR}/win32/libssh2.rc)
set_property(TARGET libssh2_shared APPEND PROPERTY SOURCES $<TARGET_OBJECTS:libssh2_winres>)
endif()
set_target_properties(libssh2_shared PROPERTIES PREFIX "" IMPORT_PREFIX "" OUTPUT_NAME "libssh2")
if(WIN32 AND BUILD_STATIC_LIBS AND NOT STATIC_LIB_SUFFIX AND
CMAKE_IMPORT_LIBRARY_SUFFIX STREQUAL CMAKE_STATIC_LIBRARY_SUFFIX)
# Extra suffix to avoid filename conflict with the static lib.
set_target_properties(libssh2_shared PROPERTIES IMPORT_SUFFIX "_imp${CMAKE_IMPORT_LIBRARY_SUFFIX}")
endif()
set_target_properties(libssh2_object PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(WIN32)
target_compile_definitions(libssh2_object PRIVATE libssh2_EXPORTS)
endif()
target_include_directories(libssh2_shared
PRIVATE "${PROJECT_SOURCE_DIR}/include/"
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>)
endif()
## Options
option(CLEAR_MEMORY "Enable clearing of memory before being freed" ON)
@ -250,8 +280,11 @@ if(NOT CLEAR_MEMORY)
add_definitions(-DLIBSSH2_NO_CLEAR_MEMORY)
endif()
add_feature_info("Static library" BUILD_STATIC_LIBS
"creating libssh2 static library")
add_feature_info("Shared library" BUILD_SHARED_LIBS
"creating libssh2 as a shared library (.so/.dll)")
"creating libssh2 shared library (.so/.dll)")
option(ENABLE_ZLIB_COMPRESSION "Use zlib for compression")
add_feature_info(Compression ENABLE_ZLIB_COMPRESSION
@ -259,24 +292,24 @@ add_feature_info(Compression ENABLE_ZLIB_COMPRESSION
if(ENABLE_ZLIB_COMPRESSION)
find_package(ZLIB REQUIRED)
target_include_directories(libssh2 PRIVATE ${ZLIB_INCLUDE_DIRS})
target_include_directories(libssh2_object PRIVATE ${ZLIB_INCLUDE_DIRS})
list(APPEND LIBRARIES ${ZLIB_LIBRARIES})
list(APPEND PC_REQUIRES_PRIVATE zlib)
if(ZLIB_FOUND)
target_compile_definitions(libssh2 PRIVATE LIBSSH2_HAVE_ZLIB=1)
target_compile_definitions(libssh2_object PRIVATE LIBSSH2_HAVE_ZLIB=1)
endif()
endif()
option(ENABLE_CRYPT_NONE "Permit \"none\" cipher -- NOT RECOMMENDED")
add_feature_info("\"none\" cipher" ENABLE_CRYPT_NONE "")
if(ENABLE_CRYPT_NONE)
target_compile_definitions(libssh2 PRIVATE LIBSSH2_CRYPT_NONE=1)
target_compile_definitions(libssh2_object PRIVATE LIBSSH2_CRYPT_NONE=1)
endif()
option(ENABLE_MAC_NONE "Permit \"none\" MAC -- NOT RECOMMMENDED")
add_feature_info("\"none\" MAC" ENABLE_MAC_NONE "")
if(ENABLE_MAC_NONE)
target_compile_definitions(libssh2 PRIVATE LIBSSH2_MAC_NONE=1)
target_compile_definitions(libssh2_object PRIVATE LIBSSH2_MAC_NONE=1)
endif()
option(ENABLE_GEX_NEW
@ -284,7 +317,7 @@ option(ENABLE_GEX_NEW
add_feature_info("diffie-hellman-group-exchange-sha1" ENABLE_GEX_NEW
"\"new\" diffie-hellman-group-exchange-sha1 method")
if(ENABLE_GEX_NEW)
target_compile_definitions(libssh2 PRIVATE LIBSSH2_DH_GEX_NEW=1)
target_compile_definitions(libssh2_object PRIVATE LIBSSH2_DH_GEX_NEW=1)
endif()
# Enable debugging logging by default if the user configured a debug build
@ -298,7 +331,7 @@ option(ENABLE_DEBUG_LOGGING "log execution with debug trace"
add_feature_info(Logging ENABLE_DEBUG_LOGGING
"Logging of execution with debug trace")
if(ENABLE_DEBUG_LOGGING)
target_compile_definitions(libssh2 PRIVATE LIBSSH2DEBUG)
target_compile_definitions(libssh2_object PRIVATE LIBSSH2DEBUG)
endif()
## Platform checks
@ -383,14 +416,19 @@ configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/libssh2_config_cmake.h.in
${CMAKE_CURRENT_BINARY_DIR}/libssh2_config.h)
# to find generated header
target_include_directories(libssh2 PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(libssh2_object PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
if(MSVC)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi /Od")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG")
endif()
target_link_libraries(libssh2 PRIVATE ${LIBRARIES})
if(BUILD_STATIC_LIBS)
target_link_libraries(libssh2_static PRIVATE ${LIBRARIES})
endif()
if(BUILD_SHARED_LIBS)
target_link_libraries(libssh2_shared PRIVATE ${LIBRARIES})
endif()
## Installation
@ -400,14 +438,21 @@ install(FILES
${PROJECT_SOURCE_DIR}/include/libssh2_sftp.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS libssh2
EXPORT Libssh2Config
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(BUILD_STATIC_LIBS)
install(TARGETS libssh2_static
EXPORT Libssh2Config
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(BUILD_SHARED_LIBS)
list(APPEND _RUNTIME_DEPENDENCIES $<TARGET_FILE:libssh2>)
install(TARGETS libssh2_shared
EXPORT Libssh2Config
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
list(APPEND _RUNTIME_DEPENDENCIES $<TARGET_FILE:libssh2_shared>)
endif()
set(RUNTIME_DEPENDENCIES ${_RUNTIME_DEPENDENCIES} CACHE INTERNAL
@ -422,7 +467,7 @@ install(EXPORT Libssh2Config
## During build, register directly from build tree
# create Libssh2Config.cmake
export(TARGETS libssh2 NAMESPACE Libssh2:: FILE Libssh2Config.cmake)
export(TARGETS ${libssh2_export} NAMESPACE Libssh2:: FILE Libssh2Config.cmake)
export(PACKAGE Libssh2) # register it
## Export a .pc file for client projects not using CMaek
@ -439,9 +484,18 @@ install(
## Versioning
set_target_properties(libssh2 PROPERTIES
SOVERSION 1
VERSION 1.0.1)
set(LIBSSH2_SOVERSION 1)
set(LIBSSH2_VERSION 1.0.1)
if(BUILD_STATIC_LIBS)
set_target_properties(libssh2_static PROPERTIES
SOVERSION ${LIBSSH2_SOVERSION}
VERSION ${LIBSSH2_VERSION})
endif()
if(BUILD_SHARED_LIBS)
set_target_properties(libssh2_shared PROPERTIES
SOVERSION ${LIBSSH2_SOVERSION}
VERSION ${LIBSSH2_VERSION})
endif()
include(CMakePackageConfigHelpers)
write_basic_package_version_file(

View File

@ -169,24 +169,23 @@ if(NOT CRYPTO_BACKEND STREQUAL "mbedTLS")
)
endif()
add_library(openssh_fixture STATIC openssh_fixture.h openssh_fixture.c)
target_link_libraries(openssh_fixture ${LIBRARIES})
target_include_directories(openssh_fixture PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" ../include)
add_library(runner STATIC runner.h runner.c openssh_fixture.h openssh_fixture.c session_fixture.h session_fixture.c)
target_include_directories(runner PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" ../include)
target_compile_definitions(runner PRIVATE FIXTURE_WORKDIR="${CMAKE_CURRENT_SOURCE_DIR}")
add_library(session_fixture STATIC session_fixture.h session_fixture.c)
target_link_libraries(session_fixture ${LIBRARIES} openssh_fixture libssh2)
target_include_directories(session_fixture PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
add_library(runner STATIC runner.h runner.c)
target_link_libraries(runner session_fixture)
target_include_directories(runner PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
# test building against shared libssh2 lib
if(BUILD_SHARED_LIBS)
set(test warmup) # any test will do
add_executable(test_${test}_shared test_${test}.c)
target_include_directories(test_${test}_shared PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
target_link_libraries(test_${test}_shared runner libssh2_shared ${LIBRARIES})
endif()
foreach(test ${TESTS})
add_executable(test_${test} test_${test}.c)
target_link_libraries(test_${test} libssh2 runner ${LIBRARIES})
target_include_directories(test_${test} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
list(APPEND TEST_TARGETS test_${test})
add_definitions(-DFIXTURE_WORKDIR="${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(test_${test} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
target_link_libraries(test_${test} runner libssh2_static ${LIBRARIES})
add_test(
NAME test_${test} COMMAND $<TARGET_FILE:test_${test}>
@ -229,12 +228,7 @@ foreach(test ${TESTS})
set_tests_properties(test_${test} PROPERTIES ENVIRONMENT "FIXTURE_TEST_CRYPT=${test}")
endforeach()
if(WIN32 AND BUILD_SHARED_LIBS)
# Workaround for platforms not exporting internal functions from libssh2 shared lib
add_executable(test_keyboard_interactive_auth_info_request test_keyboard_interactive_auth_info_request.c ../src/userauth_kbd_packet.c ../src/misc.c)
else()
add_executable(test_keyboard_interactive_auth_info_request test_keyboard_interactive_auth_info_request.c ../src/userauth_kbd_packet.c)
endif()
add_executable(test_keyboard_interactive_auth_info_request test_keyboard_interactive_auth_info_request.c ../src/userauth_kbd_packet.c)
target_compile_definitions(test_keyboard_interactive_auth_info_request PRIVATE "${CRYPTO_BACKEND_DEFINE}")
target_include_directories(test_keyboard_interactive_auth_info_request PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" "../src/" "${CRYPTO_BACKEND_INCLUDE_DIR}")
find_program(GCOV_PATH gcov)
@ -245,9 +239,9 @@ endif()
if(CMAKE_COMPILER_IS_GNUCC AND GCOV_PATH)
target_compile_options(test_keyboard_interactive_auth_info_request BEFORE PRIVATE
${TGT_OPTIONS})
target_link_libraries(test_keyboard_interactive_auth_info_request ${LIBRARIES} libssh2 gcov)
target_link_libraries(test_keyboard_interactive_auth_info_request ${LIBRARIES} libssh2_static gcov)
else()
target_link_libraries(test_keyboard_interactive_auth_info_request ${LIBRARIES} libssh2)
target_link_libraries(test_keyboard_interactive_auth_info_request ${LIBRARIES} libssh2_static)
endif()
add_test(
NAME test_keyboard_interactive_auth_info_request COMMAND $<TARGET_FILE:test_keyboard_interactive_auth_info_request>