• 编写一个通用的Makefile文件


    1.1在这之前,我们需要了解程序的编译过程

    a.预处理:检查语法错误,展开宏,包含头文件等

    b.编译:*.c-->*.S

    c.汇编:*.S-->*.o

    d.链接:.o +库文件=*.exe

    1.2体验在VC下程序的编译

    a.先编译,在链接

    b.修改了哪个文件,就单独编译此文件,在链接

    c.修改了哪个头文件,就单独编译使用该头文件的源文件,在链接

    1.3在linux下实现上述要求

    2.编写一个测试的Makefile

    2.1直接编译链接

     1 gcc -o test a.c b.c 

    缺点:改变其中一个文件,还需要重新编译所有文件,最后链接,效率低

    2.2编写一个通用的Makefile

    核心:规则

    目标:依赖1 依赖2...

      命令

    命令的执行条件:

    a.依赖文件比目标文件新

    b.没有目标文件

    2.2.1一个简单的Makefile文件

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

    缺点:当其中一个文件发生改变时,另一个文件又将从新编译链接

    2.2.2针对上述,改为如下

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

    缺点:a.如果test依赖于多个文件,将写许多代码。

    b.修改a.h程序没有反应。

    2.2.3

    针对上述a,可将其改为通配符;针对b,可增加“a.o:a.c a.h”这段代码。

    $@:表示目标;$^:表示全部依赖;$<:第一个依赖。

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

    缺点:如果一个文件的头文件非常多,不可能一个一个列出来,应该生成一个依赖文件。

    2.2.4生成依赖文件

    wildcard:检查文件是否存在

    -Wp,-MD:生成依赖文件

    objs := a.o b.o
    
    test:$(objs)
        gcc -o test $^
    
    # .a.o.d .b.o.d
    dep_files := $(foreach f,$(objs),.$(f).d)//对于objs里的每个文件,生成对应的依赖文件。eg:a.o-->.a.o.d
    dep_files := $(wildcard $(dep_files))
    
    ifneq ($(dep_files),)
      include $(dep_files)
    endif
    
    %.o : %.c 
        gcc -Wp,-MD,.$@.d -c -o $@ $<
    
    clean:
        rm *.o test

    3.参照内核的Makefile和上述的test_Makefile,编写一个通用的Makefile

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

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

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

    CROSS_COMPILE = arm-linux-      //交叉编译工具链
    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     //导出变量
    export STRIP OBJCOPY OBJDUMP
    
    CFLAGS := -Wall -O2 -g        //编译选项
    CFLAGS += -I $(shell pwd)/include
    
    LDFLAGS := -lm -lfreetype     //链接选项
    
    export CFLAGS LDFLAGS
    
    TOPDIR := $(shell pwd)
    export TOPDIR
    
    TARGET := show_file
    
    
    obj-y += main.o
    obj-y += display/
    obj-y += draw/
    obj-y += encoding/
    obj-y += fonts/
    
    
    all : 
        make -C ./ -f $(TOPDIR)/Makefile.build       //打开文件,按照顶层目录下的Makefile.build来编译
        $(CC) $(LDFLAGS) -o $(TARGET) built-in.o     //link
    
    
    clean:
        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)
        

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

    PHONY := __build
    __build:
    
    
    obj-y :=
    subdir-y :=
    
    include Makefile
    __subdir-y    := $(patsubst %/,%,$(filter %/, $(obj-y)))
    subdir-y    += $(__subdir-y)
    subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)
    
    cur_objs := $(filter-out %/, $(obj-y))
    dep_files := $(foreach f,$(cur_objs),.$(f).d)
    dep_files := $(wildcard $(dep_files))
    
    ifneq ($(dep_files),)
      include $(dep_files)
    endif
    
    
    PHONY += $(subdir-y)
    
    
    __build : $(subdir-y) built-in.o
    
    $(subdir-y):
        make -C $@ -f $(TOPDIR)/Makefile.build
    
    built-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

  • 相关阅读:
    【Netty学习】 ChannelInitializer 学习
    【Netty学习】Netty 4.0.x版本和Flex 4.6配合
    Spring框架学习
    【JS教程23】jquery链式调用
    【JS教程22】jquery特殊效果
    【JS教程21】数组及操作方法
    【JS教程20】jquery动画
    【JS教程19】jquery绑定click事件
    【JS教程18】jquery样式操作
    【JS教程17】jquery选择器
  • 原文地址:https://www.cnblogs.com/Lwd-linux/p/6217336.html
Copyright © 2020-2023  润新知