Search

4. Rules & Targets

What is Rules?

Bazel의 규칙(rule)은 빌드 작업을 수행하는 데 필요한 절차를 정의합니다. 각 규칙은 소스 코드를 컴파일하거나, 라이브러리를 링크하거나, 바이너리를 생성하는 등의 작업을 수행하는 방법을 지정합니다. 규칙은 입력(소스 파일, 라이브러리 등)과 출력(목표 바이너리, 라이브러리, 테스트 결과 등)을 갖습니다. Bazel은 여러 언어와 플랫폼을 지원하기 때문에, 각 언어와 플랫폼별로 다양한 규칙이 존재합니다.
규칙은 다음과 같은 속성을 가집니다:
이름: 규칙의 유형(예: cc_binary, java_library 등)을 나타냅니다.
소스: 규칙이 처리해야 하는 입력 파일입니다.
의존성: 규칙이 의존하는 다른 빌드 목표입니다.
출력: 규칙에 의해 생성된 결과물입니다.
예를 들어, 간단한 Java 프로젝트에서의 Bazel 규칙을 살펴봅시다. Java 프로젝트에서는 다음과 같은 규칙을 사용할 수 있습니다.
java_binary: Java 바이너리를 생성하는 규칙
java_library: Java 라이브러리를 생성하는 규칙
java_test: Java 테스트를 실행하는 규칙
1.
먼저, 프로젝트 구조를 살펴봅니다.
my_java_project/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ ├── com/ │ │ │ │ ├── example/ │ │ │ │ │ ├── Main.java │ │ │ │ │ ├── MyApp.java │ ├── test/ │ │ ├── java/ │ │ │ ├── com/ │ │ │ │ ├── example/ │ │ │ │ │ ├── MyAppTest.java ├── BUILD
Plain Text
복사
2.
프로젝트의 BUILD 파일을 작성합니다.
# BUILD 파일 # Java 라이브러리 규칙 java_library( name = "my_app_lib", srcs = glob(["src/main/java/**/*.java"]), visibility = ["//visibility:public"], ) # Java 바이너리 규칙 java_binary( name = "my_app", main_class = "com.example.Main", runtime_deps = [":my_app_lib"], ) # Java 테스트 규칙 java_test( name = "my_app_test", srcs = glob(["src/test/java/**/*.java"]), deps = [ ":my_app_lib", "@junit_junit//jar", ], test_class = "com.example.MyAppTest", )
Plain Text
복사
이 예제에서는 다음과 같은 Bazel 규칙을 사용했습니다.
1.
java_library: Java 라이브러리를 생성하는 규칙입니다. 여기서는 "my_app_lib"이라는 이름의 라이브러리를 생성하며, "src/main/java" 디렉토리의 모든 Java 파일을 컴파일합니다. 생성된 라이브러리는 공개적으로 사용할 수 있도록 visibility 속성을 설정합니다.
2.
java_binary: Java 바이너리를 생성하는 규칙입니다. 여기서는 "my_app"이라는 이름의 바이너리를 생성하며, "com.example.Main" 클래스를 메인 클래스로 사용합니다. 이 바이너리는 "my_app_lib" 라이브러리에 의존하므로 runtime_deps 속성에 해당 라이브러리를 명시합니다.
3.
java_test: Java 테스트를 실행하는 규칙입니다. 여기서는 "my_app_test"이라는 이름의 테스트를 실행하며, "src/test/java" 디렉토리의 모든 Java 파일을 컴파일합니다. 이 테스트는 "my_app_lib" 라이브러리와 JUnit 라이브러리에 의존하므로 deps 속성에 해당 라이브러리를 명시합니다. 테스트 클래스는 "com.example.MyAppTest"를 사용합니다.
Bazel 규칙을 사용하면 프로젝트의 빌드 과정을 간편하게 관리할 수 있으며, 다양한 언어와 플랫폼에 대한 지원을 제공합니다. 각 언어별로 적절한 규칙을 사용하여 프로젝트의 빌드 작업을 정의할 수 있습니다.
이제 Bazel을 사용하여 이 Java 프로젝트를 빌드하고 테스트해보겠습니다.
1.
먼저, 프로젝트의 WORKSPACE 파일을 생성합니다. 이 파일은 프로젝트 루트에 위치하며, 외부 종속성을 가져올 수 있습니다.
# WORKSPACE 파일 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar") # JUnit 라이브러리를 가져옵니다. http_jar( name = "junit_junit", url = "https://repo1.maven.org/maven2/junit/junit/4.13.1/junit-4.13.1.jar", sha256 = "a7ec7ef48e6bcfc7a96fe06968b3f6dce9d7dcbd9a6e0407da0f7976a8e6d50c", )
Plain Text
복사
2.
프로젝트를 빌드합니다. Bazel 명령어를 사용하여 프로젝트의 바이너리를 빌드할 수 있습니다.
$ bazel build //:my_app
Plain Text
복사
3.
프로젝트를 실행합니다. Bazel 명령어를 사용하여 생성된 바이너리를 실행할 수 있습니다.
$ bazel run //:my_app
Plain Text
복사
4.
테스트를 실행합니다. Bazel 명령어를 사용하여 프로젝트의 테스트를 실행할 수 있습니다.
$ bazel test //:my_app_test
Plain Text
복사
Bazel을 사용하여 Java 프로젝트를 빌드하고 테스트하는 방법에 대해 알아보았습니다. 이와 비슷한 방식으로 다양한 언어와 플랫폼의 프로젝트를 빌드하고 관리할 수 있습니다. Bazel은 규칙을 사용하여 프로젝트의 빌드 작업을 정의하므로, 프로젝트의 구조와 복잡도에 따라 적절한 규칙을 선택하고 사용하면 효율적인 빌드 관리가 가능합니다.

What is Targets?

Bazel Target은 Bazel 빌드 시스템에서 빌드 작업의 결과물로, 규칙(rule)에 의해 생성됩니다. Bazel 프로젝트에서 Target은 빌드 프로세스의 최종 출력물을 나타내며, 바이너리, 라이브러리, 테스트 결과 등 다양한 형태를 가질 수 있습니다. Target은 다른 Target에 의존할 수 있으며, 이를 통해 프로젝트 구조와 빌드 작업의 순서를 정의합니다.
예를 들어, 간단한 C++ 프로젝트에서 Bazel Target을 정의하고 사용하는 방법을 살펴보겠습니다.
1.
먼저, 프로젝트 구조를 살펴봅니다.
my_cpp_project/ ├── src/ │ ├── main.cc │ ├── my_library.cc │ ├── my_library.h ├── test/ │ ├── my_library_test.cc ├── BUILD
Plain Text
복사
2.
프로젝트의 BUILD 파일에 Bazel Target을 작성합니다.
# BUILD 파일 # C++ 라이브러리 규칙 cc_library( name = "my_library", srcs = ["src/my_library.cc"], hdrs = ["src/my_library.h"], visibility = ["//visibility:public"], ) # C++ 바이너리 규칙 cc_binary( name = "my_app", srcs = ["src/main.cc"], deps = [":my_library"], ) # C++ 테스트 규칙 cc_test( name = "my_library_test", srcs = ["test/my_library_test.cc"], deps = [":my_library"], )
Plain Text
복사
이 예제에서는 다음과 같은 Bazel Target을 정의했습니다.
1.
"my_library": C++ 라이브러리를 생성하는 cc_library 규칙에 의해 생성됩니다. 이 Target은 "src/my_library.cc"를 컴파일하고 "src/my_library.h" 헤더 파일을 사용합니다. 생성된 라이브러리는 공개적으로 사용할 수 있도록 visibility 속성을 설정합니다.
2.
"my_app": C++ 바이너리를 생성하는 cc_binary 규칙에 의해 생성됩니다. 이 Target은 "src/main.cc"를 컴파일하며, "my_library"라는 라이브러리에 의존하므로 deps 속성에 해당 라이브러리를 명시합니다.
3.
"my_library_test": C++ 테스트를 실행하는 cc_test 규칙에 의해 생성됩니다. 이 Target은 "test/my_library_test.cc"를 컴파일하며, "my_library"라는 라이브러리에 의존하므로 deps 속성에 해당 라이브러리를 명시합니다.
이처럼 Bazel Target을 사용하면 프로젝트의 구조와 의존성을 명확하게 정의할 수 있습니다. Bazel은 이러한 Target들의 정보를 바탕으로 빌드 작업을 최적화하며, 필요한 작업만 수행하도록 관리합니다. 이를 통해 빌드 시간을 줄이고, 프로젝트를 더 효율적으로 관리할 수 있습니다.
이제 Bazel을 사용하여 이 C++ 프로젝트를 빌드하고 테스트해보겠습니다.
1.
프로젝트를 빌드합니다. Bazel 명령어를 사용하여 프로젝트의 바이너리를 빌드할 수 있습니다.
$ bazel build //:my_app
Plain Text
복사
2.
프로젝트를 실행합니다. Bazel 명령어를 사용하여 생성된 바이너리를 실행할 수 있습니다.
$ bazel run //:my_app
Plain Text
복사
3.
테스트를 실행합니다. Bazel 명령어를 사용하여 프로젝트의 테스트를 실행할 수 있습니다.
$ bazel test //:my_library_test
Plain Text
복사
Bazel Target을 사용하면 프로젝트의 빌드 작업을 간편하게 관리할 수 있으며, 다양한 언어와 플랫폼에 대한 지원을 제공합니다. 각 언어별로 적절한 규칙을 사용하여 프로젝트의 빌드 작업을 정의할 수 있습니다. 또한, Bazel은 Target 간의 의존성 정보를 통해 빌드 작업을 최적화하므로, 대규모 프로젝트에서 빌드 시간을 줄이고 효율적인 빌드 관리가 가능합니다.

다른 튜토리얼을 찾아볼까요?

1. Bazel 시작하기
1. Bazel 시작하기