Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake - including dependencies inside a static library

Tags:

c++

cmake

I am very new to C++ and all the associated terms and toolchains. I am trying to build a static library that customers can use in their own projects. Ideally, I would like to send them nothing but an .a and a .lib file, plus an .h file.

Right now, my CMake file looks like this:

project(ava-engine-client)
cmake_minimum_required(VERSION 3.9.6)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )

add_compile_options(-std=c++11)

# GRPC and Protocol Buffers libraries location
list(APPEND CMAKE_PREFIX_PATH "/opt/grpc" "/opt/protobuf")

# CMake find modules
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")


# Recurse and find all the generated Protobuf .cc files
file(GLOB_RECURSE PROTO_GEN_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/ava_engine/ava/*.cc)

include_directories("${CMAKE_CURRENT_SOURCE_DIR}")

# Building the library
add_library(ava_engine_client STATIC src/AvaEngineClient.cc src/AvaEngineClient.h ${PROTO_GEN_SRCS})

target_link_libraries(ava_engine_client ${PROTOBUF_LIBRARIES} ${GRPC_LIBRARY})


## Building Playground
add_executable(playground src/Playground.cc)

target_link_libraries(playground ava_engine_client)

Now this fails at the linking stage, because I don't link the playground target, with the dependencies inside the ava_engine_client library:

Undefined symbols for architecture x86_64:
  "grpc::ClientContext::ClientContext()", referenced from:
      ...
  "grpc::ClientContext::~ClientContext()", referenced from:
      ...
  "grpc::CreateChannel(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<grpc::ChannelCredentials> const&)", referenced from:
      ...
  "grpc::g_core_codegen_interface", referenced from:
      ...

This isn't what I want, because it would require the customer to link with dependencies in my library (which doesn't' seem right to me).

Now, I have read a few Stack Overflow posts like this one: (CMake: include library dependencies in a static library) that suggest using CMAKE_CXX_ARCHIVE_CREATE to create an archive file. Is this the approach I should take? Is what I want even possible?

like image 528
Dominic Bou-Samra Avatar asked Feb 11 '18 22:02

Dominic Bou-Samra


People also ask

What does CMake target_link_libraries do?

Specify libraries or flags to use when linking a given target and/or its dependents. Usage requirements from linked library targets will be propagated. Usage requirements of a target's dependencies affect compilation of its own sources.

How do I add a library path to CMake?

To add a library in CMake, use the add_library() command and specify which source files should make up the library. Rather than placing all of the source files in one directory, we can organize our project with one or more subdirectories.


2 Answers

If you are bound to create a static library, the solution you linked in your original post is probably the best (CMake: include library dependencies in a static library). Using ar or library tools to combine the static libraries seems to be the only way to go. This is a pretty popular question on Stack Overflow and all the answers seem to come down to that.

However, if you are able, the easiest solution by far is to create a shared library and link your static libraries into it (as mentioned by jszpilewski in the comments). Yes, it does mean distributing the shared library for runtime. Whether that is practical or not depends on your project.

like image 180
avariant Avatar answered Nov 12 '22 04:11

avariant


The clause add_executable will always try to produce a binary ready to be used by the operating system so it is not suitable for producing a static library.

You may use as an inspiration or even borrow some code from the Google Test unit test framework. It is using CMake to generate the UT framework as configurable static or dynamic libraries using the final syntax like:

cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)

But it defines cxx_library and some other functions internally. So you should take a look at their CMake include file internal_utils.cmake. Google Test comes with the BSD software license.

like image 42
jszpilewski Avatar answered Nov 12 '22 06:11

jszpilewski