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
và .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_apple và https://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
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_swift
và rules_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