在很多场景下,需要先于main函数执行一些函数注册操作。
利用gcc的constructor attribute可以实现某函数先于main函数执行。
如以下main.c
, init.c
和CMakeLists.txt
:
// main.c
#include <stdio.h>
int main()
{
printf("main.\n");
}
// init.c
#include <stdio.h>
__attribute__((constructor)) static void init()
{
printf("initalized.\n");
}
cmake_minimum_required(VERSION 3.10)
project(test)
add_executable(test main.c init.c)
编译执行后,输出结果如下:
$ ./test.exe
initalized.
main.
但是,如果将init.c编译成静态库,init
函数就无法先于main
函数执行了。
修改CMakeLists.txt
如下:
cmake_minimum_required(VERSION 3.10)
project(test)
add_library(init STATIC init.c)
add_executable(test main.c)
target_link_libraries(test init)
编译执行后结果如下:
$ ./test.exe
main.
这时,可以采用whole-archive
链接选项,强制将静态库中所有的对象链接到主程序中。
修改CMakeLists.txt
如下:
cmake_minimum_required(VERSION 3.10)
project(test)
add_library(init STATIC init.c)
add_executable(test main.c)
target_link_libraries(test
-Wl,--whole-archive init # 只包含init库中的全部对象
-Wl,--no-whole-archive) # 不包含其他库中的对象
编译执行后,输出结果如下:
$ ./test.exe
initalized.
main.
这里需要注意的是,对init
库使用--whole-archive
链接选项后,一定要加上--no-whole-archive
链接选项,以排除对其他库的全部包含,否则会发生很多重复定义错误。
参考
Using LD, the GNU linker - Options
build process - ld linker question: the --whole-archive option - Stack Overflow
网友评论