Code for a shared library is modular, consists of several independent units. Each unit is built into a static library.
unit1.c
#include <stdio.h>
void HelloWorld() {
printf("Hello World!\n");
}
unit2.c
#include <stdio.h>
void GoodbyeWorld() {
printf("Goodbye World!\n");
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
add_library(unit1 STATIC unit1.c)
target_compile_options(unit1 PRIVATE -fPIC)
add_library(unit2 STATIC unit2.c)
target_compile_options(unit2 PRIVATE -fPIC)
add_library(merged SHARED)
target_link_libraries(merged unit1 unit2)
set_target_properties(merged PROPERTIES LINKER_LANGUAGE C)
Build steps:
cmake . && cmake --build .
Exported symbols by libmerged.so:
$ nm -D --defined-only libmerged.so
0000000000201020 B __bss_start
0000000000201020 D _edata
0000000000201028 B _end
00000000000005a0 T _fini
0000000000000458 T _init
Q Why symbols HelloWorld and GoodbyeWorld are not exported? How to fix it?
I've tried --version-script
without success.
Additional setting in CMakeLists.txt
set_target_properties(merged PROPERTIES LINK_FLAGS -Wl,--version- script=merged.version)
merged.version
merged { global: HelloWorld; GoodbyeWorld; local: *; };
set_target_properties(merged PROPERTIES LINK_FLAGS -Wl,-force_load,libunit1.a)
You need to pass the --whole-archive
option to the linker. In CMake, you can do it as follows.
cmake_minimum_required(VERSION 3.0.2)
add_library(unit1 STATIC unit1.c)
target_compile_options(unit1 PRIVATE -fPIC)
add_library(unit2 STATIC unit2.c)
target_compile_options(unit2 PRIVATE -fPIC)
add_library(merged SHARED)
set_target_properties(merged PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(merged
"-Wl,--whole-archive libunit1.a libunit2.a -Wl,--no-whole-archive"
unit1 unit2
)
Note: The target_link_libraries
command can be used to specify linker flags as well, not only library names. The quotes are important, otherwise CMake might rearrange the flags and remove duplicates.
$ nm libmerged.so | grep " T "
000000000000065d T GoodbyeWorld
000000000000064a T HelloWorld
0000000000000670 T _fini
0000000000000520 T _init
Another option, to avoid the problem, would be to create OBJECT
instead of STATIC
libraries for unit1
and unit2
.
cmake_minimum_required(VERSION 3.0.2)
add_library(unit1 OBJECT unit1.c)
target_compile_options(unit1 PRIVATE -fPIC)
add_library(unit2 OBJECT unit2.c)
target_compile_options(unit2 PRIVATE -fPIC)
add_library(merged SHARED $<TARGET_OBJECTS:unit1> $<TARGET_OBJECTS:unit2>)
set_target_properties(merged PROPERTIES LINKER_LANGUAGE C)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.