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