I have the following directory structure
.
├── 3rdparty
│ └── liba
│ ├── include
│ │ └── liba.hpp
│ └── lib
│ └── liba.so
├── cmake
│ └── FindLiba.cmake
├── CMakeLists.txt
└── source
├── CMakeLists.txt
└── main.cpp
Here, liba
is a commercial, closed-source third-party library. Unfortunately, the vendor of the library doesn't provide a CMake config for their library, so I wrote my own find module:
# cmake/FindLiba.cmake
# - Try to find liba
# Once done, this will define
#
# Liba_FOUND - system has liba
# Liba_INCLUDE_DIRS - the liba include directories
# Liba_LIBRARIES - link these to use liba
# Include dir
find_path(Liba_INCLUDE_DIR
NAMES liba.hpp
)
# Finally the library itself
find_library(Liba_LIBRARY
NAMES a
)
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set Liba_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(Liba DEFAULT_MSG
Liba_LIBRARY Liba_INCLUDE_DIR)
mark_as_advanced(Liba_INCLUDE_DIR Liba_LIBRARY)
set(Liba_INCLUDE_DIRS ${Liba_INCLUDE_DIR})
set(Liba_LIBRARIES ${Liba_LIBRARY})
if (NOT TARGET Liba::Liba)
add_library(Liba::Liba SHARED IMPORTED)
set_target_properties(Liba::Liba PROPERTIES
IMPORTED_LOCATION ${Liba_LIBRARIES}
INTERFACE_INCLUDE_DIRECTORIES ${Liba_INCLUDE_DIR}
)
endif()
Since main.cpp
makes use of this library, the CMakeLists.txt
in the source
folder looks like this:
find_package(Liba REQUIRED)
add_executable(main main.cpp)
# VERSION 1
target_link_libraries(main PRIVATE Liba::Liba)
# VERSION 2
target_link_libraries(main PRIVATE ${Liba_LIBRARIES})
target_include_directories(main PRIVATE ${Liba_INCLUDE_DIRS})
To build the entire thing I use cmake -Bbuild -H. -DCMAKE_PREFIX_PATH=${PWD}/3rdparty/liba && cmake --build build
.
The problem I have is the following: With version 1, the compiled binary build/source/main
links to ../3rdparty/liba/liba.so
, as can be seen in the output of ldd
:
ldd build/source/main
[...]
../3rdparty/liba/lib/liba.so => not found
[...]
With version 2, main
links against liba.so
without the relative path, but the rpath seems to be set such that it can still be found:
ldd build/source/main
[...]
liba.so => /home/manuel/development/demo/3rdparty/liba/lib/liba.so (0x00007f2a4c3f3000)
[...]
The second version is preferable, as with version 1 the executable can be run only when the current working directory is build
, cmake
, 3rdparty
or source
, otherwise the shared library can't be found. In particular, I can't just run ./build/source/main
after the project is built.
Interestingly enough, this seems only to be an issue because liba
is located within the project subtree. When I move liba
outside of the project directory and adjust the CMAKE_PREFIX_PATH accordingly, it also works fine. But I'd like to keep it where it currently is just so that is is part of the git repository and versioned with the main.cpp
that uses it.
Is there a way to configure the IMPORTED target Liba
in such a way that just adding it to the target_link_libraries
causes CMake to behave the same way as it does when adding ${Liba_LIBRARIES}
instead?