我有一个插件项目,我已经开发了几年,插件与[主应用程序版本,第三方库版本,32位与64位]的多种组合一起工作.是否有一种(干净的)方法来使用autotools来创建构建插件的所有版本的单个makefile.
从浏览autotools文档我可以看出,与我想要的最接近的是拥有项目的N个独立副本,每个副本都有自己的makefile.这对于测试和开发来说似乎有点不理想,因为(a)我需要在所有不同的副本中不断传播代码更改,并且(b)在复制项目时有很多浪费的空间.有没有更好的办法?
编辑:
我已经推出了自己的解决方案一段时间,我有一个花哨的makefile和一些perl脚本来搜索各种第三方库版本等.因此,我对其他非autotools解决方案持开放态度.对于其他构建工具,我希望它们对于最终用户来说非常容易安装.这些工具还需要足够智能,以便在没有大量麻烦的情况下搜索各种第三方库和标题.我主要是在寻找一个Linux解决方案,但也适用于Windows和/或Mac的解决方案.
如果您的问题是:
我可以在某台机器A上使用autotools创建一个可在所有其他机器上运行的通用makefile吗?
然后答案是"不".autotools甚至没有试图做到这一点.它们旨在包含可移植代码,用于确定如何在目标计算机上创建可行的makefile.
如果您的问题是:
我可以使用autotools来配置需要在不同机器上运行的软件,使用我的插件可以使用的主要软件的不同版本,以及各种第三方库,更不用说32位与64位问题了吗?
然后答案是"是".autotools旨在能够做到这一点.此外,它们适用于Unix,Linux,MacOS X,BSD.
我有一个程序,SQLCMD(它可以在十年甚至更长时间之前提供相同名称的Microsoft程序),它与IBM Informix数据库一起使用.它检测安装的客户端软件版本(称为IBM Informix ESQL/C,IBM Informix ClientSDK或CSDK的一部分),以及是32位还是64位.它还可以检测安装了哪个版本的软件,并使其功能适应支持产品中的可用功能.它支持在大约17年的时间内发布的版本.它是自动配置的 - 我必须为Informix功能编写一些autoconf宏,以及其他几个小玩意(高分辨率计时,存在/ dev/stdin等).但这是可行的.
另一方面,我不会尝试发布适合所有客户机器和环境的单个makefile; 有太多的可能性使其变得合情合理.但是autotools会为我(以及我的用户)处理细节.他们所做的只是:
./configure
这比编写如何编辑makefile更容易.(哦,在最初的10年里,程序是手工配置的.人们很难做到,即使我设置了相当不错的默认设置.这就是为什么我转向自动配置:它使得它更容易人们要安装.)
Fooz先生评论道:
我想要介于两者之间.在我的情况下,客户将在同一台机器上使用同一基本应用程序的多个版本和位数.我不担心交叉编译,比如在Linux上构建Windows二进制文件.
您是否需要为32位和64位版本单独构建插件?(我假设是 - 但你可能会让我感到惊讶.)所以你需要为用户提供一种机制
./configure --use-tppkg=/opt/tp/pkg32-1.0.3
(其中tppkg是您的第三方封装代码,地点由用户可指定).但是,请记住可用性:越少这样的选项,用户有提供,更好的; 与此相反,不要硬编码应该是可选的东西,例如安装位置.一定要查看默认位置 - 这很好.并且默认为您找到的东西的苦涩.也许如果您找到32位和64位版本,那么您应该构建两者 - 但这需要仔细构建.您可以随时回显"正在检查TP-Package ..."并指出您找到的内容以及找到它的位置.然后安装程序可以更改选项.确保记录" ./configure --help
选项是什么; 这是标准的autotools练习.
不要做任何互动的事情; configure脚本应该运行,报告它的作用.Perl Configure
脚本(注意大写字母 - 它是一个完全独立的自动配置系统)是为数不多的集中交互式配置系统之一(这可能主要是因为它的遗产;如果重新开始,它很可能是非互动).这种系统比非交互系统更容易配置.
交叉编译很难.我从来不需要这样做,谢天谢地.
Fooz先生还评论道:
感谢您的额外评论.我正在寻找类似的东西:
./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
这假设插件将是共享对象.这里的想法是autotool会检测第三方包的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`宏.
autotools中的剩余问题正在研究如何确定32位和64位标志.如果最坏的情况发生,那么你必须自己编写宏.但是,我希望(没有研究过)你可以使用autotools套件中的标准设备来完成它.
除非你自己创建一个仔细(甚至无情)对称的makefile,否则它将无法可靠地工作.