• 一个通用的Makefile(二)


    1、各级子目录的Makefile:

    • obj-y += file.o
    • obj-y += subdir/

    “obj-y += file.o” 表示把当前目录下的file.c编进程序里。

    “obj-y += subdir/”表示进入subdir这个子目录下去寻找文件来编进子程序中;

    2、顶层目录的Makefile:

    CROSS_COMPILE =                        #如果要交叉编译的话,就是: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导出来,后面的子目录就能用:

    export STRIP OBJCOPY OBJDUMP

    CFLAGS := -Wall -O2 -g 

    CFLAGS += -I $(shell pwd)/include -I 。。。。      # -I 指定到哪个目录去搜索头文件。

    LDFLAGS := -lm 。。。。。

    export CFLAGS LDFLAGS      #把这两个也导出来。

    TOPDIR := $(shell pwd)         #顶层目录

    export TOPDIR

    TARGET := show_file             #目标

    • obj-y += main.o
    • obj-y += 目录名如package/
    • obj-y += framework/

    all :

         make -C ./ -f $(TOPDIR)/Makefile.build

         $(CC) $(LDFLAGS) -o $(TARGET) built-in.o

    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)

    我们这个工程顶层有:main.c,还有package,framework等子目录

    framwork子目录下又有libs、manager、services等子目录;

    编译过程:

    Makefile是先从子目录下开始执行的:

    1> 执行顶层目录的makefile程序时,先进入顶层目录,发现有些文件和目录,将会进入如DSVICICOMSVC/

    2> 进入子目录后,又会发现又有子目录的makefile,DSVICICOMSVC、DSVICICOMMGR,执行子目录的makefile;

    3> 把test.c编译成test.o,把test目录下的.o文件打包成build_in.o

    4> 经过多个子目录后,回到顶层目录.把main.c 编译成main.o ,并与各个子目录的build-in.o打包成最终的build-in.o.
    make -C ./ -f  Makefile.build   

    3、顶层目录的Makefile.build:

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

    PHONY := __build       #假目标

    __build:

    obj-y :=

    subdir-y :=

    include Makefile                      #包含当前目录的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.o

    subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)

    # a.o b.o

    cur_objs := $(filter-out %/, $(obj-y))

    dep_files := $(foreach f,$(cur_objs),.$(f).d)   #(foreach var,list,text) 结果是由空格隔开的‘text’ 在‘list’中多次扩展的字组成的新的‘list’

    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)

    4、怎么使用这套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/

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

  • 相关阅读:
    HBase Coprocessor 剖析与编程实践
    图数据库实践系列 (一)Neo4J简介与安装
    BootStrap入门教程 (三)
    图数据库实践系列 (三)Neo4j Spatial的REST集成
    BootStrap入门教程 (二)
    R与GIS实践系列Shapefile导入与地图显示
    空间分析读书笔记
    BootStrap入门教程 (四)
    Java并发之线程池的使用浅析
    RSA详解
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/7760413.html
Copyright © 2020-2023  润新知