linux makefile模板

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

本文提供一个在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的时候,所有依赖于它的
源文件都将被重新编译。

附件是一个例子,演示了如何处理不同目录,如何处理不同目标类型,以及如何exclude文件。
 example.rar (3.39 KB, 下载次数: 467)

  1. ###############################################################################
  2. #
  3. # A smart Makefile template for GNU/LINUX programming
  4. #
  5. # Author: PRC (ijkxyz AT msn DOT com)
  6. # Date:   2011/06/17
  7. #
  8. # Usage:
  9.  $ make           Compile and link (or archive)
  10.  $ make clean     Clean the objectives and target.
  11. ###############################################################################

  12. CROSS_COMPILE =
  13. OPTIMIZE := -O2
  14. WARNINGS := -Wall -Wno-unused -Wno-format
  15. DEFS     :=
  16. EXTRA_CFLAGS := 

  17. INC_DIR   =
  18. SRC_DIR   =
  19. OBJ_DIR   =
  20. EXTRA_SRC =
  21. EXCLUDE_FILES =

  22. SUFFIX       = c cpp cc cxx
  23. TARGET       :=
  24. #TARGET_TYPE  :=
  25. TARGET_TYPE  :=
  26. #TARGET_TYPE  :=


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

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

  34. endef

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

  38. endef

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

  42. endef

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

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

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

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

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

  61. ifeq ($(filter $(TARGET_TYPE),so ar app),)
  62. $(error Unexpected TARGET_TYPE `$(TARGET_TYPE)')
  63. endif

  64. ifeq ($(TARGET_TYPE),so)
  65. CFLAGS  += -fpic -shared
  66. LDFLAGS += -shared
  67. endif

  68. PHONY = all .mkdir clean

  69. all: .mkdir $(TARGET)

  70. define cmd_o
  71. $(obj-$1): $2%.o: %.$1  $(MAKEFILE_LIST)
  72.         $(GCC) $(inc_dir) -Wp,-MT,$@ -Wp,-MMD,$@.d $(CFLAGS) -c -o $@ $<<BR style="WORD-WRAP: break-word">

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

  75. ifeq ($(TARGET_TYPE),ar)
  76. $(TARGET): AR := $(CROSS_COMPILE)ar
  77. $(TARGET): $(all_objs)
  78.         rm -f $@
  79.         $(AR) rcvs $@ $(all_objs)
  80. else
  81. $(TARGET): LD = $(if $(strip $(src-cpp) $(src-cc) $(src-cxx)),$(G++),$(GCC))
  82. $(TARGET): $(all_objs)
  83.         $(LD) $(LDFLAGS) $(all_objs) -o $@
  84. endif

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

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

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

  90. .PHONY: $(PHONY)
复制代码

实例:

makefile:

###############################################################################
#
# 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)

 

 

 

图像:linux <wbr>makefile模板

本程序的Makefile分为3类: 1. 顶层目录的Makefile 2. 顶层目录的Makefile.build 3. 各级子目录的Makefile 一、各级子目录的Makefile: 它最简单,形式如下: EXTRA_CFLAGS := CFLAGS_file.o := obj-y += file.o obj-y += subdir/ "obj-y += file.o" 表示把当前目录下的file.c编进程序里, "obj-y += subdir/" 表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。 "EXTRA_CFLAGS", 它给当前目录下的所有文件(不含其下的子目录)设置额外的编译选项, 可以不设置 "CFLAGS_xxx.o", 它给当前目录下的xxx.c设置它自己的编译选项, 可以不设置 注意: 1. "subdir/"的斜杠"/"不可省略 2. 顶层Makefile的CFLAGS在编译任意一个.c文件时都会使用 3. CFLAGS EXTRA_CFLAGS CFLAGS_xxx.o 三者组成xxx.c的编译选项 二、顶层目录的Makefile: 它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外, 主要是定义工具链前缀CROSS_COMPILE, 定义编译参数CFLAGS, 定义链接参数LDFLAGS, 这些参数就是文件用export导出的各变量。 三、顶层目录的Makefile.build: 这是最复杂的部分,它的功能就是把某个目录及它的所有子目录、需要编进程序去的文件都编译出来,打包为built-in.o 详细的讲解请看视频。 四、怎么使用这套Makefile: 1.把顶层Makefile, Makefile.build放入程序的顶层目录 在各自子目录创建一个空白的Makefile 2.确定编译哪些源文件 修改顶层目录和各自子目录Makefile的obj-y : obj-y += xxx.o obj-y += yyy/ 这表示要编译当前目录下的xxx.c, 要编译当前目录下的yyy子目录 3. 确定编译选项、链接选项 修改顶层目录Makefile的CFLAGS,这是编译所有.c文件时都要用的编译选项; 修改顶层目录Makefile的LDFLAGS,这是链接最后的应用程序时的链接选项; 修改各自子目录下的Makefile: "EXTRA_CFLAGS", 它给当前目录下的所有文件(不含其下的子目录)设置额外的编译选项, 可以不设置 "CFLAGS_xxx.o", 它给当前目录下的xxx.c设置它自己的编译选项, 可以不设置 4. 使用哪个编译器? 修改顶层目录Makefile的CROSS_COMPILE, 用来指定工具链的前缀(比如arm-linux-) 5. 确定应用程序的名字: 修改顶层目录Makefile的TARGET, 这是用来指定编译出来的程序的名字 6. 执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值