使用 Conan 构建一个简单的 CMake 项目¶
让我们从一个例子开始:我们将创建一个字符串压缩应用程序,该应用程序使用最流行的 C++ 库之一:Zlib。
在这种情况下,我们将使用 CMake 作为构建系统,但请记住,Conan 适用于任何构建系统,不限于使用 CMake。您可以在 阅读更多部分 中查看更多其他构建系统的示例。
请先克隆源代码以重现此项目,您可以在 GitHub 的 examples2 仓库 中找到它们
$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/tutorial/consuming_packages/simple_cmake_project
我们从一个非常简单的 C 语言项目开始,结构如下
.
├── CMakeLists.txt
└── src
└── main.c
该项目包含一个基本的 CMakeLists.txt,其中包含 zlib 依赖项以及字符串压缩程序在 main.c 中的源代码。
让我们看一下 main.c 文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <zlib.h>
int main(void) {
char buffer_in [256] = {"Conan is a MIT-licensed, Open Source package manager for C and C++ development "
"for C and C++ development, allowing development teams to easily and efficiently "
"manage their packages and dependencies across platforms and build systems."};
char buffer_out [256] = {0};
z_stream defstream;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = (uInt) strlen(buffer_in);
defstream.next_in = (Bytef *) buffer_in;
defstream.avail_out = (uInt) sizeof(buffer_out);
defstream.next_out = (Bytef *) buffer_out;
deflateInit(&defstream, Z_BEST_COMPRESSION);
deflate(&defstream, Z_FINISH);
deflateEnd(&defstream);
printf("Uncompressed size is: %lu\n", strlen(buffer_in));
printf("Compressed size is: %lu\n", strlen(buffer_out));
printf("ZLIB VERSION: %s\n", zlibVersion());
return EXIT_SUCCESS;
}
此外,CMakeLists.txt 的内容是
cmake_minimum_required(VERSION 3.15)
project(compressor C)
find_package(ZLIB REQUIRED)
add_executable(${PROJECT_NAME} src/main.c)
target_link_libraries(${PROJECT_NAME} ZLIB::ZLIB)
我们的应用程序依赖于 Zlib 库。 Conan 默认情况下会尝试从名为 ConanCenter 的远程服务器安装库。 您可以在那里搜索库并检查可用的版本。 在我们的例子中,在检查 Zlib 的可用版本后,我们选择使用最新版本之一:zlib/1.3.1。
安装 Zlib 库并使用 conanfile.txt 文件从我们的项目中找到它最简单的方法。 让我们创建一个包含以下内容的文件
[requires]
zlib/1.3.1
[generators]
CMakeDeps
CMakeToolchain
如您所见,我们使用类似于 INI 文件的语法将两个部分添加到此文件中。
[requires] 部分是我们声明要在项目中使用的库的地方,在本例中为 zlib/1.3.1。
[generators] 部分告诉 Conan 生成编译器或构建系统将用于查找依赖项和构建项目的的文件。 在这种情况下,由于我们的项目基于 CMake,我们将使用 CMakeDeps 生成有关 Zlib 库文件安装位置的信息,并使用 CMakeToolchain 通过 CMake 工具链文件将构建信息传递给 CMake。
除了 conanfile.txt 之外,我们还需要一个 Conan profile 来构建我们的项目。 Conan profile 允许用户为编译器、构建配置、体系结构、共享或静态库等定义配置集。 Conan 默认情况下不会自动检测 profile,因此我们需要创建一个。 为了让 Conan 尝试根据当前操作系统和已安装的工具猜测 profile,请运行
conan profile detect --force
这将检测操作系统、构建体系结构和编译器设置,基于环境。 它还会默认将构建配置设置为 Release。 生成的 profile 将存储在 Conan 主文件夹中,名称为 default,并且除非通过命令行指定另一个 profile,否则 Conan 将在所有命令中默认使用它。 此命令在 macOS 上的输出示例是
$ conan profile detect --force
Found apple-clang 14.0
apple-clang>=13, using the major as version
Detected profile:
[settings]
arch=x86_64
build_type=Release
compiler=apple-clang
compiler.cppstd=gnu17
compiler.libcxx=libc++
compiler.version=14
os=Macos
注意
关于 Conan 检测到的 C++ 标准的说明
Conan 始终将默认 C++ 标准设置为检测到的编译器版本默认使用的标准,除非 macOS 使用 apple-clang。 在这种情况下,对于 apple-clang>=11,它设置 compiler.cppstd=gnu17。 如果您想使用不同的 C++ 标准,可以编辑默认 profile 文件。 首先,使用以下命令获取默认 profile 的位置
$ conan profile path default
/Users/user/.conan2/profiles/default
然后打开并编辑该文件,并将 compiler.cppstd 设置为您想要使用的 C++ 标准。
注意
使用与自动检测的不同编译器
如果您想更改 Conan profile 以使用与默认编译器不同的编译器,则需要更改 compiler 设置,并使用 tools.build:compiler_executables 配置 显式告诉 Conan 在哪里找到它。
我们将使用 Conan 安装 Zlib 并生成 CMake 需要查找此库和构建我们的项目的文件。 我们将在 build 文件夹中生成这些文件。 为此,请运行
$ conan install . --output-folder=build --build=missing
您将获得类似于以下内容的输出
$ conan install . --output-folder=build --build=missing
...
-------- Computing dependency graph ----------
zlib/1.3.1: Not found in local cache, looking in remotes...
zlib/1.3.1: Checking remote: conancenter
zlib/1.3.1: Trying with 'conancenter'...
Downloading conanmanifest.txt
Downloading conanfile.py
Downloading conan_export.tgz
Decompressing conan_export.tgz
zlib/1.3.1: Downloaded recipe revision f1fadf0d3b196dc0332750354ad8ab7b
Graph root
conanfile.txt: /home/conan/examples2/tutorial/consuming_packages/simple_cmake_project/conanfile.txt
Requirements
zlib/1.3.1#f1fadf0d3b196dc0332750354ad8ab7b - Downloaded (conancenter)
-------- Computing necessary packages ----------
Requirements
zlib/1.3.1#f1fadf0d3b196dc0332750354ad8ab7b:cdc9a35e010a17fc90bb845108cf86cfcbce64bf#dd7bf2a1ab4eb5d1943598c09b616121 - Download (conancenter)
-------- Installing packages ----------
Installing (downloading, building) binaries...
zlib/1.3.1: Retrieving package cdc9a35e010a17fc90bb845108cf86cfcbce64bf from remote 'conancenter'
Downloading conanmanifest.txt
Downloading conaninfo.txt
Downloading conan_package.tgz
Decompressing conan_package.tgz
zlib/1.3.1: Package installed cdc9a35e010a17fc90bb845108cf86cfcbce64bf
zlib/1.3.1: Downloaded package revision dd7bf2a1ab4eb5d1943598c09b616121
-------- Finalizing install (deploy, generators) ----------
conanfile.txt: Generator 'CMakeToolchain' calling 'generate()'
conanfile.txt: Generator 'CMakeDeps' calling 'generate()'
conanfile.txt: Generating aggregated env files
如输出所示,发生了一些事情
Conan 从远程服务器安装了 Zlib 库,如果库可用,该服务器应该是 Conan Center 服务器。 该服务器存储 Conan 配方(定义如何构建库的文件)和可以重用的二进制文件,因此我们不必每次都从源代码构建。
Conan 在 build 文件夹下生成了几个文件。 这些文件是由我们在 conanfile.txt 中设置的
CMakeToolchain和CMakeDeps生成器生成的。CMakeDeps生成文件,以便 CMake 找到我们刚刚下载的 Zlib 库。 另一方面,CMakeToolchain生成 CMake 的工具链文件,以便我们可以使用与默认 profile 中检测到的相同设置使用 CMake 透明地构建我们的项目。
现在我们准备构建和运行我们的 compressor 应用程序了
$ cd build
# assuming Visual Studio 15 2017 is your VS version and that it matches your default profile
$ cmake .. -G "Visual Studio 15 2017" -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"
$ cmake --build . --config Release
...
[100%] Built target compressor
$ Release\compressor.exe
Uncompressed size is: 233
Compressed size is: 147
ZLIB VERSION: 1.3.1
$ cd build
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
$ cmake --build .
...
[100%] Built target compressor
$ ./compressor
Uncompressed size is: 233
Compressed size is: 147
ZLIB VERSION: 1.3.1
请注意,CMakeToolchain 可能会生成 CMake preset 文件,允许使用现代 CMake (>=3.23) 的用户使用 cmake --preset 代替传递工具链文件参数。 请参阅 使用 CMake preset 构建