views:

263

answers:

1

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.

+1  A: 

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:

-fPIC -DPIC

Static are not. You can force build only one type by specifing

./configure --disable-shared

or

./configure --disable-static

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.

Artyom
thanks, --disable-shared works like a charm!
As a side question, is my Makefile.cvs good? I copied it from somewhere because it allowed me to get rid of a bunch of useless files, like "depcomp" or "config.h.in"
The commands in your Makefile.cvs are generally go to autogen.sh
Artyom
There's nothing in there that looks like it needs a custom `autogen.sh`, I think the OP could be fine just running `autoreconf -i` to bootstrap the project. Also, to put the scripts like `depcomp` out of sight, add `AC_CONFIG_AUX_DIR([auxfiles])` to configure.ac. To hide the *.m4 files added by `libtoolize`, add `AC_CONFIG_MACRO_DIR([m4])` to configure.ac, and `ACLOCAL_AMFLAGS = -I m4` to your top-level Makefile.am.
Jack Kelly