makefile thực thi một mục tiêu khác


122

Tôi có một makefile có cấu trúc như sau:

all : 
    compile executable

clean :
    rm -f *.o $(EXEC)

Tôi nhận ra rằng tôi đã liên tục chạy "make clean", tiếp theo là "clear" trong thiết bị đầu cuối của mình trước khi chạy "make all". Tôi muốn có một thiết bị đầu cuối sạch trước khi thử và sàng lọc các lỗi biên dịch C ++ khó chịu. Vì vậy, tôi đã cố gắng thêm mục tiêu thứ 3:

fresh :
    rm -f *.o $(EXEC)
    clear
    make all

Điều này hoạt động, tuy nhiên điều này chạy phiên bản thứ hai của make (tôi tin là vậy). Có cách nào đúng để có được chức năng tương tự mà không cần chạy phiên bản thứ 2 của make không?

Câu trả lời:


171

Trên thực tế, bạn đã đúng: nó chạy một phiên bản khác của make. Một giải pháp khả thi sẽ là:

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : clean clearscr all

clearscr:
    clear

Bằng cách gọi điện, make freshbạn nhận được cleanmục tiêu đầu tiên , sau đó là mục tiêu clearscreenchạy clearvà cuối cùng là mục tiêu allthực hiện công việc.

CHỈNH SỬA 4 tháng 8

Điều gì xảy ra trong trường hợp xây dựng song song với -jtùy chọn của make ? Có một cách để sửa đơn hàng. Từ hướng dẫn làm, phần 4.2:

Tuy nhiên, đôi khi, bạn gặp trường hợp muốn áp đặt một thứ tự cụ thể cho các quy tắc được gọi mà không buộc cập nhật mục tiêu nếu một trong các quy tắc đó được thực thi. Trong trường hợp đó, bạn muốn xác định điều kiện tiên quyết chỉ đặt hàng. Điều kiện tiên quyết chỉ đặt hàng có thể được chỉ định bằng cách đặt một ký hiệu ống (|) trong danh sách điều kiện tiên quyết: mọi điều kiện tiên quyết ở bên trái của ký hiệu ống là bình thường; bất kỳ điều kiện tiên quyết nào ở bên phải là điều kiện chỉ theo đơn đặt hàng: target: normal-Preferences | điều kiện tiên quyết chỉ đặt hàng

Tất nhiên, phần điều kiện tiên quyết thông thường có thể để trống. Ngoài ra, bạn vẫn có thể khai báo nhiều dòng điều kiện tiên quyết cho cùng một mục tiêu: chúng được nối một cách thích hợp. Lưu ý rằng nếu bạn khai báo cùng một tệp vừa là điều kiện tiên quyết bình thường vừa là điều kiện tiên quyết chỉ đơn đặt hàng, thì điều kiện tiên quyết thông thường sẽ được ưu tiên (vì chúng là tập hợp chính xác của hành vi của điều kiện tiên quyết chỉ đặt hàng).

Do đó, makefile trở thành

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : | clean clearscr all

clearscr:
    clear

CHỈNH SỬA ngày 5 tháng 12

Không phải là vấn đề lớn nếu chạy nhiều hơn một phiên bản makefile vì mỗi lệnh bên trong nhiệm vụ sẽ là một sub-shell . Nhưng bạn có thể có các phương thức có thể sử dụng lại bằng cách sử dụng hàm gọi .

log_success = (echo "\x1B[32m>> $1\x1B[39m")
log_error = (>&2 echo "\x1B[31m>> $1\x1B[39m" && exit 1)

install:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  command1  # this line will be a subshell
  command2  # this line will be another subshell
  @command3  # Use `@` to hide the command line
  $(call log_error, "It works, yey!")

uninstall:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  ....
  $(call log_error, "Nuked!")

6
@ sas4740: về cơ bản mọi thứ sau đây .PHONY : được coi như một số từ khóa luôn được thực thi, trong khi các mục tiêu không phải giả mạo được dự định là tệp.
Dacav

"Điều kiện tiên quyết chỉ đặt hàng" có phải là điều kiện không? cho mục tiêu t2 Tôi muốn lần đầu tiên làm t0, vì chỉ nếu succeds t0 t1 chạy, và chỉ khi cả hai succeds chạy một số nhiệm vụ trong t3
fantastory

1
@fantastory, không, tôi nghĩ chúng độc lập. t2sẽ phụ thuộc vào t0, t1t3. Nếu bạn cần cái này, bạn nên đặt t3theo yêu cầu của t2, t1theo yêu cầu của t3t0theo yêu cầu của t1. Điều này có nghĩa là 3 quy tắc khác nhau. Tuy nhiên, bạn nên xác minh điều này. Tôi không chắc chắn 100%.
Dacav

3
"Điều kiện tiên quyết chỉ đặt hàng" là độc lập
fantastory

2
Tôi không thấy đâu là đảm bảo rằng 'sạch' thực hiện trước 'tất cả'? Thực tế là bạn đặt chúng ngay từ | không làm cho chúng thực thi theo thứ tự. Chỉ phụ thuộc vào đơn đặt hàng có nghĩa là mục tiêu không được cập nhật cần thiết sau hoạt động đó. Nó không liên quan gì đến thứ tự của các phần tử phụ thuộc ... hoặc?
CygnusX1

6

Nếu bạn đã xóa make alldòng khỏi mục tiêu "mới" của mình:

fresh :
    rm -f *.o $(EXEC)
    clear

Bạn có thể chỉ cần chạy lệnh make fresh all, lệnh này sẽ thực thi dưới dạng make fresh; make all.

Một số người có thể coi đây là một ví dụ thứ hai của make, nhưng chắc chắn nó không phải là một phiên bản phụ của make (làm bên trong make), đó là kết quả mà nỗ lực của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.