It Seemed Like a Good Idea at the Time Coding, Mostly

5May/090

Revenge of the Super-Makefile

So today I found some more things that the old Makefile was lacking. An "install" target, a ".PHONY" target to prevent breakage down the line, and the ability to recursively build subprojects. A few hours later, I have this:

PROJECT=foo
VERSION=0.0.1
SOURCES=bar.c baz.c
SUBPROJECTS=xyzzy fnord
LIBRARY=-lm
INCPATHS=xyzzy fnord
LIBPATHS=fnord
PREFIX=/usr/local
LDFLAGS=
CFLAGS=-c -Wall -g
CC=gcc

# ------------ MAGIC BEGINS HERE -------------

# We want subprojects to use these variables
export CC
export PREFIX

# Automatic generation of some important lists
OBJECTS=$(SOURCES:.c=.o)
INCFLAGS=$(foreach TMP,$(INCPATHS),-I$(TMP))
LIBFLAGS=$(foreach TMP,$(LIBPATHS),-L$(TMP))

# Set up the output file names for the different output types
ifeq "$(LIBRARY)" "shared"
    BINARY=lib$(PROJECT).so
else ifeq "$(LIBRARY)" "static"
    BINARY=lib$(PROJECT).a
else
    BINARY=$(PROJECT)
endif

all: $(SOURCES) $(SUBPROJECTS) $(BINARY)

$(BINARY): $(OBJECTS)
ifdef SOURCES
    # Assemble the object files into the right type of binary
    ifeq "$(LIBRARY)" "static"
        ar rcs $(BINARY) $(OBJECTS)
    else ifeq "$(LIBRARY)" "shared"
        $(CC) -shared $(LIBFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
    else
        $(CC) $(LIBFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
    endif
endif

$(SUBPROJECTS):
        make -e -C $@

.c.o:
        $(CC) $(INCFLAGS) $(CFLAGS) -fPIC $< -o $@

install:
        @ for i in $(SUBPROJECTS); do make -e -C $${i} install; done
ifdef SOURCES
    ifeq "$(LIBRARY)" "static"
        install $(BINARY) $(PREFIX)/lib
    else ifeq "$(LIBRARY)" "shared"
        install $(BINARY) $(PREFIX)/lib
    else
        install $(BINARY) $(PREFIX)/bin
    endif
endif

distclean:
        rm -f $(BINARY) $(OBJECTS)
        @ for i in $(SUBPROJECTS); do make -C $${i} distclean; done

clean:
        rm -f $(OBJECTS)
        @ for i in $(SUBPROJECTS); do make -C $${i} clean; done

.PHONY: all clean distclean install $(SUBPROJECTS)

It's longer, but not by too much, and now I can safely say it has everything I have ever needed in a fancy build system. It would be nice if I could get pretty colourized output, but this Makefile reliably builds, cleans, and installs the projects I have tested it on.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment


No trackbacks yet.