Из настройки 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})
Большое спасибо.
Ответы
Ответ 1
Устанавливая переменную CMAKE_MAKE_PROGRAM, вы хотите повлиять на процесс сборки. Но:
-
Эта переменная влияет только на сборку через cmake --build
, а не на собственный вызов инструмента (make
):
Переменная CMAKE_MAKE_PROGRAM
установлена для использования кодом проекта. Это значение также используется инструментами cmake (1) --build
и ctest (1) --build-and-test
для запуска собственного процесса сборки.
-
Эта переменная должна быть CACHEd. Он используется таким образом в генераторах, похожих на make:
Эти генераторы хранят CMAKE_MAKE_PROGRAM в кеше CMake, чтобы пользователь мог его редактировать.
То есть вам нужно установить эту переменную с
set(CMAKE_MAKE_PROGRAM <program> CACHE PATH "Path to build tool" FORCE)
-
Эта переменная должна ссылаться на сам исполняемый файл, а не на программу с аргументами:
Значение может быть полным путем к исполняемому файлу или просто именем инструмента, если ожидается, что он будет в 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
вызовов.
Ответ 2
Если вы хотите ускорить сборку, вы можете запускать несколько процессов make параллельно, но не cmake. Чтобы выполнить каждую сборку с заранее определенным числом параллельных процессов, вы можете определить это в MAKEFLAGS.
Установите MAKEFLAGS в вашем скрипте окружения, например ~/.bashrc, как вы хотите:
export MAKEFLAGS=-j8
В Linux для MAKEFLAGS устанавливается следующее число CPU-1: (оставьте один CPU свободным для других задач во время сборки) и полезно в средах с динамическими ресурсами, например VMware:
export MAKEFLAGS=-j$(($(grep -c ^processor /proc/cpuinfo) - 0))
Ответ 3
Вы можете установить переменную MAKEFLAGS env с помощью этой команды
export MAKEFLAGS=-j$(nproc)
Ответ 4
Можно ли использовать этот метод для вызова нескольких функций? подобная функция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()
Ответ 5
Мое решение состоит в том, чтобы иметь небольшой скрипт, который будет выполнять make, включающий в себя все виды других функций, а не только количество процессоров.
Я называю свой скрипт mk
и выполняю ./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. Плюс это может нарушить процесс сборки, который не будет ожидать этого странного скрипта. Наконец, мой сценарий, как я уже упоминал, позволяет мне изменять параметры в зависимости от ситуации.