前言
在 Windows 平台上开发 C++ 程序时,Microsoft Visual C++ (MSVC) 提供了强大的编译工具集,其中最核心的命令行编译工具是 cl.exe。本文将详细介绍如何使用 cl.exe 手动编译和链接 C++ 程序,帮助开发者理解其基本用法和常见选项。
![]()
1. 准备环境
在使用 cl.exe 之前,需要确保已安装 Visual Studio,并配置好开发环境。可以通过以下步骤设置命令行编译环境:
打开 Visual Studio Installer,确保安装了“Desktop development with C++”工作负载。
通过 Visual Studio 命令提示符进入开发环境。可以在开始菜单中找到“x64 Native Tools Command Prompt for VS 2022”或类似的命令提示符。
2. 基本使用方法
2.1 编译单个源文件
最基本的使用方法是编译单个 C++ 源文件。假设有一个名为 hello.cpp 的源文件,可以通过以下命令进行编译:
powershell
cl.exe /EHsc .\hello.cppMicrosoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved.hello.cppMicrosoft (R) Incremental Linker Version 14.40.33811.0Copyright (C) Microsoft Corporation. All rights reserved./out:hello.exehello.obj
此命令将生成一个名为 hello.exe 的可执行文件。选项 /EHsc 用于启用 C++ 异常处理。
2.2 编译并生成目标文件
有时需要将源文件编译为目标文件而不是直接生成可执行文件。这可以通过 /c 选项实现:
bash
cl.exe /EHsc /c .\hello.cppMicrosoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved.hello.cpp
此命令将生成一个名为 hello.obj 的目标文件。
2.3 链接目标文件
可以使用 link.exe 工具将目标文件链接为可执行文件。但在命令行中,也可以直接使用 cl.exe 完成这一步:
bash
cl.exe .\hello.objMicrosoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved.Microsoft (R) Incremental Linker Version 14.40.33811.0Copyright (C) Microsoft Corporation. All rights reserved./out:hello.exe.\hello.obj
这将生成 hello.exe 可执行文件。
3. 常见编译选项
cl.exe 提供了许多选项以控制编译过程。以下是一些常见的编译选项:
/Fe:指定输出文件名。例如,cl /Feoutput.exe hello.cpp 将输出文件命名为 output.exe。
/Fo:指定目标文件名。例如,cl /Fohello.obj /c hello.cpp 将目标文件命名为 hello.obj。
/I:指定头文件搜索路径。例如,cl /Ipath\to\headers hello.cpp。
/D:定义预处理器宏。例如,cl /DDEBUG hello.cpp 定义 DEBUG 宏。
/O2:优化生成代码以提高运行速度。
/Zi:生成调试信息。
cl.exe /?Microsoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved. C/C++ COMPILER OPTIONS -OPTIMIZATION-/O1 maximum optimizations (favor space) /O2 maximum optimizations (favor speed)/Ob<n> inline expansion (default n=0) /Od disable optimizations (default)/Og enable global optimization /Oi[-] enable intrinsic functions/Os favor code space /Ot favor code speed/Ox optimizations (favor speed) /Oy[-] enable frame pointer omission/favor:<blend|ATOM> select processor to optimize for, one of: blend - a combination of optimizations for several different x86 processors ATOM - Intel(R) Atom(TM) processors -CODE GENERATION-/Gu[-] ensure distinct functions have distinct addresses/Gw[-] separate global variables for linker/GF enable read-only string pooling /Gy[-] separate functions for linker/GS[-] enable security checks /GR[-] enable C++ RTTI/guard:cf[-] enable CFG (control flow guard)/guard:ehcont[-] enable EH continuation metadata (CET)/EHs enable C++ EH (no SEH exceptions) /EHa enable C++ EH (w/ SEH exceptions)/EHc extern "C" defaults to nothrow/EHr always generate noexcept runtime termination checks/fp:<contract|except[-]|fast|precise|strict> choose floating-point model: contract - consider floating-point contractions when generating code except[-] - consider floating-point exceptions when generating code fast - "fast" floating-point model; results are less predictable precise - "precise" floating-point model; results are predictable strict - "strict" floating-point model (implies /fp:except)/Qfast_transcendentals generate inline FP intrinsics even with /fp:except/Qspectre[-] enable mitigations for CVE 2017-5753/Qpar[-] enable parallel code generation/Qpar-report:1 auto-parallelizer diagnostic; indicate parallelized loops/Qpar-report:2 auto-parallelizer diagnostic; indicate loops not parallelized/Qvec-report:1 auto-vectorizer diagnostic; indicate vectorized loops/Qvec-report:2 auto-vectorizer diagnostic; indicate loops not vectorized/GL[-] enable link-time code generation/volatile:<iso|ms> choose volatile model: iso - Acquire/release semantics not guaranteed on volatile accesses ms - Acquire/release semantics guaranteed on volatile accesses
4. 实践示例
4.1 编译多个源文件
假设有两个源文件 main.cpp 和 utils.cpp,可以使用以下命令编译并链接它们:
bash
cl /EHsc main.cpp utils.cpp
这将生成一个名为 main.exe 的可执行文件。
4.2 使用预编译头
预编译头可以显著加快编译速度。以下是如何使用预编译头的示例:
创建一个名为 pch.h 的头文件,并在其中包含常用的头文件:
cpp
// pch.h#include <iostream>#include <vector>
创建一个名为 pch.cpp 的源文件,仅包含对 pch.h 的引用:
cpp
// pch.cpp#include "pch.h"
使用以下命令生成预编译头:
bash
cl /EHsc /Yc"pch.h" pch.cpp
在其他源文件中使用预编译头,例如在 main.cpp 中:
cpp
// main.cpp#include "pch.h"int main() { std::cout << "Hello, World!" << std::endl; return 0;}
编译时使用预编译头:
bash
cl /EHsc /Yu"pch.h" main.cpp
5. 总结
通过本文的介绍,相信读者已经掌握了如何使用 cl.exe 手动编译和链接 C++ 程序的基本方法。cl.exe 提供了丰富的选项以满足不同的编译需求,熟练掌握这些选项可以显著提高开发效率。
在 Windows 平台上开发 C++ 程序时,Microsoft Visual C++ (MSVC) 提供了强大的编译工具集,其中最核心的命令行编译工具是 cl.exe。本文将详细介绍如何使用 cl.exe 手动编译和链接 C++ 程序,帮助开发者理解其基本用法和常见选项。
1. 准备环境
在使用 cl.exe 之前,需要确保已安装 Visual Studio,并配置好开发环境。可以通过以下步骤设置命令行编译环境:
打开 Visual Studio Installer,确保安装了“Desktop development with C++”工作负载。
通过 Visual Studio 命令提示符进入开发环境。可以在开始菜单中找到“x64 Native Tools Command Prompt for VS 2022”或类似的命令提示符。
2. 基本使用方法
2.1 编译单个源文件
最基本的使用方法是编译单个 C++ 源文件。假设有一个名为 hello.cpp 的源文件,可以通过以下命令进行编译:
powershell
cl.exe /EHsc .\hello.cppMicrosoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved.hello.cppMicrosoft (R) Incremental Linker Version 14.40.33811.0Copyright (C) Microsoft Corporation. All rights reserved./out:hello.exehello.obj
此命令将生成一个名为 hello.exe 的可执行文件。选项 /EHsc 用于启用 C++ 异常处理。
2.2 编译并生成目标文件
有时需要将源文件编译为目标文件而不是直接生成可执行文件。这可以通过 /c 选项实现:
bash
cl.exe /EHsc /c .\hello.cppMicrosoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved.hello.cpp
此命令将生成一个名为 hello.obj 的目标文件。
2.3 链接目标文件
可以使用 link.exe 工具将目标文件链接为可执行文件。但在命令行中,也可以直接使用 cl.exe 完成这一步:
bash
cl.exe .\hello.objMicrosoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved.Microsoft (R) Incremental Linker Version 14.40.33811.0Copyright (C) Microsoft Corporation. All rights reserved./out:hello.exe.\hello.obj
这将生成 hello.exe 可执行文件。
3. 常见编译选项
cl.exe 提供了许多选项以控制编译过程。以下是一些常见的编译选项:
/Fe:指定输出文件名。例如,cl /Feoutput.exe hello.cpp 将输出文件命名为 output.exe。
/Fo:指定目标文件名。例如,cl /Fohello.obj /c hello.cpp 将目标文件命名为 hello.obj。
/I:指定头文件搜索路径。例如,cl /Ipath\to\headers hello.cpp。
/D:定义预处理器宏。例如,cl /DDEBUG hello.cpp 定义 DEBUG 宏。
/O2:优化生成代码以提高运行速度。
/Zi:生成调试信息。
cl.exe /?Microsoft (R) C/C++ Optimizing Compiler Version 19.40.33811 for x86Copyright (C) Microsoft Corporation. All rights reserved. C/C++ COMPILER OPTIONS -OPTIMIZATION-/O1 maximum optimizations (favor space) /O2 maximum optimizations (favor speed)/Ob<n> inline expansion (default n=0) /Od disable optimizations (default)/Og enable global optimization /Oi[-] enable intrinsic functions/Os favor code space /Ot favor code speed/Ox optimizations (favor speed) /Oy[-] enable frame pointer omission/favor:<blend|ATOM> select processor to optimize for, one of: blend - a combination of optimizations for several different x86 processors ATOM - Intel(R) Atom(TM) processors -CODE GENERATION-/Gu[-] ensure distinct functions have distinct addresses/Gw[-] separate global variables for linker/GF enable read-only string pooling /Gy[-] separate functions for linker/GS[-] enable security checks /GR[-] enable C++ RTTI/guard:cf[-] enable CFG (control flow guard)/guard:ehcont[-] enable EH continuation metadata (CET)/EHs enable C++ EH (no SEH exceptions) /EHa enable C++ EH (w/ SEH exceptions)/EHc extern "C" defaults to nothrow/EHr always generate noexcept runtime termination checks/fp:<contract|except[-]|fast|precise|strict> choose floating-point model: contract - consider floating-point contractions when generating code except[-] - consider floating-point exceptions when generating code fast - "fast" floating-point model; results are less predictable precise - "precise" floating-point model; results are predictable strict - "strict" floating-point model (implies /fp:except)/Qfast_transcendentals generate inline FP intrinsics even with /fp:except/Qspectre[-] enable mitigations for CVE 2017-5753/Qpar[-] enable parallel code generation/Qpar-report:1 auto-parallelizer diagnostic; indicate parallelized loops/Qpar-report:2 auto-parallelizer diagnostic; indicate loops not parallelized/Qvec-report:1 auto-vectorizer diagnostic; indicate vectorized loops/Qvec-report:2 auto-vectorizer diagnostic; indicate loops not vectorized/GL[-] enable link-time code generation/volatile:<iso|ms> choose volatile model: iso - Acquire/release semantics not guaranteed on volatile accesses ms - Acquire/release semantics guaranteed on volatile accesses
4. 实践示例
4.1 编译多个源文件
假设有两个源文件 main.cpp 和 utils.cpp,可以使用以下命令编译并链接它们:
bash
cl /EHsc main.cpp utils.cpp
这将生成一个名为 main.exe 的可执行文件。
4.2 使用预编译头
预编译头可以显著加快编译速度。以下是如何使用预编译头的示例:
创建一个名为 pch.h 的头文件,并在其中包含常用的头文件:
cpp
// pch.h#include <iostream>#include <vector>
创建一个名为 pch.cpp 的源文件,仅包含对 pch.h 的引用:
cpp
// pch.cpp#include "pch.h"
使用以下命令生成预编译头:
bash
cl /EHsc /Yc"pch.h" pch.cpp
在其他源文件中使用预编译头,例如在 main.cpp 中:
cpp
// main.cpp#include "pch.h"int main() { std::cout << "Hello, World!" << std::endl; return 0;}
编译时使用预编译头:
bash
cl /EHsc /Yu"pch.h" main.cpp
5. 总结
通过本文的介绍,相信读者已经掌握了如何使用 cl.exe 手动编译和链接 C++ 程序的基本方法。cl.exe 提供了丰富的选项以满足不同的编译需求,熟练掌握这些选项可以显著提高开发效率。