源代码:
//main.c
#include <stdio.h>
#include "complicated.h"
int main(){
printf("%s\n",HELLO_STRING);
printf("%s\n",PROJECT_NAME);
complicated();
return 0;
}
//complicated.h
#ifndef __COMPLICATED_H__
#define __COMPLICATED_H__
#define HELLO_STRING "hello !"
#define PROJECT_NAME "complicated"
extern void complicated(void);
#endif
//complicated.c
#include <stdio.h>
#include "complicated.h"
void complicated(void){
printf("This is a %s project!\n",PROJECT_NAME);
}
Makefile
# 描述:complicated 项目 makefile文件
# 版本:v1.5
# 修改记录:
# 1. 为complicated项目makefile添加注释
# 2. 使用变量改进我们complicated项目的makefile
# 3. 使用静态模式规则,简化makefile
# 4. 使用伪目标,加上clean规则
# 5. 引进wildcard函数,自动扫描当前目录下的源文件
# 6. 加入自动规则依赖
# 定义可执行文件变量
executbale := complicated
# wildcard函数扫描源文件,定义列表变量
# wildcard:列出符合*.c格式的文件名
sources := $(wildcard *.c)
# 使用变量的引用替换,定义object文件列表
objects := $(sources:.c=.o)
# 使用变量的引用替换,定义依赖描述文件列表
deps := $(sources:.c=.d)
# 定义编译命令变量
CC := gcc
RM := rm -rf
# 终极目标规则,生成complicated可执行文件
$(executbale): $(objects)
# 使用自动化变量改造我们的编译命令
$(CC) -o $@ $^
# 子规则, main.o和complicated.o的生成规则,使用静态模式规则
$(objects):%.o:%.c
$(CC) -o $@ -c $<
# clean规则
#.PHONY <伪目标>
.PHONY: clean
clean:
$(RM) $(executbale) $(objects) $(deps)
# 自动规则依赖
sinclude $(deps)
$(deps):%.d:%.c
$(CC) -MM $< > $@
解析规则
终极目标:依赖A 依赖B 依赖C
终极目标命令
依赖A:子依赖A1 子依赖A2
依赖A命令
依赖B:子依赖B1 子依赖B2
依赖B命令
依赖C:子依赖C1 子依赖C2
依赖C命令
对整颗依赖树以从底到上,从左到右的顺序,解析执行每一条规则:
变量的分类与赋值
foo1 = $(bar) #递归展开式变量:变量被引用时求值 \
= 和:=区别:求值时机
foo2 := $(bar) #直接展开式变量:变量被定义时求值
bar = $(ugh)
ugh = Huh?
all:
echo "foo1 is $(foo1),foo2 is $(foo2)"
特殊的变量
all:first second third
echo "\$$@ = $@" # $@ 代表规则中的目标文件名
echo "$$< = $<" # $< 代表规则的第一个依赖的文件名
echo "$$^ = $^" # $^ 代表规则中所有依赖文件的列表
first second third: