2012-01-13

Makefile example 1

#
# Introduction
#
# This is a Makefile example which can be used to build library or program from
# given directories. These directories could be at the same folder of the Makefile
# itself, or they could exist in other levels of the Makefile, sub-folders or
# parent-folders. 
#
# The Makefile searches all the .cpp files in the given folders and compile them
# into object files and link them into library or program. It generates dependency
# files automatically so that it can catch any change or the source files or 
# related header files.
#
# All the output of the make process is put in $(ODIR) folder. The default value
# is 'Build', but can be overriden with 'ODIR=xxx' when executing 'make'.   
#
#

# The folder where the Makefile exists
PWD := $(abspath $(shell pwd))

# A common folder which is parent-folder of all given folders in $(MODULES)
TOP_DIR := $(abspath ../../..)

# The default output folder, could be overriden with 'ODIR=xxx' when 'make'.
ODIR ?= Build

# The final targat. Should define only one of them: PROG or LIB
PROG := 
LIB := libapclient.a

# The modules (directories) that need to be built. All the .cpp files in these
# directories will be built automatically. They should be specified with prefix 
# of$(TOP_DIR).
MODULES   := \
  $(TOP_DIR)/Dingo/Client/AccessPoint/ServiceProxy \
  $(TOP_DIR)/Dingo/Client/AccessPoint/ServiceProxy/gSoap \
  $(TOP_DIR)/Dingo/Client/AccessPoint/Services/IncomingEventService/Source/DataObjects \
  $(TOP_DIR)/Dingo/Client/AccessPoint/Services/IncomingEventService/Source/MetadataObjects \
  $(TOP_DIR)/Dingo/Client/AccessPoint/Services/IncomingEventService/Source/Services \
$(TOP_DIR)/Dingo/Gateway/Siemens.Gateway.Linux.Client \
$(TOP_DIR)/Dingo/Client/AccessPoint/TinyXML
# The external libs need to be linked. This is used when build program.
LIBS :=

# CFLAGS for compiling. -MD -MP must be kept.
CFLAGS := -MD -MP -g -I. \
-I$(TOP_DIR)/Dingo/Gateway \
 -I$(TOP_DIR)/Dingo/Gateway/PlatformSpecific/CPP \
-I$(TOP_DIR)/Dingo/Client/AccessPoint/Services/IncomingEventService \
-I$(TOP_DIR)/Dingo/Client/AccessPoint/TinyXML

# LDFLAGS for linking. It's only used when build program.
LDFLAGS :=

# Cross compile option 
ifneq ($(ARM),yes)
CROSS_COMPILE
endif

################################################################################
# Below part should be considered as standard and normally don't need to change!
################################################################################

SRC_DIRS  := $(MODULES)
BUILD_DIRS:= $(addprefix $(ODIR),$(subst $(TOP_DIR),,$(MODULES)))

SRCS      := $(foreach sdir,$(SRC_DIRS),$(wildcard $(sdir)/*.cpp))
OBJS := $(patsubst %.cpp,%.o,$(addprefix $(ODIR),$(subst $(TOP_DIR),,$(SRCS))))
DEPS      := $(OBJS:.o=.d)

INCLUDES  := $(addprefix -I,$(SRC_DIRS))
CFLAGS += $(INCLUDES)

CC        := $(CROSS_COMPILE)g++
LD        := $(CROSS_COMPILE)g++
AR := $(CROSS_COMPILE)ar
ECHO := echo
MKDIR := mkdir -p
RM := rm -rf
LN := ln -sf

vpath %.cpp $(SRC_DIRS)

define make-goal
$1/%.o : %.cpp
@$(ECHO) "CC   $$<"
@$(CC) $(CFLAGS) -c $$< -o $$@

endef

.PHONY: all checkdirs clean 

all: checkdirs $(ODIR)/$(LIB) $(ODIR)/$(PROG)

ifneq ($(PROG),)
$(ODIR)/$(PROG): $(OBJS)
@$(ECHO) "LD   $@"
@$(LD) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
endif

ifneq ($(LIB),)
$(ODIR)/$(LIB): $(OBJS)
@$(ECHO) "AR   $@"
@$(AR) crs $@ $(OBJS)
endif

checkdirs: $(BUILD_DIRS)
$(BUILD_DIRS):
@$(ECHO) "MKDIR  $@"
@$(MKDIR) -p $@

clean:
@$(RM) $(BUILD_DIRS) $(ODIR)

$(foreach bdir,$(BUILD_DIRS),$(eval $(call make-goal,$(bdir))))

-include $(DEPS)

No comments:

Post a Comment