How to build a * .so module in Automake and a project using libtool?

I have the same problem as others :

  • I have a *.la file created by libtool in an Automake project (e.g. module.la ),
  • but I need *.so to use it for dlopen() (e.g. module.so ).

But: the project is configured and built using --disable-shared , to make sure that the generated main binary is one large statically linked program, for example. main.x (easier to deploy and debug). Therefore, *.so files are not created.

The main.x program is a huge framework application that can load extensions (modules) via dlopen() - despite the fact that it is connected statically.

This works great when I build module.so manually. But it seems impossible to do this for work in Makefile.am . Yes, I can write lib_LTLIBRARIES , but with my standard --disable-shared I don't get the *.so file.

 lib_LTLIBRARIES = module.la module_so_SOURCES = module.cpp 

A module.la file is module.la , which dlopen() refuses to load (of course).

I tried putting the rules in Makefile.am , building it manually, and this works:

 # Makefile.am (yes, .am) all: mm_cpp_logger.so SUFFIXES = .so %.so: %.cpp $(CXX) $(CXXFLAGS) -fPIC -fpic -c -I $(top_srcdir)/include -o $@ $< %.so: %.o $(CXX) $(LDFLAGS) -shared -fPIC -fpic -o $@ $< 

But this can only be a workaround. I do not get all the good automatic features like dependency checking and installation.

How can I build module.so while still creating the main program with --disable-shared (or with the same effect) in Makefile.am -way?

  • Can I post *.la files to *.so files with a special automake rule?
  • Can I configure the lib_LTLIBRARIES process to create *.so files anyway?
+10
shared-libraries libtool automake
source share
3 answers

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 application. I think this is the preferred way to use the --disable-shared setting flag (which is actually aimed at libraries, not the executable)

Something like this should work:

 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 (as usual) .libs/ subdirectory .libs/ (of course, if you do not install it).

And you can build your application and plugins at a time (even with one Makefile.am , so there is no need to call configure several times.

The use of -fPIC (and friends) should be automatically determined by Autotools.


Update : Here's a little trick to making shared libraries available where you expect them. Since all shlibs end in .libs/ , sometimes .libs/ have them in a non-hidden directory.

The following snippet of the makefile creates ancillary links (on platforms that support symbolic links; otherwise, they are copied). Just adding a snippet to your makefile (I usually use -include convenience-link.mk ) should be enough (you might need AC_PROG_LN_S in your configure.ac file)

 .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 
+12
source share

One thing that can work according to the libtool documentation for LT_INIT is to break your assembly into two packages: the main application and plugins. So you could (theoretically) call:

 ./configure --enable-shared=plugins 

and everything will work as you expected.

+1
source share

I solved a similar problem with the macro noinst_LTLIBRARIES .

The macro noinst_LTLIBRARIES creates static, non-installable libraries intended for internal use only. all static noinst_LTLIBRARIES libraries are also created if you specify the --disable-static configuration parameter.

 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 the noinst_LTLIBRARIES static libraries for two reasons:

  1. to speed up compilation time, I create static libraries for use as intermediate containers for code that needs to be linked more than once: the code compiles only once, otherwise automake will compile the same source files once for each purpose
  2. statically link code to some executable
0
source share

All Articles