zoukankan      html  css  js  c++  java
  • 模仿u-boot的makefile结构

    u-boot(2014.04)是通过顶层makefile调用各子目录中的makefile来实现整个工程的编译的,实际上子目录的makefile是include进来的。这里仿照这种结构写个模板测试一下。

    目录结构:

    mytest:

      add:

        mul:

          Makefile

          mul.c

          mul.h

        add.c

        add.h

        Makefile

      main:

        main.c

        Makefile

      scripts:

        Makefile.build

        Makefile.clean

        Makefile.lib

      sub:

        div

          div.c

          div.h

          Makefile

        sub.c

        sub.h

        Makefile

    顶层Makefile:

     1 CC := gcc
     2 LD := ld
     3 
     4 CFLAGS := -g
     5 
     6 PHONY := all
     7 
     8 target := mainApp
     9 
    10 # default target
    11 all: $(target)
    12 
    13 # dirs to be compiled
    14 src-dirs += add/
    15 src-dirs += sub/
    16 src-dirs += main/
    17 
    18 # libs to be linked
    19 libs-y := $(patsubst %/,%/built-in.o,$(src-dirs))
    20 
    21 src-dirs := $(patsubst %/,%,$(src-dirs))
    22 
    23 # include dirs
    24 inc-dirs := $(addprefix -I,$(src-dirs))
    25 
    26 # the Makefile for building
    27 build := -f scripts/Makefile.build obj
    28 
    29 CFLAGS += $(inc-dirs)
    30 export CC LD CFLAGS
    31 
    32 
    33 PHONY += $(src-dirs)
    34 
    35 # linking
    36 $(target): $(src-dirs)
    37     $(CC) -o $@ $(libs-y)
    38 
    39 # compiling source dirs
    40 $(src-dirs):
    41     make $(build)=$@
    42 
    43 # Clean
    44 clean-dirs := $(foreach f,$(src-dirs),$(if $(wildcard $f/Makefile),$f))
    45 clean-dirs := $(addprefix _clean_, $(clean-dirs))
    46 PHONY += clean $(clean-dirs)
    47 
    48 # descending to subdirs for cleaning
    49 $(clean-dirs):
    50     make $(clean)=$(patsubst _clean_%,%,$@)
    51 
    52 # just simply remove .o and target 
    53 clean: $(clean-dirs)
    54     @find . ( -name '*.o' -o -name '$(target)' ) -type f | xargs rm -f 
    55 
    56 clean := -f scripts/Makefile.clean obj
    57 .PHONY : $(PHONY)

    顶层Makefile确定target,要编译的源码目录,include的路径。

    第41行使用scripts/Makefile.build对各个源码目录进行编译,Makefile.build为实际编译代码的makefile,内容如下:

     1 src := $(obj)
     2 
     3 PHONY := __build
     4 
     5 obj-y := 
     6 
     7 # include the Makefile in the $(obj) dir
     8 build-dir := $(src)
     9 build-file := $(build-dir)/Makefile
    10 include $(build-file)
    11 
    12 # include scripts/Makefile.lib
    13 include scripts/Makefile.lib
    14 
    15 build := -f scripts/Makefile.build obj
    16 
    17 ifneq ($(strip $(obj-y)),)
    18 builtin-target := $(obj)/built-in.o
    19 endif
    20 
    21 # default target
    22 __build: $(builtin-target) $(subdir)
    23     @:
    24 
    25 # compiling .c files
    26 $(obj)/%.o: $(src)/%.c
    27     $(CC) -c $(CFLAGS) $< -o $@
    28 
    29 # subdir object
    30 $(subdir-obj-y): $(subdir) ;
    31 
    32 # linking objs
    33 $(builtin-target): $(obj-y)
    34     $(LD) -r -o $@ $^
    35 
    36 PHONY += $(subdir)
    37 
    38 # descending to subdirs
    39 $(subdir):
    40     make $(build)=$@
    41 
    42 .PHONY : $(PHONY) 

    obj变量为需要编译的源码目录,例如add,第10行将add/目录下的Makefile目录包含进来,add/Makefile内容如下:

    1 obj-y += add.o
    2 obj-y += mul/

    这里仅仅确定需编译的文件以及子目录,回到makefile.build,第13行,包含scripts/Makefile.lib文件,内容如下:

    1 subdir := $(patsubst %/,%,$(filter %/, $(obj-y)))
    2 obj-y := $(patsubst %/,%/built-in.o, $(obj-y))
    3 subdir-obj-y := $(filter %/built-in.o, $(obj-y))
    4 
    5 subdir := $(addprefix $(obj)/,$(subdir))
    6 obj-y := $(addprefix $(obj)/,$(obj-y))
    7 subdir-obj-y := $(addprefix $(obj)/, $(subdir-obj-y))

    obj-y表示要编译的目标文件,如果是目录,如mul/,则表示mul/built-in.o;subdir表示要继续编译的子目录;subdir-obj-y表示子目录下的built-in.o

    回到makefile.build,第18行,每个要编译的源码目录编译之后都将会产生一个built-in.o的文件,第27行,对.c文件进行编译,即由obj-y变量所确定的文件。第40行,对子目录执行同样的过程。第33行,对每个目录链接出一个built-in.o文件,这个built-in.o由当前目录下.o文件和子目录下的.built-in.o文件链接而成。

    在所有的源码目录都经过编译之后,回到顶层makefile执行最后的链接,得到target。

    再看看clean目标,第49行,首先在需要进行clean的目录下使用scripts/Makefile.clean执行clean,需要clean的目录为含有makefile的源码目录。Makefile.clean内容如下:

     1 src := $(obj)
     2 
     3 PHONY := __clean
     4 
     5 # default target
     6 __clean:
     7 
     8 clean := -f scripts/Makefile.clean obj
     9 
    10 # include the Makefile in the $(obj) dir
    11 build-dir := $(src)
    12 build-file := $(build-dir)/Makefile
    13 include $(build-file)
    14 
    15 # subdir to be cleaned
    16 subdir := $(patsubst %/,%,$(filter %/,$(obj-y)))
    17 subdir := $(addprefix $(obj)/,$(subdir))
    18 
    19 __clean-files :=
    20 __clean-files := $(addprefix $(obj),$(__clean-files))
    21 
    22 __clean-dirs :=
    23 __clean-dirs := $(addprefix $(obj),$(__clean-dirs))
    24 
    25 __clean: $(subdir)
    26 ifneq ($(strip $(__clean-files)),)
    27     rm -f $(__clean-files)
    28 endif
    29 
    30 ifneq ($(strip $(__clean-dirs)),)
    31     rm -rf $(__clean-dirs)
    32 endif
    33 
    34 PHONY += $(subdir)
    35 $(subdir):
    36     make $(clean)=$@
    37 
    38 .PHONY: $(PHONY)

    这里也是一个逐步往下clean的过程,要clean的文件由__clean-files变量指定。

    回到顶层makefile,简单的一个find操作,删除目录下所有.o文件和目标。

    关于include路径,u-boot讲所有头文件都集中放在了某几个目录下,于是源码中要包含其他头文件的时候是这样子做的xxx/xxx/xxx.h,我这里的main.c如下,其中对与mul和div的包含也是类似。

     1 #include <stdio.h>
     2 #include "add.h"
     3 #include "sub.h"
     4 #include "mul/mul.h"
     5 #include "div/div.h"
     6 
     7 void main(void)
     8 {
     9     int a = 1;
    10     int b = 2;
    11     printf("a = %d, b = %d
    ", a, b);
    12     printf("a + b = %d
    ", add(a, b));
    13     printf("a - b = %d
    ", sub(a, b));
    14     printf("a * b = %d
    ", mul(a, b));
    15     printf("a / b = %d
    ", div(a, b));
    16 }

    u-boot的makefile对我来说还是太复杂了,这里仅仅是它的冰山一角,可是我已经吃不消了。。。

  • 相关阅读:
    Ruby on Rails中的Rake教程(Rake如何把我灌醉!)
    十一、Spring Boot 集成Shiro和CAS
    Spring Boot 快速入门
    一位创业者的血泪史----献给85前创业者的反思
    罗振宇送给新员工的四句话
    Axure 入门
    XMind常用快捷方式汇总
    CAS 单点登陆
    mysql互换表中两列数据
    mysql默认安装目录说明
  • 原文地址:https://www.cnblogs.com/heyxiaotang/p/6438162.html
Copyright © 2011-2022 走看看