linux项目用Makefile编写

linux项目用Makefile编写


一 工程必备

顶层Makefile 顶层Makefile.build 子目录Makefile


二 编译过程

    从顶层开始递归进入子目录,当进入到一个目录的最底层时,开始使用GCC编译,再将该层的所有.o文件打包成build-in.o,返回它的上一层目录再递归进入子目录,当编译完所有的子目录后,就开始编译顶层的.c文件,最后将顶层的.o文件和顶层每个子目录的build-in.o链接成我们的目标文件


三 顶层Makefile解析

#----------------------------------------------指定编译工具链---------------------------------------------------

CROSS_COMPILE =                             #指定编译器种类

AS        = $(CROSS_COMPILE)as         #

LD        = $(CROSS_COMPILE)ld          #链接工具

CC        = $(CROSS_COMPILE)gcc       #编译工具

CPP        = $(CC) -E                             #

AR        = $(CROSS_COMPILE)ar         #打包工具

NM        = $(CROSS_COMPILE)nm       #

 

STRIP        = $(CROSS_COMPILE)strip              #优化工具

OBJCOPY        = $(CROSS_COMPILE)objcopy   

OBJDUMP        = $(CROSS_COMPILE)objdump  

 

export AS LD CC CPP AR NM                           #将定义的变量导出,方便其他makefile使用

export STRIP OBJCOPY OBJDUMP                    #将定义的变量导出,方便其他makefile使用

 

TOPDIR := $(shell pwd)                                             #获得当前程序的顶层目录

CFLAGS := -Wall -O2 -g                                            #编译器参数

INCLUDES := -I$(shell pwd)/include                          #指定编译器头文件(根据实际项目手动修改)

LDFLAGS := -lm -lfreetype -lvga                                #指定编译器链接库(根据实际项目手动修改)

export TOPDIR CFLAGS LDFLAGS  INCLUDES             #将定义的变量导出,方便其他makefile使用

 TARGET := show_file                                                #编译后的程序名(根据实际项目手动修改)

#-------------------------顶层要生成的.o文件以及顶层文件夹(根据实际项目手动修改)------------------

obj-y += main.o

obj-y += display/

obj-y += draw/

obj-y += encoding/

obj-y += fonts/

#--------------------------------------------顶层的第一个规则(默认规则)-----------------------------------------

all :

    make -C ./ -f $(TOPDIR)/Makefile.build   __build            #进入当前目录,使用顶层的makefile.build中的伪目标__build进行编译

    $(CC) $(LDFLAGS) -o $(TARGET) built-in.o         #将编译好的built-in.o文件链接生成我们的目标文件

#------------------------------------------------顶层的清除规则-------------------------------------------------------

clean:

    make -C ./ -f $(TOPDIR)/Makefile.build cleans   #进入当前目录,执行Makfile.build中的伪目标cleans

    rm -f $(shell find -name "*.o")                        #删除所有的.o文件

    rm -f $(shell find -name "*.d")                        #删除所有的.d文件

    rm -f $(TARGET)                                             #删除目标文件

.PHONY:all clean


四 顶层Makefile.build解析

PHONY := __build                                          #定义一个PHONY变量

__build:                                                       #开头说明__build伪目标,使其成为Makefile.build的第一个目标

obj-y :=                                                       #定义当前目录的目标变量,初始值为空

subdir-y :=                                                   #定义当前目录的子目录变量,初始值为空

include Makefile                                             #将当前目录的Makefile包含进来,初始化obj-y

                                                                   #obj-y:=a.o b.o c/ d/

__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))   #筛选出当前目录的目标变量中的子目录,并且去掉

                                                                            #$(filter %/, $(obj-y)):c/ d/

                                                                            #__subdir-y:c d

subdir-y += $(__subdir-y)                                        #将开始定义的subdir-y赋值为__subdir-y

                                                                            #subdir-y:c d

subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)  #对于subdir-y里面的每一个值(目录),增加一个相应的目录/built-in.o的变量

                                                                          #subdir_objs:c/built-in.o d/built-in.o

cur_objs := $(filter-out %/, $(obj-y))                        #得到obj-y中的.o文件

                                                                           #cur_objs:a.o b.o

INCLUDES += $(foreach f, $(subdir-y), -I$(TOP)/$(f)/include)  #-I用于后面编译的时候的参数,表示需要包含这个路径下的头文件

                                                                                     #ICLUDES也可以写到子目录下的Makefile中

                                                                                     #例如,INCLUDES += -I$(TOP)/c/include 

PHONY += $(subdir-y)            #将$(subdir-y)也加入到变量PHONY中

--------------------------------------------Makefile. build的第一个规则--------------------------------------------------------------

__build : $(subdir-y) built-in.o                                   #第一个规则

$(subdir-y):                                                                #第一个规则的第一个依赖规则

    make -C $@ -f $(TOPDIR)/Makefile.build                     #依次进入该子目录变量里面存储的值,使用的Makefile.build进行编译

 built-in.o : $(cur_objs) $(subdir_objs)                            #第一个规则的第二个依赖规则

      $(LD) -r -o $@ $^                                                 #该规则的命令:将该目录下的.o和$(subdir_obj)打包成built-in.o文件

%.o : %.c                                                                   #第一个规则的第二个依赖规则的依赖规则 

$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<        #用于将目录下所有的.c文件编译成.o文件

                                                                            #这里根据系统编译的情况来决定是否使用-Wp,一般不使用-Wp


subdirs_clean := $(foreach f, $(subdirs-y), $(f)_clean)   #将各个子目录名后面添加“_clean”字符,这里是为了与subdirs区分

cleans: $(subdirs_clean)

$(subdirs_clean):                                                     #这里不能直接使用subdirs-y,是因为这个名称在上面已经使用过了,

                                                                            #如果再次使用,会将之前的那个覆盖掉,所以要换名称

make -C $(patsubst %_clean, %, $@) clean         #patsubst是去掉subdirs_clean中的字符"_clean",这里就是进入子目录执行make clean

.PHONY : $(PHONY)   cleans                                      #将PHONY声明为伪目标


 五 子目录Makefile

子目录的Makefile就是包含该目录下所有的目标文件名和子目录文件夹名。

它最简单,形式如下:
obj-y += file.o
obj-y += subdir/
   
"obj-y += file.o"表示把当前目录下的file.c编进程序里,
"obj-y += subdir/"表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。
注意: "subdir/"中的斜杠"/"不可省略

转载自:http://www.cnblogs.com/lidabo/p/4521123.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值