Qt学习记录——编译库、添加库的相关操作

静态库和动态库的概念和区别:

一、什么是库:库是可执行代码的二进制形式,可以被操作系统载入内存执行,分为静态库和动态库

二、库的编译:

  • 静态库的编译过程:源代码->-目标文件>静态库

例:(linux命令行执行):

g++ -c StaticMath.cpp    //注意参数-c,生成目标文件StaticMath.o,是预编译、编译、汇编的过程

ar -crv libstaticmath.a StaticMath.o  //linux系统用ar命令,是编号、索引、压缩打包的过程

例:(在安装了VS的windows命令行执行,复杂的最好在VS里编译):

cl /c StaticMath.cpp     //创建名为“StaticMath.obj”的目标文件

lib StaticMath.obj    //创建静态库StaticMath.lib

静态库的链接:链接静态库编译生成的可执行文件中包含了被引用的库中的可执行代码。因此程序运行时不再需要原库文件。

  • 动态库的编译过程:源代码->-目标文件>动态库

g++ -fPIC -c DynamicMath.cpp  //-fPIC 创建与地址无关的编译程序(pic,position independent code),为应用程序间能共享。

g++ -shared -o libdynmath.so DynamicMath.o  //生成动态库,此时要加链接器选项-shared

(合并为一行命令使用:g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp)

windows下比较麻烦,在VS里编译。

动态库的链接:程序运行时需要原库文件的支持。

  • 这里特别要举例说一下为Android APP编译动、静态库的操作:

编译环境:64位windows7,NDK,Qt

编译工具NDK:下载解压,可以在build目录里找到ndk-build.cmd,添加包含ndk-build.cmd路径如:D:\ndk\build

要编译的库源码:libusb,网上下载,解压,查看目录,其中有个android\jni目录

具体操作演示(执行cmd打开windows命令行):

d:\>cd libusb\android\jni

d:\libusb\android\jni>set path=D:\ndk\build  //如果后续操作出错,就在windows系统变量PATH里添加这个路径

d:\libusb\android\jni>ndk-build

编译生成的文件在当前目录的lib目录里,.so文件

修改libusb.mk文件,编译静态库或动态库:obj目录里的,.a文件

# 用于生成动态库
# include $(BUILD_SHARED_LIBRARY)

# 用于生成静态库
include $(BUILD_STATIC_LIBRARY)

二、库文件的文件名规则:(静态库.a、.lib,动态库.so、.dll)

linux:.a、.so

windows::.lib、.dll

特别的,linux的库文件名命名规则:

库文件名:是包含前缀lib以及后缀.a或者.so

库名是去掉前缀和后缀剩下的部分

静态库文件名:lib库名.a,例如:libusb.a

动态库文件名:lib库名.so,例如:libusb.so

库的调用:

Linux:在代码文件里添加库的头文件.h,编译的时候,指定库的搜索路径、指定库名。

操作实例:链接的库文件是:libusb.a,头文件是:libusb.h

代码文件.CPP:#include "libusb.h"

命令行:# g++ TestStaticLibrary.cpp -L../StaticLibrary -lusb

参数说明:

-L:要连接的库所在目录

-l库名,注意是库名,链接时会自动加上前缀和后缀,即在给出的库名前面加上lib,后面加上.a或.so来确定库的文件名。

Qt引用外部库的方法:

一、在代码文件cpp里添加引用的头文件:#include "头文件"

二、在工程文件pro里添加里引用库:右击工程名,选“添加库”,进入添加库的操作,选“外部库“之后按提示操作。

Qt学习记录——编译库、添加库的相关操作_第1张图片

错误:error: No rule to make target 'D:/Documents/myapp/temp/../liblibusb1.0.a', needed by 'debug/temp.exe'.  Stop.

原因:是Qt的一个bug

解决办法:查看pro文件,删除多余的字符“lib

  • #include<>和#include""的区别:

引用系统标准库用:#include<头文件.h>,编译器只查找标准头文件目录

引用自建库(外部库)用:#include"头文件.h" ,编译器先查找当前目录是否有指定名称的头文件,然后在从标准头文件目录中查找

引用动态库编译成可执行文件跟引用静态库的操作是一样的,但是生成的可执行文件不一样,引用动态库的可执行文件在运行时需要能调用到相关动态库文件。这就为什么在windows下复制一个可执行文件的同时还要复制相关的dll文件才能运行的原因。

g++(gcc)编译选项

l  -shared :指定生成动态链接库。

l  -static :指定生成静态链接库。

l  -fPIC :表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码, 念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。

l  -L. :表示要连接的库所在的目录。

l  -l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a/.so来确定库的名称。

l  -Wall :生成所有警告信息。

l  -ggdb :此选项将尽可能的生成gdb 的可以使用的调试信息。

l  -g :编译器在编译的时候产生调试信息。

l  -c :只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件) 。

l  -Wl,options :把参数(options)传递给链接器ld 。如果options 中间有逗号,就将options分成多个选项,然后传递给链接程序。

nm命令

有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种:

l  一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;

l  一种是库中定义的函数,用T表示,这是最常见的;

l  一种是所谓的弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。

$nm libhello.h

ldd命令

ldd命令可以查看一个可执行程序依赖的共享库,例如我们编写的四则运算动态库依赖下面这些库:

 

 

内部库、外部库、系统库

QT  +=core gui

1.添加库文件静态库
linux:LIBS += your_lib_path/your_lib动态库
linux:LIBS += -L your_lib_path -lyour_lib//经过测试了
win32:LIBS += your_lib_path/your_lib例如:
LIBS += -L lib/pcsc/ -lpcsclite
LIBS += lib/pcsc/libpcsclite.a
2.添加头文件
INCLUDEPATH += your_include_path例如:
INCLUDEPATH += . /usr/local/include(点号后面有空格)
3.添加要编译的源文件和头文件
SOURCES:所有源文件列表
HEADERS:所有头文件列表
FORMS:所有.ui文件列表前期工作:

命令行编译参数 gcc windowInfo.cpp pkg-config –cflags –libs libwnck-1.0
.pro文件设置 
- GCONFIG +=libwnck-1.0
- CONFIG +=c++11 link_pkgconfig

你可能感兴趣的:(qt,android,qt)