美文网首页
GCC constructor attribute实现函数先于m

GCC constructor attribute实现函数先于m

作者: 大唐游子 | 来源:发表于2021-10-17 23:12 被阅读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

    相关文章

      网友评论

          本文标题:GCC constructor attribute实现函数先于m

          本文链接:https://www.haomeiwen.com/subject/uorgoltx.html