zoukankan      html  css  js  c++  java
  • 编写一个通用的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

  • 相关阅读:
    把影响集中到一个点
    How to avoid Over-fitting using Regularization?
    适定性问题
    Numerical Differentiation 数值微分
    What Every Computer Scientist Should Know About Floating-Point Arithmetic
    Generally a good method to avoid this is to randomly shuffle the data prior to each epoch of training.
    What is the difference between iterations and epochs in Convolution neural networks?
    Every norm is a convex function
    Moore-Penrose Matrix Inverse 摩尔-彭若斯广义逆 埃尔米特矩阵 Hermitian matrix
    perl 类里的函数调用其他类的函数
  • 原文地址:https://www.cnblogs.com/Lwd-linux/p/6217336.html
Copyright © 2011-2022 走看看