静态库调用静态库&静态库加载静态库------谈谈undefined reference to和linker input file unused because linking not done

来源:互联网 发布:恒生软件待遇 编辑:程序博客网 时间:2024/06/04 23:30

          静态库可以调用静态库吗? 静态库可以加载静态库吗?  搞清这些东西, 对于linux开发很重要, 本文我们来探讨这些问题。


          先看程序:

          business.h:

#include <iostream>using namespace std;void business();
          business.cpp:
#include <iostream>#include "business.h"using namespace std;void business(){printf("business code\n");}

        main.cpp

#include <iostream>#include "business.h"using namespace std;int main(){    business();    printf("main code\n");}

       我们来编译运行看下:

xxxxxx:~/liblearn> g++ -c business.cppxxxxxx:~/liblearn> ar rcs libbusiness.a business.oxxxxxx:~/liblearn> lsbusiness.cpp  business.h  business.o  libbusiness.a  main.cppxxxxxx:~/liblearn> g++ main.cpp -L. -lbusinessxxxxxx:~/liblearn> lsa.out  business.cpp  business.h  business.o  libbusiness.a  main.cppxxxxxx:~/liblearn> ./a.out business codemain codexxxxxx:~/liblearn> 

       一切正常。



        我们再看看:

        basic.h

#include <iostream>using namespace std;void basic();
        basic.cpp
#include <iostream>#include "basic.h"using namespace std;void basic(){    printf("basic code\n");}

        business.h:

#include <iostream>using namespace std;void business();
        business.cpp:
#include <iostream>#include "basic.h"#include "business.h"using namespace std;void business(){    basic();    printf("business code\n");}

       main.cpp内容为:

#include <iostream>#include "business.h"using namespace std;int main(){    business();    printf("main code\n");    return 0;}

      来看看结果:

xxxxxx:~/liblearn> lsbasic.cpp  basic.h  business.cpp  business.h  main.cppxxxxxx:~/liblearn> g++ -c basic.cpp xxxxxx:~/liblearn> g++ -c business.cpp xxxxxx:~/liblearn> strings business.o | grep "basic code"xxxxxx:~/liblearn> xxxxxx:~/liblearn> xxxxxx:~/liblearn> ar rcs libbasic.a basic.oxxxxxx:~/liblearn> g++ -c business.cpp -L. -lbasicg++: -lbasic: linker input file unused because linking not donexxxxxx:~/liblearn> strings business.o | grep "basic code"xxxxxx:~/liblearn> xxxxxx:~/liblearn> xxxxxx:~/liblearn> ar rcs libbusiness.a business.oxxxxxx:~/liblearn> g++ main.cpp -L. -lbusiness./libbusiness.a(business.o): In function `business()':business.cpp:(.text+0x79): undefined reference to `basic()'collect2: ld returned 1 exit statusxxxxxx:~/liblearn> xxxxxx:~/liblearn> xxxxxx:~/liblearn> g++ main.cpp -L. -lbusiness -lbasicxxxxxx:~/liblearn> xxxxxx:~/liblearn> xxxxxx:~/liblearn> ./a.out basic codebusiness codemain codexxxxxx:~/liblearn> strings a.out | grep "basic code"basic codexxxxxx:~/liblearn> 
       分析一下, 我们看到, 在编译business.cpp后, strings命令的结果没有basic code信息, 也就是business没有加载basic模块的任何东西, 因为这里只是编译, 没有链接. 即使主动链接一下, 也没有鸟用, 还会有warning提示linker input file unused because linking not done,   所以, 很自然地, g++ main.cpp -L. -lbusiness找不到basic, 很自然地需要g++ main.cpp -L. -lbusiness -lbasic, 这就带来了一个问题: libbusiness.a/business.h并不能独立地对外提供能力, 略蛋疼。

       怎么办呢? 这里可以考虑两种方法:

       a.  把libbasic.a库和libbusiness.a库合成新的libbusiness.a库, 但我个人不建议这么做。

       b.  专门为libbusiness.a搞一个宏, 使得每次链接libbusiness.a的时候, 自动也链接到libbasic.a,  这对于使用libbusiness.a的人来说, 是透明的, 不可见的, 不需要管的, 比较爽。

   

       综上所述: 

       1.  静态库 .a文件(这里更准确的说法应该是.o文件)不能加载其他静态库, 因为只涉及到编译,不涉及到链接。

       2.  静态库 .a文件(这里更准确的说法应该是.o文件)可以调用其他静态库(调用其中的函数), 此时并不会链接, 也不需要链接, 也链接不了。

           


        很多时候, 当我们的business模块要调用新的basic模块的静态库时, 要特别特别小心, 否则就会坑后面的同学, 后面同学在编译main的时候(或者其他so需要依赖于business静态库的时候), 肯定会undefined reference to xxx,  不好意思, 我曾经坑过两位同学大哭大哭


        其实, “加载”和“链接”的意思是差不多的。 好了, 本文先说道这里, 又有进步啦。




阅读全文
1 0