makefile

makefile的三要素:

  目标:要生成的目标文件

  依赖:目标文件由哪些文件生成

  命令:通过执行命令由依赖文件生成目标

规则:

  目标:依赖

  <Tab> 命令

 

执行make指令,默认是生成第一个目标

原理 :

  1. 当依赖文件不存在,如果有的依赖文件不存在,则向下搜索规则,看是否有生成该依赖文件的规则,

      如果有规则用来生成该依赖文件,则执行规则中的命令生成依赖文件;如果没有规则用来生成该依赖文件,则报错。

  2. 当依赖文件存在,如果所有的依赖文件都存在,则检查规则中依赖文件是否比目标新,如果任一依赖文件都比目标文件新,则目标必须更新。

 

变量:

  1. 普通变量:用户自定义的变量,要见名知义

    makefile中变量一般有三种赋值,“=”赋值表示变量的值是整个makefile中最后被指定的值。

    OBJ_A = A

    OBJ_B = $(OBJ_A) B

    OBJ_A = AA

    all:

      @echo $(OBJ_B)//输出AA B,不是A B,在执行make指令时,会把整个makefile展开,来决定变量的值

 

    “:=”表示直接赋值,赋予当前位置的值

    OBJ_A := A

    OBJ_B := $(OBJ_A) B

    OBJ_A := AA

    all:

      @echo $(OBJ_B)//输出A B,即根据当前位置进行赋值,“:=”才是真正意义上的直接赋值

 

    “?=”表示如果该变量没有被赋值,赋予等号后面的值

     VAR := B

     VAR ?= A

     all:

      @echo $(VAR)//输出B   

  2. 自动变量:

    

 

函数

Makefile中的%表示通配符,而*表示任意字符,举例,%.o表示匹配所有的.o文件,注意是用于匹配的。*.o是表示所有的.o文件

用途方面:前者一般用作目标,后者一般用作删除

 wildcard:

  SRC = $(wildcard ./*.c)//当前目录下的所有.c文件,并将其赋值给SRC变量

pstsubst:$(patsubst 原模式, 目标模式, 文件列表)

  OBJ = $(patsubst %.c, %.o, $(SRC))//将SRC中的所有.c文件替换为.o文件,并赋值给OBJ变量

 

链接库

  

 

Makefile中,如果一个规则没有命令或者依赖,并且它的目标不是一个存在的文件名。在执行此规则时,目标总会被认为是最新的。

就是说: 这个规则一旦被执行,make就认为它的目标已经被更新过。这样的目标在作为一个规则的依赖时,因为依赖总被认为被更新过,因此作为依赖所在的规则中定义的命令总会被执行。

all: FORCE
    @echo "****all: FORCE***"

FORCE:;

.PHONY: FORCE

 在make后,all依赖FORCE,FORCE没有命令或者依赖,并且它的目标不是一个存在的文件名,在执行此规则时,目标总会被认为是最新的。所以这个规则一旦被执行,make就认为它的目标已经被更新过。

 

多文件管理:

 fun目录下的Makefile

#获取当前目录下所有的.c文件
SRC=$(wildcard *.c)

#准备把当前目录下的.c转换为.o文件 ===>OBJ=fun.o
OBJ=$(patsubst %c,%o,$(SRC)) 

all:$(OBJ)

$(OBJ): %.o:%.c
    $(CC) $(INCLUDE_DIR) -c $^ -o $(OBJ_DIR)/$@

global目录下的Makefile

#获取当前目录下所有的.c文件
SRC=$(wildcard *.c)

#准备把当前目录下的.c转换为.o文件 ===>OBJ=fun.o
OBJ=$(patsubst %c,%o,$(SRC)) 

all:$(OBJ)

$(OBJ): %.o:%.c
    $(CC) $(INCLUDE_DIR) -c $^ -o $(OBJ_DIR)/$@

main目录下的Makefile

#获取当前目录下所有的.c文件
SRC=$(wildcard *.c)

#准备把当前目录下的.c转换为.o文件 ===>OBJ=fun.o
OBJ=$(patsubst %c,%o,$(SRC)) 

all:$(OBJ)

$(OBJ): %.o:%.c
    $(CC) $(INCLUDE_DIR) -c $^ -o $(OBJ_DIR)/$@

obj目录下的Makefile

$(BIN_DIR)/$(TARGET) : *.o
    $(CC) $(INCLUDE_DIR) $^ -o $@

主Makefile

CC := gcc
INCLUDE_DIR := -I ../include
OBJ_DIR := $(shell pwd)/obj
BIN_DIR := $(shell pwd)/bin

SUB_DIR := main fun global obj

TARGET  := my_exec

#设置SUB_DIR变量导出为全局,其他文件也可以使用
export CC INCLUDE_DIR OBJ_DIR BIN_DIR SUB_DIR TARGET

all:$(SUB_DIR)


$(SUB_DIR) : MK_BIN
    make -C $@            #-C选项后跟目录,表示到子目录下执行子目录的Makefile

MK_BIN:
    mkdir -p ./bin

clean:
    rm -rf  *.bin  ./obj/*.o

install:
    sudo cp $(BIN_DIR)/$(TARGET)  /usr/bin 

uninstall:
    sudo rm -rf /usr/bin/$(TARGET)

 

posted @ 2024-02-27 15:53  踏浪而来的人  阅读(25)  评论(0编辑  收藏  举报