Из настройки CMake "make" использовать опцию "-j" по умолчанию

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

Для этого я установил переменную CMAKE_MAKE_PROGRAM для конкретной командной строки. Я использую ProcessorCount() функция, которая дает число процессоров для выполнения сборки параллельно.

Когда я делаю makeЯ не вижу никакого ускорения. Однако если я сделаю make -j Nтогда он строится определенно быстрее.

Не могли бы вы помочь мне в этом вопросе? (Я разрабатываю это на Linux.)

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

include(ProcessorCount)
ProcessorCount(N)
message("number of processors: "  ${N})
if(NOT N EQUAL 0)
  set(CTEST_BUILD_FLAGS -j${N})
  set(ctest_test_args ${ctest_test_args} PARALLEL_LEVEL ${N})
  set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j ${N}")      
endif()
message("cmake make program" ${CMAKE_MAKE_PROGRAM})

Большое спасибо.

6 ответов

Решение

Путем установки переменной CMAKE_MAKE_PROGRAM, которую вы хотите повлиять на процесс сборки. Но:

  1. Эта переменная влияет только на сборку через cmake --build не на родном инструменте (make) вызов:

    CMAKE_MAKE_PROGRAM переменная установлена ​​для использования кодом проекта. Значение также используется cmake(1) --build и ctest(1) --build-and-test инструменты для запуска собственного процесса сборки.

  2. Эта переменная должна быть CACHE. Он используется таким образом в генераторах, похожих на make:

    Эти генераторы хранят CMAKE_MAKE_PROGRAM в кеше CMake, чтобы пользователь мог его редактировать.

    То есть вам нужно установить эту переменную с

    set(CMAKE_MAKE_PROGRAM <program> CACHE PATH "Path to build tool" FORCE)
    
  3. Эта переменная должна ссылаться на сам исполняемый файл, а не на программу с аргументами:

    Значением может быть полный путь к исполняемому файлу или просто имя инструмента, если ожидается, что он будет в PATH.

    То есть значение "make -j 2" не может использоваться для этой переменной (разделение аргументов в виде списка

    set(CMAKE_MAKE_PROGRAM make -j 2 CACHE PATH "Path to build tool" FORCE)
    

    тоже не поможет).

Таким образом, вы можете переопределить поведение cmake --build вызов с установкой переменной CMAKE_MAKE_PROGRAM в скрипт, который вызывает make с параллельными опциями. Но вы не можете повлиять на поведение для прямого make звоните.

Если вы хотите ускорить сборку, вы можете запускать несколько процессов make параллельно, но не cmake. Чтобы выполнить каждую сборку с заранее определенным числом параллельных процессов, вы можете определить это в MAKEFLAGS.

Установите MAKEFLAGS в вашем скрипте окружения, например ~/.bashrc, как вы хотите:

export MAKEFLAGS=-j8

В Linux для MAKEFLAGS устанавливается следующее число CPU - 1: (оставьте один CPU свободным для других задач во время сборки) и полезно в средах с динамическими ресурсами, например VMware:

export MAKEFLAGS=-j$(($(grep -c ^processor /proc/cpuinfo) - 0))

Вы можете установить переменную env MAKEFLAGS с помощью этой команды

export MAKEFLAGS=-j$(nproc)

Можно ли использовать этот метод для вызова нескольких функций? как функция 1,2,3 параллельно, довольно последовательно, любые другие идеи приветствуются.

пример:

 if(FLAG1)
#some variables/options settings
    function1(${OPTIONS})
    function2(${OPTIONS})
    function3(${OPTIONS})
     ....
endif()

function(fucntion1)
#some variables/options parsing and passed to command.
      execute_process(COMMAND COMMAND1
                    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
                    RESULT_VARIABLE res
                    TIMEOUT 60)
endfunction()
function(fucntion2)
#some variables/options parsing and passed to command.
      execute_process(COMMAND COMMAND2
                    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
                    RESULT_VARIABLE res
                    TIMEOUT 60)
endfunction()

Мое решение - создать небольшой скрипт, который будет запускать make, включая все виды других функций, а не только количество процессоров.

Я называю свой сценарий mk и я делаю chmod 755 mk так что я могу запустить его с ./mkв корне моего проекта. У меня также есть несколько флагов, позволяющих запускать различные вещи с помощью простой командной строки. Например, когда я работаю над кодом и получаю много ошибок, мне нравится направлять вывод вless. Я могу сделать это с./mk -l без необходимости перепечатывать все тяжелые вещи Unix...

Как видите, у меня есть -j4 в нескольких местах, где это имеет смысл. Для-l вариант, я не хочу его, потому что в этом случае это в конечном итоге приведет к одновременной печати нескольких ошибок (я пробовал это раньше!)

#!/bin/sh -e
#
# Execute make

case "$1" in
"-l")
    make -C ../BUILD/Debug 2>&1 | less -R
    ;;

"-r")
    make -j4 -C ../BUILD/Release
    ;;

"-d")
    rm -rf ../BUILD/Debug/doc/lpp-doc-?.*.tar.gz \
           ../BUILD/Debug/doc/lpp-doc-?.*
    make -C ../BUILD/Debug
    ;;

"-t")
    make -C ../BUILD/Debug
    ../BUILD/Debug/src/lpp tests/suite/syntax-print.logo
    g++ -std=c++14 -I rt l.cpp rt/*.cpp
    ;;

*)
    make -j4 -C ../BUILD/Debug
    ;;

esac

# From the https://github.com/m2osw/lpp project

С CMake это не сработает, если, как упоминал Цыварев, вы не создадите свой собственный скрипт. Но я лично не считаю разумным вызывать make из вашего скрипта make. Кроме того, это может нарушить процесс сборки, который не ожидал этого странного сценария. Наконец, мой сценарий, как я уже упоминал, позволяет мне изменять параметры в зависимости от ситуации.

Я обычно использую псевдоним в Linux, чтобы установить значение cmake .. && make -j12. Или напишите оболочку, чтобы указать ход выполнения и очистки ...

      alias cm='cmake .. && make -j12'

Затем используйте cm сделать в одной команде.

Другие вопросы по тегам