【VS2017】 一个使用 cl 和 link 命令例子

编译脚本 build_windows_x86.bat

bash 复制代码
@echo off

:: 初始化 VS2017 x86 编译环境
call "%VS2017%\vcvars32.bat"
if errorlevel 1 (
    echo [ERROR] 无法初始化 VS2017 编译环境,请检查安装路径
    pause
    exit /b 1
)

:: 5. 编译测试程序 (必须 /MD + ENABLE_DEEP_PLC/DRED/OSCE)
echo [5/5] 编译测试程序 test_opus_plc_multi_dred.exe...
cl /c /Fotest_opus_plc_multi_dred.obj /nologo /MD /O2 ^
  /DENABLE_DEEP_PLC /DENABLE_DRED /DENABLE_OSCE ^
  .\test_opus_plc_multi_dred.c ^
  /I . /I include/opus
if errorlevel 1 goto error

link /OUT:test_opus_plc_multi_dred.exe ^
  test_opus_plc_multi_dred.obj .\libopus.lib
if errorlevel 1 goto error

echo.
echo ============================================
echo  编译完成!
echo  测试  : test_opus_plc_multi_dred.exe
echo ============================================
goto end

:error
echo.
echo [ERROR] 编译失败!
pause

:end

逐行解释这个完整的批处理文件,并结合提供的环境变量截图说明关键配置。


📄 完整代码解析

第 1 行:关闭命令回显

batch 复制代码
@echo off
  • 执行时不显示命令本身,只显示命令的输出结果
  • 让控制台输出更整洁

第 3-9 行:初始化 VS2017 编译环境

batch 复制代码
:: 初始化 VS2017 x86 编译环境
call "%VS2017%\vcvars32.bat"
if errorlevel 1 (
    echo [ERROR] 无法初始化 VS2017 编译环境,请检查安装路径
    pause
    exit /b 1
)
内容 说明
call 调用另一个批处理脚本,执行完后返回当前脚本继续
%VS2017% 系统环境变量,值来自您截图中的配置
vcvars32.bat VS2017 自带的 x86 环境初始化脚本
if errorlevel 1 如果初始化失败,显示错误并暂停
🔑 环境变量关联(您的截图)
复制代码
变量名:  VS2017
变量值:  C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build

所以实际调用的是:

复制代码
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvars32.bat"

vcvars32.bat 的作用:

  • 将 cl(编译器)、link(链接器)等工具添加到当前命令行的 PATH 中
  • 设置 INCLUDE、LIB 等环境变量
  • 这是必须的一步 ,否则直接运行 cl 会提示"找不到命令"

第 11-17 行:编译(生成目标文件)

batch 复制代码
:: 编译测试程序 (必须 /MD + ENABLE_DEEP_PLC/DRED/OSCE)
echo [5/5] 编译测试程序 test_opus_plc_multi_dred.exe...
cl /c /Fotest_opus_plc_multi_dred.obj /nologo /MD /O2 ^
  /DENABLE_DEEP_PLC /DENABLE_DRED /DENABLE_OSCE ^
  .\test_opus_plc_multi_dred.c ^
  /I . /I include/opus
if errorlevel 1 goto error

详细参数:

参数 含义
cl MSVC C/C++ 编译器
/c 只编译,不链接 (生成 .obj 文件)
/Fotest_opus_plc_multi_dred.obj 指定输出文件名
/nologo 不显示编译器版本横幅
/MD 使用多线程 DLL 运行时库(必须匹配 libopus.lib 的编译方式)
/O2 速度优化(Release 级别优化)
/DENABLE_DEEP_PLC 定义宏,启用 Deep PLC 代码块
/DENABLE_DRED 定义宏,启用 DRED 代码块
/DENABLE_OSCE 定义宏,启用 OSCE 功能
/I . 头文件搜索路径:当前目录
/I include/opus 头文件搜索路径:include/opus 子目录
^ 批处理续行符,将多行拼接成一条命令

执行结果:

复制代码
.\test_opus_plc_multi_dred.c  →  test_opus_plc_multi_dred.obj

第 19-21 行:链接(生成可执行文件)

batch 复制代码
link /OUT:test_opus_plc_multi_dred.exe ^
  test_opus_plc_multi_dred.obj .\libopus.lib
if errorlevel 1 goto error
参数 含义
link MSVC 链接器
/OUT:test_opus_plc_multi_dred.exe 指定输出可执行文件名
test_opus_plc_multi_dred.obj 上一步编译生成的目标文件
.\libopus.lib Opus 静态库文件(包含 opus_encode、opus_decode 等实现)

链接过程:

  • 将 .obj 中的代码与 libopus.lib 中的 Opus API 实现合并
  • 解析所有函数调用,生成最终的 .exe 文件

第 23-28 行:成功处理

batch 复制代码
echo.
echo ============================================
echo  编译完成!
echo  测试  : test_opus_plc_multi_dred.exe
echo ============================================
goto end
  • 打印成功信息
  • goto end 跳过错误处理代码,直接到脚本末尾结束

第 30-33 行:错误处理标签

batch 复制代码
:error
echo.
echo [ERROR] 编译失败!
pause
  • :error 是一个标签(Label)
  • 编译或链接失败时跳转到这里
  • pause 暂停,等待用户按任意键(方便查看错误信息)

第 35 行:脚本结束标签

batch 复制代码
:end
  • 空标签,作为 goto end 的跳转目标
  • 脚本执行到这里自然结束

🔄 执行流程图

复制代码
开始
  │
  ▼
初始化 VS2017 环境 (vcvars32.bat)
  │
  ├── 失败 ──→ 显示错误 ──→ pause ──→ 退出
  │
  ▼
编译 test_opus_plc_multi_dred.c
  │
  ├── 失败 ──→ :error 标签 ──→ 显示"编译失败" ──→ pause
  │
  ▼
链接 .obj + libopus.lib
  │
  ├── 失败 ──→ :error 标签 ──→ 显示"编译失败" ──→ pause
  │
  ▼
显示"编译完成!"
  │
  ▼
结束

⚠️ 关键注意事项

问题 说明
必须先设置 VS2017 环境变量 您截图中的配置是正确的,脚本依赖它
必须在 VS 开发者命令提示符中运行? 不需要 ,因为脚本自己会调用 vcvars32.bat 初始化环境
/MD 必须匹配 libopus.lib 必须用 /MD 编译,否则链接会报错
源文件路径 脚本假设 test_opus_plc_multi_dred.c 和 libopus.lib 与 .bat 同目录

💡 如果要手动执行

直接在普通 CMD 或 PowerShell 中运行:

cmd 复制代码
cd c:\Users\lijian\Desktop\opus\windows_x86
build_windows_x86.bat

不需要先打开"Developer Command Prompt",因为脚本内部已经做了环境初始化。


相关推荐
咸咸咸虾1 天前
Microsoft Visual Studio 历史版本与官方安装包链接汇总
ide·microsoft·visual studio
zuiyuewentian1 天前
借助 AI 在 Win11 上搭建 Rocky Linux:用 Visual Studio 直接调试 Linux 服务
linux·运维·visual studio
C++ 老炮儿的技术栈1 天前
Linux 动态库踩坑:明明重新编译了 .so,调用函数返回值却一直不变(libfjrobot.so 版本号异常排查实录)
linux·c语言·网络·c++·visual studio
H.莓飛2 天前
【数据结构】排序总结与规模实测
linux·服务器·开发语言·数据结构·visual studio·1024程序员节
夏虫不可与之言冰3 天前
RMT 与 WS2812 灯带:可寻址 RGB 全彩控制
c语言·c++·单片机·物联网·visual studio
起个名字都难啊3 天前
visual studio C/C++空项目修改为CUDA c++
c++·windows·visual studio
zl_dfq3 天前
Visual Studio 动态链接库(DLL)生成完全指南
visual studio
瑶池酒剑仙3 天前
C++变量初始化五法完全指南:默认/拷贝/直接/列表/值初始化与窄化转换陷阱(青云之志)
c语言·开发语言·数据结构·c++·算法·visual studio
霍霍的袁5 天前
【C++11】左值右值引用与移动语义详细笔记(左值右值、右值引用、移动构造、移动赋值、引用折叠、万能转发)
c++·笔记·学习·visual studio
H.莓飛5 天前
【数据结构】归并与外排序
linux·服务器·c语言·开发语言·数据结构·visual studio