autonomy
autonomy

Reputation: 1215

How can I distribute/install 3rd-party libraries with CMake?

I'm building and distributing an executable which relies on several 3rd-party libraries, most of which are built outside of CMake's buildsystem (though, if it helps, I can add and build them as custom targets in my CMake file).

Here's how I include the libs:

target_link_libraries(MyApp
                      Lib1_x64
                      Lib2_x64
                      etc.}

I'd like to include a CMake directive which installs my executable along with its dependencies. Is there a better way to do this other than calling the install command for every single dependency?

install(DIRECTORY ${DEV_PATH}/Release/ DESTINATION lib FILES_MATCHING PATTERN "libLib1*" PATTERN "*.svn" EXCLUDE PATTERN "*-obj" EXCLUDE)

Is there maybe a way to do this via the add_library command?

Upvotes: 0

Views: 4497

Answers (3)

Pavel K.
Pavel K.

Reputation: 1093

This is possible in nowadays with CMake 3.21, which allows you to get a set of dependent libraries via parameter RUNTIME_DEPENDENCY_SET in the install command. Keep in mind, that it will gather all dependent libraries including system, you will need to filter them.

cmake_minimum_required(VERSION 3.21)

# Install your app or library
install(
    TARGETS ${PROJECT_NAME}
    RUNTIME_DEPENDENCY_SET runtime_deps
)

# Install third-party libraries (exclude system libraries Windows/Unix)
LIST(APPEND pre_exclude_regexes "api-ms-.*")
LIST(APPEND pre_exclude_regexes "ext-ms-.*")
LIST(APPEND post_exclude_regexes ".*WINDOWS[\\/]system32.*")
LIST(APPEND post_exclude_regexes "^/lib" "^/usr" "^/bin")
install(RUNTIME_DEPENDENCY_SET runtime_deps
    PRE_EXCLUDE_REGEXES ${pre_exclude_regexes}
    POST_EXCLUDE_REGEXES ${post_exclude_regexes}
)

Upvotes: 1

lidawei
lidawei

Reputation: 7

I am also finding a way to deal this problem today.

and I found :

include(ExternalProject)
ExternalProject_Add()

does it!

here is my sample CMakeLists.txt:

cmake_minimum_required(VERSION 3.13)
project(third-party-build)
include(ExternalProject)
ExternalProject_Add(libuuid
    PREFIX libuuid-prefix
    # DOWNLOAD_DIR libuuid-download
    # SOURCE_DIR libuuid-source
    # DOWNLOAD_COMMAND wget xxx.com/xxx.tar.gz && tar zxf xxx.tar.gz
    DOWNLOAD_COMMAND tar zxf ${PROJECT_SOURCE_DIR}/libuuid-1.0.3.tar.gz
    CONFIGURE_COMMAND <DOWNLOAD_DIR>/libuuid-1.0.3/configure
    BUILD_COMMAND ${MAKE}
    BUILD_IN_SOURCE 1
    INSTALL_COMMAND mkdir -p ${PROJECT_SOURCE_DIR}/lib/ && cp <SOURCE_DIR>/.libs/libuuid.a <SOURCE_DIR>/.libs/libuuid.so <SOURCE_DIR>/.libs/libuuid.so.1 <SOURCE_DIR>/.libs/libuuid.so.1.0.0 ${PROJECT_SOURCE_DIR}/lib/
    LOG_DOWNLOAD 1
    LOG_BUILD 1
    # LOG_INSTALL 1
)

Upvotes: 0

kdopen
kdopen

Reputation: 8215

Sorry, no. The add_library command serves the purpose of creating a target in your makefile to build a library. target_link_dependencies just passes the various -L ... -l ... flags to the compiler for a target.

The normal CMake approach is to test for the presence of other libraries or executables on which yours depends, and fail if they are not available.

Handling dependencies is normally left to a package manage such as apt, rpm, etc. It is unwise to build your dependent components as part of your own makefile for a number of reasons:

  • Your clients might want to use a slightly different version
  • Any change in how those dependencies build requires you to modify your own build scripts
  • Your program may work with multiple versions of a dependency, all of which build in different ways.

As someone who uses CMake to build large parts of an entire embedded Linux distribution (see Open webOS), I advise you to keep your scripts focused very tightly on building just one thing.

Upvotes: 0

Related Questions