静态库依赖关系的一种情况

首先确定的一个概念:lib文件和obj文件都是源代码生成的中间文件,只不过lib文件可能是由多个obj文件集合而来。静态库是一个或多个obj文件的打包。最终都会链接到可执行程序中去。

假设下面一种情况:

应用程序TestCallLib依赖静态链接库TestLibB;而TestLibB又依赖静态链接库TestLibA。
这里写图片描述

静态库TestLibA的定义

TestLibA是一个静态链接库,只有一个导出类TestLibA,该类只有一个导出方法print。

#TestLibA.h
#ifndef TESTLIBA_H
#define TESTLIBA_H
class __declspec(dillexport) TestLibA
{
pulic:
    TestLibA();
    void print();
}
#endif

静态库TestLibB的定义

TestLibB是一个静态链接库,只有一个导出类TestLibB,该类只有一个导出方法Print。

#TestLibB.h
#ifndef TESTLIBB_H
#define TESTLIBB_H
class __declspec(dllexport) TestLibB
{
public:
    TestLibB();
    void print();
}
#endif

TestLibB::print方法的函数体中调用了方法TestLibA::print();

#TestLibB.cpp
#include "TestLibB.h"
#include "TestLibA.h"
#include <QDebug>
TestLibB::TestLibB()
{
}

void TestLibB::print()
{
    qDebug()<<"print TestLibB";
    TestLibA testLibA;
    testLibA.print();
}

TestCallLib是一个应用程序,它会调用TestLibB::print方法。

编译的过程如下

  1. 我们首先编译TestLibA库,生成TestLibA.o文件,并打包成导出库TestLibA.a。
  2. 编译TestLibB库,由于调用了TestLibA::print方法,所以包含了TestLibA.h。

    注意:编译器只需要编译TestLibB.cpp成TestLibB.o文件,此时并未链接运行,所以不需要TestLibA::print的方法实现(TestLibA.o或TestLibA.a)。所以我们只包含TestLibA.h而不加载TestLibA.a,也能编译通过。

  3. TestCallLib编译时,我们首先链接TestLibB.a,TestLibB.a中并不包含调用的TestLibA::print的函数实现,即TestLibA.a,直接编译将会导致如下错误。

error: undefined reference to `TestLibA::TestLibA()'
error: undefined reference to 'TestLibA::print()'

所以我们还需要将TestLibA.a也链接到TestApp中,此时才能编译通过。
这就是常见的静态链接库依赖问题,我们加载一个静态库,同时还需要将其依赖的静态库,按顺序加载进APP的编译。测试环境QT5.10+QtCreator+MinGW。

根据符号名称,查询所在的系统链接库

静态库依赖一般还有下面一种情况,以libuv举例,编译静态库libuv.lib会使用一些系统方法,在使用libuv.lib时,如果忘记加载系统静态库,会报如下的错误:

libuv.lib(tty.obj):-1: error: LNK2019: 无法解析的外部符号
__imp__DispatchMessageA@4,该符号在函数
_uv__tty_console_resize_message_loop_thread@4 中被引用。

很多时候,我们并不知道DispatchMessageA到底是属于哪一个系统静态库,那么我们就需要复制这个函数名,然后到https://msdn.microsoft.com/去搜索该函数的相关介绍,及其所属库文件。如下图所示:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/tom06/article/details/80309864