본문 바로가기

building system/bazel

NASM으로 asm 파일을 컴파일해 사용하는 bazel 빌드 예제

반응형

개요

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 항목으로 사용한다. genruleouts항목에 "hello.o"가 있음으로 추적된 파일이 srcs 항목에 사용된다.

마지막으로 cc_binary에서 cc_library로 지정한 asm_libdeps 항목에 추가하면 끝이다. 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>

전체 소스

nasm_compile.zip
1.4 kB

반응형