Ubuntu에서 최신 Linux 커널 직접 빌드하기: gelf.h 오류 해결까지

먼저 결론

Ubuntu 22.04에서 Linux 커널 메인라인 소스를 직접 빌드해 bzImage까지 만들었다. 처음에는 gelf.h: No such file or directory에서 멈췄는데, 빌드 의존성을 빠뜨린 것이 원인이었다. 아래는 실패 로그까지 포함한 실제 기록이다.


이번에는 최신 메인라인 소스를 기준으로 빌드했다.


환경 세팅

$ sudo apt update
$ sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev bc git ccache -y
  • build-essential : 핵심 컴파일러 툴체인 모음 (gcc, g++, make, libc6-dev – 표준 c 라이브러리 헤더파일들)
  • libncurses-dev : 텍스트 기반 화면 (TUI) 라이브러리. (커널 make menuconfig할 때 나오는 창)
  • bison & flex : 컴파일러 구문 분석기 생성 도구. 커널 소스 내 config 파일 해석할 때 필요함.
  • libssl-dev : OpenSSL 라이브러리. 커널 빌드 시 보안 서명.
  • libelf-dev : ELF 라이브러리. 커널 내부의 디버깅 정보 생성할 때 쓰임.
  • bc : 터미널용 정밀 계산기. 빌드 시간 측정 & 내부 수치 계산할 때 쓰임.
  • git : 알지?
  • ccache : 컴파일러 캐시 유틸리티. 속도 업.

작업 디렉토리 세팅

$ mkdir -p ~/kernel_study/build
$ cd ~/kernel_study
$ git clone --depth 1 https://github.com/torvalds/linux.git
$ cd linux
  • 리누스 토발즈님의 소스를 직접 빌드해본다.
  • git clone –depth 1을 주어 방대한 history 모두 받지 않도록 함 (수 GB 넘어감).
    -> ‘–depth 1’ 주면 전체 디렉토리는 2.1GB

커널 설정 파일 생성

여기서 파일 시스템, 네트워크, 그래픽 드라이버같은걸 켜고 끌 수 있음.

$ make defconfig O=../build
  • make defconfig : define 이 아닌 default config. 현재 컴퓨터에 맞도록 기본적인 권장 설정해줌.
  • O= : output 디렉토리 설정. 처음보는 문법이네..
~/kernel_study/linux$ make defconfig O=../build
make[1]: Entering directory '/home/worker/kernel_study/build'
  UPD     /home/worker/kernel_study/build/Makefile
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/confdata.o
  HOSTCC  scripts/kconfig/expr.o
  LEX     scripts/kconfig/lexer.lex.c
  YACC    scripts/kconfig/parser.tab.[ch]
  HOSTCC  scripts/kconfig/lexer.lex.o
  HOSTCC  scripts/kconfig/menu.o
  HOSTCC  scripts/kconfig/parser.tab.o
  HOSTCC  scripts/kconfig/preprocess.o
  HOSTCC  scripts/kconfig/symbol.o
  HOSTCC  scripts/kconfig/util.o
  HOSTLD  scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#
make[1]: Leaving directory '/home/worker/kernel_study/build'

<build/.config>

~/kernel_study/build$ cat .config -n | head
     1  #
     2  # Automatically generated file; DO NOT EDIT.
     3  # Linux/x86 7.3.0-rc7 Kernel Configuration
     4  #
     5  CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
     6  CONFIG_CC_IS_GCC=y
     7  CONFIG_GCC_VERSION=110400
     8  CONFIG_CLANG_VERSION=0
     9  CONFIG_AS_IS_GNU=y
    10  CONFIG_AS_VERSION=23800

총 5486 lines;;


빌드

$ make -j$(nproc) O=../build
$ echo $(nproc)
64

근데 에러남.

/home/worker/kernel_study/linux/tools/objtool/include/objtool/elf.h:10:10: fatal error: gelf.h: No such file or directory
   10 | #include <gelf.h>
      |          ^~~~~~~~
compilation terminated.
make[5]: *** [/home/worker/kernel_study/linux/tools/build/Makefile.build:96: /home/worker/kernel_study/build/tools/objtool/signal.o] Error 1
In file included from /home/worker/kernel_study/linux/tools/objtool/include/objtool/objtool.h:13,
                 from /home/worker/kernel_study/linux/tools/objtool/include/objtool/arch.h:11,
                 from /home/worker/kernel_study/linux/tools/objtool/include/objtool/check.h:11,
                 from arch/x86/decode.c:18:
/home/worker/kernel_study/linux/tools/objtool/include/objtool/elf.h:10:10: fatal error: gelf.h: No such file or directory
   10 | #include <gelf.h>
      |          ^~~~~~~~
compilation terminated.
make[6]: *** [/home/worker/kernel_study/linux/tools/build/Makefile.build:96: /home/worker/kernel_study/build/tools/objtool/arch/x86/decode.o] Error 1
make[5]: *** [/home/worker/kernel_study/linux/tools/build/Makefile.build:158: arch/x86] Error 2
make[4]: *** [Makefile:125: /home/worker/kernel_study/build/tools/objtool/objtool-in.o] Error 2
make[3]: *** [Makefile:74: objtool] Error 2
make[2]: *** [/home/worker/kernel_study/linux/Makefile:1632: tools/objtool] Error 2
make[2]: *** Waiting for unfinished jobs....
  HOSTLD  scripts/mod/modpost
  CC      kernel/bounds.s
  CHKSHA1 /home/worker/kernel_study/linux/include/linux/atomic/atomic-arch-fallback.h
  CHKSHA1 /home/worker/kernel_study/linux/include/linux/atomic/atomic-instrumented.h
  CHKSHA1 /home/worker/kernel_study/linux/include/linux/atomic/atomic-long.h
  UPD     include/generated/timeconst.h
  UPD     include/generated/bounds.h
  CC      arch/x86/kernel/asm-offsets.s
  UPD     include/generated/asm-offsets.h
  CC      kernel/sched/rq-offsets.s
  UPD     include/generated/rq-offsets.h
  CALL    /home/worker/kernel_study/linux/scripts/checksyscalls.sh 
make[1]: *** [/home/worker/kernel_study/linux/Makefile:248: __sub-make] Error 2
make[1]: Leaving directory '/home/worker/kernel_study/build'
make: *** [Makefile:248: __sub-make] Error 2

오류의 핵심은 gelf.h 누락이었다. 위의 의존성 설치 명령을 실행하지 않은 상태였고, libelf-dev를 포함한 패키지를 설치한 뒤 같은 빌드 명령을 다시 실행했다.

패키지 설치하고 빌드 시작

  .....
  AS      arch/x86/boot/pmjump.o
  CC      arch/x86/boot/printf.o
  CC      arch/x86/boot/regs.o
  CC      arch/x86/boot/string.o
  CC      arch/x86/boot/tty.o
  CC      arch/x86/boot/video.o
  CC      arch/x86/boot/video-mode.o
  CC      arch/x86/boot/version.o
  CC      arch/x86/boot/video-vga.o
  CC      arch/x86/boot/video-vesa.o
  CC      arch/x86/boot/video-bios.o
  CPUSTR  arch/x86/boot/cpustr.h
  LDS     arch/x86/boot/compressed/vmlinux.lds
  AS      arch/x86/boot/compressed/kernel_info.o
  AS      arch/x86/boot/compressed/head_64.o
  VOFFSET arch/x86/boot/compressed/../voffset.h
  CC      arch/x86/boot/cpu.o
  CC      arch/x86/boot/compressed/string.o
  CC      arch/x86/boot/compressed/cmdline.o
  CC      arch/x86/boot/compressed/error.o
  OBJCOPY arch/x86/boot/compressed/vmlinux.bin
  RELOCS  arch/x86/boot/compressed/vmlinux.relocs
  HOSTCC  arch/x86/boot/compressed/mkpiggy
  CC      arch/x86/boot/compressed/cpuflags.o
  CC      arch/x86/boot/compressed/early_serial_console.o
  CC      arch/x86/boot/compressed/kaslr.o
  CC      arch/x86/boot/compressed/ident_map_64.o
  CC      arch/x86/boot/compressed/idt_64.o
  AS      arch/x86/boot/compressed/idt_handlers_64.o
  CC      arch/x86/boot/compressed/pgtable_64.o
  CC      arch/x86/boot/compressed/acpi.o
  CC      arch/x86/boot/compressed/efi.o
  GZIP    arch/x86/boot/compressed/vmlinux.bin.gz
  CC      arch/x86/boot/compressed/misc.o
  MKPIGGY arch/x86/boot/compressed/piggy.S
  AS      arch/x86/boot/compressed/piggy.o
  LD      arch/x86/boot/compressed/vmlinux
  ZOFFSET arch/x86/boot/zoffset.h
  OBJCOPY arch/x86/boot/vmlinux.bin
  AS      arch/x86/boot/header.o
  LD      arch/x86/boot/setup.elf
  OBJCOPY arch/x86/boot/setup.bin
  BUILD   arch/x86/boot/bzImage
Kernel: arch/x86/boot/bzImage is ready  (#1)
make[1]: Leaving directory '/home/worker/kernel_study/build'

패키지를 설치한 뒤에는 빌드가 완료됐다.

커널 훑기

~/kernel_study$ tree -L 1 build
build
├── arch
├── block
├── built-in.a
├── built-in-fixup.a
├── certs
├── crypto
├── drivers
├── fs
├── include
├── init
├── io_uring
├── ipc
├── kernel
├── lib
├── Makefile
├── mm
├── modules.builtin
├── modules.builtin.modinfo
├── modules.order
├── Module.symvers
├── net
├── scripts
├── security
├── sound
├── source -> /home/worker/kernel_study/linux
├── System.map
├── tools
├── usr
├── virt
├── vmlinux
├── vmlinux.a
├── vmlinux.o
└── vmlinux.unstripped

21 directories, 12 files

아래 vmlinux 파일이 따끈따끈한 커널 바이너리임.

52M Oct 12 19:27 vmlinux*

아래 bzImage실제 메모리에 올라가는 이미지임. vmlinux에서 불필요한 정보 빼고 gzip압축한 파일임.

~/kernel_study/build/arch/x86/boot/bzImage

끝.

이후엔 커널 드라이버(*.ko) 까보기.

결론

이번 빌드에서 가장 오래 걸린 건 컴파일 자체보다 의존성 확인이었다. defconfig로 설정을 만들고, O=../build로 결과물을 소스 트리 밖에 분리하면 실패 뒤에도 다시 살펴보기 편했다. 빌드 구조와 타깃은 Linux 커널 공식 Kbuild 문서에서 더 확인할 수 있다.

댓글 남기기