

详见: http://blog.csdn.net/liang13664759/article/details/1771246
https://www.cnblogs.com/wang_yb/p/3990952.html
http://www.360doc.com/content/14/0625/15/16285334_389630875.shtml
nmake编译错误:
1. 提示: makefile(8): fatal error U1083: target maco '' expands to nothing //makefile文件第8行, 致命错误U1083:目标宏展开为空
原因是$(EXE): $(OBJS) $(RES)这行里的变量EXE已经改成了NAME, 所以EXE展开就为空了
1. makefile文件在windows和linux下都可以用, windows下的执行命令是nmake
//安装VC6后在C:\Program Files\Microsoft Visual Studio\VC98\Bin\目录下有nmake.exe文件. 鱼C视频中用的也是这个
2. makefile文件在使用在鱼C的Win32汇编的第2和第5章都有使用示例
Makefile文件语法:
1. Makefile文件的基本格式
1)格式1:
要创建的目标文件 : 要创建这个目标依赖哪些文件
(命令前要用TAB空格)创建目标需要运行的命令
例:
$(NAME).exe: $(OBJS)
Link $(LINK_FLAG) $(OBJS) #注: 这里的Link前要用TAB键空出一个位置
2)格式2:
要生成的目标是伪目标, 即没有具体的目标, 不想上面格式1中执行后会生成一个具体的目标
例:
clean: #这个Clean就是伪目标,
del *.obj
del *.res
1. 注释: makefile文件中用#表注释
2. 变量的定义
语法: 变量名 = 变量的值
例: NAME = a.exe #变量名为NAME, 变量的值为a.exe这个字符串
3. 变量的调用
$(变量名) #调用时前加$, 后面的变量名要用括号()或花括号{}. 貌似也可以不括, 没测试过
例: $(NAME).exe: $(OBJS)
4. 变量定义符号=和:=
#用等即使把变量定义在调用变量那行的后面也有效, 用冒号等定义的变量必须在调用变量那行的前面才有效
例1: 用等定义变量可定义在调用行的后面
OBJS2 = $(OBJS1) programC.o
OBJS1 = programA.o programB.o
all:
@echo $(OBJS2)
输出: programA.o programB.o programC.o
例2: 用冒号等定义变量要把变量定义的调用行的前面才有效, 这里定义到后面无效
OBJS2 = $(OBJS1) programC.o
OBJS1 = programA.o programB.o
all:
@echo $(OBJS2)
输出: programC.o
5. 变量的替换, 例:
SRCS := programA.c programB.c programC.c
OBJS := $(SRCS:%.c=%.o) #将SRCS变量中所有.c替换为.o再赋给OBJS
all:
@echo "SRCS: " $(SRCS) #注: 这里的双引号中的内容不变, 原样输出
@echo "OBJS: " $(OBJS)
结果:
SRCS: programA.c programB.c programC.c
OBJS: programA.o programB.o programC.o
4. 通配符
* 表任意一个或多个字符
? 表任意一个字符
ex.[abcd] 表a,b,c,d中任意一个字符
[^abcd] 表除a, b, c, d外的字符
[0-9] 表0-9中任意一个字符
~ 用户的home目录
5. 命令前缀
1)默认没有前缀, 输出执行命令及命令执行的结果, 出错就停止执行
2)加@前缀, 只输入命令执行的结果, 出错的话停止执行
3)加-前缀, 命令执行有错的话, 忽略错误, 继续执行
6. 自动变量
$@ 目标的完整名称
$% 目标是函数库文件时,表示其中的目标文件名, 如目标名为mytarget.so(imago.o), 则$%为image.o, $@为mytarget.so
$< 第一个依赖目标, 如果依赖目标是多个, 逐个表示依赖目标
$? 比目标新的依赖目标的集合
$^ 所有依赖目标的集合, 会去除重复的依赖目标
$+ 所有依赖目标的集合, 不会去除重复的依赖目标
$* GNU make特有的, 不含扩展名的目标文件名
7. makefile还可嵌套, 命令包, 多种函数等.
一,makefile的两种使用示例:
1,是不带图标的:
NAME = a.exe #指定输出文件
OBJS = a.obj #需要的目标文件
LINK_FLAG = /subsystem:windows #连接选项
ML_FLAG = /c /coff #编译选项
$(NAME).exe: $(OBJS)
Link $(LINK_FLAG) $(OBJS)
.asm.obj:
ml $(ML_FLAG) $<
clean:
del *.obj
2.是带图标的:
EXE = a.exe #指定输出文件
OBJS = a.obj #需要的目标文件
RES = a.res #需要的资源文件
LINK_FLAG = /subsystem:windows #连接选项
ML_FLAG = /c /coff #编译选项
$(EXE): $(OBJS) $(RES)
Link $(LINK_FLAG) $(OBJS) $(RES)
.asm.obj: #这个是简写后的再简写
ml $(ML_FLAG) $< #符号$<表第一个依赖文件
.rc.res: #没找到说明, 个人理解前面.asm是要生成的目标,后面的.obj为需要的文件
rc $<
clean: #伪目标, 就是不会生成任何目标文件
del *.obj
del *.res
Linux下的示例
makefile文件1
main:main.o mytool1.o mytool2.o #表生成main这个目标需要后面的main.o/mytool1.o/mytool2.o三个文件
gcc -o main main.o mytool1.o mytool2.o #标明生成上行的目标main需的命令
main.o:main.c mytool1.h mytool2.h #生成main.o这个目标及需要的文件, 要包括源文件中用include引入的文件
gcc -c main.c #编译main.c的命令, 实际直接编译是不用指出.c源文件中引用了那些.h头文件的
mytool1.o:mytool1.c mytool1.h #生成mytool1.o需要的源文件及源文件中的引入的头文件
gcc -c mytool1.c #生成目标的指令
mytool2.o:mytool2.c mytool2.h #目标及目标的组成, 即要包括源及源引用的头文件
gcc -c mytool2.c #生成上行目标需要的指令
makefile文件2---精简上面的makefile文件
main:main.o mytool1.o mytool2.o #目标及依赖的对象不能精简
gcc -o $@ $^ #这里$@表目标文件(指上行中的main),
#这里 $^表目标所有依赖的文件(指main.o mytool1.o mytool2.o)
main.o:main.c mytool1.h mytool2.h #生成目标及其组成不能精简
gcc -c $< #这里$<表目标第一个依赖的文件, 即上行中的main.c
mytool1.o:mytool1.c mytool1.h #目标及依赖的对象
gcc -c $< #符号$<表上行的目标mytool.o的第一个依赖的对象mytool1.c
mytool2.o:mytool2.c mytool2.h #目标及依赖的对象
gcc -c $< #符号$<表目标mytool2.o的第一个依赖的对象mytool2.c
makefile文件3---再次精简
main:main.o mytool1.o mytool2.o #生成目标main及需要的文件
gcc -o $@ $^ #符号$@表目标, $^表目标依赖的第一个文件
.c.o: #表所有.o目标文件都是依赖.c文件, 个人信为它应该是同名目标文件依赖同名的.c文件
gcc -c $< #符号$<表目标依赖的第一个文件