CMake进阶实战:target模型与生成器表达式,打造可维护C++工程
写C也有不少年头了我越来越觉得代码写得再漂亮构建系统一塌糊涂项目照样会卡在“给别人用”这一步。很多人觉得CMake能编译过就行但等到要接第三方库、要跨平台发布、要换机器重新配置时那些“凑合能用”的CMakeLists.txt就会变成最大的坑。这篇就聊聊CMake进阶这回事重点放在target模型、生成器表达式、安装导出、strip指令、离线安装、VSCode调试这些真正影响日常开发的细节上适合已经能跑通小项目、想真正把工程化做扎实的C开发者。1. 为什么越写越乱CMake进阶到底进阶在哪儿1.1 从“能编译”到“可维护”的分水岭很多人的CMake之路是这样走的先有一个main.cppadd_executable一行搞定。后来加了几个类把源文件一行行列进去。再后来发现某些代码要编成静态库于是add_library然后target_link_libraries。这套流程跑通以后大家基本就不想再动了。直到有一天项目要发布要在别的机器上编译要在Release和Debug之间切换要往里面接spdlog、raylib、TDengine这种第三方依赖原来的写法就瞬间崩盘。分水岭其实很清晰写CMake的时候你脑袋里装的到底是“把文件列表拼成命令”还是“描述这些对象之间的依赖关系”。前者是把CMake当脚本用后者才是当构建系统用。CMake真正的能力不在add_executable这种基础命令而在于它有一套target模型能把目标的定义、依赖、编译选项、安装规则全部组织在一起。这也是我开始把CMake当“工程”而不是“脚本”来对待之后最大的体会。这里举个生活化的类比。最朴素的CMake写法相当于你住进一个出租房拉个插线板就用。target模型这套东西相当于装修时规划电路哪一路负责什么、线径多大、怎么走管全部提前定好。出租房住一个人没问题来了客人、添了家电就不行了。C工程也是这样文件多了、依赖多了不好好规划CMake结构后面每次加功能都像重装一遍房子。1.2 进阶CMake学的是三块硬骨头我总结了进阶路线上最绕不开的三块内容。第一个是target及属性的传递机制也就是PUBLIC、PRIVATE、INTERFACE这套修饰符很多人用了三年CMake都没搞明白它到底在传什么。第二个是生成器表达式用一套CMakeLists适配多套构建配置避免到处写死路径和判断分支。第三个是包的导出和安装让写好的库能被find_package找到也让项目能一键发布给别人用。配套的东西还有不少比如CTest集成、CMakePresets统一构建配置、compile_commands.json配合编辑器智能跳转、交叉编译工具链、Windows下MinGW与GUI配置等。但你会发现这些说到底都是在target模型和生成器表达式的基础上做文章。所以进阶不是多记几条命令而是把这些底层概念串起来。下面我会从概念讲到实操最后把踩过的坑整理成清单一次性把这条路走通。2. 吃透核心概念target才是CMake的灵魂2.1 target、依赖与PUBLIC/PRIVATE/INTERFACE当我们写add_executable(main main.cpp)CMake就创建了一个名为main的target所有和这个目标有关的属性头文件路径、编译选项、宏定义、链接库都可以挂到它身上。target_link_libraries除了把依赖关系串起来还有个经常被忽略的作用依赖信息的传递。拿一个真实场景举例。你写了一个logger库内部用了spdlog头文件里暴露了一个Logger类你的可执行程序exe链接logger。这个依赖关系怎么声明add_library(logger STATIC logger.cpp logger.h) target_include_directories(logger PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(logger PRIVATE spdlog::spdlog)这里三个修饰符的含义要理解透PRIVATE表示仅供logger自己使用下游不需要知道PUBLIC表示logger的接口上会用到下游exe在编译时也必须拿到spdlog的include路径和链接库INTERFACE是只有接口需要、实现不需要通常用于纯头文件库或接口库。exe只需要写一句target_link_libraries(exe PRIVATE logger)就能自动把PUBLIC的内容传过来。这个机制对接口的可维护性帮助极大。实际工程里最典型的错误是库的公有头文件已经包含了第三方头文件结果链接关系用了PRIVATE导致下游编译时找不到头文件。最后只能靠给每个target手动补include路径时间长了CMakeLists里全是重复路径和选项改一次依赖到处都是坑。记住一个原则编译选项和头文件目录像依赖一样也要想清楚是PUBLIC、PRIVATE还是INTERFACE。这会直接影响别人用你的库时是否顺畅。下面用一个表格把三者的区别说清楚。修饰符作用范围典型使用场景PRIVATE仅当前target实现细节中使用的第三方库、内部宏定义PUBLIC当前target及所有下游target公有头文件暴露的include路径、链接库INTERFACE仅下游target纯头文件库、接口库当前target自身不需要2.2 生成器表达式一套配置多份输出生成器表达式大概是CMake里最被低估的功能了。它长这样$...不是普通变量而是在CMake生成构建系统时才计算。这意味着同一个CMakeLists可以针对不同的配置、平台、生成器输出不同的内容。常见的几个要记牢$ 拿当前构建类型$BUILD_INTERFACE:...和$INSTALL_INTERFACE:...区分构建时的include路径和安装后的include路径$TARGET_FILE_DIR:tgt拿到目标所在目录$TARGET_FILE:tgt拿到目标的完整文件名。看起来有点抽象但实际用起来非常顺手。用一个例子说明它的价值。一个库在源码树里include目录是src/include安装到系统后头文件被放到include/xxx。如果你直接写target_include_directories(proto PUBLIC src/include)那install导出的包里的include路径就是错的。正确写法是用生成器表达式区分target_include_directories(proto PUBLIC $BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/include $INSTALL_INTERFACE:include )构建时用源码路径安装后用相对前缀include一套配置文件两个环境都成立。这算是进阶CMake必须掌握的核心技巧。生成器表达式还能跟条件判断配合做编译选项比如只在Release下加-O3只在MSVC下开某个警告开关这些后面3.2节会有具体例子。2.3 配置文件与包让find_package真正好用会写CMakeLists还不够进阶的一大难题是“让别人能方便地用你的库”。如果你只是把库编译出来别人拿到手还得自己找头文件目录、找库文件、猜编译选项用起来非常痛苦。CMake的解决办法是install(EXPORT)加配置文件模板。给一个最小可用的例子。假设你有个core库希望安装后别的项目能find_package(core REQUIRED)install(TARGETS core EXPORT coreTargets ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include ) install(DIRECTORY include/ DESTINATION include) install(EXPORT coreTargets FILE coreTargets.cmake NAMESPACE core:: DESTINATION lib/cmake/core)然后准备一个coreConfig.cmake.in模板PACKAGE_INIT include(${CMAKE_CURRENT_LIST_DIR}/coreTargets.cmake) check_required_components(core)在CMakeLists里用configure_package_config_file生成coreConfig.cmake再用write_basic_package_version_file写版本文件。这套东西玩熟之后自己的库也好、集成开源第三方库也好都会变得非常干净。如果拿到的SDK没提供CMake config怎么办比如TDengine的C/C接口官方可能只给你头文件和动态库。我习惯用imported target自己封装一层add_library(taos SHARED IMPORTED) set_target_properties(taos PROPERTIES IMPORTED_LOCATION /opt/taos/lib/libtaos.so INTERFACE_INCLUDE_DIRECTORIES /opt/taos/include )这样业务代码里就只用target_link_libraries(app PRIVATE taos)不用到处写路径。将来如果官方出了CMake配置文件只改这一处就行。这种封装习惯是从“能用”到“好维护”的关键转变。3. 实操搭建一个可复用的进阶CMake工程3.1 合理的目录结构工程不要写成一个大杂烩我自己比较推荐的工程目录把功能拆成app、core、third_party和tests四个区域project/ ├── CMakeLists.txt ├── CMakePresets.json ├── app/ # 可执行程序入口 ├── core/ # 项目自己的库 │ ├── CMakeLists.txt │ ├── include/core/ │ └── src/ ├── third_party/ # 第三方程库 ├── tests/ # 测试代码 └── cmake/ # 工具链、配置文件模板顶层CMakeLists负责全局设置cmake_minimum_required、project、C标准、全局编译选项、add_subdirectory。子目录CMakeLists只关注自己提供的target。我见过很多人把全部内容写进一个CMakeLists里短时间没毛病但core里的库、app的可执行文件、测试的target都要定义时文件会膨胀到几百行稍微调整就牵连一片。add_subdirectory和FetchContent怎么选如果第三方库是Git仓库且网络状况好FetchContent非常方便直接把依赖当target加入项目如果公司网络受限或依赖很稳定不如把库源码放在third_party里add_subdirectory。我自己常用的原则小工具库用FetchContent大而全的平台库如Qt、TDengine用系统安装或指定路径。还要注意把依赖版本固定住别让构建结果随上游提交漂移不然今天能编译明天可能就挂了。3.2 从零写主CMakeLists与子目录配置给一个相对完整又不过度设计的例子。场景是做一个用raylib绘制界面、用TDengine写数据的传感器数据查看工具。先看主文件cmake_minimum_required(VERSION 3.20) project(sensor_demo VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) option(SENSOR_ENABLE_TESTS Build tests ON) option(SENSOR_USE_STRIP Strip binary on release install OFF) add_subdirectory(core) add_subdirectory(app) if(SENSOR_ENABLE_TESTS) enable_testing() add_subdirectory(tests) endif()core里的库add_library(sensor_core sensor.cpp database.cpp) add_library(sensor::core ALIAS sensor_core) target_include_directories(sensor_core PUBLIC $BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include $INSTALL_INTERFACE:include ) target_link_libraries(sensor_core PRIVATE spdlog::spdlog) find_package(TDengine REQUIRED) target_link_libraries(sensor_core PRIVATE tdengine)app里的可执行文件add_executable(sensor_app main.cpp) target_link_libraries(sensor_app PRIVATE sensor::core raylib)关注几个细节ALIAS targetsensor::core能让我们不暴露真实target名将来重命名时影响面小。option开关控制功能别人拿到工程能一眼看出哪些可以关。C17标准在顶层设置一次子目录继承。TDengine官方如果没提供CMake模块就按2.3里imported target的方式自己封装。这样核心逻辑和界面逻辑被拆成两个库模块后续加测试也容易。3.3 strip指令、install、CTest与Presets一次讲透热词里反复出现“cmake中添加strip指令”这里专门说清楚。strip是去掉符号表、压缩二进制体积的工具Release发布包非常需要。在CMake里做strip有几种方式。最可控的做法是给目标设置STRIP属性并且用条件判断只影响Release构建if(SENSOR_USE_STRIP AND CMAKE_BUILD_TYPE STREQUAL Release) set_target_properties(sensor_app PROPERTIES STRIP TRUE) endif()也可以在install环节统一处理命令是cmake --install build --strip。这种方式的好处是源码目录不用做任何特殊设置只在打包时才strip。我个人更推荐这个用法避免开发调试阶段误伤符号表。我曾经在Debug模式开了STRIP属性结果调试时断点全部失效变量全都显示“optimized out”排查了半天才发现是这个开关在作怪。CTest也算进阶必备。enable_testing()打开测试支持add_test(NAME 用例名 COMMAND 可执行文件)注册用例。把测试纳入CMake后本机和CI都用ctest统一跑不用每个同事手工记命令。配合CDash或者GitLab CI都可以直接用。CMakePresets则是新版本CMake强烈推荐的方案。以前换一台机器配置命令全靠记忆cmake -DCMAKE_BUILD_TYPERelease -G Ninja ..。有了CMakePresets.json把配置固化下来团队每个人都能用同样的cmake --preset release一键搞定。VSCode的CMake插件也读取Presets选好预设就能直接配置构建调试。顺便说下cmake下载安装的问题。有些环境不能联网apt install不可用。做法是从官网下载cmake的二进制tar包拷进目标机器解压到/opt/cmake然后改PATH。如果必须源码编译注意老系统可能遇到OpenSSL版本问题比较折腾所以优先选预编译包。Ubuntu 18.04自带CMake一般只有3.10太老FetchContent、Presets这些特性都用不了强烈建议升级。装完检查cmake --version确认路径对了别用着旧版本排半天错。3.4 对接VSCode、Qt、raylib、MinGW与交叉编译热词里一大半都是VSCode配C/C环境相关其中非常典型的问题是“vscode c所有的函数变量都没办法跳转”。这个问题绝大多数时候不是装插件就完事而是编辑器没拿到编译时的详细信息包括头文件路径、宏定义、include顺序。解决思路就是让VSCode读compile_commands.json。CMake生成compile_commands.json非常简单配置时加-DCMAKE_EXPORT_COMPILE_COMMANDSON或者在CMakeLists里写set(CMAKE_EXPORT_COMPILE_COMMANDS ON)。生成的compile_commands.json在build目录里。然后在VSCode的c_cpp_properties.json里设置compileCommands: ${workspaceFolder}/build/compile_commands.json。之后函数跳转、类型提示基本都能恢复正常。这个技巧是解决跳转失败最有效的方法比手动填includePath靠谱得多。Qt项目现在用CMake也是主流。Qt 6官方全面转向CMakeQt 5同样支持。用CMake写Qt项目find_package(Qt6 COMPONENTS Widgets)之后target_link_libraries里加上Qt6::WidgetsCMake会自动处理moc、rcc、uic等步骤不需要手工跑moc脚本。相比qmakeCMake把资源管理、翻译文件、UI文件的处理都统一在target属性里心智负担小很多。raylib集成更直接。它是用CMake构建的游戏库可以add_subdirectory也可以FetchContentinclude(FetchContent) FetchContent_Declare(raylib GIT_REPOSITORY https://github.com/raysan5/raylib.git GIT_TAG 5.0) FetchContent_MakeAvailable(raylib) target_link_libraries(sensor_app PRIVATE raylib)这样搭C小游戏项目非常快图形和输入都交给raylibCMake只负责把依赖粘起来。配合前面sensor_demo的例子能直观感受到FetchContent有多省事。MinGW是Windows上的GNU工具链热词里“cmake与mingw”也是高频问题。我的经验是用cmake -G MinGW Makefiles -S . -B build前提是gcc、g、mingw32-make都在PATH里。cmake生成的MinGW项目入口是mingw32-make不是make。如果遇到“sh.exe is in your PATH”报错是MinGW自带bash干扰了Makefiles的shell把sh.exe从PATH临时移开就好。Ninja生成器也很推荐Windows和Linux都统一用cmake -G Ninja速度快、依赖处理干净。交叉编译值得单独提一下比如在x86主机上构建启明星zynq开发板linux系统下的程序。重点不是CMake本身而是工具链文件。写一个toolchain-zynq.cmake指定CMAKE_SYSTEM_NAME、CMAKE_SYSROOT、CMAKE_C_COMPILER、CMAKE_CXX_COMPILER。然后配置时加-DCMAKE_TOOLCHAIN_FILE...。CMake的target模型在这里帮了大忙主机库和目标板库不会混在一起依赖关系依然清晰。4. 踩坑记录CMake使用中的常见问题与排查4.1 环境相关GUI配置、离线安装与路径问题先聊CMake GUI。GUI适合手工配置项目Source目录选源码根目录Build目录选build文件夹点Configure选生成器再点Generate。因为有缓存机制第一次Configure后选项会出现在列表里改完再Configure。命令行环境下我一般不用GUI但拿它做可视化排查非常直观——GUI里的缓存变量列表比翻CMakeCache.txt清楚得多。很多新手在“cmake gui”里卡住多半是忘了每次改完选项要点一次Configure再Generate直接Generate会提示过期的配置。离线安装CMake踩过坑后我的排序是首选官方预编译二进制包次选源码编译不要在企业内网硬扛。源码编译时间长且可能触发OpenSSL等依赖问题。装完之后cmake --version还是旧版几乎都是PATH问题。用which cmake查一下到底指向哪里把新路径放到PATH最前面必要时删掉旧软链。路径问题也要重视。Windows下工程路径里有中文字符有些老编译器会出问题MinGW对路径中的空格也敏感。最稳妥的办法是把工程放在纯英文无空格的路径。Linux下则注意build目录不要放在只读目录。另外构建目录和源码目录分离是好习惯否则切分支时CMakeCache可能残留旧信息导致“我明明改了源码编译的还是旧版本”的灵异事件。4.2 构建相关静态库链接顺序与strip时机静态库的链接顺序是经典问题。Linux链接器从左到右扫描如果库B被库A依赖一般要把A写前面、B写后面否则报undefined reference。CMake的target_link_libraries会自动按依赖关系排序所以只要用target驱动构建一般不会踩坑。一旦你手动用link_directories加link_libraries就可能碰到顺序问题。碰到undefined reference时先检查是不是手写链接顺序或漏了库再考虑循环依赖。还有一个和它类似的问题是混合静态和动态库。同一个第三方库在Linux下可能是libxxx.a在Windows下可能是xxx.lib配合xxx.dll。CMake的target机制会帮你隐藏这些后缀差异所以我一再强调尽量用target描述依赖不要用find_library加手写路径。这句是值回票价的。strip时机上面已经说过了这里把排查思路整理成一个速查表方便你对照。现象可能原因处理方式Debug断点失效、变量显示optimized out开了STRIP属性或编译优化检查target的STRIP和编译选项只在Release安装时stripundefined reference链接顺序错误、漏库、依赖方向不对检查是否有手写链接顺序用target_link_libraries替代DLL找不到报错动态库未复制到运行目录用cmake -E copy或install规则把DLL放到可执行文件旁配置后编译的还是旧代码build目录缓存了旧配置清理build目录重新配置VSCode函数变量全部无法跳转没有compile_commands.json或未指定开启CMAKE_EXPORT_COMPILE_COMMANDS并配置c_cpp_properties4.3 平台差异Windows与Linux的库与调试Windows上用CMake最常碰到动态库运行时找不到DLL。程序编译通过双击运行时报“无法启动此程序因为计算机中丢失xxx.dll”之类。解决办法是运行时把依赖DLL所在目录加入PATH更规范的是用cmake -E copy_directory把依赖DLL复制到可执行文件旁边或者用install规则统一发布。MinGW还常遇到libstdc-6.dll这类运行时DLL发布时记得一并带上。Linux和Windows的库文件名规则差别很大Linux下静态库是libxxx.a动态库是libxxx.soWindows下静态库是xxx.lib动态库是xxx.dll加import library xxx.lib。CMake的target机制把这些差异都封装掉了这也是为什么我建议你的CMakeLists里尽量少出现针对平台的if分支把差异收敛到工具链层。写CMake最好能达到“同一套逻辑换平台只换生成器和编译器”的效果工程化水平就到了另一个层次。最后补充一下VSCode跳转失败的排查顺序先确认build目录里有没有compile_commands.json没有就去CMakeLists或CMakePresets里打开导出开关有了这个文件还不行就在c_cpp_properties.json里指定它并确认includePath没被手动配置覆盖最后检查VSCode右下角选中的C编译器Kit是否和CMake使用的是同一套工具链。严格按照这个顺序走绝大多数跳转问题能解决。我个人在实际项目里的体会是CMake写得好不好不在于命令记得多全而在于是否愿意把构建、测试、安装、发布当成一个整体来设计。先把target模型想清楚再去碰生成器表达式和包导出基本不会走偏。希望这篇踩坑总结能让你少花点时间在构建系统上把精力放回C本身。

相关新闻

OpenRig:本地AI开发的轻量级调度中枢与调试框架

OpenRig:本地AI开发的轻量级调度中枢与调试框架

1. OpenRig 是什么:一个被误读但极具潜力的本地 AI 工作流调度中枢 OpenRig 这个名字在当前的开发者社区里,正经历一场典型的“命名混淆危机”。它既不是某个广为人知的开源项目官方名称,也不是某家大厂发布的标准化工具套件——而是一个在 …

2026/10/5 7:49:50 阅读更多 →
openrig:用YAML统一编排Claude Code与Codex的AI编码工作台

openrig:用YAML统一编排Claude Code与Codex的AI编码工作台

1. 从 openrig 这个标题说起:它到底想解决什么问题第一次看到openrig这个名字,我脑子里蹦出来的第一反应是“open rig”,也就是“开放式的装配台/工作台”。结合热搜词里那一长串Claude Code、Codex、YAML、Node.js,基本可以判断…

2026/10/5 7:49:50 阅读更多 →
内存从 70GB 砍到 3GB:Edge0 的 SSD 专家卸载如何让消费者硬件跑动 35B MoE

内存从 70GB 砍到 3GB:Edge0 的 SSD 专家卸载如何让消费者硬件跑动 35B MoE

内存从 70GB 砍到 3GB:Edge0 的 SSD 专家卸载如何让消费者硬件跑动 35B MoE 【免费下载链接】Edge0 项目地址: https://gitcode.com/gh_mirrors/ed/Edge0 Edge0 是一个开源的流式 MoE 推理框架,核心能力是 SSD 专家卸载 预路由预测(…

2026/10/5 7:49:50 阅读更多 →

最新新闻

从淮师大6个月全量上线经验出发 省属高校数据治理型智慧校园落地全场景高频答疑

从淮师大6个月全量上线经验出发 省属高校数据治理型智慧校园落地全场景高频答疑

省属高校在已有数字化校园基础上启动智慧校园升级,合理的项目落地周期一般是多久?参考已落地的实操经验,适配省属高校存量系统的智慧校园升级项目,采用高效协同模式的前提下,招标后1个月即可完成核心平台搭建&#xff…

2026/10/5 9:46:38 阅读更多 →
Origin Pro 2023绘制Piper三线图全攻略:从数据换算到论文级出图

Origin Pro 2023绘制Piper三线图全攻略:从数据换算到论文级出图

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

2026/10/5 9:46:38 阅读更多 →
LPC546xx USB VBUS检测设计:从阈值计算到冷启动排查

LPC546xx USB VBUS检测设计:从阈值计算到冷启动排查

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

2026/10/5 9:46:38 阅读更多 →
工业级MRAM与PIC32嵌入式存储方案:高频写入与掉电保护实战

工业级MRAM与PIC32嵌入式存储方案:高频写入与掉电保护实战

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

2026/10/5 9:46:38 阅读更多 →
均匀分布生成高斯分布的三大核心算法解析

均匀分布生成高斯分布的三大核心算法解析

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

2026/10/5 9:46:38 阅读更多 →
安卓逆向学习路线:从应用层分析到Native层对抗

安卓逆向学习路线:从应用层分析到Native层对抗

这几年时不时就有人跑来问我:安卓逆向怎么学?是不是得会汇编?要不要先学破解?也有人直接在搜索框里敲“android 逆向学习路线”“安卓逆向教程”,然后被一堆零散的资料劝退。作为常年在这行折腾的人,我太清…

2026/10/5 9:45:38 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

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

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

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

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/4 11:40:45 阅读更多 →
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/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练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/4 20:14:29 阅读更多 →