• 再议GCC编译时的静态库依赖顺序问题


    相关博文1:http://blog.chinaunix.net/uid-20682147-id-76330.html
    相关博文:http://blog.chinaunix.net/uid-20682147-id-5096676.html

    假设有如三个源代码文件:

    $ cat a.cpp

    void a()

    {

    }

    $ cat b.cpp

    extern void a();

    void b()

    {

        a(); // 调用a.cpp中的a()

    }

    $ cat x.cpp

    extern void b();

    int main()

    {

        b(); // 调用b.cpp中的b()

        return 0;

    }

    对应的Makefile文件:

    all: x

    liba.a: a.o

    libb.a: b.o

    x: x.o liba.a libb.a # 问题出在这儿

        g++ -g -o $@ $^

    a.o: a.cpp

        g++ -g -c $^

    b.o: b.cpp

        g++ -g -c $^

    x.o: x.cpp

        g++ -g -c $^

    clean:

        rm -f a.o b.o x.o x

    使用上面的Makefile编译,将会遇到如下所示的“undefined reference”问题:

    g++ -g -c x.cpp

    g++ -g -c a.cpp

    g++ -g -c b.cpp

    g++ -g -o x x.o liba.a libb.a # 改成“g++ -g -o x x.o libb.a liba.a”即可解决

    libb.a(b.o): In function `b()':

    /tmp/b.cpp:2: undefined reference to `a()'

    collect2: ld returned 1 exit status

    make: *** [x] Error 1

    这个问题的原因是b.cpp依赖a.cpp,gcc要求(实际是ld要求)libb.a须放在liba.a前面,即需要改成:g++ -g -o x x.o libb.a liba.a,也就是被依赖的库需要放在后头。

    这是最常规的解决办法,除此之外,只需要加入--start-group和--end-group两个链接参数,即可保持被依赖的库放在前头,也就是改成如下即可:g++ -g -o $@ -Wl,--start-group $^ -Wl,--end-group。

    这里的“-Wl,”表示后面跟着的参数是传递给链接器ld的,gcc不关心具体是啥。“--start-group”表示范围的开始;“--end-group”表示范围的结束,是可选的。位于“--end-group”之后的仍然要求被依赖的库放在后头。注意“--start-group”不能重复,相关链接参数:--whole-archive 和 --no-whole-archive。

  • 相关阅读:
    使用JSON.NET实现对象属性的格式化的自定义
    AspNetCore项目-Service注入或覆盖
    发布Nuget
    收藏
    工具
    快捷键大全
    SqlServer分页查询语句
    面试相关
    Eratosthes algrithm 求素数
    code training
  • 原文地址:https://www.cnblogs.com/lidabo/p/13808305.html
Copyright © 2020-2023  润新知