包开发流程¶
本节介绍 Conan 本地开发流程,它允许您在本地项目目录中处理软件包,而无需先将软件包内容导出到 Conan 缓存。
这种本地工作流程鼓励用户在其 recipe 相关的本地子目录中进行反复试验,就像开发者通常使用其他构建工具测试构建项目一样。此阶段的策略是单独测试 conanfile.py 中的方法。
让我们对在 上一节 中创建的 hello
软件包使用此流程。
请克隆源代码以重新创建此项目。您可以在 GitHub 上的 examples2.0 仓库 中找到它们。
$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/tutorial/developing_packages/local_package_development_flow
您可以检查文件夹的内容
.
├── conanfile.py
└── test_package
├── CMakeLists.txt
├── conanfile.py
└── src
└── example.cpp
conan source¶
您通常会希望从 conan source 命令开始。这里的策略是您独立测试 source 方法,并将文件下载到相对于 conanfile.py 的临时子文件夹中。这个相对文件夹由 layout()
方法中的 self.folders.source
属性定义。在本例中,由于我们使用了预定义的 cmake_layout
,我们通过 src_folder
参数设置了该值。
注意
在本示例中,我们正在打包来自远程仓库的第三方库。如果您在同一个仓库中将源代码放在 recipe 旁边,则大多数情况下无需运行 conan source。
让我们看一下 recipe 的 source()
和 layout()
方法
...
def source(self):
# Please be aware that using the head of the branch instead of an immutable tag
# or commit is not a good practice in general.
get(self, "https://github.com/conan-io/libhello/archive/refs/heads/main.zip",
strip_root=True)
def layout(self):
cmake_layout(self, src_folder="src")
...
现在运行 conan source 命令并检查结果
$ conan source .
conanfile.py (hello/1.0): Calling source() in /Users/.../local_package_development_flow/src
Downloading main.zip
conanfile.py (hello/1.0): Unzipping 3.7KB
Unzipping 100%
您可以看到出现了一个新的 src 文件夹,其中包含所有 hello 库的源代码。
.
├── conanfile.py
├── src
│ ├── CMakeLists.txt
│ ├── LICENSE
│ ├── README.md
│ ├── include
│ │ └── hello.h
│ └── src
│ └── hello.cpp
└── test_package
├── CMakeLists.txt
├── conanfile.py
└── src
└── example.cpp
现在检查和验证源代码变得很容易。一旦您的 source 方法正确并且包含您期望的文件,您就可以继续测试与下载依赖项相关的各种属性和方法了。
conan install¶
运行 conan source 命令后,您可以运行 conan install 命令。该命令将安装所有 recipe 要求的依赖项(如果需要),并通过运行 generate()
方法准备构建所需的所有文件。
我们可以检查 recipe 中涉及此步骤的所有部分
...
class helloRecipe(ConanFile):
...
generators = "CMakeDeps"
...
def layout(self):
cmake_layout(self, src_folder="src")
def generate(self):
tc = CMakeToolchain(self)
tc.generate()
...
现在运行 conan install 命令并检查结果
$ conan install .
...
-------- Finalizing install (deploy, generators) --------
conanfile.py (hello/1.0): Writing generators to ...
conanfile.py (hello/1.0): Generator 'CMakeDeps' calling 'generate()'
conanfile.py (hello/1.0): Calling generate()
...
conanfile.py (hello/1.0): Generating aggregated env files
您可以看到出现了一个新的 build 文件夹,其中包含 Conan 构建库所需的所有文件,例如 CMake 工具链和一些环境配置文件。
.
├── build
│ └── Release
│ └── generators
│ ├── CMakePresets.json
│ ├── cmakedeps_macros.cmake
│ ├── conan_toolchain.cmake
│ ├── conanbuild.sh
│ ├── conanbuildenv-release-x86_64.sh
│ ├── conanrun.sh
│ ├── conanrunenv-release-x86_64.sh
│ ├── deactivate_conanbuild.sh
│ └── deactivate_conanrun.sh
├── conanfile.py
├── src
│ ├── CMakeLists.txt
│ ├── CMakeUserPresets.json
│ ├── LICENSE
│ ├── README.md
│ ├── include
│ │ └── hello.h
│ └── src
│ └── hello.cpp
└── test_package
├── CMakeLists.txt
├── conanfile.py
└── src
└── example.cpp
现在,构建所需的所有文件都已生成,您可以继续测试 build()
方法了。
conan build¶
运行 conan build 命令将调用 build()
方法
...
class helloRecipe(ConanFile):
...
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
...
让我们运行 conan build
$ conan build .
...
-- Conan toolchain: C++ Standard 11 with extensions ON
-- Conan toolchain: Setting BUILD_SHARED_LIBS = OFF
-- Configuring done
-- Generating done
-- Build files have been ...
conanfile.py (hello/1.0): CMake command: cmake --build ...
conanfile.py (hello/1.0): RUN: cmake --build ...
[100%] Built target hello
对于大多数 recipes,build()
方法应该非常简单,并且由于您拥有构建所需的所有文件,您也可以直接调用构建系统,而无需调用 Conan。如果您检查 src 文件夹的内容,您会发现一个 CMakeUserPresets.json 文件,您可以使用它来配置和构建 conan-release preset。让我们尝试一下
$ cd src
$ cmake --preset conan-release
...
-- Configuring done
-- Generating done
$ cmake --build --preset conan-release
...
[100%] Built target hello
您可以检查直接调用 CMake 的结果与我们使用 conan build 命令获得的结果是等效的。
注意
在此示例中,我们使用了 CMake presets。这需要 CMake >= 3.23,因为从 CMakeUserPresets.json
到 CMakePresets.json
的“include”功能仅从该版本开始支持。如果您不想使用 presets,您可以使用类似以下的方式:
cmake <path> -G <CMake generator> -DCMAKE_TOOLCHAIN_FILE=<path to
conan_toolchain.cmake> -DCMAKE_BUILD_TYPE=Release
如果您无法使用 presets 功能,Conan 在每次运行 conan install
时都会显示确切的 CMake 命令。
conan export-pkg¶
既然我们已经在本地构建了软件包的二进制文件,我们还可以使用 conan export-pkg 命令将这些 artifact 打包到 Conan 本地缓存中。请注意,此命令将在 Conan 缓存中创建软件包,然后通过运行 test_package 来测试它。
$ conan export-pkg .
conanfile.py (hello/1.0) package(): Packaged 1 '.h' file: hello.h
conanfile.py (hello/1.0) package(): Packaged 1 '.a' file: libhello.a
conanfile.py (hello/1.0): Package 'b1d267f77ddd5d10d06d2ecf5a6bc433fbb7eeed' created
conanfile.py (hello/1.0): Created package revision f09ef573c22f3919ba26ee91ae444eaa
...
conanfile.py (hello/1.0): Package folder /Users/...
conanfile.py (hello/1.0): Exported package binary
...
[ 50%] Building CXX object CMakeFiles/example.dir/src/example.cpp.o
[100%] Linking CXX executable example
[100%] Built target example
-------- Testing the package: Running test() --------
hello/1.0 (test package): Running test()
hello/1.0 (test package): RUN: ./example
hello/1.0: Hello World Release!
hello/1.0: __x86_64__ defined
hello/1.0: __cplusplus201103
hello/1.0: __GNUC__4
hello/1.0: __GNUC_MINOR__2
hello/1.0: __clang_major__14
hello/1.0: __apple_build_version__14000029
现在您可以列出本地缓存中的软件包,并检查 hello/1.0
软件包是否已创建
$ conan list hello/1.0
Local Cache
hello
hello/1.0
另请参阅
conan 命令参考:source, install, build, export-pkg 和 test。
打包预编译的二进制文件 示例
当您在本地开发软件包时,有时在调试期间可能需要进入依赖项的代码。请阅读此 关于如何调试和进入依赖项的示例 以获取有关此用例的更多信息。