'How to use CMake FetchContent to link OpenSSL?

I don't quite understand how to integrate libraries by FetchContent if they were not found by find_package.

Currently, I have the following code:

# OpenSSL dependency
option(USE_SYSTEM_OPENSSL "Use preinstalled OpenSSL" ON)

# configure OpenSSL
if(USE_SYSTEM_OPENSSL)
    find_package(OpenSSL COMPONENTS Crypto SSL)
endif()
if(NOT USE_SYSTEM_OPENSSL OR NOT OPENSSL_FOUND)
    # get dependencies from net
    include(FetchContent)

    message(STATUS "Not using system OpenSSL, using built-in OpenSSL project instead.")
    FetchContent_Declare(
        OpenSSL
            GIT_REPOSITORY https://github.com/openssl/openssl
            GIT_TAG        master
            USES_TERMINAL_DOWNLOAD TRUE)
    FetchContent_MakeAvailable(OpenSSL)

    # (1) ...

endif()

#(2)
target_link_libraries(target OpenSSL::SSL OpenSSL::Crypto)

What should I write at (1) for (2) to work?



Solution 1:[1]

You cannot use FetchContent_Declare, you must use ExternalProject_Add:

set(OPENSSL_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl-src) # default path by CMake
set(OPENSSL_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl)
set(OPENSSL_INCLUDE_DIR ${OPENSSL_INSTALL_DIR}/include)
set(OPENSSL_CONFIGURE_COMMAND ${OPENSSL_SOURCE_DIR}/config)
ExternalProject_Add(
  OpenSSL
  SOURCE_DIR ${OPENSSL_SOURCE_DIR}
  GIT_REPOSITORY https://github.com/openssl/openssl.git
  GIT_TAG OpenSSL_1_1_1n
  USES_TERMINAL_DOWNLOAD TRUE
  CONFIGURE_COMMAND
    ${OPENSSL_CONFIGURE_COMMAND}
    --prefix=${OPENSSL_INSTALL_DIR}
    --openssldir=${OPENSSL_INSTALL_DIR}
  BUILD_COMMAND make
  TEST_COMMAND ""
  INSTALL_COMMAND make install
  INSTALL_DIR ${OPENSSL_INSTALL_DIR}
)

After doing that, you cannot include or link it with your other targets yet. To do that, you still need to declare the library, as if it was found using find_package, i.e. as if FindOpenSSL.cmake was used:

# We cannot use find_library because ExternalProject_Add() is performed at build time.
# And to please the property INTERFACE_INCLUDE_DIRECTORIES,
# we make the include directory in advance.
file(MAKE_DIRECTORY ${OPENSSL_INCLUDE_DIR})

add_library(OpenSSL::SSL STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::SSL PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libssl.${OPENSSL_LIBRARY_SUFFIX})
set_property(TARGET OpenSSL::SSL PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(OpenSSL::SSL OpenSSL)

add_library(OpenSSL::Crypto STATIC IMPORTED GLOBAL)
set_property(TARGET OpenSSL::Crypto PROPERTY IMPORTED_LOCATION ${OPENSSL_INSTALL_DIR}/lib/libcrypto.${OPENSSL_LIBRARY_SUFFIX})
set_property(TARGET OpenSSL::Crypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${OPENSSL_INCLUDE_DIR})
add_dependencies(OpenSSL::Crypto OpenSSL)

Now you can include the OpenSSL and link with it normally.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Victor Paléologue