개요
bazel centry registry에 nasm를 빌드할 수 있는 환경이 이미 구축되어 있다. bzlMod를 활용하면 nasm를 컴파일하고, 결과 파일을 가져와 asm 파일을 컴파일 한 결과물과 c++ 소스를 결합해 최종 샘플을 구성할 수 있다.
풀어야 할 과제
asm 파일 컴파일 환경을 구축하는 것이 가장 큰 풀어야 할 과제다. 이미 이전 게시글에서 나머지 문제는 해결한 경험이 있다.
│ .bazelrc
│ MODULE.bazel
│
└─project
BUILD.bazel
hello.asm
main.cc
hello.asm 파일 보기
아래 asm 소스는 윈도우 64비트 환경에서 사용할 수 있는 소스다. 외부 참조로 printf
함수를 사용하고, printf
인자로 lea
레지스터에 있는 메모리 주소, 즉 msg
를 출력하는 asm_main
함수를 정의한다.
bits 64
default rel
segment .data
msg db "Hello, NASM!", 0
segment .bss
segment .text
global asm_main ; other modules can call asm_main
extern printf
asm_main:
push rdi
lea rcx, [msg]
call printf
pop rdi
ret
main.cc
hello.asm 파일에서 선언한 asm_main 함수에 대한 이름을 extern "C"
구문으로 정의한 후, main
함수에서 호출한다.
#include <iostream>
extern "C" void asm_main(void);
int main(){
std::cout << "world c++\n";
asm_main();
return 0;
}
.bazelrc
모든 컴파일 과정에서 bzlMod 사용 옵션을 사용하도록 다음 구문을 입력한다.
common --enable_bzlmod
MODULE.bazel
nasm를 사용할 수 있도록 다음 구문을 입력하면 끝이다.
bazel_dep(name = "nasm", version = "2.14.02")
project\BUILD.bazel
genrule를 사용해 asm 파일을 컴파일하는 명령어를 구성한다. srcs에 추가된 항목은 $<로 맵핑되고, outs에 추가된 항목은 $@로 맵핑된다. 이때 참조할 tools 항목으로 "@nasm"
입력한다. 이과정에서 nasm 소스 파일이 다운로드되고 컴파일된다.
이후에 $(location @nasm//:nasm)
구문으로 컴파일된 실행 파일의 전체 경로를 얻어온다. $(location ...)
구문은 bazel 시스템이 의존성 검사를 위해 파일이 관리하고 있을 때, bazel 시스템에서 관련 정보를 얻어오는 용도다. 따라서 의존성이 없는 파일에 사용될 수 없다. 그 외에도 dirname
, basename
과 같은 구문도 존재한다.
나머지는 NASM 컴파일 과정에서 사용하는 각종 옵션, 입력 소스 파일, 출력 소스 파일 이름을 순차적으로 지정한다.
cc_library
에서 genrule
로 만들어진 hello.o 파일을 srcs 항목으로 사용한다. genrule
의 outs
항목에 "hello.o"
가 있음으로 추적된 파일이 srcs
항목에 사용된다.
마지막으로 cc_binary
에서 cc_library
로 지정한 asm_lib
를 deps
항목에 추가하면 끝이다. linkopts
항목으로 링크 과정에서 legacy_stdio_definitions.lib
가 참여하도록 지정한다. legacy_stdio_definitions.lib
내부에 printf
구현이 존재한다.
genrule(
name = "asm",
srcs = [
"hello.asm",
],
outs = [
"hello.o",
],
cmd = "$(location @nasm//:nasm) -fwin64 -DWIN64 -D__x86_64__ -o $@ $<",
tools = ["@nasm"],
)
cc_library(
name = "asm_lib",
srcs = ["hello.o"],
)
cc_binary(
name = "main",
srcs = ["main.cc"],
deps = [":asm_lib"],
linkopts = ["/DEFAULTLIB:legacy_stdio_definitions.lib"],
)
전체 빌드하기
bazelisk build //...
실행하기
bazelisk run //project:main
INFO: Analyzed target //project:main (68 packages loaded, 713 targets configured).
INFO: Found 1 target...
Target //project:main up-to-date:
bazel-bin/project/main.exe
INFO: Elapsed time: 0.760s, Critical Path: 0.03s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/project/main.exe
world c++
Hello, NASM!
D:\buildsystem\bazel\vs_bazel>
전체 소스
'building system > bazel' 카테고리의 다른 글
dependency attribute란? (1) | 2024.01.27 |
---|---|
StarLark 언어로 만들어 보는 기본 예제 MD5 파일 생성하기 (1) | 2024.01.24 |
bzlMod 기반 GoogleTest 기본 예제 구현하기 (1) | 2024.01.23 |
새로운 의존성 설계 bzlMod 기본 예제 구현하기 (1) | 2024.01.22 |
http_archive/git_repository 기반 bazel 예제 구현하기 (0) | 2024.01.22 |