如何告诉自动工具在不同的文件夹中使用不同的实现

时间:2013-06-27 16:02:43

标签: c autotools automake

我有一个目前使用通信库进行通信的项目。该库不是通用的;它只能在某些机器上运行。我想移植我的项目,以便能够使用其他库进行通信。为此,我定义了一个具有不同实现的抽象层。这些实现由几个文件组成,因此我想将它们分组到不同的文件夹中。

例如,我可能有一个使用tcp的实现,另一个使用一些系统本机库进行通信。我的tcp文件夹中有一个文件夹native和一个文件夹src。我希望autotools使用在配置时使用--with-comm=XXX选择的一个实现。

如何构建Makefile.am来实现这一目标?我读过这个:Different implementations in different files in autotools, 但是那个只使用不同的文件用于不同的实现,但我想使用文件夹。

1 个答案:

答案 0 :(得分:2)

您可以使用configure.ac中的AC_ARG_WITH宏,但更适合将AC_ARG_ENABLE用于内部编译时功能。例如,在configure.ac中:

AC_ARG_ENABLE([comm], [AS_HELP_STRING([--enable-comm[[=tcp]]],
                  [specify a communications layer (default=tcp)])],
              , [enable_comm=yes])

enable_comm=`echo $enable_comm` # strip whitespace.

if test "x$enable_comm" = "xyes" || "x$enable_comm" = "xtcp" ; then
  enable_tcp="yes"
elif test "x$enable_comm" = "xnative" ; then
  enable_native="yes"
elif test "x$enable_comm" = "xno" ; then
  ; # ... error message? default to a dummy layer implementation?
else
  AC_MSG_ERROR([unknown option: '$enable_comm' for --enable-comm])
fi

AM_CONDITIONAL([ENABLE_COMM_TCP], [test "x$enable_tcp" = "xyes"])
AM_CONDITIONAL([ENABLE_COMM_NATIVE], [test "x$enable_native" = "xyes"])
...
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_FILES([src/tcp/Makefile src/native/Makefile])
...
AC_OUTPUT

当然,您可以在帮助字符串中添加任何内容,并以不同方式设置默认值。

src/Makefile.am

if ENABLE_COMM_TCP
COMM_DIR = tcp
endif

if ENABLE_COMM_NATIVE
COMM_DIR = native
endif

SUBDIRS = . $(COMM_DIR) # or '$(COMM_DIR) .' for depth-first order.

由于automake的工作方式,存在一些限制。能够通过条件变量设置COMM_DIR会很高兴,但是AFAIK并不起作用。此外,如果您使用tcp,此方法会自动在分发中包含nativemake dist个文件夹。没有必要放在EXTRA_DIST列表中,但如果可选的'层的数量可能是更好的方法。变得笨拙。


如果我正确理解您的评论,那么简单的方法是将src文件包含在子目录构建中,因此src/tcp/Makefile.am将使用:

lib_LTLIBRARIES = libcomm.la
libcomm_la_SOURCES = driver.h driver.c ../comm.h ../wrapper.c ...

如果需要将comm.h指定为$(srcdir)/../comm.h,树外构建才能正常工作,我无法记得。 src/Makefile.am可能需要也可能不需要将comm.hwrapper.c等添加到其EXTRA_DIST变量中。虽然这应该有用,但它并不是“正确的”。如何去做事......


正确的库应该在src中构建,这意味着在tcpnative中使用便捷库,让libtool担心其余部分。例如,src/Makefile

lib_LTLIBRARIES = libcomm.la
libcomm_include_HEADERS = comm.h
libcomm_la_SOURCES = comm.h wrapper.c utils.c ...
libcomm_la_LIBADD = ./$(COMM_DIR)/libcomm_layer.la

还需要订购:SUBDIRS = $(COMM_DIR) .

src/tcp/Makefile.am

AM_CPPFLAGS += -I$(srcdir)/.. # look for core headers in src

noinst_LTLIBRARIES = libcomm_layer.la # not for installation.
libcomm_layer_la_SOURCES = driver.h driver.c ...
# libcomm_layer_la_LDFLAGS = -static # optional... an archive is preferable.

这是一种更具前瞻性的方法,作为您的核心'和'层'图书馆变得更加复杂 - 他们会:)