Linux下C++程序的编译链接与运行
C++ 程序的编译链接有时候会很复杂,特别是各种链接错误,这里我总结一下相关的知识点。
编译
编译是将源文件转化为目标文件的过程。一个源文件(.cpp)对应一个目标文件(.o)。
g++在默认情况下是直接将编译和链接一起做了,产生最终的可执行文件,过程中产生的.o文件会被删除。如果只编译不链接,可以加上-c参数。编译单个文件的一个作用是可以在整个程序没有完成的情况下,检查当前文件有没有编译错误。
g++ -c main.cpp #生成main.o
g++ -c test.cpp #生成test.o
如果源文件中引用了第三方的头文件,则需要指明头文件的搜索路径。
g++对头文件的搜索顺序是:
- 源文件所在目录,必须是
#include "header.h"
形式,如果是#include <header.h>
则不会搜索本地目录 - -I参数指定的目录,多个-I按出现的顺序搜索
- 环境变量
CPLUS_INCLUDE_PATH
(C语言是C_INCLUDE_PATH
)指定的目录,: 分割多个路径 - 标准系统目录,包括操作系统头文件和编译器自带的头文件。可以使用
g++ -xc++ -E -v -
命令查看当前search path
链接
将目标文件(.o)和库文件合并生成最终的可执行文件。
g++ main.o test.o
如果用到了第三方的库,则需要用参数-l
指定库名。这里的库包括动态链接库和静态链接库,优先查找动态库,没有则找静态库。例如,-lopenssl
,则查找的库文件为libopenssl.so和libopenssl.a,搜索的路径如下:
-Llibpath
参数指定的库路径- 环境变量
LIBRARY_PATH
指定的目录,: 分割多个路径 - 系统默认的库目录,
/lib、/lib64、/usr/lib、/usr/lib64
等
运行
运行时主要涉及到动态链接库的搜索,运行时对动态链接库的搜索顺序如下:
- 在编译目标代码时所传递的动态库搜索路径(注意,这里指的是通过
-Wl,rpath=<path1>:<path2>
或-R
选项传递的运行时动态库搜索路径,而不是通过-L
选项传递的) - 环境变量
LD_LIBRARY_PATH
指定的动态库搜索路径 - 配置文件
/etc/ld.so.conf
中所指定的动态库搜索路径(更改/etc/ld.so.conf
之后,一定要执行命令ldconfig
,该命令会将/etc/ld.so.conf
文件中所有路径下的库载入内存) - 系统默认的库目录,
/lib、/lib64、/usr/lib、/usr/lib64
等
-Wl,rpath
加上-Wl,-rpath
选项的作用就是指定程序运行时的库搜索目录。例如,将当前路径加入程序运行时的库搜索目录:
g++ -Wl,-rpath=`pwd` main.o -L. -ladd -o app
pkg-config
pkg-config
在编译应用程序和库的时候作为一个工具来使用,可以帮助你插入正确的编译选项。
例如,程序中使用了openssl这个库,又不知道头文件和库文件目录在哪,就可以这样用:
gcc -o test test.c `pkg-config --libs --cflags openssl`
--cflags
一般用于指定头文件,--libs
一般用于指定库文件。
pkg-config
是需要配置的。一个.pc
文件,包含了库的信息,放置在pkg-config
的搜索路径下,默认的路径是/usr/lib64/pkgconfig/
,还可以通过PKG_CONFIG_PATH
环境变量来指定pkg-config还应该在哪些地方去寻找.pc文件。