Migrating iOS Project to Bazel – Part 2

Tiếp nối phần 1 thì phần này nội dung chính sẽ bàn tới là cấu hình cơ bản cho 1 project chạy iOS bằng bazel. Để thành thục thì chúng ta đi vào làm demo project bằng Bazel trước sau đó mới áp dụng vào project đang chạy và giải quyết các vấn đề khác.

1. Cài đặt

Để cài đặt Bazel trên macos khác đơn giản, bạn có thể vào link này https://docs.bazel.build/versions/main/install-os-x.html.

Đơn giản nhất thì mình dùng brew để cài đặt.

brew install bazel

Sau khi cài đặt xong thì bạn kiểm tra xem đã cài đặt thành công chưa bằng lệnh

bazel --version

2. Cấu trúc build config

Như bài trước mình có nói sơ qua, thì Bazel sẽ dùng những file BUILD để cấu hình cho những module trong project của mình. Ngoài ra thì còn có file WORKSPACE.bazelrc để cấu hình cho project của mình nữa.

2.1 WORKSPACE

Đây chính là file cấu hình những dependency cho project. Nó được sử dụng để kéo starlark rules (Build rules) về project để sử dụng. File WORKSPACE sẽ được đặt ở thư mục gốc của project.

Để build cho iOS thì mình dùng rules_apple và rules_swift về sử dụng. 2 rules này được open source tại https://github.com/bazelbuild/rules_applehttps://github.com/bazelbuild/rules_swift.

Đây là ví dụ về 1 file WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "build_bazel_rules_apple",
    sha256 = "c84962b64d9ae4472adfb01ec2cf1aa73cb2ee8308242add55fa7cc38602d882",
    url = "https://github.com/bazelbuild/rules_apple/releases/download/0.31.2/rules_apple.0.31.2.tar.gz",
)

load(
    "@build_bazel_rules_apple//apple:repositories.bzl",
    "apple_rules_dependencies",
)

apple_rules_dependencies()

load(
    "@build_bazel_rules_swift//swift:repositories.bzl",
    "swift_rules_dependencies",
)

swift_rules_dependencies()

load(
    "@build_bazel_rules_swift//swift:extras.bzl",
    "swift_rules_extra_dependencies",
)

swift_rules_extra_dependencies()

load(
    "@build_bazel_apple_support//lib:repositories.bzl",
    "apple_support_dependencies",
)

apple_support_dependencies()

File WORKSPACE trên sẽ thực hiện hành động theo những bước sau:

  • Sử dụng hàm load để lấy ra hàm http_archive từ trong những rules được Bazel support sẵn.
  • Gọi hàm http_archive để tải về rules_apple từ trên github
  • Sử dụng hàm load để lấy ra hàm apple_rules_dependencies từ rules_apple vừa được lấy về để cài đặt những rules mà rules_apple phụ thuộc, thì trong đó có rules_swift nên chúng ta k cần cài đặt bằng tay nữa.
  • Tiếp tục dùng hàm load và gọi hàm để cấu hình những dependency của những công cụ còn lại như rules_swift, apple_support

2.2 .bazelrc

.bazelrc là file cấu hình được đặt ngang hàng với WORKSPACE để cấu hình các tham số truyền vào khi bazel được gọi.

Như bên dưới này mình sẽ mô tả thêm tham số để Xcode gen DSYM phục vụ cho việc debug và xác định simulator nào sẽ chạy khi mình run.

build --apple_platform_type=ios
build --apple_generate_dsym
build --ios_simulator_device="iPhone 12"
build --ios_simulator_version=14.5

2.3 BUILD

Build config dependencies

Tiếp sau WORKSPACE thì chúng ta cần những file có tên BUILD lại thư mục gốc của module chúng ta cần build. Nó đại diện cho 1 package trong project. Những file BUILD này sẽ thực hiện load và gọi những hàm để cấu hình build có sẵn trong 2 rules rules_swiftrules_apple. Target trong file BUILD này có thể phụ thuộc vào target trong file BUILD kia tương đương như việc module này phụ thuộc vào module kia đó.

Để demo thì mình sẽ sử dụng project tạo repo trong thư mục start: https://github.com/vikage/DemoProjectBazel

Đầu tiên thì mình sẽ viết file WORKSPACE trước, nội dung sẽ như bên trên. Sau đó sẽ đến các file BUILD

BUILD cho TLLogging
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
load("@rules_cc//cc:defs.bzl", "objc_library")

swift_library(
    name = "TLLogging",
    module_name = "TLLogging",
    srcs = glob([
        "*.swift",
    ]),
    deps = [
        ":TLLoggingHelper",
    ],
    visibility = ["//visibility:public"],
)

objc_library(
    name = "TLLoggingHelper",
    module_name = "TLLoggingHelper",
    srcs = glob([
        "*.m",
    ]),
    hdrs = glob([
        "*.h",
    ]),
)

visibility là thuộc tính để cấu hình các package khác(file BUILD khác) có thấy được target này hay không. Ở đây 1 số chỗ mình để public có nghĩa là tất cả các package khác đều thấy.

deps là thuộc tính sẽ định nghĩa những depedencies target. Để biết cụ thể hơn thì các bạn vào docs của rules_swift hoặc rules_apple đọc nhé.

BUILD cho Assets

Để build được xcasset thì chúng ta sẽ dùng rule filegroup, rule này được buildin rồi nên không cần phải gọi hàm load để lấy ra

filegroup(
    name = "Assets",
    srcs = glob(["Assets.xcassets/**"]),
    visibility = ["//visibility:public"],
)
BUILD cho App_Classes và ios_app
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")

swift_library(
    name = "App_Classes",
    srcs = glob([
        "*.swift"
    ]),
    data = [
    	"//Assets:Assets",
    	"Base.lproj/Main.storyboard",
    	"Base.lproj/LaunchScreen.storyboard",
    ],
    deps = [
        "//Lib/Logging:TLLogging"
    ]
)

ios_application(
    name = "ios_app",
    bundle_id = "com.thanhvu.test",
    infoplists = ["Info.plist"],
    families = ["iphone"],
    minimum_os_version = "12.0",
    deps = [
        ":App_Classes",
    ]
)

Các bạn để ý sẽ thấy Assets đã được embed vào qua trường data tại target App_Classes

3. Build project bằng command line

Để build bazel bằng command line cho project này cũng đơn giản, bạn chỉ việc cd tới thư mục project trên terminal và gọi lệnh build như bên dưới là được.

bazel build //App:ios_app

Để run trên simulator thì gọi lệnh sau và simulator sẽ được bật lên 😃

bazel run //App:ios_app

Như vậy là chúng ta đã hoàn thành 1 ứng dụng demo được build bằng Bazel rồi đó. Phần tiếp mình sẽ nói về những vấn đề mình gặp phải khi migrate và cách giải quyết.

Project demo: https://github.com/vikage/DemoProjectBazel

Tham khảo thêm:
https://docs.bazel.build/versions/main/tutorial/ios-app.html
https://docs.bazel.build/versions/main/migrate-xcode.html

Leave a Reply