Cmake и параллельное здание с "Make -jn"
-
05-10-2019 - |
Вопрос
Я пытаюсь настроить параллельную сборку на основе Cmake для моего исходного дерева, но когда я выпускаю
$ cmake .
$ make -j2
Я получил:
jobserver unavailable: using -j1. Add '+' to parent make rule
как предупреждение. У кого-нибудь есть идея, если можно каким-то образом можно исправить?
Решение
Похоже, это не проблема Cmake, но только делает.
Другие советы
В сгенерированном makefile при вызове в поддесячественную его необходимо либо использовать $ (make) (не просто 'make'), либо не предшествую строке с A +. То есть правило должно выглядеть так:
mysubdir:
$(MAKE) -C mysubdir
Или, как это:
mysubdir:
+make -C mysubdir
Если вы не сделаете это одним из этих двух способов, сделать вам это предупреждение.
Я ничего не знаю о Cmake, поэтому, возможно, это генерирует Makefiles, которые не являются правильными. Или, может быть, вы сделали что-то неправильно на вашем конце.
В моем случае (с Cmake 3.5.2) тривиально cd build && cmake .. && make -j5
работает просто хорошо.
Но я получаю Расповедка не допущена Ошибка при создании пользовательских целей (как зависимости других целей) через cmake --build . --target foo
идиома.
Так:
add_custom_target(buildroot
COMMAND ${CMAKE_COMMAND} --build . --target install
COMMENT "Populating buildroot..."
)
add_dependencies(deb buildroot)
add_dependencies(rpm buildroot) #... etc
- так что пользователь может make deb
И это просто работает. Cmake восстановит Makefiles, если это необходимо, запустите компиляцию, install
все именно так, как с make install
, а затем запустите свои пользовательские сценарии, чтобы упаковать заполненную сборку в любой форме или форме, которую мне нужно.
Конечно, я бы хотел make -j15 deb
- Но это терпит неудачу.
Теперь, как объяснил На списке рассылки CMake Devs, корневая причина лежит, удивительно (или нет), внутри GNU; Есть обходной путь.
Основная причина в том, что make
не пройдет свою среду для детей в детских процессах, которые он не думает, что нет make
.
Чтобы проиллюстрировать, вот дерево процесса (ps -A f
) ветвь:
…
\_ bash
\_ make -j15 deb
\_ make -f CMakeFiles/Makefile2 deb
\_ make -f CMakeFiles/buildroot.dir/build.make CMakeFiles/buildroot.dir/build
\_ /usr/bin/cmake --build . --target install ⦿
\_ /usr/bin/gmake install
…
В ⦿ точке, make
Откатывает среду Portiferver, в конечном итоге, вызывающей однопоточную компиляцию.
То обходной путь Что отлично подходит для меня, как отдано в связанном электронном письме, является префикс всех пользовательских команд с +env
. Отказ Так:
add_custom_target(buildroot
#-- this ↓↓↓ here -- https://stackoverflow.com/a/41268443/531179
COMMAND +env ${CMAKE_COMMAND} --build . --target install
COMMENT "Populating buildroot..."
)
add_dependencies(deb buildroot)
add_dependencies(rpm buildroot) #... etc
В конце концов, это появляется в правиле для buildroot
В соответствующем Makefile (CMake генерирует их кучу), а заставляет GNU заставить себя вести себя должным образом и уважать -j
.
Надеюсь это поможет.
Только от Googleing, похоже, вы используете distcc (например, здесь)