autotools可以创建多平台makefile吗

发布于 2024-07-09 16:00:24 字数 531 浏览 7 评论 0原文

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

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

编辑:

我已经滚动自己的解决方案一段时间了,我有一个精美的 makefile 和一些 perl 脚本来寻找各种第 3 方库版本等。因此,我对其他库持开放态度非自动工具解决方案。 对于其他构建工具,我希望最终用户能够非常轻松地安装它们。 这些工具还需要足够智能,能够轻松地找到各种第 3 方库和标头。 我主要是在寻找一种 Linux 解决方案,但如果一个也适用于 Windows 和/或 Mac 的解决方案将是一个额外的好处。

I have a plugin project I've been developing for a few years where the plugin works with numerous combinations of [primary application version, 3rd party library version, 32-bit vs. 64-bit]. Is there a (clean) way to use autotools to create a single makefile that builds all versions of the plugin.

As far as I can tell from skimming through the autotools documentation, the closest approximation to what I'd like is to have N independent copies of the project, each with its own makefile. This seems a little suboptimal for testing and development as (a) I'd need to continually propagate code changes across all the different copies and (b) there is a lot of wasted space in duplicating the project so many times. Is there a better way?

EDIT:

I've been rolling my own solution for a while where I have a fancy makefile and some perl scripts to hunt down various 3rd party library versions, etc. As such, I'm open to other non-autotools solutions. For other build tools, I'd want them to be very easy for end users to install. The tools also need to be smart enough to hunt down various 3rd party libraries and headers without a huge amount of trouble. I'm mostly looking for a linux solution, but one that also works for Windows and/or the Mac would be a bonus.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

请持续率性 2024-07-16 16:00:24

如果你的问题是:

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

那么答案是“否”。 自动工具甚至不假装试图做到这一点。 它们被设计为包含可移植代码,这些代码将确定如何在目标机器上创建可用的 makefile。

如果你的问题是:

我可以使用自动工具来配置需要在不同机器上运行的软件,以及我的插件所使用的主要软件的不同版本以及各种第三方库,更不用说 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; 有太多的可能性使这种做法变得不明智。 但自动工具会为我(和我的用户)处理细节。 他们所做的就是:

./configure

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


福兹先生评论道:

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

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

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

(其中 tppkg 是第三方包的代码,并且位置可由用户指定。)但是,记住可用性:用户提供的此类选项越少越好; 与此相反,不要对应该可选的内容进行硬编码,例如安装位置。 无论如何,请查看默认位置 - 这很好。 并默认你找到的东西的细节。 也许如果您同时找到 32 位和 64 位版本,那么您应该构建两者 - 但这需要仔细构建。 您始终可以回显“正在检查 TP 包...”并指出您发现了什么以及在哪里找到它。 然后安装程序可以更改选项。 确保在“./configure --help”中记录了选项的内容; 这是标准的自动工具实践。

但不要做任何互动的事情; 配置脚本应该运行,并报告它的作用。 Perl Configure 脚本(注意大写字母 - 它是一个完全独立的自动配置系统)是剩下的少数几个密集交互的配置系统之一(这可能主要是因为它的遗产;如果重新开始,它很可能是非交互式的)。 与非交互式系统相比,此类系统的配置更加麻烦。

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


福兹先生还评论道:

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

./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< /code>' 用于存储单独的目标文件集。 您还可以按照以下方式安排您的 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,您可以指定(在 .co 规则中):

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

宏 CFLAGS 将包括处理位的 ${FLAGS} 值(例如,FLAGS_32 = -m32 和 FLAGS_64 = -m64,因此在构建 32 位版本时,FLAGS = -m32将包含在CFLAGS`宏中。

自动工具中的剩余问题是如何确定 32 位和 64 位标志。但是,我希望(没有研究过)您可以使用自动工具套件中的标准设施来完成它,

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

If your question is:

Can I use the autotools on some machine A to create a single universal makefile that will work on all other machines?

then the answer is "No". The autotools do not even make a pretense at trying to do that. They are designed to contain portable code that will determine how to create a workable makefile on the target machine.

If your question is:

Can I use the autotools to configure software that needs to run on different machines, with different versions of the primary software which my plugin works with, plus various 3rd party libraries, not to mention 32-bit vs 64-bit issues?

then the answer is "Yes". The autotools are designed to be able to do that. Further, they work on Unix, Linux, MacOS X, BSD.

I have a program, SQLCMD (which pre-dates the Microsoft program of the same name by a decade and more), which works with the IBM Informix databases. It detects the version of the client software (called IBM Informix ESQL/C, part of the IBM Informix ClientSDK or CSDK) is installed, and whether it is 32-bit or 64-bit. It also detects which version of the software is installed, and adapts its functionality to what is available in the supporting product. It supports versions that have been released over a period of about 17 years. It is autoconfigured -- I had to write some autoconf macros for the Informix functionality, and for a couple of other gizmos (high resolution timing, presence of /dev/stdin etc). But it is doable.

On the other hand, I don't try and release a single makefile that fits all customer machines and environments; there are just too many possibilities for that to be sensible. But autotools takes care of the details for me (and my users). All they do is:

./configure

That's easier than working out how to edit the makefile. (Oh, for the first 10 years, the program was configured by hand. It was hard for people to do, even though I had pretty good defaults set up. That was why I moved to auto-configuration: it makes it much easier for people to install.)


Mr Fooz commented:

I want something in between. Customers will use multiple versions and bitnesses of the same base application on the same machine in my case. I'm not worried about cross-compilation such as building Windows binaries on Linux.

Do you need a separate build of your plugin for the 32-bit and 64-bit versions? (I'd assume yes - but you could surprise me.) So you need to provide a mechanism for the user to say

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

(where tppkg is a code for your third-party package, and the location is specifiable by the user.) However, keep in mind usability: the fewer such options the user has to provide, the better; against that, do not hard code things that should be optional, such as install locations. By all means look in default locations - that's good. And default to the bittiness of the stuff you find. Maybe if you find both 32-bit and 64-bit versions, then you should build both -- that would require careful construction, though. You can always echo "Checking for TP-Package ..." and indicate what you found and where you found it. Then the installer can change the options. Make sure you document in './configure --help' what the options are; this is standard autotools practice.

Do not do anything interactive though; the configure script should run, reporting what it does. The Perl Configure script (note the capital letter - it is a wholly separate automatic configuration system) is one of the few intensively interactive configuration systems left (and that is probably mainly because of its heritage; if starting anew, it would most likely be non-interactive). Such systems are more of a nuisance to configure than the non-interactive ones.

Cross-compilation is tough. I've never needed to do it, thank goodness.


Mr Fooz also commented:

Thanks for the extra comments. I'm looking for something like:

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

where it would create both the 32-bit and 64-bit targets in one makefile for the current platform.

Well, I'm sure it could be done; I'm not so sure that it is worth doing by comparison with two separate configuration runs with a complete rebuild in between. You'd probably want to use:

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

This indicates the two separate directories. You'd have to decide how you're going to do the build, but presumably you'd have two sub-directories, such as 'obj-32' and 'obj-64' for storing the separate sets of object files. You'd also arrange your makefile along the lines of:

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

This assumes that the plugin would be a shared object. The idea here is that the autotool would detect the 32-bit or 64-bit installs for the Third Party Package, and then make substitutions. The BUILD_32 macro would be set to build_32 if the 32-bit package was required and left empty otherwise; the BUILD_64 macro would be handled similarly.

When the user runs 'make all', it will build the build_32 target first and the build_64 target next. To build the build_32 target, it will re-run make and configure the flags for a 32-bit build. Similarly, to build the build_64 target, it will re-run make and configure the flags for a 64-bit build. It is important that all the flags affected by 32-bit vs 64-bit builds are set on the recursive invocation of make, and that the rules for building objects and libraries are written carefully - for example, the rule for compiling source to object must be careful to place the object file in the correct object directory - using GCC, for example, you would specify (in a .c.o rule):

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

The macro CFLAGS would include the ${FLAGS} value which deals with the bits (for example, FLAGS_32 = -m32 and FLAGS_64 = -m64, and so when building the 32-bit version,FLAGS = -m32would be included in theCFLAGS` macro.

The residual issues in the autotools is working out how to determine the 32-bit and 64-bit flags. If the worst comes to the worst, you'll have to write macros for that yourself. However, I'd expect (without having researched it) that you can do it using standard facilities from the autotools suite.

Unless you create yourself a carefully (even ruthlessly) symmetric makefile, it won't work reliably.

も让我眼熟你 2024-07-16 16:00:24

据我所知,你不能这样做。 但是,您是否被自动工具困住了? 既不是 CMake 也不是 SCons 一个选项?

As far as I know, you can't do that. However, are you stuck with autotools? Are neither CMake nor SCons an option?

将军与妓 2024-07-16 16:00:24

我们尝试过,但行不通! 所以我们现在使用SCons

有关此主题的一些文章:12

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

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

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

make 相比,您使用的是 Python,这是一种完整的编程语言! 记住这一点,你就可以做任何事情(或多或少)。

We tried it and it doesn't work! So we use now SCons.

Some articles to this topic: 1 and 2

Edit:
Some small example why I love SCons:

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

With this line of code you add GLib to the compile environment (env). And don't forget the User Guide which just great to learn SCons (you really don't have to know Python!). For the end user you could try SCons with PyInstaller or something like that.

And in comparison to make, you use Python, so a complete programming language! With this in mind you can do just everything (more or less).

沫尐诺 2024-07-16 16:00:24

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

可以执行以下操作:

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

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

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

make -C build1 -C build2 -C build3

Have you ever considered to use a single project with multiple build directories?
if your automake project is implemented in a proper way (i.e.: NOT like gcc)

the following is possible:

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

you are able to pass different configuration parameters like include directories and compilers (cross compilers i.e.).

you can then even run this in a single make call by running

make -C build1 -C build2 -C build3
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文