Skip to content

GNU/Linux智能Makefile模板(多目录,多文件)

参考:

http://www.voidcn.com/article/p-rkpadnqa-bkn.html

http://www.voidcn.com/article/p-mpuyxady-kg.html

http://bbs.chinaunix.net/thread-3553668-1-1.html

https://gist.github.com/mauriciopoppe/de8908f67923091982c8c8136a063ea6

###############################################################################
#
# A smart Makefile template for GNU/LINUX programming
#
# Author: PRC (ijkxyz AT msn DOT com)
# Date:   2011/06/17
#
# Usage:
#   $ make           Compile and link (or archive)
#   $ make clean     Clean the objectives and target.
###############################################################################

CROSS_COMPILE =
OPTIMIZE := -O2 #其他选项:调试: -g
WARNINGS := -Wall -Wno-unused -Wno-format #其他选择: -Wno-deprecated -Wno-write-strings
#macro define
DEFS     := -DOS_COMMON_EXT -DNDEBUG -D_FILE_OFFSET_BITS=64
EXTRA_CFLAGS := -c -fvisibility=hidden -std=c++11
# 输出路径
OUT_DIR   = ../lib/linux.x64
# 多个路径,使用 空格 隔开
INC_DIR   = . ../include ../../..
# 多个路径,使用 空格 隔开
SRC_DIR   = ./src1 . ./src2 ./src3
# 需要链接的动态库的路径
LIB_DIR   = -L../lib/linux.x64 -L../../../../lib/linux.x64
# 存放object file的路径
OBJ_DIR   = build
EXTRA_SRC =
EXCLUDE_FILES =
# 需要链接的动态库
EXTRA_LIBS  := -llib1 -llib2 -Wl,--whole-archive -lssl -lcrypto -Wl,--no-whole-archive
SUFFIX       = c cpp cc cxx
TARGET       = $(OUT_DIR)/libTest.so
#TARGET_TYPE  := ar
#TARGET_TYPE  := app
TARGET_TYPE  := so

ifdef DEBUG
DEFS           += -D_DEBUG
else
OPTIMIZE       += -O2
endif

#for gcov version flags
ifdef GCOV 
EXTRA_CFLAGS   += -fprofile-arcs -ftest-coverage
EXTRA_LIBS     += -lgcov
endif


#####################################################################################
#  Do not change any part of them unless you have understood this script very well  #
#  This is a kind remind.                                                           #
#####################################################################################

#FUNC#  Add a new line to the input stream.
define add_newline
$1

endef

#FUNC# set the variable `src-x' according to the input $1
define set_src_x
src-$1 = $(filter-out $4,$(foreach d,$2,$(wildcard $d/*.$1)) $(filter %.$1,$3))

endef

#FUNC# set the variable `obj-x' according to the input $1
define set_obj_x
obj-$1 = $(patsubst %.$1,$3%.o,$(notdir $2))

endef

#VAR# Get the uniform representation of the object directory path name
ifneq ($(OBJ_DIR),)
prefix_objdir  = $(shell echo $(OBJ_DIR)|sed 's:\(\./*\)*::')
prefix_objdir := $(filter-out /,$(prefix_objdir)/)
endif

GCC      := $(CROSS_COMPILE)gcc
G++      := $(CROSS_COMPILE)g++
SRC_DIR := $(sort . $(SRC_DIR))
inc_dir = $(foreach d,$(sort $(INC_DIR) $(SRC_DIR)),-I$d)

#--# Do smart deduction automatically
$(eval $(foreach i,$(SUFFIX),$(call set_src_x,$i,$(SRC_DIR),$(EXTRA_SRC),$(EXCLUDE_FILES))))
$(eval $(foreach i,$(SUFFIX),$(call set_obj_x,$i,$(src-$i),$(prefix_objdir))))
$(eval $(foreach f,$(EXTRA_SRC),$(call add_newline,vpath $(notdir $f) $(dir $f))))
$(eval $(foreach d,$(SRC_DIR),$(foreach i,$(SUFFIX),$(call add_newline,vpath %.$i $d))))

all_objs = $(foreach i,$(SUFFIX),$(obj-$i))
all_srcs = $(foreach i,$(SUFFIX),$(src-$i))

CFLAGS       = $(EXTRA_CFLAGS) $(WARNINGS) $(OPTIMIZE) $(DEFS)
TARGET_TYPE := $(strip $(TARGET_TYPE))

ifeq ($(filter $(TARGET_TYPE),so ar app),)
$(error Unexpected TARGET_TYPE `$(TARGET_TYPE)')
endif

ifeq ($(TARGET_TYPE),so)
 CFLAGS  += -fpic -shared
 LDFLAGS += -shared
endif

PHONY = all .mkdir clean

all: .mkdir $(TARGET)

define cmd_o
$$(obj-$1): $2%.o: %.$1  $(MAKEFILE_LIST)
    $(GCC) $(inc_dir) -Wp,-MT,$$@ -Wp,-MMD,$$@.d $(CFLAGS) -c -o $$@ $$<

endef
$(eval $(foreach i,$(SUFFIX),$(call cmd_o,$i,$(prefix_objdir))))

ifeq ($(TARGET_TYPE),ar)
$(TARGET): AR := $(CROSS_COMPILE)ar
$(TARGET): $(all_objs)
        rm -f $@
        $(AR) rcvs $@ $(all_objs)
else
$(TARGET): LD = $(if $(strip $(src-cpp) $(src-cc) $(src-cxx)),$(G++),$(GCC))
$(TARGET): $(all_objs)
    $(LD) $(LDFLAGS) $(all_objs) $(LIB_DIR) $(EXTRA_LIBS) -o $@
endif

.mkdir:
        @if [ ! -d $(OBJ_DIR) ]; then mkdir -p $(OBJ_DIR); fi

clean:
    rm -f $(prefix_objdir)*.o $(TARGET)
    rm -f $(prefix_objdir)*.o.d

-include $(patsubst %.o,%.o.d,$(all_objs))

.PHONY: $(PHONY)