diff --git a/CMakeLists.txt b/CMakeLists.txt index dc66cf81..4afe735e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/docs/INSTALL_CMAKE.md b/docs/INSTALL_CMAKE.md index 7aa0708b..fe203068 100644 --- a/docs/INSTALL_CMAKE.md +++ b/docs/INSTALL_CMAKE.md @@ -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=` diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index adf27433..89d2e3bd 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f131db3f..73130472 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 $ $/${CMAKE_INSTALL_INCLUDEDIR}>) +if(BUILD_STATIC_LIBS) + list(APPEND libssh2_export libssh2_static) + add_library(libssh2_static STATIC $) + set_target_properties(libssh2_static PROPERTIES PREFIX "" OUTPUT_NAME "libssh2${STATIC_LIB_SUFFIX}") + + target_include_directories(libssh2_static + PRIVATE "${PROJECT_SOURCE_DIR}/include/" + PUBLIC + $ + $/${CMAKE_INSTALL_INCLUDEDIR}>) +endif() +if(BUILD_SHARED_LIBS) + list(APPEND libssh2_export libssh2_shared) + add_library(libssh2_shared SHARED $) + if(WIN32) + add_library(libssh2_winres OBJECT ${PROJECT_SOURCE_DIR}/win32/libssh2.rc) + set_property(TARGET libssh2_shared APPEND PROPERTY SOURCES $) + 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 + $ + $/${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 $) + 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 $) 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( diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 485b6fa8..d17c8c61 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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 $ @@ -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 $