Ответ 1
похоже, что это не проблема cmake, а только сделать.
Я пытаюсь настроить параллельную сборку на основе CMake для моего исходного дерева, но когда я выдаю
$ cmake .
$ make -j2
Я получаю предупреждение jobserver unavailable: using -j1. Add '+' to parent make rule
. Есть ли у кого-нибудь идея, можно ли как-то это исправить?
похоже, что это не проблема cmake, а только сделать.
В сгенерированном Makefile при вызове в суб-make ему нужно либо использовать $(MAKE) (а не просто "make" ), либо предшествует строке с+. То есть правило должно выглядеть так:
mysubdir:
$(MAKE) -C mysubdir
или вот так:
mysubdir:
+make -C mysubdir
Если вы не сделаете это одним из двух способов, make даст вам это предупреждение.
Я ничего не знаю о cmake, так что, возможно, он генерирует Makefiles, что неверно. Или, может быть, вы сделали что-то неправильно с вашей стороны.
В моем случае (с CMake 3.5.2) тривиальный cd build && cmake .. && make -j5
работает просто отлично.
Но я получаю сообщение о недоступности сервера jobserver при создании пользовательских целей (как зависимостей других целей) с помощью cmake --build . --target foo
idiom.
Вот так:
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 будет регенерировать make файлы, если это необходимо, запустите компиляцию, install
все точно так же, как с make install
, а затем запустите мои собственные скрипты, чтобы упаковать заполненный buildroot в любую форму или форму, в которых я нуждаюсь.
Конечно, мне бы хотелось make -j15 deb
- но это не удалось.
Теперь, когда объяснил в списке рассылки разработчиками CMake, основная причина заключается в том, что она неожиданно (или нет) внутри GNU Make; есть обходное решение.
Основная причина в том, что 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
отключается среда jobserver, что в конечном итоге вызывает однопоточную компиляцию.
Обходной путь , который отлично работал у меня, как указано в связанном письме, - это префикс всех пользовательских команд с +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
в соответствующем make файле (CMake генерирует кучу из них) и заставляет GNU Make правильно вести себя и уважать -j
.
Надеюсь, что это поможет.
Просто от googling, похоже, вы используете distcc (например, здесь)