In my project, modules are organized in subdirs for tidiness.
My project dir hierarchy:
$ ls -R .: configure.in Makefile.am Makefile.cvs src ./src: log Makefile.am main.cpp ./src/log: log.cpp Makefile.am
configure.in:
AC_INIT(configure.in) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE(myapp, 0.1) AC_LANG_CPLUSPLUS AC_PROG_CXX AM_PROG_LIBTOOL AC_OUTPUT(Makefile src/Makefile src/log/Makefile)
Makefile.am:
AUTOMAKE_OPTIONS = foreign SUBDIRS = src
Makefile.cvs:
default: aclocal libtoolize --force --copy autoheader automake --add-missing --copy autoconf
src/Makefile.am
bin_PROGRAMS = myapp myapp_SOURCES = main.cpp SUBDIRS = log myapp_LDADD = $(top_builddir)/src/log/liblog.la
src/log/Makefile.am:
INCLUDES = $(all_includes) METASOURCES = AUTO noinst_LTLIBRARIES = liblog.la liblog_la_SOURCES = log.cpp
src/main.cpp: contains int main(){}, src/log/log.cpp contains void f(){}.
Invoking make produces (edited for brevity):
libtool --mode=compile g++ -MT log.lo -MD -MP -MF .deps/log.Tpo -c -o log.lo log.cpp libtool: compile: g++ -MT log.lo -MD -MP -MF .deps/log.Tpo -c log.cpp -fPIC -DPIC -o .libs/log.o libtool: compile: g++ -MT log.lo -MD -MP -MF .deps/log.Tpo -c log.cpp -o log.o >/dev/null 2>&1 mv -f .deps/log.Tpo .deps/log.Plo libtool --mode=link g++ -o liblog.la log.lo libtool: link: ar cru .libs/liblog.a .libs/log.o libtool: link: ranlib .libs/liblog.a libtool: link: ( cd '.libs' && rm -f 'liblog.la' && ln -s '../liblog.la' 'liblog.la' ) g++ -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.cpp mv -f .deps/main.Tpo .deps/main.Po libtool --mode=link g++ -o myapp main.o ../src/log/liblog.la libtool: link: g++ -o myapp main.o ../src/log/.libs/liblog.a
The problem is the first three lines: log.cpp is compiled twice!
The question: why isn’t it just compiled once — taking half the time?
note: I have no idea what I’m doing — autotools is black magic to me, but we have to use it in our place. The docs are incomprehensible to me.
By default Libtool creates two types of libraries: static and shared. (aka libfoo.a and libfoo.so)
Static and shard require different compilation flags. Dynamic libraries — shared objects use Position Independent Code with following gcc flags:
Static are not. You can force build only one type by specifing
or
Rationale
Usually when library is provided for user it provide in two setups — static for development that allows create pure static builds and dynamic for use by most of programs that use this library. So, usually when you install library in the system you only install shared object. (aka libfoo_XYZ.deb)
When you add development version (aka libfoo-dev_XYZ.deb) you add headers and statically build version of the library that allows users make staic builds if they whant.
This is common practice for shipping libraries in UNIX. Thus libtool does this for you automatically.