RH850 GHS编译链路全解析:从.c到.elf的工程实践
1. 为什么值得把这条编译链路彻底搞明白嵌入式开发里有一类问题特别磨人代码明明写对了链接也能过烧录进去就是跑不起来或者换了一台电脑、换了一个编译选项原本正常的工程突然报出一堆莫名其妙的段错误。这类问题的根子往往不在C代码本身而在于从源文件到可执行镜像之间那条被大多数人忽略的编译链路。RH850是车规级MCU里非常典型的一个系列GHSGreen Hills Software编译器则是它常用的工具链之一。很多做汽车电子、车身控制、域控制器底层开发的朋友日常就是在GHS RH850这套组合上干活。但真正能把.c文件一路走到.elf、再走到可烧录镜像的完整过程讲清楚的人并不多。大部分人停留在“点一下编译按钮”或者“跑个make就完事”的层面一旦出问题就只能靠猜。这篇内容就是想把这条链路拆开揉碎讲一遍。从预处理、编译、汇编、链接到最终生成.elf每一步到底发生了什么、GHS编译器在RH850上有什么特殊行为、哪些参数会影响最终产物、出问题该从哪里下手排查。适合正在用RH850做项目、被编译链接问题卡过、或者想从“会写代码”进阶到“懂构建”的嵌入式工程师。看完之后你至少能做到拿到一个编译报错知道它属于哪个阶段的问题该看哪个中间文件该调哪个选项。我尽量不写成手册式的罗列而是按一个真实项目推进的顺序来讲中间穿插我自己踩过的坑和实际验证过的参数。有些细节是文档里不会写的只有真正在RH850上折腾过才会遇到。2. 整条链路的设计思路与阶段拆解2.1 从源码到镜像中间到底隔了几道工序很多人以为“编译”就是一个动作实际上从.c到.elf至少要经过四个独立阶段每个阶段由不同的工具完成输入输出格式也完全不同。理解这一点是排查问题的前提因为不同阶段的报错特征差异极大。第一个阶段是预处理。这一步由预处理器完成处理的是#include、#define、#ifdef这些以#开头的指令。它的输出仍然是一个C源文件只是所有宏都展开了、头文件都插进来了、条件编译都裁剪完了。GHS的预处理器叫cpp但通常你不会直接调用它而是通过编译驱动ccrh间接触发。第二个阶段是编译。这里的“编译”是狭义上的指把预处理后的C代码翻译成汇编代码。GHS的RH850编译器核心是ccrh它负责语法分析、语义分析、优化、寄存器分配最终输出.asm汇编文件。这个阶段是优化选项作用最明显的地方-O、-Os、-Ospace这些参数都在这里生效。第三个阶段是汇编。汇编器把.asm翻译成机器码输出可重定位的目标文件.o。GHS的汇编器是asrh。目标文件里包含的是机器指令、数据、符号表、重定位信息但地址还没最终确定。第四个阶段是链接。链接器elxrGHS的链接器叫elxr或lxr取决于版本把所有.o文件、库文件、链接脚本拼在一起分配最终地址解析所有符号引用输出.elf文件。.elf是带符号信息和调试信息的可执行文件格式之后还可以用objcopy之类的工具转成.hex、.srec或.bin用于烧录。注意GHS工具链里ccrh这个驱动命令其实可以一次性把.c直接编到.o甚至直接链接成.elf它内部会自动调用预处理器、编译器、汇编器、链接器。但排查问题时我们往往需要把这几步拆开单独执行才能定位到底哪一步出了问题。2.2 为什么GHS在RH850上要这么设计RH850是瑞萨的32位车规MCU架构上属于RH850 G3M/G3K/G4M等系列指令集和常见的ARM、x86完全不同。GHS编译器针对RH850做了大量架构相关的优化比如指令调度、延迟槽填充、寄存器窗口处理等。这些优化让编译流程比通用平台更复杂但也更值得理解。GHS把编译过程拆成多个独立工具而不是像某些工具链那样做成一个大一统的驱动主要原因是可调试性和可替换性。每个阶段输出中间文件意味着你可以在任意阶段停下来检查产物。比如优化后的汇编代码到底长什么样、链接后的符号地址对不对、某个函数有没有被内联掉这些都能通过中间文件验证。另一个原因是车规开发对可追溯性的要求。功能安全相关的项目比如ISO 26262需要记录每个阶段的输入输出、工具版本、编译选项以便复现和审计。分阶段的工具链天然适合这种流程每一步都能留下独立的产物和日志。2.3 一个典型的工程目录应该长什么样在动手之前先把工程目录结构理清楚。我见过太多项目把所有文件堆在一个目录里编译一跑满屏都是中间文件出了问题根本找不到北。一个清晰的RH850 GHS工程建议至少分成这几层project/ ├── src/ # C源文件 │ ├── main.c │ ├── drv/ │ └── app/ ├── inc/ # 头文件 ├── ld/ # 链接脚本 .ld 或 .ldrh ├── build/ # 编译输出目录 │ ├── obj/ # .o 目标文件 │ ├── asm/ # 中间汇编文件 │ └── out/ # 最终 .elf / .hex ├── Makefile └── ghs_options.mk # 编译选项集中管理把编译选项单独抽到一个.mk文件里好处是不同配置Debug/Release可以复用同一套规则只改选项文件。RH850项目经常需要在不同优化等级之间切换做对比测试这种结构能省很多事。3. 核心工具与关键参数深度解析3.1 GHS工具链里那几个你必须认识的命令GHS for RH850的工具链安装完之后bin目录下会有一堆可执行文件。日常最常打交道的其实就四个命令作用典型输入典型输出ccrh编译驱动可一站式完成.c.o/.elfcpprh预处理器.c.iasrh汇编器.asm.oelxr链接器.o.ld.elfccrh是最常用的因为它可以一步到位。但当你需要看中间产物时就要用-S保留汇编、-E只做预处理、-c只编译不链接。这几个选项和GCC是类似的GHS做了兼容设计所以有GCC经验的人上手会快很多。实操心得ccrh的-v选项会打印出它实际调用的底层命令和完整参数。当你搞不清楚某个选项到底传给了哪个阶段时加-v跑一遍看它输出的命令行一目了然。这个技巧我用了很多年排查选项冲突特别有效。3.2 影响最终.elf的关键编译选项RH850项目里编译选项直接决定了生成的代码能不能跑、跑得快不快、占多大空间。下面这几个是必须搞明白的优化等级-O0到-O3还有-Os优化体积。车规项目里Debug版本通常用-O0或-OgRelease版本用-O2或-Os。注意-O3在RH850上不一定比-O2快因为过度优化可能导致指令缓存命中率下降这个后面会细说。架构选项-crh850指定目标架构具体还要配合-cpu指定具体型号比如-cpug3m。这个选项错了生成的指令可能不被目标芯片支持烧进去直接跑飞。字节序RH850支持大端和小端-endianbig或-endianlittle。这个必须和硬件设计一致搞反了所有多字节数据都是错的。浮点支持-fp相关选项决定浮点运算是用硬件FPU还是软件模拟。RH850部分型号带FPU用-fpu开启不带FPU的型号必须用软件浮点否则链接时会报未定义符号。段分配-section相关选项控制代码和数据放到哪个段。RH850的存储空间分得很细代码放ROM、数据放RAM、常量放ROM这些都要通过段和链接脚本配合。3.3 链接脚本被低估的关键文件链接脚本.ld或.ldrh是链接阶段的“地图”它告诉链接器代码段放哪里、数据段放哪里、栈和堆怎么分配、中断向量表放在哪个地址。很多编译能过但跑不起来的问题根源都在链接脚本。一个典型的RH850链接脚本会定义这些区域MEMORY { ROM (rx) : ORIGIN 0x00000000, LENGTH 1M RAM (rwx) : ORIGIN 0xFEDE0000, LENGTH 128K } SECTIONS { .text : { *(.text) } ROM .rodata : { *(.rodata) } ROM .data : { *(.data) } RAM AT ROM .bss : { *(.bss) } RAM }.data段的AT ROM是关键数据段的初始值存在ROM里启动时由启动代码拷贝到RAM。如果链接脚本漏了这个.data段的变量初值就是随机的程序行为完全不可预测。这个坑我见过不止一次尤其是从别的平台移植过来的工程。4. 完整实操流程从.c一步步走到.elf4.1 环境准备与工具链验证动手之前先确认工具链装好了、版本对得上。GHS的安装目录通常在/opt/ghs或C:\ghs具体看平台。装完之后把bin目录加到PATH里然后跑一下ccrh --version asrh --version elxr --version三个命令都能正常输出版本号说明环境没问题。如果ccrh报找不到检查PATH如果报license错误检查license文件路径和有效期。GHS是商业工具链license问题很常见尤其是换机器或者license服务器网络不通的时候。注意GHS不同版本之间的命令行选项可能有细微差异。比如某些版本用-cpug3m某些版本用-C g3m。拿到一个新版本先翻一下它自带的release notes或者--help输出别直接套用旧版本的脚本。4.2 分步执行把每个阶段的产物都留下来假设我们有一个最简单的main.c#include stdio.h #define LED_ADDR 0xFEDE0000 int global_counter 100; int main(void) { volatile unsigned int *led (volatile unsigned int *)LED_ADDR; *led global_counter; while (1) { (*led); } return 0; }第一步只做预处理ccrh -E -I./inc main.c -o build/main.i打开build/main.i你会看到#include stdio.h被展开成了一大堆声明LED_ADDR被替换成了0xFEDE0000global_counter的定义还在。这一步能帮你确认宏展开是否符合预期头文件路径有没有找对。第二步编译到汇编ccrh -S -O2 -crh850 -cpug3m -endianlittle main.c -o build/main.asm打开build/main.asm你能看到编译器生成的RH850汇编代码。重点看几个地方main函数的入口、global_counter的访问方式、循环有没有被优化。如果开了-O2那个while(1)循环里的(*led)应该会被优化成很紧凑的几条指令。第三步汇编到目标文件asrh -crh850 -cpug3m build/main.asm -o build/obj/main.o这一步一般不会出错除非汇编文件里有语法问题。如果报错通常是编译器生成的汇编有问题或者汇编器版本和编译器版本不匹配。第四步链接成.elfelxr -crh850 -cpug3m -T ld/rh850.ld \ build/obj/main.o \ -o build/out/main.elf链接阶段最容易出问题符号未定义、段溢出、地址冲突。链接成功后用elxr自带的-map选项生成map文件elxr -crh850 -cpug3m -T ld/rh850.ld -map build/out/main.map \ build/obj/main.o -o build/out/main.elfmap文件里能看到每个段最终落在哪个地址、每个符号的地址、每个目标文件贡献了多少字节。这是排查链接问题的第一手资料。4.3 用readelf和objdump验证产物.elf生成之后别急着烧录先用工具验证一下# 查看段布局 elxr -readelf -S build/out/main.elf # 查看符号表 elxr -readelf -s build/out/main.elf # 反汇编 elxr -objdump -d build/out/main.elf build/out/main.dis重点确认三件事.text段起始地址是不是链接脚本里定义的ROM起始地址main符号的地址是不是在.text段范围内.data段的加载地址LMA是不是在ROM里、运行地址VMA是不是在RAM里。这三点任何一点不对程序都跑不起来。4.4 从.elf到可烧录镜像.elf本身不能直接烧录需要转成.hex或.bin# 转成Intel HEX elxr -objcopy -O ihex build/out/main.elf build/out/main.hex # 转成二进制 elxr -objcopy -O binary build/out/main.elf build/out/main.bin转.bin的时候要注意如果.elf里有地址空洞比如ROM和RAM地址不连续.bin文件会非常大中间全是填充。这时候用.hex更合适因为它带地址信息烧录器能正确处理。5. 常见问题与排查技巧实录5.1 编译阶段典型报错与处理报错undefined reference to xxx这是链接阶段最常见的错误意思是某个符号被引用了但没找到定义。排查顺序先确认定义该符号的.c文件有没有参与编译再确认对应的.o有没有传给链接器最后确认符号名有没有被static限制作用域或者被#ifdef条件编译掉了。报错section .text will not fit in region ROM段溢出。说明代码或常量数据超过了ROM容量。用map文件看哪个目标文件占得最多然后考虑开-Os优化体积、把不常用的函数移到单独的段、或者检查有没有大数组被误放到.text段。报错relocation truncated to fit重定位溢出。通常是因为某个跳转指令的目标地址超出了指令能表示的范围。RH850的分支指令有距离限制超过范围需要编译器插入跳板trampoline。检查是不是代码段太大或者链接脚本把相距很远的段放在了一起。5.2 链接能过但跑不起来的排查思路这类问题最头疼因为工具链不报错只能靠调试器。我的排查顺序是这样的第一确认启动代码有没有正确执行。在启动代码的入口设断点看能不能停下来。如果停不下来说明复位向量不对检查链接脚本里向量表的地址。第二确认.data段有没有被正确拷贝。在main函数入口设断点看.data段里的全局变量初值对不对。如果不对检查启动代码里的拷贝循环和链接脚本的AT ROM设置。第三确认栈指针有没有初始化。RH850的栈通常设在RAM高端启动代码里要显式设置sp寄存器。如果sp没设或者设错了一调用函数就跑飞。第四确认中断向量表有没有对齐。RH850的中断向量表有对齐要求不对齐的话中断触发时会跳到错误地址。实操心得我习惯在启动代码里加一段“点灯”代码在进入main之前先点亮一个GPIO。这样即使main跑飞了也能通过灯的状态判断启动代码有没有执行到。这个土办法在调试早期阶段特别管用比接调试器还快。5.3 优化等级引发的“灵异事件”开了-O2之后程序行为变了这是嵌入式开发里的经典问题。常见原因有三个一是volatile缺失。被优化掉的变量访问往往是因为没加volatile。编译器认为这个变量没人改就把读取优化掉了。硬件寄存器、中断里修改的变量、多线程共享的变量都必须加volatile。二是内存屏障缺失。RH850是乱序执行的编译器和CPU都可能重排内存访问顺序。如果代码依赖访问顺序比如先配置寄存器A再配置寄存器B需要加内存屏障或者用volatile强制顺序。三是未定义行为被优化。比如有符号整数溢出、空指针解引用、数组越界这些在-O0下可能“碰巧”能跑开了优化就直接崩。这类问题只能靠代码审查和静态分析工具提前发现。5.4 常见问题速查表现象可能阶段排查方向宏没展开预处理检查#define位置、-I路径语法报错编译检查C标准选项、头文件版本汇编报错汇编检查编译器与汇编器版本匹配符号未定义链接检查.o是否全部传入、库路径段溢出链接看map文件、开体积优化跑飞运行查启动代码、链接脚本、栈指针优化后行为异常编译查volatile、内存屏障、未定义行为6. 把编译链路纳入日常工程管理的几个做法6.1 用Makefile把分步流程固化下来手动敲命令只适合学习和排查日常工程必须用Makefile自动化。关键是把每个阶段的规则写清楚并且把中间产物保留下来CCRH ccrh ASRH asrh ELXR elxr CFLAGS -crh850 -cpug3m -endianlittle -O2 -I./inc LDFLAGS -crh850 -cpug3m -T ld/rh850.ld -map build/out/main.map OBJS build/obj/main.o build/obj/drv.o build/obj/app.o build/out/main.elf: $(OBJS) $(ELXR) $(LDFLAGS) $^ -o $ build/obj/%.o: src/%.c mkdir -p $(dir $) $(CCRH) $(CFLAGS) -c $ -o $ build/asm/%.asm: src/%.c mkdir -p $(dir $) $(CCRH) $(CFLAGS) -S $ -o $这样make跑完整流程make build/asm/main.asm单独生成某个文件的汇编排查问题时非常方便。6.2 版本控制里该提交什么、不该提交什么build/目录整个加到.gitignore里中间产物不提交。但有两样东西必须提交一是Makefile和所有.mk选项文件二是链接脚本。这两样是构建配置的核心丢了就复现不了。另外建议把每次Release构建的map文件和.elf归档保存打上版本标签。车规项目经常需要回溯“某个版本用的是哪个编译选项、生成了什么产物”有归档就能快速定位。6.3 编译选项的集中管理与差异对比不同配置的选项差异建议用独立的.mk文件管理# ghs_debug.mk CFLAGS -O0 -g -DDEBUG # ghs_release.mk CFLAGS -O2 -DNDEBUG构建时通过make CONFIGdebug或make CONFIGrelease切换。这样选项差异一目了然也避免了在Makefile里写一堆ifeq判断。我个人在实际操作中的体会是编译链路这东西平时不出问题的时候感觉不到它的存在一旦出问题就是大问题。花时间把每个阶段的产物、每个选项的作用、每个报错的含义搞清楚短期看是“浪费时间”长期看是省下了无数次抓瞎排查的时间。尤其是RH850这种车规平台工具链复杂、硬件行为严格对编译过程的理解深度直接决定了你解决问题的速度。最后再分享一个小技巧养成看map文件的习惯。每次链接完花两分钟扫一眼map文件里的段布局和符号地址很多潜在问题在烧录之前就能发现。比如某个大数组悄悄占了几十K的RAM、某个函数被链接到了错误的段、栈空间留得太小这些在map文件里都有迹可循。

相关新闻

2026年AI接口聚合服务深度横评:从调用稳定性看词元之河与硅基流动的中小团队适配度

2026年AI接口聚合服务深度横评:从调用稳定性看词元之河与硅基流动的中小团队适配度

2026年5月完成的一轮 AI 接口聚合服务实测横评,方法论为 72 小时连续压测、12 类典型调用场景模拟与 37 位一线开发者访谈。行业背景值得关注:据《中国AI基础设施白皮书(2026Q1)》,超过 68% 的中小技术团队在大模型应用…

2026/10/18 2:12:56 阅读更多 →
手工LL(1)编译器实战:从词法到语义的5层避坑指南

手工LL(1)编译器实战:从词法到语义的5层避坑指南

简介:本资源是一份完整的高校编译原理课程设计报告,面向计算机专业本科生及编译技术初学者,聚焦Pascal子集编译器的系统性实现与原理剖析。报告涵盖词法分析(含符号表构建与注释处理)、语法分析(自顶向下LL…

2026/10/18 2:12:56 阅读更多 →
香港公司注册怎么办理?

香港公司注册怎么办理?

一、香港公司注册是什么?有什么用? 香港公司注册,是指依据香港《公司条例》,向香港公司注册处提交申请,取得公司注册证书及商业登记证的法律程序。 对跨境卖家、外贸企业和品牌方而言,香港公司主要用于&…

2026/10/18 2:12:56 阅读更多 →

最新新闻

C#+OpenCV二维码识别:图像预处理与透视矫正实战解析

C#+OpenCV二维码识别:图像预处理与透视矫正实战解析

这个项目看起来很直接,但实际落地时坑不少。标题是“C#OpenCV识别图片二维码”,拆开看就是三件事:C#做宿主程序、OpenCV做图像处理、二维码识别作为最终目标。很多人一上来就找OpenCV的二维码识别模块,结果发现识别率惨不忍睹&…

2026/10/18 2:59:06 阅读更多 →
Flutter多因子排序:动态权重与概率统计在鸿蒙适配中的实践

Flutter多因子排序:动态权重与概率统计在鸿蒙适配中的实践

如果你维护过带排序列表的App,大概率在某个版本上被多因子业务混战折磨过:用户要综合分,运营要热度加权,产品要新品加权,风控要防刷降权,几个团队各提各的需求,最后全压在ranking模块上。我最初…

2026/10/18 2:59:06 阅读更多 →
Qwen-Agent实战:从对话到代码执行的智能体自动化框架

Qwen-Agent实战:从对话到代码执行的智能体自动化框架

如果你的工作里有一半时间是用来“搬运数据、整理表格、复制粘贴、改格式”,那么Qwen-Agent值得你花半个小时来试一下。这不是那种“跟我对话聊天”的玩具型AI工具,而是一个真正能接手干活的全能助手——给它一个任务描述,它能自动拆解步骤、…

2026/10/18 2:59:06 阅读更多 →
视频流分段返回实战:HTTP Range 原理、实现与避坑指南

视频流分段返回实战:HTTP Range 原理、实现与避坑指南

1. 视频流分段返回到底在解决什么问题第一次接触“视频流分段返回”这个需求,是在一个后台管理系统里。前端要预览一段监控回放,视频文件放在对象存储上,单个文件动辄两三百兆。最开始的做法很粗暴:后端一次性把整个文件读进内存&…

2026/10/18 2:59:06 阅读更多 →
Moonfire NVR:Rust 编写的轻量级本地 IP 摄像机录像系统

Moonfire NVR:Rust 编写的轻量级本地 IP 摄像机录像系统

简介:Moonfire NVR 是一款轻量高效、开源的网络视频录像机(NVR)系统,面向嵌入式安防开发人员、边缘视频存储方案设计者及 Rust/JavaScript 全栈工程师,解决 IP 摄像机 RTSP 流的低开销持久化存储与按需回放问题。资源包…

2026/10/18 2:59:06 阅读更多 →
开源Newsletter系统多租户安全设计:MailCheap从账户隔离到API Key撤销全链路指南

开源Newsletter系统多租户安全设计:MailCheap从账户隔离到API Key撤销全链路指南

【免费下载链接】mailcheap Newsletters where you pay for the emails you send, not for dormant subscribers, at a fraction of the price of beehiiv and the like. Open source: self-host it, or use mailcheap.ai. 项目地址: https://gitcode.com/gh_mirror…

2026/10/18 2:58:05 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →