Install nested static library, and target_link_library not working
File structure:
HelloLib
WorldLib
CMakeLists.txt
WorldLib.cpp
WorldLib.h
CMakeLists.txt
HelloLib.cpp
HelloLib.h
CMakeLists.txt
main.cpp
main.cpp
#include <iostream>
#include "HelloLib/HelloLib.h"
int main() {
std::cout << hello() << std::endl;
return 0;
}
CMakeLists.txt (root)
cmake_minimum_required(VERSION 3.16.3)
project(HelloWorld)
add_executable(${PROJECT_NAME} main.cpp)
add_subdirectory(HelloLib)
target_link_libraries(
${PROJECT_NAME}
HelloLib
)
HelloLib.cpp
#include <string>
#include "WorldLib/WorldLib.h"
std::string hello() { return "Hello " world(); }
HelloLib.h
#pragma once
#include <string>
std::string hello();
CMakeLists.txt (HelloLib)
add_library(HelloLib HelloLib.cpp)
add_subdirectory(WorldLib)
target_link_libraries(
HelloLib
WorldLib
)
WorldLib.cpp
#include <string>
std::string world() { return "World!"; }
WorldLib.h
#pragma once
#include <string>
std::string world();
CMakeLists.txt (WorldLib)
add_library(WorldLib WorldLib.cpp)
Build and run, successfully print out Hello World!
Now I would like to make HelloLib as static library
Change CMakeLists.txt (HelloLib), install to /usr/lib
and /usr/include
add_library(HelloLib HelloLib.cpp)
add_subdirectory(WorldLib)
target_link_libraries(
HelloLib
WorldLib
)
install(
TARGETS HelloLib
ARCHIVE DESTINATION lib
)
install(
DIRECTORY "${CMAKE_SOURCE_DIR}/" # source directory
DESTINATION "include" # target directory
FILES_MATCHING # install only matched files
PATTERN "*.h" # select header files
)
Run (make install
) (CMAKE_INSTALL_PREFIX=/usr
)
mkdir -p out/build
cmake -S src -B out/build -DCMAKE_INSTALL_PREFIX=/usr
cd out/build
make
make install
[ 33%] Built target WorldLib
[ 66%] Built target HelloLib
[100%] Built target HelloWorld
Install the project...
-- Install configuration: ""
-- Installing: /usr/lib/libHelloLib.a
-- Up-to-date: /usr/include
-- Installing: /usr/include/HelloLib
-- Installing: /usr/include/HelloLib/HelloLib.h
-- Installing: /usr/include/HelloLib/WorldLib
-- Installing: /usr/include/HelloLib/WorldLib/WorldLib.h
Static library (.a) should generate to /usr/lib/libHelloLib.a
Let's test it, change CMakeLists.txt (root)
cmake_minimum_required(VERSION 3.16.3)
project(HelloWorld)
add_executable(${PROJECT_NAME} main.cpp)
add_subdirectory(HelloLib)
target_link_libraries(
${PROJECT_NAME}
/usr/lib/libHelloLib.a
)
Then build, it give undefined reference error
/bin/ld: /usr/lib/libHelloLib.a(HelloLib.cpp.o): in function `hello[abi:cxx11]()':
HelloLib.cpp:(.text 0x20): undefined reference to `world[abi:cxx11]()'
What's wrong with me? This can be successful with no nested library
What is the correct way to install nested static library?
CodePudding user response:
The issue here is not the install process but the fact that you link only to libHelloLib.a
.
Your libHelloLib.a
need the symbol in libWorldLib.a
because libHelloLib.a
is a static lib and so only contains its own symbol. It does not contains the symbol world
that is defined in libWorldLib.a
.
To make your project works, you need to install WorldLib
and HelloLib
and links against this two lib.
target_link_libraries(
${PROJECT_NAME}
HelloLib
WorldLib
)
Or you can change HelloLib
into a shared library. This way the libHelloLib.so
will also contains the symbol of WorldLib
.
You can also look at this Exported Target.
It's an install command that will create some FindXX.cmake
file that you will be able to use with the find_package
command. You also will be able to defined the dependency of your lib. But if you want that HelloLib
stay a static library you will have to install WorldLib