2012-10-17 38 views
8

Tôi muốn xây dựng một ứng dụng và tôi có nhiều mô-đun được lưu trữ trong nhiều thư mục. Tôi đã quyết định thực hiện theo ý tưởng this, tức là có một tệp makefile trong mỗi thư mục và sau đó hợp nhất nó. Nhưng - như một lập trình viên mới bắt đầu - tôi vẫn không thấy làm thế nào để làm điều đó. Trước hết, làm thế nào sẽ như vậy "một phần" makefiles trông như thế nào. Chúng không thể có chức năng chính vì có thể chỉ có một cho mỗi nhị phân, mặc dù khi tôi cố gắng biên dịch nó gcc than phiền cho tham chiếu không xác định đối với chính. Thứ hai, tôi không có ý tưởng làm thế nào để đưa tất cả các mô-đun với nhau như thế nào.Makefiles trong nhiều thư mục

Tôi sẽ đánh giá cao bất kỳ trợ giúp nào, nhưng hãy cố gắng giữ cho câu trả lời của bạn đơn giản. Makefiles vẫn là một chút ma thuật đen đối với tôi.

+0

Bản sao có thể có của [Makefiles với tệp nguồn trong các thư mục khác nhau] (http://stackoverflow.com/questions/1139271/makefiles-with-source-files-in-different-directories) –

Trả lời

25

Trước khi bạn có thể làm bất cứ điều gì với một makefile, bạn phải biết làm thế nào để làm điều đó mà không có một makefile.

Vì bạn đang sử dụng gcc, tôi sẽ giả định rằng mã nguồn của bạn là C++.

Bạn chưa cho chúng tôi biết cấu trúc thư mục của bạn trông như thế nào, vì vậy tôi cho rằng bạn có ba tệp nguồn trong hai thư mục: primary/main.cc, other/foo.ccother/bar.cc. (Chúng tôi có thể xử lý các tệp tiêu đề như sau: foo.h.) Và bạn muốn xây dựng myApp.

Bước 1: làm việc đó bằng tay

Để làm điều này trong một lệnh, bạn có thể sử dụng:

gcc -Wall primary/main.cc other/foo.cc other/bar.cc -o myApp 

này sẽ biên dịch ba file nguồn và liên kết các đối tượng nhị phân với nhau thành các thực thi myApp.

Bước 2: Làm ra từ miếng (. Đừng cố này cho đến khi bạn có thể nhận được các bước trước để hoạt động hoàn hảo)

Thay vì xây dựng với một lệnh, bạn có thể mất một bước trung gian, biên soạn file nguồn vào các tập tin đối tượng nhị phân:

gcc -Wall -c primary/main.cc -o primary/main.o 
gcc -Wall -c other/foo.cc -o other/foo.o 
gcc -Wall -c other/bar.cc -o other/bar.o 

này sẽ sản xuất alpha/main.o, beta/foo.obeta/bar.o. Trình biên dịch sẽ không phàn nàn về foobar thiếu chức năng main(), bởi vì tệp đối tượng không cần. Sau đó liên kết các đối tượng với nhau thành một file thực thi:

gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp 

Bước 3: Thực hiện nó tại địa phương (Đừng cố này cho đến khi bạn có thể nhận được các bước trước để làm việc một cách hoàn hảo.)

Cũng giống như bước trước, nhưng chúng ta hành động trong primary/other/:

cd primary 
gcc -Wall -c main.cc -o main.o 
cd ../other 
gcc -Wall -c foo.cc -o foo.o 
gcc -Wall -c bar.cc -o bar.o 
cd .. 
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp 

bước 4: Sử dụng một Makefile (Đừng cố gắng điều này cho đến khi bạn có thể thực hiện bước trước đó để làm việc một cách hoàn hảo.)

Chúng tôi có thể có một makefile thực hiện BƯỚC 1, nhưng điều đó không thực sự cần thiết. Viết một makefile trong primary (tức làprimary/makefile) như thế này:.

main.o: 
    gcc -Wall -c main.cc -o main.o 

(Đó là khoảng trắng trong fromt của gcc... là một TAB)

Bây giờ thử điều này:

cd primary 
make 
cd ../other 
gcc -Wall -c foo.cc -o foo.o 
gcc -Wall -c bar.cc -o bar.o 
cd .. 
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp 

Bước 5: Sử dụng Một số Makefiles (Do not cố gắng này cho đến khi bạn có thể thực hiện bước trước đó để hoạt động hoàn hảo.)

Viết other/makefile:

both: foo.o bar.o 

foo.o: 
    gcc -Wall -c foo.cc -o foo.o 

bar.o: 
    gcc -Wall -c bar.cc -o bar.o 

và một makefile trong thư mục hàng đầu, nơi bạn đang xây dựng myApp:

myApp: 
    gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp 

Bây giờ thử điều này:

cd primary 
make 
cd ../other 
make 
cd .. 
make 

Bước 6: Sử dụng Một Makefile Đó Calls Khác (Đừng cố gắng cho đến khi bạn có thể thực hiện bước trước đó để hoạt động một cách hoàn hảo.)

Chỉnh sửa makefile top:

myApp: 
    cd primary; make 
    cd other; make 
    gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp 

Bây giờ thử:

make 

Nếu tất cả các công trình này, những gì bạn có là một hệ thống makefile thô nhưng hiệu quả . Có rất nhiều sàng lọc có thể, khi bạn đã sẵn sàng để lấy bánh xe đào tạo ra.

EDIT:

Nếu có nhiều file nguồn trong thư mục con (ví dụ other/) và bạn không muốn duy trì một danh sách trong makefile đầu bằng tay, có một số cách để xử lý nó. Đây là một:

OTHER_SOURCES := $(wildcard other/*.cc) 

OTHER_OBJECTS := $(OTHER_SOURCES:.cc=.o) 

myApp: 
    cd primary; make 
    cd other; make 
    gcc -Wall primary/main.o $(OTHER_OBJECTS) -o myApp 

Nhưng bạn nên làm cho các makefiles này hoạt động và hiểu chúng, trước khi bạn cố gắng tinh giản hơn.

+0

Cảm ơn bạn đã hướng dẫn tuyệt vời! Điều gì sẽ xảy ra nếu nếu tôi có một số lượng tệp khổng lồ trên mỗi thư mục mô-đun? Nó có thể nhận được sau đó thực sự gây phiền nhiễu để viết dòng cuối cùng của bước thứ 6. Có cách giải quyết nào không? Giống như việc hợp nhất tất cả các tệp .o thành một thư mục trên mỗi thư mục hoặc nói trong makefile để nhận tất cả các tệp .o từ một thư mục nhất định? – yauser

+0

Bạn cũng có thể sử dụng '-C' để tạo (bên trong makefile) để thay đổi thư mục và đọc makefile trong thư mục đó. – Aif

+0

@Aif: Có, tôi sử dụng '-C', nhưng tôi đã cố giữ những thứ nguyên thủy. Như tôi đã nói, nhiều cải tiến là có thể. (Và tôi đã nghe rằng '-C' không thực sự tuân thủ POSIX ...) – Beta

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