使用cl.exe在windows控制台下编译C++程序

本文介绍如何使用Visual Studio中的cl.exe、link.exe、rc.exe和lib.exe工具进行DLL的编译与链接过程,并提供了配置环境变量的方法。

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

工具

cl.exe 是控制 Microsoft C 和 C++ 编译器与链接器的 32 位工具。编译器将.cpp编译,生成中间代码目标文件(.obj)。链接器将目标文件链接,产生可执行文件 (.exe) 或动态链接库文件 (DLL)。

link.exe 是将目标文件和库链接起来以创建 32 位可执行 (.exe) 文件或动态链接库 (DLL) 的 32 位工具。

rc.exe 是将windows资源文件(.rc)编译成资源文件(.res),从而与目标文件链接,一般用于设置exe文件的图标和属性或者dll包含的资源。

lib.exe是将目标文件链接生成静态库文件(.lib),也可以用于生成dll的lib文件。

环境配置

那么这4个exe文件在哪个目录下呢?我的vs装在了E盘,然后我在 E:\vs2013\VC\bin 目录下找到了cl.exe,link.exe,lib.exe,但是没找到rc.exe,于是我在C盘看了看,结果在C:\Program Files (x86)\Windows Kits\8.1\bin\x64 目录下找到了,后来我又发现这些exe似乎不止一份,在很多目录下都有,真奇怪。。。好吧,找到了后把所在目录加入Path环境变量就可以了。

光这样还不行,还得把一些头文件和lib库也加入环境变量,目录如下:

//这4个加入INCLUDE环境变量
E:\vs2013\VC\include;
C:\Program Files (x86)\Windows Kits\8.1\include\shared 
C:\Program Files (x86)\Windows Kits\8.1\include\um 
C:\Program Files (x86)\Windows Kits\8.1\include\winrt

//这2个加入LIB环境变量
E:\vs2013\VC\lib
C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x64

使用

以生成dll为例:

  1. 先用cl命令将.cpp编译成.obj,-c选项的作用:只编译不链接,不然cl还会试图链接生成exe,但dll工程根本没有main函数,没法生成exe,所以就会出错了。
    cl -c dllmain.cpp dllclass.cpp
  2. 如果有资源文件(.rc),那么用rc.exe将.rc编译成.res
    rc dllsource.rc
  3. 用link命令将.obj .rc等文件 链接,生成dll文件及对应的.lib .exp
    link -dll dllmain.obj dllclass.obj dllsource.res

更多详细内容

cl.exe命令参数详解
cl&link用法
msdn在命令行上编译C++程序

<think>我们遇到了一个更具体的问题:在安装了VC++2013运行后,运行mysqld.exe时提示“无法定位程序输入点fesetround于动态链接MSVCR120.dll上”。这通常意味着我们使用的msvcr120.dll版本不包含这个函数(fesetround),可能是由于使用了不兼容的版本(比如来自不同系统或版本不对)。原因分析:1.fesetround函数是C99标准中定义在fenv.h中的一个函数,用于设置浮点舍入模式。2.某些版本的VC++2013运行可能没有包含这个函数(特别是早期版本),或者我们使用DLL文件被损坏或不完整。3.可能系统中存在多个msvcr120.dll,而程序加载了错误的版本(比如来自其他应用程序的旧版本)。解决方案:1.重新安装正确版本的VC++2013运行(确保是最新版本)。2.检查系统中是否存在多个msvcr120.dll,并确保程序加载的是正确的版本。3.手动替换msvcr120.dll为正确版本。以下是详细步骤和代码:解决方案1:重新安装VC++2013运行(最新版)从微软官方下载最新版的VC++2013运行并安装。解决方案2:检查并修复DLL版本我们可以编写一个PowerShell脚本来检查系统中所有msvcr120.dll的版本,并确保MySQL使用的是正确的版本。```powershell#查找系统中所有msvcr120.dll文件$dllFiles=Get-ChildItem-Path"C:\"-Recurse-Filter"msvcr120.dll"-ErrorActionSilentlyContinue#输出每个文件的版本信息$dllFiles|ForEach-Object{$versionInfo=(Get-Item$_.FullName).VersionInfoWrite-Host"Path:$($_.FullName)"Write-Host"FileVersion:$($versionInfo.FileVersion)"Write-Host"ProductVersion:$($versionInfo.ProductVersion)"Write-Host"--------------------------------"}#检查MySQL目录下的msvcr120.dll版本$mysqlDll="C:\MySQL\bin\msvcr120.dll"if(Test-Path$mysqlDll){$mysqlVersion=(Get-Item$mysqlDll).VersionInfoWrite-Host"MySQL使用的msvcr120.dll版本:$($mysqlVersion.FileVersion)"}else{Write-Host"MySQL目录下未找到msvcr120.dll"}#如果版本不对,则从系统目录复制正确的版本$systemDll="C:\Windows\System32\msvcr120.dll"if(Test-Path$systemDll){$sysVersion=(Get-Item$systemDll).VersionInfoif($sysVersion.FileVersion-like"12.0.*"){#复制到MySQL目录Copy-Item-Path$systemDll-Destination$mysqlDll-ForceWrite-Host"已将系统目录下的msvcr120.dll复制到MySQL目录"}}else{Write-Host"系统目录下未找到msvcr120.dll,请重新安装VC++2013运行"}```解决方案3:使用DependencyWalker工具分析使用DependencyWalker(depends.exe)检查mysqld.exe的依赖关系,查看msvcr120.dll是否被正确加载,以及是否包含fesetround函数。解决方案4:手动下载正确的msvcr120.dll如果系统目录下的DLL也不包含该函数,我们可以从微软官方或可信来源下载正确版本的DLL。注意:从非官方来源下载DLL存在安全风险,建议从微软官方安装运行。解决方案5:更新Windows系统某些情况下,Windows更新会提供运行的更新。运行WindowsUpdate,确保系统是最新的。解决方案6:使用DLL导出函数检查工具我们可以编写一个C#程序来检查msvcr120.dll是否包含fesetround函数。```csharpusingSystem;usingSystem.Runtime.InteropServices;classDllChecker{[DllImport("kernel32.dll",SetLastError=true)]publicstaticexternIntPtrLoadLibrary(stringdllToLoad);[DllImport("kernel32.dll",SetLastError=true)]publicstaticexternIntPtrGetProcAddress(IntPtrhModule,stringprocedureName);staticvoidMain(string[]args){stringdllPath=args.Length>0?args[0]:"msvcr120.dll";IntPtrpDll=LoadLibrary(dllPath);if(pDll==IntPtr.Zero){Console.WriteLine($"无法加载{dllPath}");return;}string[]functions={"fesetround","fesetexceptflag","feholdexcept","feclearexcept"};foreach(varfuncinfunctions){IntPtrpAddress=GetProcAddress(pDll,func);Console.WriteLine($"{func}地址:{(pAddress!=IntPtr.Zero?"存在":"不存在")}");}}}```将上述代码保存为`CheckDllExports.cs`,然后编译运行:```cmdcscCheckDllExports.csCheckDllExports.exe"C:\Windows\System32\msvcr120.dll"```如果输出显示fesetround不存在,则说明该DLL版本不包含此函数,需要更新。解决方案7:使用兼容的MySQL版本如果以上方法都无法解决,考虑升级MySQL到新版本(如8.0),因为新版本可能使用更新的VC++运行(如VC++2019)。解决方案8:在MySQL目录下放置包含fesetround的msvcr120.dll我们可以从另一台安装了完整VC++2013且运行正常的电脑上复制msvcr120.dll到MySQL的bin目录。注意:要确保复制的DLL版本与系统架构(x64)一致。最后,我们可以尝试从微软官方下载VC++2013运行的离线安装包,然后重新安装:下载地址:https://aka.ms/vc12redist对于x64系统,下载:vcredist_x64.exe安装命令:```cmdvcredist_x64.exe/install/quiet/norestart```如果问题依旧,可能需要考虑系统文件损坏,运行sfc/scannow修复。§§相关问题§§:1.如何编程检测一个DLL文件是否包含特定的导出函数?2.Windows系统中,应用程序加载DLL的搜索顺序是怎样的?3.如何避免不同应用程序之间的DLL版本冲突?4.编译C++程序时,如何静态链接运行以避免此类问题?</think>### 解决 "无法定位程序输入点 fesetround" 错误的专业方案 这个错误表明您安装的 MSVCR120.dll 版本与 MySQL 所需的版本不匹配,具体缺少 `fesetround` 函数(浮点环境操作函数)。以下是完整的解决方案: #### 原因分析 1. MySQL 5.7 需要完整版的 VC++ 2013 运行(版本 12.0.21005.1) 2. 系统安装的可能是精简版或损坏的 DLL 3. 某些系统更新会替换关键 DLL 4. 浮点运算函数在部分定制版 Windows 中被移除 #### 解决方案 1:安装正确的 VC++ 2013 运行 ```powershell # 下载官方完整版 VC++ 2013 运行 $vc2013Url = "https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe" $installerPath = "$env:TEMP\vcredist_x64_2013_full.exe" # 下载并安装 Invoke-WebRequest -Uri $vc2013Url -OutFile $installerPath Start-Process -FilePath $installerPath -ArgumentList "/install", "/quiet", "/norestart" -Wait # 验证 DLL 版本 $dllPath = "$env:windir\System32\msvcr120.dll" $dllVersion = (Get-Item $dllPath).VersionInfo.FileVersion if ($dllVersion -eq "12.0.21005.1") { Write-Host "已安装正确版本: $dllVersion" -ForegroundColor Green } else { Write-Host "版本不匹配: $dllVersion" -ForegroundColor Red } ``` #### 解决方案 2:手动替换正确的 DLL ```powershell # 从微软服务器下载正确的 DLL $dllFiles = @{ "msvcr120.dll" = "https://aka.ms/vs/17/release/VC_redist.x64.exe" } # 临时目录 $tempDir = "$env:TEMP\vc_dll_fix" New-Item -Path $tempDir -ItemType Directory -Force | Out-Null # 下载并提取 DLL foreach ($dll in $dllFiles.Keys) { $exePath = "$tempDir\vc_redist.exe" Invoke-WebRequest -Uri $dllFiles[$dll] -OutFile $exePath # 使用 7zip 提取 DLL if (-not (Get-Command 7z -ErrorAction SilentlyContinue)) { choco install 7zip -y --force } & 7z e $exePath -o"$tempDir" -y "*.dll" | Out-Null # 替换系统 DLL(需要 TrustedInstaller 权限) $sourceDll = Get-ChildItem -Path "$tempDir" -Filter $dll | Select-Object -First 1 if ($sourceDll) { Takeown-File -Path "$env:windir\System32\$dll" icacls "$env:windir\System32\$dll" /grant "$env:USERDOMAIN\$env:USERNAME:(F)" Copy-Item -Path $sourceDll.FullName -Destination "$env:windir\System32\$dll" -Force Write-Host "已替换 $dll" -ForegroundColor Green } } # Takeown-File 函数定义 function Takeown-File($Path) { takeown.exe /F $Path $acl = Get-Acl $Path $acl.SetOwner([System.Security.Principal.NTAccount]"$env:USERDOMAIN\$env:USERNAME") Set-Acl -Path $Path -AclObject $acl } ``` #### 解决方案 3:创建私有 DLL 绑定 ```powershell # 在 MySQL 目录创建私有 DLL 副本 $mysqlBin = "C:\MySQL\bin" $requiredDlls = @("msvcr120.dll", "msvcp120.dll", "vccorlib120.dll") foreach ($dll in $requiredDlls) { $source = "$env:windir\System32\$dll" $dest = "$mysqlBin\$dll" if (Test-Path $source) { Copy-Item -Path $source -Destination $dest -Force Write-Host "已复制 $dll 到 MySQL 目录" -ForegroundColor Green } else { Write-Host "未找到 $dll" -ForegroundColor Yellow } } # 创建应用程序清单文件 @" <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.VC120.CRT" version="12.0.21005.1" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b"/> </dependentAssembly> </dependency> <file name="msvcr120.dll" /> <file name="msvcp120.dll" /> <file name="vccorlib120.dll" /> </assembly> "@ | Out-File "$mysqlBin\mysqld.exe.manifest" -Encoding UTF8 ``` #### 解决方案 4:函数级兼容性修复 ```c // fesetround_wrapper.c #define _CRT_SECURE_NO_WARNINGS #include <fenv.h> #include <windows.h> // 原始函数指针 typedef int (*fesetround_func)(int round); // 包装函数 int __cdecl fesetround_wrapper(int round) { HMODULE hMod = LoadLibraryA("msvcr120.dll"); if (!hMod) return FE_INVALID; fesetround_func real_fesetround = (fesetround_func)GetProcAddress(hMod, "fesetround"); if (!real_fesetround) return FE_INVALID; return real_fesetround(round); } // 编译命令 // cl /LD /Femsvcr120_fix.dll fesetround_wrapper.c /link /DLL ``` ```powershell # 使用包装 DLL $wrapperDll = "msvcr120_fix.dll" $mysqlBin = "C:\MySQL\bin" # 编译包装 DLL @" // 上述 C 代码 "@ | Out-File "$env:TEMP\fesetround_wrapper.c" -Encoding UTF8 & "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" cl /LD /Fe"$mysqlBin\$wrapperDll" "$env:TEMP\fesetround_wrapper.c" /link /DLL # 创建重定向配置文件 @" <?xml version="1.0" encoding="UTF-8"?> <configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.VC120.CRT" publicKeyToken="1fc8b3b9a1e18e3b" /> <bindingRedirect oldVersion="12.0.0.0-12.0.99999.99999" newVersion="12.0.21005.1" /> <publisherPolicy apply="no" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration> "@ | Out-File "$mysqlBin\mysqld.exe.config" -Encoding UTF8 ``` #### 终极解决方案:升级到 MySQL 8.0 ```powershell # 下载并安装 MySQL 8.0 $mysqlUrl = "https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.33-winx64.zip" $installPath = "C:\MySQL8" Invoke-WebRequest -Uri $mysqlUrl -OutFile "$env:TEMP\mysql8.zip" Expand-Archive -Path "$env:TEMP\mysql8.zip" -DestinationPath $installPath -Force # 迁移数据 & "$installPath\bin\mysqld.exe" --initialize-insecure --basedir=$installPath --datadir="$installPath\data" Copy-Item -Path "C:\MySQL\data\*" -Destination "$installPath\data\" -Recurse -Force # 创建服务 & "$installPath\bin\mysqld.exe" --install MySQL80 --defaults-file="$installPath\my.ini" net start MySQL80 ``` ### 验证修复 ```powershell # 检查函数是否存在 function Test-DllFunction { param($dllPath, $functionName) Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class DllCheck { [DllImport("kernel32.dll", SetLastError=true)] public static extern IntPtr LoadLibrary(string dllName); [DllImport("kernel32.dll", CharSet=CharSet.Ansi)] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); } "@ $hModule = [DllCheck]::LoadLibrary($dllPath) if ($hModule -eq [IntPtr]::Zero) { Write-Host "无法加载 DLL" -ForegroundColor Red return $false } $procAddr = [DllCheck]::GetProcAddress($hModule, $functionName) return ($procAddr -ne [IntPtr]::Zero) } $dllPath = "C:\Windows\System32\msvcr120.dll" if (Test-DllFunction -dllPath $dllPath -functionName "fesetround") { Write-Host "fesetround 函数存在" -ForegroundColor Green } else { Write-Host "fesetround 函数缺失" -ForegroundColor Red } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值