Satyanvesh D
Satyanvesh D

Reputation: 403

How to create a shared library using object library in CMake

I have two shared libraries each one having its own CMakeLists.txt. The directory structure is like this.

main_dir
|--- subdir
|    |--- src1.cpp
|    |--- src2.cpp
|    |--- src3.cpp
|    |--- CMakeLists.txt
|--- src11.cpp
|--- CMakeLists.txt

Currently, I am able to build both main library and sub library (say main.so and sub.so).

The CMakeLists.txt for both looks as below.

main_dir/CMakeLists.txt

option(BUILD_SHARED_LIBS "Build the shared library" ON)

if(BUILD_SHARED_LIBS)
  add_library(mainlib SHARED)
endif()

target_sources(mainlib PRIVATE
  src11.cpp
)

add_subdirectory(subdir)

subdir/CMakeLists.txt

option(BUILD_SHARED_LIBS "Build the shared library" ON)

if(BUILD_SHARED_LIBS)
  add_library(sublib SHARED)
endif()

target_sources(sublib PRIVATE
  src1.cpp
  src2.cpp
  src3.cpp)

Now I want the object file or symbols of sub library to be included in the main library as well, so that users can still use the main library alone even if they don't link their application to the sub library.

I'm new to CMake and I was trying to create an object library out of all source files in the sub_dir and link this to my mainlib.

add_library(subarchive OBJECT src1.cpp src2.cpp src3.cpp)
target_sources(mainlib INTERFACE $<TARGET_OBJECTS:subarchive>)

But It gives me error.

(add_library) No SOURCES given to target: mainlib

How can I create an object library in sub_dir and add it to both sublib and mainlib. Is there any better way to do this. Thanks.

Upvotes: 6

Views: 7778

Answers (2)

Satyanvesh D
Satyanvesh D

Reputation: 403

I was able to get it working by setting PARENT_SCOPE for the object library in the suddirectory. The modifications to the original code look like this.

main_dir/CMakeLists.txt

set(SUBARCHIVE_OBJECTS)

add_subdirectory(subdir)
target_link_libraries(mainlib private ${SUBARCHIVE_OBJECTS}

subdir/CMakeLists.txt

add_library(subarchive OBJECT src1.cpp src2.cpp src3.cpp)
list(APPEND SUBARCHIVE_OBJECTS ${TARGET_OBJECTS:subarchive>)
set(SUBARCHIVE_OBJECTS ${SUBARCHIVE_OBJECTS} PARENT_SCOPE)

Thanks for the responses.

Upvotes: 2

Adriaan de Groot
Adriaan de Groot

Reputation: 516

To use an OBJECT library, link with it. That doesn't do any actual linking -- there is no "thing" that is the object library, it's just a collection of object files that CMake knows about -- but puts the object files in the target:

target_link_libraries(mainlib PRIVATE sublib)

Here is a complete example (it creates source files one.cpp and two.cpp so that it is entirely self-contained):

cmake_minimum_required(VERSION 3.18)
project(example)
if(NOT EXISTS one.cpp)
  file(WRITE one.cpp "int x;")
endif()
if(NOT EXISTS two.cpp)
  file(WRITE two.cpp "int y;")
endif()
add_library(sublib OBJECT one.cpp)
add_library(mainlib SHARED two.cpp)
target_link_libraries(mainlib PRIVATE sublib)

Upvotes: 7

Related Questions