|
| 1 | +# 3.变量 |
| 2 | +## 3.1 变量的定义及取值 |
| 3 | +Makefile 也支持变量定义,变量的定义也让的我们的 Makefile 更加简化,可复用。 |
| 4 | +变量的定义:一般采用大写字母,赋值方式像 C 语言的赋值方式一样,如下: |
| 5 | + |
| 6 | +```bash |
| 7 | +DIR = ./100ask/ |
| 8 | +``` |
| 9 | + |
| 10 | +变量取值:使用括号将变量括起来再加美元符,如下: |
| 11 | + |
| 12 | +```bash |
| 13 | +FOO = $(DIR) |
| 14 | +``` |
| 15 | + |
| 16 | +变量可让 Makefile 简化可复用,上面个的 Makefile 文件,内容如下: |
| 17 | + |
| 18 | +```makefile |
| 19 | +output: main.o add.o sub.o |
| 20 | + gcc -o output main.o add.o sub.o |
| 21 | +main.o: main.c |
| 22 | + gcc -c main.c |
| 23 | +add.o: add.c |
| 24 | + gcc -c add.c |
| 25 | +sub.o: sub.c |
| 26 | + gcc -c sub.c |
| 27 | +clean: |
| 28 | + rm *.o output |
| 29 | +``` |
| 30 | + |
| 31 | +我们可以将其优化,如下: |
| 32 | + |
| 33 | +```makefile |
| 34 | +#Makefile 变量定义 |
| 35 | +OBJ = main.o add.o sub.o |
| 36 | +output: $(OBJ) |
| 37 | + gcc -o output $(OBJ) |
| 38 | +main.o: main.c |
| 39 | + gcc -c main.c |
| 40 | +add.o: add.c |
| 41 | + gcc -c add.c |
| 42 | +sub.o: sub.c |
| 43 | + gcc -c sub.c |
| 44 | +clean: |
| 45 | + rm $(OBJ) output |
| 46 | +``` |
| 47 | + |
| 48 | +我们分析一下上面简化过的 Makefile,第一行是注释,Makefile 的注释采用‘#’,而且不支持像 C 语言中的多行注释。第二行我们定义了变量 OBJ,并赋值字符串”main.o,add.o,sub.o“。其中第三,四,十三行,使用这个变量。这样用到用一个字符串的地方直接调用这个变量,无需重复写一大段字符串。 |
| 49 | +Makefile 除了使用‘=’进行赋值,还有其他赋值方式,比如‘:=’和‘?=’,接下来我们来对比一下这几种的区别: |
| 50 | + |
| 51 | +赋值符‘=’ |
| 52 | +我们使用一个例子来说明赋值符‘=’的用法。Makefile 内容如下: |
| 53 | + |
| 54 | +```makefile |
| 55 | +PARA = 100 |
| 56 | +CURPARA = $(PARA) |
| 57 | +PARA = ask |
| 58 | + |
| 59 | +print: |
| 60 | + @echo $(CURPARA) |
| 61 | +``` |
| 62 | + |
| 63 | +分析代码:第一行定义变量 PARA,并赋值为“100”,第二行定义变量 CURPARA,并赋值引用变量 PARA,此时 CURPARA 的值和 PARA 的值是一样的,第三行,将变量 PARA 的变量修改为“ask”。第六行输出 CURPARA 的值,echo 前面增加@符号,代表只显示命令的结果,不显示命令本身。 |
| 64 | +通过命令“make print”执行 Makefile,如下: |
| 65 | + |
| 66 | +```bash |
| 67 | +$ make print |
| 68 | +ask |
| 69 | +``` |
| 70 | + |
| 71 | +从结果上看,变量 CURPARA 的值并不是“100”,而是 PARA 的最后一次赋值。使用赋值符“=”设置的变量,它的值在运行时才能确定,这称为“延时变量”。 |
| 72 | +其实可以理解为在 C 语言中,定义一个指针变量指向一个变量的地址。如下: |
| 73 | + |
| 74 | +```c |
| 75 | +01 int a = 10; |
| 76 | +02 int *b = &a; |
| 77 | +03 a=20; |
| 78 | +``` |
| 79 | + |
| 80 | +代码分析:我们见上面的 Makefile 的第二行的“=”替换成“:=”,重新编译,如下: |
| 81 | + |
| 82 | +```bash |
| 83 | +$ make print |
| 84 | +100 |
| 85 | +``` |
| 86 | + |
| 87 | +从结果上看,变量 CURPARA 的值为“100”。使用“:=”设置的变量被称为“即时变量”,在赋值时就确定了它的值。 |
| 88 | + |
| 89 | +赋值符‘?=’ |
| 90 | + |
| 91 | +我们用两个 Makefile 来说明赋值符“?=”的用法。如下: |
| 92 | + |
| 93 | +```makefile |
| 94 | +第一个 Makefile: |
| 95 | +PARA = 100 |
| 96 | +PARA ?= ask |
| 97 | +print: |
| 98 | + @echo $(PARA) |
| 99 | +``` |
| 100 | + |
| 101 | +编译结果: |
| 102 | + |
| 103 | +```bash |
| 104 | +$ make print |
| 105 | +100 |
| 106 | +``` |
| 107 | + |
| 108 | +```makefile |
| 109 | +第二个 Makefile: |
| 110 | +PARA ?= ask |
| 111 | +print: |
| 112 | + @echo $(PARA) |
| 113 | +``` |
| 114 | + |
| 115 | +编译结果: |
| 116 | + |
| 117 | +```bash |
| 118 | +$ make print |
| 119 | +ask |
| 120 | +``` |
| 121 | + |
| 122 | +上面的例子说明,使用“?=”给变量设置值时,如果这个变量之前没有被设置过,那么“?=”才会起效果;如果曾经设置过这个变量,那么“?=”不会起效果。赋值符‘+=’ |
| 123 | +Makefile 中的变量是字符串,有时候我们需要给前面已经定义好的变量添加一些字符串进去,此时就要使用到符号“+=”,比如如下: |
| 124 | + |
| 125 | +```makefile |
| 126 | +OBJ = main.o add.o |
| 127 | +OBJ += sub.o |
| 128 | +``` |
| 129 | + |
| 130 | +这样的结果是 OBJ 的值为:”main.o,add.o,sub.o“。说明“+=”用作与变量的追加。 |
| 131 | + |
| 132 | +## 3.2 系统自带变量 |
| 133 | + |
| 134 | +系统自定义了一些变量,通常都是大写,比如 CC,PWD,CLFAG 等等,有些有默认值,有些没有,比如以下几种,如下: |
| 135 | +* CPPFLAGS:预处理器需要的选项,如:-l |
| 136 | +* CFLAGS:编译的时候使用的参数,-Wall -g -c |
| 137 | +* LDFLAGS:链接库使用的选项,-L -l |
| 138 | +其中:默认值可以被修改,比如 CC 默认值是 cc,但可以修改为 gcc:CC=gcc使用的例子,如下: |
| 139 | + |
| 140 | +``` |
| 141 | +OBJ = main.o add.o sub.o |
| 142 | +output: $(OBJ) |
| 143 | + gcc -o output $(OBJ) |
| 144 | +main.o: main.c |
| 145 | + gcc -c main.c |
| 146 | +add.o: add.c |
| 147 | + gcc -c add.c |
| 148 | +sub.o: sub.c |
| 149 | + gcc -c sub.c |
| 150 | +
|
| 151 | +clean: |
| 152 | + rm $(OBJ) output |
| 153 | +``` |
| 154 | + |
| 155 | +使用系统自带变量,如下: |
| 156 | + |
| 157 | +``` |
| 158 | +CC = gcc |
| 159 | +OBJ = main.o add.o sub.o |
| 160 | +output: $(OBJ) |
| 161 | + $(CC) -o output $(OBJ) |
| 162 | +main.o: main.c |
| 163 | + $(CC) -c main.c |
| 164 | +add.o: add.c |
| 165 | + $(CC) -c add.c |
| 166 | +sub.o: sub.c |
| 167 | + $(CC) -c sub.c |
| 168 | +
|
| 169 | +clean: |
| 170 | + rm $(OBJ) output |
| 171 | +``` |
| 172 | + |
| 173 | +在上面例子中,系统变量 CC 不改变默认值,也同样可以编译,修改的目的是为了明确使用 gcc 编译。 |
| 174 | + |
| 175 | +## 3.3 自动变量 |
| 176 | +Makefile 的语法提供一些自动变量,这些变量可以让我们更加快速地完成Makefile 的编写,其中自动变量只能在规则中的命令使用,常用的自动变量如 |
| 177 | +下: |
| 178 | +* $@:规则中的目标 |
| 179 | +* $<:规则中的第一个依赖文件 |
| 180 | +* $^:规则中的所有依赖文件 |
| 181 | +我们上面的例子继续完善,修改为采用自动变量的格式,如下: |
| 182 | + |
| 183 | +```makefile |
| 184 | +CC = gcc |
| 185 | +OBJ = main.o add.o sub.o |
| 186 | +output: $(OBJ) |
| 187 | + $(CC) -o $@ $^ |
| 188 | +main.o: main.c |
| 189 | + $(CC) -c $< |
| 190 | +add.o: add.c |
| 191 | + $(CC) -c $< |
| 192 | +sub.o: sub.c |
| 193 | + $(CC) -c $< |
| 194 | + |
| 195 | +clean: |
| 196 | + rm $(OBJ) output |
| 197 | +``` |
| 198 | + |
| 199 | +其中:第 4 行$^表示变量 OBJ 的值,即 main.o add.o sub.o,第四,第六,第八行的$<分别表示 main.c add.c sub.c。$@表示 output。 |
0 commit comments