Подтвердить что ты не робот

Как настроить переносимые параллельные сборки в CMake?

Можно ли каким-то образом иметь возможность иметь параллельную сборку независимо от того, какой инструмент сборки используется?

В Unix мы можем добавить make -jN где N - количество потоков, а в Windows я добавил CXX_FLAG "/MP" который затем используется в Visual Studio для параллельной сборки... (?) Как я могу сделать мой версия такая, что CMAKE_MAKE_PROGRAM не всегда расширяется при запуске CMake?

Что такое общее решение?

Я придумал это:

# Add some multithreaded build support
MARK_AS_ADVANCED(MULTITHREADED_BUILD)
set(MULTITHREADED_BUILD 12 CACHE STRING "How many threads are used to build the project")
if(MULTITHREADED_BUILD)
    if(${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
            message(STATUS ${CMAKE_BUILD_TOOL})
            set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j${MULTITHREADED_BUILD}")
            message(STATUS "Added arguments to CMAKE_BUILD_TOOL: ${CMAKE_MAKE_PROGRAM}")
    elseif(MSVC)
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
      message(STATUS "Added parallel build arguments to CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
    endif()
endif()
4b9b3361

Ответ 1

С CMake 3.12 это возможно. Из примечаний к выпуску:

В параметре "cmake (1)" в инструменте сборки ("cmake –build") добавлены опции "- parallel []" и "-j []" для указания уровня параллельной сборки. Они сопоставляются с соответствующими параметрами родного инструмента сборки.

Как упоминалось в dkg, вы также можете установить переменную окружения CMAKE_BUILD_PARALLEL_LEVEL.

Ссылки на документацию CMake:

Ответ 2

Если у вас CMake v2.8.8 или выше, вы можете использовать ниндзя в качестве альтернативы GNU make:

mkdir build
cd    build
cmake -G Ninja ..
ninja              # Parallel build (no need -j12)

или

mkdir build
cd    build
cmake -G Ninja ..
cmake --build .    # Parallel build using Ninja

Как видите, не нужно использовать CMAKE_MAKE_PROGRAM, сборка по умолчанию выполняется параллельно, оптимизируя количество заданий в зависимости от доступных ядер ЦП.

Ninja основан на низкоуровневой конфигурации JSON для ускорения фазы запуска. Поэтому его конфигурацию JSON нелегко написать вручную, и я всегда генерирую его с помощью высокоуровневого инструмента /IDE:

Поскольку сборка C++ часто требует большого объема памяти, ваш компьютер должен предоставлять столько же памяти, сколько число ядер ЦП.

Как указал Руслан, CMake 3.12 (2018) имеет новую опцию cmake --build -j <N>, ограничивающую сборку до <N> ядер (заданий), таким образом, ограничивая потребление памяти (см. также документацию). Если вы используете более старую версию CMake, вы все равно можете использовать cmake --build -- -j <N>. Опция -- говорит CMake передавать остальное непосредственно основному инструменту компоновщика, здесь это Ninja.

Ответ 3

Вы не можете сделать это кроссплатформенным. Опция -jN - это параметр для создания, а не часть сгенерированного Makefile. Однако вы можете заставить CMake сгенерировать скрипт Bash, который запускает make для вашего проекта, используя -jN (где скрипт ищет количество ядер, которые у вас есть).

Ответ 4

Я остановился на написании сценария parallelmake.sh для генераторов Unix Makefiles -based. Это делается здесь: https://github.com/gabyx/ApproxMVBB

И соответствующие части в файле CMake:

https://github.com/gabyx/ApproxMVBB/blob/master/CMakeLists.txt#L89

# Add some multithreaded build support =====================================================================================================
MARK_AS_ADVANCED(MULTITHREADED_BUILD)
SET(MULTITHREADED_BUILD ON CACHE BOOL "Parallel build with as many threads as possible!")
if(MULTITHREADED_BUILD)
    if(${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
            file(COPY ${ApproxMVBB_ROOT_DIR}/cmake/parallelmake.sh DESTINATION ${PROJECT_BINARY_DIR}
                FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
                NO_SOURCE_PERMISSIONS
            )
            SET(CMAKE_MAKE_PROGRAM "${PROJECT_BINARY_DIR}/parallelmake.sh")
            MESSAGE(STATUS "Set make program to ${PROJECT_BINARY_DIR}/parallelmake.sh")
    elseif(MSVC)
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" "/MP")
      MESSAGE(STATUS "Added parallel build arguments to CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
    endif()
endif()
# ========================================================================================================================================