
로컬에서 빌드한 Rust 바이너리를 임베디드 Linux 디바이스로 전송해 실행했더니 다음과 같은 에러가 발생했다.
./example: /lib/libc.so.6: version `GLIBC_2.28' not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.30' not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.33' not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.32' not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.34' not found (required by ./example)
개발 환경에서는 잘 실행되던 프로그램이 타겟 시스템에서는 GLIBC 버전 문제로 실행되지 않는 것이다.
빌드 환경의 GLIBC 버전(2.34)과 타겟 시스템의 GLIBC 버전(2.27 이하)이 맞지 않아 발생하는 호환성 문제다.
GLIBC 동적 링크 바이너리는 시스템의 libc.so.6 등의 공유 라이브러리에 의존하기 때문에, 타겟 시스템에 호환되는 버전의 라이브러리가 필요하다.
크게 두 가지 접근 방법이 있다:
1. GLIBC 버전 맞추기 - 타겟 시스템 업그레이드 또는 낮은 버전으로 재빌드
2. musl 정적 링크 - 외부 의존성을 제거하여 모든 환경에서 실행 가능
musl은 경량 C 표준 라이브러리로, 정적 링크에 최적화되어 있다.
GLIBC의 대안으로 특히 임베디드 시스템과 컨테이너 환경에서 널리 사용된다.
장점:
단점:
| 항목 | GLIBC 동적 링크 | musl 정적 링크 |
|---|---|---|
| 의존성 | libc.so.6 등 필요 | 없음 |
| 이식성 | 낮음 (버전 의존) | 높음 (모든 Linux) |
| 바이너리 크기 | 작음 | 큼 |
| 성능 | 우수 | 약간 느림 |
| 배포 | 복잡 | 간단 |
GLIBC 빌드:
$ ldd example
libc.so.6 => /lib/libc.so.6
libm.so.6 => /lib/libm.so.6
...
musl 정적 빌드:
$ ldd example
not a dynamic executable
musl이 적합한 경우
GLIBC가 적합한 경우
대상 환경은 Synology NAS이다.
Synology DSM은 시스템 핵심 라이브러리인 GLIBC를 함부로 업데이트할 수 없는 환경이다. GLIBC 버전을 변경하면 DSM 전체가 불안정해지거나 부팅 불가 상태가 될 위험이 있다.
이러한 제약 때문에 시스템 라이브러리에 의존하지 않는 musl 정적 링크 방식을 선택했다.
sudo apt update
sudo apt install musl-tools gcc-arm-linux-gnueabihf
rustup target add arm-unknown-linux-musleabihf
# ~/.cargo/config.toml 파일에 링커 설정 추가
[target.arm-unknown-linux-musleabihf]
linker = "arm-linux-gnueabihf-gcc"
cargo build --target arm-unknown-linux-musleabihf --release
빌드된 바이너리는 target/arm-unknown-linux-musleabihf/release/ 디렉토리에 생성된다.

잘 실행이 되었다.