【问题标题】:Can autotools create multi-platform makefilesautotools可以创建多平台makefile吗
【发布时间】:2010-09-24 08:38:11
【问题描述】:

我有一个插件项目,我已经开发了几年,该插件可与 [主要应用程序版本、第 3 方库版本、32 位与 64 位] 的多种组合一起使用。是否有一种(干净的)方法可以使用 autotools 创建一个构建所有版本插件的 makefile。

从浏览 autotools 文档中我可以看出,最接近我想要的是拥有 N 个独立的项目副本,每个副本都有自己的 makefile。这对于测试和开发来说似乎有点不太理想,因为 (a) 我需要在所有不同的副本中不断传播代码更​​改,并且 (b) 多次复制项目会浪费很多空间。有没有更好的办法?

编辑:

一段时间以来,我一直在推出自己的解决方案,我有一个花哨的 makefile 和一些 perl 脚本来寻找各种 3rd 方库版本等。因此,我对其他非自动工具解决方案持开放态度。对于其他构建工具,我希望它们对最终用户来说非常容易安装。这些工具还需要足够聪明,以便在没有大量麻烦的情况下搜索各种 3rd 方库和标头。我主要是在寻找一个 linux 解决方案,但一个也适用于 Windows 和/或 Mac 的解决方案将是一个奖励。

【问题讨论】:

    标签: 64-bit makefile 32-bit autotools multiplatform


    【解决方案1】:

    如果您的问题是:

    我可以在某台机器 A 上使用自动工具来创建一个可以在所有其他机器上运行的通用 makefile 吗?

    那么答案是“否”。自动工具甚至不会假装尝试这样做。它们旨在包含可移植代码,这些代码将决定如何在目标机器上创建一个可行的 makefile。

    如果您的问题是:

    我可以使用自动工具来配置需要在不同机器上运行的软件,使用我的插件使用的不同版本的主要软件,以及各种第 3 方库,更不用说 32 位与 64 位的问题了吗?

    那么答案是“是”。自动工具旨在能够做到这一点。此外,它们适用于 Unix、Linux、MacOS X、BSD。

    我有一个程序 SQLCMD(它比 Microsoft 的同名程序早了十年甚至更多),它与 IBM Informix 数据库一起工作。它检测安装的客户端软件(称为 IBM Informix ESQL/C,IBM Informix ClientSDK 或 CSDK 的一部分)的版本,以及它是 32 位还是 64 位。它还检测安装了哪个版本的软件,并根据支持产品中的可用功能调整其功能。它支持已经发布了大约 17 年的版本。它是自动配置的——我必须为 Informix 功能和其他一些小玩意(高分辨率计时、/dev/stdin 的存在等)编写一些 autoconf 宏。但这是可行的。

    另一方面,我不会尝试发布适合所有客户机器和环境的单个 makefile;有太多的可能性是明智的。但是 autotools 会为我(和我的用户)处理细节。他们所做的只是:

    ./configure
    

    这比弄清楚如何编辑 makefile 更容易。 (哦,在最初的 10 年里,程序是手动配置的。尽管我设置了很好的默认设置,但人们很难做到。这就是我转向自动配置的原因:它使人来安装。)


    福兹先生评论:

    我想要介于两者之间的东西。在我的情况下,客户将在同一台机器上使用相同基础应用程序的多个版本和位数。我不担心交叉编译,例如在 Linux 上构建 Windows 二进制文件。

    您需要为 32 位和 64 位版本单独构建插件吗? (我认为是的 - 但你可能会让我感到惊讶。)所以你需要提供一种机制让用户说

    ./configure --use-tppkg=/opt/tp/pkg32-1.0.3
    

    (其中 tppkg 是您的第三方包的代码,位置由用户指定。)但是,请记住可用性:用户必须提供的此类选项越少,更好;对此,不要硬编码应该是可选的东西,例如安装位置。一定要查看默认位置 - 这很好。并且默认为您找到的东西的琐碎。也许如果您同时找到 32 位和 64 位版本,那么您应该同时构建这两个版本——不过,这需要仔细构建。您可以随时回显“正在检查 TP-Package ...”并指出您找到的内容和找到的位置。然后安装程序可以更改选项。确保在“./configure --help”中记录选项是什么;这是标准的 autotools 做法。

    不要做任何交互的事情;配置脚本应该运行,报告它做了什么。 Perl Configure 脚本(注意大写字母 - 它是一个完全独立的自动配置系统)是剩下的少数密集交互配置系统之一(这可能主要是因为它的传统;如果重新开始,它很可能是非交互式的)。这样的系统配置起来比非交互式系统更麻烦。

    交叉编译很难。谢天谢地,我从来不需要这样做。


    福兹先生也评论道:

    感谢额外的 cmets。我正在寻找类似的东西:

    ./configure --use-tppkg=/opt/tp/pkg32-1.0.3 --use-tppkg=/opt/tp/pkg64-1.1.2
    

    它将在一个 makefile 中为当前平台创建 32 位和 64 位目标。

    嗯,我确信可以做到;与两个单独的配置运行并在两者之间进行完全重建相比,我不太确定这样做是否值得。您可能想要使用:

    ./configure --use-tppkg32=/opt/tp/pkg32-1.0.3 --use-tppkg64=/opt/tp/pkg64-1.1.2
    

    这表示两个单独的目录。您必须决定如何进行构建,但可能会有两个子目录,例如“obj-32”和“obj-64”,用于存储单独的目标文件集。您还可以按照以下方式排列您的 makefile:

    FLAGS_32 = ...32-bit compiler options...
    FLAGS_64 = ...64-bit compiler options...
    
    TPPKG32DIR = @TPPKG32DIR@
    TPPKG64DIR = @TPPKG64DIR@
    
    OBJ32DIR = obj-32
    OBJ64DIR = obj-64
    
    BUILD_32 = @BUILD_32@
    BUILD_64 = @BUILD_64@
    
    TPPKGDIR =
    OBJDIR   =
    FLAGS    =
    
    all:    ${BUILD_32} ${BUILD_64}
    
    build_32:
        ${MAKE} TPPKGDIR=${TPPKG32DIR} OBJDIR=${OBJ32DIR} FLAGS=${FLAGS_32} build
    
    build_64:
        ${MAKE} TPPKGDIR=${TPPKG64DIR} OBJDIR=${OBJ64DIR} FLAGS=${FLAGS_64} build
    
    build:  ${OBJDIR}/plugin.so
    

    这假设插件是一个共享对象。这里的想法是自动工具将检测第三方软件包的 32 位或 64 位安装,然后进行替换。如果需要 32 位包,则 BUILD_32 宏将设置为 build_32,否则留空; BUILD_64 宏的处理方式类似。

    当用户运行'make all'时,它将首先构建build_32目标,然后是build_64目标。要构建 build_32 目标,它将重新运行 make 并为 32 位构建配置标志。同样,要构建 build_64 目标,它将重新运行 make 并为 64 位构建配置标志。重要的是,所有受 32 位和 64 位构建影响的标志都设置在 make 的递归调用上,并且构建对象和库的规则要仔细编写 - 例如,将源代码编译为object 必须小心地将对象文件放在正确的对象目录中 - 例如,使用 GCC,您可以指定(在 .c.o 规则中):

    ${CC} ${CFLAGS} -o ${OBJDIR}/$*.o -c $*.c
    

    宏 CFLAGS 将包含处理位的 ${FLAGS} 值(例如,FLAGS_32 = -m32 和 FLAGS_64 = -m64, and so when building the 32-bit version,FLAGS = -m32would be included in theCFLAGS` 宏。

    自动工具中的剩余问题是如何确定 32 位和 64 位标志。如果最坏的情况发生在最坏的情况下,您将不得不自己为此编写宏。但是,我希望(无需研究)您可以使用 autotools 套件中的标准工具来完成它。

    除非您为自己创建一个仔细(甚至是无情地)对称的 makefile,否则它不会可靠地工作。

    【讨论】:

    • 我想要介于两者之间的东西。在我的情况下,客户将在同一台机器上使用相同基础应用程序的多个版本和位数。我不担心交叉编译,例如在 Linux 上构建 Windows 二进制文件。
    • 感谢额外的 cmets。我正在寻找类似“./configure --use-tppkg=/opt/tp/pkg32-1.0.3 --use-tppkg=/opt/tp/pkg64-1.1.2”的东西,它会在其中创建当前平台的一个 makefile 中的 32 位和 64 位目标。
    【解决方案2】:

    据我所知,你不能这样做。但是,您是否坚持使用自动工具? CMakeSCons 都不是一个选项吗?

    【讨论】:

    • 谢谢。我正在对两者进行一些阅读,看看哪个更有可能处理构建过程的一些复杂性,例如调用特殊的特定于应用程序的构建包装器而不是直接调用 gcc。
    【解决方案3】:

    我们试过了,但它不起作用!所以我们现在使用SCons

    关于这个话题的一些文章:12

    编辑: 我喜欢 SCons 的一些小例子:

    env.ParseConfig('pkg-config --cflags --libs glib-2.0')
    

    通过这行代码,您可以将 GLib 添加到编译环境 (env)。并且不要忘记User Guide,它非常适合学习 SCons(您真的不必了解 Python!)。对于最终用户,您可以使用PyInstaller 或类似的方式尝试 SCons。

    make 相比,您使用的是Python,所以是一门完整的编程语言!考虑到这一点,您可以做任何事情(或多或少)。

    【讨论】:

    • 我来看看 scons。我以前没听说过。
    【解决方案4】:

    您是否考虑过使用具有多个构建目录的单个项目? 如果您的 automake 项目以正确的方式实现(即:不像 gcc)

    以下是可能的:

    mkdir build1 build2 build3
    cd build1
    ../configure $(YOUR_OPTIONS)
    cd build2
    ../configure $(YOUR_OPTIONS2)
    [...]
    

    您可以传递不同的配置参数,例如包含目录和编译器(即交叉编译器)。

    然后你甚至可以通过运行在单个 make 调用中运行它

    make -C build1 -C build2 -C build3
    

    【讨论】:

      猜你喜欢
      • 2015-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      相关资源
      最近更新 更多