Makefile入门

1. Makefile引入

简单编译C文件时一般用的gcc:gcc -o test a.c b.c
但是当项目变得十分庞大时,逐个文件编译,效率极低。这时候必须引入Makefile作为编译管理。

当项目设计诸多模块,层级目录复杂时,常规做法是在每个子目录中放一个子Makefile,在顶层目录放一个总控Makefile。执行这个Makefile,即可完成整个项目的编译。

2. 规则

makefile的核心是规则,很简单

target1 : prerequisite1 prerequisite2
	command prerequisite1 -o target1

其中:
target1: 要生成的目标
prerequisite :生成目标所需的条件,即依赖
command :生成目标所需的命令

更多隐含规则:make的隐含规则数据库可以用make -p 命令打印

3. 标记

  • #                       注释

  • %.o                    通配符

  • $@                      目标文件

  • $<                 第1个依赖文件

  • $^                     所有依赖文件

    main : main.o stack.o maze.o
    	gcc -o $@ $^
    	
    main.o: main.h stack.h maze.h
    stack.o: stack.h main.h
    maze.o: maze.h main.h
    
    main.o: main.c
    	gcc -c $<
    	
    stack.o: stack.c
    	gcc -c stack.c
    
    maze.o: maze.c
    	gcc -c maze.c
    
  • .PHONY              伪目标

    .PHONY: clean
    clean:
    	# -代表即使rm执行失败,也会继续删除后续的*.o, 而不会就此中断
    	# -一般用在rm/mkdir。因为则2个命令可能会失败
    	-rm *.o
    
    	# 打印出信息
    	@echo clean all objfiles
    

4. 变量

makefile中定义变量:v = xxx。当需要引用变量v时:$(v)。这里讨论如下运算符:=, :=, ?=, +=

  • :=    即时变量,在定义时即确定

    # 	desc: 代表遇到变量定义立即展开
    x := foo
    y := $(x) bar
    
    # 当读到$(b)时b还未定义,则展开为空值(什么也没有)。即:$(a) -> 空格+bar
    a := $(b) bar
    b := hello
    tar2:
    	@echo "-$(a)-"
    
  • = 延时变量,值使用到时才确定

    # 	desc: 当makefile读到这行时,不会立即展开$(bar)
    # 	      而是当读到@echo $(foo)是再展开$(foo),继而展开$(bar)
    foo = $(bar)
    bar = Huh?
    tar1:
    	@echo $(foo)
    
  • ?= 如果变量前面未定义过,则?=相当于=。否则什么也不做

    # 	desc: 如果foo前面未定义过,则?=相当于=。否则什么也不做
    foo ?= I am a fool
    tar3:
    	@echo "-$(foo)-"
    
  • += 附加, 它是即时变量还是延时变量取决于前面的定义

    # 	desc:给变量追加值。
    #         如果obj是=定义的,则+=仍保持=的特性; 
    # 	      如果obj是:=定义的,则+=保持:=的特性
    obj := main.o
    obj += $(fo)
    fo = fo.o bar.o
    tar4:
    	@echo "-$(obj)-"
    

4. 函数

  • $(foreach var,list,text) 把参数中的单词逐一取出放到参数所指定的变量中,然后再执行< text>所包含的表达式
  • $(filter pattern...,text) 在text中取出符合patten格式的值
  • $(filter-out pattern...,text) 在text中取出不符合patten格式的值
  • $(wildcard pattern) pattern定义了文件名的格式,wildcard取出其中存在的文件
  • $(patsubst pattern,replacement,$(var)) 从列表中取出每一个值,如果符合pattern,则替换为replacement
posted on 2022-08-14 09:58  rogerg6  阅读(62)  评论(0)    收藏  举报