文章

编译MT7620 OpenWrt的所有机型的固件

编译MT7620 OpenWrt的所有机型的固件

前置条件:准备WSL-Ubuntu16.04的编译环境

安装编译需要的插件

sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip sharutils libncurses5-dev ncurses-term zlib1g-dev gawk asciidoc libz-dev git-core uuid-dev libacl1-dev liblzo2-dev pkg-config libc6-dev curl libxml-parser-perl ocaml-nox

1.git clone https://git.openwrt.org/openwrt/openwrt.git

2.git checkout openwrt-18.06

3../scripts/feeds update -a

4../scripts/feeds install -a

5.make menuconfig

6.make download && make,等待固件编译成功

7.编译成功之后固件如下图所示


Debug

你在编译 OpenWrt 时遇到的 c-stack.c:55:26: error: missing binary operator before token "(" 错误,通常与较新版本的宿主系统(如 Ubuntu 22.04)编译较老版本的构建工具(如 m4)时遇到的兼容性问题有关。

​错误原因​​:
这个错误源于 Glibc 2.34 及以后版本中 SIGSTKSZ 的定义方式发生了变化,从之前的宏定义变成了一个变量。这导致在条件编译预处理语句(如 #elif HAVE_LIBSIGSEGV && SIGSTKSZ < 16384)中,SIGSTKSZ 无法再被直接用于编译时比较,从而引发语法错误。


🔧 解决方案

请按照以下步骤修改 c-stack.c 文件:

  1. ​找到文件位置​​:
    根据你的错误信息,c-stack.c 文件位于 /home/tzb/projects/openwrt/build_dir/host/m4-1.4.18/lib/c-stack.c。你可以使用 find 命令再次确认:

    1
    
     find /home/tzb/projects/openwrt -name "c-stack.c"
    
  2. ​修改文件​​:
    使用文本编辑器(如 nanovim)打开该文件:

    1
    
     nano /home/tzb/projects/openwrt/build_dir/host/m4-1.4.18/lib/c-stack.c
    

    定位到第55行附近,找到包含 #elif HAVE_LIBSIGSEGV && SIGSTKSZ < 16384 的条件编译块。​​注释掉​​有问题的 #elif 及其对应的 #endif 之间的内容。

    ​修改前​​:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
     #ifndef SIGSTKSZ
     # define SIGSTKSZ 16384
     #elif HAVE_LIBSIGSEGV && SIGSTKSZ < 16384
     /* libsigsegv 2.6 through 2.8 have a bug where some architectures use
        more than the Linux default of an 8k alternate stack when deciding
        if a fault was caused by stack overflow. */
     # undef SIGSTKSZ
     # define SIGSTKSZ 16384
     #endif
    

    ​修改后​​:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
     #ifndef SIGSTKSZ
     # define SIGSTKSZ 16384
     //#elif HAVE_LIBSIGSEGV && SIGSTKSZ < 16384
     /* libsigsegv 2.6 through 2.8 have a bug where some architectures use
        more than the Linux default of an 8k alternate stack when deciding
        if a fault was caused by stack overflow. */
     //# undef SIGSTKSZ
     //# define SIGSTKSZ 16384
     #endif
    

    保存并退出编辑器(在 nano 中按 Ctrl+O 保存,按 Ctrl+X 退出)。

  3. ​重新编译​​:
    返回到 OpenWrt 的根目录(/home/tzb/projects/openwrt),然后重新运行编译命令:

    1
    2
    3
    
     make -j$(nproc) V=s
     # 或者如果并行编译仍出现问题,使用单线程编译以更清晰地查看错误
     # make -j1 V=s
    

⚠️ 注意事项

  • ​修改的性质​​:此修改是针对​​构建主机​​的工具(host tool),旨在让编译过程继续下去,​​不会影响​​最终为目标设备(如路由器)生成的系统镜像或软件包的功能和安全性。
  • ​可能的其他错误​​:在后续编译过程中,你可能会遇到类似的兼容性问题。例如,libfakeroot.c 中可能缺少 _STAT_VER 的宏定义,导致编译错误。如果遇到,可以参考类似的方法,在相应文件中添加针对不同架构的定义:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      #ifndef _STAT_VER
      #if defined (__aarch64__)
      #define _STAT_VER 0
      #elif defined (__x86_64__)
      #define _STAT_VER 1
      #else
      #define _STAT_VER 3
      #endif
      #endif
    
  • ​彻底清理​​:如果修改后编译仍然失败,可以尝试先进行一次彻底的清理,然后再重新编译:

    1
    2
    3
    
      make clean
      # 或者更彻底的清理(这会删除所有编译好的文件,包括工具链,下次编译时间会很长)
      # make dirclean
    

💎 总结

这个错误是由于新版系统库与旧版构建工具之间的兼容性问题导致的。通过修改 c-stack.c 文件的源码,可以绕过这个 Glibc 变更带来的问题。修改后,编译通常能够继续进行。如果遇到其他类似错误,思路是类似的:找到源文件,根据错误信息进行针对性的兼容性修改。

希望这些步骤能帮助你解决问题!如果还有其他错误,建议运行 make -j1 V=s 来获取更详细的输出,以便精准定位。


从日志中可以看出,编译失败的具体原因是 m4 工具在编译过程中遇到了 freadahead.c 文件的兼容性问题。这是一个典型的宿主工具(host tool)在新系统上编译时遇到的 glibc 兼容性问题。

🔧 解决方案

1. 修改 freadahead.c 文件

打开问题文件:

1
nano /home/tzb/projects/openwrt/build_dir/host/m4-1.4.18/lib/freadahead.c

找到以下代码段(大约在92行):

1
2
3
#else
  #error "Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
#endif

将其修改为:

1
2
3
4
5
#elif defined(__GLIBC__)
  return (fp->_IO_read_end - fp->_IO_read_ptr);
#else
  #error "Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
#endif

2. 应用补丁(替代方法)

如果你需要多次编译或与他人共享解决方案,可以创建补丁文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 创建补丁目录
mkdir -p ~/patches

# 生成补丁
cat > ~/patches/0001-fix-freadahead-for-glibc.patch << 'EOF'
--- a/lib/freadahead.c
+++ b/lib/freadahead.c
@@ -89,6 +89,9 @@
   return fp->_r;
 #elif defined __sfer               /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin */
   return fp->_r;
+#elif defined(__GLIBC__)
+  /* Workaround for newer glibc versions */
+  return (fp->_IO_read_end - fp->_IO_read_ptr);
 #else
   #error "Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
 #endif
EOF

# 应用补丁
cd /home/tzb/projects/openwrt/build_dir/host/m4-1.4.18
patch -p1 < ~/patches/0001-fix-freadahead-for-glibc.patch

3. 重新编译 m4

1
2
3
4
5
# 清理 m4 的编译状态
make tools/m4/clean

# 重新编译 m4(使用详细输出)
make tools/m4/compile V=s -j1

📌 问题原因

这个错误是由于新版本的 glibc(特别是 2.28+)改变了 FILE 结构体的内部实现导致的:

  • 旧版本使用 _IO_read_ptr_IO_read_end
  • 新版本使用了不同的内部结构
  • m4 1.4.18 的 gnulib 库没有适配这个变化

💡 额外建议

  1. ​考虑更新 OpenWrt 版本​​:较新的 OpenWrt 版本可能已经修复了这个问题

  2. ​使用 OpenWrt 官方补丁​​:检查是否有官方补丁可用:

    1
    
     ls package/utils/m4/patches/
    

    如果有类似 *.patch 文件,确保它们已应用

  3. ​如果问题仍然存在​​:尝试使用更完整的补丁:

1
2
3
4
#elif defined _IO_EOF_SEEN || defined _IO_ftrylockfile
  if (fp->_IO_write_ptr > fp->_IO_write_base)
    return 0;
  return fp->_IO_read_end - fp->_IO_read_ptr;

⚠️ 注意事项

这个修改只影响宿主工具的编译(在构建机器上运行的 m4),不会影响最终生成的固件。这是解决此类兼容性问题的常见方法。

完成修改后,编译应该能够继续进行。如果遇到其他问题,请提供后续日志。

本文由作者按照 CC BY 4.0 进行授权