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

    Параллельная компиляция 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 и забыть про настройку будущих проектов.

    Спасибо всем за дополнения.
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 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!

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