makefile与gcc常用操作

  • 一、温故知新
  • 1、可执行程序的生成过程
  • 2、gcc的常用操作
  • 二、make操作
  • 三、编写Makefile文件时常用操作
  • 注意:在Makefile文件中 空格和缩进是完全不同的,不可以相互转换。
  • 1、框架格式
  • 2、举例
  • 3、优化
  • 1). 伪目标 .PHONY
  • 2). $ 和 @ 符号的作用
  • 3). 变量
  • 注意:
  • 变量种类
  • 4). 匹配模式
  • 4、Makefile中的条件判断 ifeq ifdef
  • 使用:
  • 注意事项:
  • 5、Makefile中的循环 foreach
  • 6、Makefile中的赋值 = 和 :=
  • 总结

一、温故知新

1、可执行程序的生成过程

[转帖]gcc与makefile常用操作(绝对常用,也绝对够用)_常用操作

2、gcc的常用操作

gcc/g++ 命令的基本格式为
gcc -[选项] [文件名]
例如:
gcc -c -I /home/inc/ test.c -o test.o
gcc -I /home/inc/ -O2 -g3 main.c test.o -o main

[转帖]gcc与makefile常用操作(绝对常用,也绝对够用)_赋值_02

二、make操作

make 的基本格式为:
make -[选项] [文件名]
例如:
make -v
make -n
make -C /home/erc/ -f Makefile02 -s

[转帖]gcc与makefile常用操作(绝对常用,也绝对够用)_文件名_03

三、编写Makefile文件时常用操作

下面会着重介绍编写Makefile文件时经常用到的操作,对于makef的执行规则等更细致全面的知识可以参考Makefile教程(绝对经典,所有问题看这一篇足够了)

注意:在Makefile文件中 空格和缩进是完全不同的,不可以相互转换。

1、框架格式

目标1:依赖
	命令
目标2:依赖
	命令
目标3:依赖
	命令

2、举例

假如说我现在有这么一个程序需要编译:

所需的 .h 头文件在 /home/inc/ 目录下
所需的 .c 源文件在 /home/src/ 目录下
#include "myadd.h" 
#include "mysub.h"
主函数在当前目录下的 main.c 里
int main()
{
return 0;
}

那么Makefile文件应该这么编写

main:/home/inc/myadd.o /home/inc/mysub.o ./main.o
	gcc -I /home/inc/ /home/inc/myadd.o /home/inc/mysub.o ./main.o -o main
/home/inc/myadd.o:/home/src/myadd.c

gcc -c -I /home/inc/ /home/src/myadd.c -o /home/src/myadd.o
/home/inc/mysub.o:/home/src/mysub.c

gcc -c -I /home/inc/ /home/src/mysub.c -o /home/src/mysub.o
./main.o:./main.c

gcc -c -I /home/inc/ ./main.c -o ./main.o
clean:
rm -rf /home/inc/mysub.o /home/inc/myadd.o ./main.o main

3、优化

以下是优化后的代码

NAME=main
SRC=\((</span>wildcard ./*.c<span >)</span></span> <span ><span >\)(wildcard /home/src/*.c)
OBJ=\((</span>patsubst %.c, %.o, <span >\)(SRC))
INC=-I"/home/inc/"
\((</span>NAME<span >)</span></span><span class="token builtin class-name">:</span><span ><span >\)(OBJ)

@ \((</span>CC<span >)</span></span> <span >-g</span> <span ><span >\)(INC) \((</span>OBJ<span >)</span></span> <span >-o</span> <span ><span >\)(NAME)
%.o:%.c

@ \((</span>CC<span >)</span></span> <span >-c</span> <span ><span >\)(INC) \(^ <span >-o</span> <span >\)@
.PHONY:clean
clean:

@ rm -f \((</span>OBJ<span >)</span></span> <span ><span >\)(NAME)

1). 伪目标 .PHONY

声明目标成伪目标之后,make会无条件执行该目标,
且不会判断目标是否存在或者是否需要更新。

例如:常常把 clean声明为伪目标

.PHONY:clean
clean:
<span >rm</span> <span >-rf</span> <span ><span >$(</span>OBJ<span >)</span></span> <span ><span >$(</span>NAME<span >)</span></span> 


clean:
<span >rm</span> <span >-rf</span> <span ><span >$(</span>OBJ<span >)</span></span> <span ><span >$(</span>NAME<span >)</span></span>

2). $ 和 @ 符号的作用

@ :运行命令时,隐藏命令
例如:@ rm -f $(OBJ) $(NAME) 会删除这些文件,但终端上不会有rm -r 输出

$ :使用变量,(定义变量的时候不需要加$)
例如 echo $(NAME)

3). 变量

注意:

不管是自定义变量或者是系统变量,使用方法都一样

使用方法即: $(变量名称)

变量的工作原理和 C语言中的 define类似,是会直接替换的,
所以一定要处理好空格。

变量种类

自定义变量:
定义: NAME=main
使用: echo $(NAME)

系统常量: 优点:与设备无关,全平台通用,使 makefile 可以跨平台。 常见系统常量:

[转帖]gcc与makefile常用操作(绝对常用,也绝对够用)_常用操作_04

Makefile 中常见系统变量: (加 星号 的是使用频率较高的)

[转帖]gcc与makefile常用操作(绝对常用,也绝对够用)_文件名_05

4). 匹配模式

目标前缀名和依赖前缀名相同时,可以使用匹配模式缩减代码长度
例如:
myadd.o : myadd.c 可以被替换为
%.o : %.c

$(wildcard /home/src/*.c)
获取某目录下的所有.c文件名称

$(patsubst %.c, %.o, $(SRC))
获取某些 .c 文件对应的 .o 文件

使用方法

获取当前目录下的所有 .c 文件的全名,获取 /home/src/目录下的所有 .c 文件的全名
并把文件名储存到 SRC 变量里
SRC=$(wildcard ./*.c) $(wildcard /home/src/*.c)
获取SRC变量里的 .c 文件对应的 .o 文件的全名

并把文件名储存到 OBJ 变量里
OBJ=\((</span>patsubst %.c, %.o, <span >\)(SRC))

此时再回头看优化代码,OvO,原来是这样。

4、Makefile中的条件判断 ifeq ifdef

使用:

ifeq 判断两个变量是否相等
括号里是要判断的两个变量

A=aa
TMP:=
ifeq ($(A),aa)
    TMP1:=aa
else    
    TMP1:=no-aa
endif

ifdef 判断某变量是否定义且赋值(如果没有赋值也是false)

B=
TMP2:=
ifdef (B)
    TMP2:=def-B
else
    TMP2:=ndef-B
endif

注意事项:

注意书写格式,ifeq 或者 ifdef 和括号之间有一个空格!!!

Makefile中不存在 elif 但可以嵌套调用 ifeq 或 ifdef 来实现elif的功能

5、Makefile中的循环 foreach

语法

命令 $(foreach v, 集合, 对v进行重命名或拼接等)

例子

TARGET=t1 t2 t3 t4
all:
mkdir \((</span>foreach v, <span >\)(TARGET), $v_dir)

说明:

遍历TARGET变量,然后在每个变量名后面拼接_dir组成新的名称,

然后以新的名称创建目录

演示结果:

[转帖]gcc与makefile常用操作(绝对常用,也绝对够用)_文件名_06

6、Makefile中的赋值 = 和 :=

= 是最终赋值,
:= 是临时赋值,
实际上 := 类似 C++中的变量引用,
对于 = 和 := 具体的区别,大家可以自己动手实操感受下。

总结

纸上谈来终觉浅,绝知此事要躬行!