Win32 SDK基础(2)—— 自己动手用cl.exe和link.exe编译和连接程序

本文通过一个简单的Windows对话框程序示例,详细讲解如何使用cl.exe和link.exe命令行工具进行源代码的编译与链接,最终生成可执行文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从程序的编译过程说起

    上一文我们介绍了windows系统下面程序的分类、编译器、连接器、常用头文件、库文件等知识。本文再谈一下程序的编译过程。

相信大家都知道源代码的编译过程共分为两个步骤:一是编译过程,主要工作是把我们的源代码翻译成中间文件,这在windows中就是cl.exe的作用,它将我们的.c文件或者.cpp文件翻译成中间.obj文件;二是连接过程,主要工作是将多种中间文件、库文件连接生成可执行文件,这在windows中就是link.exe的作用,它将.obj文件和库文件等链接成exe程序。

本文主要教大家摆脱VSIDE,用命令行的方式用cl.exelink.exe编译和链接程序。

编写我们的Test.c文件

    首先我们新建一个test.txt文件,然后重命名为text.c,在该文件中我们填写如下代码:

#include "windows.h"
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,  
                     _In_opt_ HINSTANCE hPrevInstance,  
                     _In_ LPWSTR    lpCmdLine,  
                     _In_ int       nCmdShow)   
{
  MessageBox(NULL,"Hello Win32","sdk",MB_ABORTRETRYIGNORE|MB_ICONERROR);
  return 0;
}

        #include "windows.h"导入了我们所需要所有windows系统下必须的头文件。然后我们引入了windows窗口程序的主函数wWinMain。这里简单解释下Winmain各个形参的作用:hInstance是当前程序的实例句柄,也就是目前程序所在的内存的位置;hPrevInstance当前程序前一个实例句柄,目前已经废弃;lpCmdLine是命令行参数,就是我们以命令行的方式执行程序时可以附带一些字符串作为参数;nCmdShow是窗口显示方式,最大化、最小化那种。我们在主函数中调用了MessageBox定义了一个模式对话框,如果编译成功,我们执行程序后将会弹出一个对话框。

现在Test.c文件已经编写完成,我们接下来要做的就是分别编译和链接文件。

编译Test.c

    我们将打开windowscmd命令行工具,然后切换到我们当前的工作目录,使用以下命令编译Test.c文件:

       Cl.exe /c test.c

 

 

    编译完成后会在工作目录下生成test.obj中间文件:

    如果你的命令行提示找不到cl.exe命令等诸如此类的信息,相信你应该明白这是环境变量中没有引入cl.exe所在的目录,我们可以先添加该环境变量或者使用全路径的方式进行引入。如果你生成了test.obj文件说明编译过程完成了,我们可以开始连接过程了。

四、链接生成test.exe

    接下来我们执行下面的命令生成可执行文件:

    Link.exe test.obj user32.lib

 

 

        User32.lib这个库我们在上一文中曾经提到过,它包含了所欲的用户界面、消息相关的API,我们的需要调用的MessageBox就在这个库里面定义,如果不出意外,你的工作目录下应该会生成test.exe这个可执行文件:


    双击这个exe,弹出了我们定义的对话框:


 

        OK,试验结束。我们完全脱离了VS带界面的IDE生成了一个自定义的对话框,是不是很神奇?此处应该有小岳岳那贱贱的表情。。。

Github位置:

https://github.com/HymanLiuTS/Win32SDK

克隆本项目:

git clone git@github.com:HymanLiuTS/Win32SDK.git

获取本文源代码:

git checkout WL02


 

<think>我们正在处理用户的问题:尽管cl.exe已经配置在PATH中,但系统仍然提示未找到MSVC工具集。我们需要参考用户提供的引用内容,尤其是引用[4]中提到的现象:配置了cl.exe的路径后,命令行可以识别cl命令,但编译时会报错。这表明环境变量配置不完整。 根据引用[1][2][3][4],我们可以分析: - 引用[4]明确指出:即使将cl.exe的路径添加到PATH中,并且cl.exe可以运行(显示帮助信息),但在实际编译时仍会报错,因为缺少其他必要的环境变量(如INCLUDELIB)。 - 引用[3]提到,除了PATH,还需要设置INCLUDE(包含头文件的目录)LIB(库文件的目录)环境变量。 因此,问题在于:仅仅将cl.exe的路径添加到PATH中是不够的,还需要设置INCLUDELIB环境变量,以告知编译器头文件库文件的路径。 解决方案步骤: 1. **确定MSVC工具集的安装路径**: 假设MSVC工具集安装在:`D:\VS2019\2019\VC\Tools\MSVC\14.29.30133`(根据引用[4]的路径示例)。 2. **设置环境变量**: - `PATH`:添加cl.exe所在的目录(如`D:\VS2019\2019\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64`)。 - `INCLUDE`:添加包含目录,该目录包含系统头文件(如`D:\VS2019\2019\VC\Tools\MSVC\14.29.30133\include`,以及Windows SDK的include目录)。 - `LIB`:添加库目录(如`D:\VS2019\2019\VC\Tools\MSVC\14.29.30133\lib\x64`,以及Windows SDK的lib目录)。 3. **注意Windows SDK的依赖**: MSVC工具集还需要Windows SDK的头文件库。因此,INCLUDELIB环境变量中还需要包含Windows SDK的路径。通常,Windows SDK安装在`C:\Program Files (x86)\Windows Kits\10`下,但具体版本可能不同。 4. **验证环境变量**: 在命令行中执行以下命令检查环境变量: ```cmd echo %PATH% echo %INCLUDE% echo %LIB% ``` 确保这些路径都存在。 5. **更可靠的方法:使用vcvarsall.bat**: 手动设置这些环境变量容易出错,特别是Windows SDK的路径可能随版本变化。因此,推荐使用Visual Studio自带的`vcvarsall.bat`脚本来设置环境。该脚本会自动设置所有必要的环境变量(包括PATH、INCLUDE、LIB等)。 使用方法: ```cmd call "D:\VS2019\2019\VC\Auxiliary\Build\vcvarsall.bat" x64 ``` 其中`x64`表示目标平台为64位,也可以使用`x86`(32位)或`arm`等。 6. **为什么cl.exe能运行但编译报错?** 因为cl.exe本身在PATH中,所以可以运行。但编译过程中需要头文件库文件,如果INCLUDELIB环境变量没有正确设置,编译器找不到这些文件,就会报错(如无法打开头文件、找不到库文件等)。 7. **引用[4]中的错误示例**: 用户提到“直接编译源码文件会报错”,常见的错误有: - `fatal error C1034: stdio.h: no include path set` - `LINK : fatal error LNK1104: cannot open file 'kernel32.lib'` 8. **永久配置(可选但不推荐)**: 如果确实需要在全局环境变量中配置,可以手动设置INCLUDELIB。但要注意,不同版本的MSVC工具集可能需要不同的SDK,全局设置可能导致版本冲突。因此,建议每次使用时通过vcvarsall.bat配置。 9. **多版本共存问题**: 如果安装了多个MSVC版本,确保vcvarsall.bat使用的cl.exe版本一致。 10. **在CMake中指定工具集**: 如果是在CMake中使用,可以在生成项目时指定工具集版本,例如: ```cmd cmake -G "Visual Studio 16 2019" -T v142 ... ``` 总结:用户的问题在于环境变量配置不完整。解决方法有两种: - 方法一(推荐):使用vcvarsall.bat脚本初始化环境(每次使用前运行)。 - 方法二:手动设置PATH、INCLUDELIB环境变量(注意包含Windows SDK路径)。 下面我们按照要求生成回答。</think>针对 `cl.exe` 已配置但 MSVC 工具集仍提示未找到的问题,核心原因是**环境变量配置不完整**。MSVC 编译需要三个关键环境变量协同工作,仅配置 `PATH`(`cl.exe` 路径)是不够的。以下是详细解决方案: --- ### **问题根源分析** 1. **`PATH` 已生效但编译失败** 如引用[4]所述,配置 `PATH` 后 `cl` 命令可识别,但编译时报错: ```bash fatal error C1034: stdio.h: no include path set LINK : fatal error LNK1104: cannot open file 'kernel32.lib' ``` - **原因**:缺少头文件路径(`INCLUDE`)库文件路径(`LIB`)环境变量[^4]。 2. **MSVC 工具集的依赖关系** | 环境变量 | 作用 | 缺失后果 | |----------|------|----------| | `PATH` | 定位 `cl.exe`, `link.exe` | 命令无法识别 | | `INCLUDE` | 指定头文件路径(如 `stdio.h`) | 找不到头文件 | | `LIB` | 指定库文件路径(如 `kernel32.lib`) | 链接失败 | --- ### **完整解决方案** #### 步骤 1:定位 MSVC 工具集安装路径 假设工具集安装在: ```bash D:\VS2019\2019\VC\Tools\MSVC\14.29.30133 ``` 需确认以下子目录存在: - `bin\Hostx64\x64` → `cl.exe` 位置 - `include` → 头文件目录 - `lib\x64` → 库文件目录 #### 步骤 2:配置系统环境变量 ```bash # 1. 添加 PATH (已部分完成) PATH += D:\VS2019\2019\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64 # 2. 新增 INCLUDE (关键缺失项) INCLUDE = D:\VS2019\2019\VC\Tools\MSVC\14.29.30133\include; C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt; # Windows SDK 头文件 # 3. 新增 LIB (关键缺失项) LIB = D:\VS2019\2019\VC\Tools\MSVC\14.29.30133\lib\x64; C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x64; # Windows SDK 库文件 ``` > 📌 注意:`Windows Kits` 路径需根据实际安装的 SDK 版本调整(检查 `C:\Program Files (x86)\Windows Kits\10`) #### 步骤 3:验证环境配置 ```bash # 检查环境变量 echo %PATH% echo %INCLUDE% echo %LIB% # 测试编译 cl /EHsc test.cpp ``` 成功标志: 1. 生成 `test.obj` `test.exe` 2. 无头文件或库文件报错 --- ### **备选方案:自动配置脚本(推荐)** 避免手动配置错误,使用 Visual Studio 自带的环境初始化脚本: ```batch :: 以管理员身份运行 CMD call "D:\VS2019\2019\VC\Auxiliary\Build\vcvarsall.bat" x64 ``` 此脚本自动设置 `PATH`, `INCLUDE`, `LIB` 等所有变量[^1]。可将此命令保存为 `msvc_env.bat`,编译前执行。 --- ### **常见问题排查** 1. **Windows SDK 路径不匹配** - 检查 SDK 版本:在 `C:\Program Files (x86)\Windows Kits\10\Include` 下确认子目录名 - 更新环境变量中的版本号(如 `10.0.19041.0` → `10.0.20348.0`) 2. **32/64 位混淆** - 编译 32程序:`LIB` `bin` 路径用 `x86` 替代 `x64` - 显式指定平台:`cl /EHsc /arch:IA32 test.cpp` 3. **多版本工具集冲突** 在 CMake 中显式指定工具集版本: ```bash cmake -G "Visual Studio 16 2019" -T v142 -A x64 .. ``` --- ### **永久生效配置(不推荐)** > ⚠️ 警告:全局修改可能引发版本冲突 1. 打开系统环境变量设置 2. 新建系统变量: - 变量名:`INCLUDE` - 变量值:`D:\VS2019\...\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt;...` 3. 新建系统变量: - 变量名:`LIB` - 变量值:`D:\VS2019\...\lib\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x64;...` --- ### 相关问题 1. 如何检查当前生效的 MSVC 工具集版本? 2. 多版本 Visual Studio 共存时如何切换工具集? 3. CMake 如何强制指定 Windows SDK 版本? 4. 为什么链接时会出现 `LNK1104: cannot open file 'ucrt.lib'` 错误? [^1]: 仅配置 PATH 会导致头文件库文件缺失,需完整设置 INCLUDE LIB [^4] [^2]: Windows SDK 路径必须与 MSVC 工具集兼容,版本不匹配是常见错误源 [^3]: 使用 `vcvarsall.bat` 可避免手动配置错误,是官方推荐方式 [^1]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值