musl을 이용해서 컴파일 하기

CharlieMoon·2026년 1월 25일
post-thumbnail

로컬에서 빌드한 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이란?

musl은 경량 C 표준 라이브러리로, 정적 링크에 최적화되어 있다.
GLIBC의 대안으로 특히 임베디드 시스템과 컨테이너 환경에서 널리 사용된다.

주요 특징

장점:

  • 정적 링크 최적화 - 단일 실행 파일 생성 용이
  • 높은 이식성 - GLIBC 버전과 무관하게 실행
  • 작은 크기 - GLIBC보다 가볍고 컴팩트
  • 의존성 제거 - 시스템 라이브러리 불필요
  • 배포 간소화 - 단일 파일만 전송

단점:

  • 약간의 성능 저하 (5-10%, 특히 멀티스레딩)
  • 일부 GLIBC 전용 기능 미지원
  • 정적 링크로 인한 바이너리 크기 증가

GLIBC vs musl 비교

항목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을 사용하나?

  • musl이 적합한 경우

    • CLI 도구, 유틸리티
    • 컨테이너/Docker 이미지 (Alpine Linux)
    • 임베디드 시스템
    • 다양한 환경에 배포해야 하는 경우
    • 구형 시스템에 배포하는 경우
  • GLIBC가 적합한 경우

    • 최고 성능이 필요한 서버 애플리케이션
    • GUI 애플리케이션 (GTK, Qt 등)
    • 복잡한 C 라이브러리 의존성이 있는 경우

musl을 선택한 이유

대상 환경은 Synology NAS이다.
Synology DSM은 시스템 핵심 라이브러리인 GLIBC를 함부로 업데이트할 수 없는 환경이다. GLIBC 버전을 변경하면 DSM 전체가 불안정해지거나 부팅 불가 상태가 될 위험이 있다.
이러한 제약 때문에 시스템 라이브러리에 의존하지 않는 musl 정적 링크 방식을 선택했다.

musl로 빌드하기

필수 도구 설치

sudo apt update
sudo apt install musl-tools gcc-arm-linux-gnueabihf

Rust 타겟 추가

rustup target add arm-unknown-linux-musleabihf

Cargo 설정

# ~/.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/ 디렉토리에 생성된다.

잘 실행이 되었다.

profile
산만한 개발자의 노트

0개의 댓글