免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 28666 | 回复: 16
打印 上一主题 下一主题

GNU/Linux通用Makefile模板 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-06-17 16:53 |只看该作者 |倒序浏览
本帖最后由 prc 于 2011-06-21 12:42 编辑

本文提供一个在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, 下载次数: 1072)

  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 $@ $<

  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)
复制代码

论坛徽章:
0
2 [报告]
发表于 2012-10-24 18:13 |只看该作者
炬力的老伙计,确实不错

论坛徽章:
0
3 [报告]
发表于 2013-01-09 16:17 |只看该作者
请问一下,如果要编译与线程有关的内容,需要参数-lpthread。应该在哪个地方添加-lpthread这个参数

论坛徽章:
0
4 [报告]
发表于 2013-01-09 16:21 |只看该作者
LDFLAGS += -lpthread

论坛徽章:
0
5 [报告]
发表于 2013-01-09 16:58 |只看该作者
回复 4# colorash
按照你的方法修改,依然报错:
url.c.text+0x32): undefined reference to `pthread_join'
url.c.text+0x4: undefined reference to `pthread_create'


   

论坛徽章:
0
6 [报告]
发表于 2013-01-09 23:32 |只看该作者
哈哈,学习一下!

求职 : c/c++研发
论坛徽章:
0
7 [报告]
发表于 2013-01-10 10:30 |只看该作者
多谢lz了,一直不会写makefile,有了这个模板就可以好好学习下了

求职 : c/c++研发
论坛徽章:
0
8 [报告]
发表于 2013-03-27 19:21 |只看该作者
回复 1# prc
头文件中如果使用语句
#ifndef
#define

#endif
在make的时候会不通过,lz测试过么

   

论坛徽章:
0
9 [报告]
发表于 2013-09-30 11:12 |只看该作者
common_Makefile.7z (3.32 KB, 下载次数: 228)

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

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: 编译过程中显示完整的命令。

论坛徽章:
0
10 [报告]
发表于 2013-09-30 11:25 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP