Ubuntu20编译openwrt15疑难杂症排查与修复指南

📅 2026/6/29 18:33:56
Ubuntu20编译openwrt15疑难杂症排查与修复指南
1. 环境准备与GCC降级在Ubuntu 20.04上编译老版本的OpenWrt 15.05首先要解决的就是工具链兼容性问题。新系统默认的GCC 9.x版本会导致大量语法和链接错误就像开着一辆2023年的跑车去参加1998年的赛车比赛——发动机太先进反而会违反比赛规则。我实际操作时发现最稳妥的方案是将GCC降级到4.8版本。这个版本与OpenWrt 15.05的开发时期匹配度最高。具体操作步骤如下首先添加旧版软件源sudo vim /etc/apt/sources.list在文件末尾追加deb http://dk.archive.ubuntu.com/ubuntu/ xenial main deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe安装多版本GCC并设置优先级sudo apt-get update sudo apt-get install g-4.8 gcc-4.8 g-5 gcc-5 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 sudo update-alternatives --install /usr/bin/g g /usr/bin/g-4.8 40 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50 sudo update-alternatives --install /usr/bin/g g /usr/bin/g-5 50切换默认版本sudo update-alternatives --config gcc选择gcc-4.8对应的编号即可。这里有个坑要注意切换后建议重启终端会话否则可能遇到环境变量缓存问题。2. gnulib兼容性问题解决编译过程中最常见的错误就是gnulib库的兼容性报错典型表现为freadahead.c:91:3: error: #error Please port gnulib freadahead.c to your platform!这个问题本质上是新版glibc对文件锁操作的修改导致的。我摸索出的通用解决方案是定位到报错模块的源码目录cd build_dir/host/m4-1.4.17/执行以下修复命令sed -i s/IO_ftrylockfile/IO_EOF_SEEN/ lib/*.c echo #define _IO_IN_BACKUP 0x100 lib/stdio-impl.h这个修改的原理是用IO_EOF_SEEN宏替代已废弃的IO_ftrylockfile并添加必要的宏定义。类似的问题在bison、findutils等组件中都会出现都可以用相同方法解决。3. 设备号相关函数缺失问题当遇到如下错误时undefined reference to major undefined reference to minor undefined reference to makedev这是因为新版glibc将这些设备号操作函数移到了单独的sysmacros.h头文件。解决方法是在每个报错的源文件中添加头文件引用使用vim编辑报错文件vim build_dir/host/make-ext4fs-2015-05-01/contents.c在文件开头添加#include sys/sysmacros.h我统计过在完整编译过程中大约需要修改15-20个文件。这里分享一个快速批量修改的技巧grep -rl major( build_dir/ | xargs sed -i 1i #include sys/sysmacros.h4. PIE链接错误处理遇到如下错误时relocation R_X86_64_32S against .rodata can not be used when making a PIE object这是Ubuntu 20.04默认启用了PIE(Position Independent Executable)安全机制导致的。解决方法是在cmake的配置中添加编译参数修改bootstrap文件vim build_dir/host/cmake-2.8.12.2/bootstrap在约765行后添加cmake_c_flags${CFLAGS} -fpic -fPIC -fpie -fPIE在约815行后添加cmake_cxx_flags${CXXFLAGS} -fpic -fPIC -fpie -fPIE对于使用CMake的项目可以在CMakeLists.txt中添加foreach(lang C CXX) set(CMAKE_${lang}_FLAGS ${CMAKE_${lang}_FLAGS} -Wno-format -fpic -fPIC -fpie -fPIE) endforeach()5. gawk语法兼容性问题当看到如下警告时warning: regexp escape sequence \# is not a known regexp operator这是因为新版gawk对正则表达式语法更加严格。需要修改所有包含\#的awk脚本查找所有需要修改的文件grep -rl sub (/\\#./, \\); build_dir/统一修改为sub (/#./, );特别要注意libgpg-error相关组件中的多个.awk文件都需要修改。此外还需要将所有出现namespace关键字的地方替换为pkg_namespace避免与gawk内置关键字冲突。6. 函数重定义问题遇到如下错误时error: redefinition of msgidxof这是头文件包含关系导致的函数重复定义。解决方法是在errnos-sym.h文件中注释掉重复定义的函数#if 0 static GPG_ERR_INLINE int msgidxof (int code) { return (0 ? 0 : ((code 0) (code 140)) ? (code - 0) : -1); } #endif同时需要确保所有调用处使用统一的函数名。如果遇到undefined reference错误可能需要将errnos_msgidxof改为msgidxof。7. 依赖库版本问题当configure报错Building GCC requires GMP 4.2, MPFR 2.4.0 and MPC 0.8.0虽然OpenWrt自带这些库的源码但需要单独编译安装make tools/gmp/compile Vs make tools/mpfr/compile Vs make tools/mpc/compile Vs然后在对应工具的Makefile中添加编译参数CFLAGS-fPIE CPPFLAGS-fPIE最后在gcc的configure脚本中强制设置have_gmpyes跳过版本检查。这个方案虽然有点取巧但在实际测试中验证可行。8. 其他实用技巧在整个编译过程中我总结了几个提高效率的方法并行编译使用-j参数加速编译如make -j$(nproc)错误定位遇到错误时先查看最后出现的具体错误信息再向上追溯根本原因。日志记录建议使用Vs参数保留完整日志make Vs 21 | tee build.log增量编译修复错误后可以进入对应目录单独编译而不需要每次都从头开始。经过这些调整最终在Ubuntu 20.04上成功编译出了MT7628平台的OpenWrt 15.05固件。整个过程虽然踩了不少坑但解决问题的思路对处理其他老项目的跨版本编译也有参考价值。