windows cl命令行编译和nmake

nmake.exe和cl.exe现在安装的vs的bin目录下,加到环境变量Path中去。

然后新建两个环境变量INCLUDE和LIB,INCLUDE就是放所需要的头文件路径,LIB就是库文件路径了,例如D:\vs2012\VC\includevs2012\VC\include加到INCLUDE中,D:\vs2012\VC\lib加到LIB中,还有C盘下的标准库文件,C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib,vs2015的话比较麻烦一下。vs也是奇怪选择安装路径了,还是把库文件放到C盘占几个G,不过是有办法转移,太麻烦就算了。总之,需要什么就把路径加进去。这样在cmd 中输入cl和nmake就能看到了。

这里说cmd的话,安利一个cmder,替换cmd,百度一下就有了,可以直接使用linux下的命令也可以使用,复制粘贴方便,主要是好看~~。

接着看cl,写一个测试文件,test.cpp

#include <iostream> 
using namespace std;
 
int main()
{
  cout<<"Hellow World"<<endl;
  return 0;
}

执行 cl test.cpp, 就会发现生成了test.obj和test.exe

要向使用vs那样编译,要加一下参数,可以直接看MSDN (http://msdn.microsoft.com/en-us/library/vstudio/9s7c9wdw.aspx

或者直接输入 cl /?查看,你想知道的都会有。

CL   [option...]   file...   [option   |   file]...   [lib...]   [@command-file]   [/link   link-opt...]     

option   一个或多个   CL   选项。请注意,所有选项都应用于所有指定的源文件。选项是由一个正斜杠   (/)   或一个短划线   (–)   指定的。如果某个选项带有参数,则该选项的说明指定在选项和参数之间是否允许有空格。选项名(/HELP   选项除外)区分大小写。。      
file   一个或多个源文件、.obj   文件或库的名称。CL   编译源文件并将   .obj   文件和库的名称传递给链接器。   
lib   一个或多个库名。CL  将这些名称传递给链接器。      
command-file   包含多个选项和文件名的文件。    
link-opt   一个或多个链接器选项。CL   将这些选项传递给链接器。    
您可以指定任意数目的选项、文件名和库名,条件是命令行上的字符数不超过   1024,该限制是操作系统指定的。

下面记录几个常用的选项 (window的选项前面都是使用‘/’符号,但使用‘-’也可以,这样就跟gcc一样了):

/c  只编译不连接 不链接就是只生成.obj文件没有exe,连接生成exe

/I 指定头文件的目录 

/C 在编译期间保留代码注释

/EH 异常处理模式,后面可以接一些参数 / EH { s | a } [ c ] [ r ] [ - ],最常用的就是/ EHsc ,表示仅捕获C ++异常,并告诉编译器假定声明为extern“ C”的函数绝不会引发C ++异常。别的可以看MSDN(https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?redirectedfrom=MSDN&view=vs-2019#arguments

/RTC 运行时错误检查

/D 预处理程序定义  可以与#if#ifdef一起使用。符号定义将一直有效,直到在代码中重新定义它,或者被#undef指令取消。/ D#define源代码文件开头的指令具有相同的作用,默认定义的符号值为1,/D name等效于/D name=1/ D和符号之间可以有空格。符号和等号之间,或等号和任何分配的值之间不能有空格。例如 /D WIN32 :定义WIN32平台上编译  /D _DEBUG:定义预处理器   /D _CONSOLE  /D _UNICODE /D UNICODE:字符集

编译Debug版本时,调试信息需要保留,我们可以选择直接将调试信息写到.obj文件中,或者存到.pdb文件中。

Z7 不产生.pdb文件,将所有调试信息存入.obj文件中,不跟/ Gm(启用最小重建)一起用。

/Zi和/ZI 都产生.pdb文件,使用/ Zi编译的对象创建库,则当库链接到程序时,关联的.pdb文件必须可用。因此,如果分发库,则还必须分发PDB文件。要创建一个包含调试信息的库而不使用PDB文件,您必须选择/ Z7选项。如果使用预编译头选项,则预编译头和其余源代码的调试信息都将放在PDB文件中。

/ZI 产生PDB文件,支持编辑和继续功能,会禁止#pragma optmize 指令,也不能和/clr一起用。

/W3 警告级别 IDE中的默认设置

/Wall 显示/ W4显示的所有警告以及/ W4不包括的所有其他警告,例如,默认情况下处于关闭状态的警告。

/WX 将所有编译器警告视为错误

/sdl(启用其他安全检查) 添加建议的安全开发生命周期(SDL)检查,如果发现相关警告,转变成错误输出。/ sdl启用/ GS提供的基准安全检查的超集,并覆盖/ GS-。默认情况下,/ sdl是关闭的。/ sdl-禁用其他安全检查。

/O选项(优化代码) / Od禁用优化,以加快编译速度并简化调试,/ Og启用全局优化,/ O2设置了优化的组合,这些优化可优化代码以实现最大速度, / Oy禁止在调用堆栈上创建帧指针,以实现更快的函数调用。

/RTC 运行时错误检查

/MD   使用   MSVCRT.lib   编译以创建多线程   DLL    
/MDd   使用   MSVCRTD.lib   编译以创建调试多线程   DLL    
/ML   使用   LIBC.lib   编译以创建单线程可执行文件    
/MLd   使用   LIBCD.lib   编译以创建调试单线程可执行文件    
/MT   使用   LIBCMT.lib   编译以创建多线程可执行文件    
/MTd   使用   LIBCMTD.lib   编译以创建调试多线程可执行文件  

/LD 创建一个DLL。/ LDd 创建一个debugDLL定义_MT_DEBUG

/GS(缓冲区安全性检查)

/ Yc(创建预编译的头文件) 指示编译器创建一个预编译的头文件(.pch),该文件表示特定点的编译状态。/Yc "stdafx.h" 制定stdafx.h为预编译头文件

/Fp(.pch文件名)提供预编译头的路径名,而不使用默认路径名。/Fp"Debug\HelloWorld.pch" 指定预编译文件, 这样staafx.h编译出的内容放在HelloWorld.pch中,可以大大提高编译速度。因为VC中的预编译文件很大,每次重新编译很耗时。

/Fo(对象文件名)指定obj文件的放置路径 /Fo"Debug\\" 指定.obj文件存放在Debug目录下

/Fd:指定pdb文件的放置路径  /Fd"Debug\vc110.pdb" 指定pdb文件路径

/Gd 仅用于x86平台。如果C++函数没有显示指定__stdcall或者__fastcall,就采用__cdecl

/TC   / TP指定将在命令行上命名的所有文件都视为C源文件(/ TC)或C ++源文件(/ TP

/analyze- 这是关闭代码分析功能

/errorReport:prompt 提示内部错误信息

 

LINK

LINK 是将通用对象文件格式 (COFF) 对象文件和库链接起来以创建 32 位可执行 (.exe) 文件或动态链接
库 (DLL) 的 32 位工具。

LINK 用法如下:

/ALIGN 指定每一节的对齐方式
/ALIGN 选项指定程序线性地址空间中每一节的对齐方式。number 参数以字节为单位,并且必须是2 的幂。默认值是 4K (4096)。如果对齐方式产生无效的图像,则链接器发出警告。除非正在编写诸如设备驱动程序的应用程序,否则应不需要修改对齐方式。
/DLL 生成 DLL
/DRIVER 创建 Windows NT 核心模式驱动程序
/EXETYPE 生成虚拟设备驱动程序
/EXETYPE:DYNAMIC 创建动态加载的虚拟设备驱动程序。
/EXETYPE:DEV386 创建静态加载的虚拟设备驱动程序。这是 /EXETYPE 的默认值
/INCREMENTAL 控制增量链接
/LARGEADDRESSAWARE 通知编译器应用程序支持大于 2 GB 的地址
/LIBPATH 允许用户重写环境库路径
/LIBPATH:"e:/VC/LIB" /LIBPATH:"e:/DX/LIB"
/MACHINE 指定目标平台
  /MACHINE:{AM33|ARM|EBC|IA64|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|SH3|SH3DSP|SH4|SH5|THUMB|X86|X64/*8.0版本*/}
/MACHINE:X86
/NOENTRY 创建纯资源 DLL       创建纯资源 DLL 时要求 /NOENTRY 选项。
/OPT 控制 LINK 优化    如果生成仅运行于 Windows NT 或 Windows 2000 上的组件,则应使用 /OPT:NOWIN98。
/SUBSYSTEM: 指定子系统 {CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|
WINDOWSCE}[,#[.##]]
/OUT 指定输出文件名
/OUT:Hello.exe

 

使用nmake

编写makefile,这里就不具体说怎么写makefile,其实原理跟在linux下是一样的,看几个例子就知道怎么写了。

nmake 执行两种形式

1、nmake [options] [/f makefile] [/x stderrfile] [macrodefs] [targets]

2、nmake @commandfile   commandfile 是存储命令行参数的文本文件

第一种方式中直接使用了参数,各参数的意义如下
./f 参数:指明使用的 makefile 文件名,如果不指定,则使用名为“makefile”的文件。
./X 参数:指定错误输出文件,见/X 选项。
. macrodefs:定义宏

MAKE 的选项(Options)有很多种,选项使用“/”或“.” 作为其前缀,选项名不区分大小写.
 

https://blog.youkuaiyun.com/csfreebird/article/details/10110035 这篇博客里介绍了一种设置环境变量的方法。写一个vc_env.bat文件,内容是:

@rem modifed by Dean Chen to only support Visual Studio 2012 x86/x64 tools, initial version from http://bojan-komazec.blogspot.com/2011/10/nmake-and-its-environment.html 
@echo off

@if "%1"=="x86" goto set_x86
@if "%1"=="x64" goto set_x64
@if "%1"=="" goto error

:set_x86
@echo Setting environment for using Microsoft Visual Studio 2012 x86 tools.

set INCLUDE=^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\INCLUDE;^
C:\Program Files (x86)\Windows Kits\8.0\include\shared;^
C:\Program Files (x86)\Windows Kits\8.0\include\um;^
C:\Program Files (x86)\Windows Kits\8.0\include\winrt;

set LIB=^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\LIB;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\LIB;^
C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86;

set PATH=^
%SystemRoot%\system32;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE;^
C:\Program Files (x86)\Windows Kits\8.0\bin\x86;

goto test_bin_locations

:set_x64
@echo Setting environment for using Microsoft Visual Studio 2012 x64 tools.

set INCLUDE=^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\INCLUDE;^
C:\Program Files (x86)\Windows Kits\8.0\include\shared;^
C:\Program Files (x86)\Windows Kits\8.0\include\um;^
C:\Program Files (x86)\Windows Kits\8.0\include\winrt;

set LIB=^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\LIB\amd64;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\lib\amd64;^
C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x64;

set PATH=^
%SystemRoot%\system32;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\amd64;^
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE;^
C:\Program Files (x86)\Windows Kits\8.0\bin\x64;

goto test_bin_locations

:test_bin_locations
@echo on
where nmake
where cl.exe
where link.exe
@echo off
goto:eof

:error
@echo Usage: setenv.bat [x86^|x64]

goto:eof

运行之后环境变量就设置好了,不用在右击属性一个个往里加了。

 

看一个makefile

INCLUDE_DIR = ..\include
OBJ_DIR = ..\obj
BIN_DIR = ..\bin
SRC_DIR = ..\src
EXE_NAME = step.exe

OBJ_FILES = \
	$(OBJ_DIR)\main.obj \
	$(OBJ_DIR)\printer.obj

$(OBJ_DIR)\main.obj: $(SRC_DIR)\main.cpp
	cl /c /EHsc /I$(INCLUDE_DIR) $(SRC_DIR)\main.cpp
	copy main.obj $(OBJ_DIR)
	del main.obj

$(OBJ_DIR)\printer.obj: $(SRC_DIR)\printer.cpp
	cl /c /EHsc /I$(INCLUDE_DIR) $(SRC_DIR)\printer.cpp
	copy printer.obj $(OBJ_DIR)
	del printer.obj

$(EXE_NAME): $(OBJ_FILES)
	link /out:$(BIN_DIR)\$(EXE_NAME) $(OBJ_FILES)

all: $(EXE_NAME)

执行 nmake all ,就会生成step.exe文件 ,执行nmake all 时t目标 all将会被执行,all依赖target  $(EXE_NAME),因此该target被执行,又依赖$(OBJ_FILES),因此OBJ_FILES里面的每个obj都会被执行,最后回到link命令进行连接。

上面makefile中定义的变量,在windows中成为宏,看一下特殊宏

$@当前目标的全名(全路径)
$$@当前目标的全名(全路径),作为依赖项
$*除去了文件扩展名的当前目标的全名
$**当前目标的所有依赖项
$?时间戳晚于当前目标的时间戳的所有依赖项
$<时间戳晚于当前目标的时间戳的所有依赖项。在推理规则的命令中有效
MAKE调用NMAKE
MAKEDIR调用NMAKE时的当前目录
MAKEFLAGS当前有效的选项(去掉/F),使用方法如下/S( MAKEFLAGS)

另外还有一些命令:

需要检测如果所需目录不存在,能够自动创建 @if not exist判断,用mkdir 创建目录

删除不需要的目录  使用@if exit判断,用rmdir /S /Q 删除目录

build的时候显示一些信息   @echo

INCLUDE_DIR = ..\include
OBJ_DIR_X86 = ..\obj_x86
BIN_DIR_X86 = ..\bin_x86
SRC_DIR = ..\src
EXE_NAME = step.exe

OBJ_FILES = \
	$(OBJ_DIR_X86)\main.obj \
	$(OBJ_DIR_X86)\printer.obj

{$(SRC_DIR)}.cpp{$(OBJ_DIR_X86)}.obj::
    @echo Compiling...	
    cl /c /EHsc /Fo$(OBJ_DIR_X86)\ /I$(INCLUDE_DIR) $<

$(EXE_NAME): $(OBJ_DIR_X86)\*.obj
	link /out:$(BIN_DIR_X86)\$(EXE_NAME) $(OBJ_FILES)

all: clean create_dirs $(EXE_NAME)

clean: 
	@echo "remove folders"
	@if exist $(BIN_DIR_X86) rmdir /S /Q $(BIN_DIR_X86)
	@if exist $(OBJ_DIR_X86) rmdir /S /Q $(OBJ_DIR_X86)

create_dirs:
	@echo "create folders"
	@if not exist $(BIN_DIR_X86) mkdir $(BIN_DIR_X86)
	@if not exist $(OBJ_DIR_X86) mkdir $(OBJ_DIR_X86)

{$(SRC_DIR)}.cpp{$(OBJ_DIR_X86)}.obj::
    @echo Compiling...    
    cl /c /EHsc /Fo$(OBJ_DIR_X86)\ /I$(INCLUDE_DIR) $< 

这里用到了批处理规则,两个冒号::  (http://msdn.microsoft.com/en-us/library/f2x0zs74.aspx)

#define macros
EXECUTABLE_NAME = HoriAndVerPro.exe
DIR_SRC = E:\test\projection\src
DIR_INCLUDE = \
        /I "D:\opencv\build\include"
       # /I "D:\vs2012\VC\include"
        
DIR_BIN = E:\test\projection\bin
DIR_BIN_X64 = $(DIR_BIN)\x64
DIR_INTERMEDIATE = E:\test\projection\intermediate
DIR_INTERMEDIATE_X64 = $(DIR_INTERMEDIATE)\x64

LIBDIRS = D:\opencv\build\x86\vc11\lib
LIBS = opencv_world300.lib 
LINKFLAGS = $(LIBDIRS) $(LIBS)


SRC_FILES= \
  $(DIR_SRC)\HoriAndVerPro.cpp
  
{$(DIR_SRC)}.cpp{$(DIR_INTERMEDIATE_X64)}.obj ::
#{$(DIR_INTERMEDIATE_X64)}.obj:$(SRC_FILES)
	@echo Compiling...
	cl /c /EHsc /Tp /Fo$(DIR_INTERMEDIATE_X64)\  $< $(DIR_INCLUDE)

$(EXECUTABLE_NAME) : $(DIR_INTERMEDIATE_X64)\*.obj
	@echo Linking $(EXECUTABLE_NAME)...
	link /out:$(DIR_BIN_X64)\$(EXECUTABLE_NAME)  $(DIR_INTERMEDIATE_X64)\*.obj /LIBPATH:$(LINKFLAGS)

# build application
HoriAndVerPro: $(EXECUTABLE_NAME)

# create output directories
create_dirs:
	@if not exist $(DIR_BIN_X64) mkdir $(DIR_BIN_X64)
	@if not exist $(DIR_INTERMEDIATE_X64) mkdir $(DIR_INTERMEDIATE_X64)

# delete output directories
clean:
	@if exist $(DIR_BIN) rmdir /S /Q $(DIR_BIN)
	@if exist $(DIR_INTERMEDIATE) rmdir /S /Q $(DIR_INTERMEDIATE)

# create directories and build application
all: clean create_dirs HoriAndVerPro

最后有一本书 精通windowsAPI 可以用来查阅一下,基本上内容都有。链接在这

链接:https://pan.baidu.com/s/1GAABUwkQlWq8S7bGxstPTA 
提取码:c1b0

windows下安装perl模块方法必备软件nmake dmake devcpp: 方式一: 将 nmake.exe 放到system32目录下 用一下方式: perl Makefile.pl nmake nmake test nmake install 如果成功,将不用看下面内容。 方式二: 手动编译方式 优点:通吃所有模块 缺点:有点麻烦 具体步骤:1安装编译器2设置编译器的环境变量3可能安装dmake 具体方法:如下 1.首先要有个c编译器,推荐dev-cpp(开源免费的,网上自己搜索),记得要下含有mingw的就是了(不懂c,下载含有mingw的因为这个版本的bin目录里有gcc.exe等工具). 1.1安装好了编译器之后,要能在cmd中以命令方式运行的话,必须要设置环境变量,在winxp中[我的电脑]->[属性]->[高级]->[环境变量]里设置,只需要在path里加个你路径,比如你的安装路径是c:\dev-cpp,那你就要加上c:\dev-cpp\bin (path中有很多其他的路径,之间记得用;隔开 )弄完好,在cmd中运行gcc -v 显示出内容表示编译器安装成功,并且可以用命令行编译. 2.编译步骤,在cpan上下载需要的模块,比如Win32::SerialPort,下载好了解压,在cmd中进入这个目录(简单的dos命令应该知道吧),就用常见的方法: perl Makefile.pl make make test make install 如果成功,将不用看下面内容。 方式三: 使用方式二make很可能会出现错误,不能编译,找了很多原因,有高人介绍了解决办法,就是下载一个叫dmake的工具,解压缩,将里面的dmake.exestartup的文件夹(好象是这个名字)一起复制到c:\dev-cpp\bin 里(因为这个目录注册到环境变量里的),之后安装改成: perl Makefile.pl dmake dmake test dmake install 注意: 如果安装过oracle10g你将会发现出现版本冲突的情况。 解决方案如下:修改%PERL5LIB%环境变量,修改为perl所在目录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值