由于AM_INIT_AUTOMAKE中的subdir-objects选项,Autotools构建失败

7

我目前正在开发一个C++项目,该项目依赖于递归式的自动构建工具进行构建。 我想要构建一个共享库,该库中 src 目录下的 Makefile.am 如下所示:

# ...

# Library name
lib_LTLIBRARIES = libadapter-@MY_API_VERSION@.la

# Sources
libadapter_@MY_API_VERSION@_la_SOURCES = \
    $(top_builddir)/src/sourceA.cpp \
    $(top_builddir)/src/sourceB.cpp

# ...

自从版本1.14开始,当在configure.ac未指定AM_INIT_AUTOMAKE中的subdir-objects选项时,automake会发出警告。然而,添加subdir-objects选项似乎会导致构建过程中出现问题,使得make抱怨缺少.Plo文件。我已经搜索了网上遇到类似问题的人们,但没有找到任何明智的提示来解决此问题,而不必将项目更改为非递归式。任何帮助都将不胜感激。 编辑: 更深入地研究问题后,我注意到./configure创建了一个目录,名称为当前库源目录下的$(top_builddir),其中包含构建库所需的所有.Plo文件。然而,在Makefile中,我发现我的库源代码的.Plo等价物(例如sourceA.cppsourceB.cpp)以include $(top_builddir)/src/$(DEPDIR)/为前缀,并且$(top_builddir)是定义为相对路径的变量(即../../../src/.deps/)。现在很明显make为什么找不到.Plo文件了,因为它搜索了错误的目录。这看起来像是bug #16375的可能重复。有什么解决方法吗? 编辑2: 进一步深入网络后发现了两个更多的线程,其中讨论了此问题:#1327automake-bug。已知一个可行方法是将--disable-dependency-tracking选项传递给./configure。对我来说至少还可以运行。

我只是使用 ACLOCAL_AMFLAGS 来设置宏路径 (-I ...)。AM_INIT_AUTOMAKE 选项由 AUTOMAKE_OPTIONS 设置:1.11 foreign。就这样。 - ldav1s
另一方面,也许我并没有使用相对路径。也许我需要将 top_srcdir 切换为 abs_top_srcdir,将 top_builddir 切换为 abs_top_builddir。嗯... - ldav1s
@ldav1s - 听起来和我使用的差不多。似乎没有关于 top_builddirtop_srcdir 的问题,但是这个问题在很多地方都出现了,特别是在 1.14.x 版本中。 - Brett Hale
@Marcel - 你能提供有问题的Makefile.am文件吗? - Brett Hale
@Brett,我在我的问题中添加了Makefile.am的内容。 - Marcel
显示剩余9条评论
1个回答

11
automake-1.14.1 NEWS文件中:
The next major Automake version (2.0) will unconditionally activate
the 'subdir-objects' option.  In order to smooth out the transition,
we now give a warning (in the category 'unsupported') whenever a
source file is present in a subdirectory but the 'subdir-object' is
not enabled.  For example, the following usage will trigger such a
warning:

        bin_PROGRAMS = sub/foo
        sub_foo_SOURCES = sub/main.c sub/bar.c

在准备工作中,如果您使用上述描述的子目录来命名'object',则需要将subdir-objects作为AM_INIT_AUTOMAKE选项之一,此选项将默认为2.0版本开启。
如果您能提供失败目录的Makefile.am,可能会提供相对目录不匹配的原因线索。

好的,关于这个Makefile.am有几件事情需要注意。首先,有正确版本化libtool库的方法,而@MY_API_VERSION@替换不是正确的方法。例如,在configure.ac中可以形成一个数字字符串,然后跟随AC_SUBST(MY_API_VERSION)

Makefile.am中:libadapter_la_LDFLAGS = -release $(MY_API_VERSION)将把此信息放入libadapter.la libtool元文件中。

对于严格的版本控制,其中接口兼容性、修订版本、二进制兼容性等都是可取的,您可以查看versioning上的libtool参考。重要的系统库,特别是GNOME/GTK(查看它们的configure.ac文件!),会全力以赴地做这些事情。除非我考虑发布一些东西到公共领域,否则我肯定不会这样做。我仍然觉得这很困惑。

忽略@MY_API_VERSION@,你也可以使用libadapter_la_SOURCES。但是,源文件不会相对于任何builddir路径找到,这可能是您的.Plo文件问题的来源。 builddir变量描述了构建组件的位置-您还可以进行树外构建,这是测试您的automake设置是否健壮的好方法。一些软件包推广这种方法,例如,进入软件包的顶部,在那里创建一个名为buildmy_build或其他合适的目录:

cd my_build; ../configure <options>; make

软件包、它的源代码树和递归目录将被保持不变,所有内容都将在my_build目录下构建,并且子目录将镜像您的源代码树,只是它们将充满已构建的对象、库、可执行文件等。make install也应该可以使用生成的my_build/Makefile正常工作。

回到正题 - 这些源文件是相对于$(srcdir)目录的,该目录对应于当前(递归)Makefile.am的目录。各种builddirsrcdir变量在这里中有描述。

如果您的src目录位于顶级目录下,则可以使用:"$(top_srcdir)/src/sourceA.cpp" - 请注意,在这种情况下,"$(srcdir)/src/sourceA.cpp"将是错误的,因为它会像指定"$(top_srcdir)/src/src/sourceA.cpp"一样。

可以使用"$(srcdir)/sourceA.cpp",但是这个目录已经是隐式的了。您需要的只是:

libadapter_la_SOURCES = sourceA.cpp sourceB.cpp

将任何头文件放在libadapter使用的src目录中,加入到SOURCES列表中也是完全可以接受的。更改头文件将重新构建所需内容。


无论如何,我并不是想写这么多,但我知道获取有关Autotools的清晰信息是多么令人沮丧。 Autotools Mythbuster 提供了优秀的“步骤演示”教程,并保持非常更新。


我已经知道了automakeNEWS文件中的这个片段,但据我所知,如果在configure.ac中简单地将subdir-objects选项添加到AM_INIT_AUTOMAKE中,automake应该可以平稳地工作 - 无论在Makefile.am中使用相对路径还是绝对路径。如果我错了,请纠正我。 - Marcel
@Marcel - 我尝试解决了你的 Makefile.am 中出现的问题。希望对你有所帮助。 - Brett Hale
非常感谢您详尽的回答。我了解了top_srcdirtop_builddir之间的区别,但我不明白为什么用前者代替后者对于树内构建会有任何影响,因为这是我目前所做的。此外,省略MY_API_VERSION不应该有助于解决问题。与此同时,我认为我已经找到了构建失败的原因,请参见我的更新问题。 - Marcel
是的,我尝试过了,但没有任何效果 - 错误仍然存在。 - Marcel
将"subdir-objects"添加到我的AM_INIT_AUTOMAKE中解决了我的问题。谢谢。 - thedoctar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接