用户名:  密码:   
您当前的位置:首页 > 程序设计 >  汇编与密码学 > 

makefile文件及nmake介绍

上次修改时间: 2017-12-22 11:29:55      来源:网络总结      作者:钢铁长陈
上一页      路径:DSD\Learn\assembly与反assembly\Win32汇编\      下一页

详见: 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 $<       #符号$<表目标依赖的第一个文件