Makefile 整理

1 简介

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
Makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

2 主要解决两个问题

2.1 大量代码的关系维护

大项目中源代码比较多,手工维护、编译时间长而且编译命令复杂,难以记忆及维护。把代码维护命令及编译命令写在makefile文件中,然后再用make工具解析此文件自动执行相应命令,可实现代码的合理编译。

2.2 减少重复编译时间

在改动其中一个文件的时候,能判断哪些文件被修改过,可以只对该文件进行重新编译,然后重新链接所有的目标文件,节省编译时间。

3 make命令格式

make是一个命令工具,它解释Makefile 中的指令(应该说是规则),make命令格式:make [ -f file ][ options ][ targets ]
[ -f file ]:

  • make默认在工作目录中寻找名为GNUmakefile、makefile、Makefile的文件作为makefile输入文件
  • -f 可以指定以上名字以外的文件作为makefile输入文件

[ options ]:

  • -v: 显示make工具的版本信息
  • -w: 在处理makefile之前和之后显示工作路径
  • -C dir:读取makefile之前改变工作路径至dir目录
  • -n:只打印要执行的命令但不执行
  • -s:执行但不显示执行的命令

[ targets ]:

  • 若使用make命令时没有指定目标,则make工具默认会实现makefile文件内的第一个目标,然后退出
  • 指定了make工具要实现的目标,目标可以是一个或多个(多个目标间用空格隔开)

4 Makefile工作原理

1、若想生成目标, 检查规则中的依赖条件是否存在,如不存在,则寻找是否有规则用来 生成该依赖文件
2、检查规则中的目标是否需要更新,必须先检查它的所有依赖,依赖中有任一个被更新,则目标必须更新

总结:
Ø 分析各个目标和依赖之间的关系

Ø 根据依赖关系自底向上执行命令

Ø 根据修改时间比目标新,确定更新

Ø 如果目标不依赖任何条件,则执行对应命令,以示更新

5 Makefile语法规则

目标:依赖文件列表
Tab命令列表
Makefile基本规则三要素:
1)目标:

  • 通常是要产生的文件名称,目标可以是可执行文件或其它obj文件,也可是一个动作的名称

2)依赖文件:

  • 用来输入从而产生目标的文件
  • 一个目标通常有几个依赖文件(可以没有)

3)命令:

  • make执行的动作,一个规则可以含几个命令(可以没有)
  • 有多个命令时,每个命令占一行
test:test1 test2
	echo "test"
test1:
	echo "test1"
test2:
	echo "test2"

在这里插入图片描述

6 Makefile中的变量

在Makefile中使用变量有点类似于C语言中的宏定义,使用该变量相当于内容替换,使用变量可以使Makefile易于维护,修改内容变得简单变量定义及使用。

6.1 自定义变量

1、定义变量方法
变量名=变量值
变量名:=变量值

2、引用变量:
$(变量名)或${变量名}

3、makefile的变量名:

  • makefile变量名可以以数字开头
  • 变量是大小写敏感的
  • 变量一般都在makefile的头部定义
  • 变量几乎可在makefile的任何地方使用
OBJS=add.o sub.o mul.o div.o test.o
TARGET=test

$(TARGET):$(OBJS)
    gcc $(OBJS) -o $(TARGET) 

add.o:add.c
    gcc -c add.c -o add.o

sub.o:sub.c
    gcc -c sub.c -o sub.o

mul.o:mul.c
    gcc -c mul.c -o mul.o

div.o:div.c
    gcc -c div.c -o div.o

test.o:test.c
    gcc -c test.c -o test.o

clean:
    rm -rf $(OBJS) $(TARGET)

6.2 自动变量

  • $@: 表示规则中的目标
  • $<: 表示规则中的第一个条件
  • $^: 表示规则中的所有条件, 组成一个列表, 以空格隔开,如果这个列表中有重复的项则消除重复项。

注意:自动变量只能在规则的命令中中使用

OBJS=add.o sub.o mul.o div.o test.o add.o
TARGET=test
CC=gcc

#$@: 表示目标
#$<: 表示第一个依赖
#$^: 表示所有的依赖

$(TARGET):$(OBJS)
    #$(CC) $(OBJS) -o $(TARGET) 
    $(CC) $^ -o $@
    echo $@
    echo $<
    echo $^

add.o:add.c
    $(CC) -c $< -o $@ 

sub.o:sub.c
    $(CC) -c $< -o $@ 

mul.o:mul.c
    $(CC) -c $< -o $@ 

div.o:div.c
    $(CC) -c $< -o $@ 

test.o:test.c
    $(CC) -c $< -o $@

clean:
    rm -rf $(OBJS) $(TARGET)

6.3 Makefile中已定义好的默认变量

除了使用用户自定义变量,makefile中也提供了一些变量(变量名大写)供用户直接使用,我们可以直接对其进行赋值。
CC = gcc #arm-linux-gcc
CPPFLAGS : C预处理的选项 如:-I
CFLAGS: C编译器的选项 -Wall -g -c
LDFLAGS : 链接器选项 -L -l
MAKE: 在Makefile中使用$(MAKE),可执行子目录下的Makefile,或者生成当前Makefile中的目标依赖

# $(MAKE) 执行shared crypto_utility目标
test:
        $(MAKE) shared
        $(MAKE) crypto_utility
shared: 
        @echo "hello shared"

crypto_utility:
        @echo "hello crypto_utility"

#  $(MAKE) 执行src目录下的Makefile, src目录下的clean目标
all: qimgsearchd

qimgsearchd:
        $(MAKE) -C src
clean:
        $(MAKE) clean -C src

7 Makefile中的函数

  1. wildcard – 查找指定目录下的指定类型的文件
    src = $(wildcard *.c) //找到当前目录下所有后缀为.c的文件,赋值给src
  2. patsubst – 匹配替换
    obj = $(patsubst %.c,%.o, $(src)) //把src变量里所有后缀为.c的文件替换成.o
SRC=$(wildcard *.c)
OBJS=$(patsubst %.c, %.o, $(SRC))
TARGET=test
$(TARGET):$(OBJS)
	gcc $(OBJS) -o $(TARGET) 

%.o:%.c
	gcc -c $< -o $@
  1. foreach
    foreach 函数和别的函数非常的不一样。因为这个函数是用来做循环用的,Makefile中的foreach函数几乎是仿照于Unix标准Shell (/bin/sh)中的for语句,或是C-Shell(/bin/csh)中的foreach语句而构建的。它的语法是:$(foreach <var>,<list>,<text>)
    这个函数的意思是,把参数<list>;中的单词逐一取出放到参数<var>;所指定的变量中,然后再执行< text>;所包含的表达式。每一次<text>;会返回一个字符串,循环过程中,<text>;的所返回的每个字符串会 以空格分隔,最后当整个循环结束时,<text>;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。
# 将当前路径,当前目录下的thirdparty目录,autho目录的所有cc文件复制给src变量
DIR := . thirdparty auth
SRC := $(foreach d, $(DIR), $(wildcard $(d)/*.cc))

8 Makefile中的伪目标

伪目标声明: .PHONY:clean,声明目标为伪目标之后,makefile将不会该判断目标是否存在或者该目标是否需要更新。
命令中的特殊符号:

  • “-”此条命令出错,make也会继续执行后续的命令。如:“-rm main.o”
  • “@”不显示命令本身,只显示结果。如:“@echo clean done”
SRC=$(wildcard *.c)
OBJS=$(patsubst %.c, %.o, $(SRC))
TARGET=test
$(TARGET):$(OBJS)
	gcc $(OBJS) -o $(TARGET) 

%.o:%.c
	gcc -c $< -o $@
.PHONY:clean
clean:
	rm -rf $(OBJS) $(TARGET
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值