ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

手动为KEIL MDK添加ARM Compiler 5(AC5)解决老工程编译报错

手动为KEIL MDK添加ARM Compiler 5(AC5)解决老工程编译报错 接手一个老项目打开工程按下F7等来的不是编译通过的提示而是“Target uses ARM-Compiler Arm Compiler 5 which is not available”这类报错相信不少朋友都遇到过。KEIL MDK从5.37版本开始不再默认集成ARM Compiler 5也就是大家常说的AC5默认只带AC6的armclang编译器。可老工程的启动文件、底层驱动、第三方库很多都是按AC5的语法和规范写的直接切到AC6会冒出一堆警告和错误改起来非常难受。这时候手动给MDK补上AC5编译器就是最省事的解法。这篇文章我就把自己实际操作中总结的完整流程、版本匹配的细节、以及各种奇奇怪怪的坑原原本本写出来供有同样需求的朋友参考。1. 为什么要手动添加AC5编译器差异与兼容性问题1.1 AC5和AC6到底差在哪先说清楚AC5和AC6的关系。AC5是ARM原生的armcc编译器MDK 4.x和5.x早期版本默认使用的就是它。AC6则是ARM基于LLVM架构的armclang编译器从MDK 5.15左右开始作为可选编译器引入到了5.37之后成为默认且唯一的编译器。两者的编译器前端、代码生成策略、优化逻辑都不一样。最直观的差异有几个方面语法标准AC6对C语言标准支持更严格比如对隐式声明的处理、对结构体初始化方式的宽容度老代码里常见的#pragma指令很多在AC5有效但AC6不认。内联汇编AC5的内联汇编语法是__asmAC6则是__asm volatile配合寄存器约束写法完全不同。芯片启动文件、RTOS移植代码、底层驱动里这种汇编到处都是。内置函数和关键字__irq、__forceinline、__packed这类老式关键字AC6虽然部分兼容但编译选项和宏定义已经变化。优化行为同样的代码AC5和AC6优化后的代码体积、执行效率、变量分配策略都不同AC6在某些场景下会更深地优化但也更容易触发老代码里的未定义行为。所以老工程如果直接切换到AC6往往不是改一两处语法的问题而是几十上百个警告、错误扑面而来。手动装回AC5就是为了让老项目继续按原来的方式稳定编译不折腾。1.2 哪些场景最容易遇到AC5缺失我总结下来遇到这个问题最多的是三类人第一类是接手遗留项目的开发者。公司代码仓库里躺着七八年前的项目换台新电脑装最新的MDK 5.38或5.39一编译直接报错找不到AC5。第二类是使用老版本芯片支持包和老启动文件的工程师。有些早期的芯片型号、第三方库其启动文件和应用代码只针对AC5验证过在AC6下需要重新适配。虽然芯片厂商在不断更新但老代码没时间改就是没时间改。第三类是使用特定中间件或RTOS的场景。比如一些老版本的RT-Thread、FreeRTOS移植包、老的DSP库、老的USB协议栈其内部实现依赖AC5的编译行为用AC6编译会导致奇怪的运行时问题。无论属于哪一类手动添加AC5都是最高效的方案。具体怎么操作下面详细说。2. 手动添加ARM Compiler 5前的准备工作2.1 确认当前MDK版本与系统环境在操作之前先打开KEIL MDK点击菜单栏的Help - About uVision确认当前的MDK版本号。这个信息很重要后面选择AC5版本时要用。不同MDK版本能适配的AC5版本不完全一样。以我手头的环境为例MDK 5.36及更早版本默认直接集成AC5不需要额外安装。如果你装的还是这些版本编译报错的话大概率是安装时勾选项没选全或者开发板支持包把编译器路径搞乱了。MDK 5.37和5.38默认不带AC5但可以通过手动安装AC5的方式补上兼容性比较好。MDK 5.39同样支持手动添加AC5但有细微的路径识别要求。我自己实测5.39配合AC5 5.06 update 7可以正常工作。系统环境方面Windows 7 SP1、Windows 10 1809以上、Windows 11都可以正常安装AC5。需要注意的是AC5编译器安装程序是32位的在64位系统上运行没有问题但安装路径建议使用默认路径避免后续MDK识别出错。2.2 AC5从哪儿下载多种合法渠道说明AC5编译器官方下载渠道主要是KEIL官网和ARM官网的软件开发工具页面。这里我以普通用户最容易操作的两种方式说明。第一种方式通过KEIL官网的MDK历史版本页面下载。KEIL官网的“MDK-ARM Version History”页面列出了各个MDK版本部分版本页面下提供了对应的独立编译器安装包下载链接。从MDK 5.37之后官方明确提供ARM Compiler 5作为独立安装包文件名形如ARM.Compiler.5.06_update7.zip这个zip包就是标准的AC5安装包下载后解压运行里面的安装程序即可。第二种方式通过ARM Development Studio页面下载Legacy Compiler。ARM官网的产品下载页面中有专门的“Legacy ARM Compiler Tools”区域里面提供ARM Compiler 5旧版本下载。这个路径稍微隐蔽一些需要从开发者工具入口一层层点进去但这个渠道是官方维护的版本齐全。这里需要注意一个常见误区不要从第三方博客或网盘下载所谓“绿色版”、“免安装版”的AC5。编译器安装包如果被篡改轻则安装失败重则编译结果不可信甚至带毒。实际使用中我见过不少人为了图方便下载了精简版AC5结果编译时莫名其妙报内部错误最后重新装官方完整包才解决。2.3 版本选择建议与匹配关系AC5的常见版本号是5.06和5.06 update 1直到5.06 update 7。这里直接给结论长期稳定首选ARM Compiler 5.06 update 7即5.06u7。这是AC5最后的更新版本修复了大量已知问题对Cortex-M全系列都支持兼容性最好。MDK 5.37及以上版本推荐安装AC5 5.06u7不要装更早的update版本。初代5.06在部分Win10/11机器上存在代码生成优化问题老版本编译器在某些场景下生成的代码有概率触发芯片硬件异常。如果项目原本是在MDK 5.36时代创建的工程里默认用的就是5.06u7那你装AC5 5.06u7能实现无缝切换。版本匹配的底层逻辑在于MDK的IDEuVision在生成编译命令时会根据编译器版本的差异注入不同的预定义宏和命令行选项。AC5 5.06u7和MDK 5.37之后的版本配合是官方验证过的组合用其他旧版本会有命令行参数不匹配的风险。3. 手把手添加AC5完整操作流程3.1 解压安装包并运行安装程序这里用一个可复现的实例来说。假设你下载好了ARM.Compiler.5.06_update7.zip。第一步解压这个zip包。右键选择“解压到当前文件夹”注意不是直接双击进去看压缩包内容而是完整解压到一个目录。解压后会看到一个名为ARM_Compiler_5.06u7的文件夹里面有一个README.txt、一个LICENSE.txt和安装程序文件夹。第二步打开其中的安装程序目录找到setup.exe部分版本是installer.exe右键以管理员身份运行。提示安装AC5必须用管理员权限运行安装程序否则安装器无法写入C:\Keil_v5\ARM和注册表项后续MDK会识别不到。第三步安装向导会询问安装路径。默认路径是C:\Keil_v5\ARM\ARM_Compiler_5.06u7。如果你的MDK安装在别的目录比如D:\Keil_v5那这里要手动改成D:\Keil_v5\ARM\ARM_Compiler_5.06u7。安装路径必须位于MDK安装目录下的ARM子目录里这是uVision扫描编译器的固定目录规则放在其他位置会识别不到。3.2 在uVision中注册和启用AC5安装完成后打开KEIL MDK。这时候大概率还不会自动识别到新装的AC5需要手动注册一次。点击菜单栏的Project - Manage - Project Items在弹出的对话框里切换到Folders/Extensions标签页。或者更直接的方式点击工具栏上的魔术棒图标Options for Target在Target标签页右侧找到“ARM Compiler”下拉框。如果下拉框里没有出现“Use default compiler version 5”说明MDK还没有扫描到AC5。这时候需要回到Project Items对话框的Folders/Extensions页检查“ARM compiler versions”列表里有没有显示出AC5的路径。如果没有显示点击下方的“Add”按钮手动选择C:\Keil_v5\ARM\ARM_Compiler_5.06u7这个目录。选择后列表里会出现ARMCC和对应的版本号目录。勾选上该版本前面的复选框然后点击OK保存。注意uVision的编译器扫描机制是启动时读取ARM\目录下的子文件夹名称识别规则是文件夹名以ARM_Compiler开头就能纳入候选。如果你手动改过文件夹名MDK可能识别不到建议还是保持默认命名。3.3 在具体工程中切换编译器并验证编译器添加到MDK后还需要在目标工程里实际切换验证。打开你的老工程点击Options for Target图标在Target标签页找到“ARM Compiler”下拉框。正常情况下这里会出现两个选项Use default compiler version 5通过工具链路径参数自动选择默认是AC5或者直接显示Arm Compiler 5.06 update 7 (armcc)选择AC5后点击OK回到编辑界面。接下来做三件事验证重新编译工程按F7或者点击Build按钮。查看编译输出窗口里是否出现“compiling xxx.c... armcc”字样确认调用的确实是ARMCC而不是armclang。检查编译输出目录里的Object文件是否正常生成。如果编译顺利通过那恭喜AC5已经正式接管这个工程的编译工作。4. 实操中的关键细节与配置优化4.1 编译器的路径与命令行参数匹配问题在实际操作中我发现很多人明明装好了AC5但编译时还是会报“unsupported option”或“.d file not found”。排查下来很多情况是编译器路径与MDK内置的调用规则不匹配。MDK调用AC5编译时会通过环境变量和命令行参数组合出完整的编译命令。这个命令格式大概是C:\Keil_v5\ARM\ARM_Compiler_5.06u7\bin\armcc.exe --cpu Cortex-M4 --c99 --apcsinterwork -o ... -c ...如果你的AC5安装路径包含空格或特殊字符比如D:\My Tools\Keil\ARM_Compiler_5.06u7某些MDK版本的命令行解析会出错。处理方法是路径里有空格就用C:\Progra~1这样的短文件名替代或者在安装AC5时直接选用默认路径。不要用中文路径MDK对中文路径的兼容性一直是老大难问题。工程路径和编译器路径里面出现中文AC5编译时可能出现fatal error: cannot open source file这类问题。我实际建议C:\Keil_v5和D:\Keil_v5都是比较稳妥的安装位置。尽量不用D:\KEIL\这类精简命名——虽然大多数情况没问题但个别MDK版本对路径长度有隐藏限制。4.2 老工程中AC5相关的编译选项设置补装AC5后很多老工程的编译选项其实不用动默认配置就能工作。但有几个关键的编译选项值得检查一下能少走很多弯路。第一个是C语言标准选择。AC5默认使用C90标准如果你的代码里用了//注释C99特性没问题AC5默认支持但如果你用了for(int i 0; ...)这种C99式的循环内变量声明AC5会报错。解决办法是在C/C标签页的“Language mode”下拉框里选择c99或c99 GNU。第二个是优化等级。老代码在AC5下用-O0或-O1编译一般没事但如果你把优化等级开到-O3一些依赖特定编译行为的老驱动可能出问题。建议初上手时维持工程原来的优化设置不要顺手调高。第三个是预定义宏。很多芯片启动文件和驱动代码依赖__CC_ARM宏来区分编译器AC5编译时默认会定义这个宏不需要手动加。但有些老工程里可能会有#if defined(__CC_ARM)这样的条件编译如果工程提供的启动文件和cmsis_armcc.h路径不对会导致条件编译走错分支。检查一下C/C标签页的Include Paths里是否包含正确的CMSIS目录比如C:\Keil_v5\ARM\PACK\ARM\CMSIS\5.7.0\CMSIS\Core\Include。4.3 许可证激活的常见坑AC5编译器需要许可证才能正常工作。如果你用的是MDK评估版限制代码大小的免费LicenseAC5同样受评估版的编译限制比如编译输出代码超过32KB会报错。这时候需要在License Management里激活正式许可证。实际操作步骤是打开MDK点击File - License Management。看License状态里是否有ARM Compiler 5相关的条目。如果显示missing或expired确认你采购的是MDK Professional或MDK Plus许可证并且许可证类型里包含ARM Compiler 5的授权。点击“Add License”按钮输入注册码License ID Code通常16位或导入许可证文件。这里有个不值得踩的坑AC5在旧版MDK中被视为默认编译器其许可证和MDK License是绑定的AC6在较新MDK里也被包含在同类许可证中。但某些针对性购买的AC5独立许可证注册时需要确认许可证文件中确实包含“ARM Compiler 5”组件而不是只有“MDK Professional”组件。如果你的公司是节点锁定LicenseNode-locked在换电脑后需要先反激活旧机器上的License否则新机器激活时报“license already in use”。5. 常见问题与排查技巧实录5.1 编译报错“Arm Compiler 5 not found”怎么办这是最典型的问题明明安装了AC5MDK还是提示找不到。排查顺序如下第一步确认AC5安装目录结构与MDK版本的对应关系。打开你已经安装的目录看看是不是长这样D:\Keil_v5\ARM\ARM_Compiler_5.06u7\bin\armcc.exe。如果你的目录是D:\Keil_v5\ARM\ARMCC\bin\armcc.exe那MDK也能识别因为uVision同时支持ARM_Compiler前缀和ARMCC目录名但如果你把编译器的bin目录直接放到了D:\Keil_v5\ARM\bin这一级那就会识别不到。第二步检查MDK的启动日志。MDK在启动时会向C:\Users\xxx\AppData\Roaming\Keil\UV4目录写入日志文件查看uVision.log里有没有“compiler not found”或者“toolchain not registered”的字样。如果有说明MDK注册表里的路径信息没写进去重新运行一次安装程序修复。第三步重置MDK设置。有时候MDK的Global Settings里缓存了旧的编译器路径导致新安装的AC5没被扫描。操作方法是关闭MDK删除C:\Users\xxx\AppData\Roaming\Keil\UV4下的UV4.INI文件再重新打开MDK。这样MDK会重新生成配置并扫描所有工具链。5.2 AC5与AC6共存时的切换方法和冲突问题装了AC5后工程仍可以在AC5和AC6之间切换这本身不是问题。但有个场景要注意一个工程的多目标Target可能一个配置为AC5另一个配置为AC6两个Target编译出来的产物行为不同容易把人绕晕。更常见的冲突是全局默认编译器设置和工程级设置不一致。uVision里有一个全局默认编译器版本设置位于Project - Manage - Project Items - Folders/Extensions的“Default”下拉框会作为新建工程的默认值。而每个工程又可以单独指定编译器。如果你添加AC5后发现新工程默认还是AC5或者反过来改全局默认值就好。我处理这种情况的习惯是老项目统一用AC5新项目统一用AC6通过全局默认值设定当前常用编译器然后每个工程单独固定。这样最直观不容易混。5.3 编译时出现“internal error: #10060-...”等AC5内部错误AC5编译器偶尔会报内部错误格式形如internal error: #10060-...或fatal error: C3900U: Internal error。这不是你的代码写错了而是编译器自身处理某些代码组合时的崩溃。实测下来这类内部错误有几种常见诱因非常复杂的宏嵌套和结构体初始化比如#define里套20多层。带__packed属性的结构体与指针转换混用。高优化等级下大量内联函数和虚继承/C类模板组合。遇到这类问题的处理方式按优先级排列先把工程优化等级降到-O0看错误是否消失。如果消失说明是优化器触发的问题这时候可以尝试把出问题的源文件单独设低优化其他文件保持全局优化。拆分大函数。把报错的函数拆成多个小函数这是最粗暴但也最有效的A5避坑法。规避复杂的宏表达式。老代码里的“奇技淫巧”型宏在AC5特定补丁版本可能触发bug改写为内联函数。5.4 常见问题速查表我把平时群里、论坛里问得最多的问题整理成表格方便对照处理问题现象根本原因解决方案编译报错“Target uses ARM-Compiler which is not available”MDK未注册AC5工具链在Project Items的Folders/Extensions中添加AC5路径并勾选编译器下拉框里只有AC6AC5文件夹命名不被识别确认文件夹名以“ARM_Compiler”开头路径位于MDK/ARM目录下编译成功但无法下载调试工程配置里的Flash算法或调试器版本与AC5生成代码不匹配更新芯片支持包重新选择正确的Flash下载算法打开老工程编译头文件找不到工程Include Paths未更新到新MDK解析出的CMSIS路径在C/C标签页恢复默认Include Paths或手动添加CMSIS Core Include目录AC5编译通过但程序运行异常AC5生成代码与启动文件/链接脚本不匹配或优化等级过高检查启动文件版本降低优化等级核对分散加载文件安装AC5时提示“cannot install because another installation is in progress”残留安装进程打开任务管理器结束所有setup.exe进程重启系统后重装MDK 5.39中AC5编译出现“unhandled exception”崩溃armcc在特定系统环境下的兼容性问题以Win7兼容模式运行uVision并将AC5的bin目录加入杀毒软件白名单5.5 使用AC5编译老工程的三个附加建议最后聊几个和AC5相关的附加建议都是实际操作中积累的经验。建议一AC5生成的目标文件不要和AC6混用。一个工程里一部分源文件用AC5编译一部分用AC6编译极大可能出现链接时找不到符号或者ABI不兼容的问题。所以要换编译器就整个工程切不要搞混编。建议二用AC5编译的产物稳定性和可读性都比较好但优化选项建议保守设置。AC5在-O2及以上对Cortex-M0/M0的处理已经比较成熟但对Cortex-M7的VLLIM指令序列优化存在一些边缘问题可能导致总线错误。如果项目用在量产设备上-O1比-O3更让人安心。建议三做好版本记录。建议在项目的README或交付文档中明确记录使用的MDK版本、AC5版本、芯片支持包版本。即使不写下完整环境至少把编译器版本号记下来方便以后维护和换环境复现。6. 从AC5迁移到AC6的过渡思路手动添加AC5解决了眼下的编译问题但从更长远的角度看AC5毕竟是老编译器官方已经停止更新对新一代芯片和新CMSIS版本的支持会越来越少。我建议在稳住老项目的同时可以顺便规划向AC6的渐进迁移。具体来说可以先在工程里复制出一个Target单独设置为AC6编译逐文件修复编译错误和警告利用AC6编译器的诊断信息把老代码里隐性问题挖出来。AC6对-Werror的态度也更坚决很多AC5时代忽略的警告在AC6里直接变成error但这些error修复后代码质量反而是提升的。迁移不是一蹴而就的我是说如果你手头有精力就把AC5当作“存量项目的保障手段”把AC6当作“新需求和新代码的默认选择”。两条腿走路比死守AC5或者硬着头皮一刀切AC6都要稳妥。7. 最后分享几个安装过程中的小技巧根据我装过十几台电脑MEIL MDK和AC5的经验有几个小技巧平时不写在官方文档里但对成功率影响很大。第一个技巧是安装AC5前把MDK完全关闭包括右下角托盘里的License管理服务有些版本有后台进程。关闭后重新打开再安装避免文件占用问题。第二个技巧如果AC5安装成功后MDK仍然不识别试着删除工程目录原始计算机id.txt、MDK自动生成的.bak文件夹重新打开工程一次。有几次就是这样的“玄学操作”意外解决了识别不到的问题。第三个技巧如果你的MDK装在非C盘建议在安装AC5前先给系统环境变量里添加一个KEIL_MDK_ARM变量值指向MDK安装目录下的ARM文件夹例如D:\Keil_v5\ARM。我自己测试过设置了KEIL_MDK_ARM环境变量之后不少MDK版本对AC5的定位更准确识别率明显更高。第四个技巧AC5安装完成后在命令行工具里验证一下编译器能否独立运行。打开命令提示符切换到D:\Keil_v5\ARM\ARM_Compiler_5.06u7\bin目录输入armcc.exe --version。如果输出正常显示编译器版本信息说明AC5已经能独立工作问题大概率只出在MDK的路径识别上如果报缺少DLL或者无法启动那就要检查系统运行库。最后一点也是我最想强调的一点AC5安装包虽然写着“Compiler”但它本质上和MDK是一套配套生态。安装前花两分钟确认MDK版本、系统位数、License授权这三件事能省掉后面所有“为什么还是不行”的折腾时间。嵌入式开发里编译环境本身就是工程资产的一部分维护好它和写好驱动代码一样重要。
返回列表