rbaleksandar
rbaleksandar

Reputation: 9701

How to properly configure FetchContent_Declare for static build of dependencies

In the dependencies subdirectory of my CMake project (Win10, VS2017) I have multiple libraries retrieved and build through the FetchContent_Declare()/FetchContent_MakeAvailable() mechanism. I do have a problem with libcurl though namely some of the options I have set before fetching do not seem to affect the type of build of the library.

CMakeLists.txt (libcurl)

message(STATUS "Fetching dependency curl...")
set(BUILD_SHARED_LIBS OFF CACHE BOOL INTERNAL "Build shared libraries")
set(BUILD_CURL_EXE OFF CACHE BOOL INTERNAL "Build curl EXE")
# Only FILE and HTTP support required so deactivate the rest
set(CURL_ENABLE_SSL OFF CACHE BOOL INTERNAL "Enable SSL support")
set(CURL_DISABLE_FTP ON CACHE BOOL INTERNAL "Disable FTP support")
set(CURL_DISABLE_LDAP ON CACHE BOOL INTERNAL "Disable LDAP support")
set(CURL_DISABLE_POP3 ON CACHE BOOL INTERNAL "Disable POP3 support")
set(CURL_DISABLE_IMAP ON CACHE BOOL INTERNAL "Disable IMAP support")
set(CURL_DISABLE_SMB ON CACHE BOOL INTERNAL "Disable SMB support")
set(CURL_DISABLE_SMTP ON CACHE BOOL INTERNAL "Disable SMTP support")
set(CURL_DISABLE_RTSP ON CACHE BOOL INTERNAL "Disable RTSP support")
set(CURL_DISABLE_MQTT ON CACHE BOOL INTERNAL "Disable MQTT support")
set(CURL_DISABLE_TELNET ON CACHE BOOL INTERNAL "Disable TELNET support")
set(CURL_DISABLE_TFTP ON CACHE BOOL INTERNAL "Disable TFTP support")
set(CURL_DISABLE_DICT ON CACHE BOOL INTERNAL "Disable DICT support")
set(CURL_DISABLE_GOPHER ON CACHE BOOL INTERNAL "Disable GOPHER support")
# ZLIB should be avoided since 1)it's not required for OpenWeather calls and 2)because it cannot
# be integrated with FetchContent
if(WIN32)
    add_definitions("-DCURL_STATICLIB")
    set(ENABLE_UNICODE ON CACHE BOOL INTERNAL "Set to ON to use the Unicode version of the Windows API functions")
endif()
FetchContent_Declare(curl
    GIT_REPOSITORY https://github.com/curl/curl.git
    GIT_TAG origin/master
    GIT_SHALLOW TRUE
    SUBBUILD_DIR "${DEPS_ARTIFACTS}/build/curl/"
    TMP_DIR "${DEPS_ARTIFACTS}/tmp/curl/"
    STAMP_DIR "${DEPS_ARTIFACTS}/stamp/curl/"
    LOG_DIR "${DEPS_ARTIFACTS}/log/curl/"
    BINARY_DIR "${DEPS_ARTIFACTS}/deps_builds/curl"
)
FetchContent_MakeAvailable(curl)

When I run cmake I see the following information:

Fetching dependency curl...
curl version=[7.85.0-DEV]
Could NOT find Perl (missing: PERL_EXECUTABLE) 
Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR) 
Could NOT find LibPSL (missing: LIBPSL_LIBRARY LIBPSL_INCLUDE_DIR) 
Could NOT find LibSSH2 (missing: LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR) 
Enabled features: IPv6 unixsockets AsynchDNS Largefile alt-svc HSTS NTLM unicode
Enabled protocols: FILE HTTP
Enabled SSL backends: 

...

At least the feature selection (only FILE and HTTP protocol support) seems to work. However once everything is built I can clearly see two things in the build directory where my binaries are:

The same issue appears to affect my jsoncpp dependency:

CMakeLists.txt (jsoncpp)

message(STATUS "Fetching dependency jsoncpp...")
set(JSONCPP_WITH_EXAMPLE OFF CACHE BOOL INTERNAL "Compile JsonCpp example")
set(JSONCPP_WITH_TESTS OFF CACHE BOOL INTERNAL "Compile and (for jsoncpp_check) run JsonCpp test executables")
set(JSONCPP_WITH_POST_BUILD_UNITTEST OFF CACHE BOOL INTERNAL "Automatically run unit-tests as a post build step")
set(BUILD_OBJECT_LIBS OFF CACHE BOOL INTERNAL "Build jsoncpp_lib object files.")
set(BUILD_STATIC_LIBS ON CACHE BOOL INTERNAL "Build jsoncpp_lib as a static library.")
set(BUILD_SHARED_LIBS OFF CACHE BOOL INTERNAL "Build jsoncpp_lib as a shared library.")
FetchContent_Declare(jsoncpp
    QUIET
    GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp.git
    GIT_TAG origin/master
    GIT_SHALLOW TRUE
    SUBBUILD_DIR "${DEPS_ARTIFACTS}/build/jsoncpp/"
    TMP_DIR "${DEPS_ARTIFACTS}/tmp/jsoncpp/"
    STAMP_DIR "${DEPS_ARTIFACTS}/stamp/jsoncpp/"
    LOG_DIR "${DEPS_ARTIFACTS}/log/jsoncpp/"
    BINARY_DIR "${DEPS_ARTIFACTS}/deps_builds/jsoncpp"
)
FetchContent_MakeAvailable(jsoncpp)

Again I have as output

even though I have disabled JSONCPP_WITH_TESTS. Funny enough I cannot find any examples being built so I guess that works...

Since this affects multiple of my dependencies I am thinking that I am using FetchContent_Declare() incorrectly although it's not impossible for both to not be compatible with this mechanism (fine example here would be zlib).

I tried using CMAKE_ARGS, which supposedly will be passed onto the underlying ExternalProject_Add() according to the documentation of FetchContent_Declared() but that didn't show even the slightest improvement.

Upvotes: 3

Views: 3154

Answers (1)

sdbbs
sdbbs

Reputation: 5492

I was looking for this myself, and I cannot provide an answer for the actual OP example - but this was my case: I wanted to use CMake FetchContent to get restbed, and to link to it statically.

Basically, what I did, was simply going by the example in https://discourse.cmake.org/t/how-to-statically-link-external-library-by-target-link-libraries/1718/2 - and I added add_library CMake call after the call to FetchContent_MakeAvailable, for a STATIC and IMPORTED library; and if you have IMPORTED library, you must use set_target_properties for to specify the path. So I eventually have in my CMakeLists.txt:

# ...
FetchContent_Declare(
  restbed
  GIT_REPOSITORY https://github.com/Corvusoft/restbed
  GIT_PROGRESS   TRUE
  GIT_TAG        0c99284 # Oct 3, 2022, latest in Jan 2024
)
FetchContent_MakeAvailable(restbed)
add_library(restbed STATIC IMPORTED)
set_target_properties(restbed PROPERTIES IMPORTED_LOCATION ${restbed_BINARY_DIR}/librestbed.a)
# ...
target_link_libraries(${PROJECT_NAME} PUBLIC ... restbed) # a lot more dependencies in my actual case, were dropped
# ...

Not sure if this is the proper understanding of how things should work in CMake with FetchContent, but the above worked for me.

Upvotes: 0

Related Questions