이 글은 Ubuntu 환경에서 Clang / LLVM 툴체인을 이용해 Linux 커널을 실제로 빌드하는 방법을 단계별로 정리한다.
Clang/LLVM 툴체인 설치는 아래 글을 먼저 확인한다.
Ubuntu 커널 빌드에 대한건 아래 글을 참고한다.
전체 빌드 흐름 한눈에 보기

커널 소스
↓
.config 생성 (defconfig / menuconfig)
↓
make LLVM=1
↓
clang → LLVM IR → ld.lld
↓
vmlinux / Image / modules
핵심은 LLVM=1 하나로 컴파일러 + 링커 + binutils 계열을 모두 LLVM 쪽으로 전환한다는 점이다.
커널 소스 준비
소스 받기
준비되어 있는 커널 소스가 없다면 아래와 같이 소스를 받는다.
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
실무에서는 다음 중 하나를 써도 무방하다.
- LTS 커널
- 배포판 커널 소스
- SoC 벤더 커널 트리
빌드 방법 자체는 동일하다.
Out-of-tree 빌드 디렉터리 구성
커널 빌드는 산출물이 많기 때문에 O= 옵션을 쓰는 것이 정석이다.
mkdir -p out
이후 모든 make 명령에 O=out을 붙인다.
x86_64 (native) Clang/LLVM 커널 빌드
기본 config 생성
make O=out defconfig
이 단계에서 .config가 생성된다.
필자의 경우는 기존에 빌드 해 준 소스가 있어서 mrproper후 진행했다.
$ make mrproper
$ make O=out defconfig
Clang/LLVM 빌드 실행
make O=out LLVM=1 -j$(nproc)
이 한 줄이 의미하는 바는 다음과 같다.
| 항목 | 의미 |
|---|---|
LLVM=1 | clang + ld.lld + llvm-binutils 사용 |
-j$(nproc) | 병렬 빌드 |
중간에 LTO, CFI 등의 config 선택이 나오면 여기서는 Enter로 넘어간다.
컴파일을 하다보면, 아래와 같이 GCC로 빌드할때와는 다르게 error가 발생한다. 이는 Clang 으로 빌드하면서, 기존 GCC에서는 warnning 처리하던 것들이 강화된 조건에 error로 잡히면서 나오는 것들이다.
../net/netfilter/nf_conntrack_netlink.c:677:41: error: variable 'len' is uninitialized when used here [-Werror,-Wuninitialized]
677 | + nla_total_size(sizeof(char) * len); /* CTA_SECCTX_NAME */
| ^~~
../net/netfilter/nf_conntrack_netlink.c:670:9: note: initialize the variable 'len' to silence this warning
670 | int len, ret;
| ^
| = 0
1 error generated.
make[5]: *** [../scripts/Makefile.build:243: net/netfilter/nf_conntrack_netlink.o] Error 1
make[4]: *** [../scripts/Makefile.build:481: net/netfilter] Error 2
make[4]: *** Waiting for unfinished jobs....
...
이 error는 len이 초기화 없이 사용된 경우로 len = 0 으로 초기화 할 것을 제안하고 있다.
각 발생되는 error를 확인하고 수정해서 컴파일을 완료되도록 한다.
arm64 크로스 컴파일 (Clang/LLVM)
arm64에서는 ARCH 지정이 필수다.
arm64 defconfig 설정
make O=out ARCH=arm64 defconfig
Clang + GNU cross 혼합 빌드 (가장 흔한 패턴)
make O=out ARCH=arm64 LLVM=1 \
CROSS_COMPILE=aarch64-linux-gnu- \
-j$(nproc)
설명하면,
- 컴파일러/링커: Clang + LLD
- 일부 도구 / asm fallback: GNU binutils
실무에서 가장 안정적인 조합이다.
Integrated Assembler 문제 발생 시
특정 .S 파일에서 에러가 나면 통합 어셈블러를 끈다.
make O=out ARCH=arm64 LLVM=1 LLVM_IAS=0 \ CROSS_COMPILE=aarch64-linux-gnu- \ -j$(nproc)
빌드 산출물 확인
주요 결과물:
| 파일 | 의미 |
|---|---|
vmlinux | ELF 커널 이미지 |
arch/x86/boot/bzImage | x86 부트 이미지 |
arch/arm64/boot/Image | arm64 커널 이미지 |
modules/ | 커널 모듈 |
빌드 성공 여부 빠른 체크
file out/vmlinux
아래와 같이 “ELF 64-bit LSB pie executable, ARM aarch64” 정도가 확인되면 정상적으로 빌드 됐다고 판단할 수 있다.
$ file out/vmlinux
out/vmlinux: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=b21eee087608e453d874e6e8ce457056496c39ac, with debug_info, not stripped
GCC 빌드와의 차이 요약
| 항목 | GCC | Clang/LLVM |
|---|---|---|
| 빌드 플래그 | 기본 | LLVM=1 |
| 링커 | ld.bfd | ld.lld |
| BTF 연계 | 보통 | 매우 좋음 |
| 분석 도구 | 제한적 | sanitizer, analyzer 풍부 |