How to build *.so module in Automake and a libtool-using project?
One thing that could work according to the libtool documentation for LT_INIT is to partition your build into two packages: the main application and the plugins. That way you could (in theory) invoke:
./configure --enable-shared=plugins
and things would work the way you would expect.
I've solved a similar problem using the noinst_LTLIBRARIES macro.
The noinst_LTLIBRARIES macro creates static, non installable libraries to be only used internally. all noinst_LTLIBRARIES static libraries are created also if you specify the --disable-static configure option.
lib_LTLIBRARIES = libtokenclient.la
noinst_LTLIBRARIES = libtokenclient_static.la
libtokenclient_la_SOURCES = $(TOKEN_SERVER_CLIENT_SOURCES) cDynlib.c cDynlib.h token_mod.h
libtokenclient_la_CFLAGS = @BASE_CFLAGS@
libtokenclient_la_CXXFLAGS = $(libtokenclient_la_CFLAGS)
libtokenclient_la_LIBADD = @B_BASE_OS_LIBS@
libtokenclient_la_LDFLAGS = @LT_PLUGIN_LIBS_FLAGS@ @LIBS_FLAGS@ $(TOKEN_SERVER_CLIENT_EXPORT_SYMBOLS)
libtokenclient_static_la_SOURCES = $(libtokenclient_la_SOURCES)
libtokenclient_static_la_CFLAGS = $(libtokenclient_la_CFLAGS)
libtokenclient_static_la_CXXFLAGS = $(libtokenclient_static_la_CFLAGS)
token_test_SOURCES = $(TEST_SOURCES)
token_test_LDADD = @B_BASE_OS_LIBS@ libtokenclient_static.la
token_test_CFLAGS = @BASE_CFLAGS@
token_test_CXXFLAGS = $(token_test_CFLAGS)
I use noinst_LTLIBRARIES static libraries for 2 reasons:
- to speed up compile time I create static libraries to be used as intermediate containers for code that shall be linked against more than once: the code is compiled just once, otherwise automake would compile same source files once for each target
- to statically link the code to some executable
What you are looking for is called a module. You can tell Autotools to create a static binary (executable) by adding -all-static
to the LDFLAGS
of the application. I think this is the preferred way over using --disable-shared
configure flag (which really is aimed at the libraries rather than the executable)
Something like this should do the trick:
AM_CPPFLAGS=-I$(top_srcdir)/include
lib_LTLIBRARIES = module.la
module_la_LDFLAGS = -module -avoid-version -shared
module_la_SOURCES = mm_cpp_logger.cpp
bin_PROGRAMS = application
application_LDFLAGS = -all-static
application_SOURCES = main.cpp
The .so
file will (as usual) end up in the .libs/
subdirectory (unless you install it, of course).
And you can build both your application and plugins in one go (even with a single Makefile.am
), so there is no need to call configure
multiple times.
The use of -fPIC
(and friends) should be auto-detected by Autotools.
Update: here's a little trick to make the shared-libraries available where you expect them. Since all shlibs end up in .libs/
, it is sometimes nice to have them in a non-hidden directory.
The following makefile snippet creates convenience links (on platforms that support symlinks; otherwise they are copied). Simply adding the snippet to your makefile (i usually use an -include convenience-link.mk
) should be enough (you might need an AC_PROG_LN_S
in your configure.ac)
.PHONY: convenience-link clean-convenience-link
convenience-link: $(lib_LTLIBRARIES)
@for soname in `echo | $(EGREP) "^dlname=" $^ | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do \
echo "$$soname: creating convenience link from $(abs_builddir)/.libs to $(top_builddir)"; \
rm -f $(top_builddir)/$$soname ; \
test -e $(abs_builddir)/.libs/$$soname && \
cd $(top_builddir) && \
$(LN_S) $(abs_builddir)/.libs/$$soname $$soname || true;\
done
clean-convenience-link:
@for soname in `echo | $(EGREP) "^dlname=" $(lib_LTLIBRARIES) | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do \
echo "$$soname: cleaning convenience links"; \
test -L $(top_builddir)/$$soname && rm -f $(top_builddir)/$$soname || true; \
done
all-local:: convenience-link
clean-local:: clean-convenience-link