//------------------------------------------------------------------------------------------------------------
//
// 此文章所有权归huapingsmith$gmail.com所有,如若转载,请注明此行
// 2008-05-07
//-------------------------------------------------------------------------------------------------------------
也许有一部分人想在vc下使用MakeFile来编绎项目,有些是为了跨平台、有些是因为开源,根本就没有dsp,dsw,slution之类的文
件、有些是为了提高自己的水平、也有人像我一样,因为机器配置的问题,不愿意多次打开VS2005——这个东西吃内存和CPU不是一般的厉害。而网上又很
难找到合适的中文资料,MSDN上讲的东西又太粗放了,寥寥几句,令人茫然。闲话少说,下面正式开始。
据我所知,VS2005不再像VC6一样,可以导出MakeFile,所以如果你需要MakeFile就要自己写。但是它仍然支持MakeFile,这一点是不用担心的。首先有五个问题要说明一下。
第一是vc的环境变量设置,有些人不明白VC的环境变量,往往得到这个错误提示“'nmake'
不是内部或外部命令,也不是可运行的程序或批处理文件。”。在调用nmake之前,要先调用vc的路径下的VCVARS32.BAT,这个文件位于vc的
安装目录下,为"...\Program Files\Microsoft Visual Studio 8\VC\bin\。
第二是nmake的调用,msdn中有详细的讲解。
NMAKE [option...] [macros...] [targets...] [@commandfile...],举个例子,有一个test.mak文件,如果你需要用它来生成exe,那么你可以:
nmake /f demo.mak。
如果你要指定生成目标:
nmake ALL /f demo.mak
如果你要指定宏定义:
nmake ALL CFG=DEBUG /f demo.mak
其中CFG=DEBUG定义了一个宏,值为DEBUG,这个我们后面再详细说明。
第三是cl.exe的调用,这个命令有非常多的选项,但是常用的就几个。这个命令用于编译c/c++文件,生成.obj目标文件。
第四是link.exe的调用,这个命令是用来链接生成exe和debug数据库的。
第五是rc.exe的调用,这个命令很简单,用来从.rc生成二进制的.res资源。在link的时候要用到.res——如果你的程序用资源的话。
当然还有其他的事项,这里不能一一加以说明,最详细的还是要查MSDN。
下面正式开始MakeFile的说明。
1、描述块:
MakeFile的核心是“规则”,MSDN中称之为“描述块”(Description blocks),描述块是一个说明了依赖性的行,可以带有命令行,Fig1.0中的hello: hello.exe about.res就是一个描述块,但是它没有带命令行。
about.res: about.rc
rc /l 0x804 /fo ".\release\about.res" "about.rc"
也是一个描述块,它后面跟有命令行——请注意,命令行不是描述块的一部分。MakeFile由一个个描述块组成。描述块的语法如下:
targets... : dependents...
commands...
描述块中间必须有“:”,否则nmake.exe将报这一行有语法错误。targets是要生成的目标、dependents是生成源,一般为c/c++文件。commands说明了如何生成targets.一个targets可以依赖多个dependet项。
hello :hello.exe about.res
hello.obj: hello.c
cl /02 /nologo /Ob1 /Oy /D "_MD" /EHsc /D
"WIN32" /D "NDEBUG" /D "WINDOWS" /D "_MBCS" /GF /FD /MT /Gy /Fo ".
\Release\\" /W4 /c /TC /errorReport:none hello.c
about.res: about.rc
rc /l 0x804 /fo ".\release\about.res" "about.rc"
hello.exe: hello.obj
link /OUT:".\Release\TIC.exe"
/INCREMENTAL:NO /MANIFEST /MANIFESTFILE:
".\Release\TIC.exe.intermediate.manifest" /DELAYLOAD: "OleAcc.dll"
/SUBSYSTEM:WINDOWS /MACHINE:X86 /ERRORREPORT:PROMPT DelayImp.lib
".\release\hello.obj" User32.lib Winmm.lib Gdi32.lib
".\Release\about.res"
Fig1.0
好,我们知道描述块是做什么的了,那么MakeFile又是怎么生成目标文件的呢?MakeFile中的第一个目标称为默认目标,如果nmake时没有指
定目标,则生成默认目标。在Fig1.1中,ALL是默认目标,如果你执行nmake /f fig1.2.mak,会生成tic.exe。如果执行
nmake CLEAN /f
fig1.2.mak,会删除.\debug\*.obj。目标指明了要做什么,而依赖项,也就是冒号后面的那些内容指明了生成源,后面的
commands指明了如何去生成。在生成.obj前,nmake会检查它依赖的.c&.cpp&.h是否更新,如果更新就重新执行
commands生成新的.obj,否则nmake什么也不做。按照这个顺序从上到下依次检查,从最底下的.c&.cpp开始生成.obj,然后
链接成我们需要的.exe。2、MakeFile中的宏
MakeFile中的宏可以在nmake的参数中赋值,也可以在MakeFile中赋值,用户可以自定义宏,另外还有一些特殊宏,我基本上不用这些特殊
宏,因为它们比较难懂,不适合项目中的交流。一个宏名可以是数字、字母和下划线的组合,建议使用大写字母增加可读性。FIig1.1中使用了大量的宏。宏
赋值直接用"="即可,比如定义一个宏CFG,赋值就可以CFG=DEBUG,$(CFG)表示使用这个宏。
Fig1.1
也许有人不理解为什么使用宏,使用宏的最大好处是可以减少重复输入,同时提高MakeFile的可读性和可维护性。