可以。你现在踩到的不是单个 `libc6` 问题，而是 **Debian/Ubuntu 发行版安装系统时自动维护了一整套隐式约定**。你自己做精简 sysroot 时，这些隐式行为都要手动还原，否则 GCC/ld/CMake 会报各种“明明有文件但找不到”的错误。

下面一次说完整。

---

# 1. 发行版真正安装包时做了什么

Ubuntu 不是简单把 `.deb` 文件解压到 `/`。正常 `apt install` / `dpkg -i` 会做这些事：

| 行为                    | 说明                                                  | 你用 `dpkg-deb -x` 是否会做 |
| --------------------- | --------------------------------------------------- | --------------------- |
| 解包文件                  | 把 deb 里的文件释放到根目录                                    | 会                     |
| 解析依赖                  | 自动安装 `Depends` 包                                    | 不会                    |
| 执行 `preinst/postinst` | 包安装前后脚本                                             | 不会                    |
| 执行 trigger            | 例如 `ldconfig`、icon cache、man-db                     | 不会                    |
| 维护 dpkg 数据库           | `/var/lib/dpkg/status`                              | 不会                    |
| 创建/更新 alternatives    | 例如 `/usr/bin/cc` 指向 gcc                             | 不会                    |
| 保持 symlink 布局         | `/lib`、`/bin`、`libc.so.6` 等软链接                      | 只解包原样；跨 Windows 打包可能丢 |
| 维护动态库缓存               | `/etc/ld.so.cache`                                  | 不会                    |
| 按 multiarch 放路径       | `/usr/lib/x86_64-linux-gnu`、`/lib/x86_64-linux-gnu` | 文件本身会解包，但你裁剪时可能漏      |

所以 `dpkg-deb -x` 只是：

```bash
把 deb 里的文件倒出来
```

不是：

```bash
完整安装一个 Ubuntu 包
```

---

# 2. sysroot 里必须同时有“运行库”和“开发文件”

你现在做 GCC/CMake 编译 sysroot，至少要分清这几类包。

## 2.1 `libc6`

提供 glibc 运行库，通常包含：

```text
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/libm.so.6
/lib/x86_64-linux-gnu/libpthread.so.0
/lib/x86_64-linux-gnu/libdl.so.2
/lib/x86_64-linux-gnu/librt.so.1
```

这些是运行期 ELF 文件。

你的错误：

```text
cannot find /lib/x86_64-linux-gnu/libc.so.6 inside sysroot
cannot find /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 inside sysroot
```

就是缺这类文件，或者这些文件在错误位置。

## 2.2 `libc6-dev`

提供 glibc 编译开发文件，通常包含：

```text
/usr/include/stdio.h
/usr/include/features.h
/usr/lib/x86_64-linux-gnu/crt1.o
/usr/lib/x86_64-linux-gnu/crti.o
/usr/lib/x86_64-linux-gnu/crtn.o
/usr/lib/x86_64-linux-gnu/Scrt1.o
/usr/lib/x86_64-linux-gnu/rcrt1.o
/usr/lib/x86_64-linux-gnu/libc.so
/usr/lib/x86_64-linux-gnu/libc_nonshared.a
```

注意：

```text
/usr/lib/x86_64-linux-gnu/libc.so
```

通常不是 ELF 动态库，而是 **ld linker script**。

里面会写类似：

```text
GROUP (
  /lib/x86_64-linux-gnu/libc.so.6
  /usr/lib/x86_64-linux-gnu/libc_nonshared.a
  AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 )
)
```

所以即使你有：

```text
/usr/lib/x86_64-linux-gnu/libc.so.6
```

也不够。因为 `libc.so` 脚本明确让链接器去找：

```text
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
```

## 2.3 `linux-libc-dev`

提供 Linux UAPI headers：

```text
/usr/include/linux/*.h
/usr/include/asm-generic/*.h
/usr/include/x86_64-linux-gnu/asm/*.h
```

这个是编译很多 Linux 程序需要的头文件，不提供 glibc runtime。

---

# 3. `/usr/lib` 和 `/lib` 不是可以随便互换的

你截图里有：

```text
sysroot/usr/lib/x86_64-linux-gnu/libc.so.6
```

但链接器要的是：

```text
sysroot/lib/x86_64-linux-gnu/libc.so.6
```

这是两个路径。

在真实 Ubuntu 系统里，发行版可能通过以下方式保证它们都正常：

```text
/lib 是真实目录
或者 /lib -> usr/lib
或者包里带了软链接
或者 loader/linker script 指向固定路径
```

但你自己裁剪 sysroot、再打包到 Windows 时，最容易丢的是：

```text
/lib
/lib64
软链接
绝对 symlink
```

尤其 WinRAR 会提示“跳过可能不安全的链接”，这就会破坏 Linux sysroot。

---

# 4. `/lib64` 也可能必须存在

x86_64 glibc 的动态加载器有时通过这些路径出现：

```text
/lib64/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
```

具体看你的：

```bash
cat "$sysroot/usr/lib/x86_64-linux-gnu/libc.so"
```

只要 `libc.so` 里写了某个绝对路径，例如：

```text
/lib64/ld-linux-x86-64.so.2
```

那么 sysroot 里就必须有：

```text
$sysroot/lib64/ld-linux-x86-64.so.2
```

只要它写的是：

```text
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
```

那么 sysroot 里就必须有：

```text
$sysroot/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
```

**规则很简单：linker script 里的绝对路径 `/xxx`，ld 使用 `--sysroot` 后会找 `$sysroot/xxx`。**

---

# 5. `/usr/lib/x86_64-linux-gnu/libc.so` 是关键

你不要只看有没有 `libc.so.6`。真正要看这个：

```bash
cat "$sysroot/usr/lib/x86_64-linux-gnu/libc.so"
```

然后把里面所有 `/lib/...`、`/usr/lib/...`、`/lib64/...` 的绝对路径都补齐。

可以用这个检查：

```bash
target=x86_64-linux-gnu
sysroot=/ae/sysroots/ubuntu2004

echo "[INFO] libc.so linker script:"
cat "$sysroot/usr/lib/$target/libc.so"

echo "[INFO] Absolute paths referenced by libc.so:"
grep -oE '/(lib64|lib|usr/lib)[^ )]+' "$sysroot/usr/lib/$target/libc.so" | sort -u

echo "[INFO] Check referenced files:"
grep -oE '/(lib64|lib|usr/lib)[^ )]+' "$sysroot/usr/lib/$target/libc.so" | sort -u | while read -r p; do
  if [ -e "$sysroot$p" ]; then
    echo "[OK]  $sysroot$p"
  else
    echo "[MISS] $sysroot$p"
  fi
done
```

这个比猜测更可靠。

---

# 6. 你这种精简 sysroot 必须手动还原的东西

最终 sysroot 至少应该有：

```text
usr/include/stdio.h
usr/include/features.h

usr/include/linux
usr/include/asm-generic
usr/include/x86_64-linux-gnu/asm

usr/lib/x86_64-linux-gnu/crt1.o
usr/lib/x86_64-linux-gnu/crti.o
usr/lib/x86_64-linux-gnu/crtn.o
usr/lib/x86_64-linux-gnu/Scrt1.o
usr/lib/x86_64-linux-gnu/rcrt1.o
usr/lib/x86_64-linux-gnu/libc.so
usr/lib/x86_64-linux-gnu/libc_nonshared.a

lib/x86_64-linux-gnu/libc.so.6
lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

lib64/ld-linux-x86-64.so.2    # 如果 libc.so 或工具链需要
```

另外常见还需要：

```text
lib/x86_64-linux-gnu/libm.so.6
lib/x86_64-linux-gnu/libpthread.so.0
lib/x86_64-linux-gnu/libdl.so.2
lib/x86_64-linux-gnu/librt.so.1
lib/x86_64-linux-gnu/libresolv.so.2
lib/x86_64-linux-gnu/libgcc_s.so.1
```

但 `libgcc_s.so.1` 最好来自你的 GCC 工具链，不要混旧系统版本，除非你明确知道搜索顺序。

---

# 7. 你之前的 rsync 白名单还要注意 symlink

你的白名单应该保留：

```bash
--include='/lib/'
--include="/lib/${target}/***"
--include='/lib64/***'
--include='/usr/'
--include='/usr/include/***'
--include='/usr/lib/'
--include="/usr/lib/${target}/***"
--include='/usr/lib/gcc/'
--include="/usr/lib/gcc/${target}/***"
--exclude='*'
```

但问题是：如果 `/lib` 是 symlink，或者里面的 `libc.so.6` 是 symlink，Windows 打包时可能丢。

所以给 Windows 工具链发布用，建议最后做一次“实体化”：

```bash
sudo cp -aL "$src" "$dst"
```

`-L` 的意义是：如果源文件是软链接，就复制软链接指向的真实文件。

---

# 8. `cc` 也是发行版隐式行为

你前面遇到的 `cc 9.4` 也是同一类问题。

Ubuntu 发行版通常提供：

```text
/usr/bin/cc -> /etc/alternatives/cc -> /usr/bin/gcc
```

但你自己 `make install` GCC 时，通常只生成：

```text
gcc
g++
c++
cpp
```

不一定生成：

```text
cc
```

所以如果 configure 里传了：

```text
CC=cc
```

而你的工具链目录没有 `cc`，shell 就会继续往 PATH 后面找，最后找到系统 `/usr/bin/cc`。

这也是发行版帮你做了 `update-alternatives`，你自己的工具链没有。

---

# 9. `dpkg-deb -x` 方式的正确认知

你现在这种函数：

```bash
install_iso_deb_to_sysroot_by_name "libc6-dev" ...
```

本质是：

```text
从 ISO pool 找 deb -> 解包文件 -> 放入 sysroot
```

它不会自动安装依赖。

所以如果你解 `libc6-dev`，它可能依赖：

```text
libc6
linux-libc-dev
```

但它不会帮你自动解这两个包。

而 Live ISO 的 `/pool` 里不一定有 `libc6`，因为 `libc6` 已经在：

```text
casper/filesystem.squashfs
```

里面了。

所以正确策略是：

```text
libc6：优先从已解出的 rootfs 复制/修正
libc6-dev：从 ISO pool 解包
linux-libc-dev：从 ISO pool 解包
```

---

# 10. 你应该采用的最终流程

## 第一步：unsquashfs 提取完整 rootfs

```bash
sudo unsquashfs -d /ae/sysroots/ubuntu2004 /media/wyc/Ubuntu\ 20.04.6\ LTS\ amd64/casper/filesystem.squashfs
```

这个里面通常已经有：

```text
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
```

## 第二步：从 ISO pool 解包开发包

```bash
libc6-dev
linux-libc-dev
```

## 第三步：生成精简 sysroot

只复制这些：

```text
/usr/include
/usr/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/lib64
/etc/ld.so.conf
/etc/ld.so.conf.d
```

## 第四步：修正 glibc runtime 绝对路径

检查：

```bash
cat "$sysroot/usr/lib/x86_64-linux-gnu/libc.so"
```

凡是里面写的绝对路径，必须在：

```text
$sysroot + 绝对路径
```

存在。

## 第五步：Windows 打包前实体化 symlink

尤其是：

```text
libc.so.6
ld-linux-x86-64.so.2
libm.so.6
libpthread.so.0
libdl.so.2
librt.so.1
libresolv.so.2
```

不要让 WinRAR 跳过软链接。

---

# 11. 最终检查命令

在 Linux 打包前，对最终 sysroot 跑：

```bash
target=x86_64-linux-gnu
sysroot=/path/to/final/sysroot

check() {
  if [ -e "$sysroot/$1" ]; then
    echo "[OK]   $1"
  else
    echo "[MISS] $1"
  fi
}

check "usr/include/stdio.h"
check "usr/include/features.h"

check "usr/lib/$target/crt1.o"
check "usr/lib/$target/crti.o"
check "usr/lib/$target/crtn.o"
check "usr/lib/$target/Scrt1.o"
check "usr/lib/$target/libc.so"
check "usr/lib/$target/libc_nonshared.a"

check "lib/$target/libc.so.6"
check "lib/$target/ld-linux-x86-64.so.2"

if [ -e "$sysroot/usr/lib/$target/libc.so" ]; then
  echo "[INFO] Checking absolute references in libc.so:"
  grep -oE '/(lib64|lib|usr/lib)[^ )]+' "$sysroot/usr/lib/$target/libc.so" | sort -u | while read -r p; do
    if [ -e "$sysroot$p" ]; then
      echo "[OK]   $p"
    else
      echo "[MISS] $p"
    fi
  done
fi
```

这个检查能直接解释你 CMake 那种错误。

---

# 12. 一句话总结

发行版隐式帮你维护了：

```text
依赖关系
multiarch 路径
/lib 与 /usr/lib 布局
/lib64 loader
glibc linker script 引用路径
软链接
cc alternatives
ldconfig/triggers
```

你现在不是在“正常安装 Ubuntu”，而是在做一个 **可发布到 Windows 的精简 Linux sysroot**。因此必须自己保证：

```text
linker script 里引用的绝对路径，在 sysroot 里真实存在
```

尤其是：

```text
sysroot/lib/x86_64-linux-gnu/libc.so.6
sysroot/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
```

不能只看：

```text
sysroot/usr/lib/x86_64-linux-gnu/libc.so.6
```
