1 февраля 2012 в 19:52

Параллельная компиляция Qt в Windows

Qt*
Параллельная компиляция Qt-проектов под Windows с использованием QtCreator — зверь загадочный и очень привередливый. В этой небольшой статье я расскажу, как же все-таки его приручить. Параллельная компиляция может быть выполнена достаточно просто в теории, на практике дела обстоят не совсем гладко, чему в подтверждение бесконечное число тем на форумах, где предлагаются всевозможные решения. Ни одно из них, к сожалению, нам не помогло.


В теории для случая MinGW достаточно указать параметр –j[число процессов компиляции] у команды сборки make, которая в QtSDK MinGW представлена mingw32-make. Например, получается команда mingw32-make.exe –j10.

Рекомендуемое число процессов компиляции составляет число процессоров+1. Если параметр не задается, то считается, что j=1. Если указать слишком большое число также ничего страшного не случится. Make запустит ровно столько, сколько дает прирост производительности.

Для удобства можно воспользоваться переменной окружения %NUMBER_OF_PROCESSORS%, которая показывает число процессоров в системе. Получается команда вида

mingw32-make.exe –j%NUMBER_OF_PROCESSORS%

Однако, не все так просто. Qmake создает три make-файла. Общий Makefile, который по определенным define’ам выбирает из Makefile.Debug и Makefile.Release в зависимости от сборки релиза или дебага. Дело в том, что параметр –j не наследуемый. И когда в QtCreator вызывается make, то он вызывается для Makefile. А вот до Makefile.Debug или Makefile.Release уже не добирается.

Для того чтобы это исправить придется написать команду в явном виде. Например,

mingw32-make.exe –j9 –f Makefile.Debug.

Не очень удобно, но прирост скорости сборки это сильно компенсирует. Для примера, пересборка нашего проекта на core-i7-2630 без распараллеливания осуществляется за 12 минут, с флагом –j9 сборка занимает менее двух минут. Прирост производительности в шесть раз заставляет задуматься.

Но даже после указания таких флагов сборки у нас на двух машинах это стало работать, а на двух нет. На форумах пишут, что дело может быть в версии Qt, в кривости mingw, в особенностях работы qmake, версии ОС. Однако, конфигурации наших машин таковы, что методом исключения можно сделать вывод о непричастности версий QtSDK, QtCreator, Windows или разрядности системы ко всему этому.

Решение оказывается очень простым, но в тоже время не таким очевидным. Нужно добавить абcолютный путь к mingw32-make в переменную окружения PATH. На всякий случай, лучше поставить точку с запятой после пути. И после этого чудесным образом начинает работать параллельная компиляция, а программистам не придется по 10 минут отвлекаться каждый раз при добавлении какого-нибудь Q_OBJECT к проекту и его пересборке.

Все эти флаги компиляции могут быть заданы в QtCreator на вкладке Проекты в параметрах make.

image

Надеюсь, статья окажется полезным и решит вопросы многих у кого до этого не работала параллельная сборка в QtCreator.

UPD (из комментариев): Что касается Linux/MacOS пользователей, им повезло гораздо больше — достаточно только ключа -jX.

Также если вы используете компилятор MSVC, то проблем быть не должно.

В случае QtCreator нужно добавить запись
QMAKE_CXXFLAGS_RELEASE += -MP[число процессов]
в .pro файл проекта и установление переменной окружения как я описал.

В случае Visual Studio свойствах VS проекта: «Properties»=>«Configuration Properties»=>«C/C++»=>«Command Line». А в поле «Additional options» дописать -MP[число процессов]. Спасибо IGHOR

Также при использовании компилятора MSVC помочь может jom.

Постоянную часть флагов можно вынести в отдельную переменную окружения MAKEFLAGS. Make сам возьмет оттуда установленные флаги. К примеру MAKEFLAGS=-j10. А в параметрах make остается только не забыть указать файл для сборки. Например, -f Makefile.Debug. Если вы все время собираете одну версию, то можно вынести все флаги целиков в MAKEFLAGS и забыть про настройку будущих проектов.

Спасибо всем за дополнения.
Александр Грицай @AllGrit
карма
23,0
рейтинг 0,0
Похожие публикации
Самое читаемое Разработка

Комментарии (20)

  • +3
    Ну а если использовать компилятор от Microsoft, то поможет утилита jom.
    • 0
      Или добавление QMAKE_CXXFLAGS_RELEASE += -MP[число процессов] в .pro файл проекта и установление переменной окружения как я описал.
      • 0
        Или в свойствах VS проекта:
        «Properties»=>«Configuration Properties»=>«C/C++»=>«Command Line»
        И в поле «Additional options» дописать -MP[число процессов].
  • +1
    Вообще, у меня почему то при компиляции с помощью mingw отладочной версии и запуска из QtCreator-а — постоянно падает gdb. Никто не знает, чего не так?
    • 0
      У меня то же самое, на виртуалке в которой поставил все с нуля на чистую операционку работает хорошо. Путем разборок нашел что не работает на машине python, ошибка странная разобраться в чем дело не получилось.
  • +3
    Автор, спасибо большое за совет! Время действительно уменьшается в шесть раз на Core i7, только что проверил в своем проекте. Не сразу разобрался, что писать во вкладке Projects, если у кого-то подобная проблема, этот скриншот поможет.

  • +1
    Остаётся только добавить, что в Linux/MacOS достаточно только ключа -jX.
  • 0
    При установке QT SDK для MSVC параллельная компиляция работает из коробки.
    • +1
      а я вот при компиляции под MSVC использую jom. И в последующих сборках проекта тоже. Весьма помогает
  • +1
    А make берет из консоли опцию MAKEOPTS? Если берёт, то просто задать эту переменную глобально и всё.
    • +2
      Make берет MAKEFLAGS, можно задать ее как переменную окружения равную -j10, например.
      • 0
        Так проще один раз в переменные среды залезть и выставить этот флаг!
        • 0
          Все равно придется менять флаг -f Makefile.Debug на -f Makefile.Release
  • 0
    не совсем понял фразу
    «по 10 минут отвлекаться каждый раз при добавлении какого-нибудь Q_OBJECT к проекту и его пересборке. » при добавлении к проекту нового класса пересобираются только исходники этого класса и те файлы куда его заинклюдили. Если при этом пересобирается весь проект целиком-тут ошибка конфигурации и надо ее исправить…

    тоже неплохое ускорение компиляции достигается при использовании утилит типа ccache, она и для винды есть, только надо отключить precompile headers, а на линуксе-distcc, что запускает распределенную компиляцию…
    • 0
      Чтобы перегенерировались moc-файлы, которые создаются при наличии Q_OBJECT-макроса необходимо произвести полную пересборку. Досборка не помогает. В случае QtCreator.
      • 0
        Пересборку не обязательно — главное выполнить qmake, а после него — make. Тогда заработает.
        • 0
          Это стандартные этапы сборки для команды Собрать. После нее, к сожалению, не работает, если добавить Q_OBJECT. Приходится выбирать пересобрать. Речь идет о QtCreator.
          • +1
            Так и я с ним работаю. Обычно он по команде «Собрать» вызывает только make, если ты не трогал .pro или настройки проекта. Поэтому перед сборкой иногда приходится жать qmake. Я даже его на хоткей Ctrl+Q повесил.
            • 0
              Спасибо, попробуем.
      • 0
        use cmake, Luke!

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