用于库编译的C/C++约定/工具链

C / C++ conventions/toolchains for library compilation

本文关键字:C++ 约定 工具 编译 用于      更新时间:2023-10-16

C/C++的基本问题在于库编译例如,软件A使用库Z,因此在编译并随后使用和/或开发软件A之前,必须编译库Z。

在许多情况下,都有配置项目然后调用make+make-install的概念。例如,打开命令行并输入:

./configure
make
make install

./configure是放置在项目顶层目录中的shell脚本。我想它会检查系统中是否存在所有依赖项,并保存这些依赖项的路径。稍后,make可以利用这些收集的信息向编译器提供相应的包含路径和库位置(例如.so/.a文件的位置)。

make负责按照正确的顺序编译和链接源文件(如makefile所指定的,这些文件由I-dont-know生成,格式为XYZ)。当然,它本身并不编译/链接任何东西,而是调用实际的编译器和链接器来完成它的工作。

make install获取生成的二进制文件,并将它们放置在系统中的某个位置(例如,如果项目是库,则为/usr/lib;对于可执行文件,则为usr/bin)。如果手头的项目是一个库,那么它应该还会获取库的头文件并将其安装在系统中的某个位置。

这是一个相对复杂的过程;让我们使用CMI来表示这种类型的编译过程(CMI=configure make-install)。此外,CMI概念——据我所知——是Linux世界特有的。它在Windows上不能这样工作,例如,因为没有可以用来执行的shell/配置。make甚至可能仅限于gcc/g++,但我不知道情况是否如此。

最重要的是,我甚至不知道该在哪里查。我还想了解CMI概念是否支持同时安装不同版本的库。假设您是软件B和软件C的开发人员。无论出于何种原因,软件B和C都依赖于库Y,但B需要Y 1.0.x,C需要1.1.x。如果make-install将库的头文件放在系统上的某个位置,难道不会发生冲突吗?我再次问自己,我在哪里可以查到它?


让我们讨论一个示例库:libzip。主页没有说明支持或推荐什么编译器或平台。你现在将如何处理?

有趣的是,该页面声称MySQL Workbench正在使用libzip。MySQL Workbench也是为Windows提供的,所以我认为libzip可以在Windows上编译。

我还观察到,libzip附带了CMakeLists.txt配置脚本。甚至还有一个libzip.pc.inCMake模板,据说是用于pkg配置工具的。还有Makefile.am(不管是什么)和Makefile.in,据说是另一个CMake模板。最后但同样重要的是,我注意到一个文件夹m4和.m4文件(都在m4文件夹和项目的根文件夹中)。但我们不要忘记cmake-config.h.in,cmake-zipconf.h.in。

因此,如果你想编译libzip,你必须考虑以下替代方案:

  • 使用CMI概念
    • 不适用于Windows(对吗?)
  • 使用CMake,这是一个元构建系统
    • 那么您必须决定编译器/IDE CMake应该为:gcc生成什么?MSVC?Mingw还是QTSDK/Mingw?(不管有什么不同)
  • 也许用M4,不管是什么

M4似乎与GNU autoconf有关。我想我也可以把它添加到上面的列表中。

(附带说明:到目前为止,我已经尝试过使用CMake+VisualStudio2010的组合编译libzip。目前我正在修复各种编译错误。)


这是我的中心观察结果:

libzip是一个简单的库;只是一些拉链的东西。然而,编译涉及到太多的工具,这是一项极其困难的任务,即使对于高级程序员来说也是如此。

此外,这些工具中的大多数都缺乏文档(否则,为什么我有所有这些问题,不知道在哪里可以找到答案?)。更不用说,如果不在逆向工程中投入数小时来修复,大多数工具甚至无法工作,例如,有缺陷的CMake FindPackage脚本叹息


我可以这样持续几个星期。我迷失在众多的编译概念中,所有这些是如何相互关联的,它们与哪些平台和编译器配合得很好等等。

另一个例子:RetroShare。即使Windows的编译过程有文档记录,完成编译也是极其困难的。只要考虑一下,在Windows上编译RetroShare涉及QtSDK/MingW、Cygwin和MingW/MSYS,所有这些都适用于不同的部分/依赖项。这些工具是如何协同工作的?

我完全迷失了方向,我希望你告诉我你是如何处理这类问题的,以及考虑到所有这些工具/工具链/编译器/平台,你是如何保护你的大脑免受严重损害的。

你们是非常聪明还是我非常愚蠢?为什么这件事如此复杂

"我可以这样持续几周。">

你听起来确实有点困惑。我将谈几点具体问题。

"配置-制造-安装"过程特别使用make,这是一种更通用的工具。也就是说,make和makefile可以用在其他方面。记住这一点。

"make负责编译和链接正确的顺序(由生成的makefile指定我不知道并且具有XYZ格式)。">

你迟早要学会自己编写makefile。Make是一个构建系统,对于C/C++程序员来说,它是一个非常有用的、近乎强制性的工具。如果您使用IDE,它可能已经在为您创建生成文件。下面是一个为一个小项目手工编写的makefile示例:

wx = `wx-config --cxxflags --libs`
test1: main.cpp main.h window.o
g++ -Wall -g main.cpp window.o -o test1 $(wx)
window.o: window.cpp window.h
g++ -Wall -g -c window.cpp -o window.o $(wx)

第一行定义了一个变量,链接器的一些标志,之后会使用两次。如果您在命令行中使用gcc,那么接下来的两位应该很熟悉。要在没有make的情况下构建此项目,您需要先通过g++ ...,然后通过test1编译window.o。有了makefile,您所要做的就是运行make。在项目中再添加一些对象(.o)文件,它开始显得非常方便。此外,您还可以将不同的">目标"写入一个生成文件中。有各种各样的制作教程,GNU版本的官方文档:

http://www.gnu.org/software/make/manual/make.html

这并不难弄清楚。

"make-install获取生成的二进制文件并将其放置系统中的某个位置">

make install是一个目标,通常在configure make install上下文中使用的makefile中定义它。你可以在上面的makefile中添加这样一个东西:

install: test1
cp test1 /usr/local/bin/

冒号后与目标位于同一行的内容都是先决条件——它指的是必须存在于生成树中的文件(或必须运行的另一个目标指令)。如果文件不存在(或者其某些先决条件自生成以来发生了更改),并且有一个具有相同名称的目标(在本例中,test1——也可以查看以前的先决条件),则首先运行该目标指令。

"此外,CMI概念——据我所知——是特定于Linux世界。">

没有,但它与windows世界有点不同。这有时与自动工具有关,后者可用于生成配置脚本和相应的生成文件。请注意,如果安装了mingw,则可以在windows上使用CMI包。

"使用CMake,这是一个元构建系统">

CMake本质上与make相同,只是不同。make只有在makefile中显式调用时才使用gcc;makefile可以用来做shell脚本所能做的任何事情,包括运行编译器等。CMake希望变得更便携/更热衷于平台,也许对用户友好。有些人更喜欢它。

"如果make-install将库的头文件放在系统上的某个位置,难道不会发生冲突吗?">

理想情况下,没有。自动工具("CMI")设置的部分目的是允许打包程序实现处理此类问题的机制(如果存在)。可以安装同一库的多个版本。WRT头,如果这些改变,它们(希望)保持向后兼容,就像库本身一样。如果没有,应该有一些明确的指示("版本2与版本1不兼容!"),当这种情况发生时,任何有头脑的人都会从一开始就有版本2的不同标题,并在API中引用。

了解使用什么也很有帮助:http://www.elpauer.org/stuff/learning_cmake.pdf