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

本文提供一个在GNU/Linux环境下通用的智能Makefile模板,用户可以将其引入到自己的工程当中。即使用户对此
Makefile的工作原理不甚了解,但是只需要修改少数几个关键变量,就可以满足不同的应用需求。



1. 使用环境
GNU make 3.8.1或者以上版本
sed
gcc/binutils
cygwin或者Linux

2. 关键变量
CROSS_COMPILE:交叉编译器前缀
OPTIMIZE:关于优化的编译参数
WARNINGS:关于warning的编译参数
DEFS:    关于宏定义的编译参数
EXTRA_CFLAGS:其它的编译参数
$(OPTIMIZE) $(WARNINGS) $(DEFS) $(EXTRA_CFLAGS)共同构成了传给gcc的编译参数。

INC_DIR:头文件目录
SRC_DIR:源文件目录(当前目录.是被默认包含的)
OBJ_DIR:object文件的输出目录
EXTRA_SRC:源文件列表
EXCLUDE_FILES:exclude文件列表

SUFFIX:源文件的后缀名
TARGET:最终的目标程序名
TARGET_TYPE:目标程序的类型。
可以定义的类型为:ar(static library),so(shared library)和app(application)。

最终Makefile的行为是:
在$(SRC_DIR)定义的每个目录中查找后缀为$(SUFFIX)的文件,并加上$(EXTRA_SRC)中的文件,然后排除掉
$(EXCLUDE_FILES)中的文件,获得本工程定义的源文件列表。对于每一个源文件,编译生成的一个.o文件和一个.d文件
(依赖文件),放在$(OBJ_DIR)目录下。最终生成的目标文件为$(TARGET)。
此Makefile已经充分考虑到文件之间的依赖关系,即,如果某个头文件发生改变,当运行make的时候,所有依赖于它的

源文件都将被重新编译。

###############################################################################
#
# 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
WARNINGS := -Wall -Wno-unused -Wno-format
DEFS     :=
EXTRA_CFLAGS := 

INC_DIR   =
SRC_DIR   =
OBJ_DIR   =
EXTRA_SRC =
EXCLUDE_FILES =

SUFFIX       = c cpp cc cxx
TARGET       :=
#TARGET_TYPE  :=
TARGET_TYPE  :=
#TARGET_TYPE  :=


#####################################################################################
#  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) -o $@
endif

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

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

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

.PHONY: $(PHONY)


==========================================================
升级版本。与之前版本相比,有如下改动:

1.  在objdir中生成与source相似的目录树,防止不同source目录下同名的源文件生成的obj文件相互覆盖。
2.  在编译过程中,默认显示短命令。可以通过变量设置切换为显示长命令。
3.  用户可自扩展编译规则。

==========================================================
模板中用到的可配置的变量列表:

DEFINES:              定义编译参数,一般用-U或者-D进行宏定义。
EXTRA_CFLAGS:  定义其它的编译参数

inc-y:   头文件搜索目录
src-y:   源文件列表。其中以/结尾的表示目录,其它的表示文件。
SOURCE_SUFFIXES:  源文件后缀名。在src-y指定的目录中搜索以$(SOURCE_SUFFIXES)为后缀的文件,加入到源文件列表中。

例如:
src-y = dir1/ dir2/ file9.c
SOURCE_SUFFIXES := c cpp
最终形成的源文件列表为: dir1/*.c dir1/*.cpp dir2/*.c dir2/*.cpp file9.c

obj-y: 加入连接的obj文件列表。通常这些obj文件不通过源文件编译产生。

ucmd_X: 自定义后缀名为X的源文件的编译规则。

EXCLUDE_FILES: 不参与编译的源文件列表。

OBJECT_DIR:obj文件的输出目录。

LIBS:连接时需要的lib文件。

LDFLAGS:连接参数。

OBJECT_SUFFIX:  obj文件的后缀名
DEPEND_SUFFIX: depend文件的后缀名

TARGET: 整个工程最终产生的target文件名。
TARGET_TYPE: $(TARGET)类型。
TARGET_DEPENDS: $(TARGET)的依赖。

CENTRALIZED_SINGLE_DEPEND_FILE: 将所有依赖关系集中生成到同一个depend文件中。默认是每个obj产生一个单独的depend文件。

VERBOSE_COMMAND: 编译过程中显示完整的命令。

###############################################################################
#
# A FLEXIBLE MAKEFILE TEMPLATE
#
# The purpose of implementing this script is help quickly deploy source code
# tree during initial phase of development. It is designed to manage one whole
# project from within one single makefile and to be easily adapted to
# different directory hierarchy by simply setting user configurable variables.
# This script is expected to be used with gcc toolchains on bash-compatible 
# shell.
# 
# Author: Pan Ruochen <coderelease@163.com>
# Date:   2012/10/10
#
###############################################################################

#-----------------------------------------------------------------------------------------------------#
# User configurable variables
#
# ====================================================================================================
# GNU_TOOLCHAIN_PREFIX:   The perfix of gnu toolchain.
# ====================================================================================================
# DEFINES:        The compiler flags for macro definitions.
# EXTRA_CFLAGS:   Any other compiler flags.
# inc-y:          Header include paths.
# src-y:          Sources. The items ending with a trailing / are regarded as directories, the others
#                 are regareded as files. The files with specified suffixes in those directories will
#                 be automatically involved in compilation.
# obj-y:          Extra object file list.
# ucmd_X:         User defined command to generate targets for the prerequisites
#                 whith the specified suffix X (i.e, X could be c, cpp, etc).
#
# EXCLUDE_FILES:  The files that are not included during compilation.
# OBJECT_DIR:     The directory where object files are output.
# LD_SCRIPT:      The explicit linker script for linking.
# LIBS:           The libraries for linking.
# LDFLAGS:        All other linker flags.
# ====================================================================================================
# STRIP_UNUSED:   Remove all unreferenced functions and data during linking.
# SOURCE_SUFFIXES:The suffixes of source files.
# OBJECT_SUFFIX:  The suffix of object files.
# DEPEND_SUFFIX:  The suffix of dependency files.
# TARGET_TYPE:    The target type which can be application, shared object, archive library etc.
# TARGET:         The path name of the final target.
# IGNORE_ME:      The changes of this script will not cause remaking of any target.
# CENTRALIZED_SINGLE_DEPEND_FILE:  Use one single dependency file instead of 
#                                  generating one dependency file for each source file.
# TARGET_DEPENDS: The dependent targets by the final target.
# VERBOSE_COMMAND:Display verbose commands instead of short commands during the make process.
#-----------------------------------------------------------------------------------------------------#

#****************************************************************************#
#  PART II: FUNCTIONALITY IMPLEMENTATIONS                                    #
#****************************************************************************#

# Quiet commands
ifeq ($(VERBOSE_COMMAND),)
Q           = @
Q_compile   = @echo '  CC     $$< => $$@';
Q_link      = @echo '  LD     $@';
Q_ar        = @echo '  AR     $@';
Q_mkdir     =  echo '  MKDIR  $1';
Q_clean     = @echo '  CLEAN';
Q_distclean = @echo '  DISTCLEAN';
endif

O := $(if $(OBJECT_SUFFIX),$(OBJECT_SUFFIX),o)
D := $(if $(DEPEND_SUFFIX),$(DEPEND_SUFFIX),d)

ifndef SOURCE_SUFFIXES
SOURCE_SUFFIXES := c cpp cc cxx S s
endif

GCC    := $(GNU_TOOLCHAIN_PREFIX)gcc

src-d = $(filter %/,$(src-y))
src-f = $(foreach i,$(SOURCE_SUFFIXES),$(filter %.$i,$(src-y)))

is_equal = $(if $(filter $1,$2),$(filter $2,$1))

objdir := $(shell echo $(OBJECT_DIR)|sed -e 's:\(\./*\)*::g')
ifeq ($(objdir),)
objdir       := ./
else
objdir       := $(objdir)/
have_objdir  := y
endif

## Combine compiler flags togather.
CFLAGS   = $(foreach i,$(inc-y),-I$i) $(EXTRA_CFLAGS) $(DEFINES)

## Output file types:
##  EXE:  Application
##  AR:   static library
##  SO:   shared object
##  DLL:  dynamic link library
##  BIN:  raw binary
TARGET_TYPE := $(strip $(TARGET_TYPE))
ifeq ($(filter $(TARGET_TYPE),SO DLL AR EXE BIN),)
$(error Unknown TARGET_TYPE `$(TARGET_TYPE)')
endif

ifneq ($(filter DLL SO,$(TARGET_TYPE)),)
CFLAGS  += -shared
LDFLAGS += -shared
endif
ifneq ($(STRIP_UNUSED),)
CFLAGS  += -ffunction-sections -fdata-sections
LDFLAGS += --gc-sections
endif

ifeq ($(CENTRALIZED_SINGLE_DEPEND_FILE),)
CFLAGS += -MMD -MF $$@.$(D) -MT $$@
else
single_depend_file := $(objdir)depend
endif

g_makefile_list = $(if $(IGNORE_ME),,$(MAKEFILE_LIST))

#--------------------------------------------------#
# Exclude user-specified files from source list.   #
#  $1 -- The sources list                          #
#--------------------------------------------------#
exclude = $(filter-out $(EXCLUDE_FILES),$1)

#----------------------------------------------------------#
# List files with specified suffix inside the directory.   #
#  $1 -- The directory                                     #
#  $2 -- The suffix                                        #
#----------------------------------------------------------#
ls = $(wildcard $1*.$2)


#---------------------------------------------#
# Replace the specified suffixes with $(O).   #
#  $1 -- The file names                       #
#  $2 -- The suffixes                         #
#---------------------------------------------#
get_object_names = $(strip $(foreach i,$2,$(patsubst %.$i,%.$O,$(filter %.$i,$1))))

#---------------------------------------------#
# Get the suffix name from a file name.       #
#  $1 -- The file name                        #
#  $2 -- The favorite suffixes                #
#---------------------------------------------#
get_suffix_names = $(strip $(foreach i,$2,$(if $(filter %.$i,$1),$i)))

#-------------------------------------------------------------------#
# Replace the pattern .. with !! in the path names in order that    #
# no directories are out of the object directory                    #
#  $1 -- The path names                                             #
#-------------------------------------------------------------------#
objdir_transform = $(if $(have_objdir),$(subst ..,!!,$1),$1)


#------------------------------------------------------------------#
# Set up static pattern rules for sources with specified suffixes  #
# in specified directories.                                        #
#  $1 -- Source directories                                        #
#  $2 -- Source suffixes                                           #
#  $3 -- Equal to $(call ls $1,$2)                                 #
#------------------------------------------------------------------#
static_pattern_rules = $(if $3,$(call __static_pattern_rule,$(patsubst %.$2,$(objdir)%.$O,$3),$1,$2))


#------------------------------------#
# Command to make directory          #
#  $1 -- The directory to be made    #
#------------------------------------#
define cmd_make_directory
$(Q)if test ! -d "$1"; then $(Q_mkdir)mkdir -p "$1"; fi

endef

cmd_compile = $(Q_compile)$(if $(ucmd_$1),$(ucmd_$1),$(GCC) -I$$(dir $$<) $(CFLAGS) -c -o $$@ $$<)

#------------------------------------------------------------------#
#  Static pattern rule                                             #
#  $1 -- Targets                                                   #
#  $1 -- Source directories                                        #
#  $3 -- The source suffix                                         #
#------------------------------------------------------------------#
define __static_pattern_rule
$(call objdir_transform,$1): $(call objdir_transform,$(objdir)$2%.$(O)): $2%.$3 $(g_makefile_list)
	$(call cmd_compile,$3)

endef


#--------------------------------------------------------------#
#  Ordinary rule                                               #
#  $1 -- The prerequisite                                      #
#  $2 -- The Target                                            #
#--------------------------------------------------------------#
define ordinary_rule
$(call objdir_transform,$2): $1 $(g_makefile_list)
	$(call cmd_compile,$(call get_suffix_names,$1,$(SOURCE_SUFFIXES)))

endef

#--------------------------------------------------------#
# Make sure the default target "all" is the first target
#--------------------------------------------------------#
PHONY = all clean distclean make_sub_dirs
all: make_sub_dirs $(TARGET)

#----------------------------------------------------#
# Dynamic Targets
#----------------------------------------------------#
$(eval $(foreach i,\
    $(sort $(src-d)),\
    $(foreach j,$(SOURCE_SUFFIXES),$(call static_pattern_rules,$i,$j,$(call exclude,$(call ls,$i,$j)))))\
    $(foreach i,$(call exclude,$(sort $(src-f))),$(call ordinary_rule,$i,$(objdir)$(call get_object_names,$i,$(SOURCE_SUFFIXES)))))


#-------------------------------------#
# Get the list of all source files    #
#-------------------------------------#
srcs = $(call exclude,\
	$(foreach i,$(SOURCE_SUFFIXES),\
	$(foreach j,$(src-d),\
	$(wildcard $j*.$i)) $(filter %.$i,$(src-f))))

ifeq ($(strip $(srcs)),)
$(error Empty source list! Please check both src-y and SOURCE_SUFFIXES are correctly set.)
endif

#-------------------------------------#
# Get the list of all object files    #
#-------------------------------------#
objs = $(call objdir_transform,$(addprefix $(objdir),$(call get_object_names,$(srcs),$(SOURCE_SUFFIXES))))
objs += $(obj-y)

#----------------------------------------------------#
# Static Targets
#----------------------------------------------------#
make_sub_dirs:
	$(call cmd_make_directory,$(dir $(TARGET)))
	$(foreach i,$(call objdir_transform,$(sort $(src-d) $(dir $(src-f)))),$(call cmd_make_directory,$(objdir)$i))

ifneq ($(single_depend_file),)
$(single_depend_file): $(srcs) $(filter-out $@,$(g_makefile_list)) $(objdir)
	$(GCC) $(CFLAGS) -MM -MG $(srcs) | \
sed 's#\([^[:space:]]\+\)\.$O:\s\([^[:space:]]\+\)\.\([^[:space:].]\+\s\?\)#$(objdir)\2.$O: \2.\3#g' > $@
$(objdir): ; $(call cmd_make_directory,$(objdir))
endif

ifeq ($(TARGET_TYPE),AR)
$(TARGET): AR := $(GNU_TOOLCHAIN_PREFIX)ar
$(TARGET): $(TARGET_DEPENDS) $(objs)
	$(Q_ar)rm -f $@ && $(AR) rcvs $@ $(objs)
else

ifeq ($(TARGET_TYPE),BIN)
tmp_target   = $(basename $(TARGET)).elf
LDFLAGS     += -nodefaultlibs -nostdlibs -nostartupfiles
$(TARGET): $(tmp_target)
	$(GNU_TOOLCHAIN_PREFIX)objcopy -O binary $(tmp_target) $@
	$(GNU_TOOLCHAIN_PREFIX)objdump -d $(tmp_target) > $(basename $(@F)).lst
	$(GNU_TOOLCHAIN_PREFIX)nm $(tmp_target) | sort -k1 > $(basename $(@F)).map
else
tmp_target   = $(TARGET)
endif

$(tmp_target): LD = $(if $(foreach i,cpp cc cxx,$(filter %.$i,$(srcs))),$(GNU_TOOLCHAIN_PREFIX)g++,$(GCC))
$(tmp_target): $(TARGET_DEPENDS) $(objs) $(LD_SCRIPT)
	$(Q_link)$(LD) $(LDFLAGS) $(if $(LD_SCRIPT),-T $(LD_SCRIPT)) $(objs) $(LIBS) -o $(tmp_target)

endif

clean:
	$(Q_clean)rm -rf $(filter-out ./,$(objdir)) $(TARGET) $(filter-out $(obj-y),$(objs))
distclean: clean
	$(Q_distclean)find -name '*.$O' -o -name '*.$D' | xargs rm -f; $(if $(single_depend_file),rm -f $(single_depend_file))
print-%:
	@echo $* = $($*)

.DEFAULT_GOAL = all

sinclude $(if $(filter all,$(if $(MAKECMDGOALS),$(MAKECMDGOALS),$(.DEFAULT_GOAL))), \
$(if $(single_depend_file),$(single_depend_file),$(foreach i,$(objs),$i.$(D))))


example

linux@ubuntu:~/Workspace/app$ tree -a
.
|-- GNUmakefile
|-- include
|   `-- common.h
|-- main.c
|-- src1
|   |-- a1-1.h
|   |-- a1-2.h
|   |-- a1.c
|   |-- a2-2.h
|   |-- a2.cpp
|   `-- skipme1.c
|-- src2
|   |-- a
|   |   |-- a2a-1.cc
|   |   |-- a2a-2.cxx
|   |   `-- skipme2.c
|   `-- b
|       `-- a2b.c
|-- src3
|   |-- a3.c
|   `-- z3.c
`-- src4
    |-- a4.c
    `-- z4.cpp


7 directories, 17 files

###############################################################################

#

# 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

WARNINGS := -Wall -Wno-unused -Wno-format

DEFS     := -DMYDEF=1 -UMYDEF2

EXTRA_CFLAGS := 



INC_DIR   = include

SRC_DIR   = src1 src2/a src2/b

OBJ_DIR   = out/target

EXTRA_SRC = src3/z3.c src4/z4.cpp

EXCLUDE_FILES = src1/skipme1.c src2/a/skipme2.c



SUFFIX       = c cpp cc cxx

TARGET       := out/go.exe

#TARGET_TYPE  := ar

TARGET_TYPE  := app

#TARGET_TYPE  := so





#####################################################################################

#  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) -o $@

endif



.mkdir:

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



clean:

	rm -f $(prefix_objdir)*.o $(TARGET)



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



.PHONY: $(PHONY)



原文地址:http://bbs.chinaunix.net/thread-3553668-1-1.html

网上盛传的另一个makefile,我稍微修改了一下:

#############################################################################
#
# Generic Makefile for C/C++ Program
#
# License: GPL (General Public License)
# Author:  whyglinux <whyglinux AT gmail DOT com>
# Date:    2006/03/04 (version 0.1)
#          2007/03/24 (version 0.2)
#          2007/04/09 (version 0.3)
#          2007/06/26 (version 0.4)
#          2008/04/05 (version 0.5)
#
# Description:
# ------------
# This is an easily customizable makefile template. The purpose is to
# provide an instant building environment for C/C++ programs.
#
# It searches all the C/C++ source files in the specified directories,
# makes dependencies, compiles and links to form an executable.
#
# Besides its default ability to build C/C++ programs which use only
# standard C/C++ libraries, you can customize the Makefile to build
# those using other libraries. Once done, without any changes you can
# then build programs using the same or less libraries, even if source
# files are renamed, added or removed. Therefore, it is particularly
# convenient to use it to build codes for experimental or study use.
#
# GNU make is expected to use the Makefile. Other versions of makes
# may or may not work.
#
# Usage:
# ------
# 1. Copy the Makefile to your program directory.
# 2. Customize in the "Customizable Section" only if necessary:
#    * to use non-standard C/C++ libraries, set pre-processor or compiler
#      options to <MY_CFLAGS> and linker ones to <MY_LIBS>
#      (See Makefile.gtk+-2.0 for an example)
#    * to search sources in more directories, set to <SRCDIRS>
#    * to specify your favorite program name, set to <PROGRAM>
# 3. Type make to start building your program.
#
# Make Target:
# ------------
# The Makefile provides the following targets to make:
#   $ make           compile and link
#   $ make NODEP=yes compile and link without generating dependencies
#   $ make objs      compile only (no linking)
#   $ make tags      create tags for Emacs editor
#   $ make ctags     create ctags for VI editor
#   $ make clean     clean objects and the executable file
#   $ make distclean clean objects, the executable and dependencies
#   $ make help      get the usage of the makefile
#
#===========================================================================

## Customizable Section: adapt those variables to suit your program.
##==========================================================================
-include ../Rules.make
# The pre-processor and compiler options.
MY_CFLAGS =

# The linker options.
MY_LIBS   =

# The pre-processor options used by the cpp (man cpp for more).
CPPFLAGS  = -Wall

# The options used in linking as well as in any direct use of ld.
LDFLAGS   += -lrt

# The directories in which source files reside.
# If not specified, only the current directory will be serached.
SRCDIRS   = ./kf_base ./kf_net ./kf_share .

# The executable file name.
# If not specified, current directory name or `a.out' will be used.
PROGRAM   = kfserver

## Implicit Section: change the following only when necessary.
##==========================================================================

# The source file types (headers excluded).
# .c indicates C source files, and others C++ ones.
#SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp
SRCEXTS = .c

# The header file types.
#HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp
HDREXTS = .h

# The pre-processor and compiler options.
# Users can override those variables from the command line.
CFLAGS  = -g -O0 -Wall -mcpu=arm926ej-s
CXXFLAGS= -g -O2

GNU_TOOLCHAIN_PREFIX = $(CSTOOL_PREFIX)
# The C program compiler.
CC     := $(GNU_TOOLCHAIN_PREFIX)gcc

# The C++ program compiler.
#CXX    = g++

# Un-comment the following line to compile C programs as C++ ones.
#CC     = $(CXX)

# The command used to delete file.
#RM     = rm -f

ETAGS = etags
ETAGSFLAGS =

CTAGS = ctags
CTAGSFLAGS =
#VERBOSE_COMMAND = quiet
## Quiet commands
ifeq ($(VERBOSE_COMMAND),)
Q           = @
Q_compile   = @echo '  CC     $< => $@';
Q_link      = @echo '  LD     $@';
Q_ar        = @echo '  AR     $@';
Q_mkdir     =  echo '  MKDIR  $1';
Q_clean     = @echo '  CLEAN';
Q_distclean = @echo '  DISTCLEAN';
endif
## Stable Section: usually no need to be changed. But you can add more.
##==========================================================================
SHELL   = /bin/sh
EMPTY   =
SPACE   = $(EMPTY) $(EMPTY)
ifeq ($(PROGRAM),)
  CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))
  PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))
  ifeq ($(PROGRAM),)
    PROGRAM = a.out
  endif
endif
ifeq ($(SRCDIRS),)
  SRCDIRS = .
endif
SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))

CFLAGS   = $(foreach i,$(SRCDIRS),-I$i)

SRC_CXX = $(filter-out %.c,$(SOURCES))
OBJS    = $(addsuffix .o, $(basename $(SOURCES)))
DEPS    = $(OBJS:.o=.d)

## Define some useful variables.
DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \
                  echo "-MM -MP"; else echo "-M"; fi )
DEPEND      = $(CC)  $(DEP_OPT)  $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS)
DEPEND.d    = $(subst -g ,,$(DEPEND))
COMPILE.c   = $(Q_compile)$(CC)  $(MY_CFLAGS) $(CFLAGS)   $(CPPFLAGS) -c
COMPILE.cxx = $(Q_compile)$(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c
LINK.c      = $(Q_link)$(CC)  $(MY_CFLAGS) $(CFLAGS)   $(CPPFLAGS) $(LDFLAGS)
LINK.cxx    = $(Q_link)$(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)

.PHONY: all objs tags ctags clean distclean help show

# Delete the default suffixes
.SUFFIXES:

all: $(PROGRAM)

# Rules for creating dependency files (.d).
#------------------------------------------

%.d:%.c
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

%.d:%.C
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

%.d:%.cc
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

%.d:%.cpp
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

%.d:%.CPP
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

%.d:%.c++
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

%.d:%.cp
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

%.d:%.cxx
	@echo -n $(dir $<) > $@
	@$(DEPEND.d) $< >> $@

# Rules for generating object files (.o).
#----------------------------------------
objs:$(OBJS)

%.o:%.c
	$(COMPILE.c) $< -o $@

%.o:%.C
	$(COMPILE.cxx) $< -o $@

%.o:%.cc
	$(COMPILE.cxx) $< -o $@

%.o:%.cpp
	$(COMPILE.cxx) $< -o $@

%.o:%.CPP
	$(COMPILE.cxx) $< -o $@

%.o:%.c++
	$(COMPILE.cxx) $< -o $@

%.o:%.cp
	$(COMPILE.cxx) $< -o $@

%.o:%.cxx
	$(COMPILE.cxx) $< -o $@

# Rules for generating the tags.
#-------------------------------------
tags: $(HEADERS) $(SOURCES)
	$(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES)

ctags: $(HEADERS) $(SOURCES)
	$(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)

# Rules for generating the executable.
#-------------------------------------
$(PROGRAM):$(OBJS)
ifeq ($(SRC_CXX),)              # C program
	$(LINK.c)   $(OBJS) $(MY_LIBS) -o $@
	@echo Type ./$@ to execute the program.
else                            # C++ program
	$(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@
	@echo Type ./$@ to execute the program.
endif

ifndef NODEP
ifneq ($(DEPS),)
  sinclude $(DEPS)
endif
endif

install:
	cp -f kf920.elf  /home/linux-138/kf920/rootfs/kfserver
clean:
	$(Q_clean)$(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe

distclean: clean
	$(Q_distclean)$(RM) $(DEPS) TAGS

# Show help.
help:
	@echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5'
	@echo 'Copyright (C) 2007, 2008 whyglinux <whyglinux@hotmail.com>'
	@echo
	@echo 'Usage: make [TARGET]'
	@echo 'TARGETS:'
	@echo '  all       (=make) compile and link.'
	@echo '  NODEP=yes make without generating dependencies.'
	@echo '  objs      compile only (no linking).'
	@echo '  tags      create tags for Emacs editor.'
	@echo '  ctags     create ctags for VI editor.'
	@echo '  clean     clean objects and the executable file.'
	@echo '  distclean clean objects, the executable and dependencies.'
	@echo '  show      show variables (for debug use only).'
	@echo '  help      print this message.'
	@echo
	@echo 'Report bugs to <whyglinux AT gmail DOT com>.'

# Show variables (for debug use only.)
show:
	@echo 'PROGRAM     :' $(PROGRAM)
	@echo 'SRCDIRS     :' $(SRCDIRS)
	@echo 'HEADERS     :' $(HEADERS)
	@echo 'SOURCES     :' $(SOURCES)
	@echo 'SRC_CXX     :' $(SRC_CXX)
	@echo 'OBJS        :' $(OBJS)
	@echo 'DEPS        :' $(DEPS)
	@echo 'DEPEND      :' $(DEPEND)
	@echo 'COMPILE.c   :' $(COMPILE.c)
	@echo 'COMPILE.cxx :' $(COMPILE.cxx)
	@echo 'link.c      :' $(LINK.c)
	@echo 'link.cxx    :' $(LINK.cxx)

## End of the Makefile ##  Suggestions are welcome  ## All rights reserved ##
#############################################################################


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值