make: Không có gì phải làm cho tất cả


97

Tôi đang đi qua một ví dụ pgm để tạo một tệp tạo.

http://mrbook.org/tutorials/make/

Thư mục eg_make_creation của tôi chứa các tệp sau,

desktop:~/eg_make_creation$ ls
factorial.c  functions.h  hello  hello.c  main.c  Makefile

Makefile

# I am a comment, and I want to say that the variable CC will be
# the compiler to use.
CC=gcc
# Hwy!, I am comment no.2. I want to say that CFLAGS will be the
#options I'll pass to the compiler
CFLAGS=-c -Wall

all:hello

hello:main.o factorial.o hello.o
  $(CC) main.o factorial.o hello.o -o hello

main.o:main.c
  $(CC) $(CFLAGS) main.c

factorial.o:factorial.c
  $(CC) $(CFLAGS) factorial.c

hello.o:hello.c
  $(CC) $(CFLAGS) hello.c

clean:
  rm -rf *o hello

lỗi:

desktop:~/eg_make_creation$ make all
make: Nothing to be done for `all'.

Xin hãy giúp tôi hiểu để biên dịch chương trình này.


12
Hãy thử làm một "làm sạch" theo sau là một "làm cho tất cả"
Paul R

11
Đó không phải là một lỗi, nó chỉ có nghĩa hellolà đã được cập nhật. Thay đổi cleanthành rm -f *.o hellotrước khi nó thực hiện điều gì đó không mong muốn, sau đó chạy make clean allvà xem liệu điều đó có hoạt động không.
Mat

1
Bạn cũng nên thêm .phony: all clean, vì allcleankhông phải tên tệp.
Kerrek SB

3
Không đặt -c trong CFLAGS của bạn.
wildplasser

Câu trả lời:


121

Đôi khi, lỗi "Không có gì phải làm cho tất cả" có thể do dấu cách trước lệnh trong quy tắc makefile thay vì tab. Hãy đảm bảo rằng bạn sử dụng các tab thay vì khoảng trắng bên trong quy tắc của mình.

all:
<\t>$(CC) $(CFLAGS) ...

thay vì

all:
    $(CC) $(CFLAGS) ...

Vui lòng xem hướng dẫn tạo GNU để biết mô tả cú pháp quy tắc: https://www.gnu.org/software/make/manual/make.html#Rule-Syntax


obj-m + = hello.o all: </t> make -C / lib / modules / $ (shell uname -r) / build M = $ (PWD) module clean: make -C / lib / modules / $ ( shell uname -r) / build M = $ (PWD) clean
Narendra Jaggi

tệp trên là tệp hợp lệ ??
Narendra Jaggi

Trong ngữ cảnh của makefile mẹ-con, đôi khi lỗi "Không có gì phải làm cho tất cả" có thể do các mục tiêu con được đánh dấu không chính xác được khai báo .PHONY trong Makefile mẹ.
donhector

Tôi đã có all : src/server/mod_wsgi.la, mà tôi đã đổi thành all : </t> src/server/mod_wsgi.la. Bây giờ tôi nhận được lỗi: make: execvp: src/server/mod_wsgi.la: Permission denied Makefile:29: recipe for target 'all' failed make: *** [all] Error 127sau khi sudo make. Bất kỳ giúp đỡ?
Mooncrater

@Mooncrater Xem gnu.org/software/make/manual/make.html#Rule-Syntax . Ở đây có nội dung: Các dòng công thức bắt đầu bằng ký tự tab (hoặc ký tự đầu tiên trong giá trị của biến .RECIPEPREFIX; xem Biến đặc biệt). Dòng công thức đầu tiên có thể xuất hiện trên dòng sau điều kiện tiên quyết, với một ký tự tab hoặc có thể xuất hiện trên cùng một dòng, với dấu chấm phẩy. Dù bằng cách nào thì hiệu quả là như nhau. Vì vậy, điều kiện tiên quyết của bạn chỉ đơn giản là trở thành công thức. Bạn không cần tab trong trường hợp này.
VirtualVDX

31

Xóa hellotệp khỏi thư mục của bạn và thử lại.

Các allmục tiêu phụ thuộc vào hellomục tiêu. Các hellomục tiêu đầu tiên cố gắng tìm tập tin tương ứng trong hệ thống tập tin. Nếu nó tìm thấy nó và nó được cập nhật với các tệp phụ thuộc — thì không cần làm gì cả.


obj-m + = hello.o all: </t> make -C / lib / modules / $ (shell uname -r) / build M = $ (PWD) module clean: make -C / lib / modules / $ ( shell uname -r) / build M = $ (PWD) clean
Narendra Jaggi

ở trên có phải là một tập tin làm hợp lệ không?
Narendra Jaggi

21

Khi bạn chỉ tạo make, nó sẽ tạo ra quy tắc đầu tiên trong makefile của bạn, tức là "tất cả". Bạn đã chỉ định rằng "tất cả" phụ thuộc vào "hello", phụ thuộc vào main.o, factorial.o và hello.o. Vì vậy, 'make' cố gắng xem liệu các tệp đó có tồn tại hay không.

Nếu chúng có mặt, hãy 'make' xem liệu các phụ thuộc của chúng, ví dụ: main.o có phụ thuộc main.c, có thay đổi không. Nếu chúng đã thay đổi, hãy tạo lại chúng, nếu không sẽ bỏ qua quy tắc. Tương tự, nó tiếp tục xây dựng một cách đệ quy các tệp đã thay đổi và cuối cùng chạy lệnh trên cùng, "tất cả" trong trường hợp của bạn để cung cấp cho bạn một tệp thực thi, 'xin chào' trong trường hợp của bạn.

Nếu họ không có mặt, hãy mù quáng xây dựng mọi thứ theo quy tắc.

Đến với vấn đề của bạn, nó không phải là một lỗi nhưng 'make' đang nói rằng mọi phụ thuộc trong makefile của bạn đều được cập nhật và nó không cần phải tạo bất cứ thứ gì!


16

Make đang hoạt động chính xác. hellođã tồn tại và không cũ hơn các .ctệp, và do đó không còn việc phải làm nữa. Có bốn tình huống trong đó thực hiện sẽ cần (lại) xây dựng:

  • Nếu bạn sửa đổi một trong các .ctệp của mình , thì tệp đó sẽ mới hơn hellovà sau đó nó sẽ phải xây dựng lại khi bạn chạy make.
  • Nếu bạn xóa hello, thì rõ ràng nó sẽ phải xây dựng lại
  • Bạn có thể buộc thực hiện để xây dựng lại mọi thứ với -Btùy chọn.make -B all
  • make clean allsẽ xóa hellovà yêu cầu xây dựng lại. (Tôi đề nghị bạn xem nhận xét của @ Mat vềrm -f *.o hello

4

Tôi nghĩ rằng bạn đã bỏ lỡ một tab ở dòng thứ 9. Dòng sau tất cả: xin chào phải là một tab trống. Đảm bảo rằng bạn có một tab trống ở dòng thứ 9. Nó sẽ làm cho trình thông dịch hiểu rằng bạn muốn sử dụng công thức mặc định cho makefile.


4

Đó không phải là một lỗi; lệnh make trong unix hoạt động dựa trên dấu thời gian. Tức là nếu bạn đã thực hiện một số thay đổi nhất định factorial.cppvà biên dịch bằng cách sử dụng makethì hãy thực hiện hiển thị thông tin mà chỉ cc -o factorial.cpplệnh được thực thi. Lần tới nếu bạn thực hiện cùng một lệnh tức là makekhông thực hiện bất kỳ thay đổi nào đối với bất kỳ tệp nào có .cppphần mở rộng, trình biên dịch sẽ thông báo rằng tệp đầu ra đã được cập nhật. Trình biên dịch cung cấp thông tin này cho đến khi chúng tôi thực hiện các thay đổi nhất định đối với bất kỳ file.cpp.

Ưu điểm của makefilenó là nó giảm thời gian biên dịch bằng cách biên dịch các tệp duy nhất được sửa đổi và bằng cách sử dụng .otrực tiếp các tệp đối tượng ( ) của các tệp chưa được sửa đổi.


0

Tôi đã đến một lỗi đặc biệt, khó gỡ lỗi này thông qua một con đường khác. Rắc rối của tôi cuối cùng là tôi đang sử dụng quy tắc mẫu trong bước xây dựng khi mục tiêu và phần phụ thuộc nằm trong các thư mục riêng biệt. Một cái gì đó như thế này:

foo/apple.o: bar/apple.c $(FOODEPS)

%.o: %.c
    $(CC) $< -o $@

Tôi đã thiết lập một số phụ thuộc theo cách này và đang cố gắng sử dụng một công thức mẫu cho tất cả chúng. Rõ ràng, một thay thế duy nhất cho "%" sẽ không hoạt động ở đây. Tôi đã đưa ra các quy tắc rõ ràng cho từng phụ thuộc và tôi thấy mình đã trở lại giữa những chú chó con và kỳ lân!

foo/apple.o: bar/apple.c $(FOODEPS)
    $(CC) $< -o $@

Hy vọng điều này sẽ giúp ai đó!

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.