Embedded System/Embedded Linux Build Systems buildroot

Buildroot 임베디드 파일 시스템 크기 최적화: BusyBox, Musl, SquashFS 및 Binary Strip 설정

임베디드 친구 2025. 5. 6. 08:43
반응형

1. Buildroot 임베디드 파일 시스템 크기 최적화 배경: SquashFS 및 Musl C Library 도입의 필요성

임베디드 리눅스 시스템 개발 환경에서는 NAND Flash, NOR Flash, eMMC 등 저장 공간의 물리적 제약이 존재합니다. Buildroot 기본 구성(Default Configuration)으로 빌드한 루트 파일 시스템(RootFS)은 불필요한 패키지, 디버그 심볼, 미사용 라이브러리를 포함하여 용량이 비대해질 수 있습니다.

파일 시스템 크기가 증가하면 저장 장치 비용이 상승하고, 부팅 속도가 지연되며, OTA(Over-The-Air) 펌웨어 업데이트 시 네트워크 대역폭 소비가 늘어납니다. Musl C 라이브러리 전환, SquashFS 압축 파일 시스템 적용, Binary Strip 처리, BusyBox 미사용 유틸리티 제거 기법을 적용하면 파일 시스템 크기를 최소화하고 런타임 성능을 향상시킬 수 있습니다.

2. Buildroot RootFS 용량 최적화 핵심 요약 (TL;DR)

  • C 라이브러리 및 압축 최적화: make menuconfig에서 Toolchain C library를 Musl(BR2_TOOLCHAIN_USES_MUSL=y)로 변경하고, Filesystem images에서 SquashFS(BR2_TARGET_ROOTFS_SQUASHFS=y)를 선택합니다.
  • 디버그 심볼 및 패키지 제거: BR2_STRIP_strip=y 설정으로 타겟 바이너리의 심볼을 제거하고, target-finalize 스크립트 또는 후처리 스크립트(Post-build script)를 활용해 /usr/share/doc, /usr/share/man 디렉터리를 삭제합니다.
  • BusyBox 및 커널 최적화: make busybox-menuconfig를 통해 미사용 CLI 명령어를 제거하고, make linux-menuconfig에서 불필요한 파일 시스템 및 드라이버 모듈을 비활성화합니다.

3. Buildroot 용량 최적화 상세 분석 및 구현

3.1 파일 시스템 최적화 기법별 특징 및 용량 절감 효과 비교

최적화 기법 (Optimization Technique) 주요 적용 대상 (Target Component) 설정 옵션 (Configuration Symbol) 용량 절감 효과 (Size Reduction Impact)
C Library 전환 Glibc / Musl / uClibc BR2_TOOLCHAIN_USES_MUSL=y 수 MB ~ 십수 MB 절감 (Glibc 대비)
압축 파일 시스템 적용 RootFS Image BR2_TARGET_ROOTFS_SQUASHFS=y RootFS 전체 용량 최대 60~70% 압축
Binary Strip Executables & Libraries BR2_STRIP_strip=y 바이너리 용량 30~50% 감소
BusyBox 경량화 Core Utilities (/bin, /sbin) make busybox-menuconfig 수백 KB ~ 수 MB 절감
문서 및 헤더 제거 /usr/share/man, /usr/include BR2_PACKAGE_OVERRIDE_FILE / Post-build Script 수 MB 절감

3.2 Musl C Library 및 SquashFS 파일 시스템 설정

Glibc(GNU C Library)는 기능이 풍부하지만 임베디드 환경에서는 메모리와 바이너리 크기 부담이 큽니다. Musl C Library 또는 uClibc-ng를 사용하면 크기를 크게 줄일 수 있습니다. 또한, 읽기 전용(Read-Only) 파일 시스템인 SquashFS를 적용하면 XZ 또는 ZSTD 압축을 통해 높은 압축률을 얻을 수 있습니다.

주의 (Technical Correction): .config 파일을 직접 수정하여 BR2_PACKAGE_PYTHON=n과 같이 작성하는 방식은 make 실행 시 Kconfig 의존성 체크에 의해 덮어씌워질 수 있습니다. 반드시 make menuconfig 인터페이스를 사용하거나 디폴트 컨피그(defconfig)를 통해 수정해야 합니다.

make menuconfig 내 최적화 옵션 경로는 다음과 같습니다.

# 1. C Library 변경 (Musl 적용)
Toolchain  --->
    C library (musl)  --->
        (X) musl

# 2. SquashFS 압축 파일 시스템 선택
Filesystem images  --->
    [*] squashfs filesystem
    Compression provider (xz)  --->

.config 파일 반영 예시:

# Toolchain optimization with Musl C library
BR2_TOOLCHAIN_BUILDROOT_MUSL=y
BR2_TOOLCHAIN_USES_MUSL=y

# SquashFS image configuration with XZ compression
BR2_TARGET_ROOTFS_SQUASHFS=y
BR2_TARGET_ROOTFS_SQUASHFS_XZ=y

3.3 Target Binary Strip 및 디버그 심볼 제거

컴파일된 ELF 바이너리에 포함된 디버그 심볼(Debug Symbol)과 심볼 테이블은 타겟 실행 환경에서 불필요한 용량을 차지합니다.

주의 (Technical Correction): 기존 글의 BR2_STRIP_STRIP=y 및 BR2_ENABLE_DEBUG=n은 올바르지 않은 Symbol Name입니다. Buildroot의 공식 Kconfig Symbol은 BR2_STRIP_strip=y 및 BR2_ENABLE_DEBUG=n이 포함되지 않는 기본 구조입니다.

make menuconfig 경로:

Target packages  --->
    [*] Strip target binaries

.config 파일 설정:

# Strip symbols from binaries and libraries on target
BR2_STRIP_strip=y
BR2_STRIP_EXCLUDE_FILES=""
BR2_STRIP_EXCLUDE_DIRS=""

3.4 BusyBox 및 Linux Kernel 기능 최적화

BusyBox의 미사용 명령어(Applet)와 Linux 커널의 불필요한 파일 시스템/드라이버 모듈을 제거하면 바이너리와 모듈 디렉터리(/lib/modules)의 크기를 최소화할 수 있습니다.

BusyBox 경량화

다음 명령어를 실행하여 미사용 Applet(예: vi, wget, ftpd 등)을 비활성화합니다.

$ make busybox-menuconfig

Linux 커널 모듈 최적화

다음 명령어를 실행하여 사용하지 않는 파일 시스템(NTFS, ISO9660) 및 드라이버를 제거합니다.

$ make linux-menuconfig

설정 파일(kernel.config) 변경 예시:

# Disable unused file systems in Linux Kernel
# CONFIG_NTFS_FS is not set
# CONFIG_ISO9660_FS is not set

# Build essential USB storage driver as built-in instead of module
CONFIG_USB_STORAGE=y

4. Buildroot 용량 최적화 실무 팁

4.1 Post-Build Script를 활용한 불필요한 문서 및 디렉터리 자동 삭제

Buildroot 빌드 완료 직후 타겟 파일 시스템(output/target)에서 문서, 매뉴얼, C 헤더 파일 등을 자동으로 제거하도록 후처리 스크립트(Post-build script)를 등록합니다.

make menuconfig 설정:

System configuration  --->
    Custom scripts  --->
        (board/custom/post_build.sh) Custom scripts to run inside the target filesystem

board/custom/post_build.sh 예시:

#!/bin/sh
# Remove documentation, manual pages, and header files from Target RootFS
TARGET_DIR=$1

rm -rf ${TARGET_DIR}/usr/share/doc
rm -rf ${TARGET_DIR}/usr/share/man
rm -rf ${TARGET_DIR}/usr/share/info
rm -rf ${TARGET_DIR}/usr/include

4.2 ncdu 도구를 활용한 Target RootFS 용량 분석

빌드 완료 후 어떤 디렉터리나 파일이 용량을 많이 차지하는지 분석하기 위해 ncdu 도구를 활용합니다.

# Analyze size distribution of output/target directory
$ sudo apt-get install ncdu
$ ncdu output/target/

5. Buildroot 용량 최적화 시 흔히 하는 실수 및 트러블슈팅

1. BR2_STATIC_LIBS=y (전역 정적 링크) 적용 시 용량 증가 문제

  • 증상: BR2_STATIC_LIBS=y 옵션을 설정한 후 전체 RootFS 이미지 크기가 오히려 증가함.
  • 원인: 정적 링크(Static Linking)는 단일 바이너리 실행 시 공유 라이브러리 Dependency를 없애주지만, 실행 파일이 여러 개일 경우 중복된 C 라이브러리 코드가 각 바이너리에 모두 포함되어 전체 용량이 늘어납니다.
  • 해결 방법: 다수의 실행 파일과 데몬이 존재하는 일반적인 RootFS 환경에서는 동적 링크(Dynamic Linking)를 유지하고 라이브러리 자체를 Musl로 경량화합니다. 단일 바이너리만 실행되는 극소형 램디스크(Initramfs) 환경에서만 BR2_STATIC_LIBS=y를 고려합니다.

2. Glibc 전용 애플리케이션의 Musl 빌드 실패 (gnu/stubs.h 에러)

  • 증상: C 라이브러리를 Musl로 변경 후 빌드 시 fatal error: gnu/stubs.h: No such file or directory 에러 발생.
  • 원인: 소스 코드가 Glibc 전용 비표준 API(GNU Extension)에 의존하고 있어 Musl C 라이브러리와 호환되지 않음.
  • 해결 방법: 소스 코드의 GNU 전용 API를 POSIX 표준 API로 수정하거나, 해당 패키지에 대해 Musl 호환 패치를 적용합니다. 수정이 불가능한 경우 uClibc-ng를 대안으로 선택합니다.

6. 결론: 체계적인 Buildroot RootFS 경량화 프로세스

Buildroot 파일 시스템 크기 최적화는 단일 설정이 아닌 시스템 전체 구성 요소의 정밀한 조정을 통해 달성됩니다.

  1. C 라이브러리 및 압축 최적화: Musl C Library 및 SquashFS(XZ/ZSTD)를 적용하여 기본 용량을 절감합니다.
  2. 바이너리 및 문서 정형화: BR2_STRIP_strip=y 설정 및 Post-build Script를 적용하여 디버그 심볼, manual, header 파일을 제거합니다.
  3. 컴포넌트 튜닝: Busybox 및 Linux Kernel 설정을 통해 미사용 기능과 드라이버 모듈을 제거합니다.

단계별 최적화를 통해 용량 제약을 극복하고 안정적인 임베디드 시스템을 구축할 수 있습니다.

반응형