如何使用 Conan 交叉编译你的应用程序:主机和构建上下文¶
请先克隆源代码以重新创建此项目。 你可以在 GitHub 上的 examples2 仓库 中找到它们
$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/tutorial/consuming_packages/cross_building
在前面的示例中,我们学习了如何使用 *conanfile.py* 或 *conanfile.txt* 构建一个使用 *Zlib* 和 *CMake* Conan 包压缩字符串的应用程序。 此外,我们还解释了你可以在名为 Conan 配置文件的文件中设置操作系统、编译器或构建配置等信息。 你可以使用该配置文件作为参数 (--profile) 来调用 conan install 命令。 我们还解释了不指定该配置文件等效于使用 --profile=default 参数。
对于所有这些示例,我们都使用相同的平台来构建和运行应用程序。 但是,如果你想在运行 Ubuntu Linux 的机器上构建应用程序,然后在另一个平台(如 Raspberry Pi)上运行它怎么办? Conan 可以使用两个不同的配置文件来模拟这种情况,一个用于 **构建** 应用程序的机器(Ubuntu Linux),另一个用于 **运行** 应用程序的机器(Raspberry Pi)。 我们将在下一节中解释这种“两个配置文件”方法。
Conan 两个配置文件模型:构建和主机配置文件¶
即使你在调用 Conan 时只指定一个 --profile 参数,Conan 也会在内部使用两个配置文件。 一个用于 **构建** 二进制文件的机器(称为 **构建** 配置文件),另一个用于 **运行** 这些二进制文件的机器(称为 **主机** 配置文件)。 调用此命令
$ conan install . --build=missing --profile=someprofile
等效于
$ conan install . --build=missing --profile:host=someprofile --profile:build=default
正如你所看到的,我们使用了两个新参数
profile:host
:这是定义构建的二进制文件将在其上运行的平台的配置文件。 对于我们的字符串压缩器应用程序,此配置文件将应用于将在 **Raspberry Pi** 上运行的 *Zlib* 库。profile:build
:这是定义将在其上构建二进制文件的平台的配置文件。 对于我们的字符串压缩器应用程序,此配置文件将由 *CMake* 工具使用,该工具将在 **Ubuntu Linux** 机器上编译它。
请注意,当你只使用一个参数作为配置文件时,--profile
等效于 --profile:host
。 如果你不指定 --profile:build
参数,Conan 将在内部使用 *default* 配置文件。
因此,如果我们想在 Ubuntu Linux 机器上构建压缩器应用程序,但在 Raspberry Pi 上运行它,我们应该使用两个不同的配置文件。 对于 **构建** 机器,我们可以使用默认配置文件,在我们的例子中,它看起来像这样
[settings]
os=Linux
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=gnu14
compiler.libcxx=libstdc++11
compiler.version=9
以及用于 Raspberry Pi 的配置文件,即 **主机** 机器
[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-9
CXX=arm-linux-gnueabihf-g++-9
LD=arm-linux-gnueabihf-ld
重要
请注意,为了成功构建此示例,你应该安装一个工具链,其中包括编译器和所有用于为适当架构构建应用程序的工具。 在这种情况下,主机是一台运行 *armv7hf* 架构操作系统的 Raspberry Pi 3,并且我们在 Ubuntu 机器上安装了 *arm-linux-gnueabihf* 工具链。
如果你查看 *raspberry* 配置文件,会有一个名为 [buildenv]
的部分。 此部分用于设置构建应用程序所需的环境变量。 在这种情况下,我们声明了指向交叉构建工具链编译器和链接器的 CC
、CXX
和 LD
变量,分别。 将此部分添加到配置文件将每次我们执行 conan install 时都会调用 *VirtualBuildEnv* 生成器。 此生成器会将该环境信息添加到 conanbuild.sh
脚本中,我们将在使用 CMake 构建之前对其进行源化,以便它可以使用交叉构建工具链。
注意
在某些情况下,你无法在构建平台上获得工具链。 对于这些情况,你可以使用 Conan 包作为交叉编译器,并将其添加到配置文件的 [tool_requires]
部分。 有关使用工具链包进行交叉构建的示例,请查看 此示例。
构建和主机上下文¶
现在我们已经准备好了两个配置文件,让我们看看我们的 *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)
正如你所看到的,这实际上与我们在 前面的示例 中使用的 *conanfile.py* 相同。 我们将需要 zlib/1.2.11 作为常规依赖项,并需要 cmake/3.22.6 作为构建应用程序所需的工具。
我们将需要该应用程序使用交叉构建工具链为 Raspberry Pi 构建,并且还需要链接为同一平台构建的 zlib/1.2.11 库。 另一方面,我们需要 cmake/3.22.6 二进制文件在 Ubuntu Linux 上运行。 Conan 在依赖关系图中内部管理这一点,区分了我们所说的“构建上下文”和“主机上下文”
**主机上下文** 填充了根包(在 conan install 或 conan create 命令中指定的那个)及其通过
self.requires()
添加的所有需求。 在这种情况下,这包括压缩器应用程序和 zlib/1.2.11 依赖项。**构建上下文** 包含构建机器上使用的工具需求。 此类别通常包括所有开发工具,如 CMake、编译器和链接器。 在这种情况下,这包括 cmake/3.22.6 工具。
这些上下文定义了 Conan 将如何管理每个依赖项。 例如,由于 zlib/1.2.11 属于 **主机上下文**,因此我们在 raspberry 配置文件(配置文件主机)中定义的 [buildenv]
构建环境仅适用于构建时的 zlib/1.2.11 库,并且不会影响属于 **构建上下文** 的任何内容,例如 cmake/3.22.6 依赖项。
现在,让我们构建应用程序。 首先,使用构建和主机平台的配置文件调用 conan install。 这将安装为 *armv7hf* 架构构建的 zlib/1.2.11 依赖项和在 64 位架构上运行的 cmake/3.22.6 版本。
$ conan install . --build missing -pr:b=default -pr:h=./profiles/raspberry
然后,让我们调用 CMake 来构建应用程序。 正如我们在前面的示例中所做的那样,我们必须激活 **构建环境** 运行 source Release/generators/conanbuild.sh
。 这将设置定位交叉构建工具链和构建应用程序所需的环境变量。
$ cd build
$ source Release/generators/conanbuild.sh
Capturing current environment in deactivate_conanbuildenv-release-armv7hf.sh
Configuring environment variables
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
$ cmake --build .
...
-- Conan toolchain: C++ Standard 14 with extensions ON
-- The C compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/arm-linux-gnueabihf-gcc-9 - skipped
-- Detecting C compile features
-- Detecting C compile features - done [100%] Built target compressor
...
$ source Release/generators/deactivate_conanbuild.sh
你可以通过运行 file
Linux 实用程序来检查我们是否为正确的架构构建了应用程序
$ file compressor
compressor: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically
linked, interpreter /lib/ld-linux-armhf.so.3,
BuildID[sha1]=2a216076864a1b1f30211debf297ac37a9195196, for GNU/Linux 3.2.0, not
stripped
另请参阅
使用 tool_requires 进行交叉构建
使用 Conan 为 iOS 构建