VS中的c++的makefile nmake

VS中的c++的makefile    nmake
简介

大家已经习惯于微软提供的功能强大的IDE,已经很少考虑手动编连项目了,所谓技多不压身,有空的时候还是随我一块了解一下命令行编译。

C/C++/VC++程序员或有Unix/Linux编程经验应该很熟悉,以前我曾写过一篇文章描述用csc/vbc来进行命令行编译,今天再介绍一下MS提供的更加快捷有效的编译工具NMake。

MSDN的描述: Microsoft 程序维护实用工具 (NMAKE.EXE) 是一个 32 位,基于说明文件中包含的命令生成项目的工具。

NMake具有丰富的选项,可以完成复杂编译操作。它可以辨别源代码的改动,并选择性的编译,为你节省大量不必要的编译时间。

使用NMAKE

语法:NMAKE [options] [macros] [targets] [@commandfile]

说明:其中,options是NMAKE的选项,macros是在命令行中的宏定义,targets是NMAKE的目标文件列表,commandfile是包含命令行输入的文本文件(或响应文件)。

NMAKE 使用指定 /F 选项的Makefile(生成文件,通常名字是makefile);如果未指定 /F 选项,则使用当前目录下的Makefile。如果未指定Makefile,则 NMAKE 使用推理规则生成命令行 targets。

NMake本身很简单,与NMAKE配合的是Makefile。Makefile的语法比较复杂,通常需要开发者自己手动编写Makefile,下一节我们详细讲解Makefile。

上面的options和macros做了MSDN的链接,内容较多,请自己查询相关页,可以从这里进入NMake的MSDN帮助页面,在线帮助点这里

编写MAKEFILE

注:本节内容来自MSDN,熟悉此节的朋友可以直接跳过

Makefile的组成部分包括:成文件包含:

a.描述块

描述块是后面可跟有命令块的依赖项行:

    targets... : dependents...
            commands...

依赖项行指定一或多个目标以及零或多个依赖项。目标必须位于行首。用冒号 (:) 将目标和依赖项分开;允许使用空格或制表符。若要拆分行,请在目标或依赖项后面使用反斜杠 (\ )。如果目标不存在、目标的时间戳比依赖项早或者目标是伪目标,则 NMAKE 执行命令。如果某依赖项是其他地方的目标,并且不存在或对于自己的依赖项已过期,则 NMAKE 在更新当前依赖项之前更新该依赖项。

b.命令

如果依赖项已过期,则描述块或推理规则指定要运行的命令块。NMAKE 在运行命令之前显示每个命令,除非使用了 /S 选项、.SILENT!CMDSWITCHES 或 @。如果描述块后面没有紧跟命令块,NMAKE 将查找匹配的推理规则。

命令块包含一个或多个命令,每个命令位于各自的命令行上。在依赖项(或规则)和命令块之间不能出现空行。但是可以出现只包含空格或制表符的行;该行被解释为空命令,并且不出现错误。命令行之间允许有空行。

命令行以一个或多个空格或制表符开始。后面紧跟着换行符的反斜杠 ( \ ) 在命令中被解释为空格;在行尾使用反斜杠继续下一行命令。如果反斜杠后紧跟有其他任何字符(包括空格或制表符),则 NMAKE 按原义解释反斜杠。

无论后面是否紧跟有命令块,前面带分号 (;) 的命令可以出现在依赖项行上或推理规则中:

project.obj : project.c project.h ; cl /c project.c

c.宏

宏用另一个字符串替换生成文件中的特定字符串。使用宏可以:

  • 创建可生成不同项目的生成文件。
  • 指定命令选项。
  • 设置环境变量。

可以定义您自己的宏或使用 NMAKE 的预定义宏

d.推理规则

推理规则提供命令来更新目标并推理目标的依赖项。推理规则中的扩展名与具有相同基名称的单个目标和依赖项匹配。推理规则是用户定义的,或预定义的;预定义的规则可以重新定义。

如果过期的依赖项没有命令,并且如果 .SUFFIXES 包含依赖项的扩展名,则 NMAKE 使用其扩展名与当前或指定目录中的目标和现有文件匹配的规则。如果有多个规则与现有文件匹配,.SUFFIXES 列表将确定使用哪一个规则;列表优先级从左向右按降序排列。如果依赖文件不存在,并且未在另一个描述块中作为目标列出,则推理规则可以从具有相同基名称的另一个文件创建缺少的依赖项。如果描述块的目标没有依赖项或命令,推理规则可以更新目标。即使不存在描述块,推理规则也可以生成命令行目标。即使指定了显式依赖项,NMAKE 也可以调用推理依赖项的规则。

e.点指令

在描述块之外的行首指定点指令。点指令以句点 ( . ) 开始,后面跟一个冒号 (:)。允许使用空格或制表符。点指令名区分大小写并且应为大写。

指令 作用
.IGNORE : 忽略从指定该指令的位置到生成文件末尾之间,由命令返回的非零退出代码。默认情况下,如果命令返回非零退出代码,NMAKE 将暂停。若要还原错误检查,请使用 !CMDSWITCHES。若要忽略单个命令的退出代码,请使用短划线 (-) 修饰符。若要忽略整个文件的退出代码,请使用 /I 选项。
.PRECIOUS : targets 若更新 targets 的命令暂停,则将 targets 保留在磁盘上;若命令通过删除文件处理中断,则该指令无效。用一或多个空格或制表符分隔目标名称。默认情况下,如果通过使用 CTRL+C 或 CTRL+BREAK 组合键中断生成,NMAKE 将删除目标。.PRECIOUS 的每一次使用都应用于整个生成文件;多次指定是累计的。
.SILENT : 取消从指定该指令的位置到生成文件末尾之间的已执行命令的显示。默认情况下,NMAKE 显示它调用的命令。若要还原回显,请使用 !CMDSWITCHES。若要取消单个命令的回显,请使用 @ 修饰符。若要取消整个文件的回显,请使用 /S 选项。
.SUFFIXES : list 列出推理规则匹配的扩展名;预定义为:.exe .obj .asm .c .cpp .cxx .bas .cbl .for .pas .res .rc。

若要更改 .SUFFIXES 列表顺序或指定新列表,请清除此列表并指定新的设置。若要清除此列表,请不要在冒号后指定扩展名:

.SUFFIXES :

若要将其他后缀添加到列表的末尾,请指定

.SUFFIXES : suffixlist

其中 suffixlist 是附加后缀的列表,由一或多个空格或制表符分隔。若要查看 .SUFFIXES 的当前设置,请运行选项为 /P 的 NMAKE。

f.预处理指令

可以通过使用预处理指令和表达式控制 NMAKE 会话。预处理指令可以放置在生成文件或 Tools.ini 文件中。使用指令可以有条件地处理生成文件,显示错误信息,包括其他生成文件,取消定义宏以及打开或关闭某些选项。

    Makefile示例

    看了一堆理论,很累了吧?下面看一段简单的MakeFile

    # 宏定义
                                SOURCES=AssemblyInfo.cs \
                                Form1.cs \
                                Form2.cs \
                                Form3.cs \
                                HelloWorld.cs
                                # 引用规则
                                # 目标:
                                CLRProfiler.exe : $(SOURCES) #<--依赖项
                                # 标志
                                # 下面是命令
                                csc /t:winexe /out:HelloWorld.exe /r:System.Windows.Forms.dll $(SOURCES)
                                clean:
                                del HelloWorld.exe
                                
     

    将上述代码保存为Makefile(没有后缀)放在你的项目文件夹下, 然后打开VS2003.NET命令行窗口,进入项目夹所在路径,打入NMake回车, ok

    示例2

    下面演示一下多个项目时的编译,每个单独的项目创建单独的makefile,解决方案下放一个总的makefile

    all:
                                # 分别对项目进行编译
                                cd project1
                                nmake
                                cd ..
                                cd project2
                                nmake
                                cd ..
                                cd project3
                                nmake
                                cd ..
                                # 将编译结果汇总到当前路径
                                copy project1\project1.dll
                                copy project2\project2.dll
                                copy project3\project3.exe
                                clean:
                                # 清除编译结果
                                del project1.dll
                                del project2.dll
                                del project3.exe
                                cd project1
                                nmake clean
                                cd ..
                                cd project2
                                nmake clean
                                cd ..
                                cd project3
                                nmake clean
                                cd ..
                                
     
    小节

    本文简单介绍了NMAKE的用法,并对Makefile的语法做了介绍。篇幅所限,既不能面面俱到,又不能深入剖析,只希望能够让更多人了解此工具。笔者也是刚刚接触,经验不多,还请各位网友多多拍砖!

    附表(makefile中常用的几个符号)


    符合 作用
    ^ (caret) 用于关闭某些字符所具有的特殊意义,使其只表示字面上的意义。例如:^#abc表示#abc这个字符串,而#abc则用于在makefile中加入注释,#在这里为注释标志,就像C++中的//。另外,在一行的末尾加上^,可以使行尾的回车换行符成为字串的一部分。
    # (number sign) 注释标志,NMAKE会忽略所有从#开始到下一个换行符之间的所有文本。这里要注意的是:在command lines中不能存在注释。因为对于command lines,NMAKE是将其整行传递给OS的。通常对于command lines的注释都是放在行与行之间。
    \ (backslash) 用于将两行合并为一行。将其放在行尾,NMAKE就会将行尾的回车换行符解释为空格(space)。
    % (percent symbol) 表示其后的字符串为一文件名。
    ( (left parentheses)  
    ) (right parentheses)  
    {  
    }  
    ! (exclamation symbol) 命令修饰符
    @ (at sign) 命令修饰符
    - (hyphen)  
    : (colon) 用于dependent lines和inference rules中,用于分隔target和dependent。
    ; (semicolon) 如果对于一个dependent line只有一条命令,则可以将该命令放在dependent line的后面,二者之间用“;”分隔。
    $ (dolor sign) 用于调用宏



    VS构建工具介绍

    我们都知道C/C++源代码要生成可执行的.exe程序,需要经过编译、链接的过程。你在VS工具中只需要选择菜单Build或按一下F5可以编译、链接、运行了,其实IDE帮我隐藏了好多的具体细节。

    我先假设VS2013安装在以下目录中:

    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin      //这是2013的目录

    打开安装目录下的可以看到一系列的可执行程序.exe和批处理文件,这些就是VS2010构建、编译、链接时要用到的工具。看一下几个主要的工具: 
    cl.exe:编译程序 
    link.exe:链接程序 
    lib.exe:加载lib库的程序 
    nmake.exe:用makefile进行构建、编译的工具



    命令行编译程序

    要在命令行(而不是VS)中编译程序,先要配制环境变量。网上有些教程说执行VSDIR\VC\bin\vcvars32.bat的批处理就可以了,但我执行这个批处理时会报错:

    Setting environment for using Microsoft Visual Studio 2010 x86 tools.

    这又是另外一个问题,我就不管了,直接手动配制环境变量把: 
    右键我的计算机->属性->高级系统设置->高级->环境变量,配制的环境变量(建议配制在用户的环境变量中)的值如下: 
    VS2010_DIR: 
    C:\Program Files (x86)\Microsoft Visual Studio 10.0 
    WIN_SDK: 
    C:\Program Files (x86)\Microsoft SDKs 
    path: 
    C:\Users\Administrator.dnx\bin;%VS2010_DIR%\VC\bin;%VS2010_DIR%\Common7\IDE 
    include: 
    %VS2010_DIR%\VC\include;%WIN_SDK%Windows\v7.0A\Include; 
    lib: 
    %VS2010_DIR%\VC\lib;%WIN_SDK%\Windows\v7.0A\Lib;


    测试

    D:\CppWorkspace\CommandTest\HelloWorld.cpp:

    #include <iostream>
    #include <stdio.h>
    
    int main()
    {
        std::cout << "This is a native C++ program." << std::endl;
        printf("printf: Hello World");
        return 0;
    }
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    编译结果: 

    命令行中编译C/C++程序 
    命令行中编译C/C++程序

    HelloWorld.obj就是编译出的二进制文件,HelloWorld.exe就是链接成的可执行文件。


    说明

    在以上的编译过程中我们只用了cl的编译命令就帮我们最终的可执行文件HelloWorld.exe,这是因为cl.exe程序在编译时自己会去调用link.exe、lib.exe等程序。

    可通过”cl -help “查看常用的编译选项

    选项 作用
    /O1 创建小代码
    /O2 创建快速代码
    /Oa 假设没有别名
    /Ob 控制内联展开
    /Od 禁用优化
    /Og 使用全局优化
    /Oi 生成内部函数




    先创建目录:

    [plain]  view plain  copy
    1. mkdir HelloWorld  
    2. cd HelloWorld  

    用Emacs创建man.cpp文件。

    [cpp]  view plain  copy
    1. #include <iostream>  
    2.   
    3. int main()  
    4. {  
    5.   std::cout << "Hello, world!" << std::endl;  
    6.   return 0;  
    7. }  

    再创建一个makefile文件。

    [plain]  view plain  copy
    1. foo: main.cpp  
    2.     cl main.cpp  


    这个makefile文件只包含了一个描述块(Description Block)

    语法则是常见的makefile规则:

    [plain]  view plain  copy
    1. targets... : dependents...  
    2.     commands...  

    现在启动windows command窗口,最普通的那种。

    然后运行设置环境变量的批处理文件,来自于普通Windows控制台窗口运行nmake编译VC

    [cpp]  view plain  copy
    1. C:\study\nmake>vc_env.bat x86  
    2. Setting environment for using Microsoft Visual Studio 2012 x86 tools.  
    3.   
    4. C:\study\nmake>where nmake  
    5. C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\nmake.exe  
    6.   
    7. C:\study\nmake>where cl.exe  
    8. C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\cl.exe  
    9.   
    10. C:\study\nmake>where link.exe  
    11. C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\link.exe  

    然后进入HelloWorld目录,运行nmake 命令:

    [plain]  view plain  copy
    1. C:\study\nmake\HelloWorld>nmake  
    2.   
    3. Microsoft (R) Program Maintenance Utility Version 11.00.60610.1  
    4. Copyright (C) Microsoft Corporation.  All rights reserved.  
    5.   
    6.         cl main.cpp  
    7. Microsoft (R) C/C++ Optimizing Compiler Version 17.00.60610.1 for x86  
    8. Copyright (C) Microsoft Corporation.  All rights reserved.  
    9.   
    10. main.cpp  
    11. C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xlocale(336) : warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc  
    12. Microsoft (R) Incremental Linker Version 11.00.60610.1  
    13. Copyright (C) Microsoft Corporation.  All rights reserved.  
    14.   
    15. /out:main.exe  
    16. main.obj  
    有一个警告,以后解决,不过已经看到cl命令了,cl main.cpp,并且最后生成了main.exe和main.obj文件。


    现在运行main.exe程序,得到结果:

    [cpp]  view plain  copy
    1. C:\study\nmake\HelloWorld>main.exe  
    2. Hello, world!  

    VC编译包含两步骤,cl生成obj文件, link将obj文件连接成binary。这里由于没有使用/c参数,所以自动完成了link操作。




    转载:  http://truly.cnblogs.com/archive/2005/08/13/213810.html#_asug_description_blocks

    http://blog.csdn.net/luoweifu/article/details/49847749

    http://www.lellansin.com/%E5%BE%AE%E8%BD%AF-cl-exe-%E7%BC%96%E8%AF%91%E5%99%A8.html





    • 1
      点赞
    • 11
      收藏
      觉得还不错? 一键收藏
    • 0
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值