Thursday, November 29, 2007

Seven steps to write a functioning Makefile

In my opinion, writing a Makefile is not simple, it sometimes can be more complicated if you want to your code compiled with different compilers, different running environments or targets, and different builds to support diffent features. A Makefile can accept shell or sed scripts, it makes the building process more advance. Today, I just want to cover the basic part of Makefile, or the parts I am using for a Makefile.

First define directory variables, you specifies this to tell `make' where is your project?

PROJECT_ROOT_DIR = /devel/src/foo


Second, specify the common compiler settings, most of my time is build for embedded target, so here is the code:

export ARCH :=arm
export CROSS_COMPILE := arm-linux-

#
# Include make variables (CC, etc...)
#
ASM := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
CC := $(CROSS_COMPILE)gcc
CXX := $(CROSS_COMPILE)g++
AR := $(CROSS_COMPILE)ar


3rd, specifies the source code compileing rules, how you compile c++ or c code. The rules will make the later life easier


%.o : %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<

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


Fourth, is more specific compiling setting, you define CFLAGS, CXXFLAGS, or LDFLAGS, so you specify what header directory to include, you specify what library to link, you also specify "-g" for debug, and how you want the compiler post warning message etc.

CFLAGS += -I$(PROJECT_ROOT_DIR)/include
CFLAGS += -I$(INCLS) -D_FOO_=1 -g


Fiveth, now you can provide the basic feature you want in the Makefile. Here is the sample:

compile: libfoo foo_bin

You want the user use "make compile" for build foo.

Sixth, specifiy all source code you build in seperate directories.

SRCS_FOO_DIR = $(PROJECT_ROOT_DIR)/src
SRCS_FOO = $(SRCS_FOO_DIR)/util_arm.s \
$(SRCS_FOO_DIR)/foo_info.c \
$(SRCS_FOO_DIR)/foo_main.c $(FOO_SRC_DIR)/foo_help.c
OBJS_FOO = $(patsubst %.s,%.o, $(patsubst %.c,%.o, $(SRCS_FOO)))
$(OBJS_FOO) : INCLS=-I$(SRCS_FOO_DIR)

SRCS_GST_DIR = $(PROJECT_ROOT_DIR)/gst
SRCS_GST = $(SRCS_GST_DIR)/gst.c
OBJS_GST = $(SRCS_GST:.c=.o)
$(OBJS_GST) : INCLS=-I$(SRCS_GST_DIR)


Seventh, now weave them together.


libfoo : $(OBJS_FOO) $(OBJS_GST)
$(CC) $(CFLAGS) -shared -o $@.so $^


For now, the Makefile is done, to add "clean" feature, is quite simple based the content from here.