使用 Hook 扩展 Conan 功能
在Conan 1.8 博客文章发布中,我们介绍了一种所谓的“插件系统”。通过阅读用户的一些反馈,我们很快意识到,尽管这是一个非常有用的功能,但它并不是一个真正的插件机制。通常,这种机制更通用、更强大,可以更广泛地替换或补充工具的功能。
相反,该功能的设计理念是在某些 Conan 事件之间执行预操作和后操作。这与git hooks 功能非常相似,因此我们决定以其命名,并考虑在未来开发一个真正的插件系统。
Hook 的状态
Hook 的发布是为了让用户除了 Conan 中通常的操作(如导出、构建、上传等)之外,还可以执行其他任务,甚至可以将其他操作作为 Conan 行为的一部分来实现。这种观点没有改变,我们坚信它们对于在公司或组织内部使用 Conan 的人来说非常有意义,这些人希望在构建所有软件包时拥有自定义的行为。
然而,不仅公司可以从 Conan 中自定义操作的功能中受益,开源社区也可以。在检查配方中的语法、检查缺少的属性(如许可证)、确保正确应用设置等等方面,Hook 非常方便。
在最近的版本中,我们对 Hook 进行了一些小的改进和修复,尽管可用性几乎保持不变。Hook 现在可以安装在配置文件中 hooks 文件夹下的不同文件夹中,允许用户将多个 Hook 放在一起,避免命名冲突。当在 Hook 中重用模块或存储其他文件(如许可证、自述文件、需求文件等)时,此结构可能会派上用场。
您可以在文档中找到有关如何从命令行激活和共享 Hook 的更多信息。
使用 Hook
Conan Hook 是一种 Python 脚本,旨在扩展 Conan 的功能,并允许用户在特定点增强客户端的行为。要使用它们,我们需要拥有 Hook 的源代码以便由 Conan 执行,并通过一些命令激活它们(请参阅下面的部分)。
让我们看看如何做到这一点。
克隆 Hook 仓库
如文档中所述,Hook 可以使用conan config install
共享,使其成为配置的一部分,并在 conan.conf 中默认激活。这种机制对于那些一起共享配置的人很有用,但是,如果您正在开发 Hook 呢?如果您想将它们版本化到自己的仓库中呢?文档中为此提出的机制是使用git clone
直接到 ~/.conan/hooks 目录中,并为它们使用子目录。
$ cd ~/.conan/hooks
$ git clone https://github.com/conan-io/hooks.git conan-io
我们坚信它们需要一个独立的仓库来发展和成熟,因此我们提出了在git
下控制开发的解决方案,这将有助于我们在将来进行版本控制。
您可能已经注意到我们将仓库克隆到了 conan-io
文件夹中,这样做是为了避免 Hook 的名称冲突,以便我们可以使用其路径来区分它们。
激活一些 Hook
现在我们已经克隆了 Hook,只需要激活所需的 Hook 即可。有几种方法可以做到这一点。
-
编辑 conan.conf 文件:您可以转到
[hooks]
部分,并编写要使用的 Hook 相对于 hooks 文件夹的路径。conan.conf
... [hooks] conan-io/hooks/attribute_checker conan-io/hooks/binary_linter
-
从命令行:使用
conan config set hooks.<hook path>
命令(如上所述的相对路径)。$ conan config set hooks.conan-io/hooks/attribute_checker $ conan config set hooks.conan-io/hooks/binary_linter ...
-
使用环境变量
CONAN_HOOKS
:这允许使用多个用逗号分隔的 Hook,路径可以相对于 hooks 文件夹,也可以是任何其他位置的绝对路径。这对于 CI 环境可能很有用。$ set CONAN_HOOKS=/home/user/.conan/hooks/conan-io/hooks/attribute_checker,/home/user/.conan/hooks/conan-io/hooks/binary_linter
正在开发中的 Hook
在文档中,我们提出了一些想法和关于 Hook 的小示例,例如配方中的属性检查、包签名或源代码下载不变性。我们已经将属性检查器 linter 作为 Hook 实现。
除此之外,我们还创建了一个 Hook 仓库,以便开始为社区开发有用的 Hook,并且我们已经收到了一些请求和大量关于如何改进 Hook 与 Conan 的集成并讨论配置、测试、文档等事项的想法。
在这篇文章中,我们想分享在此仓库中创建的 Hook 以及如何使用它们。
属性检查器
这是第一个作为示例创建的 Hook,现在已提取到此仓库中。这是一个学习如何编写第一个 Hook 的简单示例。
$ conan export . user/channel
[HOOK - conan-io/hooks/attribute_checker.py] pre_export(): WARN: Conanfile doesn't have 'url'. It is recommended to add it as attribute
[HOOK - conan-io/hooks/attribute_checker.py] pre_export(): WARN: Conanfile doesn't have 'license'. It is recommended to add it as attribute
查看 Hook 文档:attribute_checker
二进制 linter
二进制 linter Hook 提供了一些关于在package()
调用之后构建并最终打包的工件的提示。它有助于分析共享库中可能缺少的依赖项,以及检查生成的二进制文件是否与使用的配置文件匹配。
您可以在此处看到 Hook 的简要输出
$ conan create . docopt/0.6.2@user/testing
[HOOK - cona-nio/hooks/binary_linter.py] post_package(): conan binary linter plug-in
[HOOK - conan-io/hooks/binary_linter.py] post_package(): file "~/.conan/data/docopt/0.6.2/user/testing/package/970e773c5651dc2560f86200a4ea56c23f568ff9/conaninfo.txt" is not a executable, skipping...
[HOOK - conan-io/hooks/binary_linter.py] post_package(): checking file "~/.conan/data/docopt/0.6.2/user/testing/package/970e773c5651dc2560f86200a4ea56c23f568ff9/bin/docopt.dll"
[HOOK - conan-io/hooks/binary_linter.py] post_package(): "~/.conan/data/docopt/0.6.2/user/testing/package/970e773c5651dc2560f86200a4ea56c23f568ff9/bin/docopt.dll" doesn't import library "msvcr110.dll"
...
[HOOK - conan-io/hooks/binary_linter.py] post_package(): "~/.conan/data/docopt/0.6.2/user/testing/package/970e773c5651dc2560f86200a4ea56c23f568ff9/bin/docopt.dll" imports library "vcruntime140.dll"
[HOOK - conan-io/hooks/binary_linter.py] post_package(): "~/.conan/data/docopt/0.6.2/user/testing/package/970e773c5651dc2560f86200a4ea56c23f568ff9/bin/docopt.dll" doesn't import library "vcruntime140d.dll"
...
查看 Hook 文档:binary_linter
Bintray 更新器
正如一些人可能知道的那样,当将包上传到 Bintray 时,配方的元数据根本不会被处理。这会导致 Bintray 的信息为空。但是,使用此 Hook,您将获得所有已填充的信息。
您必须提供您的 Bintray 用户名和 API 令牌作为环境变量(BINTRAY_LOGIN_USERNAME
和BINTRAY_PASSWORD
)。
激活此 Hook 后,信息将从配方属性中收集,例如name
、license
、url
、homepage
和description
。成熟度级别基于分支名称,例如master
、release
和stable
被视为Stable
成熟度级别。项目徽标不受支持。所有信息在使用Bintray REST API上传配方后更新。
$ conan upload docopt/0.6.2@user/testing -r bintray
Uploading docopt/0.6.2@user/testing to remote 'bintray'
...
Uploaded conan recipe 'docopt/0.6.2@user/testing' to 'bintray': https://bintray.com/user/public-conan
[HOOK - conan-io/hooks/bintray_update.py] post_upload_recipe(): Reading package info form Bintray...
[HOOK - conan-io/hooks/bintray_update.py] post_upload_recipe(): Inspecting recipe info ...
[HOOK - conan-io/hooks/bintray_update.py] post_upload_recipe(): Bintray is outdated. Updating Bintray package info: licenses, issue_tracker_url, vcs_url, website_url, desc
查看 Hook 文档:bintray_updater
Conan Center 审核器
遵循第三方包含指南,我们使用此 Hook 创建了一个完整的 Conan Center 检查器。它主要用于在向 Conan Center 提交包含请求之前审核包。
它是用于管理中央仓库的工具之一,尽管完整的检查集仅在conan create
期间执行,但您也可以将其与软件包开发命令(如conan source
、conan build
等)一起使用。
$ conan create . user/channel
[HOOK - conan-io/hooks/conan-center_reviewer.py] pre_export(): ERROR: [RECIPE METADATA] Conanfile doesn't have 'url'. It is recommended to add it as attribute
[HOOK - conan-io/hooks/conan-center_reviewer.py] pre_export(): ERROR: [RECIPE METADATA] Conanfile doesn't have 'license'. It is recommended to add it as attribute
[HOOK - conan-io/hooks/conan-center_reviewer.py] pre_export(): [HEADER ONLY] OK
[HOOK - conan-io/hooks/conan-center_reviewer.py] pre_export(): [NO COPY SOURCE] OK
[HOOK - conan-io/hooks/conan-center_reviewer.py] pre_export(): [FPIC OPTION] OK
[HOOK - conan-io/hooks/conan-center_reviewer.py] pre_export(): [FPIC MANAGEMENT] 'fPIC' option not found
[HOOK - conan-io/hooks/conan-center_reviewer.py] pre_export(): [VERSION RANGES] OK
Exporting package recipe
Installing package: TestPkg/0.0.1@user/channel
Requirements
TestPkg/0.0.1@user/channel from local cache - Cache
Packages
TestPkg/0.0.1@user/channel:ca33edce272a279b24f87dc0d4cf5bbdcffbc187 - Build
...
TestPkg/0.0.1@user/channel: Copying sources to build folder
TestPkg/0.0.1@user/channel: Generator cmake_paths created conan_paths.cmake
TestPkg/0.0.1@user/channel: Calling build()
TestPkg/0.0.1@user/channel: WARN: This conanfile has no build step
TestPkg/0.0.1@user/channel: Package 'ca33edce272a279b24f87dc0d4cf5bbdcffbc187' built
[HOOK - conan-io/hooks/conan-center_reviewer.py] post_build(): [MATCHING CONFIGURATION] OK
[HOOK - conan-io/hooks/conan-center_reviewer.py] post_build(): [SHARED ARTIFACTS] OK
TestPkg/0.0.1@user/channel: Generated conaninfo.txt
TestPkg/0.0.1@user/channel: Generated conanbuildinfo.txt
...
TestPkg/0.0.1@user/channel: Calling package()
TestPkg/0.0.1@user/channel: WARN: This conanfile has no package step
TestPkg/0.0.1@user/channel package(): WARN: No files in this package!
TestPkg/0.0.1@user/channel: Package 'ca33edce272a279b24f87dc0d4cf5bbdcffbc187' created
[HOOK - conan-io/hooks/conan-center_reviewer.py] post_package(): ERROR: [PACKAGE LICENSE] No package licenses found in: ~/.conan/data/TestPkg/0.0.1/user/channel/package/ca33edce272a279b24f87dc0d4cf5bbdcffbc187. Please package the library license to a 'licenses' folder
[HOOK - conan-io/hooks/conan-center_reviewer.py] post_package(): [DEFAULT PACKAGE LAYOUT] OK
[HOOK - conan-io/hooks/conan-center_reviewer.py] post_package(): [MATCHING CONFIGURATION] OK
[HOOK - conan-io/hooks/conan-center_reviewer.py] post_package(): [SHARED ARTIFACTS] OK
如您所见,所有检查均非阻塞且通常提供信息。有配方语法检查,以及许可证和二进制格式检查。
查看 Hook 文档:conan-center_reviewer
GitHub 更新器
此 Hook 类似于 Bintray 更新器,但使用的是 GitHub。它更新存储库信息,例如描述、主题和网页。这样,所有信息都位于 GitHub 中,这将有助于搜索配方源。
您需要将 GitHub API 令牌设置为环境变量GITHUB_TOKEN
,并导出要更新其信息的配方的信息。它将使用配方中的 URL 属性执行更新。
查看 Hook 文档:github-updater
Hook 开发注意事项
请记住,Hook 非常通用,并且只要 Python 扩展就能使用,但是,不建议将 Hook 用于任何可能损害二进制兼容性并干扰包 ID 生成模型的任务。软件包的可重复性也可能在某个时候成为问题,但用户有责任跟踪 Conan 配置中的 Hook。
我们还考虑了 Hook 在未来可能出现的改进,这些改进将随着社区的采用而出现,例如
- 用于管理 Hook 的专用命令:安装、激活、更新、列出等。
- Hook 的版本控制系统以及与 Conan 客户端版本的兼容性。
- 通过配置文件、环境或自定义配置 Hook 参数。
- 安装期间的验证和测试。
- 自动解析使用的外部 pip 需求。
最后说明
所有这些 Hook 仍在开发中,但我们希望鼓励每个人,尤其是在 OSS 社区中,使用它们并提供反馈。
我们欢迎改进现有 Hook 或提出新的 Hook 的贡献,这些 Hook 可能对社区感兴趣。如果您有兴趣,请在Hook 问题跟踪器中发表评论,并随时使用您的建议打开 PR。
最后,别忘了查看文档以了解更多信息!