4.3. Makefile#
Giới thiệu về Makefile
1.1 Make là gì?
1.2 Vì sao nên sử dụng Makefile trong MLOps?Cài đặt và thiết lập môi trường
2.1 Kiểm tra Make đã có sẵn
2.2 Cài đặt Make trên các hệ điều hànhCấu trúc cơ bản của Makefile
3.1 Targets và Dependencies
3.2 Phần thân (Recipe)
3.3 Biến (Variables)
3.4 Hàm (Functions) trong MakefileCác lệnh và tùy chọn quan trọng trong Make
4.1 make
4.2 make -f
4.3 make -j
4.4 make clean
4.5 make helpCác lưu ý khi viết Makefile
5.1 Dấu tab trong phần recipe
5.2 Quy ước đặt tên target
5.3 Quy tắc về thứ tự rule
5.4 Phần chú thíchVí dụ Makefile cơ bản cho MLOps
6.1 Tải dữ liệu
6.2 Tiền xử lý dữ liệu
6.3 Huấn luyện mô hình
6.4 Đóng gói và triển khai (Docker, v.v.)Các kỹ thuật nâng cao
7.1 Phân chia Makefile nhiều file
7.2 Sử dụng Makefile trong CI/CD pipeline
7.3 Tự động hoá với Shell script và Makefile
4.3.1. Giới thiệu về Makefile#
4.3.1.1. Make là gì?#
Make là một công cụ tự động hoá quá trình xây dựng (build) và quản lý các dự án phần mềm, thường được sử dụng trong các dự án C/C++.
Makefile là tập tin cấu hình chứa tập hợp các quy tắc (rule) mà
make
sẽ sử dụng để biết cách và thời điểm cần (re)build các thành phần.Mặc dù ra đời ban đầu cho việc build chương trình C/C++, Makefile có thể được ứng dụng rộng rãi để tự động hoá bất kỳ quy trình nào, đặc biệt hữu ích trong MLOps khi ta cần chạy nhiều tác vụ (tải data, tiền xử lý, huấn luyện, đóng gói, v.v.).
4.3.1.2. Vì sao nên sử dụng Makefile trong MLOps?#
Tái sử dụng và kiểm soát phiên bản: Dễ dàng quản lý các bước trong pipeline, nhất là khi dùng chung Git.
Tự động hoá: Giúp tự động hoá mọi tác vụ lặp lại như cài dependencies, chạy training, evaluate, v.v.
Tính module hoá: Chia nhỏ các tác vụ phức tạp thành các rule nhỏ, dễ bảo trì.
Tích hợp CI/CD: Makefile có thể chạy trong các pipeline CI/CD (GitHub Actions, GitLab CI, Jenkins, v.v.) một cách dễ dàng.
4.3.2. Cài đặt và thiết lập môi trường#
4.3.2.1. Kiểm tra Make đã có sẵn#
Trước hết, hãy kiểm tra xem make
đã được cài trên hệ thống chưa:
make --version
Nếu có, bạn sẽ thấy phiên bản Make được in ra, ví dụ:
GNU Make 4.3 Built for x86_64-pc-linux-gnu
Nếu chưa được cài đặt, hãy cài theo hướng dẫn bên dưới.
4.3.2.2. Cài đặt Make trên các hệ điều hành#
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install build-essential
CentOS/Fedora/RHEL:
sudo yum groupinstall "Development Tools"
macOS:
Cài đặt Xcode Command Line Tools (thường mặc định đã có
make
).Hoặc dùng Homebrew:
brew install make
Windows:
4.3.3. Cấu trúc cơ bản của Makefile#
Dưới đây là ví dụ tối giản:
# Tên target: Danh sách dependencies
# Lệnh recipe (thường cần dấu tab ở đầu dòng)
all: main.py data.csv # chạy trước 2 dependencies là main.py và data.csv
python main.py
main.py:
echo "print('Hello, MLOps!')" > main.py
data.csv:
echo "col1,col2" > data.csv
echo "1,2" >> data.csv
4.3.3.1. Targets và Dependencies#
Target: Thường là file đầu ra (lúc này target đại diện cho file output sau khi chạy lệnh xong), hoặc tên nhiệm vụ (phím tắt). Ví dụ:
all
,train
,data.csv
.mỗi target mặc định được hiểu là một tệp tin (file) đầu ra — tức là, nếu bạn định nghĩa một target có tên trùng với một file, Make sẽ so sánh thời gian sửa đổi (timestamp) của target đó với các dependencies để quyết định xem có cần chạy recipe (các lệnh để tạo/update target) hay không.
Dependencies: Những thứ target cần có trước khi chạy recipe. Nếu dependencies đã sẵn sàng và “mới hơn” target, lệnh recipe sẽ chạy để cập nhật target.
Phony target
.PHONY
là một danh sách chỉ định những target nào không liên quan đến file trên đĩa. Thông báo cho Make rằng đây chỉ là target mang tính “chức năng” (task), chứ không gắn với một file cụ thể.
.PHONY: all clean train
all: train
@echo "All tasks done!"
train:
python train.py --data data.csv --model model.pkl
@echo "Training completed."
clean:
rm -f data.csv processed.csv model.pkl
@echo "Cleaned up."
Nếu không có
.PHONY: clean
, Make sẽ kiểm tra xem có file tênclean
trong thư mục hay không. Nếu có một file tênclean
, Make có thể so sánh timestamp giữa file đó và dependencies (nếu có) để quyết định có chạy recipe hay không, hoặc thậm chí nhầm lẫn rằng “fileclean
đang mới hơn, ta không cần chạy lệnh rm… nữa”.Khai báo
.PHONY: clean
sẽ giúp Make luôn chạy recipe củaclean
khi bạn gõmake clean
. Make không tìm fileclean
thực trên ổ đĩa để so sánh timestamp nữa.Lợi ích của việc khai báo
.PHONY
Tránh trùng tên file: Đảm bảo target luôn được thực thi, kể cả khi có file trùng tên.
Phản ánh rõ mục đích: Cho Make biết những target nào là “chức năng” (task), không phải file đầu ra.
Tăng tính nhất quán: Khi hợp tác với nhiều người, định nghĩa
.PHONY
giúp người khác nhanh chóng hiểu logic Makefile hơn.
Nên đặt target
all
hoặchelp
lên đầu để làm mặc định.
4.3.3.2. Phần thân (Recipe)#
Là các lệnh shell sẽ được chạy khi target cần cập nhật.
Mỗi lệnh bắt buộc phải bắt đầu bằng dấu tab (thay vì dấu cách).
Có thể chứa nhiều lệnh shell liên tiếp.
4.3.3.3. Biến (Variables)#
Giúp tái sử dụng các giá trị và tránh lặp code.
PYTHON = python3
DATA = data.csv
preprocess:
$(PYTHON) preprocess_pipeline.py --data=$(DATA)
train: preprocess # để chạy train cần preprocess chạy trước
$(PYTHON) train.py --data=$(DATA)
Sử dụng cú pháp
$(BIEN)
để gọi biến.
4.3.3.4. Hàm (Functions) trong Makefile#
Make hỗ trợ một số hàm tiện ích như
shell
,wildcard
,patsubst
, v.v.Ví dụ, muốn lấy danh sách file
.py
:
SRC = $(wildcard *.py)
Hoặc gọi lệnh shell:
GIT_COMMIT := $(shell git rev-parse HEAD)
4.3.4. Các lệnh và tùy chọn quan trọng trong Make#
4.3.4.1. make
#
Lệnh mặc định để chạy.
make
sẽ tìm fileMakefile
hoặcmakefile
trong thư mục hiện tại.Khi gọi không kèm target,
make
sẽ chạy target đầu tiên trong Makefile.
4.3.4.2. make -f
#
Chỉ định tệp Makefile cụ thể:
make -f MyMakefile
4.3.4.3. make -j
#
Chạy song song nhiều job (ví dụ, build nhiều file cùng lúc). Rất hữu ích khi build các project lớn:
make -j 4
4.3.4.4. make clean
#
Thường được định nghĩa như một target để dọn dẹp file tạm, file build cũ. Ví dụ:
clean:
rm -rf *.o *.pyc
Để chạy:
make clean
4.3.4.5. make help
#
Hay được sử dụng để liệt kê các target kèm mô tả. Ví dụ:
help:
@echo "Possible targets:"
@echo " train : Train the model"
@echo " clean : Remove temporary files"
4.3.5. Ví dụ Makefile cơ bản cho MLOps#
.PHONY: all data preprocess train docker-build docker-run clean
all: train
data:
wget https://example.com/dataset.csv -O data.csv
echo "Data downloaded."
preprocess: data
python3 preprocess.py --input data.csv --output processed.csv
echo "Data preprocessed."
train: preprocess
python3 train.py --data processed.csv --model model.pkl
echo "Model trained."
docker-build: train
docker build -t my-ml-model:latest .
echo "Docker image built."
docker-run:
docker run -p 8080:8080 my-ml-model:latest
echo "Docker container is running."
clean:
rm -f data.csv processed.csv model.pkl
echo "Cleaned up."
make data
tải dữ liệu từ nguồn nào đó (s3, http,…).make preprocess
: trước khi chạy preprocess, Make sẽ kiểm tra và gọidata
(nếu chưa có hoặc cũ hơn).make train
(tự động gọipreprocess
)make docker-build
(tự động gọitrain
):docker-build
phụ thuộc vàotrain
để đảm bảo model đã được huấn luyện trước khi đóng gói vào container.make docker-run
chạy container đã buildmake all
chạy targettrain
(vìall: train
)
4.3.6. Các kỹ thuật nâng cao#
4.3.6.1. Phân chia Makefile nhiều file#
Khi dự án lớn, có thể chia Makefile thành nhiều file để dễ quản lý:
Makefile
chính: bao gồm rule cơ bản và lệnhinclude
:
include Makefile.data
include Makefile.model
include Makefile.deploy
Makefile.data
: chứa các rule liên quan đến dữ liệu.Makefile.model
: chứa các rule liên quan đến huấn luyện, test, v.v.Makefile.deploy
: chứa các rule liên quan đến Docker, k8s, deploy, v.v.
4.3.6.2. Sử dụng Makefile trong CI/CD pipeline#
GitHub Actions:
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Install dependencies
run: make install # Giả sử có target install
- name: Run training
run: make train
- name: Build Docker
run: make docker-build
GitLab CI hay Jenkins cũng tương tự, ta chỉ cần chạy các lệnh
make
tương ứng.
4.3.6.3. Tự động hoá với Shell script và Makefile#
Kết hợp lệnh Shell script phức tạp trong
*.sh
với Makefile, khi Makefile chỉ gọi shell script tương ứng.
.PHONY: train
train:
bash scripts/train.sh
Giúp tổ chức code sạch hơn, tách logic dài ra khỏi Makefile.
4.3.7. Tổng kết và tài nguyên tham khảo#
Makefile là một công cụ mạnh mẽ để tự động hoá và quản lý quy trình MLOps.
Với một cấu trúc rule - dependencies - recipe đơn giản, ta có thể thiết lập và duy trì pipeline MLOps hiệu quả, từ tải dữ liệu, tiền xử lý, huấn luyện cho đến đóng gói, triển khai.
Kết hợp Makefile với các CI/CD platform (GitHub Actions, GitLab CI, Jenkins,…) sẽ giúp tự động hoá mọi thứ, giảm thiểu sai sót, rút ngắn thời gian phát triển và triển khai.