工作区文件

警告

此功能是新的孵化功能的一部分。这意味着它仍在开发中,并且正在寻求用户测试和反馈。有关更多信息,请参阅 孵化部分

工作区由 conanws.yml 和/或 conanws.py 文件定义,这些文件将定义“根”工作区文件夹。

conanws.yml

工作区最基本的形式是 conanws.yml 文件。它定义了工作区的 packages(可编辑包)。例如,一个定义了 2 个 packages 的工作区 conanws.yml 可以是

conanws.yml
packages:
   - path: dep1
     ref: dep1/0.1
   - path: dep2
     ref: dep2/0.1

此外,它也可以没有 ref 字段,让 Conan 从相应的 path/conanfile.py 中读取名称/版本

conanws.yml
packages:
   - path: dep1
   - path: dep2

conanws.py

conanws.yml 可以通过功能更强大的 conanws.py 进行扩展,后者遵循与 ConanFile 与其 conandata.yml 相同的关系。如果我们想动态定义 packages,例如基于文件夹中某些 name.txtversion.txt 文件的存在,则可以在 conanws.py 中定义包,如下所示:

conanws.py
import os
from conan import Workspace

class MyWorkspace(Workspace):

   def packages(self):
      result = []
      for f in os.listdir(self.folder):
         if os.path.isdir(os.path.join(self.folder, f)):
            with open(os.path.join(self.folder, f, "name.txt")) as fname:
               name = fname.read().strip()
            with open(os.path.join(self.folder, f, "version.txt")) as fversion:
               version = fversion.read().strip()
            result.append({"path": f, "ref": f"{name}/{version}"})
      return result

还可以通过 Workspace.load_conanfile() 帮助器在 set_name()set_version() 方法中重用 conanfile.py 逻辑。

conanws.py
import os
from conan import Workspace

class MyWorkspace(Workspace):
   def packages(self):
      result = []
      for f in os.listdir(self.folder):
         if os.path.isdir(os.path.join(self.folder, f)):
            conanfile = self.load_conanfile(f)
            result.append({"path": f, "ref": f"{conanfile.name}/{conanfile.version}"})
      return result

conanws.py 超级构建选项

用于超级构建工作区文件的 conanws.py 可以通过两种不同的方式管理选项:

  • 它可以定义自己的 options,使用标准的 conanfile.py 语法,因此为超级项目生成的 conan_toolchain.cmake 将使用这些输入。

  • 它可以收集工作区包的选项,使用 workspace_packages_options,并以用户自定义的方式处理它们。

超级项目选项

conanws.py 必须在 ConanFile 类中定义超级构建的选项,并在 generate() 方法中使用这些选项,就像通常使用 conanfile.py 文件一样,类似于:

from conan import ConanFile, Workspace

class MyWs(ConanFile):
   settings = "arch", "build_type"
   options = {"myoption": [1, 2, 3]}

   def generate(self):
      self.output.info(f"Generating with my option {self.options.myoption}!!!!")

class Ws(Workspace):
   def root_conanfile(self):
      return MyWs

然后,可以通过常规语法,通过配置文件或命令行提供选项。

$ conan workspace super-install -of=build -o "*:myoption=1"
> conanws.py base project Conanfile: Generating with my option 1!!!!

请注意,工作区包中定义的 options 可能会与此处定义的选项重叠,因为对于超级项目,这些选项将被忽略,只有超级项目的选项才会被考虑用来生成 conan_toolchain.cmake。例如,conanws.py 可以定义一个 shared 选项,以便当定义类似 -o "*:shared=True" 时,conan_toolchain.cmake 能正确地定义 BUILD_SHARED_LIBS 或不定义。因为当工作区包在依赖图中折叠以模拟超级项目时,它们具有 shared 选项的信息将被丢弃。

包选项

第二种选择是收集已折叠的工作区包的 options。请记住,在最终的依赖图中,工作区包不再被表示,因为它们不再是独立的包,而是当前超级构建的一部分。访问它们的选项信息的方法是通过 workspace_packages_options,并且这些信息可以在 generate() 方法中使用,以便在超级构建项目级别执行任何期望的操作。

因此,假设一个包含 dep/0.1 包的工作区,该包包含标准的 shared 选项,它定义了以下超级构建 ConanFile

from conan import ConanFile, Workspace

class MyWs(ConanFile):
   def generate(self):
      for pkg, options in self.workspace_packages_options.items():
         for k, v in options.items():
               self.output.info(f"Generating with opt {pkg}:{k}={v}!!!!")

class Ws(Workspace):
   def root_conanfile(self):
      return MyWs

然后,当定义了工作区包选项后,工作区 ConanFile 就可以收集它们。

$ conan workspace super-install -of=build -o "*:shared=True"
> conanws.py base project Conanfile: Generating with opt dep/0.1:shared=True!!!!!!!!

注意

实际上,工作区创建者有责任定义如何处理选项,无论是通过定义自己的选项还是收集工作区包的选项。请注意,无法自动将工作区包的选项映射到超级项目,因为选项是按包定义的。两个不同的包可能具有不同的 shared=Trueshared=False 值。此外,生成工具链文件的影响通常是自定义的,并在每个包的 generate() 方法中实现。这种影响是程序化的(非声明性的),在单个工具链中聚合所有这些影响将极其困难。

另请参阅

阅读 工作区教程 部分。