2015-02-10 2 views
1

При работе над проектом C++ я заметил, что внес изменения в один из файлов заголовков, связанных с моим основным кодом, но утилита make не регистрировала его. Мне пришлось заставить его компилировать по-разному, учитывая изменения, используя «make-B».Понимание зависимостей Makefile (C++)

Я хочу знать, почему это так; это из-за того, как написан мой make-файл, как мои файлы зависят друг от друга, и то, и другое?

Вот мой Makefile:

CXXFLAGS = -Wall -Werror -std=c++11 -pedantic -Wvla -g 
//CXXFLAGS = -std=c++11 

all: main.o game.o zombie.o 
     g++ $(FLAGS) game.o main.o zombie.o -o main $(CXXFLAGS) 

game: game.cpp 
     g++ $(FLAGS) -c game.cpp $(CXXFLAGS) 

zombie: zombie.cpp 
     g++ $(FLAGS) -c zombie.cpp $(CXXFLAGS) 

main: main.cpp 
     g++ $(FLAGS) -c main.cpp pairing_heap.h $(CXXFLAGS) 

Я сделал изменения в pairing_heap.h
который #included в моем главном файле.

Почему вы не заметили, что он должен скомпилироваться снова? Поскольку я чувствую, что это концептуальное недоразумение, я чувствовал, что нет необходимости включать изменения, которые я сделал, или разницу в выходе, когда я делал «make-B». Это были простые вещи, такие как cout's и cerr, включенные в новую парную_игру.h, которые не собирались до принудительного.

Сообщите мне, если мне нужно предоставить дополнительную информацию.

спасибо.

ответ

0

Make не знает ничего о каком-либо конкретном языке или инструменте программирования, поэтому он не понимает, что файлы C/C++ зависят от заголовков, а также от исходных файлов. У него есть только правила вида

target: dependencies 
     actions 

Все это известно из этого является то, что файл target зависит от файлов, перечисленных в dependencies, и если какой-либо из этих файлов новее, команды actions должны работать, чтобы обновить target. Это действительно так - все, что делает, происходит от этой простой идеи о целевых файлах, зависимостях и действиях.

Теперь - это. У него есть куча встроенных правил для обычных вещей, которые вы часто хотите делать, а также способы указания правил шаблона - правила, в которых цель содержит wildcard, поэтому их можно использовать для разных целей, которые зависят от других файлов с соответствующими именами.

Теперь в вашем случае, у вас есть правило:

all: main.o game.o zombie.o 
     g++ $(FLAGS) game.o main.o zombie.o -o main $(CXXFLAGS) 

, который говорит, что переделать файл all, если его старше файлы main.o, game.o или zombie.o он должен выполнить команду. Это первое правило в файле, поэтому оно создается по умолчанию при вводе make.

Теперь у вас, вероятно, нет файла с именем all (если бы вы сделали make, вероятно, ничего не сделали), но это нормально, как будто его нет, его явно не актуально, поэтому необходимо выполнить команду. Когда команда должна запускаться, она также проверяет любые зависимости, чтобы увидеть, имеют ли они в свою очередь зависимые от предыдущих (поэтому их необходимо перестроить). Поскольку все эти файлы заканчиваются на .o, они соответствуют встроенному правилу, который знает, как их создать из файла с тем же именем, за исключением того, что он заканчивается .cpp, поэтому он запускает эти действия, если (и только если) файл .cpp является новее ,

Теперь вы говорите: «Как насчет моих других правил - что они делают?«Ну, оказывается, они ничего не делают. Это правила для создания файлов с именами game, zombie и main, и поскольку вы никогда не просите их создавать, и от них ничего не зависит, они ничего не делают. удалите их.

Вы также спросите: «Как мне его перестроить, если файл заголовка изменится?» Ну, если вы добавите правило без каких-либо действий (только цель и зависимости), оно просто добавит эти зависимости к другому правилу (встроенный в данном случае), что делает есть действие Так что, если вы добавите строку:.

main.o: pairing_heap.h 

(без действия), make добавит эту зависимость к встроенному в правило, которые знают, как строить main.o из main.cpp и будет работать это правило (перекомпилировании main.cpp), если либоmain.cpp или pairing_hep.h новее, чем main.o - это именно то, что вы хотите.

+0

Спасибо, что объяснили общую картину, а затем погрузились в более тонкие детали. Очень педагогический; Я могу выкопать его. Я предвижу гораздо лучшие отношения между мной и make-файлами. –

1

Вы перечисляете pairing_heap.h в рецепте main, который не делает его зависимость от main (кроме того, вы не должны передавать заголовки компилятором как это), для этого вам нужно написать правило следующим образом:

main: main.cpp pairing_heap.h 
     g++ $(FLAGS) -c main.cpp $(CXXFLAGS) 

Есть целый ряд других вещей, которые неправильно в вашем файле, например, тот факт, что ваши цели не являются сами файлы (main: должны быть main.o: и т.д.), и вы не делаете использование автоматических переменных или шаблонов, но, вероятно, проще просто заменить все на следующие

CPPFLAGS := -MMD -MP 
CXXFLAGS := -Wall -Werror -std=c++11 -pedantic -Wvla -g 
SOURCES := $(wildcard *.cpp) 

main: $(SOURCES:.cpp=.o) 

-include $(SOURCES:.cpp=.d) 

, который использует сделать в implicit rules и ССЗ/поколение авто зависимость лязгом, чтобы сделать исполняемый файл под названием main.

Смежные вопросы