Reputation: 321
I have a project that currently uses a communication library for communication. The library is not generic; it only runs on some machines. I want to port my project to be able to use a other libraries for communication. To do that, I defined a abstract layer that has different implementations. These implementations are consists of several files, so I want to group them into different folders.
For example, I might have a implementation that uses tcp, and another uses some system native library for communication. I have a folder tcp
and a folder native
in my src
folder. I want the autotools to use one implementation that is selected at configure time with --with-comm=XXX
.
How do I structure the Makefile.am to achieve this? I've read this: Different implementations in different files in autotools, but that one uses only different files for different implementations, but I want to use folders.
Upvotes: 1
Views: 90
Reputation: 22318
You can use the AC_ARG_WITH
macro in configure.ac
, but it's more appropriate to use AC_ARG_ENABLE
for internal, compile-time features. e.g., in 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
You can, of course, put whatever you like in the help string, and set defaults differently.
In 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.
There are limitations because of the way automake works. It would be nice to be able to set COMM_DIR
through a condition variable, but AFAIK this doesn't work. Furthermore, this approach automatically includes both tcp
and native
folders in the distribution if you use make dist
. There's no need to put either in the EXTRA_DIST
list, though it might be a better approach if the number of optional 'layers' becomes unwieldy.
If I understand your comments correctly, then the simple way would be to include the src
files in the subdirectory build, so src/tcp/Makefile.am
would use:
lib_LTLIBRARIES = libcomm.la
libcomm_la_SOURCES = driver.h driver.c ../comm.h ../wrapper.c ...
I can't remember offhand if comm.h
needs to be specified as $(srcdir)/../comm.h
for out-of-tree builds to work correctly. src/Makefile.am
may or may not need to add comm.h
, wrapper.c
, etc., to its EXTRA_DIST
variable. While this should work, it's not the 'right' way to go about things...
The library proper should be built in src
, and that means using convenience libraries in either tcp
or native
, and letting libtool
worry about the rest. e.g., 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
It will also be necessary to order: SUBDIRS = $(COMM_DIR) .
In 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.
This is a more future-proof approach as your 'core' and 'layer' libraries become more complex - and they will:)
Upvotes: 2