从零构建NI LinuxRT:云环境下的完整编译指南

📅 发布时间:2026/7/6 12:29:04 👁️ 浏览次数:
从零构建NI LinuxRT:云环境下的完整编译指南
1. 为什么选择云端编译NI LinuxRT如果你和我一样是个喜欢折腾嵌入式Linux系统的开发者肯定对NI LinuxRT不陌生。它是美国国家仪器公司NI为其工业控制和数据采集硬件比如那些经典的CompactRIO、PXI控制器量身定制的实时操作系统。很多时候我们需要根据自己项目的特定需求比如添加一个特殊的驱动、集成一个第三方库或者仅仅是研究其构建系统去从头编译一套自己的NI LinuxRT镜像。但问题来了这编译过程可不是一般的“吃”硬件。官方文档里轻描淡写但真干起来你会发现它对CPU核心数、内存大小和硬盘IO速度的要求高得吓人。我最初尝试在自己的工作站i9-12核、64G内存上编译结果光是“bitbake nilrt-base-system-image”这一步就跑了将近20个小时期间内存占用一度冲到80G以上风扇狂转电脑几乎没法干别的。更别提从GitHub拉取源码和众多层Layer时那令人抓狂的网络速度和时不时出现的连接超时。所以折腾了几次之后我彻底放弃了本地编译的想法转向了云端。在阿里云、腾讯云这类服务商那里你可以按小时租用一台拥有几十核CPU、上百G内存、NVMe SSD的“怪兽级”服务器。编译时间能从20小时缩短到2-3小时网络也是机房内网下载飞快。最关键的是编译完释放资源成本可能就几十块钱比你升级一台电脑划算太多了。这篇文章我就手把手带你在云服务器上从零开始搭建一个专为编译NI LinuxRT 23.5/hardknott版本而生的完整环境直到生成那个梦寐以求的.iso引导文件。2. 云端服务器的选型与初始化2.1 如何挑选一台合适的“编译机器”选云服务器不能只看价格得针对编译任务的特点来。NI LinuxRT基于Yocto Project构建而BitBakeYocto的构建引擎有两个特点一是极度并行能榨干每一个CPU核心二是内存消耗巨大因为要同时解压、编译海量的软件包。我的经验是对于nilrt/23.5/hardknott这个版本以下配置是一个比较稳妥的起点CPU至少16核推荐32核或以上。核心数直接决定编译速度几乎是线性提升。选择计算优化型实例例如阿里云的ecs.c7、ecs.g7系列或者腾讯云的S5、SA3系列会有更好的性价比。内存这是最容易爆掉的资源。96GB是底线128GB会更从容。我曾用64GB内存尝试在编译webkitgtk这类大型组件时直接被OOM内存溢出杀手终止了进程。内存大小比CPU核心数更重要。硬盘500GB SSD是必须的。编译过程中tmp-glibc工作目录会膨胀到200GB以上再加上源码、下载的缓存DL_DIR空间消耗非常快。一定要选择云盘IOPS高的SSD云盘否则硬盘读写会成为瓶颈看着CPU空闲干着急。系统镜像选择Ubuntu 22.04 LTS 64位。这是经过大量社区验证与Yocto项目兼容性最好的发行版之一。避免使用太新或太旧的版本以免遇到奇怪的依赖库问题。基于以上我通常会选择阿里云的ecs.g7.8xlarge32核vCPU128G内存配合500GB ESSD PL1云盘按量付费。编译一次大约运行3-4小时成本在几十元人民币完全可以接受。2.2 系统初始化与基础配置当你拿到一台崭新的云服务器后别急着开干做好基础配置能让后续过程顺畅很多。首先以root用户登录更新系统并安装一些必备工具# 更新软件源索引 apt update apt upgrade -y # 安装我们后续会频繁使用的工具 apt install -y vim wget curl git htop tree screen接下来强烈建议创建一个专用的编译用户而不是一直使用root。这能避免一些权限上的小麻烦也更安全。# 创建用户例如命名为builder adduser builder # 将用户添加到sudo组方便执行特权命令 usermod -aG sudo builder然后切换到新用户并配置一下Git因为我们要从GitHub克隆大量代码su - builder git config --global user.name Your Name git config --global user.email your.emailexample.com # 可选配置GitHub加速使用国内镜像能显著提升克隆速度 git config --global url.https://hub.njuu.cf/.insteadOf https://github.com/最后我们调整一下系统的交换空间Swap。虽然我们有大量物理内存但设置一个Swap作为保险总是好的防止极端情况下进程被直接Kill。# 创建一个8GB的Swap文件 sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 使其永久生效 echo /swapfile none swap sw 0 0 | sudo tee -a /etc/fstab做完这些我们的“地基”就算打牢了。你可以运行htop命令看一眼一个干净、强大的编译环境正在等待我们。3. 搭建编译环境工具链与Docker3.1 获取NI LinuxRT源码与官方工具链NI LinuxRT的源代码托管在GitHub上。我们按照指定的分支进行克隆。这里要注意官方仓库包含了多个层meta-nilrt, meta-nilrt-hardknott等我们通过--recursive或后续的submodule命令来完整获取。# 切换到用户主目录或者你专门为项目准备的目录 cd ~ # 克隆指定分支的源码。注意分支名是 nilrt/23.5/hardknott git clone -b nilrt/23.5/hardknott https://github.com/ni/nilrt.git cd nilrt # 确保切换到正确的发布标签这里以23.5为例具体请查看仓库的tag # git checkout nilrt/23.5 # 初始化并更新子模块这是关键一步会拉取所有必要的Yocto层 git submodule init git submodule update --remote --checkout这个过程可能会花费一些时间因为子模块很多。耐心等待网络好的话十几分钟能完成。接下来是编译工具链。NI提供了一个预编译的交叉工具链这是编译目标系统x86-64 Core2架构二进制文件的基础。我们必须安装它。# 回到nilrt目录下载工具链安装脚本 # 注意这个URL是示例请务必从NI官方支持页面获取对应版本的正确链接 # 对于23.5版本工具链版本可能是10.0或更高 wget https://download.ni.com/support/softlib/labview/labview_rt/2023Q4/LinuxToolchains/linux/oecore-x86_64-core2-64-toolchain-10.0.sh # 赋予执行权限并安装 chmod x oecore-x86_64-core2-64-toolchain-10.0.sh sudo ./oecore-x86_64-core2-64-toolchain-10.0.sh安装过程中安装程序会询问安装路径默认是/opt/ni/oecore-x86_64-core2-64/10.0/直接回车即可。安装完成后非常重要的一步是将其加入当前shell的环境变量。但别急NI的构建脚本ni-oe-init-build-env通常会帮我们处理好所以我们暂时不需要手动设置。3.2 配置Docker构建环境NI官方强烈推荐使用Docker容器来进行构建这能保证环境的一致性避免宿主机的库版本差异导致构建失败。我们首先安装Docker。# 卸载可能存在的旧版本 sudo apt-get remove docker docker-engine docker.io containerd runc -y # 安装依赖包 sudo apt-get install -y ca-certificates curl gnupg lsb-release # 添加Docker官方GPG密钥使用国内镜像加速 curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 设置稳定版仓库阿里云镜像 echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装Docker引擎 sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 将当前用户builder加入docker组这样就不用每次都sudo了 sudo usermod -aG docker $USER # 注意需要退出当前shell重新登录或者执行 newgrp docker 使组生效 newgrp docker # 启动Docker服务并设置开机自启 sudo systemctl enable docker --now # 验证安装 docker run --rm hello-world看到“Hello from Docker!”的输出说明Docker安装成功。现在在nilrt源码目录下有一个docker/子目录里面包含了构建专用镜像的脚本。# 回到nilrt根目录 cd ~/nilrt # 构建名为 build-nilrt 的Docker镜像 sudo bash ./docker/create-build-nilrt.sh这个脚本会基于一个特定的基础镜像安装所有在容器内编译NI LinuxRT所需的包。构建镜像也需要一些时间取决于网络速度。完成后可以用docker images命令查看应该有一个build-nilrt的镜像。4. 深入构建配置与核心镜像编译4.1 初始化构建目录与关键配置环境准备好了现在我们进入真正的构建环节。首先我们需要初始化一个构建目录build并设置一些本地配置。# 在nilrt目录下初始化构建环境 . ./ni-oe-init-build-env执行这个命令后你的终端提示符会发生变化表示你已经进入了BitBake构建环境。同时它会在当前目录下创建一个conf文件夹里面最重要的是local.conf和bblayers.conf文件。bblayers.conf定义了参与构建的Yocto层通常不需要修改。我们需要重点关注local.conf它是我们调整构建参数的主战场。用编辑器打开它vim conf/local.conf这里有几个我强烈建议你根据云服务器情况修改的选项并行线程数找到BB_NUMBER_THREADS和PARALLEL_MAKE。将它们设置为你的CPU核心数比如32核的机器就设为32。这能最大化利用CPU资源。BB_NUMBER_THREADS 32 PARALLEL_MAKE -j 32下载目录默认下载缓存DL_DIR在构建目录内。我们可以把它指向一个更大的、可能持久化的位置比如挂载的数据盘。但为了简单首次编译可以不动。禁用QEMU/KVM在云服务器尤其是虚拟化实例上通常无法使用KVM加速。为了避免构建QEMU相关组件时出错我们需要注释掉对/dev/kvm的调用。找到类似MACHINE_FEATURES:append kvm的行或者直接搜索/dev/kvm将其注释行首加#。修改保存后我们可以验证一下BitBake版本bitbake --version正常会输出BitBake的版本信息。4.2 分步构建从包源到完整镜像NI LinuxRT的构建是分阶段的官方也推荐这样做便于调试和分步验证。我们一步步来。第一步构建包源Package Feeds这步会编译构成系统的基础软件包集合ni-core和ni-extra。这是最耗时的一步可能需要1-3小时取决于机器性能。# 构建核心包源 bitbake packagefeed-ni-core # 构建额外包源如果构建core失败先不要进行这一步 bitbake --continue packagefeed-ni-extra--continue参数允许在遇到某些非致命错误时继续构建。第一次编译我建议不加这个参数让它在第一个错误处停止方便我们排查问题。常见问题可能是网络超时导致某个包下载失败或者宿主机的某个依赖库版本不对。多试几次bitbake packagefeed-ni-coreYocto有缓存机制已成功的步骤不会重复执行。第二步构建安全模式根文件系统安全模式是一个最小化的、用于恢复和诊断的系统。bitbake nilrt-safemode-rootfs这一步会快很多因为它基于之前已经编译好的包。第三步构建运行模式镜像这是主系统包含了图形界面、LabVIEW Runtime等完整功能。bitbake nilrt-base-system-image这是另一个耗时大户因为它要集成所有东西生成最终的根文件系统镜像。耐心等待。第四步生成可引导的ISO恢复镜像这是我们的最终目标一个可以烧录到U盘或光盘用于安装或恢复NI LinuxRT的ISO文件。bitbake nilrt-recovery-media当所有命令都成功执行完毕后成果物就在tmp-glibc/deploy/images/x64/目录下。你会找到几个关键文件nilrt-safemode-rootfs-x64.tar.xz安全模式根文件系统压缩包。nilrt-base-system-image-x64.tar.xz运行模式根文件系统压缩包。nilrt-recovery-media-x64.iso我们最终需要的可引导ISO镜像。5. 实战避坑指南与经验分享编译过程很少一帆风顺尤其是在第一次。我把自己踩过的坑和解决方案总结一下希望能帮你节省大量时间。坑1网络超时与下载失败这是最常见的问题。Yocto需要从全球各地的源码仓库下载软件包网络不稳定极易失败。解决方案使用代理或镜像源。对于git协议前面已经配置了GitHub镜像。对于http/https下载可以在local.conf中设置预镜像PREMIRRORS。例如添加国内的开源镜像站PREMIRRORS:prepend \ git://.*/.* https://mirrors.tuna.tsinghua.edu.cn/git/ \n \ ftp://.*/.* https://mirrors.tuna.tsinghua.edu.cn/ \n \ http://.*/.* https://mirrors.tuna.tsinghua.edu.cn/ \n \ https://.*/.* https://mirrors.tuna.tsinghua.edu.cn/ \n \ 另外对于特定的SRC_URI可以手动下载放到DL_DIR目录下BitBake会优先使用本地文件。坑2内存不足OOM Killer编译webkitgtk、chromium或llvm这类巨型组件时即便有96G内存也可能被耗尽。解决方案除了增加物理内存可以尝试在local.conf中限制这些“内存杀手”任务的并行度。例如为特定包设置更小的PARALLEL_MAKEPN:append:llvm PARALLEL_MAKE \-j 8\更根本的方法是如果你不需要这些大型组件可以在local.conf或镜像配方中将其移除IMAGE_INSTALL:remove。坑3Docker容器内权限问题有时在Docker容器内构建时会遇到文件权限错误导致构建失败。解决方案确保在宿主机上你的源码目录对Docker容器内的用户通常是build是可读写的。最省事的方法是在运行构建命令前检查目录权限。或者在启动容器时通过-v参数正确映射目录并指定用户ID。坑4bitbake命令卡住或报错“Task X failed”Yocto构建是一个复杂的过程某个任务失败会导致整个构建停止。解决方案首先查看错误日志。日志位置通常在tmp-glibc/work/architecture/package-name/version/temp/下比如log.do_compile或log.do_configure。根据日志中的具体错误信息去搜索大部分问题都有解决方案。清理特定包重新编译的命令是bitbake -c cleansstate package-name然后再次执行bitbake package-name。最后当你看到tmp-glibc/deploy/images/x64/nilrt-recovery-media-x64.iso这个文件安静地躺在那里并且文件大小在1GB以上时那种成就感是无与伦比的。你可以用md5sum检查一下它的完整性然后就可以用任何刻录工具如dd命令或Rufus把它写到U盘上去启动你的NI硬件了。整个云端编译之旅从服务器选购到ISO生成虽然步骤繁多但每一步都有其意义。