Search code examples
cvariablesmakefilebuild-processgnu-make

Makefile recursive not passing CPPFLAGS


First of all, sorry if I end up making a too long post, but I think it would be missing information otherwise.

I'd like to include my repository version in each build. There is a main makefile that masters some other ones in their respective subdirectories. The subprojects are "automaked".

I am trying to pass a variable containing the svnversion to inner Makefiles like this:

# Main Makefile

SUBDIRS = sd1 sd2
REPO_VERSION = `svnversion`
export ECHO = @echo
export CPPFLAGS

all: versioned
    $(ECHO) "Build of all projects in $(PWD) finished."

clean :
    $(ECHO) "Cleaning up entire project tree..."
    -for d in $(SUBDIRS); do ($(ECHO) "Cleaning up \"$$d\""; $(MAKE) -C $$d clean ); done

.PHONY: versioned unversioned $(SUBDIRS)

versioned:  CPPFLAGS = -DREPO_VERSION=\"v$(REPO_VERSION)\"

versioned:  subdirs

unversioned:    subdirs

versioned unversioned:
    $(ECHO) "Build $@ finished."

subdirs: $(SUBDIRS)

$(SUBDIRS):
    $(ECHO) "== Building $@                      =="
    $(ECHO) "    [ CPPFLAGS = \"$(CPPFLAGS)\" ]"
    ( cd $@ && \
        ( [ -f Makefile ] || \
            ( aclocal       && \
            autoheader  && \
            automake --foreign --add-missing && \
            autoconf    && \
            configure ) )   && \
        $(MAKE) \
        )

Each subdirectory has a Makefile.am and configure.ac like this:

Makefile.am:

# Makefile.am in "sd1" and "sd2"

bin_PROGRAMS = app
app_SOURCES = source.c

configure.ac:

AC_PREREQ(2.59)

AC_INIT([app], [1.00], [<suport@domain>])
AM_INIT_AUTOMAKE

AC_CONFIG_HEADER([config.h])

# Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET

# Checks for header files.
AC_HEADER_STDC

# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T

# Output configuration files.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

I expected this to work, but autotools are embedding REPO_VERSION in the makefile when run, and changes in the main Makefile's REPO_VERSION are ignored in further builds.

A piece of an output looks like this:

== Building sd1                      ==
    [ CPPFLAGS = "-DREPO_VERSION="1050"" ]
( cd sd1 && \
        ( [ -f Makefile ] || \
                ( aclocal               && \
                autoheader      && \
                automake --foreign --add-missing && \
                autoconf        && \
                configure ) )   && \
        make \
        )
make[1]: Entrando no diretório `./recursive/sd1'
make  all-am
make[2]: Entrando no diretório `./recursive/sd1'
gcc -DHAVE_CONFIG_H -I.   -DREPO_VERSION=\"1049M\"  -g -O2 -MT source.o -MD -MP -MF .deps/source.Tpo -c -o source.o source.c
mv -f .deps/source.Tpo .deps/source.Po
gcc  -g -O2   -o app source.o
make[2]: Saindo do diretório `./recursive/sd1'
make[1]: Saindo do diretório `./recursive/sd1'

The program outputs:

> ./sd1/appVersão = [1049M].

This clearly is not what I wanted.

Can anybody here please give a way to fix this?

Thanks.


Solution

  • In your top level make file add

    export REPO_VERSION
    

    and modify each Makefile.am to have

    REPO_VERSION ?= unknown
    AM_CPPFLAGS = -DREPO_VERSION="$(REPO_VERSION)"
    

    The export directive makes it so that the value of REPO_VERSION is exported to recursive make invocations. The Makefile.am snippet sets a default value for REPO_VERSION if it is not given (e.g. make is run from the shell in the subdirectory) and AM_CPPFLAGS specifies the default value of CPPFLAGS for all targets in that Makefile. If you have a target specific _CPPFLAGS variable, you should either add $(AM_CPPFLAGS) to that or include the -DREPO_VERSION="$(REPO_VERSION)" in it. With a bit more effort you can add some stuff into the configure.ac files so that the default for REPO_VERSION can be set at configure time.