使用 Conan 依赖构建一个简单的 Autotools 项目

警告

此示例仅适用于 Linux 和 OSX 环境,不支持 Windows 直接运行,包括 msys2/cygwin 子系统。但是,由于 Windows Subsystem for Linux (WSL) 提供了 Linux 环境,因此应该可以工作。虽然 Conan 为 Autotools 在 Windows 环境中提供了一定程度的支持(通过 win_bash = True),但这在本教程中不适用。

在此示例中,我们将创建一个字符串格式化应用程序,该应用程序使用了最流行的 C++ 库之一:fmt

我们将使用 Autotools 作为构建系统,并使用 pkg-config 作为辅助工具,因此在继续本示例之前,您应该先在 Linux 和 Mac 上安装它们。

请先克隆源代码以重现此项目。您可以在 GitHub 上的 examples2 仓库 中找到它们。

git clone https://github.com/conan-io/examples2.git
cd examples2/examples/tools/autotools/autotoolstoolchain/string_formatter

我们从一个非常简单的 C++ 项目开始,其结构如下

.
├── configure.ac
├── Makefile.am
├── conanfile.txt
└── src
    └── main.cpp

此项目包含一个基本的 configure.ac <https://gnu.ac.cn/software/autoconf/manual/autoconf-2.60/html_node/Writing-configure_002eac.html>_ 文件,其中包括 fmt 的 pkg-config 依赖以及字符串格式化程序在 main.cpp 中的源代码。

让我们看看 main.cpp 文件,它只打印一个简单的消息,但使用了 fmt::print 方法。

main.cpp
#include <cstdlib>
#include <fmt/core.h>

int main() {
    fmt::print("{} - The C++ Package Manager!\n", "Conan");
    return EXIT_SUCCESS;
}

configure.ac 文件使用 AC_PROG_CXX 宏检查 C++ 编译器,并使用 PKG_CHECK_MODULES 宏检查 fmt.pc pkg-config 模块。

configure.ac
AC_INIT([stringformatter], [0.1.0])
AM_INIT_AUTOMAKE([1.10 -Wall no-define foreign])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_FILES([Makefile])
PKG_CHECK_MODULES([fmt], [fmt])
AC_PROG_CXX
AC_OUTPUT

Makefile.am 文件指定 string_formatter 是预期的可执行文件,并且应链接到 fmt 库。

Makefile.am
AUTOMAKE_OPTIONS = subdir-objects
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}

bin_PROGRAMS = string_formatter
string_formatter_SOURCES = src/main.cpp
string_formatter_CPPFLAGS = $(fmt_CFLAGS)
string_formatter_LDADD = $(fmt_LIBS)

conanfile.txt 文件看起来很简单,它只安装了 fmt 包并使用两个生成器来构建我们的项目。

conanfile.txt
[requires]
fmt/9.1.0

[generators]
AutotoolsToolchain
PkgConfigDeps

在本例中,我们将使用 PkgConfigDeps 来生成关于 fmt 库文件安装位置的信息(通过 *.pc 文件),并使用 AutotoolsToolchain 通过 conanbuild[.sh|.bat] 文件(描述编译环境)将构建信息传递给 autotools

我们将使用 Conan 来安装 fmt 库,为 Autotools 生成一个工具链,并生成 .pc 文件以便 pkg-config 找到 fmt

在 Linux 和 macOS 上构建

首先,我们应该安装一些必要的依赖。在 Linux 上,你需要安装 automakepkgconfmake 包,它们的包名可能会因 Linux 发行版而异,但本质上,它们应该包含构建以下示例所需的所有工具(aclocal, automake, autoconf 和 make)。

在本例中,我们不考虑特定的 Conan profile,但 fmt 与许多不同的配置高度兼容。因此,它主要适用于 GCC 和 Clang 编译器的版本。

第一步,我们应该安装 conanfile.txt 中列出的所有依赖。命令 :ref: conan install<reference_commands_install> 不仅会安装 fmt 包,而且在您的 profile 与远程仓库中的预构建二进制文件不匹配时,还会从源代码构建它。此外,它还会提供 conanfile.txt 中列出的这些生成器。

conan install . --build=missing

运行 conan install 命令后,string_formatter 文件夹中应该会出现新文件

└── string_formatter
    ├── Makefile.am
    ├── conanautotoolstoolchain.sh
    ├── conanbuild.conf
    ├── conanbuild.sh
    ├── conanbuildenv-release-armv8.sh
    ├── conanfile.txt
    ├── conanrun.sh
    ├── conanrunenv-release-armv8.sh
    ├── configure.ac
    ├── deactivate_conanbuild.sh
    ├── deactivate_conanrun.sh
    ├── fmt-_fmt.pc
    ├── fmt.pc
    ├── run_example.sh
    └── src
        └── main.cpp

这些文件是由 conanfile.txt 中列出的那些生成器产生的。一旦生成了构建示例所需的所有文件并安装了 fmt,现在我们可以加载脚本 conanbuild.sh

source conanbuild.sh

conanbuild.sh 是由 VirtualBuildEnv 生成的默认文件,它帮助我们加载其他脚本文件,这样我们就无需手动执行更多步骤来加载每个生成器文件。它会加载由 AutotoolsToolchain 生成的 conanautotoolstoolchain.sh 文件,该文件根据我们在运行 conan install 命令时使用的 Conan profile 定义了环境变量。这些配置的环境变量与编译器和 autotools 有关,例如 CFLAGSCPPFLAGSLDFLAGSPKG_CONFIG_PATH

下一步,我们可以按顺序运行以下命令来配置项目

aclocal
automake --add-missing
autoconf
./configure

aclocal 命令将读取 configure.ac 文件并生成一个名为 aclocal.m4 的新文件,该文件包含 automake 所需的宏。第二步,automake 命令将读取 Makefile.am,并生成 Makefile.in 文件。然后,autoconf 命令将使用这些文件并生成 configure 文件。一旦我们运行 configure,所有环境变量都将被使用。由于 autotools 使用自定义的 PKG_CONFIG_PATH 来查找 fmt.pc,所以 fmt.pc 在这一步也会被加载。

然后,最后,我们可以构建项目以生成字符串格式化程序应用程序。现在我们运行 make 命令,该命令将使用由 autotools 生成的 Makefile

make

make 命令将读取 Makefile 并调用编译器,然后构建 main.cpp,在同一文件夹中生成可执行文件 string_formatter

./string_formatter
Conan - The C++ Package Manager!

最终的输出是一个新应用程序的结果,它在 fmt 库的帮助下打印一条消息,并由 Autotools 构建。