LINUX.ORG.RU

Почему не перекомпилируются изменения, внесенные в *.h - файл?

 , ,


0

2

Вот есть у меня в проекте файлы main.cpp и main.h. В main.cpp прописан инклюд файла main.h.

В файле main.h есть определение:

#define RELEASE_VERSION   72

Я меняю значение этого определения на 73, и запускаю сборку. В результате генерируется бинарник, в котором в разделе «Версия программы» видна версия 72 а не 73. А чтобы версия в бинарнике поменялась, надо запустить полную пересборку проекта!

Я залез в Makefile, там для цели main.o есть зависимость src/main.h:

build/main.o: src/main.cpp src/main.h \
		src/views/mainWindow/MainWindow.h \
		src/models/appConfig/AppConfig.h

И при сборке видно, что цель main.o компилится:

14:31:59: Starting: "/usr/bin/make" 
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_WEBKIT -DANY_OS=1 -DMEEGO_OS=2 -DANDROID_OS=3 -DTARGET_OS=ANY_OS -DQT_SVG_LIB -DQT_XML_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtNetwork -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtXml -I/usr/include/qt4/QtSvg -I/usr/include/qt4 -Isrc -Ibuild -o build/main.o src/main.cpp

Но почему тогда конечный бинарник не содержит измененного номера версии?

★★★★★

Ответ на: комментарий от mix_mix

Этот Makeile генерирует qmake. Там черт ногу сломит, но примерно так:

TARGET        = bin/superproga
OBJECTS       = build/main.o \
		build/RecordTableScreen.o \
		build/RecordTableView.o ...
...

all: Makefile $(TARGET)

$(TARGET):  $(OBJECTS)  
	@$(CHK_DIR_EXISTS) bin/ || $(MKDIR) bin/ 
	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
	{ test -n "$(DESTDIR)" && DESTDIR="$(DESTDIR)" || DESTDIR=.; } && test $$(gdb --version | sed -e 's,[^0-9][^0-9]*\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $$DESTDIR" -ex quit '$(TARGET)' && test -f $(TARGET).gdb-index && objcopy --add-section '.gdb_index=$(TARGET).gdb-index' --set-section-flags '.gdb_index=readonly' '$(TARGET)' '$(TARGET)' && rm -f $(TARGET).gdb-index || true
Xintrea ★★★★★
() автор топика
Ответ на: комментарий от router

А ты твёрдо уверен, что окно «Версия программы» создаётся именно в main.cpp ?

Нет, оно создается в другом месте, в MainWindow.cpp. В нем есть инклюд main.h.

Разобраться в зависимостях целей в сгенерированном qmake файле не могу.

Возможно, что зависимости MainWindow.cpp от main.h просто нет?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Для MainWindow.o есть явная зависимость MainWindow.cpp и MainWindow.h.

build/MainWindow.o: src/views/mainWindow/MainWindow.cpp src/views/mainWindow/MainWindow.h
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o build/MainWindow.o src/views/mainWindow/MainWindow.cpp

Возможно есть и другие рекурсивные зависимости, но я не могу в голове распарсить весь сгенерированный qmake мейкфайл.

По логике вещей, если qmake генерит Makefile, то она должна генерить зависимости согласно инклюдам файлов проекта в *.cpp и *.h, иначе ерунда получится.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Неоднократно наталкивался на то, что сгенеренный через qmake Makefile очень странно реагирует на изменения исходников. На многие изменения реагирует, как и положено, но изменения некоторых cpp и h-файлов упорно не замечает. Немного помогает удаление бинарника - тогда при линковке вдруг замечает что исходники изменились, хотя только-что утверждал что бинарник самый последний и ничего делать не надо!

sigurd ★★★★★
()
Ответ на: комментарий от sigurd

А так не в mtime часом засада-то?

anonymous
()
Ответ на: комментарий от sigurd

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

d_a ★★★★★
()
Ответ на: комментарий от sigurd

Неоднократно наталкивался на то, что сгенеренный через qmake Makefile очень странно реагирует на изменения исходников.

Не так часто, но да, бывает. Время от времени приходится живительный ребилдол принимать.

hobbit ★★★★★
()
Ответ на: комментарий от sigurd

Неоднократно наталкивался на то, что сгенеренный через qmake Makefile очень странно реагирует на изменения исходников.

QMake никогда не позиционировался и уже не будет инкрементальной системой сборки общего назначения, его написали для сборки исключительно самого Qt и его примеров. Об этом писали сами разработчики давным давно. Меня больше поражает что признавая это они всё равно пихают его в тот же QtCreator как систему сборки по умолчанию, ни словом не заикаясь про отсутствие инкрементальности. Как результат если сборка случайно завалилась при изменении исходников или переключении веток в системе контроля версий, то вам ещё повезло. Хуже когда оно таки молча скомпилировалось и слинковалось в нерабочий бинарь. Кто ценит нервы и время давно переключились на CMake или, на худой конец, QBS.

Dendy ★★★★★
()
Ответ на: комментарий от kaffeine

Полная пересборка нужна не всегда. Если ты знаешь, какие .cpp используют твой измененнный хидер (у меня при таких проблемах обычно не более одного-двух), то просто удаляешь объектные файлы соответствующие этим .cpp и запускаешь сборку снова. Удаленные объектники пересобираются, линкуются и вуаля - в случае больших проектов сэкономлена туча времени :)

P.S. Вместо удаления объектников можно чуть-чуть поправить эти .cpp, например пробел добавить, и запустить сборку.

Burns
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.