cmake и параллельное построение с "make -jN" - PullRequest
15 голосов
/ 31 мая 2010

Я пытаюсь настроить параллельную сборку на основе CMake для моего дерева исходных текстов, но когда я выдаю

$ cmake .
$ make -j2

Я получаю:

jobserver unavailable: using -j1.  Add '+' to parent make rule

как предупреждение. У кого-нибудь есть идея, можно ли как-то это исправить?

Ответы [ 4 ]

23 голосов
/ 21 ноября 2010

В сгенерированном Makefile при обращении к подмейку необходимо либо использовать $ (MAKE) (а не просто make), либо предшествовать строке с + То есть правило должно выглядеть так:

mysubdir:
    $(MAKE) -C mysubdir

или как это:

mysubdir:
    +make -C mysubdir

Если вы не сделаете это одним из этих двух способов, make выдаст вам это предупреждение.

Я ничего не знаю о cmake, так что, возможно, он генерирует файлы Makefile, которые не верны. Или, возможно, вы сделали что-то неправильно на вашем конце.

7 голосов
/ 21 декабря 2016

В моем случае (с CMake 3.5.2) тривиальный cd build && cmake .. && make -j5 работает просто отлично.

Но я получаю ошибку jobserver недоступен при создании пользовательских целей (как зависимостей от других целей) с помощью идиомы 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 при необходимости восстановит 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 отбрасывает среду сервера заданий, в конечном итоге вызывая однопоточную компиляцию.


Обходной путь , который отлично сработал для меня, как указано в сообщении, связанном с электронной почтой, заключается в добавлении к префиксам всех пользовательских команд +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.

Надеюсь, это поможет.

0 голосов
/ 20 августа 2010

похоже, что это не проблема cmake, а только make.

0 голосов
/ 02 июня 2010

Похоже, вы используете distcc (например, здесь )

.
...