Làm thế nào để truyền đối số cho Makefile từ dòng lệnh?


109

Làm thế nào để truyền đối số cho Makefile từ dòng lệnh?

Tôi hiểu tôi có thể làm

$ make action VAR="value"
$ value

với Makefile

VAR = "default"
action:
    @echo $(VAR)

Làm thế nào để tôi có được hành vi sau đây?

$ make action value
value

?

Làm thế nào về

$make action value1 value2
value1 value2


3
Có thể có bản sao của Truyền đối số để "chạy"
lesmana

Câu trả lời:


212

Bạn có thể không nên làm điều này; bạn đang phá vỡ khuôn mẫu cơ bản về cách hoạt động của Make. Nhưng đây là:

action:
        @echo action $(filter-out $@,$(MAKECMDGOALS))

%:      # thanks to chakrit
    @:    # thanks to William Pursell

CHỈNH SỬA:
Để giải thích lệnh đầu tiên,

$(MAKECMDGOALS) là danh sách các "mục tiêu" được viết trên dòng lệnh, ví dụ: "action value1 value2".

$@là một biến tự động cho tên của mục tiêu của quy tắc, trong trường hợp này là "hành động".

filter-outlà một hàm loại bỏ một số phần tử khỏi danh sách. Vì vậy, $(filter-out bar, foo bar baz)trả về foo baz(nó có thể tinh tế hơn, nhưng chúng ta không cần sự tinh tế ở đây).

Đặt chúng lại với nhau và $(filter-out $@,$(MAKECMDGOALS))trả về danh sách các mục tiêu được chỉ định trên dòng lệnh không phải là "action", có thể là "value1 value2".


1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')để bỏ qua tất cả các mục tiêu trước đó và chỉ coi những điều sau là đối số:make target1 target2 action value1 value2
Evgeniy Generalov

1
Xin thứ lỗi cho sự thiếu hiểu biết của tôi. Tôi đã thử googling %:@:không thể tìm thấy thông tin về những gì "chỉ thị" (hoặc bất cứ điều gì chúng được gọi) làm. Bạn có thể vui lòng giải thích?
Jon

15
@Jon: Sách hướng dẫn ở đây . Phần bao gồm %:@:là một quy tắc . Tên mục tiêu %có nghĩa là nó là một quy tắc phù hợp với bất kỳ thứ gì ; nghĩa là, nếu Make không thể tìm thấy bất kỳ cách nào khác để xây dựng thứ mà bạn yêu cầu nó xây dựng, nó sẽ thực thi quy tắc đó. Đây @:là một công thức ; các :phương tiện không làm gì cả, và các @phương tiện làm điều đó âm thầm.
Beta

Cảm ơn. Tôi đã đọc hướng dẫn sử dụng đó và lúc đầu tôi không xem xét, đó %:thực sự là % :, tên mục tiêu kiểu ký tự đại diện. Tôi không thấy bất kỳ điều gì trong trang hướng dẫn đó liên quan đến @:mặc dù ... nó gợi ý rằng quy tắc "không làm gì" chỉ đơn giản là có ;sau đặc tả mục tiêu, vì vậy, sẽ không chính xác hơn nếu viết % : ;là "ký tự đại diện làm -không có gì "quy tắc?
Jon

1
filter-outkhông hoạt động khi hành động là một phần phụ thuộc của mục tiêu được chỉ định trên dòng lệnh, vì $@sẽ được đặt thành tên của phần phụ thuộc, không phải đối số ban đầu được gọi trên dòng lệnh. Thay vào đó, tôi gán MAKECMDGOALScho một mảng shell và sau đó xóa phần tử đầu tiên:@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
Gingi

18

Đây là một giải pháp làm việc chung dựa trên @ Beta's

Tôi đang sử dụng GNU Make 4.1 với SHELL=/bin/bashtrên đỉnh Makefile của tôi, vì vậy YMMV!

Điều này cho phép chúng tôi chấp nhận các tranh luận phụ (bằng cách không làm gì khi chúng tôi nhận được một công việc không phù hợp, thay vì ném một lỗi).

%:
    @:

Và đây là một macro nhận được thông tin chi tiết cho chúng tôi:

args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`

Đây là một công việc có thể gọi là:

test:
    @echo $(call args,defaultstring)

Kết quả sẽ là:

$ make test
defaultstring
$ make test hi
hi

Ghi chú! Tốt hơn là bạn nên sử dụng "Taskfile", là một mẫu bash hoạt động tương tự để tạo, chỉ không có các sắc thái của Maketools. Xem https://github.com/adriancooney/Taskfile


Nó đã làm việc!! CHO người khác dùng thử, hãy chắc chắn rằng có tabtrước đó @echo, không space.
Abdullah Al Maruf - Tuhin

11

Aproach dễ dàng hơn nhiều. Xem xét một nhiệm vụ:

provision:
        ansible-playbook -vvvv \
        -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory \
        --private-key=.vagrant/machines/default/virtualbox/private_key \
        --start-at-task="$(AT)" \
        -u vagrant playbook.yml

Bây giờ khi tôi muốn gọi nó, tôi chỉ cần chạy một cái gì đó như:

AT="build assets" make provision

hoặc chỉ:

make provisiontrong trường hợp ATnày là một chuỗi rỗng


-2

đừng cố gắng làm điều này

$ make action value1 value2

thay vào đó hãy tạo tập lệnh:

#! /bin/sh
# rebuild if necessary
make
# do action with arguments
action "$@"

và làm điều này:

$ ./buildthenaction.sh value1 value2

để biết thêm lời giải thích tại sao điều này và cảnh báo về makefile hackery, hãy đọc câu trả lời của tôi cho một câu hỏi khác rất giống nhưng dường như không trùng lặp: Chuyển đối số để "chạy"

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.