CMake Visibility for Imported Libraries - c++

I have an imported library that I am trying to link using CMake. However, the library always shows up empty (or not found). I know that imported libraries have different visibility rules (according to this thread) than the standard libraries, but no matter what I try the library always ends up missing. To start, here's my folder structure:
Root
├── build
├── cmake
├── src
│ ├── external
│ │ ├── openvdb
│ │ │ ├── openvdb
│ │ │ ├── cmake
│ │ │ ├── CMakeLists.txt
│ │ ├── tbb
│ │ ├── zlib
│ │ ├── CMakeLists.txt
│ ├── CMakeLists.txt
├── CMakeLists.txt
In my Root CMakeLists.txt file I add the libraries called TBB_LIBS and TBBMALLOC_LIBS like this:
cmake_minimum_required(VERSION 3.2.2 FATAL_ERROR)
include(ExternalProject)
project(openVDBBuild)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (WIN32)
set(CMAKE_CXX_FLAGS "-bigobj /EHsc")
endif ()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
if(NOT CMAKE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX debug)
endif()
if(NOT CMAKE_RELEASE_POSTFIX)
set(CMAKE_RELEASE_POSTFIX release)
endif()
set(BUILD_VARIANTS "release debug")
set(TBB_PREFIX "tbb")
set(TBB_LIBS_DIR "${CMAKE_SOURCE_DIR}/src/external/tbb/build/${TBB_PREFIX}_")
set(TBB_ROOT ${CMAKE_SOURCE_DIR}/src/external/tbb)
set(TBB_INCLUDE_DIR ${TBB_ROOT}/include)
#********** Here I create the library and add the Global Flag ***********
add_library(TBBMALLOC_LIBS SHARED IMPORTED GLOBAL)
add_library(TBB_LIBS SHARED IMPORTED GLOBAL)
if (WIN32)
#********** Here I set different paths for debug and release versions of the library ***********
set_property(TARGET TBBMALLOC_LIBS PROPERTY IMPORTED_LOCATION_RELEASE ${CMAKE_BINARY_DIR}/lib/tbbmalloc.dll )
set_property(TARGET TBBMALLOC_LIBS PROPERTY IMPORTED_LOCATION_DEBUG ${CMAKE_BINARY_DIR}/lib/tbbmalloc_${CMAKE_DEBUG_POSTFIX}.dll )
set_property(TARGET TBB_LIBS PROPERTY IMPORTED_LOCATION_RELEASE ${CMAKE_BINARY_DIR}/lib/tbb.dll )
set_property(TARGET TBB_LIBS PROPERTY IMPORTED_LOCATION_DEBUG ${CMAKE_BINARY_DIR}/lib/tbb_${CMAKE_DEBUG_POSTFIX}.dll )
add_custom_command(
TARGET ProjectTbbExternal
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "$<$<CONFIG:debug>:${TBB_LIBS_DIR}${CMAKE_DEBUG_POSTFIX}/tbb_${CMAKE_DEBUG_POSTFIX}.dll>$<$<CONFIG:release>:${TBB_LIBS_DIR}${CMAKE_RELEASE_POSTFIX}/tbb.dll>" "${CMAKE_BINARY_DIR}/lib"
COMMAND ${CMAKE_COMMAND} -E copy "$<$<CONFIG:debug>:${TBB_LIBS_DIR}${CMAKE_DEBUG_POSTFIX}/tbbmalloc_${CMAKE_DEBUG_POSTFIX}.dll>$<$<CONFIG:release>:${TBB_LIBS_DIR}${CMAKE_RELEASE_POSTFIX}/tbbmalloc.dll>" "${CMAKE_BINARY_DIR}/lib"
COMMAND ${CMAKE_COMMAND} -E copy "$<$<CONFIG:debug>:${TBB_LIBS_DIR}${CMAKE_DEBUG_POSTFIX}/tbbmalloc_proxy_${CMAKE_DEBUG_POSTFIX}.dll>$<$<CONFIG:release>:${TBB_LIBS_DIR}${CMAKE_RELEASE_POSTFIX}/tbbmalloc_proxy.dll>" "${CMAKE_BINARY_DIR}/lib"
)
endif ()
add_subdirectory("src")
Now, down inside the CMakeLists.txt in the src/external/openvdb directory I try to link the libraries like this:
project(OpenVDBCore)
#define OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER 4
#define OPENVDB_LIBRARY_MINOR_VERSION_NUMBER 0
#define OPENVDB_LIBRARY_PATCH_VERSION_NUMBER 0
#*********** I'm going to omit some lines here since **********
#*********** they're standard for the OpenVDB build ***********
SET_SOURCE_FILES_PROPERTIES ( ${OPENVDB_LIBRARY_SOURCE_FILES}
PROPERTIES
COMPILE_FLAGS "-DOPENVDB_PRIVATE -DOPENVDB_USE_BLOSC ${OPENVDB_USE_GLFW_FLAG}"
)
ADD_LIBRARY ( openvdb_static STATIC ${OPENVDB_LIBRARY_SOURCE_FILES} )
ADD_LIBRARY ( openvdb_shared SHARED ${OPENVDB_LIBRARY_SOURCE_FILES} )
TARGET_LINK_LIBRARIES ( openvdb_static
zlib
TBB_LIBS
TBBMALLOC_LIBS
)
TARGET_LINK_LIBRARIES ( openvdb_shared
zlib
TBB_LIBS
TBBMALLOC_LIBS
)
MESSAGE(STATUS "TBB_LIBS library location is ${TBB_LIBS}")
MESSAGE(STATUS "TBBMALLOC_LIBS library location is ${TBBMALLOC_LIBS}")
You can see that I put a status message in CMake to see what the ${TBB_LIBS} and ${TBBMALLOC_LIBS} variables are... but that part is always empty. Accordingly, the openvdb_shared and openvdb_static project files that get generated by CMake also do not link the libraries correctly (since those libraries are unknown). Does anyone know why this occurs (and how to fix it)?

Related

CMake header files can't be found (fatal error: file not found)

I'm working on a CMake project but Im getting this error and I don't understand why. Im using VS Code on MacOS and I'm using Clang as the compiler.
Here is the structure of my folder project:
tree
.
├─ app
│ ├── CMakeLists.txt
│ └── src
│ └── main.cpp
├─ CMakeLists.txt
├─ build
└─ engine
├── CMakeLists.txt
├── external
├── include
│ └── project_engine
│ └── engine.h
└── src
└── engine.cpp
The root CMakeLists.txt is
cmake_minimum_required(VERSION 3.5)
project(vulkanEngine_developement_env VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_subdirectory(app)
add_subdirectory(engine)
The CMakeLists.txt in the app folder:
cmake_minimum_required(VERSION 3.5)
project(vulkanEngine VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} vulkanEngine_engine)
target_include_directories(${PROJECT_NAME} PRIVATE vulkanEngine_engine)
and the one in engine is:
cmake_minimum_required(VERSION 3.5)
project(vulkanEngine_engine VERSION 0.0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_library(${PROJECT_NAME} src/engine.cpp)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
)
target_link_libraries(${PROJECT_NAME}
PUBLIC
PRIVATE
)
Whenever I try to include the header file in both cpp files I get the error "file not found", I tried using both
#include <project_engine/engine.h>
and
#include "project_engine/engine.h"
I also tried linking the path to the header in the vs code include path setting but it didn't work, I added include_directories to the engine CMake file but that didn't work either.

CMake warning: CMake Targets may link only to libraries. CMake is dropping the item [duplicate]

This question already has answers here:
Understanding "requests linking to directory" cmake warning
(1 answer)
CMake link to external library
(6 answers)
Closed 10 months ago.
I am making an anpr algorithm that requires tesseract to decode the image to text. When running cmake .. inside my build dir, I get a warning saying:
┌──(user㉿MacBookArch)-[~/dev/anpr/build]
└─$ cmake ..
-- Configuring done
CMake Warning at CMakeLists.txt:15 (target_link_libraries):
Target "main" requests linking to directory
"/home/user/dev/anpr/build/libs/leptonica". Targets may link only to
libraries. CMake is dropping the item.
CMake Warning at CMakeLists.txt:16 (target_link_libraries):
Target "main" requests linking to directory
"/home/user/dev/anpr/build/libs/tesseract". Targets may link only to
libraries. CMake is dropping the item.
-- Generating done
-- Build files have been written to: /home/user/dev/anpr/build
This leads me into the thoughts that I have made something wrong. I have copied the repos for leptonica and tesseract into the libs directory for portability.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.2.2)
project( ANPR )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include )
include_directories(${PROJECT_SOURCE_DIR}/libs/tesseract/include)
include_directories(${PROJECT_SOURCE_DIR}/libs/leptonica/include)
link_directories(${PROJECT_SOURCE_DIR}/libs/tesseract)
link_directories(${PROJECT_SOURCE_DIR}/libs/leptonica)
add_executable( main src/main.cpp )
target_link_libraries( main ${OpenCV_LIBS} )
target_link_libraries( main ${CMAKE_CURRENT_BINARY_DIR}/libs/leptonica)
target_link_libraries( main ${CMAKE_CURRENT_BINARY_DIR}/libs/tesseract)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/samples/001.jpg
${CMAKE_CURRENT_BINARY_DIR}/samples/001.jpg
COPYONLY
)
and this is my project structure:
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── LeptonicaTargets.cmake
│ ├── libs
│ ├── main
│ ├── Makefile
│ └── samples
├── CMakeLists.txt
...
├── include
│ └── main.hpp
├── libs
│ ├── leptonica
│ └── tesseract
...
├── samples
│ └── 001.jpg
└── src
└── main.cpp
The contents of the build dir is auto generated with cmake.
make command inside the build dir goes fine without errors even after make clean:
┌──(user㉿MacBookArch)-[~/dev/anpr/build]
└─$ make
[ 50%] Building CXX object CMakeFiles/main.dir/src/main.cpp.o
[100%] Linking CXX executable main
[100%] Built target main
How can I resolve this warning? I am open to all improvements, thank you!

Build zLib with CMake

I'm trying to build Zlib and quazip automatic with the rest of my project. I want to do it in a similar way as I add googletest to my project.
zLib and Quazip shall be linked static to my App.
I want to to this because of CI/ CD reasons and if somebody else wants to build the project he do not have to worry about those dependencies (especially under windows)...
Download it at configure time with CMake ExternalProject_Add
add it on target level
My structure is like the following:
project/
├── CMakelists.txt (1)
├── sources/
│ ├── APP/
│ │ ├── CMakeLists.txt (2)
│ │ ├── thirdparty/
│ │ │ ├── CMakeLists.txt (3)
│ │ │ ├── zlib
│ │ │ │ ├── CMakeLists.txt.in
│ │ │ ├── quazip
│ │ │ │ ├── CMakeLists.txt.in
│ │ │ │ ├── CMakeListsBuild.txt.in
Thats complicated enough but let me show you what I do where...
(1) CMakeLists.txt
Noting special just adding all the packages together like APP
(2) CMakeLists.txt
cmake_minimum_required(VERSION 3.15.2)
project(Project VERSION 0.0.1)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
#Add the needed Qt Components
find_package(Qt5 COMPONENTS
Core
Network
REQUIRED)
add_subdirectory(thirdparty)
SET(INCLUDES
...
)
SET(SOURCES
...
)
target_compile_options(${PROJECT_NAME} PUBLIC
...
)
target_compile_definitions(${PROJECT_NAME} PUBLIC
QUAZIP_STATIC )
target_include_directories(${PROJECT_NAME} PRIVATE
OtherIncludes
"${QUAZIP_INCLUDE_DIR}"
)
target_link_libraries(${PROJECT_NAME}
Qt5::Network
Qt5::Core
SomeOtherDep
quazip_static <---- adding static targets here
zlibstatic <---- adding static targets here
)
(3) CMakeLists.txt
# Download and unpack at configure time
configure_file(zlib/CMakeLists.txt.in zlib-download/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/zlib-download"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/zlib-download"
)
add_subdirectory("${CMAKE_BINARY_DIR}/zlib-src"
"${CMAKE_BINARY_DIR}/zlib-build"
)
# Download and unpack at configure time
configure_file(quazip/CMakeLists.txt.in quazip-download/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/quazip-download"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/quazip-download"
)
configure_file(quazip/CMakeListsBuild.txt.in ${CMAKE_BINARY_DIR}/quazip-src/CMakeLists.txt COPYONLY)
add_subdirectory("${CMAKE_BINARY_DIR}/quazip-src"
"${CMAKE_BINARY_DIR}/quazip-build"
)
set(QUAZIP_INCLUDE_DIR
"${CMAKE_BINARY_DIR}/quazip-src/quazip" PARENT_SCOPE)
The two CMakeLists.txt.in have nearly the same Content...
cmake_minimum_required(VERSION 2.8.2)
include(ExternalProject)
project(quazip-download NONE)
ExternalProject_Add(quazip
GIT_REPOSITORY git://github.com/stachenov/quazip.git
GIT_TAG v0.8.1
SOURCE_DIR "${CMAKE_BINARY_DIR}/quazip-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/quazip-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
cmake_minimum_required(VERSION 2.8.2)
include(ExternalProject)
project(zlib-download NONE)
ExternalProject_Add(zlib
GIT_REPOSITORY git://github.com/madler/zlib.git
GIT_TAG v1.2.11
SOURCE_DIR "${CMAKE_BINARY_DIR}/zlib-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/zlib-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
Then there is the last CMakeListsBuild.txt.in in the quazip folder. I'm just editing the original one and feed the zlib dependencies directly in. It looks like this:
cmake_minimum_required(VERSION 2.6)
project(QuaZip)
...
EVERYTHING ORIGINAL
...
# Use system zlib on unix and Qt ZLIB on Windows
# will be set from outside ZLIB_LIBRARIES ZLIB_INCLUDE_DIRS
--------------------ADDED BY ME REMOVED find_packages...
set(ZLIB_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/zlib-src
${CMAKE_BINARY_DIR}/zlib-build)
if(UNIX)
set(ZLIB_LIBRARIES
"${CMAKE_BINARY_DIR}/zlib-build/libz.a")
elseif(MINGW)
set(ZLIB_LIBRARIES
"${CMAKE_BINARY_DIR}/zlib-build/libzlibstatic.a")
endif()
...
EVERYTHING ORIGINAL
...
Question
Downloading and building the static lib of zlib works but I get the following error while compiling under linux.
/home/linuxmint/someDirectory/build/zlib-src/test/example.c:8:10: fatal error: zlib.h: No such file or directory
#include "zlib.h"
^~~~~~~~
compilation terminated.
zlib-build/CMakeFiles/example.dir/build.make:75: recipe for target 'zlib-build/CMakeFiles/example.dir/test/example.o' failed
make[2]: *** [zlib-build/CMakeFiles/example.dir/test/example.o] Error 1
CMakeFiles/Makefile2:1355: recipe for target 'zlib-build/CMakeFiles/example.dir/all' failed
make[1]: *** [zlib-build/CMakeFiles/example.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
This is the strange part I dont understand. If I have a look in the CMakeLists of zlib. (LINK)
They add everything of of the source and binary folder to the include with this:
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
So I don't understand why the example of zlib (and everything else which need zlib.h) can't be build...
Perhabs somebody has a hint...
Thanks...
Edit
If I install the headers with apt building works... But why ;) Since nowhere find_package is called...
Thanks to #squarekittles who pointed me in the right direction.
In the CMakeLists.txt of zlib the include dir is specified as ${CMAKE_SOURCE_DIR}. This is of course the wrong directory...
I added a additional CMakeLists.txt.in for zlib which will replace the original one. It's all the same only two lines are different:
...
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
^~~~~~~~~~~~~ Added in
#============================================================================
# zlib
#============================================================================
set(ZLIB_PUBLIC_HDRS
${CMAKE_CURRENT_BINARY_DIR}/zconf.h
${CMAKE_CURRENT_SOURCE_DIR}/zlib.h
) ^~~~~~~~~~~~~ Added in
...
Now the examples compile...
Also I needed to add the headers of zlib to my project did it by editing CMakeLists.txt (3)
...
configure_file(zlib/CMakeListsBuild.txt.in ${CMAKE_BINARY_DIR}/zlib-src/CMakeLists.txt COPYONLY) <--- Replacing CMakeLists.txt for zlib
...
set(QUAZIP_INCLUDE_DIR
"${CMAKE_BINARY_DIR}/quazip-src/quazip"
${ZLIB_INCLUDE_DIR} PARENT_SCOPE)
^~~~~~~~~~~~ Added in
...

Public headers not finding other public headers

I've created a static library using CMake and I'm installing the public headers in /usr/local/include/. The library and its tests compile fine on their own, but when using the library in another project I get an error:
/usr/local/include/weftworks/common/network/tcp/acceptor.hpp:28:10: fatal error: utility.hpp: No such file or directory
#include "utility.hpp"
where both acceptor.hpp and utility.hpp are public headers.
This is the related folder structure:
root/
├ cmake/
├ external/
├ library/
│ ├─ include/
│ │ ├─ network/
│ │ │ └─ tcp/
│ │ │ └─ acceptor.hpp
│ │ └─ utility.hpp
│ ├─ src/
│ └─ CMakeLists.txt
├ test/
└ CMakeLists.txt
./library/CMakeLists.txt:
# ./library/CMakeLists.txt
# Required CMake version
cmake_minimum_required(VERSION 3.13)
include(GNUInstallDirs)
# Project details
project(
weftworks-common-library
VERSION 0.4.0
DESCRIPTION "Internal Weftworks Common Library project."
)
# Library target sources
list(APPEND WEFTWORKS_COMMON_LIBRARY_PRIVATE_SOURCES)
list(APPEND WEFTWORKS_COMMON_LIBRARY_PUBLIC_SOURCES)
list(APPEND WEFTWORKS_COMMON_LIBRARY_INTERFACE_SOURCES)
include(src/CMakeLists.txt)
# A static library target
add_library(weftworks-common-library STATIC)
# Required compiler features
target_compile_features(
weftworks-common-library
PUBLIC
cxx_auto_type
cxx_constexpr
cxx_defaulted_functions
cxx_deleted_functions
cxx_final
cxx_lambdas
cxx_noexcept
cxx_override
cxx_range_for
cxx_static_assert
cxx_std_17
cxx_strong_enums
cxx_trailing_return_types
cxx_uniform_initialization
cxx_variadic_macros
)
target_compile_options(
weftworks-common-library
PRIVATE
-Wall
-Wextra
-pedantic
)
target_include_directories(
weftworks-common-library
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:include>"
)
target_link_libraries(
weftworks-common-library
PUBLIC
Boost::boost
Boost::system
Boost::program_options
spdlog::spdlog
Threads::Threads
)
target_sources(
weftworks-common-library
PUBLIC ${WEFTWORKS_COMMON_LIBRARY_PUBLIC_SOURCES}
INTERFACE ${WEFTWORKS_COMMON_LIBRARY_INTERFACE_SOURCES}
PRIVATE ${WEFTWORKS_COMMON_LIBRARY_PRIVATE_SOURCES}
)
# Create alias target
add_library(weftworks::common-library ALIAS weftworks-common-library)
# Install library target
install(
TARGETS weftworks-common-library
EXPORT weftworks-common-library-config
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(
EXPORT weftworks-common-library-config
NAMESPACE weftworks::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/weftworks/common-library
)
# Install public headers
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/weftworks/common
)
Now I don't know what I need to do to make this work. I'd like to avoid having the "library prefix" in the project structure i.e. library/include/weftworks/common/ to keep it simple.
You need to include "weftworks/common/network/utility.hpp".
This will also ensure that you actually include your header not some other header which someone has written with the very generic name "utility.hpp".

cmake the following imported targets are referenced, but are missing

I have a repository with two libraries (liba and libb) whereas liba
depends on libb. They are part of a single repository and are built using a single cmake "context". The file structure is shown below:
├── CMakeLists.txt
├── liba
│ ├── CMakeLists.txt
│ ├── internal
│ │ └── private.hh
│ ├── module.cc
│ ├── module.hh
└── libb
├── CMakeLists.txt
├── other.cc
└── other.hh
Everything compiles and installs without any issues. Although, if I try to create a new project that depends on liba. Like so:
cmake_minimum_required(VERSION 3.5)
find_package(Threads REQUIRED)
find_package(OpenCV REQUIRED)
find_package(liba REQUIRED)
add_executable(exec exec.cc)
target_link_libraries(exec PRIVATE is::liba)
I get the following error:
CMake Error at CMakeLists.txt:5 (find_package):
Found package configuration file:
/home/hodor/is-sdk/lib/cmake/liba/libaConfig.cmake
but it set liba_FOUND to FALSE so package "liba" is considered to be NOT
FOUND. Reason given by package:
The following imported targets are referenced, but are missing: is::libb
What I am missing here? Repository link for context
CMakeLists that generates liba:
cmake_minimum_required(VERSION 3.5)
include(GNUInstallDirs)
find_package(OpenCV REQUIRED core)
find_package(Threads REQUIRED)
list(APPEND liba_public_headers
"module.hh"
)
list(APPEND liba_private_headers
"internal/private.hh"
)
list(APPEND liba_sources
"module.cc"
${liba_public_headers}
${liba_private_headers}
)
add_library(liba ${liba_sources})
target_include_directories(
liba
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> # for headers when building
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # for generated files in build mode
$<INSTALL_INTERFACE:include/is/liba> # for clients in install mode
PRIVATE
${OpenCV_INCLUDE_DIRS}
)
target_link_libraries(liba
PRIVATE
is::libb
${OpenCV_LIBRARIES}
Threads::Threads
)
set_property(TARGET liba PROPERTY CXX_STANDARD 11)
install(
TARGETS liba EXPORT libaTargets
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
install(FILES ${liba_public_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/is/liba)
install(
EXPORT libaTargets
FILE libaConfig.cmake
NAMESPACE is::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/liba
)
CMakeLists that generates libb:
cmake_minimum_required(VERSION 3.5)
include(GNUInstallDirs)
list(APPEND libb_public_headers
"other.hh"
)
list(APPEND libb_sources
"other.cc"
${libb_public_headers}
)
add_library(libb ${libb_sources})
target_include_directories(
libb
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> # for headers when building
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # for generated files in build mode
$<INSTALL_INTERFACE:include/is/libb> # for clients in install mode
)
install(
TARGETS libb EXPORT libbTargets
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
install(FILES ${libb_public_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/is/libb)
install(
EXPORT libbTargets
FILE libbConfig.cmake
NAMESPACE is::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libb
)
add_library(is::libb ALIAS libb)
Top level CMakeLists that includes liba and libb:
cmake_minimum_required(VERSION 3.5)
add_subdirectory(liba)
add_subdirectory(libb)
After watching C++Now 2017: Daniel Pfeifer “Effective CMake"
I now realized what was missing in my configuration. As mentioned by #Tsyvarev the problem was about libaConfig.cmake.
When exporting a library with dependencies you should export mylibraryTargets.cmake, like so:
install(
EXPORT libaTargets
FILE libaTargets.cmake
NAMESPACE is::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/liba
)
And then manually (a bit disappointed here I have to say) write a mylibraryConfig.cmake with all the dependencies like so:
include(CMakeFindDependencyMacro)
find_dependency(libb)
find_dependency(OpenCV)
find_dependency(Threads)
include("${CMAKE_CURRENT_LIST_DIR}/libaTargets.cmake")