首页
社区
课程
招聘
[原创]想抛开IDE,用神秘的MAKEFILE享受纯粹写代码的乐趣吗?——手把手与你搭建一个MASM开发环境学写Makefile
发表于: 2007-12-21 23:24 30914

[原创]想抛开IDE,用神秘的MAKEFILE享受纯粹写代码的乐趣吗?——手把手与你搭建一个MASM开发环境学写Makefile

2007-12-21 23:24
30914

//
// 前言
//
如果你从网上下载过一些开源的代码, 好奇的你一定曾被里面一个个名叫 Makefile 的文件
勾起过浓厚的兴趣。要揭开其神秘的面纱,并不是仅仅用记事本打开它,看看里面陌生的代
码就能完事的。因为我们的 IDE 在这之间竖起了一道墙,同时,抛开了现有 IDE 的我们必
须找到一组替代的工具,而这些工具我们往往是非常陌生的,你可能多次兴冲冲的尝试后仍
不能迈出那关键的第一步。今天,我们就一起来跨出这一步,走进一片新的天地。

注:闲话少说,我会直入主题,不再做任何铺垫,如何你看到某处比较疑惑,很正常不用管
它,一步步跟着动手做了再说,我也是摸索过之后才能有个感性认识的。

//
// 概述
//
我们要迈出这一步,需要做两件事:
一、搭建一个开发环境(我们以 MASM 为例子,C++ 等类同),以脱离固有 IDE 的束缚
二、了解 MAKEFILE 的最基本写法,用我们搭建的开发环境写一个 Hello Makefile 的汇编程序

//
// 一、搭建 MASM 开发环境
//
1、组件
搭建一个开发环境需要的组件有:操作系统,使用该操作系统 API 的头文件与库文件,源
代码编译器,资源文件编译器,链接器,源代码编辑器,最后是 Makefile 解释器

    a> 对于操作系统,我们不找了,搭建 MASM 开发环境就用 Windows 吧
   
    b> 头文件与库文件我们使用 MASM32 的 Include 与 Lib 目录里现有的
   
    c> 源代码编译器,资源编译器与链接器我们使用 MASM32 的 Bin 目录里现有的
   
    d> 源代码编辑器我们的选择很多, 有Windows 自带的记事本、EditPuls、UltraEdit、
       Notepad2等等等等,我们选 Notepad2     

    e> Makefile 解释器我们选微软的 nmake,VC 自带,也可以从网上单独下载

2、组装
上面列出了那么多东西一看头就晕了是吧,别管它们,现在我们来组装。组装就是把上面那
些东西统统找来,然后“放”到一起
   
    a> 在桌面新建一个文件夹,取名为 MasmIDE
      
    b> 打开 http://www.masm32.com/masmdl.htm,下载 m32v9r.zip 到桌面并解压,解压
       后里面是一个名为 install.exe 的文件,运行它,将 Masm32 安装到 C 盘      

    c> 进入 C 盘根目录 Masm32 文件夹,将该文件夹里的 bin / include / lib 这 3 个
       目录复制到先前我们建立的 MasmIDE 目录里。复制好后我们将 Masm32 文件夹整个
       删除,因为我们已经不再需要它了
      
   
    d> 打开 http://www.flos-freeware.ch/notepad2.html,点击该页面下部的链接下载
       Notepad2,这是一个支持语法高亮的、简约的、开源的……文本编辑器。你可以直接
       下载这个帖子下面附件 Notepad2.zip,里面的 Notepad2 我配制过字体、颜色等
      
      
    e> 下载好文本编辑器后,我们将其复制到我们的 MasmIDE 根目录下。
      
    f> 从 VC 目录里拷贝或直接下载附件 NMake.zip,解压缩后将其拷贝到 MasmIDE 目
       录下的 Bin 目录里,如图所示
      
   
    歇一口气,我们通过操作系统的 开始->运行->输入 cmd ->回车,打开一个命令提示符
    窗口。在闪动的提示符下输入 nmake 或 ml 或 link,然后回车,此时黑黑的窗口上灰
    不溜秋的一行字告诉我们不存在该命令或该可执行程序。看来我们的工作还没完,我们
    下面继续。
   
   
3、配制
在命令提示符下运行程序,操作系统(实际是 shell? 或 cmd.exe? 我们不去管它把它当操
作系统好了)会先到当前目录下搜索,如果不存在该执行程序则会到操作系统的环境变量里
列出的目录里搜索,如果这些目录里仍不存在,则提示说该程序不存在。说到这里,如果你
不是很清楚环境变量是什么,最好还是“研究研究”弄明白是咋回事。当然,如果不想弄明
白也没关系,直接跳过这一部分,下载附件 EnvPath.zip 解压缩后运行一下就自动设置好
了(最好是将其拷贝到我们的 MasmIDE 目录下,方便以后使用)。对于想了解细节的朋友,
我们来详细讨论下。

    a> 搭建一个完整的 Masm 开发环境,我们要将 MasmIDE\Bin 目录的完整路径添加到名
       为 path 的环境变量中,这是为操作系统能找到我们 MasmIDE\Bin 目录中的可执行
       文件准备的。除此之外我们还要将 MasmIDE\Include 与 MasmIDE\Lib 的路径分别
       添加到名为 include 与 lib 的环境变量中,它们是为我们的编译器 ml.exe 与链接
       器 link.exe 在编译与链接程序时定位头文件与库文件而准备。ml.exe 在处理源文
       件时遇到 include 预处理命令就会在该源文件所在目录里搜索该命令后的列出的文
       件,如果没找到,则会到名为 include 的环境变量包含的目录中搜索,如果仍未找
       到,链接器会给出一个某某头文件不存在的错误,并停止编译,link.exe 类似。
      
    b> 修改或添加环境变量的方法有很多种,可以用批处理,可以改注册表,可以手动添加,
       也可以用下面将说到的脚本直接添加的方法。与源代码编辑器一样,各人有各人的喜
       好,这里只说下我认为比较好的方法,其他方法请用搜索引擎搜索一下。
      
    c> 用 vb script 自动添加环境变量。这里也是今天现学现卖的,写出的代码可能会有
       明显的不足之处,不多说了,下载附件 EnvPath.zip 就 OK 了。这里截个图,各
       位朋友可以先一睹下我们将要使用的代码编辑器的芳容,顺便也放松下吧。
      
      
至此,我们搭建 MASM 开发环境的工作全部完成,现在我们的 MasmIDE 目录大致是这样:


//
// 二、Hello Makefile
//
1、我们在桌面上 MasmIDE 文件夹旁新建一个文件夹,取名为 HelloMakefile(当然咯,跟
MasmIDE 一样,你可以放该文件夹到任何路径)

2、运行 Notepad2.exe,将空白文件保存为 HelloMakefile\HelloMakefile.asm,并键入一
段完整的汇编源代码。如图所示,完整源代码请下载附件 HelloMakefileSrc.zip


3、在 HelloMakefile 目录下新建一个名为 Makefile(无后缀名)的文件,并用 Notepad2
打开并键入相应代码。这里直接给出附带较详细注释的代码,这样可以让我们对 Makefile
文件的编写有一个感性的认识。同上面的 vb 脚本代码一样,这些我也是知之甚少,仅起个
抛砖引玉之用,说错了的地方请回帖指正,使我不至于误人也误己。好了,废话少说,我们
开始吧,Let's go!

# 首先, Makefile 的注释符号是 # 号,仅此一种单行注释的方法

# 然后,在我现在的理解看来,Makefile 跟上面的 vb script 一样,是一种解释型的脚本
# 语言,它帮助我们完成重复的、繁杂的编译链接工作。也就是说,这种“脚本语言”将目
# 标明确的围绕着两件事情来为我们服务——编译、链接,同时,其工作对象便是——文件。

# 大凡作为一门语言,在其背后往往就会存在一个逻辑上的设计概念作为其基础,比如有面
# 向过程、面向对象等等。那么 Makefile 面向什么的呢?Makefile 是面向文件依赖关系的,
# 或者说是基于文件依赖关系的。拿面向过程的语言来说,它的源代码由一个个过程或函数
# 组成的。要编写一个函数,我们首先要按一定的格式书写函数的头部好让编译器或解释器
# 知道这是一个函数,接着我们要在函数头的下一行一个 tab 处开始写函数体以完成具体的
# 动作。Makefile 也是类似的,它是基于文件依赖关系的,所以它的源文件由一个个文件依
# 赖关系组成,并藉此完成它的“使命”。同样的,要编写一个文件依赖关系,我们首先要
# 按它所规定的语法书写一个“头”,接着我们在该“头”下一行一个 tab 处开始书写该依
# 赖关系的“体”好让 Makefile 解释器执行该依赖关系具体要完成的动作(命令)。与函
# 数稍稍不同的是,一个函数的函数体行首可以没有 tab 或空格,但一个依赖则必须有。

# 我们来看看一个依赖关系大致的样子:
# 目标文件名 : 此目标文件依赖的文件
#     命令序列

# 在真正编写 Makefile 之前,我们再来做一个类比。对于面向过程语言中的一个函数而言,
# 我们只有主动的、显式的去调用,该函数才会被执行,而 Makefile 中的依赖关系则不是
# 这样。我们知道,当我们察看一个文件的属性,我们会看到这个文件的创建时间与最后修
# 改时间。Makefile 的工作对象是文件,当一个依赖关系中目标文件所依赖文件的最后修改
# 时间大于该目标文件时,该依赖关系的“体”就会被执行,也就是说对应的命令序列会被
# 执行。这样的执行规则很明显的一个好处是,我们只编译与链接已经修改过的文件,对于
# 一个大型工程来说,这是很有益处的。

#
# 下面就是编译我们的 HelloMakefile 所需的一个完整的 Makefile
#

# 最终可执行文件的依赖关系(相当于主函数)
# 在这个例子里,其命令序列是将 obj 文件链接成可执行文件
HelloMakefile.exe: HelloMakefile.obj
    link /subsystem:windows HelloMakefile.obj

# 子属依赖关系(相当于一个子函数)
# 在这个例子里,其命令序列是将 asm 文件编译成 obj 文件
HelloMakefile.obj: HelloMakefile.asm
    ml /c /coff HelloMakefile.asm
   
将上面的代码键入到我们的 HelloMakefile\Makefile 文件里,保存一下,接着切换到编辑
HelloMakefile\HelloMakefile.asm 汇编源文件的 Notepad2 窗口。在菜单项上选择文件->
运行->命令->输入 cmd->回车,打开一个命令提示符窗口(当前路径会被自动设置为该源文
件所在路径)。在该窗口中输入 nmake 然后回车,nmake 会搜索当前目录下的 Makefile 文
件,找到后就会解释其中的指令,帮我们完成编译与链接的工作。如下图:


呵呵,是不是要欢呼一下?且慢,我们再稍微走远一点点吧。我们对上面的 Makefile 做一
点小小的改进,代码如下(嘿,朋友,其实这一步你可以考虑自己研究了^^)。

# Makefile 支持变量(相当于宏),这里定义一个 NAME 变量,赋值为 HelloMakefile
NAME = HelloMakefile

# 这里定义一个名为 OBJS 的变量,并引用 NAME 变量为其赋值
# 在 Makefile 里变量用 $() 引用
OBJS = $(NAME).obj

# 这里定义名为 LINK_FLAG 与 ML_FLAG 的两个变量
# 分别赋值为链接与编译的参数
LINK_FLAG = /subsystem:windows
ML_FLAG = /c /coff

# 同先前的 Makefile 一样的一个依赖关系,这里仅仅是引入了变量
$(NAME).exe: $(OBJS)
    link $(LINK_FLAG) $(OBJS)

$(OBJS): $(NAME).asm
    ml $(ML_FLAG) $(NAME).asm

# 这里是一种特殊的依赖关系,其目标文件称为“伪目标”,Makefile 解释器默认会执行
# Makefile 文件中的第一个依赖关系及所有目标文件最后修改时间小于其所直接或间接依
# 赖文件的依赖关系。下面这个依赖关系没有任何直接依赖文件,当然也不会有任何间接
# 的依赖文件,同时,其又不是本 Makefile 文件中的第一个依赖关系,它永远都不会被解
# 释器执行,除非我们以命令行参数的方式指定解释器执行之,比如输入:nmake clean
# 作用:完成一些比如清理、备份等等工作
clean:
    del *.obj

//
// 更多信息
//
这是一整天的学习成果,终于对 Makefile 有个了解了,各位朋友不知道我这一步“憋”了
有多久。忍不住激动的心情,与大家分享,希望对和我一样久久徘徊于 Makefile 门外的朋
友有点帮助。如果需要获取更多的信息,强烈推荐下载附件 跟我一起写Makefile.zip。这
是由孟岩写的一篇非常优秀的 Makefile 教程。最后想说,写或读这么篇文章可真不容易,谢
谢各位的阅读。

    Have fun!

    刘泽围 2007年12月21日 于杭州


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (42)
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
2
好文,帮顶
2007-12-21 23:56
0
雪    币: 2943
活跃值: (1788)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
3
图文并茂,的确好文,帮顶!
2007-12-22 08:38
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
4
强啊。

学asm不久,偶只能看懂汇编。镶嵌的C里面用
2007-12-22 09:08
0
雪    币: 290
活跃值: (11)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
5
makefile 又名 选择性编译!!!  跟批处理类似!
具体是判断被编译的文件是否被修改 (按照日期判断) 没被修改得不编译!
冒个泡!!!
NAME =  "MAC"
$(NAME)
2007-12-22 10:02
0
雪    币: 266
活跃值: (52)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
6
LZ辛苦了

不就是编译,连接嘛, 不知道为什么都喜欢用MakeFile, 我从来没有弄懂它的含义,觉得麻烦

我一直都是写个批处理文件,加上两条指令:

ml ........

link ........

不就OK了,干嘛那么费事?
2007-12-22 16:44
0
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
7
MASM32可以为你生成它-_-
2007-12-22 16:57
0
雪    币: 324
活跃值: (91)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
8
其实我也不知道 Makefile 相比批处理的优点, 我想, 可能正是因为不了解所以才不清楚其优点吧.

我猜测 Makefile 可能会比批处理更强大之外, 他们之间还有一个本质的区别, Makefile 具有一定的自主性, 它会根据文件的最后修改日期选择性的完成命令序列中的一部分.

另外, 我觉得 Makefile 存在的意义还在于其含有 标准化 的意味, 可以方便交流.

还有, Makefile 存在就有它的意义吧, 我们了解它更多可能会发现更多.

最后, 我们学写 Makefile 是为了开阔眼界, 从而有可能步入另一个领域, 脱离固有 IDE 的束缚.

一个程序员的眼界我觉得很重要!
2007-12-22 18:03
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
9
很好!要么不搞,要搞的话一定搞懂搞透彻!
2007-12-23 01:18
0
雪    币: 224
活跃值: (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
与批处理相比的优点应该就是编译的文件数目不一样吧
批处理重新全部编译一次,而makefile根据更新时间来选择的吧
2007-12-23 17:42
0
雪    币: 223
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
好文!!!
收藏了。
2008-1-4 19:25
0
雪    币: 424
活跃值: (3353)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
好文,顶一下!
2008-1-4 19:52
0
雪    币: 146
活跃值: (33)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
13
很好的教程!!!,其实都图文并茂到这个地步了,开始还不如做个动画片.....
2008-1-4 20:10
0
雪    币: 97697
活跃值: (200759)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
14
Thanks.
2008-1-6 00:15
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
好文,太及时了!
2008-4-21 21:27
0
雪    币: 235
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
实在是太感谢了.正要找这个.
2008-4-24 21:29
0
雪    币: 201
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
关于path的设置,到不一定要修改系统的相关东西,用变量就足够了。
LINK = c:\masm32\bin\link
链接的时候:$(LINK)  $(LINKFLAG) $(OBJFILES)这样的方式就行了。

没用过makefile的关注一下linux下的软件吧,比起批处理实在灵活强大太多了。楼主介绍的功能还仅仅是九牛一毛罢了。

不过我倒是用cygwin的make而不是nmake
2008-4-25 17:11
0
雪    币: 210
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
我也不用IDE,但是也不用makefile。批处理就足够了。
2008-5-5 18:18
0
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
19
好文,学习之,谢谢楼主
2008-5-5 22:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
写得很不错!!

少理论多操作

谢谢楼主
2008-5-6 01:00
0
雪    币: 272
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
说实话,我大概看了一下,很郁闷。。。

makefile 到底是做什么用的?怎么不在文章开始就明确写出来?

其实用汇编的话就用 AOGO的 IDE就很好了!比MAKE FILE方便很多,

如果你要说用IDE会导致交流上的困难(比如会发生file not found错误)的话,

那可以把所需要的inc和lib同时拷贝再发布。。。。。。。。。反正比用make file方便,

至少在ASM中是如此,而在VC和VB中的话,相信大家都是直接用光盘安装的MS标准的IDE,

也不会发生什么错误,所以我认为make file是把简单事情复杂化了。。。。。
2008-5-6 10:01
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
22
应该以前非视窗时代的利器吧
2008-5-12 00:24
0
雪    币: 315
活跃值: (23)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
23
不错的文章。认真看下去收获不小。。 顶上去。。
2008-5-13 23:58
0
雪    币: 286
活跃值: (14)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
24
好文,收藏,支持。
2008-5-15 18:10
0
雪    币: 286
活跃值: (14)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
25
真的很好,好文,支持。
2008-5-15 18:29
0
游客
登录 | 注册 方可回帖
返回
//