使用VS Code(Trae)在WSL中进行有AI智能体辅助的嵌入式Linux开发
前言在上一篇文章中笔者已经完成了基于TraeWSL的嵌入式Linux开发环境搭建主要是完成了在WSL上的开发BSP下载、交叉编译工具链配置与调试ADB工具传输代码环境搭建这是底层的准备工作无论是Trae还是VSCode都可以使用这个环境但是并没有介绍如何开始开发。所以在这篇文章中主要介绍了如何使用现代化的IDE进行有AI辅助的嵌入式Linux开发整个开发过程比传统的虚拟机方式优雅、方便一些。为何又使用VSCode进行开发可跳过不看笔者一开始仍然想用Trae进行开发但是这里遇到了一个问题微软对非自家IDE做了限制VSCode 官方插件市场的 C/C 插件仅允许自家产品使用Trae 等非官方产品被禁用。没有了C/C插件就没有了代码跳转的功能不过也有替代方案使用clangd工具但这又涉及到相应的配置为了省事笔者直接选择了VSCode。当然如果还想使用Trae进行开发也可以在WSL子系统中根据此前创建的备份镜像再装一个18.04的doker容器在Trae中配置clangd工具再新建一个容器主要是为了隔离可以随便折腾。配置clangd可以参考韦东山老师的博客文章【CSDN】在Windows使用VSCode搭建嵌入式Linux开发环境笔者有机会可能也会尝试一下这个方法。前置知识可跳过不看WSL架构:下面的两张WSL架构图图来自Trae的WSL官方文档和微软的VSCode WSL官方文档可以看出来本质都是一回事都是“客户端 - 服务端分离 文件系统映射” 的设计。微软官方文档这样介绍VSCode的WSL扩展允许直接从VSCode使用WSL作为全职开发环境可以在基于 Linux 的环境中进行开发使用 Linux 特有的工具链和实用程序并可在 Windows 的舒适环境中运行和调试基于 Linux 的应用程序。该扩展直接在 WSL 中运行命令和其他扩展因此用户可以编辑位于 WSL中的文件而无需担心路径问题、二进制兼容性或其他跨操作系统挑战。该扩展将在 WSL 内安装 VS Code Server此服务器独立于 WSL 中任何现有的 VS Code 安装。这使得 VS Code 能够提供本地品质的开发体验——包括完整的 IntelliSense代码补全、代码导航和调试——无论用户的代码托管在哪里。方案选择可跳过不看一开始想的是让VSCode进入容器下载了BSP、配置了交叉编译工具链中开发首先让VS Code 连接进入 WSL2接着使用Dev Containers 插件让 VSCode 从 WSL2 再深入连接进 Docker 容器内部。简要操作步骤运行容器点击左下角的远程开发按钮在命令面板中选择附加到正在运行的容器或Dev Containers: Attach to Running Container...选择自己的容器。按以上步骤操作后报错如图这个错误的原因是版本冲突使用的 VS Code 是 1.86 及以上版本该版本的 VS Code 远程服务器Remote Server强制要求运行环境的 GLIBC 版本 ≥ 2.28而我的容器是 Ubuntu 18.04系统自带的 GLIBC 版本固定为 2.27无法满足最低要求因此直接拒绝连接。尝试了几种方法后没有解决这个问题因此放弃使用这个「Attach to Container」的方式采用折中方案VS Code在WSL中写代码通过命令调用容器编译操作步骤如下。1️⃣方案核心原理与前置检查1.1 核心逻辑编辑端VS Code 运行在 WSL2 (Ubuntu 24.04) 中在这里写代码享受完整的语法高亮、代码补全。编译端通过 docker exec 命令远程 “遥控” Ubuntu 18.04 容器里的交叉编译工具链来编译代码。数据共享通过 Docker 的 -v 数据卷挂载确保 WSL 里改的代码容器里能立刻看到编译出的 .ko 文件WSL 里也能立刻拿到。1.2前置检查确认Docker正在运行确认容器存在且数据卷已挂载执行命令docker inspect imx6ull-1804 | grep -A 10 Mounts若创建容器时挂载过数据卷但这里没有查看到则可能的原因和解决方法见笔者的上一篇文章的5.1节。2️⃣配置VSCodeWSL环境在VSCode中确保已进入WSL即左下角显示蓝色的WSL: Ubuntu-24.04.4。2.1在VSCode中打开工作区点击文件——打开文件选择WSL里的挂载目录~/dev见上一篇文章在弹出的“是否信任此文件夹”中勾选并点击 “是我信任此作者”。2.2准备内核头文件代码索引VS Code 的代码补全引擎IntelliSense需要读取 Linux 内核的头文件才能识别 file_operations、kmalloc 等结构体和函数。由于我们现在不 “进入” 容器我们需要把容器里的内核源码复制一份到 WSL 供 VS Code 索引。在 WSL 的终端中执行这里只是个示例实际应用要修改为自己容器内的内核源码路径docker cp ubuntu-1804:/home/root/linux-imx-rel_imx_4.9.88 ~/kernel_headers。语法docker cp 容器名:容器内的内核源码路径 WSL本地存放路径。执行完后WSL 里的 ~/kernel_headers 目录下就有了完整的内核源码。2.3配置c_cpp_properties.json (代码智能提示)1.在 VS Code 中按 CtrlShiftP。2.输入并选择C/C: Edit Configurations (JSON)。这一步可能找不到C/C: Edit Configurations (JSON)这是因为没有把微软官方的「C/C 扩展」正确安装到当前生效的 WSL 环境中在Windows本地中安装这个扩展是不够的因为现在是在WSL的环境中VSCode的扩展是严格环境隔离的。所以要在左侧的扩展面板中找到C/C点击在 WSL: Ubuntu-24.04.4 中安装即可。3.将以下内容完整复制到打开的json文件中注意修改为自己的路径{ configurations: [ { name: IMX6ULL-Linux, includePath: [ ${workspaceFolder}/**, // 下面这三行指向刚才从容器复制到 WSL 的内核头文件 ${env:HOME}/kernel_headers/include, ${env:HOME}/kernel_headers/arch/arm/include, ${env:HOME}/kernel_headers/arch/arm/include/generated, // 如果有交叉编译工具链的头文件也可以加在这里 ${env:HOME}/kernel_headers/include/uapi ], defines: [ __KERNEL__, MODULE, __GNUC__, ARCHarm ], compilerPath: /usr/bin/gcc, cStandard: c99, cppStandard: c11, intelliSenseMode: linux-gcc-arm } ], version: 4 }2.4配置tasks.json实现一键编译这一步的作用是实现按下 CtrlShiftB 就能自动调用容器进行编译。1.在 VS Code 中按 CtrlShiftP。2.输入并选择Tasks: Configure Task。3.选择使用模板创建tasks.json文件或Create tasks.json from template。4.选择Others。5.将以下内容完整复制进去覆盖原有内容{ version: 2.0.0, tasks: [ { label: 编译 IMX6ULL 驱动模块, type: shell, command: docker, args: [ exec, ubuntu-1804, // 1. 替换为你的容器名 make, -C, /home/dev, // 2. 替换为容器内的源码挂载路径 ], group: { kind: build, isDefault: true }, problemMatcher: [$gcc], detail: 在 Docker 容器中使用交叉编译工具链编译 }, { label: 清理编译文件, type: shell, command: docker, args: [ exec, imx6ull-1804, make, -C, /home/dev, //替换为容器内的源码挂载路径,同上 clean ], problemMatcher: [] } ] }3️⃣日常开发完整流程以下步骤是模拟的开发流程。注意这里工作区还是在一开始打开的WSL的挂载文件夹~/dev。3.1写代码直接在 VS Code 里新建文件例如 hello_drv.c写一个驱动代码#include linux/module.h #include linux/kernel.h #include linux/init.h static int __init hello_init(void) { printk(KERN_INFO Hello, IMX6ULL!\n); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO Goodbye, IMX6ULL!\n); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE(GPL);3.2编写Makefile在同一目录下创建 MakefileCROSS_COMPILE : /home/....../arm-buildroot-linux-gnueabihf- KERNELDIR : /home/root/linux-imx-rel_imx_4.9.88 # 容器内的内核源码路径CURRENT_PATH : $(shell pwd)改成你自己的 obj-m : hello_drv.o build: kernel_modules kernel_modules: $(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) ARCHarm CROSS_COMPILE$(CROSS_COMPILE) clean: $(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) clean3.3一键编译按下快捷键CtrlShiftB观察下方的「终端」面板会看到Docker调用容器内的make开始编译。编译成功后可以在当前目录看到 hello_drv.ko等文件这是容器编译出来的但因为数据卷挂载WSL 里也能看到。3.4安装驱动由上一篇文章笔者已经在WSL子系统中安装好了ADB工具因此直接按文章中的步骤将开发板连接到PC上上电把USBattach到WSL中。接着执行adb devices查看设备查看到设备后执行adb push hello_drv.ko /root/某个目录。然后执行adb shell进入开发板系统进入存放hello_drv.ko的目录执行ismod安装这个驱动程序在执行rmmod命令卸载这个驱动程序之后执行dmesg可以看到两个输出信息如图这说明开发链路打通。3.5 AI智能体辅助开发正如文章标题指出耗费力气打通整个开发链路的一大原因之一就是要使用IDE中的智能体所以下面模拟一下使用智能体进行开发。在资源管理器中点开刚才的hello_drv.c文件打开右侧的侧栏这里就是与AI对话的窗口演示时笔者使用的是Copilot这里可以自主选择要使用的智能体比如Codex等。如图在窗口中给AI一条编辑指示它会根据指示完成操作。接着再次按快捷键编译将.ko文件push进开发板的目录执行ismod和rmmod再dmesg可以看到输出如图这说明可以使用AI工具进行辅助开发。未来也许可以将这整个流程交给智能体来做可能需要自己做一个MCP什么的暂时不是很懂。4️⃣其他4.1代码补全、跳转定义除了使用上面的C/C工具外也可以使用clangd工具建立索引实现代码补全、跳转定义等功能不过要进行相应的配置。实际使用时C/C的反应比较慢有时跳转不到函数或变量的定义后续有机会笔者可以考虑使用clangd当然也可以考虑使用Trae进行开发它与VSCode的差别不大基本是相通的。4.2驱动文件的存放目录在上面的步骤中驱动的hello_drv.c和Makefile文件都放在了挂载目录~/dev下实际开发中为了方便管理最好在此目录下为每个程序创建一个目录比如hello_drv_test将前面的两个文件都移动到这个目录下然后一定要将tasks.json文件中的编译路径重新指向刚才创建的文件夹hello_drv_test。如果后续要加新的驱动比如led_drv只需要 3 步在工作区根目录即WSL的挂载目录新建led_drv文件夹放入led_drv.c和对应的Makefile。在tasks.json里修改编译任务修改编译路径为/home/dev/led_drv。按下CtrlShiftB即可选择对应驱动编译完全不影响原有代码。4.3微软的WSL官方文档是个非常好的参考资料里面有很多WSL相关的知识