본문 바로가기

building system/bazel

StarLark 언어로 만들어 보는 기본 예제 MD5 파일 생성하기

반응형

개요

이번 게시글에서는 StarLark 언어를 사용해 md5 파일 생성하는 예제를 구현한다. 본 예제를 통해 사용자 정의 rule를 만들고, rule 기능을 수행하는 implementation function를 구현한다.

풀어야 할 과제

다음과 같은 파일로 구성된다. main.cc 파일의 md5 해쉬값을 생성할 것이다.

    .bazelrc
    BUILD.bazel
    main.cc
    make_md5_binary.bzl
    MODULE.bazel

console 창에 아래 명령어를 입력하면 윈도우 환경에서 해쉬값을 얻어낼 수 있다.

[윈도우] certutil -hashfile main.cc md5
[윈도우] bash.exe -c "md5sum main.cc"
[우분투] md5sum main.cc

결과 화면

CMD> certutil -hashfile main.cc md5

MD5의 main.cc 해시:
5de1159032af460be82d283fbbcea820
CertUtil: -hashfile 명령이 성공적으로 완료되었습니다.
CMD> bash.exe -c "md5sum main.cc"

5de1159032af460be82d283fbbcea820  main.cc

.bazelrc

모든 명령어를 처리하는 과정에서 bzlmod 기반 옵션이 추가되도록 다음 문구를 입력해준다.

common --enable_bzlmod

MODULE.bazel

MODULE.bazel 파일은 빌드 시스템의 맨 상위를 추적하는 용도로만 사용할 예정임으로 파일만 생성하고 추가할 내용은 없다.

make_md5_binary.bzl

오늘 게시글에서 가장 중요한 파트는 아래 코딩을 이해하는 것이다. .bzl 확장자는 StarLark 언어로 rule 또는 aspect를 정의할 수 있다.

아래 코딩은 make_md5_binary rule를 정의한다. 전체적인 흐름은 BUILD.bazel에서 make_md5_binary를 사용하고, 컴파일 과정에서 분석이 시작되면, 먼저 아래 쪽 rule 구문이 수행하는데, implementation 항목으로 rule 구문 이후에 호출할 implementation function를 지정한다. 부가적으로 필요한 항목을 attrs 항목으로 추가한다.

이렇게 작동된 결과는 묶어 현재 분석중인 rule의 context object를 생성 한 후, context object의 implementation function로 ctx 이름으로 자기 자신을 전달해 수행한다. implementation function는 필히 dependency set를 반환해야 한다.

ctxctx.actions 항목으로 각종 필요한 함수를 제공한다.
ctx.attr의 세부 항목으로 rule에서 정의한 attrs의 세부 항목을 맵핑하고, 자주 사용하는 항목에 대한 축약 attribute를 정의하고 있다.

ctx.outputs 항목은 rule의 attrs에서 attr.ouput()으로 생성된 이름에 대한 축약 attribute다. 따라서 ctx.outputs.out는 rule의 "out"이 적용된 값이다.
ctx.file 항목은 rule의 attrs에서 attr.label에서 allow_single_file = True 항목을 가진 이름에 대한 축약 attribute다. 따라서 ctx.file.src는 rule의 "src"이 적용된 적용된 값이다.

ctx.actions.run_shell 구문은 bash.exe를 수행한다.
outputs 항목은 출력으로 사용할 File 객체 목록을, inputs 항목은 입력으로 사용할 File 객체 목록을, 각각 의미하고, commandbash.exe -c 이후에 추가할 제어 명령어를 정의한다. format 함수를 통해 해시할 파일 이름을 적어주고 redirection >를 통해 저장할 파일 이름을 적어주면 원하는 결과를 얻어낼 수 있다.

마지막으로 implementation function는 의존성 파일 정보를 반환한다.
최종적으로 만들어진 md5 파일을 누군가 사용하길 원할 것이다.

# make_md5_binary.bzl
def _make_md5_binary_impl(ctx):
    ctx.actions.run_shell(
        outputs = [ctx.outputs.out],
        inputs = [ctx.file.src],
        command = "md5sum {} > {}".format(ctx.file.src.path, ctx.outputs.out.path),
    )
    return DefaultInfo(files = depset([ctx.outputs.out]))

make_md5_binary = rule(
    implementation = _make_md5_binary_impl,
    attrs = {
        "src": attr.label(mandatory = True, allow_single_file = True),
        "out": attr.output(),
    },
)

참고로 visual code에 Bazel-Stack-VSCode 플러그인을 설치하면 조금 더 깔금한 환경에서 코딩을 작성할 수 있다.

BUILD.bazel

load 함수로 bzl 파일을 로드하고 make_md5_binary rule를 사용할 수 있도록 가져온다. make_md5_binary 사용 과정에서 항목 이름과 bzl 파일 적성 파일과 서로 맵핑되는 것을 알 수 있다.

load(":make_md5_binary.bzl","make_md5_binary")

make_md5_binary(
    name ="test",
    src = "main.cc",
    out ="test.md5"
)

실행하기

CMD> bazelisk build //...

INFO: Analyzed target //:test (4 packages loaded, 7 targets configured).
INFO: Found 1 target...
Target //:test up-to-date:
  bazel-bin/test.md5
INFO: Elapsed time: 5.757s, Critical Path: 5.23s
INFO: 2 processes: 1 internal, 1 local.
INFO: Build completed successfully, 2 total actions

CMD> bash.exe -c "cat bazel-bin/test.md5"
5de1159032af460be82d283fbbcea820  main.cc

예제 파일

make_md5.zip
1.2 kB

728x90
반응형