您的位置:首页 > Web前端

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

2017-06-16 21:57 489 查看
          静态库可以调用静态库吗? 静态库可以加载静态库吗?  搞清这些东西, 对于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.cpp
xxxxxx:~/liblearn> ar rcs libbusiness.a business.o
xxxxxx:~/liblearn> ls
business.cpp  business.h  business.o  libbusiness.a  main.cpp
xxxxxx:~/liblearn> g++ main.cpp -L. -lbusiness
xxxxxx:~/liblearn> ls
a.out  business.cpp  business.h  business.o  libbusiness.a  main.cpp
xxxxxx:~/liblearn> ./a.out
business code
main code
xxxxxx:~/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> ls
basic.cpp  basic.h  business.cpp  business.h  main.cpp
xxxxxx:~/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.o
xxxxxx:~/liblearn> g++ -c business.cpp -L. -lbasic
g++: -lbasic: linker input file unused because linking not done
xxxxxx:~/liblearn> strings business.o | grep "basic code"
xxxxxx:~/liblearn>
xxxxxx:~/liblearn>
xxxxxx:~/liblearn> ar rcs libbusiness.a business.o
xxxxxx:~/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 status
xxxxxx:~/liblearn>
xxxxxx:~/liblearn>
xxxxxx:~/liblearn> g++ main.cpp -L. -lbusiness -lbasic
xxxxxx:~/liblearn>
xxxxxx:~/liblearn>
xxxxxx:~/liblearn> ./a.out
basic code
business code
main code
xxxxxx:~/liblearn> strings a.out | grep "basic code"
basic code
xxxxxx:~/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,  不好意思, 我曾经坑过两位同学




        其实, “加载”和“链接”的意思是差不多的。 好了, 本文先说道这里, 又有进步啦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐