zoukankan      html  css  js  c++  java
  • Makefile

    makefile工作原则

    原则一

    若想生成目标,检查规则中的依赖条件是否存在,如不存在,则去寻找是否有规则去生成依赖文件。如:

    makefile

    All:hello
    hello:hello.o
        gcc hello.o -o hello
    
    hello.o:hello.c
        gcc -c hello.c -o hello.o
    

    编译

    $ make
    gcc -c hello.c -o hello.o
    gcc hello.o -o hello
    
    原则二

    命名: makefile Makefile

    一个规则

    目标:依赖条件
    	[tab]命令
    
    一个例子

    单文件

    $ tree
    .
    ├── hello.c
    └── makefile
    

    编辑makefile:

    hello:hello.c
    	gcc hello.c -o hello
    

    使用make编译

    $ make
    gcc hello.c -o hello
    $ ls
    hello  hello.c  makefile
    

    多文件

    • 文件结构
    $ tree
    .
    ├── add.c
    ├── hello.c
    ├── makefile
    └── sub.c
    
    • makefile

    为了提高编译效率,当修改一个源文件时,必须要重新编译其他没变的文件

    # 1. 方式一
    hello:hello.c add.c sub.c
    	gcc hello.c add.c sub.c -o hello
    # 2. 方式二,当修改一个源文件,只会编译这个文件,并链接,省略了其他文件的编译和汇编
    hello:hello.o add.o sub.o
    	gcc hello.o add.o sub.o -o hello
    hello.o:hello.c
    	gcc -c hello.c -o hello.o
    add.o:add.c
    	gcc -c add.c -o add.o
    sub.o:sub.c
    	gcc -c sub.c -o sub.o
    

    ​ 1) 第一次编译:

    $ make
    gcc -c hello.c -o hello.o
    gcc -c add.c -o add.o
    gcc -c sub.c -o sub.o
    gcc hello.o add.o sub.o -o hello
    

    ​ 2) 当修改了add.c后,再次编译

    $ make
    gcc -c add.c -o add.o
    gcc hello.o add.o sub.o -o hello
    

    2个函数

    src = $(wildcard *.c)
    

    找到当前目录下所有后缀为.c的文件,赋值给src,即src会被替换为hello.c, add.c..

    obj = $(patsust %.c,%.o,$(src))
    

    把src变量中所有后缀名为.c的文件替换成.o,obj为hello.o add.o ..

    ​ 改写为:

    # 仅仅代表字符串替换
    src = $(wildcard *.c)  # add.c sub.c hello.c
    obj = $(patsubst %.c,%.o,$(src))  # add.o sub.o hello.o
    
    All:hello
    hello:$(obj)
    	gcc $(obj) -o hello
    hello.o:hello.c
    	gcc -c hello.c -o hello.o
    add.o:add.c
    	gcc -c add.c -o add.o
    sub.o:sub.c
    	gcc -c sub.c -o sub.o
    clean:
    	-rm -rf $(obj) hello # -表示出错也执行
    
    • clean
    make clean -n  # 预览要执行的操作
    make clean  # 执行clean操作
    

    3个自动变量

    $@

    表示规则中的目标,只能出现在一组规则中的命令中

    hello:$(obj)
    	gcc $(obj) -o $@
    hello.o:hello.c
    	gcc -c hello.c -o $@  # $@ == hello.o
    

    $<

    表示规则中的第一个条件

    hello.o:hello.c
    	gcc -c $< -o $@  # $@ == hello.o
    

    如果该变量用在模式规则中,可将依赖条件中的列表依次取出,套用模式规则

    $^

    表示规则中的所有条件,组成一个列表,以空格隔开,如果这个列表中有重复的项则消除重复项

    • 升级为:
    src = $(wildcard *.c)            # hello.c add.c sub.c
    obj = $(patsubst %.c,%.o,$(src)) # hello.c add.o sub.o
    
    All:hello
    
    hello:$(obj)
        gcc $^ -o $@
    
    hello.o:hello.c
        gcc -c $<  -o $@
    add.o:add.c
        gcc -c $< -o $@
    sub.o:sub.c
        gcc -c $< -o $@
    
    clean:
        -rm -rf $(obj) hello
    

    目前已经很大的增强了项目的拓展行

    当新增文件时,只需要添加如下代码:

    mul.o:mul.c
        gcc -c $< -o $@
    

    模式规则

    -升级为:

    src = $(wildcard *.c)            # hello.c add.c sub.c
    obj = $(patsubst %.c,%.o,$(src)) # hello.c add.o sub.o
    
    All:hello
    
    hello:$(obj)
        gcc $^ -o $@
    
    %.o:%.c
        gcc -c $< -o $@
    
    clean:
        -rm -rf $(obj) hello
    

    这样,新增文件时,就不需要更改Makefile了

    至此,已经可以实现单层目录的编译了。

    多层目录(嵌套执行make)

    目录结构

    .
    ├── add.c
    ├── dir1
    │   ├── makefile
    │   └── mul.c
    ├── hello.c
    ├── makefile
    └── sub.c
    

    根目录下的时总控Makefile:

    src = $(wildcard *.c)            # hello.c add.c sub.c
    obj = $(patsubst %.c,%.o,$(src)) # hello.c add.o sub.o
    
    All:hello
    
    hello:$(obj)
        gcc $^ -o $@
    
    %.o:%.c
        gcc -c $< -o $@
    
    clean:
        -rm -rf $(obj) hello
    
    subsystem:
        cd dir1 && $(MAKE)
    

    通过为目标 subsystem完成子目录的编译

    • 目录结构
    ├── hello
    ├── inc
    │   └── mymath.h
    ├── makefile
    ├── obj
    │   ├── dir1
    └── src
        ├── add.c
        ├── dir1
        │   ├── makefile
        │   └── mul.c
        ├── hello.c
        └── sub.c
    

    src目录放源码(.c),obj目录放汇编文件(.o)

    src = $(wildcard ./src/*.c)            # hello.c add.c sub.c
    src += $(wildcard ./src/dir1/*.c)
    # src = ./src/hello.c  ..
    obj = $(patsubst ./src/%.c, ./obj/%.o,$(src)) # hello.c add.o sub.o
    # obj = ./obj/hello.o ..
    
    All:hello
    
    
    hello:$(obj)
        gcc $^ -o $@
    
    # obj = ./obj/hello.o ...
    $(obj):./obj/%.o:./src/%.c
        gcc -c $< -o $@
    
    clean:
        -rm -rf $(obj)
        -rm -rf hello
    
    exec:
        @echo $(obj)
        @echo $(src)
    

    注意模式匹配中的 %只能匹配文件名,不匹配路径

    但是在函数中的 %可以匹配任意字符,包括路径

    结果:

    .
    ├── hello
    ├── inc
    │   └── mymath.h
    ├── makefile
    ├── obj
    │   ├── add.o
    │   ├── dir1
    │   │   └── mul.o
    │   ├── hello.o
    │   └── sub.o
    └── src
        ├── add.c
        ├── dir1
        │   ├── makefile
        │   └── mul.c
        ├── hello.c
        └── sub.c
    
  • 相关阅读:
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.0
    《Three.js 入门指南》2.4.1- 照相机
    《Three.js 入门指南》2.3.1- 照相机
    《Three.js 入门指南》2- 照相机
    《Three.js 入门指南》1.3
  • 原文地址:https://www.cnblogs.com/zhuxiang1633/p/12287602.html
Copyright © 2011-2022 走看看