我有一个项目目前使用通信库进行通信。该库不是通用的;它只在某些机器上运行。我想移植我的项目以便能够使用其他库进行通信。为此,我定义了一个具有不同实现的抽象层。这些实现由多个文件组成,因此我想将它们分组到不同的文件夹中。
例如,我可能有一个使用 tcp 的实现,另一个使用一些系统 native 库进行通信。我的 src
文件夹中有一个文件夹 tcp
和一个文件夹 native
。我希望自动工具使用一种在配置时通过 --with-comm=XXX
选择的实现。
如何构建 Makefile.am 来实现这一点?我读过这个:Different implementations in different files in autotools , 但是那个只针对不同的实现使用不同的文件,但我想使用文件夹。
最佳答案
您可以使用 AC_ARG_WITH
configure.ac
中的宏,但使用 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
会很好,但据我所知这是行不通的。此外,如果您使用 make dist
,此方法会在分发中自动包含 tcp
和 native
文件夹。无需将两者都放在 EXTRA_DIST
中列表,但如果可选“层”的数量变得笨重,这可能是更好的方法。
如果我正确理解了您的意见,那么简单的方法是将 src
文件包含在子目录 build 中,这样 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.h
、wrapper.c
等添加到其 EXTRA_DIST
变量。虽然这应该可行,但这不是处理事情的“正确”方法......
适当的库应该在 src
中构建,这意味着在 tcp
或 native
中使用方便的库,并让 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.
随着您的“核心”和“层”库变得越来越复杂,这是一种更具前瞻性的方法 - 它们将会:)
关于c - 如何告诉自动工具在不同的文件夹中使用不同的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17347970/