Как написать make-файл для цели, которая включает заголовочный файл? - PullRequest
2 голосов
/ 08 февраля 2020

У меня есть два файла "create-тренировка. cpp" и "exerc.hpp". Я хочу написать make-файл, чтобы использовать gnu ++ 17 и g ++ для их компиляции. Упражнение .hpp включено в создание-упражнение. cpp. Я только хочу получить бинарный файл из упражнения create. cpp. Я бы использовал команду g++ -std=gnu++17 create-exercise.cpp -o create-exercise, и она работает хорошо. Я попытался использовать следующее в файле make.

CXXFLAGS=-Wall -std=gnu++17

create-exercise: create-exercise.cpp exercise.hpp

, но сгенерировал следующее g++ -Wall -std=gnu++17 create-exercise.cpp exercise.hpp -o create-exercise Я не хочу, чтобы exercise.hpp был включен в команду компиляции. Вместо этого я также попытался использовать следующее:

CXXFLAGS=-Wall -std=gnu++17

create-exercise.o: create-exercise.cpp exercise.hpp

Это породило g++ -Wall -std=gnu++17 -c -o create-exercise.o create-exercise.cpp. Я не хочу флаг -c. потому что, когда я пытаюсь запустить create-exercise.o, это приводит к ошибке отказа в разрешении. Я также попробовал следующее:

CXXFLAGS=-Wall -std=gnu++17

create-exercise.o: create-exercise.cpp exercise.hpp
    $(CXX) $(CXXFLAGS) create-exercise.cpp -o create-exercise.o

, но когда я редактирую exercise.hpp, make говорит 'create-exercise.o' is up to date. и не перекомпилирует его. что мне делать?

Ответы [ 3 ]

2 голосов
/ 08 февраля 2020

Правило записи в вашем make-файле:

create-exercise.o: exercise.hpp

Это правило без рецепта, и оно просто добавляет еще одно условие (exercise.hpp) к цели create-exercise.o, т.е. всякий раз, когда exercise.hpp изменяется, create-exercise.o следует перестраивать.

Однако проблема при предоставлении этого правила заключается в том, что GNU Make предполагает, что create-exercise.o является объектным файлом, сгенерированным из исходного файла C при сборке. create-exercise. Следовательно, он не связывает библиотеку C ++, а библиотеку C, поэтому у вас есть симпатичная ошибка неопределенной ссылки на std::cout.

В GNU Make есть следующее неявное правило для генерации исполняемый файл из исходного файла C ++:

%: %.cpp
#  commands to execute (built-in):
   $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

Вы можете использовать рецепт этого правила для сборки create-exercise из creating-exercise.o и по-прежнему обрабатывать creating-exercise.o как объектный файл, созданный из исходного файла C ++:

create-exercise: create-exercise.o
    $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

Тогда весь файл makefile будет:

CXXFLAGS = -Wall -std=gnu++17 

create-exercise: create-exercise.o
    $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

create-exercise.o: exercise.hpp

Цель create-exercise также становится целью по умолчанию, поскольку это первое правило в файле makefile. Это цель для сборки, если вы не укажете make.

2 голосов
/ 09 февраля 2020

Вы можете сделать это:

CXXFLAGS = -Wall -std=gnu++17

create-exercise: create-exercise.o
        $(LINK.cpp) $^ $(LDLIBS) -o $@

create-exercise.o: exercise.hpp

Это говорит: build create-exercise из объектного файла create-exercise.o, если он изменился. И это говорит перестроить create-exercise.o, если файл заголовка exercise.hpp изменяется; неверно изменять или перестраивать исходный файл , если изменяется заголовок. Это объектный файл , который зависит от заголовка.

Make имеет ряд встроенных правил. Среди них есть правила, которые знают, как связать программу, но, к сожалению, предполагается, что ваши объектные файлы были созданы из файлов C, поэтому, если вы используете C ++, вам нужно создать специальный c рецепт. Но вы все равно можете использовать переменные по умолчанию для GNU make.

Он также знает, как создать файл .o из файла .cpp самостоятельно: вам не нужно писать этот рецепт.

0 голосов
/ 08 февраля 2020

Я не уверен, но, возможно, попробуйте включить файл .hpp вместо компиляции с другим файлом. Вы можете сделать это, используя g ++ *. cpp -I * .hpp -o output

Попробуйте и дайте мне знать, работает ли он для вас.

...