2

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

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

编辑:

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

4

4 回答 4

6

如果您的问题是:

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

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

如果您的问题是:

我可以使用自动工具来配置需要在不同机器上运行的软件,使用我的插件使用的不同版本的主要软件,以及各种 3rd 方库,更不用说 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”中记录选项是什么;这是标准的自动工具实践。

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

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


福兹先生还评论说:

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

./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,并且构建对象和库的规则要仔细编写 - 例如,将源编译为对象的规则必须是小心地将目标文件放在正确的目标目录中 - 例如,使用 GCC,您将指定(在.c.o规则中):

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

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

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

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

于 2008-11-27T17:59:52.307 回答
5

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

于 2008-11-27T16:17:34.727 回答
1

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

该主题的一些文章:12

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

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

使用这行代码,您可以将 GLib 添加到编译环境 ( env )。不要忘记学习 SCons 的用户指南(你真的不必了解 Python!)。对于最终用户,您可以使用PyInstaller或类似的东西尝试 SCons。

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

于 2008-11-27T16:25:29.890 回答
0

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

以下是可能的:

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

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

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

make -C build1 -C build2 -C build3
于 2010-06-10T17:35:57.780 回答