在拥有多个子项目时声明布局

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

$ git clone https://github.com/conan-io/examples2.git
$ cd examples2/examples/conanfile/layout/multiple_subprojects

假设我们有一个项目包含两个子项目:*hello* 和 *bye*,它们需要访问同一层级(同级文件夹)的一些信息。每个子项目都会是一个 Conan 包。结构可能类似于这样:

.
├── bye
│   ├── CMakeLists.txt
│   ├── bye.cpp        # contains an #include "../common/myheader.h"
│   └── conanfile.py   # contains include(../common/myutils.cmake)
├── common
│   ├── myheader.h
│   └── myutils.cmake
└── hello
    ├── CMakeLists.txt # contains include(../common/myutils.cmake)
    ├── conanfile.py
    └── hello.cpp      # contains an #include "../common/myheader.h"

hellobye 这两个子项目都需要使用位于 common 文件夹内的某些文件(这些文件也可能被其他子项目使用和共享),并且它们通过相对位置引用这些文件。common 并非 intended to be a Conan package(意图成为一个 Conan 包)。它只是一些通用的代码,将被复制到不同的子项目包中。

我们可以使用 self.folders.root = ".." 布局说明符来定位项目根目录,然后使用 self.folders.subproject = "subprojectfolder" 将大部分布局重新定位回当前子项目文件夹,因为该文件夹将包含构建脚本、源代码等,这样其他助手(如 cmake_layout())就能继续工作。让我们看看 helloconanfile.py 会是什么样子:

./hello/conanfile.py
import os
from conan import ConanFile
from conan.tools.cmake import cmake_layout, CMake
from conan.tools.files import copy


class hello(ConanFile):
    name = "hello"
    version = "1.0"

    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeToolchain"

    def layout(self):
        self.folders.root = ".."
        self.folders.subproject = "hello"
        cmake_layout(self)

    def export_sources(self):
        source_folder = os.path.join(self.recipe_folder, "..")
        copy(self, "hello/conanfile.py", source_folder, self.export_sources_folder)
        copy(self, "hello/CMakeLists.txt", source_folder, self.export_sources_folder)
        copy(self, "hello/hello.cpp", source_folder, self.export_sources_folder)
        copy(self, "common*", source_folder, self.export_sources_folder)

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()
        self.run(os.path.join(self.cpp.build.bindirs[0], "hello"))

让我们构建 hello,并检查它是否能正确构建,使用 common 文件夹的内容。

$ conan install hello
$ conan build hello
...
[100%] Built target hello
conanfile.py (hello/1.0): RUN: ./hello
hello WORLD

您也可以运行 conan create 并检查它是否也能正常工作。

$ conan create hello
...
[100%] Built target hello
conanfile.py (hello/1.0): RUN: ./hello
hello WORLD

注意

请注意 export_sources() 方法的重要性,它能够保持 *hello* 和 *common* 文件夹在本地开发者流程(在当前文件夹中)和这些源文件被复制到 Conan 缓存(以便在那里使用 conan createconan install --build=hello 进行构建)时相同的相对布局。这是 layout() 的设计原则之一:事物的相对位置在用户文件夹和缓存中必须是一致的。

另请参阅