GCC constructor attribute实现函数先于m

2021-10-17  本文已影响0人  大唐游子

在很多场景下,需要先于main函数执行一些函数注册操作。

利用gcc的constructor attribute可以实现某函数先于main函数执行。

如以下main.c, init.cCMakeLists.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

上一篇下一篇

猜你喜欢

热点阅读