All Articles

Golang - Hướng dẫn build ứng dụng đa nền tảng

golang-cross-platform-1

Golang là một ngôn ngữ mạnh mẽ, được đánh giá là khá trong sáng và dễ học hơn nhiều so với một số ngôn ngữ khác như C/C++. Kèm theo đó là một số tính năng “đặc sản” nhà Go như goroutines, garbage collection, bộ packages phong phú đi kèm, v.v.. Thế nên Go luôn là sự lựa chọn đầu tiên đối với các developers cần một ngôn ngữ build app nhanh chóng nhưng đảm bảo được performance

Thêm vào đó, Go có thể build trên hầu hết các nền tảng Linux, Windows, MacOS và cả WebAssembly, trên hầu hết các kiến trúc i386, arm, amd64, mips,.. Một số anh em dev gọi đó là cross-platform hay multi-platform

Tuy nhiên, mặc định Go sẽ build binary file dựa trên cấu hình của máy host. Nghĩa là khi build trên máy với OS=linux Arch=amd64, thì bạn không thể vác file đó chạy trên máy OS=linux Arch=arm như Raspberry Pi chẳng hạn. Muốn build cho mạch nhúng như Raspberry Pi, chúng ta phải set 2 biến môi trường là GOOSGOARCH để Go compiler hiểu chúng ta muốn build cho một platform cụ thể nào đó. Ví dụ: GOOS=linux GOARCH=arm go build .

Khá là phiền phức và rắc rối nếu chúng ta muốn build hàng loạt cho tất cả các platforms mà chúng ta muốn hỗ trợ. Script sau đây sẽ giúp bạn đơn giản hóa vấn đề đó

1. Platforms file

Trước tiên, chúng ta cần define một file như platforms.txt bao gồm các platforms mà chương trình của chúng ta support. Để lấy được list các platform mà Go support chúng ta chạy lệnh go tool dist list, bạn sẽ nhận được danh sách như sau

# >go tool dist list aix/ppc64 android/amd64 android/arm64 linux/386 linux/amd64 linux/arm64 # ... windows/386 windows/amd64 windows/arm

Notes: Tuy Go có hỗ trợ build cho Android tuy nhiên nó yêu cầu bạn phải cài đặt Android NDK để làm việc

File platforms.txt của mình sẽ support một số platforms phổ biến, nội dung nó như sau:

darwin/amd64 darwin/arm64 linux/amd64 linux/arm windows/386 windows/amd64 windows/arm

2. Scripting

Mình sẽ thực hiện viết bash script, mình cũng comment trong code để giải thích

#!/bin/bash # Chúng ta sẽ pass tên ứng dụng thông qua cli, vd: bash ./build.sh hello-world APP_NAME_ARG=$1 APP_NAME="${APP_NAME_ARG:-go-app}" WORKING_DIR="${PWD}" PLATFORMS_FILE="platforms.txt" FULL_PATH_PLATFORMS_FILE=$WORKING_DIR/$PLATFORMS_FILE # check file platforms.txt if [ ! -f $FULL_PATH_PLATFORMS_FILE ]; then echo "Platforms file: $FULL_PATH_PLATFORMS_FILE does not exist" exit 1 fi # Xóa folder build echo "Clean build folder" rm -rf ./build # Tạo folder build echo "Create build folder" mkdir -p build # install dependencies echo "Install dependencies" go mod download # Đọc file platforms.txt while read line; do platform_split=(${line//\// }) # Tương tự "linux/arm".split("/") Javascript GOOS=${platform_split[0]} GOARCH=${platform_split[1]} output_name=$APP_NAME # Đối với OS=windows thì sẽ thêm đuôi .exe if [ $GOOS = "windows" ]; then output_name+='.exe' fi mkdir -p build/$GOOS/$GOARCH output_path="$WORKING_DIR/build/$GOOS/$GOARCH/$output_name" echo "====================================================" #Separator echo "Building for OS=$GOOS Architecture=$GOARCH" # Cờ -ldflags="-s -w" được đặt để giảm dung lượng file env GOOS=$GOOS GOARCH=$GOARCH go build -ldflags="-s -w" -o $output_path if [ ! -f $output_path ]; then echo "Failed when build for OS=$GOOS Architecture=$GOARCH" else fileSize=$(find "$output_path" -printf "%s") echo "Done with output file: $output_path ($fileSize bytes)" fi if [ $? -ne 0 ]; then echo 'An error has occurred! Aborting the script execution...' exit 1 fi done < $PLATFORMS_FILE echo "DONE"

3. Done

golang-cross-platform-2

Thực hiện chạy lệnh: bash ./build.sh hello-world cấu trúc folder dự án sau khi build sẽ như sau. Các binary files sẽ nằm trong các folder OS/Architecture tương ứng

. ├── build │ ├── darwin │ │ ├── amd64 │ │ │ └── hello-world │ │ └── arm64 │ │ └── hello-world │ ├── linux │ │ ├── amd64 │ │ │ └── hello-world │ │ └── arm │ │ └── hello-world │ └── windows │ ├── 386 │ │ └── hello-world.exe │ └── amd64 │ └── hello-world.exe ├── build.sh ├── go.mod ├── main.go └── platforms.txt

Đến đây bạn có thể deploy ứng dụng của mình được rồi. Chúc các bạn thành công!

Toàn bộ source code của mình tại đây github.com/tranphuquy19/golang-build-cross-platform