0
votes

I am beginning to learn autotools in order to first understand and later extend an existing project's build system. Currently the project builds a program as it's output. The build system is quite complex consisting of several subdirectories and Makefile.am's with files generated in a maintainer-mode and so on. I would like to optionally be able to create a library using much of the same source code, reusing much of the the existing build system.

What I am imagining is a new make target so that after running configure, I can then run either make to make the program, or, say, make library to build the library. What is the correct way to do this or something with a similar effect?

I do not want to build both the library and program when I run plain make (just the program as before), and I do not want to build the program when I run make library (I only want the library).

If someone could provide a simple example, e.g. a program made up of main.c, foo.c and bar.c and a library made up of foo.c and bar.c that would be really helpful too.

EDIT

To clarify, I originally thought that the program and lib could be built entirely separately. The library contains only a subset of the code of the main program, and I believed the two were separate entities. However, things are more complicated. The program itself is built and used to output some code which is then compiled into the program in a second step (I think). I have effectively got what I want by doing the following steps.

First add a conditional to configure.ac

dnl Adds LIBRARY conditional for --enable-foolib mode to
dnl build foo as a library
AC_ARG_ENABLE(foolib,
AS_HELP_STRING([--enable-foolib],
               [enable qucslib build, default: no]),
[case "${enableval}" in
             yes) foolib=true ;;
             no)  foolib=false ;;
             *)   AC_MSG_ERROR([bad value ${enableval} for --enable-foolib]) ;;
esac],
[foolib=false])

AM_CONDITIONAL(FOOLIB, test x"$foolib" = x"true")

Then in the appropriate Makefile.am I did something similar to the following:

if FOOLIB
noinst_LIBRARIES = libbar.a libfoo.a
else
noinst_LIBRARIES = libbar.a
endif

bin_PROGRAMS = barprog

barprog_SOURCES = main.cpp src1.cpp src2.cpp etc.cpp

barprog_LDADD = libbar.a              \
    subdir1/libsubdir1.a                  \
    subdir2/libsubdir2.a          \
    etcdir/libetc.a 

... other stuff

if FOOLIB
libfoo_a_LIBADD = libbar.a            \
    subdir1/libsubdir1.a                  \
    subdir2/libsubdir2.a          \
    etcdir/libetc.a 

libfoo_a_SOURCES = src1.cpp src2.cpp etc.cpp
endif

Then when I want to make the library I do

configure --enable-foolib
make

This works for now, but seems kludgy. I wasn't sure though how to implement the provided answer in the build system.

1
It can do that. What have you tried?ldav1s
Break them up. Put the library in one project, and the program in another.William Pursell

1 Answers

0
votes

If the program depends on the library, then it will not be possible to build the program without building the library. You already have the ability to build individual libraries: configure && make libfoo.a should work just fine (or make libfoo.la). If you wish a target named library, you can simply add the following to any Makefile.am:

library:
        libfoo.a

(Or you may need libfoo.la. Basically, if the library is specified in Makefile.am under the LIBRARIES primary, then you would use libfoo.a, but if specified under an LTLIBRARIES primary, you would use libfoo.la.) This will only create a library target in each directory that contains a Makefile.am. If you have a complex recursive build (you should really simplify it, but that's another question), you can put something like the following in your top-level Makefile.am to build the libraries throughout the tree:

library:
        cd subdir && $(MAKE) $(AM_MAKEFLAGS) library

This assumes you have added a library target to subdir/Makefile.am as described above.

To be pedantic, you might want to use $(am__cd) instead of cd, but it's not strictly necessary.