一个简单的Makefile编译框架

2019-11-18 14:51 来源:未知

一个简单的Makefile编译框架

最近在做一个项目时对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文件。

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

# 编译所需参数
# EXTRA_LDFLAGS:链接时需要的参数
EXTRA_LDFLAGS =

# 加载make.obj文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.obj
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.obj
endif
endif

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

# 用户清理
user_clean:

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

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

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

# 目标文件夹
 src-y = src

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

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

# 加载make.src文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
endif
endif

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

# 用户清理
user_clean:

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

user_debug:
$(call PRINT,CURR_DIR) 

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

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

clean:
 rm -rf *.[od]

distclean: clean

.PHONY: clean distclean
  1. 关于./make.rules目录中的规则或配置文件。

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

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

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

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

四、一些实现细节

  1. 打印函数

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

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

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

    COLORING=sed -e "s/[Ee]rror[: ]/$(CCERROR)$(CCEND)/g" -e "s/[Ww]arning[: ]/$(CCWARNING)$(CCEND)/g" %.o: %.c $(CC) $(EXTRA_CFLAGS) $(CFLAGS) -MD -c $< -o [email protected] -DNOTDIR_FILE=$(notdir $&1 | $(COLORING)

%.o: %c是一种指定泛型的目标与依赖方式,在同一个makefile中,只要其他目标有依赖后缀为.o目标,那么执行到该目标时,就会执行%.o: %.c。这时-D__NOTDIR_FILE__=$(notdir$

可以除掉路径,只留下文件名。那么这里为何要定义一个-D__NOTDIR_FILE__的宏呢,因为如果这里的$带了路径>

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

  1. 循环函数

    $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) clean || exit "$$?";)

Makefile中可以直接调用foreach循环函数,例如上边的dir,循环一次就会从SUBDIRS中取出下一个值,然后在执行的shell代码中使用该值。

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

    $(LD) -r $(EXTRA_LDFLAGS) -o $(MODULE) $(SUB_OBJS) || exit "$$?"

在shell命令后直接加上一句|| exit "$$?,执行失败立即退出。

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

五、demo中所有的文件

./app/api/api.c

#include 

void api_print(void)
{
DEBUG_1("api.cn");
}

./app/api/Makefile

clean:
 rm -rf *.[od]

distclean: clean

.PHONY: clean distclean

./app/include/app.h

#ifndef APP_H
 #define APP_H

#ifdef __NOTDIR_FILE__
#define M2STR(x) #x
#define M2STR_IMPL(x) M2STR(x)
#define __BFILE__ M2STR_IMPL(__NOTDIR_FILE__)
#else
#define __BFILE__ __FILE__
#endif

#define LIGHT_BLUE "33[1;34m"
#define FMT_NONE "33[m"

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

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

#else
#define DEBUG(fmt, arg...)
#endif

#endif 

./app/Makefile

# 目标文件夹
 src-y = src
src-y += api

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

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

# 加载make.src文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
endif
endif

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

# 用户清理
user_clean:

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

user_debug:
$(call PRINT,CURR_DIR) 

./app/src/app.c

#include "app.h"
 #include 
#include 
#include 

void app_print(void)
{
DEBUG("app.cn");
}

./app/src/Makefile

clean:
 rm -rf *.[od]

distclean: clean

.PHONY: clean distclean

./main/include/main.h

#ifndef MAIN_H
 #define MAIN_H

#endif 

./main/Makefile

# 目标文件夹
 src-y = src

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

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

# 加载make.src文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
endif
endif

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

# 用户清理
user_clean:

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

user_debug:
$(call PRINT,CURR_DIR) 

./main/src/main.c

#include "main.h"
 #include 
#include 
#include 

int main()
{
api_print();
app_print();
sdk1_1_print();
sdk1_2_print();
sdk2_1_print();
sdk2_2_print();
return 0;
}

./main/src/Makefile

clean:
 rm -rf *.[od]

distclean: clean

.PHONY: clean distclean

./make.rules/config.in

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

MAKE_RULES := $(shell pwd)/make.rules
export MAKE_RULES

# 环境变量添加编译工具链路径
PATH := /usr/local/bin:$(PATH)
export PATH

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

export AS = $(CROSS_COMPILE)as
export LD = $(CROSS_COMPILE)ld
export CC = $(CROSS_COMPILE)gcc
export CPP = $(CROSS_COMPILE)g++
export AR = $(CROSS_COMPILE)ar
export NM = $(CROSS_COMPILE)nm
export STRIP = $(CROSS_COMPILE)strip
export OBJCOPY = $(CROSS_COMPILE)objcopy
export OBJDUMP = $(CROSS_COMPILE)objdump
export RANLIB = $(CROSS_COMPILE)ranlib

# c c++ 编译的通用编译参数
COMMON_CFLAGS := 
COMMON_CXXFLAGS := 

export CFLAGS += $(COMMON_CFLAGS)
export CXXFLAGS += $(COMMON_CXXFLAGS)

# 打印帮助信息
help:
@echo "Usage: make [ target ] [ DEBUG_LEVEL = 0,1,2 ]"
@echo "Compile a project."
@echo "The following targets are support:"
@echo
@echo " all                - compile and link"
@echo " clean              - clean target"
@echo " distclean          - clean target and otherinformation"
@echo " DEBUG_LEVEL LEVEL  - print the variable,  LEVEL can be 0, 1, 2"
@echo "                      -- 0 print all of the variables"
@echo "              -- 1 print the debug variables"
@echo "      -- 2 print the user_debug variables"
@echo " help               - print help information"
@echo
@echo "To compile an entire project, do 'make all'" 

./make.rules/make.obj

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

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

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

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

# 编译生成目标
$(MODULE): subdir 
$(LD) -r $(EXTRA_LDFLAGS) -o [email protected] $(SUB_OBJS)

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

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

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

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

# 编译完成打印
msg_done:
$(call PRINT_DONE,MODULE)

# 打印内部变量
debug:
$(call PRINT_IN,SUBDIRS)
$(call PRINT_IN,MODULE)
$(call PRINT_IN,SUB_OBJS)
$(call PRINT_IN,DEBUG_TAG)
$(call PRINT_IN,EXTRA_LDFLAGS) 

./make.rules/make.src

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

# 路径
# CURR_DIR:当前路径
# SUBDIRS:源文件路径
# VPATH:指定源文件搜索路径到路径SUBDIRS中
CURR_DIR = $(shell pwd)
SUBDIRS = $(src-y)
VPATH = $(patsubst %,$(CURR_DIR)/%, $(SUBDIRS))

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

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

# 编译
$(MODULE): $(SUB_OBJS)
$(LD) -r $(EXTRA_LDFLAGS) -o $(MODULE) $(SUB_OBJS) || exit "$$?"

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

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

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

# 编译完成打印
msg_done:
$(call PRINT_DONE,MODULE)

# 打印内部变量
debug:
$(call PRINT_IN,CURR_DIR)
$(call PRINT_IN,SUBDIRS)
$(call PRINT_IN,VPATH)
$(call PRINT_IN,MODULE)
$(call PRINT_IN,SUB_OBJS)
$(call PRINT_IN,DEBUG_TAG)
$(call PRINT_IN,EXTRA_LDFLAGS)
$(call PRINT_IN,EXTRA_CFLAGS)
$(call PRINT_IN,EXTRA_CXXFLAGS)
$(call PRINT_IN,CFLAGS)
$(call PRINT_IN,CXXFLAGS) 

./make.rules/rules.mk

# 定义打印色彩值
 REDCOLOR=33[31m
GREENCOLOR=33[32m
BROWNCOLOR=33[33m
BLUECOLOR=33[34m
PURPLECOLOR=33[35m
BABYBLUECOLOR=33[34;1m
WHITECOLOR=33[37;1m
YELLOWCOLOR=33[32;1m
ENDCOLOR=33[0m

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

# 编译源文件为.o和.d文件
%.o: %.c
$(CC) $(EXTRA_CFLAGS) $(CFLAGS) -MD -c $< -o [email protected] -D__NOTDIR_FILE__=$(notdir $&1 | $(COLORING)

%.o: %.cpp
$(CPP) $(EXTRA_CXXFLAGS) $(CXXFLAGS) -MD -c $< -o [email protected] -D__NOTDIR_FILE__=$(notdir $&1 | $(COLORING)

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

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

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

ifdef DEBUG_LEVEL
ifeq ($(DEBUG_LEVEL), 0) 
DEBUG_TAG = debug user_debug
endif

ifeq ($(DEBUG_LEVEL), 1) 
DEBUG_TAG = debug
endif

ifeq ($(DEBUG_LEVEL), 2) 
DEBUG_TAG = user_debug
endif
endif

.PHONY: debug user_debug clean  distclean user help

./sdk/Makefile

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

# 编译所需参数
# EXTRA_LDFLAGS:链接时需要的参数
EXTRA_LDFLAGS =

# 加载make.obj文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.obj
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.obj
endif
endif

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

# 用户清理
user_clean:

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

./sdk/sdk1/include/sdk_1.h

#ifndef SDK1_H
 #define SDK1_H


#endif 

./sdk/sdk1/Makefile

# 目标文件夹
 src-y = src

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

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

# 加载make.src文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
endif
endif

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

# 用户清理
user_clean:

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

user_debug:
$(call PRINT,CURR_DIR) 

./sdk/sdk1/src/Makefile

clean:
 rm -rf *.[od]

distclean: clean

.PHONY: clean distclean

./sdk/sdk1/src/sdk1_1.cpp

#include "sdk1.h"
 #include 

extern "C" void sdk1_1_print(void)
{
printf("sdk1_1.cppn");
}

./sdk/sdk1/src/sdk1_2.c

#include "sdk1.h"
 #include 

void sdk1_2_print(void)
{
printf("sdk1_2.cn");
}

./sdk/sdk2/Makefile

# 编译子目录
 obj-y = sdk2_1
obj-y += sdk2_2
SUBDIRS = $(obj-y)

# 编译所需参数
# EXTRA_LDFLAGS:链接时需要的参数
EXTRA_LDFLAGS =

# 加载make.obj文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.obj
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.obj
endif
endif

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

# 用户清理
user_clean:

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

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

#ifndef SDK2_1_H
 #define SDK2_1_H


#endif 

./sdk/sdk2/sdk2_1/Makefile

# 目标文件夹
 src-y = src

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

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

# 加载make.src文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
endif
endif

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

# 用户清理
user_clean:

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

./sdk/sdk2/sdk2_1/src/Makefile

clean:
 rm -rf *.[od]

distclean: clean

.PHONY: clean distclean

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

#include "sdk2_1.h"
 #include 

void sdk2_1_print(void)
{
printf("sdk2_1.cn");
}

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

#ifndef SDK2_2_H
 #define SDK2_2_H


#endif 

./sdk/sdk2/sdk2_2/Makefile

# 目标文件夹
 src-y = src

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

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

# 加载make.src文件
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
else
include ./rules.conf
ifdef MAKE_RULES
include $(MAKE_RULES)/make.src
endif
endif

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

# 用户清理
user_clean:

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

./sdk/sdk2/sdk2_2/src/Makefile

clean:
 rm -rf *.[od]

distclean: clean

.PHONY: clean distclean

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

#include "sdk2_2.h"
 #include 

void sdk2_2_print(void)
{
printf("sdk2_2.cn");
}

最近在做一个项目时对makefile有了一个简单的认识,于是自己写了一个简单的编译框架,留待后用。下边是一个...

TAG标签:
版权声明:本文由990888藏宝阁发布于计算机网络,转载请注明出处:一个简单的Makefile编译框架