首先要有一个linux环境,可以是群晖的dsm或ubuntu,或debian


先下载 toolchain

选择版本后,下载对应平台的文件

image.png


下载Synology NAS GPL Source

选择版本后,先择linux-开头的对应内核版本的文件

image.png


root账户权限,使用winscp连接环境系统后,

安装所需软件:

plaintext
apt-get install build-essential
apt-get install libncurses-dev
apt-get install bison
apt-get install flex
apt-get install libssl-dev
apt-get install libelf-dev
apt-get install libncurses5-dev
apt-get install bc
apt-get install dialog
apt-get install dpkg-dev
apt-get install autocon

创建一个工作目录,例如在home里创建syno

plaintext
mkdir /home/syno

上传toolchain文件到工作目录:

image.png

使用下面命令,解压文件到当前目录

plaintext
tar -xvf *.txz

解压后,进入解压后的目录,上传GPL sources文件,

image.png

再次使用解压命令解压到当前文件夹

plaintext
cd x86_64-pc-linux-gnu
tar -xvf *.txz

进入解压后的目录,不同内核版本目录不同

plaintext
cd linux-4.4.x

image.png

复制平台对应的配置文件到此目录,

4.4内核的配置文件在synoconfigs目录内

5.1内核的配置文件在synology/synoconfigs

image.png

plaintext
cp synoconfigs/geminilake .config

菜单化修改配置文件

plaintext
make menuconfig

找到需要编译的驱动,按空格键切换为,

image.png

保存后,创建环境,及执行清理文件,编译工作

plaintext
# 平台,x86或arm64
export ARCH=x86
# 工具路径,在上一级的bin目录
export CROSS_COMPILE=[前面的路径补全]/bin/x86_64-pc-linux-gnu-
# 清理
make clean
# 执行编译,j值为编译工作调用核心数
make modules -j4

如只需编译指定类型的驱动可使用M参数指定目录

plaintext
make modules M=./drivers/hwmon -j4

编译后的文件在路径drivers下面对应的分类里。

如螃蟹网卡驱动在这里:

image.png

关于编译时候报错:

plaintext
subcmd-util.h: In function ‘xrealloc’:
subcmd-util.h:58:31: error: pointer ‘ptr’ may be used after ‘realloc’ [-Werror=use-after-free]
   58 |                         ret = realloc(ptr, 1);
      |                               ^~~~~~~~~~~~~~~
subcmd-util.h:52:21: note: call to ‘realloc’ here
   52 |         void *ret = realloc(ptr, size);
      |                     ^~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors


代码原因

旧版本 Linux 的 linux-5.10.x/tools/lib/subcmd/subcmd-util.h 里写法有点问题,realloc 后还用 ptr,新编译器严格检查时会触发警告。

解决办法

编辑出错的文件:

tools/lib/subcmd/subcmd-util.h

找到这一段,大概在L50:

plaintext
static inline void *xrealloc(void *ptr, size_t size)
{
void *ret = realloc(ptr, size);
if (!ret && !size)
ret = realloc(ptr, 1);
if (!ret) {
ret = realloc(ptr, size);
if (!ret && !size)
ret = realloc(ptr, 1);
if (!ret)
die("Out of memory, realloc failed");
}
return ret;
}


改为:

plaintext
static inline void *xrealloc(void *ptr, size_t size)
{
    void *ret = realloc(ptr, size);
    if (!ret && !size)
        ret = realloc(NULL, 1);
    if (!ret) {
        ret = realloc(NULL, size);
        if (!ret && !size)
            ret = realloc(NULL, 1);
        if (!ret)
            die("Out of memory, realloc failed");
    }
    return ret;
}


再重新编译即可