Linux下C++的编译、链接以及包管理
前言
最近一段时间要设计一套,同时支持公司自动驾驶中间件和ROS的静态融合代码开发工作流。搞完之后,对Linux下C++的编译、链接以及包管理有了更深入的理解。所以认真搞一篇文章,记录分享一下。
主要围绕一个非常基础、非常关键、非常实用的问题,即如何在自己的程序中使用别人现成的代码?,从具体实践(而不是理论)的角度来展开。
最简单直观的做法当然是,别人写了一个很好用的函数,你拷贝过来粘到你的头文件里,然后在源文件中直接调用即可。编译、链接什么的问题,不存在!!!
但如果是100个、1000个函数呢?如果原作者不想公布源码把这些函数编成了库然后发布的呢?此时这个做法略显沙雕了,因为我不想把这么些个函数一一找到,然后再一个个复制粘贴过来,或者说根本没地方找源码。
当然了,如果这些函数作者是实现在头文件里的还好。在自己的cpp中把该包含的头文件包含进来,然后愉快的调用这些函数即可,同样不涉及太多的编译和链接问题。这就是现在比较多的header only模式,一些有名的库会提供这样的封装方式,比如boost_header_only。不过考虑到C++接口与实现相分离的原则、以及体积问题,绝大多数包还是以头文件+库的方式提供。
于是便有了包和链接的这一套机制。对于链接,理论部分看一下CSAPP第9章即可,实践部分暂时没啥要讲的。所以重点说说包的概念。
包是什么?
首先第一个问题,包在程序开发的语境下具体指什么?先上答案——大多数情况下指一个由库和头文件组成的文件夹。
安装一个包又意味着什么?
我们在ubuntu上通过sudo apt install
安装各种依赖,其实就是把这个文件夹从服务器上拷贝下来,然后库和头文件分别放到系统的特定目录下。这些特定目录就是类似这种的目录:
/usr/include
/usr/lib
/usr/local/include
/usr/local/lib
如何使用包?
安装好之后,马上面临另外一个问题,就是咋用?
- 其实Linux系统以及gcc编译器的开发者早就商量好了,(一定程度上)已经给你安排明白了。具体怎么安排的,看这里
- 或者你不放心、不想被安排,想主动地、明明白白地用它。那也简单,头文件和库安装的路径你都知道了,编译和链接的时候把这些路径指定好就可以了。
- 如果你的程序是直接在命令行调用gcc进行编译的,那么用
-I
和-l
就可以进行头文件和库文件路径的指定。 - 如果你是用CMake来管理编译过程,那么把头文件路径加到CMakeLists.txt中的
target_include_directories
命令中,把库的路径加到find_library
命令中,其实就可以了。
- 如果你的程序是直接在命令行调用gcc进行编译的,那么用
- 但是这样需要包的使用者安装之后先找到安装的位置,然后处理一串长长的路径,不够elegant,所以懒惰的程序员又搞了自动生成这些路径的机制:
- 命令行中调用gcc进行编译时,可以像这样
gcc -o main showPhoto.c 'pkg-config opencv4 --cflags --libs'
把路径的生成交给pkg-config。其背后的逻辑是原作者在封装包时同时准备了一个opencv4.pc
文件,pkg-cofig命令会到usr/lib/
和${PKG_CONFIG_PATH}
指定的路径下找这个文件,然后通过解析它来生成gcc要的东西。 - 如果你是用CMake,可以用CMake提供的配套解决方案,就是
find_package
机制。具体用法三两句说不清楚,详情看这里
- 命令行中调用gcc进行编译时,可以像这样
触类旁通1:源码安装(比如OpenCV)也是一样的道理,只不过是从服务器上拷下来的是源码和CMakeLists.txt,然后用本机的编译器编一下,最后还是
make install
到刚才说的那些系统特定目录中。触类旁通2:安装一个软件也是同理,只不过软件包一般没有头文件,但是会多一些可执行文件。这些可执行文件会被放到
**/bin
目录中,然后配合环境变量$PATH
,就可以愉快地使用软件了。
如何管理包?
首先定义什么叫做管理包?或者说为什么存在这样一个问题?
举两个可能不太严谨的例子,原作者选择将自己的源码用gcc8编译一下,然后再发布给别人用。但是你这边用的是gcc9编译器,这样链接的时候就有可能不兼容。
这还是小问题,更麻烦的是依赖!!!可以说谁搞谁头大,分分钟高血压。具体来讲,一位作者借助库A1.0写了个库B1.0,那么你想用库B1.0就得先把库A1.0准备好,版本还不能错。递归嵌套下来,你需要面对的就是一棵树,每个节点的版本,编译器信息什么的都要严丝合缝才行。
因此,就有了conan这样的包管理工具。具体怎么用,看这里
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!