2011-01-12 20 views
8

Tôi có mã chung (ví dụ: hello.cpp) được nhiều tệp thi hành sử dụng. Tôi đang sử dụng một Makefile để xây dựng tất cả:Giúp đơn giản hóa một Makefile cho nhiều tập tin thực thi

EXE=app1.out app2.out 
SRC=hello.cpp 
OBJ=$(SRC:.cpp=.o) 
SRC_MAIN=app1.cpp app2.cpp 
OBJ_MAIN=$(SRC_MAIN:.cpp=.o) 
all: $(EXE)  
app1.out: app1.o $(OBJ) 
    g++ $< $(OBJ) -o [email protected]  
app2.out: app2.o $(OBJ) 
    g++ $< $(OBJ) -o [email protected]  
.cpp.o: 
    g++ -c $< -o [email protected]  
clean: 
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN) 

Tôi không hài lòng về việc có mục tiêu riêng cho từng mục đích thực thi - các mục tiêu về cơ bản giống nhau. Có cách nào để làm điều này với một mục tiêu cho tất cả các thực thi? Tôi đã hy vọng rằng một cái gì đó như thế này sẽ làm việc:

EXE=app1.out app2.out 
SRC=hello.cpp 
OBJ=$(SRC:.cpp=.o) 
SRC_MAIN=app1.cpp app2.cpp 
OBJ_MAIN=$(SRC_MAIN:.cpp=.o) 
all: $(EXE) 
.o.out: $(OBJ) 
    g++ $< $(OBJ) -o [email protected] 
.cpp.o: 
    g++ -c $< -o [email protected] 
clean: 
    rm -f $(EXE) $(OBJ) $(OBJ_MAIN) 

Nhưng tôi nhận được một lỗi khi liên kết:

[email protected]:~/cpp/stack$ make -f Makefile2 
g++ -c app1.cpp -o app1.o 
g++ app1.o hello.o -o app1.out 
g++: hello.o: No such file or directory 
make: *** [app1.out] Error 1 
rm app1.o 

Đối với một số lý do nó cố gắng để xây dựng app1.out mà không cần xây dựng sự phụ thuộc của nó hello.o. Bất cứ ai có thể giải thích lý do tại sao điều này không làm việc, và đề nghị một cái gì đó mà không?

Đây là phần còn lại của mã giả, chỉ trong trường hợp.

app1.cpp:

#include "hello.h" 
int 
main(void) 
{ 
    print_hello(); 
} 

app2.cpp:

#include "hello.h"  
int 
main(void) 
{ 
    for (int i = 0; i < 4; ++i) 
     print_hello(); 
    return 0; 
} 

hello.cpp:

#include "hello.h"  
#include <stdio.h>  
void 
print_hello() 
{ 
    printf("hello world!\n"); 
} 

hello.h:

#ifndef HELLO_H 
#define HELLO_H 
void 
print_hello(); 
#endif 

Trả lời

4

Sự cố có vẻ là bạn đang sử dụng các quy tắc hậu tố kiểu cũ. Từ làm cho thông tin:

Suffix rules cannot have any prerequisites of their own. If they have any, they are treated as normal files with funny names, not as suffix rules. Thus, the rule:

.c.o: foo.h 
      $(CC) -c $(CFLAGS) $(CPPFLAGS) -o [email protected] $< 

tells how to make the file '.c.o' from the prerequisite file 'foo.h', and is not at all like the pattern rule:

%.o: %.c foo.h 
      $(CC) -c $(CFLAGS) $(CPPFLAGS) -o [email protected] $< 

which tells how to make '.o' files from '.c' files, and makes all '.o' files using this pattern rule also depend on 'foo.h'.

Các giải pháp là sử dụng kiểu mới quy tắc mẫu:

%.out: %.o $(OBJ) 
    g++ $< $(OBJ) -o [email protected] 
%.o: %.cpp 
    g++ -c $< -o [email protected] 

(Cũng lưu ý rằng bạn không cần phải xác định một cpp để .o quy tắc; make có một mặc định hợp lý.)

+0

Cảm ơn câu trả lời của bạn. Tôi sử dụng quy tắc .cpp to .o để cung cấp 'CPPFLAGS' tùy chỉnh cho trình biên dịch. Tôi đã không hiển thị chúng trong mã mẫu vì tôi đã giữ mọi thứ đơn giản. Các giá trị mặc định 'làm' sẽ vẫn bao gồm các tên biến" mặc định "(ví dụ:' CFLAGS', 'CPPFLAGS',' LDFLAGS', v.v ...)? – misha

+1

Có, nhưng 'CPPFLAGS' dành cho bộ xử lý trước C. 'CXXFLAGS' là dành cho cờ C++. –

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