你的位置:首页 > 操作系统

[操作系统]4通用Makefile编写


 

a.c

#include<stdio.h>#include "a.h"int main(){    printf("hello world\n");  printf("A= %d\n",A);  test_fun();  return 0;}

a.h

#define A 1

b.c

#include <stdio.h>int test_fun(){   printf("it is B\n");  return 0;}

 

编译test_Makefile的方法:
a. gcc -o test a.c b.c
对于a.c: 预处理、编译、汇编
对于b.c:预处理、编译、汇编
最后链接
优点:命令简单
缺点:如果文件很多,即使你只修改了一个文件,但是所有的文件文件都要重新"预处理、编译、汇编"
      效率低

 

b. 写Makefile
核心:规则

目标:依赖1 依赖2
    命令

命令执行的条件:
i. "依赖"文件 比 "目标"文件 新
ii.没有"目标"这个文件
  

Makefile_1 

test: a.c b.c a.h   gcc -o test a.c b.c

只要有任一文件变化,就执行gcc -o test a.c b.c效率低

Makefile_2

test : a.o b.o   gcc -o test a.o b.oa.o : a.c  gcc -c -o a.o a.cb.o : b.c  gcc -c -o b.o b.c

文件不会随着某个文件变化而全部编译

 

Makefile_3

test : a.o b.o   gcc -o test a.o b.o  a.o : a.c a.h%.o : %.c  gcc -c -o $@ $<

加通通配符,通配符%,$@表示目标值,$<表示第一个依赖,$^表示所有依赖

不能生成依赖文件

 

电子书Makefile

 

CROSS_COMPILE = arm-linux-AS    = $(CROSS_COMPILE)asLD    = $(CROSS_COMPILE)ldCC    = $(CROSS_COMPILE)gccCPP    = $(CC) -EAR    = $(CROSS_COMPILE)arNM    = $(CROSS_COMPILE)nmSTRIP    = $(CROSS_COMPILE)stripOBJCOPY    = $(CROSS_COMPILE)objcopyOBJDUMP    = $(CROSS_COMPILE)objdumpexport AS LD CC CPP AR NM export STRIP OBJCOPY OBJDUMP

编译选项

CFLAGS := -Wall -O2 -gCFLAGS += -I $(shell pwd)/include

链接选项

LDFLAGS := -lm -lfreetypeexport CFLAGS LDFLAGS

假目标

PHONY := __build__build:


obj-y :=subdir-y :=

包含当前目录下的Makefile
include Makefile

 

 

最终文件

Makefile

CROSS_COMPILE = AS    = $(CROSS_COMPILE)asLD    = $(CROSS_COMPILE)ldCC    = $(CROSS_COMPILE)gccCPP    = $(CC) -EAR    = $(CROSS_COMPILE)arNM    = $(CROSS_COMPILE)nmSTRIP    = $(CROSS_COMPILE)stripOBJCOPY    = $(CROSS_COMPILE)objcopyOBJDUMP    = $(CROSS_COMPILE)objdumpexport AS LD CC CPP AR NMexport STRIP OBJCOPY OBJDUMPCFLAGS := -Wall -O2 -gCFLAGS += -I $(shell pwd)/include  -I /usr/include/freetype2/LDFLAGS := -lm -lfreetype  -lvga -lvgaglexport CFLAGS LDFLAGSTOPDIR := $(shell pwd)export TOPDIRTARGET := show_fileobj-y += main.oobj-y += display/obj-y += draw/obj-y += encoding/obj-y += fonts/all :   make -C ./ -f $(TOPDIR)/Makefile.build  $(CC) $(LDFLAGS) -o $(TARGET) built-in.oclean:  rm -f $(shell find -name "*.o")  rm -f $(TARGET)distclean:  rm -f $(shell find -name "*.o")  rm -f $(shell find -name "*.d")  rm -f $(TARGET)

Makefile.build

PHONY := __build__build:obj-y :=subdir-y :=include Makefile# obj-y := a.o b.o c/ d/# $(filter %/, $(obj-y))  : c/ d/# __subdir-y : c d# subdir-y  : c d__subdir-y  := $(patsubst %/,%,$(filter %/, $(obj-y)))subdir-y  += $(__subdir-y)# c/built-in.o d/built-in.osubdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)# a.o b.ocur_objs := $(filter-out %/, $(obj-y))dep_files := $(foreach f,$(cur_objs),.$(f).d)dep_files := $(wildcard $(dep_files))ifneq ($(dep_files),) include $(dep_files)endifPHONY += $(subdir-y)__build : $(subdir-y) built-in.o$(subdir-y):  make -C $@ -f $(TOPDIR)/Makefile.buildbuilt-in.o : $(cur_objs) $(subdir_objs)  $(LD) -r -o $@ $^dep_file = .$@.d%.o : %.c  $(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<  .PHONY : $(PHONY)

 

 

本程序的Makefile分为3类:
1. 顶层目录的Makefile
2. 顶层目录的Makefile.build
3. 各级子目录的Makefile

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

注意: "subdir/"中的斜杠"/"不可省略

二、顶层目录的Makefile:
   它除了定义obj-y来指定根目录下要编进程序去的文件、子目录外,主要是定义工具链、编译参数、链接参数──就是文件中用export导出的各变量。

三、顶层目录的Makefile.build:
   这是最复杂的部分,它的功能就是把某个目录及它的所有子目录中、需要编进程序去的文件都编译出来,打包为built-in.o
   详细的讲解请看视频。

四、怎么使用这套Makefile:
1.把顶层Makefile, Makefile.build放入程序的顶层目录
2.修改顶层Makefile
2.1 修改工具链
2.2 修改编译选项、链接选项
2.3 修改obj-y决定顶层目录下哪些文件、哪些子目录被编进程序
2.4 修改TARGET,这是用来指定编译出来的程序的名字

3. 在各一个子目录下都建一个Makefile,形式为:
obj-y += file1.o
obj-y += file2.o
obj-y += subdir1/
obj-y += subdir2/

4. 执行"make"来编译,执行"make clean"来清除,执行"make distclean"来彻底清除