0

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?

autonomy
  • 1,165
  • 1
  • 12
  • 18
  • 2
    There's a cmake module called 'BundleUtilities' that can help with this. I ended up writing my own install directory "fixer", which is based on `get_bundle_keys()` from the above package, which finds all binary library dependencies. – Peter Dec 17 '14 at 18:16
  • Does [`install(RUNTIME_DEPENDENCY_SET)`](https://cmake.org/cmake/help/latest/command/install.html#runtime-dependency-set) help? – starball Sep 25 '22 at 21:15

3 Answers3

1

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}
)
Pavel K.
  • 983
  • 9
  • 21
0

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.

kdopen
  • 8,032
  • 7
  • 44
  • 52
  • Well, I have no say in how we build the dependencies, I'm just trying to copy the libraries through CMake as part of a 'one-click' build. Perhaps CMake isn't the right tool for that? – autonomy Dec 17 '14 at 16:42
  • CMake is meant for building a single component. It isn't a build management system - that's why there are things like openembedded, and Android's build system. Generally, when you package your component for distribution, your packaging system will have a way to specify dependencies. Then the installation program will do the necessary to ensure those are met before installing yours. It's no different really than auto-tools, or make in that regard. – kdopen Dec 17 '14 at 17:02
0

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
)
lidawei
  • 7
  • 3