如果您的问题是:
我可以在某台机器 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 = -m32
FLAGS_64 = -m64 , and so when building the 32-bit version,
FLAGS = -m32 would be included in the
CFLAGS` 宏。
自动工具中的剩余问题是如何确定 32 位和 64 位标志。如果最坏的情况发生在最坏的情况下,您将不得不自己为此编写宏。但是,我希望(没有研究过)您可以使用 autotools 套件中的标准工具来完成它。
除非您仔细(甚至无情地)为自己创建一个对称的 makefile,否则它不会可靠地工作。