MSVC编译环境介绍

简介: MSVC编译环境介绍

MSVC 是 windows 比较早期的编译工具链,这个工具链主要有 两个软件, cl.exe (编译器) 跟 link.exe(链接器)。

这两个 软件 通常集成在 vs2019 里面。点击 vs2019 菜单栏 Tool → Get Toole and Feature ,如下:

安装上 MSVC 之后,需要找到 x64 Native Tools Command Prompt for VS 2019,这个是 vs2019 的CMD,用这个 CMD 启动命令行会有 vs2019 的环境变量。

打开后,可以使用 where 查询 cl.exe 跟 link.exe 的位置。如下:



下面就来使用一下 cl 跟 link 来编译 C 代码,其实这两个软件 跟 之前在 Linux 环境用 gcc 是类似的。都是单个文件编译,把 C程序 编译成 字节码,然后用链接器把多个字节码文件链接在一起。

还是以 之前的单文件项目 c-single 为例,hello.c 代码如下:

#include <stdio.h>
int main()
{
    printf("hello ffmpeg \r\n");
    return 0;
}

我在 D 盘 创建了 c-single 文件夹,把 hello.c 放在里面。然后在 vs2019 的CMD 里面使用 cl.exe 编译这个文件。如下:

cl.exe /c /Fohello.obj hello.c

上面命令中的 /c 跟 linux gcc 的 -c 一样,都是只编译,不进行链接操作。cl.exe 的选项 习惯都是 / 开头的,而 gcc 的选项是 以 - 开头。

目前 cl.exe 也支持 -c 的写法。

/Fo 这个选项是指定输出的 目标文件名。

Windows 平台编译过程通常会遇到 有 3种 后缀的文件。

1,.obj 后缀,这是目标文件。

2,.lib 后缀,这个是静态库,或者是 动态库的 import 库。

3,.dll 后缀,动态库。

Windows 的动态库跟 Linux 的动态库不太一样,Linux 是把所有信息都放在 so 文件里面,而 Windows 把 import 导入信息单独放在 lib 文件来 让编译阶段能找到关联关系,实现隐式调用动态库。

因此,Windows 的dll 动态库,在编译以及链接阶段 都不需要使用,只有程序运行的时候才需要。编译以及链接阶段需要用到动态库的 import 库即可。

而 Linux 的 so 动态库,我们在编译的时候要指定so文件,运行的时候也要指定so文件,因为他所有信息都放在一起了。


无论是 .obj,.lib,.dll 其实他们的文件格式都是 COFF 格式。而Windows的 PE 格式 跟 Linux 的ELF 格式 都是基于 COFF 格式发展来的。

exe 文件就是 PE 格式。PE 跟 ELF 有很多相似之处,都是基于段的结构。


我们已经编译出来 hello.obj 目标文件了,怎么查看里面的内容呢?Windows 提供了 跟 Linux 的 objdump 类似的工具 dumpbin

我们查看一下 hello.obj 里面的汇编代码,命令如下:

dumpbin /DISASM hello.obj

从上图可以看到,printf 的地址也是没有修正的。

不过 dumpbin 是命令行工具,对于初学者还是不太优好,这里推荐 PEview 跟 HxD 来查看 PE/COFF 文件。


回到 本文主题,hello.obj 已经出来了,下面就到 链接阶段,因为 hello.c 是 C 程序,所以跟 Linux 类似,需要链接 C运行时库。命令如下:

link.exe /DEBUG /OUT:hello.exe hello.obj

/OUT: 是指定输出文件名。

我们想知道 这个 hello.exe 链接的 C运行时是动态的还是静态的,可以使用 dumpbin 命令来查看,如下:

提醒: Dependencies 工具查看动态库依赖不太准,还是用 dumpbin 靠谱。

dumpbin /dependents hello.exe

在 Windows 平台, C运行时库是 libcmt.lib (静态库) 跟 msvcrt.dll (动态库),因为上图没出现 msvcrt.dll ,所以 hello.exe 默认是静态链接 C运行时库。


那么有什么方法 可以让 hello.exe 动态链接 C运行时库呢?使用 /MD 选项即可。如下:

cl.exe /c /MD /Fohello-md.obj hello.c
link.exe /DEBUG /OUT:hello-md.exe hello-md.obj
dumpbin /dependents hello-md.exe

Windows 指定 动态还是静态,是在编译阶段指定的,编译阶段指定之后会保存 链接信息进 obj 文件的 .drectv 段,然后 链接阶段就会取这些信息。如下:

如果要静态链接 C运行时库,可以使用 /MT ,这个是默认值。


扩展知识:hello.c 的代码其实也是跨平台的,linux 跟 windows 都可以编译,不需要改动源代码。大家可能经常听说 C++ 的跨平台比较好,但实际上,C语言的很多语法函数,目前也是可以跨平台使用的。

任何一门技术,刚出来的时候,都是混乱的,包括C语言。20世纪70年代C语言变得非常流行时,许多大学、公司和组织都自发地编写自己的C语言变种和基础函数库,因此当到了80年代时,C语言已经出现了大量的变种和多种不同的基础函数库,这对代码迁移等方面造成了巨大的障碍。

因此 美国国家标准协会 成立了一个委员会,建立了 ANSI C 标准,也就是后来的 C89 标准。标准定义了 C运行时库的一些行为。

printf 这个函数 是C运行时库里面的函数,C 运行时库屏蔽了不同的 系统实现,提供统一的函数给上层用,例如 windows 下的 printf 的内部实现 其实是跟 Linux 的 printf 不太一样的。windows 调的是 win32 API 函数。

参考资料:

1,《link 链接器选项》


目录
相关文章
|
10月前
|
IDE 开发工具 开发者
仓颉开发语言入门教程:搭建开发环境
仓颉开发语言是华为为鸿蒙系统自主研发的编程语言,肩负重要使命。本文介绍如何从零搭建仓颉开发环境,重点演示在DevEco Studio中安装插件、配置项目及运行Hello World示例,助力开发者快速上手。
|
12月前
|
数据挖掘 BI
|
9月前
|
机器学习/深度学习 JSON 监控
拼多多API库存预警系统:避免缺货损失千万!
在电商运营中,缺货可能导致订单流失与经济损失,拼多多推出的API库存预警系统可实时监控库存,及时预警,降低缺货风险。系统支持多语言集成,商家可快速构建自动化监控与补货流程,提升供应链效率,保障销售连续性。
684 0
|
存储 Prometheus 监控
InfluxDB和 Prometheus
【5月更文挑战第13天】InfluxDB和 Prometheus
1152 10
|
存储 机器学习/深度学习 缓存
如何使用PySpark进行离线数据分析?
【6月更文挑战第15天】如何使用PySpark进行离线数据分析?
318 10
|
机器学习/深度学习 前端开发 JavaScript
230+本图灵编程高清文字版无水印电子书合集【制作不易,点赞收藏❤️】
今日精选,200余本图灵出版的高质量编程电子书,覆盖编程、系统架构、算法及机器学习等热门领域,助你全面提升技术能力。无论你是初学者还是资深开发者,都能从中找到适合自己的学习资源,从《Python编程:从入门到实践》到《深度学习入门》,每一本书都将是你技术成长道路上的良师益友,帮助你在瞬息万变的技术浪潮中站稳脚跟,稳步前行。
707 2
|
编译器 C语言 C++
MinGW安装gcc
MinGW安装gcc
557 0
|
安全 开发者 流计算
python中的deque详解
`deque`是Python中功能强大且灵活的双端队列,提供了高效的双端操作,适用于多种实际应用场景。通过详细了解 `deque`的基本特性和常见操作,开发者可以更好地利用这一数据结构来提高代码的性能和可读性。希望本文对你在Python编程中使用 `deque`有所帮助。
927 0
|
存储 关系型数据库 数据库
PostGIS简介
PostGIS是PostgreSQL的扩展插件,增强其处理地理空间数据的能力,支持空间数据存储、索引、查询及分析等功能。它适用于2D和3D空间数据,提供多种几何类型和栅格数据支持,兼容多种第三方工具。安装需先配置EPEL和PowerTools仓库,然后通过DNF安装PostGIS包,并在目标数据库中启用扩展。PostGIS支持geometry、geography和raster等数据类型,适用于不同场景的空间数据分析。
1066 0
|
机器学习/深度学习 算法
基于VMD-SSA-LSTM的多维时序光伏功率预测
基于VMD-SSA-LSTM的多维时序光伏功率预测

热门文章

最新文章