1 điểm bởi GN⁺ 2024-09-22 | 2 bình luận | Chia sẻ qua WhatsApp
  • Dù các công cụ build mới liên tục xuất hiện, Makefile vẫn hữu ích như một công cụ mặc định nhẹ để gom các tác vụ lặp lại của dự án
  • Nhờ các lệnh mang tính quy ước như make, make build, make install, make dev, ngay cả với dự án lần đầu thấy bạn cũng có thể nhanh chóng thử build, cài đặt và chạy server phát triển
  • Dù stack khác nhau như Jekyll, Hugo, 11ty, các framework web Python, Docker hay gulp, Makefile vẫn đóng vai trò là giao diện thực thi chung
  • Trong các dự án cá nhân, vài target đơn giản như dev, build, deploy thường là đủ, thay vì điều kiện hay flag
  • GNU Make rất phổ biến; ngay cả khi không có, bạn vẫn có thể chạy trực tiếp các lệnh shell trong Makefile, nên gánh nặng nhỏ ngay cả trong môi trường bị hạn chế

Gom các lệnh khác nhau của từng dự án vào một điểm vào duy nhất

  • Makefile được dùng để bọc các dự án có cách build, chạy và triển khai khác nhau bằng một tập lệnh quen thuộc
  • Nếu một dự án lần đầu thấy có Makefile, thường có thể bắt đầu thử bằng các lệnh sau
    • make
    • make build
    • make install
  • Khi mở lại một dự án cá nhân cũ, bạn cũng có thể cấu hình để chỉ cần chạy make dev là xử lý cùng lúc các bước build cần thiết và chạy server phát triển
  • Dù stack công nghệ khác nhau như Jekyll, Hugo, 11ty hay nhiều framework web Python, vẫn có thể duy trì cùng một điểm vào
  • Ngay cả khi dùng Docker hoặc gulp, Makefile không thay thế các công cụ đó mà hoạt động như một lớp điều phối
    • Ví dụ: make build build các image Docker cần thiết, đồng thời truyền thêm tham số riêng theo từng dự án

Cách dùng đơn giản trong dự án cá nhân

  • Việc dùng Makefile tập trung vào gom các lệnh shell hơn là các tính năng phức tạp
    • Không dùng các tính năng như điều kiện hay flag
    • Đơn vị công việc của make về mặt kỹ thuật là target, nhưng trong thực tế được xem như task
    • Có thể tạo bằng hàm trong script bash, nhưng tác giả cho rằng Makefile dễ và nhanh hơn
  • Các tác vụ thường dùng trong dự án cá nhân thường chỉ có 2–3 cái
    • dev: khởi động server phát triển
    • build: build dự án khi cần
    • deploy: triển khai hoặc xuất bản dự án
    • watch: dùng như tác vụ bổ sung để tự động chạy lại build khi file nguồn thay đổi
  • Makefile của blog hiện tại chỉ có một target dev
    • Chạy npm run dev bên dưới dev:
  • Trong các dự án cá nhân phức tạp hơn, các tác vụ sau được gom bằng Makefile
    • dev: chạy server phát triển bằng bundle exec jekyll serve
    • build: build tài nguyên bằng npm run gulp build
    • watch: theo dõi một thư mục cụ thể bằng npm run gulp watch
    • deploy: sau khi build Jekyll trong môi trường production, chạy make encrypt, netlify deploy --prod
    • encrypt: mã hóa các file HTML trong thư mục _site bằng npx staticrypt

Những hạn chế và ưu điểm cần biết

  • Trong ví dụ đã lược bỏ phony targets, nhưng nếu có file trùng tên như dev, build, watch, deploy, encrypt, Makefile có thể không hoạt động như mong đợi
  • GNU Make là phần mềm chạy makefile; nó nhiều khả năng đã được cài sẵn trên Linux và phổ biến đến mức trên MacBook cũng khó nhớ là có cần cài riêng hay không
  • Make không đòi hỏi nhiều phụ thuộc bổ sung, nên có thể hữu ích trong môi trường bị hạn chế, nơi việc cài package khó hoặc không thể thực hiện vì lý do bảo mật
  • Ngay cả khi không có Make, bạn vẫn có thể sao chép trực tiếp các lệnh trong Makefile vào shell để chạy
    • Ngược lại, nếu server không có gulp, sẽ khó dán nguyên mã JavaScript vào terminal để chạy; đây là điểm khác biệt
  • Dù bạn tìm thấy một công cụ build mới tốt hơn và nhanh hơn, Make vẫn có thể tiếp tục được dùng như một lớp lệnh chung để quản lý các công cụ và cấu hình khác nhau

2 bình luận

 
kayws426 2024-09-22

Tôi thích Makefile

Nếu một makefile không định nghĩa các dependency, thì thay bằng justfile sẽ mang lại trải nghiệm sử dụng tốt hơn.

 
GN⁺ 2024-09-22
Ý kiến trên Hacker News
  • Không cần nản lòng trước những lời trong luồng này rằng “bạn đang dùng make sai cách”. Một trong những lý do Make là công cụ tốt là nó có thể bắt đầu đơn giản hơn vẻ ngoài của nó
    Không dùng .PHONY có thể gây vấn đề, nhưng với dự án nhỏ thì đó có thể là cái bẫy phải một năm sau mới đạp phải, và khi đó nhiều khả năng chỉ cần gãi đầu khoảng một giờ là xong. Trong 99% trường hợp, bạn có thể bắt tay làm ngay mà không cần bận tâm đến “chuẩn mực”, và Make chỉ đòi hỏi mức độ phức tạp vừa đủ để không sụp đổ

    • Một trong những điểm tệ nhất của Make là nhìn bề ngoài thì có vẻ đơn giản
      Make nhận các tệp đầu vào và phụ thuộc để tạo ra chính xác một tệp đầu ra. Các quy tắc không tạo đầu ra như install, all, clean, hoặc tất cả target trong bài viết, phải phụ thuộc vào một target ma thuật đặc biệt như .PHONY; nhưng .PHONY không có trong POSIX năm 2017 (IEEE Std 1003.1-2017, https://pubs.opengroup.org/onlinepubs/9699919799/utilities/m...) và chỉ mới được đưa vào tiêu chuẩn hiện tại (IEEE Std 1003.1-2024, https://pubs.opengroup.org/onlinepubs/9799919799/utilities/m...). Nếu muốn tạo nhiều tệp như object file, module, header biên dịch sẵn, bạn phải tự viết những mẹo dễ vỡ. Không phải Make nào cũng là GNU Make, và các hệ kiểu nix như BSD, Solaris/Illumos vẫn còn tồn tại
      Điều đó không có nghĩa Make vô dụng. Nó hữu ích cho những dự án đủ phức tạp nhưng chưa đến mức cần một hệ thống build “tốt hơn”. Vấn đề là các dự án như vậy sẽ phức tạp hơn khi mã tăng lên, rồi cuối cùng có script/chương trình sinh ra Makefile hoặc một phần của nó, tạo thành một hệ meta-build tạm bợ
      Vấn đề lớn hơn không phải là dùng nó, mà là đề xuất nó như một giải pháp cho “tất cả mọi người”. Và ngay khi trong thư mục gốc dự án xuất hiện một thư mục hay tệp tên build hoặc dev, Makefile đó sẽ ngừng hoạt động
    • Một ví dụ Makefile phức tạp hơn một chút mà tôi dùng khi bắt đầu dự án TypeScript mới nằm ở đây: https://github.com/borisovg/node-ts-template/blob/main/Makef...
      Dạo này tôi chuyển sang pnpm, nhưng vẫn không thấy nó quá phức tạp. Đúng là cần biết cú pháp ở mức nào đó, nhưng vẫn đỡ khó hơn so với việc làm cho các công cụ khác chạy đúng ngay từ đầu
    • Hơn 20 năm qua tôi đã dùng make rất ổn trong nhiều dự án và nhiều ngôn ngữ, và chưa từng gặp vấn đề với các tác vụ .PHONY mà mọi người hay bận tâm đến vậy
      Nó đơn giản, dễ đọc, có thể chỉnh sửa, có thể kết hợp, và hầu như ở đâu cũng đã được cài sẵn. Nó làm đúng những gì ghi trên bề mặt và gần như không làm gì hơn
      Nhân tiện, khi phải xử lý các hệ thống build theo trào lưu hoặc các hệ thống build ác mộng trong những dự án khác, tôi cũng bọc chúng bằng make
    • Hoàn toàn đồng ý. Tốt hơn là dùng công cụ phù hợp với công việc, và kể cả khi không phải chuyên gia thì như vậy vẫn tốt hơn nhiều so với chọn sai công cụ chỉ để tránh lời phê bình của những người cầu toàn
      Ai cũng phải bắt đầu từ đâu đó, và một khi đã chạy được thì có thể dễ dàng bổ sung cải tiến dần dần
    • Mọi recipe trong makefile phải tạo ra chính xác một sản phẩm đầu ra là $@. Toàn bộ Makefile có thể tạo số lượng đầu ra tùy ý vì quy tắc này có thể phụ thuộc vào quy tắc khác
      Từ đây có một quy tắc kinh nghiệm gọn gàng cho target phony. Nếu recipe không đụng đến $@ thì nên đánh dấu $@ là phony. Quản lý các target phony bằng một danh sách sẽ dễ hơn nhiều
      phonies :=
      phonies += something
      something:
      ./do-something
      phonies += something-else
      something-else: something
      ./do-something-else
      # touches $@ and thus does not need to be phony
      create-file:
      ./generate-some-output > $@
      .PHONY: $(phonies)
  • Makefile là một công nghệ tệ hại. Chỉ là nó đỡ tệ hơn một chút so với phần lớn các hệ thống build khác mà chúng ta tạo ra, nên trở nên hữu ích theo nghĩa tự hành hạ bản thân
    Các hệ thống build thường hoặc quá sơ khai nên hễ build thứ gì hơn đồ chơi là thành hỗn loạn, hoặc quá phức tạp nên đòi hỏi quá nhiều kiến thức nền, quan liêu, đồng bộ và mã khuôn mẫu, hoặc không có thư viện chuẩn nên cùng một mẫu build bị phân tán thành 10.000 cách triển khai không tương thích, hoặc quá hạn chế nên khi nhu cầu tăng lên lại phải di chuyển sang hệ khác, hoặc có quá nhiều phép màu, hoặc cú pháp khó hiểu và thiếu nhất quán

    • Theo tôi, Makefile là một công nghệ tuyệt vời, chỉ là nhiều người chưa học nó đúng cách hoặc không dùng theo cách nó được thiết kế
      Hơn một nửa phần mềm tôi dùng chỉ sử dụng Makefile bình thường và đôi khi thêm script configure. Không cần autotools, chỉ tùy chọn chạy ./configure rồi make, make install là chạy được. Đây hoàn toàn không phải cấu hình đồ chơi, mà được cấu thành từ những chương trình nhỏ làm tốt một việc
      Make và cách nó hoạt động, ít nhất với tôi, rất dễ hiểu. Tôi nghĩ trải nghiệm tệ mà mọi người gặp thường là do cấu hình build tệ của các dự án phức tạp hoặc thiếu kiến thức cần thiết, hơn là do bản thân Make
      Việc không có thư viện chuẩn là nhằm không phụ thuộc công cụ, nhờ đó nó có thể áp dụng phổ quát cho nhiều công cụ, ngôn ngữ và mục đích khác nhau. Tôi xem đó là tính năng chứ không phải khiếm khuyết. Lớp đơn giản đó là theo dõi phụ thuộc, target và dependency cũng rõ ràng, nên khó có thể gọi là ma thuật. Cú pháp thì chắc chắn có thể cải thiện hơn
    • Những hệ thống build tệ nhất là những thứ được tạo xoay quanh một ngôn ngữ lập trình cụ thể. Nếu số ngôn ngữ là N>>1 thì số hệ thống build cũng thành N>>1, tạo gánh nặng nhận thức quá lớn và không mở rộng được
      Các hệ thống build đa dụng bao quát nhiều ngôn ngữ chỉ có make hoặc những hệ thống nhắm đến make như CMake. Lý do chúng không hay là vì make không hay. make thật sự rất khó dùng cho đúng, có các vấn đề như recursive make và non-recursive make, có nhiều biến thể không tương thích như Unix/POSIX make, BSD make, GNU make, Windows nmake, và trông cũng khá xấu xí
      Dù vậy, make nếu được dùng đúng thì khá tốt. Thật may là chúng ta có make làm mẫu số chung nhỏ nhất
    • Đồng ý. Khá nhiều lựa chọn thay thế cũng không phải công cụ “chạy thứ gì đó” đa dụng như Make, mà tập trung vào một ngôn ngữ cụ thể
      Việc Make thậm chí không xử lý gọn gàng được thư mục con là khá khó hiểu. Tôi tò mò không biết có gì tốt hơn Make không. Có Ninja, nhưng nó không được thiết kế để con người viết trực tiếp
    • Có thể nói sự hỗn loạn đó “rất giả định” hoàn toàn không phải do compiler hay do những ngôn ngữ không có module không
      Bạn nghĩ mức độ là bao nhiêu? Chẳng phải khoảng 20%, 40%, 70% sao
    • Nếu nói “một hoặc nhiều hơn” thì có nhiều khoảng trống. Ước đoán của tôi như sau: Makefile không quá sơ khai. Nó có thể trở nên quá phức tạp, nhưng còn tùy cách tạo ra. Thư viện chuẩn thì có các hàm tích hợp. Tôi chưa từng thấy nó quá hạn chế, nên tôi nghĩ là không. Target và dependency rõ ràng nên cũng không có nhiều ma thuật. Chỉ có cú pháp là chắc chắn có thể tốt hơn, và có lẽ chỉ cần một file JSON bình thường thôi cũng đã tốt hơn rồi
  • Tôi thật sự thích Make. Trong 20 năm qua, với mọi công việc hay dự án từng đụng tới, tôi đều viết ít nhất một cái
    Không có gì thông minh cả, chỉ là tập hợp các mảnh ghép với vài biến. Kiểu như make run, make test, make lint
    make recent lint rồi chạy script được sửa gần đây nhất. Có thể làm bằng Bash hay shell khác, nhưng như vậy sẽ bị hút vào thế giới developer và chỉ tăng độ phức tạp mà không có thêm giá trị. Make chỉ là một ngôn ngữ chuyên biệt miền cho việc “file kiểu này được tạo từ file kiểu kia, và lúc đó chạy một hai lệnh này”. Vì thế nó cực kỳ mạnh

    • Tôi thích cách diễn đạt “file kiểu này được tạo từ file kiểu kia, và lúc đó chạy một hai lệnh này”
      Nhiều thập kỷ trước tôi từng tạo một framework test bằng Java, cho phép chỉ định test và các class phụ thuộc bằng cú pháp giống make. Có một tập các class test định nghĩa “bộ test chuẩn”, rồi các tầng class test khác phụ thuộc lên đó chỉ được chạy nếu tầng phía trước thành công
      Tôi không hiểu vì sao ngày nay mọi người lại làm mọi thứ phức tạp đến vậy. Tôi luôn khuyên hãy bám vào các công cụ Unix chuẩn và cách làm của chúng, tức những phương pháp đã được thời gian kiểm chứng, trừ khi rơi vào tình huống tuyệt đối không thể làm như vậy. Thời gian là hữu hạn, nên tôi muốn dùng nó cho phần cốt lõi của giải quyết vấn đề như thiết kế hệ thống/chương trình, mô hình hóa, cấu trúc, pattern, v.v.; phần còn lại chỉ là thứ yếu
    • Mọi Makefile tôi từng gặp trong thực tế đều làm nhiều việc hơn rất nhiều so với “chỉ có vậy”
    • Tôi cũng tương tự. Trước đây tôi không dùng nhiều, nhưng ở công ty hiện tại thì hầu như repo nào cũng có Makefile
      Biết rằng bất kể stack, ngôn ngữ hay repo nào, cứ chạy make test là hoạt động, quả là một sự giải thoát lớn
    • Vấn đề của Make không nằm ở Make, mà ở chỗ những thứ Make gọi đến không còn hoạt động theo mô hình đó nữa
      Makefile của dự án trước có bốn lệnh chính: build, test, frontend, deploy. build và test gọi maven, frontend gọi npm, deploy gọi docker và aws
      Tất cả các công cụ này đều có cơ chế theo dõi trạng thái, caching và xử lý gia tăng riêng, nhưng không báo cáo chúng đã làm gì. Vì vậy không thể viết các quy tắc ở mức phân tử như “chỉ deploy khi build đã được cập nhật”. Vì maven/cargo/dotnet/npm/go không phơi bày thông tin đó
  • Tác giả thậm chí không dùng theo dõi phụ thuộc dựa trên mtime. Các target cũng đáng ra phải là .PHONY nhưng lại không được đánh dấu. Hoàn toàn có thể thay bằng một shell script đọc $1, so khớp rồi quyết định việc cần làm

    • Hoặc cũng có thể thay bằng một trình chạy lệnh đơn giản như just
      https://just.systems/
    • Có một câu chuyện kinh dị một dòng từ một dự án đang làm thực tế: .PHONY: $(MAKECMDGOALS)
      ./build.sh dev đúng là kém rõ ràng hơn make dev. Một lý do khác để dùng Make ngay cả khi không có bước non-phony nào là về sau, nếu cần, ta có thể thêm các bước đó. Tất nhiên tôi đồng ý rằng tác giả nên đánh dấu {dev,build,deploy} là phony
    • Về mặt kỹ thuật thì đúng, nhưng điểm cốt lõi tôi rút ra từ bài viết là có được sự nhất quán trong cách sử dụng không chỉ ở dự án của mình mà cả ở các dự án bên thứ ba
      Makefile của họ có thể cải thiện về mặt kỹ thuật, nhưng điều quan trọng hơn là trải nghiệm “bắt đầu” khi vào một dự án được nhất quán
    • Tất cả chúng ta đều từng là người mới. Để học một công cụ, việc thật sự dùng nó, dù theo kiểu người mới chưa hoàn hảo, cũng rất hữu ích. Vừa học vừa cải thiện dần là được
    • Vẻ đẹp của make và shell nằm ở chỗ chúng tuân theo nguyên tắc Unix: đơn giản và làm tốt một việc
      Người ta muốn nó làm thật nhiều việc khác như ngôn ngữ script, trình theo dõi phụ thuộc, v.v., rồi kéo vào những công cụ phình to. Mới hơn không nhất thiết là tốt hơn. Autoconf và automake không phải là make
  • Về mặt kỹ thuật, các target make này đều tìm một file có cùng tên với tên target. Mỗi target thực ra nên được định nghĩa là .PHONY
    Trước đây tôi cũng luôn dùng những Makefile kiểu này, nhưng vài năm gần đây đã chuyển sang just và justfile. Hành vi này là mặc định và nhìn chung dễ dùng hơn. Những thứ như tham số cũng đơn giản hơn
    https://github.com/casey/just

    • Những hệ thống giống make này khá tốt, nhưng có một vấn đề. Make đã có sẵn trên mọi Linux và Mac, và trên Windows cũng khá dễ có. Thật đáng tiếc là nó không đi kèm Git Bash. Tôi xem việc dùng mẫu số chung nhỏ nhất tự thân đã là một lợi thế lớn của Make
    • Sai lầm lớn của Make là trộn target phony và target file vào cùng một namespace. Chẳng hạn, lẽ ra chỉ cần nhìn tên đã phân biệt được, như để target phony bắt đầu bằng :
      Tất nhiên giờ thì đã quá muộn
    • just thật sự khá ổn, nhưng vì thường không được cài sẵn nên hơi phiền
      Có lẽ đã đến lúc xuất hiện một bản phân phối coreutils mới, gom các công cụ mới và hữu ích như just, ripgrep để cài ở bất cứ nơi nào ta muốn dùng
  • Thật thú vị khi make lại khơi ra tranh luận dữ dội như vậy. Nó giống các cuộc tranh luận vi và emacs ngày trước, gần như nửa chiến tranh tôn giáo
    Tôi hoàn toàn đồng ý với bài gốc, và đặc biệt cho rằng cách bọc các công cụ build tinh vi hơn bằng một Makefile cấp cao nhất là thông minh. Lợi ích là chuẩn hóa. Không cần nhớ gì cả; nếu là dự án tôi viết thì chỉ cần gõ make là biết nó sẽ chạy
    Ví dụ, khi một người dùng C muốn biên dịch một dự án Rust, họ không cần tra cách dùng cargo mà chỉ cần gõ make hoặc gmake. Tôi cố gắng tuân thủ POSIX và không dùng tính năng đặc thù của GNU, nhưng cũng đúng là gần như 100% make ngoài đời là gmake
    Đề xuất dùng make vượt thời gian như một kiểu trình điều phối hệ thống build cấp cao nhất có lẽ vẫn sẽ chạy sau 250 năm nữa

    • Thật buồn cười khi một tiêu đề đơn giản như vậy lại châm ngòi tranh luận nảy lửa. Bản thân bài viết chỉ là một ca sử dụng make đơn giản đến điên rồ, và nói về việc dùng gulp vào năm 2024, nhưng rõ ràng dường như chẳng ai đọc cả
    • cargo là ví dụ không hay. Vì phổ biến là dùng cargo build
      Bản thân Make thì tuyệt vời, nhưng trong hầu hết các trường hợp tôi làm với dự án C, đó là tổ hợp cmake/autotools và cài package toàn cục, và những thứ đó thì thường phải tra cứu
    • Điều đó có thể không xảy ra nếu trước đó bazel/blaze thống trị. Nếu nghi ngờ, hãy nhìn Chrome so với Firefox, hoặc Kubernetes so với docker-compose
  • Tôi đồng ý với tinh thần ở đây, nhưng đang viết lại nhiều thứ bằng Justfile
    https://github.com/casey/just
    Có thể tránh được rất nhiều điểm kỳ quặc riêng của Makefile

    • Việc GPT hỗ trợ viết Makefile đã thật sự đem lại sự sống thứ hai cho Makefile và làm chậm cái chết của nó
    • Tôi cũng vậy. Việc cùng một file chạy được trên Windows cũng là một điểm cộng
  • Đúng, Make rất tuyệt. Tôi dùng nó cho rất nhiều việc. Đây là một cách tốt để tự động hóa tác vụ
    Ví dụ, website cá nhân của tôi dùng Makefile gọi bash script để tạo lại các trang web đã cập nhật, git push lên server, rồi git hook trên server gọi Make để triển khai. Tuy nhiên, tôi không muốn đưa các khối binary thường xuyên thay đổi như PDF tài liệu bài giảng vào kho Git. Không sao cả. Makefile có target uploads chỉ tải các PDF đã sửa đổi lên server, và target này là phụ thuộc của target deploy thực hiện git push, nên tôi không cần bận tâm
    Ngoài ra, các PDF tài liệu bài giảng đã cập nhật được một Makefile khác tự động đưa vào cây source của website. Với Makefile đó, tôi có thể tạo PDF mình dùng từ source LaTeX, hoặc tạo các phiên bản thay thế cho sinh viên từ cùng source, chẳng hạn phiên bản không có lời giải bài tập, tự động đăng lên phiên bản website local rồi khi muốn thì đưa lên website đã cập nhật
    Đó là một kiểu cấu trúc Makefile nối tiếp bất tận. Tôi thích Makefile

  • Trong trường hợp này, thứ tác giả thật sự cần không phải make mà là just
    https://just.systems/man/en/

    • just chỉ là thêm một phụ thuộc nữa. make thì có ở khắp nơi
  • Với vai trò trình chạy tác vụ, make không tệ, nhưng ngày nay có những lựa chọn thay thế tốt hơn như just, như các bình luận khác đã nói
    Với vai trò hệ thống build, make ổn cho đến khi bạn gặp các nhược điểm của nó. make/Makefile không được chuẩn hóa, nên automake mới tồn tại. Vì vậy bạn không viết Makefile trực tiếp mà dùng template rồi để nó tạo makefile thật. Nếu bạn tự sở hữu toàn bộ toolchain thì không sao, nhưng đa số không như vậy, nên người ta làm thế để bảo đảm Makefile có tính di động
    make không thực hiện bất kỳ kiểu phân giải phụ thuộc nào và giả định rằng những thứ cần thiết đã ở ngay đó. Vì vậy mới có script configure; mà script configure cũng không phải chuẩn, nên trước khi chạy target của make, bạn lại tạo script configure bằng autoconf/autoreconf
    make và các công cụ lân cận như automake/autoconf/autoreconf dùng mtime khi xác định đầu vào có bị cũ hay không. Ngay cả khi chạy autoconf/autoreconf/automake/configure, bạn vẫn có thể rơi vào tình huống đầu vào mãi bị coi là cũ và không build được gì. Nhân tiện, nhiều hệ thống build dùng mtime vẫn ổn nếu có theo dõi phụ thuộc đúng cách
    Nhìn chung, khiếm khuyết thiết kế căn bản của make là nó được xây theo triết lý Unix, tức “làm một việc và làm thật tốt”. Việc đó là “nếu đầu vào đã cũ thì build lại target”, nhưng đây là một công cụ rất hạn chế, nên các hệ thống build hiện đại phải chồng rất nhiều thứ lên trên nó để khiến nó hữu ích hơn một trình chạy tác vụ cơ bản

    • make không phân giải phụ thuộc ư?
      dependency:
      ...
      target: dependency
      ...
    • Có thể đây là câu hỏi thiếu hiểu biết, nhưng phân giải phụ thuộc chẳng phải là cốt lõi của make sao? Chính xác thì ở đây đang nói đến điều gì?
    • Quy ước cũ bên đó là make configure. Cái này thiết lập những thứ cần cho make [build]
    • Điều tôi thực sự tiếc ở make chỉ là khả năng diễn giải mtime theo tiêu chí khác ngoài mtime
      Vì vậy cuối cùng phải dùng touchfile; tuy hơi bừa bộn nhưng vẫn hoạt động tốt hơn nhiều thứ khác. Tôi nói vậy đặc biệt là khi nhìn vào caching của docker build