2012-10-17 14 views
8

Chcę zbudować aplikację i mam wiele modułów przechowywanych w wielu katalogach. Postanowiłem podążać za pomysłem this, tj. Mieć plik Makefile w każdym katalogu, a następnie scalić go. Ale - jako początkujący programista - nadal nie wiem, jak to zrobić. Po pierwsze, jak by wyglądały takie "częściowe" pliki makefile. Nie mogą pełnić głównej funkcji, ponieważ może być tylko jeden na binarny, ale gdy próbuję go skompilować, gcc narzeka na niezdefiniowane odniesienie do głównej. Po drugie, nie mam pojęcia, jak wyglądałyby te wszystkie moduły.Pliki Makefile w wielu katalogach

Byłbym wdzięczny za każdą pomoc, ale staraj się, aby twoje odpowiedzi były proste. Pliki Makefile są dla mnie wciąż czarną magią.

+0

Możliwy duplikat [Makefile z plikami źródłowymi w różnych katalogach] (http://stackoverflow.com/questions/1139271/makefiles-with-source-files-in-different-directories) –

Odpowiedz

25

Zanim będziesz mógł zrobić cokolwiek z plikiem makefile, musisz wiedzieć, jak to zrobić bez pliku Makefile.

Ponieważ używasz gcc, zakładam, że Twój kod źródłowy to C++.

Nie powiedziałeś nam, jak wygląda twoja struktura katalogów, więc przypuszczam, że masz trzy pliki źródłowe w dwóch katalogach: primary/main.cc, other/foo.cc i other/bar.cc. (Możemy zajmować się plikami nagłówkowymi, takimi jak foo.h później.) A chcesz zbudować myApp.

KROK 1: Robi to ręcznie

Aby to zrobić w jednym poleceniu można użyć:

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

Będzie to kompilacja trzech plików źródłowych i połączyć obiekty binarne razem do plik wykonywalny myApp.

KROK 2: Doing It In Pieces (. Nie próbuj tego momentu można dostać poprzedni krok, aby idealnie współpracować)

Zamiast budować za pomocą jednego polecenia, można podjąć etap pośredni, kompilowania pliki źródłowe do binarnych plików obiektowych:

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 

To będzie produkują alpha/main.o, beta/foo.o i beta/bar.o. Kompilator nie będzie narzekał na foo i bar bez funkcji main(), ponieważ plik obiektowy nie potrzebuje. Następnie połączyć obiekty razem do pliku wykonywalnego:

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

KROK 3: Robi lokalnie (nie próbuj tego momentu można dostać poprzedni krok, aby idealnie współpracować.)

Tak jak poprzedni krok, ale działają w primary/ i 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 

kROK 4: Korzystanie z Makefile ( Nie próbuj tego, dopóki nie uzyskasz poprzedniego kroku do perfekcji).

Możemy mieć makefile wykonać KROK 1, ale to naprawdę nie jest konieczne. Napisz plik Makefile w primary (tj.primary/makefile) tak:.

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

(To spacje w fromt gcc... jest TAB)

Teraz spróbuj tego:

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 

KROK 5: Korzystanie z wielu Makefile (NIE próbuj tego, dopóki nie uzyskasz poprzedniego kroku do perfekcyjnego działania.)

Napisz 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 

i makefile w głównym katalogu, gdzie budujemy myApp:

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

Teraz spróbuj tego:

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

Krok 6: Korzystanie z One Makefile, który wywołuje Inne (Nie należy podejmować prób, dopóki nie będzie można uzyskać poprzedniego kroku do perfekcyjnego działania.)

Edit top makefile:

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

Teraz spróbuj:

make 

Jeśli wszystko działa, co masz jest surowy ale skuteczny system makefile. Istnieje wiele udoskonaleń, kiedy jesteś gotowy, aby zdjąć koła treningowe.

EDIT:

Jeśli istnieje wiele plików źródłowych w podkatalogu (np other/) i nie chcesz, aby utrzymać listę w górę makefile przez strony, istnieje kilka sposobów, aby sobie z tym poradzić. To jest jedno:

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 

Ale powinieneś dostać te pliki Makefile i zrozumieć je, zanim spróbujesz jeszcze bardziej usprawnić.

+0

Dzięki za świetny tutorial! A jeśli mam naprawdę dużą liczbę plików w katalogu modułów? Może to być naprawdę denerwujące, gdy napiszesz ostatnią linię szóstego kroku. Czy istnieje obejście tego problemu? Podobnie jak łączenie wszystkich plików .o w jeden na katalog lub mówienie w pliku makefile, aby uzyskać wszystkie pliki .o z danego katalogu? – yauser

+0

Możesz również użyć '-C' do utworzenia (wewnątrz pliku makefile) zmiany katalogu i odczytu makefile w tym katalogu. – Aif

+0

@Aif: Tak, używam '-C', ale starałem się zachować prymitywność. Jak już powiedziałem, wiele udoskonaleń jest możliwych. (I słyszałem, że "-C" w rzeczywistości nie jest zgodne z POSIX ...) – Beta

Powiązane problemy