2016-02-19 16 views
5

Có ai biết cách sử dụng chuyển hướng tài liệu ở đây trên công thức không?Công thức Makefile với chuyển hướng tài liệu tại đây

test: 
    sh <<EOF 
    echo I Need This 
    echo To Work 
    ls 
    EOF 

tôi không thể tìm thấy bất kỳ giải pháp cố gắng phương pháp xuyệc ngược thông thường (mà về cơ bản kết thúc bằng một lệnh trong một dòng duy nhất).

Lý do:

Tôi có một tập hợp các công thức nấu ăn nhiều đường mà tôi muốn để proxy thông qua lệnh khác (ví dụ, sh, Docker).

onelinerecipe := echo l1 
define twolinerecipe := 
echo l1 
echo l2 
endef 
define threelinerecipe := 
echo l1 
echo l2 
echo l3 
endef 

# sh as proxy command and proof of concept 
proxy := sh 

test1: 
    $(proxy) <<EOF 
    $(onelinerecipe) 
    EOF 

test2: 
    $(proxy) <<EOF 
    $(twolinerecipe) 
    EOF 

test3: 
    $(proxy) <<EOF 
    $(threelinerecipe) 
    EOF 

Giải pháp tôi muốn tránh: chuyển đổi macro nhiều dòng thành một dòng.

define threelinerecipe := 
echo l1; 
echo l2; 
echo l3 
endef 

test3: 
    $(proxy) <<< "$(strip $(threelinerecipe))" 

Công trình này (tôi sử dụng gmake 4.0 và bash làm vỏ) nhưng yêu cầu thay đổi công thức và tôi có rất nhiều. Dải xóa các dòng mới, khỏi macro, sau đó mọi thứ được viết trong một dòng.

mục tiêu cuối cùng của tôi là: proxy := docker run ...

+0

Làm thế nào về sh -c ''đặt lệnh của bạn ở đây''? – fanton

+0

Có thể trùng lặp của [Heredoc trong một Makefile?] (Http://stackoverflow.com/questions/5873025/heredoc-in-a-makefile) – e0k

+0

@ e0k Tôi đã thêm ngữ cảnh –

Trả lời

5

Sử dụng dòng .ONESHELL: đâu đó trong Makefile của bạn sẽ gửi tất cả các dòng công thức để một invocation vỏ duy nhất, bạn nên tìm Makefile gốc của bạn hoạt động như mong đợi.

+1

Ghi chú thiếu quan trọng: hiệu ứng của nó là toàn cầu và không phải cục bộ cho một quy tắc và công thức duy nhất. Nếu nó xuất hiện ở bất kỳ đâu trong makefile thì ** tất cả ** dòng recipe ** cho mỗi ** target sẽ được cung cấp cho một lời gọi đơn của shell. Nó không đưa ra vấn đề trong trường hợp của tôi. Nhưng cũng lưu ý rằng '.SHELLFLAGS = -ec' là bắt buộc để giữ cho hành vi mặc định của việc để lại do lỗi. –

+1

Tôi đã sử dụng giải pháp này cho một số ngày và hạn chế duy nhất mà tôi có cho đến nay là lặp lại các vấn đề. Bởi vì với '.ONESHELL:', dẫn '@' bây giờ là hợp lệ cho toàn bộ công thức. Điều này làm cho chọn lọc vang (echo một lệnh và không khác) không còn có thể. Để giải quyết điều này, bạn chỉ có thể thay đổi công thức của bạn, do đó phá vỡ một quy tắc tôi đang tìm kiếm: proxy minh bạch. Dù sao, đây là giải pháp duy nhất cho phép ở đây-doc, vì vậy tôi xác nhận nó. –

3

Khi làm thấy một khối đa dòng trong một công thức (ví dụ, một khối dòng tất cả kết thúc bằng \, ngoài việc cuối cùng), nó đi mà khối un-modifed để vỏ. Điều này thường hoạt động trong bash, ngoài các tài liệu này.

Một cách để khắc này là dải bất kỳ trailing \ s, sau đó vượt qua chuỗi kết quả để bash 's eval. Bạn làm điều này trong làm cho bằng cách chơi với ${.SHELLFLAGS}${SHELL}. Bạn có thể sử dụng cả hai biểu mẫu này ở dạng mục tiêu cụ thể nếu bạn chỉ muốn nó khởi động cho một vài mục tiêu.

.PHONY: heredoc 

heredoc: .SHELLFLAGS = -c eval 
heredoc: SHELL = bash -c 'eval "$${@//\\\\/}"' 

heredoc: 
    @echo First 
    @cat <<-there \ 
     here line1 \ 
     here anotherline \ 
    there 
    @echo Last 

cho

$ make 
First 
here line1 
here anotherline 
Last 

Cẩn thận với trích dẫn, Eugene. Lưu ý gian lận ở đây: Tôi xóa tất cả các dấu gạch chéo ngược, không chỉ các dấu gạch chéo ở cuối dòng. YMMV.

+0

Đặc biệt, cảm ơn "Khi thực hiện thấy một khối nhiều dòng trong một công thức (tức là, một khối tất cả kết thúc bằng \, ngoài việc cuối cùng), nó chuyển khối đó chưa được sửa đổi cho vỏ." bit: Tôi đã cố gắng sử dụng một tài liệu ở đây, nơi nó được giải quyết bằng kỹ thuật đó một mình. – kostix

Các vấn đề liên quan