automake 第三方库

Posted

技术标签:

【中文标题】automake 第三方库【英文标题】:automake third party libraries 【发布时间】:2015-06-05 23:18:44 【问题描述】:

如何用automake编译和链接第三方库?

我的文件结构是:

program/
  |
  +--src/
  |   |
  |   +--Makefile.am
  |   +--main.cpp
  |
  +--lib/
  |   |
  |   +--Makefile.am
  |   +--library.cpp
  |
  +--Makefile.am
  +--configure.ac
  +--README

automake 文件的内容非常通用:

# src/Makefile.am
bin_PROGRAMS = program
program_SOURCES = main.cpp

# Makefile.am
SUBDIRS = src lib
dist_doc_DATA = README

# configure.ac
AC_INIT([program], [1.0])
AM_INIT_AUTOMAKE([-Wall])
AC_PROG_CXX
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile src/Makefile lib/Makefile])
AC_OUTPUT

lib/Makefile.am的内容应该是什么?

【问题讨论】:

只是为了添加到@chrono 的答案,SUBDIRS 列出了深度优先下降的目录。由于src 依赖于lib 构建,因此考虑设置:SUBDIRS = lib src。您甚至可以添加. 目录来指导相对于当前目录的处理顺序。 【参考方案1】:

(当您似乎自己可以控制库代码时​​,不确定为什么要说“第三方”...有关使用 Automake 创建和使用库的更多信息,请参阅@ 987654321@)

lib/Makefile.am

lib_LIBRARIES = libYOURLIB.a
libYOURLIB_a_SOURCES = library.cpp

如果您不想安装库本身,可以使用noinst_lib_LIBRARIES。请注意,我假设您只想构建一个静态库。请参阅 GNU Automake 手册的 Building A Shared Library 部分,以与 Libtool 集成以生成共享库。您当然可以手动完成,但使用 Libtool 会容易得多,因为它可以处理各种平台差异。

要将您的库链接到program,您需要在src/Makefile.am中添加以下行:

program_DEPENDENCIES = $(top_builddir)/lib/libYOURLIB.a
program_LDADD = $(top_builddir)/lib/libYOURLIB.a

_DEPENDENCIES 行只是告诉 Automake program 依赖于首先构建的 lib/libYOURLIB.a_LDADD 行只是将库添加到链接器命令。


以上假设您已经有构建库的规则。由于您使用的是SUBDIRS,因此您收到了“没有规则使目标XXXXXX”构建失败,这表明您没有(至少从src 子目录中的Makefile 的角度来看)。为了解决这个问题,您可以在 src/Makefile.am 中尝试以下操作(取自 GNU Automake 邮件列表档案中的 "Re: library dependency"):

FORCE:

$(top_builddir)/lib/libYOURLIB.a: FORCE
<TAB>(cd $(top_builddir)/lib && $(MAKE) $(AM_MAKEFLAGS) libYOURLIB.a)

当然,您也可以简单地将lib 设为src 的子目录,如您的评论所示,并使其更简单。

或者,您可以停止使用递归构建设置并使用可能更简单的非递归构建设置。有关这方面的一些信息,请参阅 GNU Automake Manual §7.3: An Alternative Approach to Subdirectories 和 Non-recursive Automake,但一般的想法是改变一些事情以允许:

configure.ac

AM_INIT_AUTOMAKE([-Wall subdir-objects])
...
AC_CONFIG_FILES([Makefile])

Makefile.am

# Instead of using the SUBDIRS variable.
include src/Makefile.am.inc
include lib/Makefile.am.inc
dist_doc_DATA = README

lib/Makefile.am 重命名为 lib/Makefile.am.inc

# Full path relative to the top directory.
lib_LIBRARIES = lib/libYOURLIB.a
lib_libYOURLIB_a_SOURCES = lib/library.cpp

src/Makefile.am 重命名为 src/Makefile.am.inc

# Full path relative to the top directory.
bin_PROGRAMS = bin/program
bin_program_SOURCES = src/main.cpp
bin_program_DEPENDENCIES = lib/libYOURLIB.a
bin_program_LDADD = lib/libYOURLIB.a

重命名文件是可选的(您总是可以只使用include src/Makefile.am),但它有助于表明它并不是一个独立的 Automake 源文件。

另外,假设lib/library.cppsrc/main.cpp 都在#include "library.hpp" 中,并且它在另一个目录中,您可能还想对所有文件使用AM_CPPFLAGS = -I $(top_srcdir)/include 或对用于构建的所有源文件使用obj_program_CPPFLAGS = -I include bin/program,假设 library.hppprogram/include 中。我不确定$(top_srcdir) 是否正确,当另一个项目将您的整个program 源目录包含在它自己的SUBDIRS 变量中时,$(srcdir) 将始终引用***program 目录在这种情况下一个非递归的 automake,使其在包含此包作为组件的大型项目中可能更有用。

【讨论】:

我已经相应地修改了lib/Makefile.amsrc/Makefile.am,但是在将AC_PROG_RANLIB添加到configure.ac之后,我得到了另一个错误No rule to make target ../../src/../lib/libtest.a 到目前为止,我的解决方法是将 lib 移动到 src/lib 并仅修改 src/Makefile.am => program_SOURCES = main.cpp lib/library.cpp @Daveel 现在对我来说似乎很明显为什么会发生这种情况,但当时我根本没有意识到会发生这种情况。我已经编辑了我的评论,以解释您拥有的其他选项。

以上是关于automake 第三方库的主要内容,如果未能解决你的问题,请参考以下文章

包括使用 automake 和 autoconf 的动态库

Automake/libtool 不构建共享库

Automake:如何在不安装的情况下构建共享库

Automake 包含所有库

automake 和 libtool 中的链接库问题

有没有办法在 Automake 中引用库?