Chinaunix首页 | 论坛 | 博客
  • 博客访问: 312602
  • 博文数量: 82
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 490
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-13 10:58
文章分类

全部博文(82)

文章存档

2018年(2)

2017年(9)

2016年(71)

我的朋友

分类: 嵌入式

2017-04-05 12:50:21

 最近在做一个项目时对makefile有了一个简单的认识,于是自己写了一个简单的编译框架,留待后用。下边是一个demo示例,附上所有的源文件,移植工程时搬过来应该就可以用了。

一、demo的文件目录树

  1. ├── app
  2. │ ├── api
  3. │ │ ├── api.c
  4. │ │ └── Makefile
  5. │ ├── include
  6. │ │ └── app.h
  7. │ ├── Makefile
  8. │ └── src
  9. │ ├── app.c
  10. │ └── Makefile
  11. ├── main
  12. │ ├── include
  13. │ │ └── main.h
  14. │ ├── Makefile
  15. │ └── src
  16. │ ├── main.c
  17. │ └── Makefile
  18. ├── Makefile
  19. ├── make.rules
  20. │ ├── config.in
  21. │ ├── make.obj
  22. │ ├── make.src
  23. │ └── rules.mk
  24. └── sdk
  25.     ├── Makefile
  26.     ├── sdk1
  27.     │ ├── include
  28.     │ │ └── sdk1.h
  29.     │ ├── Makefile
  30.     │ └── src
  31.     │ ├── Makefile
  32.     │ ├── sdk1_1.cpp
  33.     │ └── sdk1_2.c
  34.     └── sdk2
  35.         ├── Makefile
  36.         ├── sdk2_1
  37.         │ ├── include
  38.         │ │ └── sdk2_1.h
  39.         │ ├── Makefile
  40.         │ └── src
  41.         │ ├── Makefile
  42.         │ └── sdk2_1.c
  43.         └── sdk2_2
  44.             ├── include
  45.             │ └── sdk2_2.h
  46.             ├── Makefile
  47.             └── src
  48.                 ├── Makefile
  49.                 └── sdk2_2.c

二、使用说明

1.编译帮助,在主目录中输入make help,可以得到编译的帮助信息。

2.user_debug目标是留给用户打印变量使用的。只要在该目标下调用$(call PRINT,变量),就能在执行makefile时打印出指定的变量的值。编译时需要指明打印等级,0-打印所有变量,1-打印内部变量,2-打印用户定义的变量。只打印用户变量使用make all DEBUG_LEVEL=2

3.user_clean目标是留给用户做清理工作的,在make clean之前会调用到。

4.user目标是留给用户编译时使用的。比如可以在编译完成之后自动清理掉生成的不需要的.o文件,可以直接在user后边加上一个依赖clean

5.主目录中编译整个工程直接使用make all,只清理.o和可执行文件使用make clean,清理掉所有生成的文件使用make distclean。也可以指定单个目录进行编译,比如make –C app就会只编译app目录,make –C app clean就会单独清理掉app目录。

6.非主目录编译需要先在主目录中成功make all一次,只有生成了配置文件rules.conf才能找到编译时需要依赖的规则文件。所以要在非主目录中编译,不能使用make distclean命令。在非主目录中编译直接使用make 就可以了,清理使用make clean,打印变量使用make DEBUG_LEVEL=2

三、编译框架说明

1. 整个编译过程用到了三种makefile文件。

1)第一种是将各个子目录中的.o文件链接成一个.o目标文件。如下,./sdk/Makefile文件。

  1. # 需要编译的子目录
  2. obj-y = sdk1
  3. obj-y += sdk2

  4. # 编译所需参数
  5. # EXTRA_LDFLAGS:链接时需要的参数
  6. EXTRA_LDFLAGS =

  7. # 加载make.obj文件
  8. ifdef MAKE_RULES
  9. include $(MAKE_RULES)/make.obj
  10. else
  11. include ./rules.conf
  12. ifdef MAKE_RULES
  13. include $(MAKE_RULES)/make.obj
  14. endif
  15. endif    

  16. # 用户编译配置处
  17. # clean: 清除掉源文件生成的目标文件
  18. # distclean: 清除当前和子目录所有的目标文件
  19. # 编译时在这里可以做其它事情
  20. user:

  21. # 用户清理
  22. user_clean:

  23. # 打印变量
  24. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  25. # DEBUG_LEVEL = 2时,才会有打印
  26. user_debug:
  27.     $(call PRINT,MAKE_OBJ)

这个makefile几乎不用修改任何地方,除了必须指定需要编译的子目录obj-y。其中的所有链接工作是在./make.rules/make.obj文件中完成的。

2)第二种是将子目录中的源文件编译成.o文件,然后将所有.o文件连接成一个目标.o文件。如下,./sdk/sdk1/Makefile文件。

  1. # 目标文件夹
  2. src-y = src

  3. # 目标文件类型
  4. source_type = .cpp .c    

  5. # 编译所需参数
  6. # EXTRA_CFLAGS:c编译参数
  7. # EXTRA_CXXFLAGS:cpp编译参数
  8. # EXTRA_LDFLAGS:链接成目标.o时的参数
  9. EXTRA_CFLAGS += -I$(CURR_DIR)/include
  10. EXTRA_CXXFLAGS += -I$(CURR_DIR)/include
  11. EXTRA_LDFLAGS =

  12. # 加载make.src文件
  13. ifdef MAKE_RULES
  14. include $(MAKE_RULES)/make.src
  15. else
  16. include ./rules.conf
  17. ifdef MAKE_RULES
  18. include $(MAKE_RULES)/make.src
  19. endif
  20. endif    

  21. # 用户编译配置处
  22. # clean: 清除掉源文件生成的目标文件
  23. # distclean: 清除当前和子目录所有的目标文件
  24. user:

  25. #     用户清理
  26. user_clean:

  27. # 打印变量
  28. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  29. # DEBUG_LEVEL = 2时,才会有打印

  30. user_debug:
  31.     $(call PRINT,CURR_DIR)

这个文件需要指定源文件目录src-y和需要编译的源文件类型source_type,还有编译的头文件目录。其主要编译规则在./make.rules/make.src中。


3)第三种makefile是在源文件中,主要是用来进行清理工作的,比如./sdk/sdk1/src/Makefile,如下

  1. clean:
  2.     rm -rf *.[od]

  3. distclean: clean
  4.     
  5. .PHONY: clean distclean


2.
关于./make.rules目录中的规则或配置文件。

    config.in:提供编译时需要的全局变量,比如make.rules的位置,环境变量,编译工具链,一些通用的编译参数。

    rules.mk: 提供具体的编译规则,打印函数,打印等级,打印颜色。

    make.obj: 将多个.o文件连接成一个.o文件。

    make.src: 将源文件编译成.o文件,并链接成一个.o文件。


四、一些实现细节

  1. 打印函数 

  1. PRINT = @echo -e "$(BABYBLUECOLOR)$(1): $($(1)) $(ENDCOLOR)\n";
  2. $(call PRINT,变量)

  使用call会将PRINT视为一个函数调用,而后边的变量则视为函数的参数。$(1)变量的名称,$($(1))变量中的内容。


  2. 自动编译,彩色警告和错误,去掉c中的__FILE__的绝对路径

  1. COLORING=sed -e "s/[Ee]rror[: ]/$(CCERROR)\0$(CCEND)/g" -e "s/[Ww]arning[: ]/$(CCWARNING)\0$(CCEND)/g"
  2. %.o: %.c
  3.     $(CC) $(EXTRA_CFLAGS) $(CFLAGS) -MD -c $< -o $@ -D__NOTDIR_FILE__=$(notdir $<) 2>&1 | $(COLORING)

%.o: %c是一种指定泛型的目标与依赖方式,在同一个makefile中,只要其他目标有依赖后缀为.o目标,那么执行到该目标时,就会执行%.o: %.c。这时-D__NOTDIR_FILE__=$(notdir $<)中的$<就代表源文件的路径,它可能和源文件名一样,也可能在文件名前边带了路径,所以使用$(notdir $<)

可以除掉路径,只留下文件名。那么这里为何要定义一个-D__NOTDIR_FILE__的宏呢,因为如果这里的$<带了路径,那么__FILE__宏一定带有路径,我想很多人在打印文件名时也遇到过这样的问题,只是没有深究。因此,在打印文件名时就可以直接使用__NOTDIR_FILE__宏了,而不使用__FILE__宏。为何不直接替换掉__FILE__的内容,因为__FILE__gcc自带的内部定义宏,尽量不要修改。还有一种方法是调用basename(__FILE__)函数,这样可以得到不带路径的文件名,但是没有前一种高效,因为每次打印都要调用一次basename函数。

    关于彩色警告和错误的打印其实就是使用sed在打印的字符串前后加了颜色编码。
 

  3. 循环函数

  1. $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) clean || exit "$$?";)
  Makefile中可以直接调用foreach循环函数,例如上边的dir,循环一次就会从SUBDIRS中取出下一个值,然后在执行的shell代码中使用该值。

  4. 遇到错误后停止编译,直接退出

  1. $(LD) -r $(EXTRA_LDFLAGS) -o $(MODULE) $(SUB_OBJS) || exit "$$?"
  在shell命令后直接加上一句|| exit "$$?,执行失败立即退出。

  5. VPATH变量
  这个变量会指定编译时寻找的目录,如果当前目录没有要找的文件,那么就会跳到VPATH指定的路径下边去查找。


五、demo中所有的文件

./app/api/api.c

  1. #include <stdio.h>

  2. void api_print(void)
  3. {
  4.     DEBUG_1("api.c\n");
  5. }

./app/api/Makefile

  1. clean:
  2.     rm -rf *.[od]

  3. distclean: clean
  4.     
  5. .PHONY: clean distclean

./app/include/app.h

  1. #ifndef APP_H
  2. #define APP_H

  3. #ifdef __NOTDIR_FILE__
  4. #define M2STR(x) #x
  5. #define M2STR_IMPL(x) M2STR(x)
  6. #define __BFILE__ M2STR_IMPL(__NOTDIR_FILE__)
  7. #else
  8. #define __BFILE__ __FILE__
  9. #endif

  10. #define LIGHT_BLUE "\033[1;34m"
  11. #define FMT_NONE "\033[m"

  12. #if 1
  13. #define DEBUG(fmt, arg...) do { \
  14.     fprintf(stdout, "[ %s ] [ %d ] [ %s ]:" \
  15.     LIGHT_BLUE fmt FMT_NONE, __BFILE__, __LINE__, __FUNCTION__, ##arg); \
  16. } while(0)

  17. #define DEBUG_1(fmt, arg...) do { \
  18.     fprintf(stdout, "[ %s ] [ %d ] [ %s ]:" \
  19.     LIGHT_BLUE fmt FMT_NONE, __FILE__, __LINE__, __FUNCTION__, ##arg); \
  20. } while(0)

  21. #else
  22. #define DEBUG(fmt, arg...)
  23. #endif

  24. #endif

./app/Makefile

  1. # 目标文件夹
  2. src-y = src
  3. src-y += api

  4. # 目标文件类型
  5. source_type = .cpp .c    

  6. # 编译所需参数
  7. # EXTRA_CFLAGS:c编译参数
  8. # EXTRA_CXXFLAGS:cpp编译参数
  9. # EXTRA_LDFLAGS:链接成目标.o时的参数
  10. EXTRA_CFLAGS += -I$(CURR_DIR)/include
  11. EXTRA_CXXFLAGS +=
  12. EXTRA_LDFLAGS =

  13. # 加载make.src文件
  14. ifdef MAKE_RULES
  15. include $(MAKE_RULES)/make.src
  16. else
  17. include ./rules.conf
  18. ifdef MAKE_RULES
  19. include $(MAKE_RULES)/make.src
  20. endif
  21. endif    

  22. # 用户编译配置处
  23. # clean: 清除掉源文件生成的目标文件
  24. # distclean: 清除当前和子目录所有的目标文件
  25. # 编译时在这里可以做其它事情
  26. user:

  27. #     用户清理
  28. user_clean:

  29. # 打印变量
  30. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  31. # DEBUG_LEVEL = 2时,才会有打印

  32. user_debug:
  33.     $(call PRINT,CURR_DIR)

./app/src/app.c

  1. #include "app.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>

  5. void app_print(void)
  6. {
  7.     DEBUG("app.c\n");
  8. }

./app/src/Makefile

  1. clean:
  2.     rm -rf *.[od]

  3. distclean: clean
  4.     
  5. .PHONY: clean distclean

./main/include/main.h
  1. #ifndef MAIN_H
  2. #define MAIN_H

  3. #endif

./main/Makefile

  1. # 目标文件夹
  2. src-y = src

  3. # 目标文件类型
  4. source_type = .cpp .c    

  5. # 编译所需参数
  6. # EXTRA_CFLAGS:c编译参数
  7. # EXTRA_CXXFLAGS:cpp编译参数
  8. # EXTRA_LDFLAGS:链接成目标.o时的参数
  9. EXTRA_CFLAGS += -I$(CURR_DIR)/include
  10. EXTRA_CXXFLAGS +=
  11. EXTRA_LDFLAGS =

  12. # 加载make.src文件
  13. ifdef MAKE_RULES
  14. include $(MAKE_RULES)/make.src
  15. else
  16. include ./rules.conf
  17. ifdef MAKE_RULES
  18. include $(MAKE_RULES)/make.src
  19. endif
  20. endif    

  21. # 用户编译配置处
  22. # clean: 清除掉源文件生成的目标文件
  23. # distclean: 清除当前和子目录所有的目标文件
  24. # 编译时在这里可以做其它事情
  25. user:

  26. #     用户清理
  27. user_clean:

  28. # 打印变量
  29. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  30. # DEBUG_LEVEL = 2时,才会有打印

  31. user_debug:
  32.     $(call PRINT,CURR_DIR)

./main/src/main.c

  1. #include "main.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>

  5. int main()
  6. {
  7.     api_print();
  8.     app_print();
  9.     sdk1_1_print();
  10.     sdk1_2_print();    
  11.     sdk2_1_print();
  12.     sdk2_2_print();
  13.     return 0;
  14. }

./main/src/Makefile

  1. clean:
  2.     rm -rf *.[od]

  3. distclean: clean
  4.     
  5. .PHONY: clean distclean



./make.rules/config.in

  1. # 编译规则的文件路径
  2. # MAKE_RULES:编译规则路径

  3. MAKE_RULES := $(shell pwd)/make.rules
  4. export MAKE_RULES
  5.     
  6. # 环境变量添加编译工具链路径
  7. PATH := /usr/local/bin:$(PATH)
  8. export PATH

  9. # 指定编译工具名称
  10. # CROSS_COMPILE:不同平台的交叉编译工具的前缀
  11. CROSS_COMPILE :=

  12. export AS = $(CROSS_COMPILE)as
  13. export LD = $(CROSS_COMPILE)ld
  14. export CC = $(CROSS_COMPILE)gcc
  15. export CPP = $(CROSS_COMPILE)g++
  16. export AR = $(CROSS_COMPILE)ar
  17. export NM = $(CROSS_COMPILE)nm
  18. export STRIP = $(CROSS_COMPILE)strip
  19. export OBJCOPY = $(CROSS_COMPILE)objcopy
  20. export OBJDUMP = $(CROSS_COMPILE)objdump
  21. export RANLIB = $(CROSS_COMPILE)ranlib

  22. # c c++ 编译的通用编译参数
  23. COMMON_CFLAGS     :=
  24. COMMON_CXXFLAGS :=

  25. export CFLAGS     += $(COMMON_CFLAGS)
  26. export CXXFLAGS += $(COMMON_CXXFLAGS)

  27. # 打印帮助信息
  28. help:
  29.     @echo "Usage: make [ target ] [ DEBUG_LEVEL = 0,1,2 ]"
  30.     @echo "Compile a project."
  31.     @echo "The following targets are support:"
  32.     @echo
  33.     @echo " all - compile and link"
  34.     @echo " clean - clean target"
  35.     @echo " distclean - clean target and otherinformation"
  36.     @echo " DEBUG_LEVEL LEVEL - print the variable, LEVEL can be 0, 1, 2"
  37.     @echo " -- 0 print all of the variables"
  38.     @echo "     -- 1 print the debug variables"
  39.     @echo "         -- 2 print the user_debug variables"
  40.     @echo " help - print help information"
  41.     @echo
  42.     @echo "To compile an entire project, do 'make all'"

./make.rules/make.obj

  1. # 加载rules.mk文件
  2. ifdef MAKE_RULES
  3. include $(MAKE_RULES)/rules.mk
  4. endif    

  5. # 编译子目录
  6. SUBDIRS = $(obj-y)

  7. # 目标
  8. # MODULE:最终生成的目标
  9. # SUB_OBJS:链接时需要用到的子目标
  10. SUB_OBJS = $(join $(SUBDIRS), $(patsubst %, /obj-%.o, $(SUBDIRS)))
  11. MODULE = obj-$(shell pwd | sed "s/.*\///" ).o

  12. # 编译入口
  13. all: $(DEBUG_TAG) $(MODULE) user msg_done save_env

  14. # 编译生成目标
  15. $(MODULE): subdir
  16.     $(LD) -r $(EXTRA_LDFLAGS) -o $@ $(SUB_OBJS)    

  17. # 编译子目录    
  18. subdir:
  19.     $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) || exit "$$?";)

  20. # 循环清除下一级目录的所有生成文件
  21. clean: user_clean
  22.     $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) clean || exit "$$?";)
  23.     rm -rf *.[od]    

  24. # 清除当前和下一级目录生成的文件    
  25. distclean:
  26.     $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) distclean || exit "$$?";)    
  27.     rm -rf *.[od]    rules.conf

  28. # 保存一些环境变量
  29. # MAKE_RULES: 保存make规则文件的路径
  30. save_env:
  31.     @if [ ! -f ./rules.conf ]; then \
  32.         if [ -n "${MAKE_RULES}" ]; then \
  33.             echo "MAKE_RULES=${MAKE_RULES}" > ./rules.conf; \
  34.         fi \
  35.     fi

  36. # 编译完成打印
  37. msg_done:
  38.     $(call PRINT_DONE,MODULE)
  39.     
  40. # 打印内部变量
  41. debug:
  42.     $(call PRINT_IN,SUBDIRS)
  43.     $(call PRINT_IN,MODULE)
  44.     $(call PRINT_IN,SUB_OBJS)
  45.     $(call PRINT_IN,DEBUG_TAG)
  46.     $(call PRINT_IN,EXTRA_LDFLAGS)

./make.rules/make.src

  1. # 加载rules.mk文件
  2. ifdef MAKE_RULES
  3. include $(MAKE_RULES)/rules.mk
  4. endif    

  5. # 路径
  6. # CURR_DIR:当前路径
  7. # SUBDIRS:源文件路径
  8. # VPATH:指定源文件搜索路径到路径SUBDIRS中
  9. CURR_DIR = $(shell pwd)
  10. SUBDIRS = $(src-y)
  11. VPATH = $(patsubst %,$(CURR_DIR)/%, $(SUBDIRS))

  12. # 目标
  13. # MODULE: 最终生成的.o目标
  14. # SUB_OBJS: 源文件生成的.o目标
  15. MODULE = obj-$(shell pwd | sed "s/.*\///" ).o
  16. find_source_objs = $(subst $(type),.o,$(wildcard $(patsubst %,%/*$(type), $(SUBDIRS))))
  17. SUB_OBJS = $(foreach type,$(source_type),$(find_source_objs))

  18. # 编译入口
  19. all: $(DEBUG_TAG) $(MODULE) user msg_done save_env

  20. # 编译
  21. $(MODULE): $(SUB_OBJS)
  22.     $(LD) -r $(EXTRA_LDFLAGS) -o $(MODULE) $(SUB_OBJS) || exit "$$?"
  23.     
  24. # 循环清除下一级目录的所有生成文件
  25. clean: user_clean
  26.     $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) clean || exit "$$?";)    
  27.     rm -rf *.[od]
  28.     
  29. # 清除当前和下一级目录生成的文件
  30. distclean:
  31.     $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) distclean || exit "$$?";)    
  32.     rm -rf *.[od] rules.conf

  33. # 保存一些环境变量
  34. # MAKE_RULES: 保存make规则文件的路径
  35. save_env:
  36.     @if [ ! -f ./rules.conf ]; then \
  37.         if [ -n "${MAKE_RULES}" ]; then \
  38.             echo "MAKE_RULES=${MAKE_RULES}" > ./rules.conf; \
  39.         fi \
  40.     fi
  41.     
  42. # 编译完成打印
  43. msg_done:
  44.     $(call PRINT_DONE,MODULE)    
  45.     
  46. # 打印内部变量
  47. debug:
  48.     $(call PRINT_IN,CURR_DIR)
  49.     $(call PRINT_IN,SUBDIRS)
  50.     $(call PRINT_IN,VPATH)
  51.     $(call PRINT_IN,MODULE)
  52.     $(call PRINT_IN,SUB_OBJS)
  53.     $(call PRINT_IN,DEBUG_TAG)
  54.     $(call PRINT_IN,EXTRA_LDFLAGS)
  55.     $(call PRINT_IN,EXTRA_CFLAGS)
  56.     $(call PRINT_IN,EXTRA_CXXFLAGS)
  57.     $(call PRINT_IN,CFLAGS)
  58.     $(call PRINT_IN,CXXFLAGS)

./make.rules/rules.mk

  1. # 定义打印色彩值
  2. REDCOLOR=\033[31m
  3. GREENCOLOR=\033[32m
  4. BROWNCOLOR=\033[33m
  5. BLUECOLOR=\033[34m
  6. PURPLECOLOR=\033[35m
  7. BABYBLUECOLOR=\033[34;1m
  8. WHITECOLOR=\033[37;1m
  9. YELLOWCOLOR=\033[32;1m
  10. ENDCOLOR=\033[0m

  11. # 编译时警告和错误添加颜色和闪烁
  12. CCDONE=$$(echo -e "\033[5;33m")
  13. CCERROR=$$(echo -e "\033[5;31m")
  14. CCWARNING=$$(echo -e "\033[1;35m\033[5m")
  15. CCEND=$$(echo -e "\033[0m")
  16. COLORING=sed -e "s/[Ee]rror[: ]/$(CCERROR)\0$(CCEND)/g" -e "s/[Ww]arning[: ]/$(CCWARNING)\0$(CCEND)/g"

  17. # 编译源文件为.o和.d文件
  18. %.o: %.c
  19.     $(CC) $(EXTRA_CFLAGS) $(CFLAGS) -MD -c $< -o $@ -D__NOTDIR_FILE__=$(notdir $<) 2>&1 | $(COLORING)

  20. %.o: %.cpp
  21.     $(CPP) $(EXTRA_CXXFLAGS) $(CXXFLAGS) -MD -c $< -o $@ -D__NOTDIR_FILE__=$(notdir $<) 2>&1 | $(COLORING)

  22. # 打印变量
  23. # PRINT: 用户(user_debug)打印函数
  24. # PRINT_IN: 内部(debug)打印函数
  25. # PRINT_DONE: 编译目标完成时的打印,有闪烁

  26. PRINT = @echo -e "$(BABYBLUECOLOR)$(1): $($(1)) $(ENDCOLOR)\n";
  27. PRINT_IN = @echo -e "$(GREENCOLOR)$(1): $($(1)) $(ENDCOLOR)\n";
  28. PRINT_DONE = @echo -e "$(CCDONE) make $($(1)) done $(ENDCOLOR)\n";

  29. # 打印等级
  30. # DEBUG_LEVEL: 打印等级,0表示打印用户和系统变量,1表示打印系统变量,2表示打印用户变量

  31. ifdef DEBUG_LEVEL
  32. ifeq ($(DEBUG_LEVEL), 0)
  33. DEBUG_TAG = debug user_debug
  34. endif

  35. ifeq ($(DEBUG_LEVEL), 1)
  36. DEBUG_TAG = debug
  37. endif

  38. ifeq ($(DEBUG_LEVEL), 2)
  39. DEBUG_TAG = user_debug
  40. endif
  41. endif

  42. .PHONY: debug user_debug clean distclean user help

./sdk/Makefile

  1. # 需要编译的子目录
  2. obj-y = sdk1
  3. obj-y += sdk2

  4. # 编译所需参数
  5. # EXTRA_LDFLAGS:链接时需要的参数
  6. EXTRA_LDFLAGS =

  7. # 加载make.obj文件
  8. ifdef MAKE_RULES
  9. include $(MAKE_RULES)/make.obj
  10. else
  11. include ./rules.conf
  12. ifdef MAKE_RULES
  13. include $(MAKE_RULES)/make.obj
  14. endif
  15. endif    

  16. # 用户编译配置处
  17. # clean: 清除掉源文件生成的目标文件
  18. # distclean: 清除当前和子目录所有的目标文件
  19. # 编译时在这里可以做其它事情
  20. user:

  21. #     用户清理
  22. user_clean:

  23. # 打印变量
  24. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  25. # DEBUG_LEVEL = 2时,才会有打印
  26. user_debug:
  27.     $(call PRINT,MAKE_OBJ)

./sdk/sdk1/include/sdk_1.h

  1. #ifndef SDK1_H
  2. #define SDK1_H


  3. #endif

./sdk/sdk1/Makefile

  1. # 目标文件夹
  2. src-y = src

  3. # 目标文件类型
  4. source_type = .cpp .c    

  5. # 编译所需参数
  6. # EXTRA_CFLAGS:c编译参数
  7. # EXTRA_CXXFLAGS:cpp编译参数
  8. # EXTRA_LDFLAGS:链接成目标.o时的参数
  9. EXTRA_CFLAGS += -I$(CURR_DIR)/include
  10. EXTRA_CXXFLAGS += -I$(CURR_DIR)/include
  11. EXTRA_LDFLAGS =

  12. # 加载make.src文件
  13. ifdef MAKE_RULES
  14. include $(MAKE_RULES)/make.src
  15. else
  16. include ./rules.conf
  17. ifdef MAKE_RULES
  18. include $(MAKE_RULES)/make.src
  19. endif
  20. endif    

  21. # 用户编译配置处
  22. # clean: 清除掉源文件生成的目标文件
  23. # distclean: 清除当前和子目录所有的目标文件
  24. # 编译时在这里可以做其它事情
  25. user:

  26. #     用户清理
  27. user_clean:

  28. # 打印变量
  29. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  30. # DEBUG_LEVEL = 2时,才会有打印

  31. user_debug:
  32.     $(call PRINT,CURR_DIR)

./sdk/sdk1/src/Makefile

  1. clean:
  2.     rm -rf *.[od]

  3. distclean: clean
  4.     
  5. .PHONY: clean distclean

./sdk/sdk1/src/sdk1_1.cpp

  1. #include "sdk1.h"
  2. #include <stdio.h>

  3. extern "C" void sdk1_1_print(void)
  4. {
  5.     printf("sdk1_1.cpp\n");
  6. }

./sdk/sdk1/src/sdk1_2.c

  1. #include "sdk1.h"
  2. #include <stdio.h>

  3. void sdk1_2_print(void)
  4. {
  5.     printf("sdk1_2.c\n");
  6. }

./sdk/sdk2/Makefile

  1. # 编译子目录
  2. obj-y = sdk2_1
  3. obj-y += sdk2_2
  4. SUBDIRS = $(obj-y)

  5. # 编译所需参数
  6. # EXTRA_LDFLAGS:链接时需要的参数
  7. EXTRA_LDFLAGS =

  8. # 加载make.obj文件
  9. ifdef MAKE_RULES
  10. include $(MAKE_RULES)/make.obj
  11. else
  12. include ./rules.conf
  13. ifdef MAKE_RULES
  14. include $(MAKE_RULES)/make.obj
  15. endif
  16. endif    

  17. # 用户编译配置处
  18. # clean: 清除掉源文件生成的目标文件
  19. # distclean: 清除当前和子目录所有的目标文件
  20. # 编译时在这里可以做其它事情
  21. user:

  22. #     用户清理
  23. user_clean:

  24. # 打印变量
  25. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  26. # DEBUG_LEVEL = 2时,才会有打印
  27. user_debug:
  28.     $(call PRINT,MAKE_OBJ)

./sdk/sdk2/sdk2_1/include/sdk2_1.h

  1. #ifndef SDK2_1_H
  2. #define SDK2_1_H


  3. #endif

./sdk/sdk2/sdk2_1/Makefile

  1. # 目标文件夹
  2. src-y = src

  3. # 目标文件类型
  4. source_type = .cpp .c    

  5. # 编译所需参数
  6. # EXTRA_CFLAGS:c编译参数
  7. # EXTRA_CXXFLAGS:cpp编译参数
  8. # EXTRA_LDFLAGS:链接成目标.o时的参数
  9. EXTRA_CFLAGS += -I$(CURR_DIR)/include
  10. EXTRA_CXXFLAGS +=
  11. EXTRA_LDFLAGS =

  12. # 加载make.src文件
  13. ifdef MAKE_RULES
  14. include $(MAKE_RULES)/make.src
  15. else
  16. include ./rules.conf
  17. ifdef MAKE_RULES
  18. include $(MAKE_RULES)/make.src
  19. endif
  20. endif    

  21. # 用户编译配置处
  22. # clean: 清除掉源文件生成的目标文件
  23. # distclean: 清除当前和子目录所有的目标文件
  24. # 编译时在这里可以做其它事情
  25. user:

  26. #     用户清理
  27. user_clean:

  28. # 打印变量
  29. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  30. user_debug:
  31.     $(call PRINT,CURR_DIR)
  32.     $(call PRINT,VPATH)
  33.     $(call PRINT,SUB_OBJS)

./sdk/sdk2/sdk2_1/src/Makefile

  1. clean:
  2.     rm -rf *.[od]

  3. distclean: clean
  4.     
  5. .PHONY: clean distclean

./sdk/sdk2/sdk2_1/src/sdk2_1.c

  1. #include "sdk2_1.h"
  2. #include <stdio.h>

  3. void sdk2_1_print(void)
  4. {
  5.     printf("sdk2_1.c\n");
  6. }

./sdk/sdk2/sdk2_2/include/sdk2_2.h

  1. #ifndef SDK2_2_H
  2. #define SDK2_2_H


  3. #endif

./sdk/sdk2/sdk2_2/Makefile

  1. # 目标文件夹
  2. src-y = src

  3. # 目标文件类型
  4. source_type = .cpp .c    

  5. # 编译所需参数
  6. # EXTRA_CFLAGS:c编译参数
  7. # EXTRA_CXXFLAGS:cpp编译参数
  8. # EXTRA_LDFLAGS:链接成目标.o时的参数
  9. EXTRA_CFLAGS += -I$(CURR_DIR)/include
  10. EXTRA_CXXFLAGS +=
  11. EXTRA_LDFLAGS =

  12. # 加载make.src文件
  13. ifdef MAKE_RULES
  14. include $(MAKE_RULES)/make.src
  15. else
  16. include ./rules.conf
  17. ifdef MAKE_RULES
  18. include $(MAKE_RULES)/make.src
  19. endif
  20. endif    

  21. # 用户编译配置处
  22. # clean: 清除掉源文件生成的目标文件
  23. # distclean: 清除当前和子目录所有的目标文件
  24. # 编译时在这里可以做其它事情
  25. user:

  26. #     用户清理
  27. user_clean:

  28. # 打印变量
  29. # $(call PRINT,变量):调用该函数可以打印编译时变量的值,该函数定义在rules.mk文件中
  30. # DEBUG_LEVEL = 2时,才会有打印
  31. user_debug:
  32.     $(call PRINT,CURR_DIR)

./sdk/sdk2/sdk2_2/src/Makefile

  1. clean:
  2.     rm -rf *.[od]

  3. distclean: clean
  4.     
  5. .PHONY: clean distclean

./sdk/sdk2/sdk2_2/src/sdk2_2.c

  1. #include "sdk2_2.h"
  2. #include <stdio.h>

  3. void sdk2_2_print(void)
  4. {
  5.     printf("sdk2_2.c\n");
  6. }


阅读(6930) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~