Почему изменения в исходном коде не всегда отражаются в машинном коде после сборки во время перестройки? - PullRequest
9 голосов
/ 29 марта 2011

Иногда, когда я изменяю код в своем проекте Qt (Qt Creator 2.1.0 с mingw32), изменения не отражаются в созданном машинном коде после его сборки.Это происходит главным образом, когда я меняю такие вещи, как значения по умолчанию в конструкторах или порядок параметров в методах / конструкторах.Обычно полная перестройка исправляет это (но занимает несколько минут).

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

Я пришел из java / .net и привык к другому поведению.Я был бы счастлив, если бы кто-нибудь мог объяснить мне, что я делаю неправильно и / или указать мне на некоторые связанные статьи.

Спасибо!

Ответы [ 4 ]

15 голосов
/ 29 марта 2011

Обычно после изменения заголовка все исходные файлы, включая этот заголовок, должны быть перестроены. Однако qmake немного необычен в этом отношении, вам нужно установить DEPENDPATH для включаемых папок, отличных от текущего каталога. Например, если у вас есть

INCLUDEPATH += somepath_in_my_project

также добавьте

DEPENDPATH += some_path_in_my_project

Только с DEPENDPATH файлы, созданные с помощью файлов .pro, перестраиваются, если изменяется какой-либо заголовок в some_path_in_my_project (если они включают этот заголовок)!

Я предлагаю добавить для каждой строки INCLUDEPATH одинаковую строку DEPENDPATH, если вы не включите какой-либо системный каталог, который вы не ожидаете изменить.

Edit:

Аналогичная проблема существует при статическом соединении с qmake: если статический lib foo.a изменяется, двоичные файлы, ссылающиеся на него, не перекомпоновываются. Это ошибка в QMake, не генерирующая правильных зависимостей.

Обходной путь, который я нашел в предыдущем проекте:

static:unix:TARGETDEPS += path_to_my/somestaticlib.a
static:win32:TARGETDEPS += path_to_my/somestaticlib.lib

Редактировать редактировать:

С некоторого времени (Qt 5?) Приведенный выше код должен использовать POST_TARGETDEPS вместо TARGETDEPS.

3 голосов
/ 29 марта 2011

Если вы перечисляете все соответствующие заголовочные файлы в файле проекта, этого не должно произойти.Но на самом деле это происходит постоянно, потому что QMAKE глючит (у него были проблемы с генерацией зависимостей, которые не фиксировались годами).Так что лучше почистите его и перекомпилируйте или используйте Cmake.А также QMAKE ничего не знает (и почти ничего не обнаруживает) о зависимостях между исходными файлами и заголовочными файлами, и это может привести к таким проблемам.

3 голосов
/ 29 марта 2011

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

Анализируйте зависимости и исправляйте их.

Пример:

// what you write                  // what the compiler generates
void foo( int i = 0 ) {}           void foo( int i ) {} // default removed
int main() {                       int main() {
   foo();                             foo( 0 );         // compiler injected
}                                  }
0 голосов
/ 29 марта 2011

Если в вашем Makefile (или вашем моральном эквиваленте Makefile) отсутствует информация о зависимостях, вы можете получить несинхронизированные сборки. Для каждого файла с #include "header.h" необходимо убедиться, что Makefile ставит header.h в качестве зависимости от этого файла.

Вот маленький кусочек Makefile, который у меня есть:

parser_yacc.c parser_yacc.h: parser_yacc.y parser.h
        $(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y

parser_lex.c: parser_lex.l parser_yacc.h parser.h
        $(LEX) ${LEXFLAGS} -o$@ $<

parser_lex.o: parser_lex.c parser.h parser_yacc.h
        $(CC) $(EXTRA_CFLAGS) -c -o $@ $<

parser_misc.o: parser_misc.c parser.h parser_yacc.h af_names.h cap_names.h
        $(CC) $(EXTRA_CFLAGS) -c -o $@ $<

Каждый объектный файл явно зависит от соответствующих исходных и заголовочных файлов. Если бы мы забыли cap_names.h, то parser_misc.o не будет перестроен при изменении cap_names.h. Ошибки могут возникнуть.

Боюсь, это длинное и утомительное исправление: проверить каждый файл, составить список его зависимостей и добавить недостающие зависимости в Makefile. На платформе Linux вы можете использовать инструмент strace(1), чтобы узнать, какие файлы нужно открывать компилятору при компиляции каждого исходного файла, и улучшить зависимости с этим списком. Я не знаю, существует ли какой-либо подобный инструмент в Windows, но стоило бы потратить несколько минут на его поиск, прежде чем погрузиться в него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...