Зависимости в Makefile не учтены должным образом

У меня есть некоторые ограниченные знания о make-файле GNU, которые в настоящий момент меня подвели.

У меня есть файл объявления класса: mdfTree.h, реализация класса mdfTree.cpp и файл mdfTree_x.cpp с основным, где я создаю объект класса mdfTree и вызываю его открытые функции, которые в свою очередь вызывают некоторый закрытый член переменные mdfTree.

Я собираю его с Makefile:

CXX=g++
CXXFLAGS=-g -Wall -W -Wconversion -Wshadow -Wcast-qual -Wwrite-strings $(shell root-config --cflags --gl\
ibs)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)

mdfTree_x: mdfTree_x.o
g++ $(LDFLAGS) -o mdfTree_x mdfTree_x.o $(LDLIBS)

mdfTree_x.o: mdfTree_x.cpp
g++ $(LDFLAGS) $(CXXFLAGS) -c mdfTree_x.cpp

mdfTree.cpp и mdfTree_x.cpp имеет #include mdfTree.h в этом. Нужно ли mdfTree_x.cpp #include mdfTree.cpp также?

Я думаю, что мой Makefile неправильный, потому что публичная функция из класса mdfTree не может видеть приватную переменную того же класса, когда я пытаюсь скомпилировать. Кроме того, когда я вставляю синтаксическую ошибку в mdfTree.h, компилятор не принимает ее. Как мне сказать Makefile, что mdfTree_x должен использовать / compile mdfTree.h / .cpp?

0

Решение

Вам нужно будет явно добавить все зависимости, в этом случае ваш исполняемый файл зависит от созданного mdfTree.o, а mdfTree.o и mdfTree_x.o зависят от mdfTree.h. Ваши зависимости должны быть как

mdfTree_x:mdfTree_x.o mdfTree.o
mdfTree.o:mdfTree.cpp mdfTree.h
mdfTree_x.o:mdfTree_x.cpp mdfTree.h

Некоторые компиляторы (например, GNU & intel) умеет автоматически перечислять зависимости заголовка в формате make. Например, этот make-файл будет восстанавливать исполняемый файл, когда любой из mdfTree_x.cpp, mdfTree.cpp или же mdfTree.h изменено:

# Compiler flags...
CPPFLAGS+=-MMD -MP
mdfTree_x:mdfTree_x.o mdfTree.o
-include mdfTree_x.d mdfTree.d

CPPFLAGS создаст файл .d с зависимостями заголовка при компиляции, строка -include попытается включить их в make-файл, если он присутствует (если их нет, исходный файл все равно будет перекомпилирован, поэтому дополнительные зависимости не нужны). не имеет значения). Содержимое файла .d будет примерно таким

mdfTree.o:mdfTree.h

Кроме того, вам не нужно явно писать make-правила в большинстве случаев — например, если у вас есть файл foo.o перечислены в качестве зависимостей правила GNU Make по умолчанию для запуска

$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o foo.o foo.cpp

(и аналогично для других языков). Аналогично, связывание происходит автоматически, если имя исполняемого файла совпадает с одним из объектных файлов, например,

foo:foo.o

будет работать (обратите внимание, что CC не CXX)

$(CC) $(LDFLAGS) -o foo foo.o $(LDLIBS)

Использование правил по умолчанию упрощает make-файлы, а также позволяет использовать переменные окружения для настройки компилятора по умолчанию.

1

Другие решения

Нет, вам нужно настроить файл make для компиляции и связать mdfTree.cpp.

Что-то вроде этого

mdfTree.o: mdfTree.cpp
g++ $(LDFLAGS) $(CXXFLAGS) -c mdfTree.cpp

и измените шаг ссылки на

mdfTree_x: mdfTree_x.o mdfTree.o
g++ $(LDFLAGS) -o mdfTree_x mdfTree_x.o mdfTree.o $(LDLIBS)
2

У меня есть файл объявления класса: mdfTree.h, реализация класса mdfTree.cpp и файл mdfTree_x.cpp с основным, где я создаю объект класса mdfTree и вызываю его открытые функции, которые в свою очередь вызывают некоторый закрытый член переменные mdfTree.

Ваша программа нуждается в возможностях, определенных как в mdfTree.cpp, так и в mdfTree_x.cpp. Поэтому вам нужно скомпилировать оба этих файла, а ваша ссылка должна включать как mdfTree.o, так и mdfTree_x.o.

Вы можете написать два правила: одно для компиляции mdfTree.cpp, другое для компиляции mdfTree_x.cpp. Это быстро выйдет из-под контроля. Будь злым. Одно правило, чтобы построить их всех, одно правило, чтобы найти их, одно правило, чтобы привести их всех и в темноте связать их.

objects = mdfTree_x.o mdfTree.o
$(objects): %.o: %.cpp
g++ $(CXXFLAGS) -c $<

Обратите внимание, что нет $(LDFLAGS) в приведенном выше правиле компиляции. Вы не должны указывать параметры ссылок при компиляции.

Вам необходимо связать объекты, чтобы сформировать исполняемый файл:

mdfTree_x: $(objects)
g++ $(LDFLAGS) -o $@ $^ $(LDLIBS)

Обратите внимание, что теперь вам нужно указать параметры компоновщика; Вы связываете.

Один последний пункт перед следующим шагом: порядок, в котором вы указываете правила в make-файле в общем, не имеет значения. Однако есть одно исключение. Самое первое правило — это правило по умолчанию, которое будет использоваться, если вы вообще не указали цель в make команда. Это хорошая идея, чтобы явно поместить правило по умолчанию в самый верх make-файла. Например, поместите следующее где-то в верхней части вашего make-файла, следуя любым другим правилам:

default: mdfTree_x

В mdfTree.cpp и mdfTree_x.cpp есть #include mdfTree.h. Нужно ли mincTree_x.cpp #include mdfTree.cpp?

Никогда #include исходный файл. Никогда. Пусть линкер сделает это.

Однако здесь чего-то не хватает. Предположим, вы изменили mdfTree.h. Вам нужно восстановить. Makefile пока не будет этого делать. Чего не хватает, так это зависимости от mdfTree.h. В этом случае есть простое решение этой проблемы зависимости: просто укажите зависимость.

$(objects): mdfTree.h

В общем, эта проблема зависимости заголовка является очень сложной проблемой. Лучше не помещать эти зависимости заголовочного файла в make-файл. Пусть какой-то автоматизированный инструмент, такой как makedepend выяснить эти зависимости для вас.

1
По вопросам рекламы [email protected]