Autotools

Autotools 构建助手是 autotools 命令行调用的封装器。它会将类似 ./configuremake 的调用抽象为 Python 方法调用。

用法

from conan import ConanFile
from conan.tools.gnu import Autotools

class App(ConanFile):
    settings = "os", "arch", "compiler", "build_type"

    def build(self):
        autotools = Autotools(self)
        autotools.configure()
        autotools.make()

它将读取 AutotoolsToolchain 生成的 conanbuild.conf 文件,以了解调用 configure 和 make 脚本的参数

  • configure_args:调用 configure 脚本的参数。

  • make_args:调用 make 脚本的参数。

参考

class Autotools(conanfile, namespace=None)
参数:
  • conanfile – 当前的配方对象。始终使用 self

  • namespace – 此参数可避免在同一个配方中进行多次工具链调用时发生冲突。通过设置此参数,用于将信息传递给工具链的 *conanbuild.conf* 文件将被命名为:*<namespace>_conanbuild.conf*。默认值为 None,这意味着生成文件的名称为 *conanbuild.conf*。此命名空间还必须在 AutotoolsToolchain 的构造函数中以相同的值设置,以便它从正确的文件读取信息。

configure(build_script_folder=None, args=None)

调用 configure 脚本。

参数:
  • args – 用于 configure 调用参数列表。

  • build_script_folder – 包含 configure 脚本的子文件夹。如果未指定,则使用 conanfile.source_folder。

make(target=None, args=None, makefile=None)

调用 make 程序。

参数:
  • target – (可选,默认为 None):选择要构建的目标。这允许构建例如文档、共享库或某些 Autotools 项目的安装。

  • args – (可选,默认为 None):用于 make 调用的参数列表。

  • makefile – (可选,默认为 None):允许指定要使用的自定义 Makefile,而不是默认的“Makefile”。

install(args=None, target=None, makefile=None)

这只是 self.make(target="install")self.make(target="install-strip") 的“别名”。

参数:
  • args – (可选,默认为 None):用于 make 调用的参数列表。默认情况下,如果传递的值为 None,则会将参数 DESTDIR=unix_path(self.package_folder) 添加到调用中。有关 tools.microsoft.unix_path() 函数 的更多信息。

  • target – (可选,默认为 None):选择要安装的目标。

  • makefile – (可选,默认为 None):允许指定要使用的自定义 Makefile,而不是默认的“Makefile”。

autoreconf(build_script_folder=None, args=None)

调用 autoreconf

参数:
  • args – (可选,默认为 None):用于 autoreconf 调用的参数列表。

  • build_script_folder – 包含 configure 脚本的子文件夹。如果未指定,则使用 conanfile.source_folder。

conf

Autotools 构建助手受这些 [conf] 变量影响

  • tools.gnu:make_program 允许定义正在使用的 make 可执行文件。对于 MinGW 构建,这将默认为 mingw32-make,对于任何其他构建,则默认为 make

  • tools.build:install_strip(自 Conan 2.20.0 起)将在 Autotools.install() 方法中定义 make install-strip 目标(如果设置为 True),否则将使用 make install 目标。

关于使用 Autotools 构建助手在 macOS 中构建可重定位共享库的说明

在使用 Autotools 在 macOS 中构建共享库时,会向 .dylib 添加一个 LC_ID_DYLIB 和另一个 LC_LOAD_DYLIB 部分。这些部分存储 install_name 信息,即安装库或其依赖项的文件夹的位置。您可以使用 otool 命令检查共享库的 install_name

$ otool -l path/to/libMyLib.dylib
...
cmd LC_ID_DYLIB
    cmdsize 48
        name path/to/libMyLib.dylib (offset 24)
time stamp 1 Thu Jan  1 01:00:01 1970
    current version 1.0.0
compatibility version 1.0.0
...
Load command 11
        cmd LC_LOAD_DYLIB
    cmdsize 48
        name path/to/dependency.dylib (offset 24)
time stamp 2 Thu Jan  1 01:00:02 1970
    current version 1.0.0
compatibility version 1.0.0
...

为什么在使用 Conan 时会出现这个问题?

在使用 Conan 时,库将在本地缓存中构建,这意味着该位置将指向 Conan 本地缓存文件夹,库安装在其中。这是库告诉任何使用它的其他二进制文件在运行时从哪里加载它的位置。这是一个问题,因为您可以构建一个机器上的共享库,然后将其上传到服务器并在另一个机器上安装它以使用它。在这种情况下,如 Autotools 默认行为所表现,您将拥有一个库,其中存储的 install_name 指向当前机器上不存在的文件夹,因此在构建时会收到链接器错误。

如何在 Conan 中解决此问题

Conan 可以做的唯一事情是修补构建的二进制文件在安装之后。为此,在使用 Autotools 构建助手并在 Makefile 的 install() 步骤之后,可以使用 fix_apple_shared_install_name() 工具来搜索构建的 .dylib 文件并使用 macOS 实用程序 install_name_tool 对它们进行修补,如下所示

from conan.tools.apple import fix_apple_shared_install_name
class HelloConan(ConanFile):
  ...
  def package(self):
      autotools = Autotools(self)
      autotools.install()
      fix_apple_shared_install_name(self)

这将更改 .dylib 文件中 LC_ID_DYLIBLC_LOAD_DYLIB 部分的值为

$ otool -l path/to/libMyLib.dylib
...
cmd LC_ID_DYLIB
    cmdsize 48
        name @rpath/libMyLib.dylib (offset 24)
time stamp 1 Thu Jan  1 01:00:01 1970
    current version 1.0.0
compatibility version 1.0.0
...
Load command 11
        cmd LC_LOAD_DYLIB
    cmdsize 48
        name @rpath/dependency.dylib (offset 24)
time stamp 2 Thu Jan  1 01:00:02 1970
    current version 1.0.0
compatibility version 1.0.0

特殊关键字 @rpath 将告诉加载器搜索路径列表以查找库。这些路径可以由使用该库的消费者通过定义 LC_RPATH 字段来定义。通过在构建库的消费者时传递链接器标志 -Wl,-rpath -Wl,/path/to/libMyLib.dylib 来完成此操作。然后,如果 Conan 构建一个使用 libMyLib.dylib 库的可执行文件,它将自动添加 -Wl,-rpath -Wl,/path/to/libMyLib.dylib 标志,以便在构建时正确找到该库。