2009-10-23 35 views
23

Làm cách nào để chạy tập lệnh, phải thực thi trước tất cả các lệnh makefile khác? Và nó sẽ được tốt đẹp (nhưng không bắt buộc) để kịch bản không được thực hiện nếu không có gì để xây dựng.Tạo trước một bước trong makefile

Tôi đã tìm kiếm SO và Google nhưng không thể tìm thấy bất kỳ thứ gì.

Tôi có cách giải quyết này:

# myscript.bat output is empty 
CHEAT_ARGUMENT = (shell myscript.bat) 
CFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT) 
AFLAGS += -DCHEAT_ARGUMENT=$(CHEAT_ARGUMENT) 

Nhưng nó rất xấu xí. Có cách nào khác để chạy "tạo trước bước" trong makefile?

+0

"không thực thi nếu không có gì để xây dựng" không phải là rất quan trọng bây giờ, nhưng sẽ là tốt. Câu hỏi đã thay đổi. – zxcat

+0

Bạn đang cố gắng làm gì? Myscript.bat làm gì? Bạn có thực sự chỉ cần cố gắng tính toán một số cờ biên dịch bổ sung, hoặc đây là một ví dụ contrived? –

+0

Tập lệnh của tôi được sửa đổi và kiểm tra SVN, nó được sửa đổi từ lần commit cuối cùng. Nó đặt thông tin này vào kịch bản lệnh khác (tạo tệp rev.bat), thông tin này xuất ra đơn giản mà không cần bất cứ điều gì khác. Sau đó trong makefile tôi sử dụng REVISION = $ (shell rev.bat) để có được thông tin này. Và sau đó: AXF_FILE = project_r $ (REVISION) _ $ (KIẾN TRÚC) .axf – zxcat

Trả lời

22

Tôi đề xuất hai giải pháp. Các bắt chước đầu tiên những gì NetBeans IDE tạo:

CC=gcc 

.PHONY: all clean 

all: post-build 

pre-build: 
    @echo PRE 

post-build: main-build 
    @echo POST 

main-build: pre-build 
    @$(MAKE) --no-print-directory target 

target: $(OBJS) 
    $(CC) -o [email protected] $(OBJS) 

clean: 
    rm -f $(OBJS) target 

Điều thứ hai là inpired bởi những gì Eclipse IDE tạo:

CC=gcc 

.PHONY: all clean 
.SECONDARY: main-build 

all: pre-build main-build 

pre-build: 
    @echo PRE 

post-build: 
    @echo POST 

main-build: target 

target: $(OBJS) 
    $(CC) -o [email protected] $(OBJS) 
    @$(MAKE) --no-print-directory post-build 

clean: 
    rm -f $(OBJS) target 

Lưu ý rằng trong một đầu tiên, trước và sau khi xây dựng được luôn gọi bất kể xây dựng chính được xác định là được cập nhật hay không.

Trong bước thứ hai, bước sau khi xây dựng không được thực hiện nếu trạng thái của bản dựng chính được cập nhật. Trong khi bước xây dựng trước luôn được thực hiện trong cả hai.

+5

tạo trước không phải chạy trước khi xây dựng chính trong ví dụ thứ hai vì không có sự phụ thuộc giữa chúng. Xem ra cho điều này nếu bạn làm một song song làm. –

+0

Scott Wales là chính xác. Tôi đã nhìn thấy các phụ thuộc bổ sung được thêm vào từ bản dựng trước để xây dựng chính và từ xây dựng chính đến sau xây dựng, để chống lại điều này. – mlepage

+0

Tôi nghĩ bạn đúng ... Hãy đề nghị/thực hiện các chỉnh sửa để cải thiện ví dụ thứ hai. – Amro

9

Tùy thuộc vào phiên bản make của bạn, giống như sau ít nhất nên tránh chạy hàng chục lần nếu CFLAGS và AFLAGS được đánh giá hàng chục lần:

CHEAT_ARG := $(shell myscript) 

Note đại tràng.

Điều này chạy chính xác một lần. Không bao giờ nhiều hơn một lần, nhưng cũng không bao giờ ít hơn một lần. Chọn sự cân bằng của riêng bạn.

+0

Sẽ không chạy anyway ngay cả khi nó không cần phải? Câu hỏi yêu cầu nó không thực thi nếu không có gì để xây dựng. –

+0

Ồ đúng. Vâng, ít nhất nó chạy chính xác một lần và do đó không bao giờ mover hơn một lần, ngay cả khi có hàng chục quy tắc mở rộng CFLAGS và AFLAGS. – ndim

+1

ndim, Cảm ơn bạn! Câu trả lời này là cách tốt nhất cho tôi. – zxcat

3

Những gì bạn đang đề xuất có vẻ hơi "không giống như". Tại sao không chỉ chạy lệnh trong bất kỳ mục tiêu makefile nào bạn cần nó đi trước?

Ví dụ, nếu bạn cần nó để chạy trước khi nối foo:

foo: ${OBJS} 
    my-command-goes-here 
    ${CC} -o [email protected] ${OBJS} ${LIBS} 
+1

Cảm ơn bạn đã trả lời. Vâng, tôi cũng đã thử điều này. Nhưng tôi có nhiều quy tắc $ (CC) và $ (AS) (armasm sử dụng các tham số khác nhau cho các kiến ​​trúc khác nhau - nhị phân là phổ quát và chọn mã phụ thuộc vào kiến ​​trúc trong thời gian chạy). Và không nên thêm "lệnh của tôi" vào nhiều nơi. Nhưng tốt hơn thì phương pháp hiện tại của tôi – zxcat

+0

Tôi không thể chạy nó trước khi liên kết, bởi vì tôi cần kết quả trước đó. Và tôi muốn chạy nó một lần, không phải trên mỗi quá trình xử lý tệp. Trước khi bất kỳ tập tin precessing khác. – zxcat

5

Bạn có thể thêm một mục tiêu đặc biệt để Makefile của bạn và có tất cả xây dựng quy tắc của bạn phụ thuộc vào điều đó:

run-script: 
    myscript 

.o.c: run-script 
    $(CC) $(CFLAGS) -o [email protected] $< 

.o.S: run-script 
    $(AS) $(AFLAGS) -o [email protected] $< 

Tuỳ về những gì kịch bản của bạn thực sự làm, đặt nó để chạy một lần trong một giai đoạn trước khi Makefile (cấu hình giai đoạn trong điều khoản autoconf) có thể làm cho ý nghĩa hơn (và được ít công việc).

+0

Nó gần như giống nhau, như asveikau đề nghị. Kịch bản sẽ được thực hiện trước mỗi tệp (nhiều lần). – zxcat

+0

Và autoconf sẽ cho kết quả giống như câu trả lời đầu tiên của bạn, phải không? – zxcat

+1

Uhm, bạn nói đúng (cần thêm cà phê). Chỉ khi bạn có thể thể hiện một số việc làm phù hợp trên tập lệnh của mình, bạn có thể lưu vào các lời gọi. – ndim

1

Cảm ơn bạn đã trả lời. ndim đã giúp tôi rất nhiều, asveikau. Tệp cuối cùng là một tệp nhị phân có thể thực thi được, vì vậy tôi có thể sử dụng ngay bây giờ như sau:

run-script: 
    myscript 
$(AXF_FILE): run-script $(OBJ_DIRS) $(OBJ_FILES) 
    $(LINK) #...... 

Nó sẽ chạy myscript một lần. Giá trị {AXF_FILE} tùy thuộc vào myscript và tôi phải chạy nó trước. Và trong trường hợp này myscript chạy luôn, không chỉ khi xây dựng lại là cần thiết. Sau, Câu trả lời đơn giản nhất lóe lên trong óc tôi:

all: run-script $(AXF_FILE) 

Đó là tất cả;) (Tất nhiên, bất kỳ mục tiêu có thể được sử dụng thay cho "tất cả")


Chỉnh sửa: phương thức này thực thi tập lệnh sau $ (AXF_FILE) cũng được tính toán. Vì vậy, nó có thể để có được giá trị sai của AXF_FILE. Bây giờ chỉ có câu trả lời đầu tiên bởi ndim hoạt động như tôi cần.

+0

Tôi không nghĩ rằng điều này đảm bảo rằng tập lệnh chạy xảy ra trước khi các tệp obj được tạo. – mlepage

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