О правильном отслеживании зависимостей в qmake

27.06.2014

Вы когда-нибудь сталкивались с неприятным ощущением того, что при пересборке проекта у вас что-то не собралось либо не перекомпоновалось? Если вы пользуетесь qmake для сборки, то, скорее всего, сталкивались.

Секрет в недостаточном отслеживании зависимостей. Скажем, для для одного нашего проекта сейчас используется переменная SUBDIRS c добавлением в конфиг модификатора ordered. Это, конечно, приводит к пересборке той или иной статической библиотеки при изменении исходного текста этой библиотеки. Но поскольку приложения сейчас везде неправильно используют переменную PRE_TARGETDEPS, то перелинковки самих приложений со свеженькой библиотекой не происходит.

Итак, в переменной PRE_TARGETDEPS должен указываться полный путь к библиотеке, при изменении которой должна производиться перекомпоновка приложения. Тут возникает проблема, что для разных платформ путь к библиотеке и её название разные. Её надо будет решить. Скажем, так:

win32 {
    CONFIG(debug, debug | release) {
        LIBDIR = debug
    } else {
        LIBDIR = release
    }
}

win32 {
    LIBSUFFIX = .lib
} else {
    LIBPREFIX = lib
    LIBSUFFIX = .a
}

PRE_TARGETDEPS += \
    $$OUT_PWD/../../libs/core/src/$${LIBDIR}/$${LIBPREFIX}common$${LIBSUFFIX}\
    $$OUT_PWD/../../libs/core/src/$${LIBDIR}/$${LIBPREFIX}commoncpp$${LIBSUFFIX}\
    $$OUT_PWD/../../libs/core/src/$${LIBDIR}/$${LIBPREFIX}corelib$${LIBSUFFIX}\
    $$OUT_PWD/../../libs/core/src/$${LIBDIR}/$${LIBPREFIX}corelibcpp$${LIBSUFFIX}

Для ленивых можно предложить такую автоматизацию: deps.pri:

win32 {
    LIBSUFFIX = .lib
} else {
    LIBPREFIX = lib
    LIBSUFFIX = .a
}

win32 {
    CONFIG(debug, debug | release) {
        LIBDIR = debug
    } else {
        LIBDIR = release
    }
}

!isEmpty(LIBRARIES) {
    for(libpath, LIBRARIES) {
        out_libpath = $${OUT_PWD}/$${libpath}
        inc_libpath = $${_PRO_FILE_PWD_}/$${libpath}
        libbase = $$basename(libpath)
        INCLUDEPATH += $${inc_libpath}
        LIBS += -L$$out_libpath/$${LIBDIR}
        LIBS += -l$$libbase
        PRE_TARGETDEPS+=$${out_libpath}/$${LIBDIR}/$${LIBPREFIX}$${libbase}$${LIBSUFFIX}
    }
}

А в pro. файле приложения пишем так:

LIBRARIES += ../rbcommon
LIBRARIES += ../plugins/styxcore
LIBRARIES += ../plugins/animationeditor
LIBRARIES += ../plugins/imageeditor
LIBRARIES += ../plugins/mixballs
#track dependencies
include(../../../deps.pri)

В этом случае автоматически наполняются переменные LIBS, INCLUDEPATH и PRE_TARGETDEPS.

Недостаток этого метода в том, что он требует называть цели сборки (styxcore.lib) и соответствующие папки исходников (styxcore) одинаковыми именами. Поэтому, скажем, на настоящий момент он не подойдёт для mixballsresources.lib, т.к. папка исходников называется просто resources.

Последние записи блога

Напишите нам

Хотите разработать приложение? Требуется логотип или сайт?

Мы открыты для сотрудничества! Вы можете отправить нам сообщение прямо сейчас.

+7

Обновить