0
\- lib
  CMakeLists.txt 
  libA.a
  libB.a
  \- src 
    \- mod1
    \- mod2
  \- inc
    \- mod1
    \- mod2
    \- libA
    \- libB
\- examples
  \- common_inc // common includes for all examples
  \- my_executable
    CMakeLists.txt 
    \- src 
    \- inc

src contains .cpp files for mod1 and mod2, both depend on libA, libB, inc contains headers for libA, libB, and for mod1 and mod2

The question is:

I want to make one shared library which contains libA.a, libB.a and also my src (mod1 and mod2), how I can achieve that?

Is there any other way besides creating static lib (lets call it libMy) from mod1 and mod2 and then link all 3 libs (libMy, libA, libB) into one shared library?

I came up with following CMakeLists.txt but it cannot find -llibA and -llibB

cmake_minimum_required (VERSION 3.5)

project (libMy CXX)
set (CMAKE_CXX_STANDARD 14)

set (SRC
                "src/mod1/a1.cpp"
                "src/mod2/a2.cpp"
)

set (INC
                "inc/mod1/a1.hpp"
                "inc/mod2/a2.hpp"
                "inc/lib1/libA.hpp"
                "inc/lib2/libB.hpp"

)
add_library(libMy STATIC ${SRC} ${INC})
target_include_directories(libMy PUBLIC inc)

add_library(master_library SHARED
    dummy.cpp
)
target_link_libraries(master_library libMy)
target_link_libraries(master_library -lpthread)
target_link_libraries(master_library libA.a)
target_link_libraries(master_library libB.a)

UPDATE

Thanks to @Tsyvarev I managed to solve this problem. But there is another one...

When I try to link my shared library into my_executable I get undefined reference error, here is full error message:

../../../lib/libmylib.a(session.cpp.o): In function `mylib::network::session::write(mylib::network::packet const&)':
session.cpp:(.text+0x4e5): undefined reference to `libA::tcp_client::async_write(libA::tcp_client::write_request const&)'
../../../lib/libmylib.a(tcp_server.cpp.o): In function `mylib::network::tcp_server::tcp_server()':
tcp_server.cpp:(.text+0x24b): undefined reference to `libA::tcp_server::tcp_server()'
../../../lib/libmylib.a(tcp_server.cpp.o): In function `mylib::network::tcp_server::~tcp_server()':
tcp_server.cpp:(.text+0x323): undefined reference to `libA::tcp_server::~tcp_server()'
../../../lib/libmylib.a(tcp_server.cpp.o): In function `mylib::network::tcp_server::start(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)::{lambda(std::shared_ptr<libA::tcp_client> const&)#1}::operator()(std::shared_ptr<libA::tcp_client> const&) const':
tcp_server.cpp:(.text+0x445): undefined reference to `libA::tcp_client::async_read(libA::tcp_client::read_request const&)'
../../../lib/libmylib.a(tcp_server.cpp.o): In function `mylib::network::tcp_server::start(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)':
tcp_server.cpp:(.text+0x52c): undefined reference to `libA::tcp_server::start(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int, std::function<bool (std::shared_ptr<libA::tcp_client> const&)> const&)'
../../../lib/libmylib.a(tcp_server.cpp.o): In function `mylib::network::tcp_server::on_new_message(std::shared_ptr<libA::tcp_client> const&, libA::tcp_client::read_result const&)':
tcp_server.cpp:(.text+0x767): undefined reference to `libA::tcp_client::async_read(libA::tcp_client::read_request const&)'
tcp_server.cpp:(.text+0x801): undefined reference to `libA::tcp_client::disconnect(bool)'
../../../lib/libmylib.a(pool.cpp.o): In function `mylib::libB::pool::~pool()':
pool.cpp:(.text+0x42): undefined reference to `ConnectionPool_free'
pool.cpp:(.text+0x5f): undefined reference to `URL_free'
../../../lib/libmylib.a(pool.cpp.o): In function `mylib::libB::pool::connect(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
pool.cpp:(.text+0x249): undefined reference to `URL_new'
pool.cpp:(.text+0x26a): undefined reference to `ConnectionPool_new'
pool.cpp:(.text+0x284): undefined reference to `Exception_stack'
pool.cpp:(.text+0x28b): undefined reference to `pthread_getspecific'
pool.cpp:(.text+0x298): undefined reference to `Exception_stack'
pool.cpp:(.text+0x2a9): undefined reference to `pthread_setspecific'
pool.cpp:(.text+0x2e3): undefined reference to `ConnectionPool_start'
pool.cpp:(.text+0x2f8): undefined reference to `Exception_stack'
pool.cpp:(.text+0x2ff): undefined reference to `pthread_getspecific'
pool.cpp:(.text+0x30c): undefined reference to `Exception_stack'
pool.cpp:(.text+0x316): undefined reference to `pthread_setspecific'
pool.cpp:(.text+0x325): undefined reference to `SQLException'
pool.cpp:(.text+0x39d): undefined reference to `Exception_throw'
../../../lib/libmylib.a(connection.cpp.o): In function `mylib::libB::connection::connection(ConnectionPool_S*)':
connection.cpp:(.text+0x18): undefined reference to `ConnectionPool_getConnection'
../../../lib/libmylib.a(connection.cpp.o): In function `mylib::libB::connection::~connection()':
connection.cpp:(.text+0x41): undefined reference to `Connection_close'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::query(Connection_S*, char const*)':
query.cpp:(.text+0x28): undefined reference to `Connection_prepareStatement'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::set(int)':
query.cpp:(.text+0x93): undefined reference to `PreparedStatement_setInt'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::set(char const*)':
query.cpp:(.text+0xe3): undefined reference to `PreparedStatement_setString'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::get_int()':
query.cpp:(.text+0x15d): undefined reference to `ResultSet_getInt'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::get_str[abi:cxx11]()':
query.cpp:(.text+0x1ee): undefined reference to `ResultSet_getString'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::execute_query()':
query.cpp:(.text+0x28e): undefined reference to `PreparedStatement_executeQuery'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::execute()':
query.cpp:(.text+0x2e4): undefined reference to `PreparedStatement_execute'
query.cpp:(.text+0x2f3): undefined reference to `PreparedStatement_rowsChanged'
../../../lib/libmylib.a(query.cpp.o): In function `mylib::libB::query::next()':
query.cpp:(.text+0x326): undefined reference to `ResultSet_next'
collect2: error: ld returned 1 exit status
CMakeFiles/my_executable.dir/build.make:121: recipe for target 'my_executable' failed
make[2]: *** [my_executable] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/my_executable.dir/all' failed
make[1]: *** [CMakeFiles/my_executable.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

/lib/CMakeLists.txt:

cmake_minimum_required (VERSION 3.5)

project (my_executable CXX)
set (CMAKE_CXX_STANDARD 14)

set (SRC
                "src/main.cpp"
                "src/mysrcA.cpp"
)

set (INC
                "inc/mysrcA.hpp"
)

add_library(mylib STATIC IMPORTED GLOBAL)
set_target_properties(mylib PROPERTIES 
    IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../../lib/mylib.so"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/../../lib/inc"
)


add_executable (my_executable ${SRC})
target_include_directories(dbserver PRIVATE "${CMAKE_SOURCE_DIR}/inc")
target_include_directories(dbserver PRIVATE "${CMAKE_SOURCE_DIR}/../common_inc")

target_link_libraries(my_executable mylib)

/examples/my_executable/CMakeLists.txt:

cmake_minimum_required (VERSION 3.5)

project (mylib CXX)
set (CMAKE_CXX_STANDARD 14)

set (SRC
                "src/mod1/mod1A.cpp"
                "src/mod2/mod2A.cpp"
)

set (INC
                "inc/mod1/mod1A.hpp"
                "inc/mod2/mod2A.hpp"
                "inc/libA/libA.hpp"
                "inc/libB/libB.h"
)

add_library(mylib STATIC ${SRC} ${INC})
target_include_directories(mylib PUBLIC ${CMAKE_SOURCE_DIR}/inc)

add_library(libA STATIC IMPORTED)
set_target_properties(libA PROPERTIES 
    IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libA.a"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/inc/libA"
)

add_library(libB STATIC IMPORTED)
set_target_properties(libB PROPERTIES 
    IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/res/libB.a"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/inc/libB.h"
)
#)
target_link_libraries(mylib libA libB -lpthread)
KaDw
  • 78
  • 1
  • 7
  • 1
    Why you create intermediate `libMy` (static) library? Just create shared `master_library` and list all sources in it. As for linking errors, see [that question](https://stackoverflow.com/questions/8774593/cmake-link-to-external-library) for proper link with existing libraries. – Tsyvarev May 05 '18 at 12:32
  • @Tsyvarev How I can do that? Something like this? https://pastebin.com/5sVverXD – KaDw May 05 '18 at 12:41
  • 1
    What is wrong with `add_library(master_library SHARED ${SRC} ${INC})`? – Tsyvarev May 05 '18 at 12:42
  • @Tsyvarev Thanks! I've got it working, edited first post – KaDw May 05 '18 at 13:20
  • @Tsyvarev It turns out if I link master_library.so to executable in another project I get undefined reference. As I mentioned earlier I would like to get a master_library which has inside libA and libB so if I want to use my lib, I only link master_library. This is my actual [CMakeLists.txt](https://pastebin.com/VCMjQ25s). Now linker tells me `relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC` So I added add_compile_options(-fPIC). But this doesn't work. – KaDw May 06 '18 at 09:35
  • @Tsyvarev Ok, linkers tell me that -fPIC should be used on libA.a but it's is already built and I can't build it myself. – KaDw May 06 '18 at 10:39
  • Yes, for use a static library in position-relocatable shared objects(shared library or executable), this static library should be compiled with `-fPIC`. Alternatively, you may disable that feature for your shared library and executable by setting [CMAKE_POSITION_INDEPENDENT_CODE](https://cmake.org/cmake/help/v3.9/variable/CMAKE_POSITION_INDEPENDENT_CODE.html) variable to `0`. – Tsyvarev May 06 '18 at 13:15
  • @Tsyvarev Thanks, it seems to work. Now when I link this library to executable it says undefined reference. I supply all headers in [CMakeLists.txt](https://pastebin.com/jPBMuwXm). I don't know if this is library fault or I'm not linking it right. – KaDw May 07 '18 at 21:03
  • Here is my actual code to build shared lib which should contain static libA.a and libB.a https://pastebin.com/ptDyAx80 – KaDw May 07 '18 at 21:10
  • "I don't know if this is library fault or I'm not linking it right." - Without **exact error message** we don't know too. Add it to the question post (and update the code in it). – Tsyvarev May 07 '18 at 22:08
  • @Tsyvarev Updated question post. – KaDw May 08 '18 at 22:05
  • Error `undefined reference to `libA::tcp_client::async_write ...` means that `liba` either doesn't define this method or define it in **incompatible format** (e.g. `liba` is compiled with a compiler, different from one you use for the main project). – Tsyvarev May 09 '18 at 11:38
  • @Tsyvarev I recompiled everything (libA, libB, mylib, my_executable ) with my current toolchain (5.4.0 GCC ubuntu) and I'm still having trouble with undefined reference. Also checked headers and they have all of the definitions. Is there anything wrong with CMakeLists.txt? – KaDw May 10 '18 at 19:54
  • `Also checked headers and they have all of the definitions.` - Usually, a header only *declares* a function or a class method. **Definition** of the function/method comes in a `.cpp` file. And it seems that such **definition** is absence in your case. – Tsyvarev May 10 '18 at 20:21

0 Answers0