• makefile 精粹


    • SHELL = /bin/bash # 设置执行shell, 默认为sh, sh又怎么能发挥 Linux 的全部威力呢?

    要想知道执行 make 命令的 shell, 使用代码

    SHELL := /bin/bash
    
    .PHONY: info
    info:
        @echo 当前shell: $$0
    
    d@MyServer: ~/git/make $ make info
    当前shell: /bin/bash
    
    • Rule 速记 --> $@: $< $? $^ | 仅指示的先决条件

    自动变量 含义
    $@ 目标的完整名称。
    $* 避免使用, 在模式规则下匹配不包含扩展名的目标文件名称。etc
    $< 第一个依赖文件的名称。
    $^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。
    $+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
    $? 更新的依赖文件,这些依赖文件的修改日期比目标的创建日期晚。
    $% 如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称
    为 ar.a(a.o, b.o),则 $@ 为 ar.a,而 $% 为 a.o b.o。
    AR 归档维护程序的名称,默认值为 ar。
    ARFLAGS 归档维护程序的选项。
    AS 汇编程序的名称,默认值为 as。
    ASFLAGS 汇编程序的选项。
    CC C 编译器的名称,默认值为 cc。
    CCFLAGS C 编译器的选项。
    CPP C 预编译器的名称,默认值为 $(CC) -E。
    CPPFLAGS C 预编译的选项。
    CXX C++ 编译器的名称,默认值为 g++。
    CXXFLAGS C++ 编译器的选项。

    • 仅指示的先决条件(order-only-prerequisites)

    在构建目标前, 可能需要先创建目录, 这些目录的时间戳经常会由于普通的文件操作而改变, 但是却令规则被触发, 这是无法容忍的
    因此使用仅指示的先决条件来指示这些依赖, 只要它们存在, 即使它们比target新, 也不会触发规则, 如果不存在就会先构建这个先决目标
    相应的自动变量为 $|

    all: src/main.c src/lib.c | bin
        gcc -o $|/target $^
    
    bin: 
        mkdir bin
    
    • $ 是 makefile 关键字, 要在 shell 中使用 '$' 字符, 一律使用 "$$" 转义

    • 使用同一个Shell

    默认情况下, 每个命令运行在单独的 shell 进程中, 执行完成后 shell 被销毁, 变量无法被导出

    .PHONY: info
    info:
            @echo $$$$
            @echo $$$$
    
    d@MyServer: ~/git/make $ make info
    16207
    16208
    

    这非常不方便共享数据, 比如无法传递环境变量, 使用同一个Shell不仅提高性能, 还能方便配方编程
    只需在非配方区域声明一行代码:

    .ONESHELL:
    

    例如

    .ONESHELL:
    SHELL := /bin/bash
    
    .PHONY: info
    info:
            @echo $$$$
            @echo $$$$
    
    d@MyServer: ~/git/make $ make info
    16225
    16225
    

    使用一个Shell进程还有一个好处, 要屏蔽所有的命令回显, 只需在第一行开头的命令上写@即可, 甚至直接将@作为第一行配方命令
    缺陷: 事实上是将换行隐式转义了, 这样一来所有的配方都变成了一条命令, 某一条配方失败了仍然会继续...

    真正的变量:在规则和配方中使用shell命令和通配符 -> $(shell) $(wildcard)函数

    • $(shell)函数使用find命令实现匹配所有特定后缀文件的先决条件
      假如我们要匹配src目录下的所有.c文件,它们编译后生成一个libtest.so动态链接库文件,则规则如下:
    libtest.so: $(shell find src -name '*.c')
        $(CC) -o $@ -shared -fPIC $^
    
    • $(wildcard)函数 * ** 通配符
      *匹配一个目录下的任意文件或目录(的部分字符)
      **递归匹配子目录,不过具有兼容性问题,建议不要使用
    libtest.so: $(wildcard )
        $(CC) -o $@ -shared -fPIC $^
    

    makefile代理

    在不使用$(shell)和$(wildcard)函数的情况下,可以使用makefile代理,根据目录的stat属性检测一个目录的结构是否发生变化,从而生成一个新的makefile代理文件,由它来完成最终的make任务

    make -f makefile_proxy
    

    参考项目 https://github.com/develon2015/make


    官方文档 [https://www.gnu.org/software/make/manual/make.html](https://www.gnu.org/software/make/manual/make.html)
  • 相关阅读:
    C#高级编程第11版
    C#特性
    设计模式 单一职责原则
    设计模式 依赖倒置原则
    C# 预处理指令
    毕业设计 python opencv实现车牌识别 矩形矫正
    毕业设计 python opencv实现车牌识别 颜色判断
    毕业设计 python opencv实现车牌识别 界面
    南昌大学航天杯第二届程序设计竞赛校赛网络同步赛 I
    南昌大学航天杯第二届程序设计竞赛校赛网络同步赛 G
  • 原文地址:https://www.cnblogs.com/develon/p/11622537.html
Copyright © 2020-2023  润新知