1. Build a simple CMake project using Conan
首先创建一个使用最流行的 C++ 库之一 Zlib 的字符串压缩器应用程序,教程将使用 CMake 构建系统,但需要注意 Conan 适用于任何系统构建方式。 为了完成教程,首先下载对应的项目:
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 会尝试从远程服务器安装对应的库。安装 Zlib 库并从项目中找到它的最简单方法是使用 conan.txt 文件,文件内容如下所示:
# 声明使用的库
[requires]
zlib/1.2.11
# 指定生成器
[generators]
CMakeDeps
CMakeToolchain
除了 connfile.txt,项目还需要一个 Conan 配置文件来构建项目。Conan 配置文件允许用户为编译器、构建配置、架构、共享或静态库等定义配置集。默认情况下,Conan 不会尝试自动检测配置文件,因此需要创建一个。为了让 Conan 根据当前的操作系统和安装的工具猜测配置文件,需要运行下面的代码:
conan profile detect --force
这将根据环境检测操作系统、构建架构和编译器设置。默认情况下,它还将构建配置设置为Release。生成的配置文件将以默认名称存储在Conan主文件夹中,默认情况下Conan将在所有命令中使用该配置文件,除非通过命令行指定了另一个配置文件。
项目将使用 Conan 安装 Zlib 并生成 CMake 查找此库和构建项目所需的文件。为了在 build 文件夹中生成这些文件需要运行下面的代码:
conan install . --output-folder=build --build=missing
从输出中可以发现:(1)Conan 从远程服务器下载了 Zlib 库,此服务器存储 Conan recipes 和可重用的二进制文件,因此不需要每次都从源代码构建;(2)Conan 再 build 文件夹下生成了几个文件,这些文件是由 conanfile.txt 中设置的 CMakeToolchain 和 CMakeDeps 生成的。
完成应用程序 TPL 的安装后,可以对应用程序进行构建和运行,对于 Linux 构建和运行代码如下所示:
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
执行 compressor 可得到下面的结果:
2. Using build tools as Conan packages
上一个示例构建了一个 CMake 项目,并使用Conan 安装和定位 Zlib 库。上一个示例使用已经安装在系统中的 CMake 来构建项目,本示例将通过特定版本的 CMake 来构建项目。在这种情况下,Conan 可以是哟个名为 tool_requires 的需求类型声明此依赖关系,下面将通过本示例进行说明该用法。
首先创建一个使用最流行的 C++ 库之一 Zlib 的字符串压缩器应用程序,教程将使用 CMake 构建系统,但需要注意 Conan 适用于任何系统构建方式。 为了完成教程,首先下载对应的项目:
git clone https://github.com/conan-io/examples2.git
cd examples2/tutorial/consuming_packages/tool_requires
教程从一个非常简单的C语言项目开始,其结构如下:
.
├── CMakeLists.txt
└── src
└── main.c
该示例与上一个示例的主要区别在于 conanfile.txt 文件中添加了 [tool_requires] 部分,该文件内容如下所示:
[requires]
zlib/1.2.11
[tool_requires]
cmake/3.22.6
[generators]
CMakeDeps
CMakeToolchain
该实例在 CMakeLists.txt 中添加一条消息,以输出 CMake 版本,该文件内容如下所示:
cmake_minimum_required(VERSION 3.15)
project(compressor C)
find_package(ZLIB REQUIRED)
message("Building with CMake version: ${CMAKE_VERSION}")
add_executable(${PROJECT_NAME} src/main.c)
target_link_libraries(${PROJECT_NAME} ZLIB::ZLIB)
与上一个示例类似,本示例将使用 Conan 安装 Zlib 和 CMake 3.22.6,并生成可执行文件,这一步需要执行的代码如下:
conan install . --output-folder=build --build=missing
通过上述指令, Conan 成功生成一个名为 conanbuild.sh/bat 的新文件,该文件为 conan.txt 中声明 tool_requires 时自动调用 VirtualBuildEnv 生成器的结果。此文件设置了一些环境变量,例如一个新的PATH。为了使用特定版本的 CMake,需要执行下面的代码:
cd build
source conanbuild.sh
执行上述指令后,检查 CMake 版本如下图所示:
可以发现,在激活环境后,CMake v3.22.6 二进制文件夹被添加到路径中,现在是当前活动的版本。这时可以直接通过这个版本的 CMake 来构建项目,需要执行的指令如下所示:
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
如果需要恢复到默认的 CMake 版本,需要执行 build 目录下的 deactivate_conanbuild.sh/bat 脚本,需要执行的代码如下所示:
source deactivate_conanbuild.sh
执行上述指令后,检查 CMake 版本如下图所示:
3. Building for multiple configurations: Release, Debug, Static and Shared
首先创建一个使用最流行的 C++ 库之一 Zlib 的字符串压缩器应用程序,教程将使用 CMake 构建系统,但需要注意 Conan 适用于任何系统构建方式。 为了完成教程,首先下载对应的项目:
git clone https://github.com/conan-io/examples2.git
cd examples2/tutorial/consuming_packages/different_configurations
之前的示例介绍了如何构建一个依赖于 zlib 库的简单 CMake 项目,并了解了 tool_requires。这两个示例都没有指定要在发布或调试模式下构建应用程序,也没有指定是否要静态链接或共享库。如果没有另行指示,Conan 将使用默认配置文件中声明的默认配置。可以通过指令 "conan config home" 定位 Conan 用户主页:
Conan 主页中的 profile 目录下的 default 文件如下所示:
[settings]
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=7
os=Linux
其中,setting 部分包含有关操作系统、体系结构、编译器以及构建配置等信息。当调用设置-- profile 参数的 Conan 命令时,Conan 将从配置文件中获取所有信息,并将其应用于要构建或安装的包。如果不指定该参数,则相当于使用--profile=default调用它,即下面两个命令的效果是相同的:
conan install . --build=missing
conan install . --build=missing --profile=default
可以存储不同的配置文件,并使用它们为不同的设置进行构建,首先要创建对应的配置文件,其内容如下所示:
[settings]
arch=x86_64
build_type=Debug
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=7
os=Linux
修改上述文件之后,可以通过下面的指令来安装应用程序的依赖:
conan install . --output-folder=build --build=missing --settings=build_type=Debug
这时可以直接通过这个版本的 CMake 来构建项目,需要执行的指令如下所示:
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug
cmake --build .
到目前位置,示例一直在应用程序中静态链接 zlib。可以通过使用 --option 参数将共享选项设置为 true,如下所示:
conan install . --output-folder=build --build=missing --options=zlib/1.2.11:shared=True
通过上述代码,Conan 将安装 zlib 共享库,生成使用它们构建的文件,以及在运行应用程序时定位的这些动态库所需的文件。这时可以直接通过这个版本的 CMake 来构建项目,需要执行的指令如下所示:
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug
cmake --build .
在运行可执行文件之前需要首先运行下面的脚本:
source conanrun.sh
运行可执行文件之后需要运行下面的脚本:
source deactivate_conanrun.sh
4. Understanding the flexibility of using conanfile.py vs conanfile.txt
之前的示例通过 conanfile.txt 来声明依赖关系。对于更复杂的依赖关系,可以通过 conanfile.py 来声明依赖关系,本实例将介绍如何完成这一的依赖声明。
首先创建一个使用最流行的 C++ 库之一 Zlib 的字符串压缩器应用程序,教程将使用 CMake 构建系统,但需要注意 Conan 适用于任何系统构建方式。 为了完成教程,首先下载对应的项目:
git clone https://github.com/conan-io/examples2.git
cd examples2/tutorial/consuming_packages/conanfile_py
教程从一个非常简单的C语言项目开始,其结构如下:
.
├── CMakeLists.txt
├── conanfile.py
└── src
└── main.c
与 conanfile.txt 等价的 conanfile.py 如下所示:
from conan import ConanFile
class CompressorRecipe(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
def requirements(self):
self.requires("zlib/1.2.11")
def build_requirements(self):
self.tool_requires("cmake/3.22.6")
这时可以直接通过这个版本的 CMake 来构建项目,需要执行的指令如下所示:
conan install . --output-folder=build --build=missing
cd build
source conanbuild.sh
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
conanfile.py 除了可以完成 conan.txt 可以完成的任务,还能进一步实现项目结构的定义。
5. How to cross-compile your applications using Conan: host and build contexts
首先创建一个使用最流行的 C++ 库之一 Zlib 的字符串压缩器应用程序,教程将使用 CMake 构建系统,但需要注意 Conan 适用于任何系统构建方式。 为了完成教程,首先下载对应的项目:
git clone https://github.com/conan-io/examples2.git
cd examples2/tutorial/consuming_packages/cross_building
Conan 可以使用两个不同的配置文件构建应用于不同普通的应用程序,例如,一个应用于 Ubuntu Linux,另一个应用于 Raspberry Pi。为了实现上述目的,需要准备两个 profiles 。
# default
[settings]
os=Linux
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=9
# raspberry
[settings]
os=Linux
arch=armv7hf
compiler=gcc
build_type=Release
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=9
[buildenv]
CC=arm-linux-gnueabihf-gcc
CXX=arm-linux-gnueabihf-g++
LD=arm-linux-gnueabihf-ld
之后需要 修改conanfile.py,如下所示:
from conan import ConanFile
from conan.tools.cmake import cmake_layout
class CompressorRecipe(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
def requirements(self):
self.requires("zlib/1.2.11")
def build_requirements(self):
self.tool_requires("cmake/3.22.6")
def layout(self):
cmake_layout(self)
除此之外,为了实现 ARM 应用程序的顺利构建,需要在 Ubuntu 机器上安装 arm-linux-gnueabihf 工具链。
sudo apt update
sudo apt install gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-gcc --version
至此可以进行应用程序的构建,首先使用构建平台和主机平台的配置文件调用 conan install。这将安装为 armv7hf 架构构建的 zlib/1.2.11 依赖项和为 64 位架构运行的 cmake/3.22.6 版本。指令如下所示:
conan install . --build missing -pr:b=default -pr:h=./profiles/raspberry
这时可以直接通过这个版本的 CMake 来构建项目,需要执行的指令如下所示:
cd build
source Release/generators/conanbuild.sh
cmake .. -DCMAKE_TOOLCHAIN_FILE=Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
最后通过 file 对生成的应用程序进行检查,如下图所示:
6. Introduction to versioning
之前的示例一直在使用带有固定版本的依赖,例如,requires="zlib/1.2.12"。但有时依赖关系会演变,新版本会发布,消费者希望尽可能容易地更新到这些新版本。始终可以编辑connfiles并明确地将版本更新为新版本,但Conan中有机制允许在不修改配方的情况下进行此类更新。
首先创建一个使用最流行的 C++ 库之一 Zlib 的字符串压缩器应用程序,教程将使用 CMake 构建系统,但需要注意 Conan 适用于任何系统构建方式。 为了完成教程,首先下载对应的项目:
git clone https://github.com/conan-io/examples2.git
cd examples2/tutorial/consuming_packages/versioning
该项目的 conanfile.py 如下所示:
from conan import ConanFile
class CompressorRecipe(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
def requirements(self):
self.requires("zlib/[~1.2]")
其中,zlib 的版本被设置为 "1.2" 版本附近,该配置对应 zlib/1.2.8、zlib/1.211 等,但不会对应 zlib/1.3.0。如果执行 conan install 会出现:
如果将对应的设置更改为 zlib/[>1.2.12] 并执行 conan install 则会出现:
同样的思想也可以应用在 tool_requires。