2012-12-03 40 views
6

Tôi có một cấu trúc thư mục sau đây trong dự án của tôi:Thực hành tốt của Makefile

bin/ 
dist/ 
include/ 
├── module_a/ 
└── module_b/ 
Makefile 
src/ 
├── module_a/ 
└── module_b/ 

Thư mục include/ chứa *.hpp 's trong khi *.cpp' s là trong src/. Tôi muốn biên dịch tất cả các nguồn thành bin/ và sau đó liên kết chúng với nhau để dist/. Có vẻ là một điều ước khá hợp lý đối với tôi.

Tôi muốn biết các phương pháp hay nhất cho Makefile cho trường hợp này. Tất cả tôi có thể tìm thấy là %.o: %.cpp mục tiêu, nhưng điều đó không thực sự làm việc, vì nguồn khác nhau và thư mục nhị phân.

Tôi đã cố gắng sử dụng một cái gì đó như thế này:

D_SRC = src 
D_BIN=bin 

F_CPP := $(shell find $(D_SRC) -iname '*.cpp' -type f) 
F_OBJ := $(shell echo $(F_CPP) | sed s:\ :\\n:g | sed s:$(D_SRC):$(D_BIN): | sed 's:^\(.*\)\.cpp$$:\1\.o:') 

$(F_OBJ): $(F_SRC)                 
    $(foreach file, $(F_SRC), \              
     $(GXX) $(CXXFLAGS) -c $(file)\            
    ) 

mục tiêu này không hoạt động, vì $(F_OBJ) đường dẫn bắt đầu với bin/, trong khi foreach biên dịch nguồn để dir làm việc hiện tại. Tôi có thể làm cho nó biên dịch thành bin/, nhưng điều đó sẽ xảy ra chỉ với một vài biểu thức sed và nó đủ xấu xí như nó.

Nó có lẽ khó khăn đối với tôi, bởi vì tôi không biết make tất cả những gì tốt, nhưng tôi không thể là người duy nhất có thiết lập dự án này. Theo tôi, nó phải là một thứ khá phổ biến. Tôi biết tôi có thể viết một Makefile cho từng mô-đun riêng biệt, nhưng đó thực sự là lựa chọn tốt nhất ở đây?

EDIT: Tôi đã tự hỏi tôi sẽ đạt được điều gì với một số Makefiles. Nếu một người ở gốc và một người khác ở số src/module_a, người này sẽ biết như thế nào về số bin/? Nếu bạn thực hiện nó với make -f src/module_a/Makefile, nó sẽ giống như thực thi nó từ thư mục gốc, vì thư mục làm việc của nó sẽ là gốc. Một cách khác, tôi đoán, sẽ thay đổi thư mục trước khi thực hiện nó, như vậy: make -C include/module_a, nhưng trong trường hợp đó, làm thế nào nó sẽ tìm thấy bin/? Tôi sẽ không muốn có một cái gì đó như D_BIN = ../../bin trong một Makefile.

+0

Đã cập nhật câu trả lời của tôi ... –

Trả lời

6

Những gì tôi thường làm là có một Makefile trong thư mục src (có thể được gọi từ cấp cao nhất Makefile nếu bạn thích) và sau đó sử dụng quy tắc như thế này:

D_BIN = ../bin 
$(D_BIN)/%.o: %.cpp 

Bạn cũng có thể thử nghiệm với chỉ một makefile trong dir cấp cao nhất, và các quy tắc sử dụng mà trông như thế này:

D_BIN = bin 
D_SRC = src 
$(D_BIN)/%.o: $(D_SRC)/%.cpp 

nhưng tôi đã không sử dụng quy tắc như vậy, vì vậy tôi không biết những ưu/nhược điểm vs cách tôi thường làm điều đó. Con đường tôi thường làm nó hoạt động tốt, tôi thậm chí có quy tắc xây dựng phụ thuộc như vậy:

$(D_BIN)/%.d: %.cpp 

và nguyên tắc liên kết sẽ như thế nào:

../dist/outexe: $(F_OBJ) 

Sử dụng foreach thường được tán thành bởi vì nó không sử dụng tất cả các tính năng được xây dựng thành quy tắc makefile thông thường (nghĩa là không có kiểm tra phụ thuộc vào từng tệp, hoặc bạn xây dựng mọi thứ hoặc không có gì), và như vậy chỉ nên sử dụng như một phương sách cuối cùng, nhưng trong trường hợp bạn sẽ có thể làm cho nó hoạt động mà không có sự cho phép.

Ngoài việc này có nhiều cách dễ dàng hơn để xây dựng danh sách tệp của bạn, bạn không cần phải sử dụng trình bao hoặc sed.

F_CPP = $(wildcard *.cpp) 
F_OBJ = $(F_CPP:.cpp=.o) 

Cập nhật: Đây là cách tôi thường đưa ra làm cho đệ quy:

SUBDIRS = src 
.PHONY: $(SUBDIRS) 
all: $(SUBDIRS) 

$(SUBDIRS): 
    @echo "Building [email protected]" 
    $(MAKE) -C [email protected] $(MFLAGS) 

Sau đó thực sự trong submake bạn, bạn sẽ cần phải sử dụng ../bin ví dụ.

Tuy nhiên với một dự án đơn giản như của bạn, bạn có thể là tốt hơn hết chỉ có một makefile ở cấp độ gốc và sử dụng quy tắc như thế này:

D_BIN = bin 
D_SRC = src 
$(D_BIN)/%.o: $(D_SRC)/%.cpp 

makefiles đệ quy là ok (ok nhưng không lớn) nếu bạn có một cấu trúc thư mục thực sự phức tạp, nơi bạn sẽ thêm/xóa/sửa đổi cây dir mới khi thời gian trôi qua. Nhưng đối với một dự án đơn giản, nơi bạn chỉ muốn có các thư mục riêng biệt cho mã và obj, nó có lẽ là quá mức cần thiết.

+0

Điều này trông giống như mọi thứ tôi đang tìm kiếm. Tôi không thể kiểm tra nó ngay bây giờ, nhưng theo như tôi có thể nói, điều này sẽ làm việc. Cảm ơn nhiều. –

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