以前使用 Visual Stdio 都是在 IDE 环境下。这两天编译 GSL 感觉用 IDE 环境特别不方便,所以就花了点时间简单学习了如何在命令行下使用 Visual Stdio C++ 编译器、连接器。
我个人对 gcc 还是比较熟悉的,所以这里的各种用法都做了 gcc 的类比,这样也便于记忆。
编译器 CL
Visual Stdio 中的 C/C++ 编译器都是同一个,叫做 CL。下面表格列出了一些基本的命令行选项。
CL | gcc | 说明 |
---|---|---|
/E | -E | 输出预处理结果 |
/Fa | -S | 输出汇编文件 |
/Za | -ansi | 禁止语言扩展,这两个还不是等价的 |
/Dname | -Dname | 定义一个宏,相对于在代码中添加了 #define name |
/Dname=value | -Dname=value | 定义一个宏,相对于在代码中添加了 #define name value |
/Wall | -Wall | 将所有的警告信息全开。 |
/Od | -O0 | 禁止优化 |
/O1 | -Os | 以最节省空间为目标优化 |
/O2 | -O2 | 以允许速度最快为目标优化 |
/Idirecotry | -Idirecotry | 指定头文件搜索路径 |
/c | -c | 生成目标文件 .obj, 不链接 |
/libpath:direcotry | -Ldirecotry | 指定库文件搜索路径(MSVC的/libpath属于链接选项,第一个链接选项之前要指定/link选项,用来告诉编译器驱动,后续选项传给链接器使用) |
/GR,/GR- | -frtti,-fno-rtti | 开启或关闭RTTI |
/link | -Wl | 链接指定的模块或给链接器传递参数 |
/LD | -shared | 编译产生DLL文件 |
/LDd | 编译产生DLL文件(调试版) | |
/MD | 与动态多线程版本运行库MSVCRT.LIB链接 | |
/MDd | 与调试版动态多线程版本运行库MSVCRTD.LIB链接 | |
/MT | 与静态多线程版本运行库LIBCMT.LIB链接 | |
/MTd | 与调试版静态多线程版本运行库LIBCMTD.LIB链接 |
除了这些,还有不少的命令行选项,不过一般用途来说,这些就够用了。
连接器 link
对应 gcc 工具链中的 ld。
link | ld | 说明 |
---|---|---|
/BASE:address | 指定输出文件的基地址 | |
/DEBUG | 输出调试模式版本 | |
/DEF:filename | 指定模块定义文件.DEF | |
/DEFAULTLIB:library | 指定默认运行库 | |
/DLL | –relocateable | 产生DLL |
/ENTRY:symbol | –entry=symbol | 指定程序入口 |
/EXPORT:symbol | 指定某个符号位导出符号 | |
/HEAP | 指定默认堆大小 | |
/LIBPATH:dir | 指定链接时库搜索路径 | |
/MAP:MAPFILE | -Map MAPFILE | 产生链接MAP文件 |
/NODEFAULTLIB | 禁止默认运行库 | |
/OUT:name | -o name | 指定输出文件名为 name |
/STACK | 指定默认栈大小 | |
/SUBSYSTEM | 指定子系统,常见选项是 windows 和 console |
生成静态库. lib
lib 可以将一系列的 obj 文件打包为一个静态库 .lib。也可以将几个 .lib 合成一个 .lib。或者将几个 .obj 和 .lib 合成一个 .lib。
比如我们有 add.obj sub.obj div.lib 这三个文件,我们想将他们合成为一个 all.lib。
那么可以这样:
lib add.obj sub.obj div.lib /out:all.lib
如果要将这三个文件合并为一个 all.dll 那么我们还需要个 .def 文件。里面给出哪些符号要导出。
类似下面这个样子:
LIBRARY all.dll
EXPORTS
add
sub
div
之后执行 link 命令:
link /SUBSYSTEM:windows /dll /def:all.def /out:all.dll add.obj sub.obj div.lib