I have the following reduced CMake code for using Abseil in a library: (minimal repository to reproduce)
cmake_minimum_required(VERSION 3.20)
project(MyProject)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
set(ABSL_PROPAGATE_CXX_STD ON)
find_package(absl REQUIRED)
add_library(MyStaticLibTarget STATIC MyStaticLib.cpp)
target_link_libraries(MyStaticLibTarget absl::strings)
install(TARGETS MyStaticLibTarget EXPORT MyProjectTargets)
install(TARGETS strings EXPORT MyProjectTargets)
if(EXPORT_MYSTATICLIB)
export(TARGETS MyStaticLibTarget FILE lib/cmake/MyProject/MyProjectTargets.cmake)
endif()
# Setup for downstream clients of MyProject?
install(EXPORT MyProjectTargets DESTINATION lib/cmake/MyProject COMPONENT cmake-exports)
However, I run into an error as shown if I try to use the export
code path, when running CMake with:
cmake -G Ninja -S . -B build -DABSL_ENABLE_INSTALL=ON -DEXPORT_MYSTATICLIB=ON
# CMake Error in CMakeLists.txt:
# export called with target "MyStaticLibTarget" which requires target
# "strings" that is not in any export set.
I don't understand the error message; it seems to me that strings
is already part of MyProjectTargets
(which I think is an export set?), so there shouldn't be any error.
That said, based on the error message, I tried adding an export
line for strings
, and transitively fixed all the errors, and I ended up with
export(TARGETS
strings
strings_internal
type_traits
base
config
throw_delegate
dynamic_annotations
log_severity
base_internal
raw_logging_internal
atomic_hook
core_headers
spinlock_wait
endian
bits
int128
memory
errno_saver
meta
APPEND FILE lib/cmake/MyProject/MyProjectTargets.cmake)
That does fix all errors! In practice, this would be very painful to do by hand for a larger library. It also seems like the "wrong" solution, because I am naming lots of internal details of Abseil by hand.
I have the following constraints:
MyStaticLibTarget
so it can be used by downstream clients.target_link_libraries
) needs to be public, as in the actual case (this is a minimal example), Abseil headers will be included in the library's public headers.TLDR: Follow the Conan docs, especially the cmake_find_package docs and skim the cheatsheet.
Following @Tsyvarev's advice in the comments, I used a different setup and made this work, you can see the final result in conan branch.
The steps are as follows:
conanfile.txt
. Now, "install" is a scary word (I did not want to modify global state), but Conan essentially just caches sources and build artifacts, which means that you can have multiple versions of the same libraries in different directories, and different projects can use these different versions, and it should "just work". (At least, that's my basic understanding so far.)
[requires] # Which 3rd party conan packages we are using
abseil/20210324.2
[generators] # How to create build system files that capture the dependency information
cmake_find_package
cmake_paths
With the above configuration, Conan can be run:
conan install . --install-folder build/conan
# Bunch of CMake files will be available under build/conan
CMakeLists.txt
.
include("${CMAKE_BINARY_DIR}/conan/conan_paths.cmake")
cmake -G Ninja -S . -B build -DEXPORT_MYSTATICLIB=ON
(The ABSL_ENABLE_INSTALL
option is handled by Conan and is no longer needed.)