Wie konfiguriere ich portable parallele Builds in CMake?
-
12-12-2019 - |
Frage
Ist es irgendwie möglich, einen parallelen Build durchzuführen, unabhängig davon, welches Build-Tool verwendet wird?
Unter Unix können wir hinzufügen make -jN
wobei N die Anzahl der Threads ist, und unter Windows habe ich zum hinzugefügt CXX_FLAG "/MP"
die dann in Visual Studio zum parallelen Erstellen verwendet wird ... (?) Wie kann ich meine Version so gestalten? CMAKE_MAKE_PROGRAM
wird nicht immer erweitert, wenn ich CMake ausführe?
Was ist eine allgemeine Lösung?
Ich habe mir Folgendes ausgedacht:
# 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()
Lösung
Mit CMake 3.12 ist dies möglich.Aus den Versionshinweisen:
Der "CMake (1)" -Build-Werkzeugmodus ("CMake-build") hat "-parallel [] und "-J [] -Optionen gewonnen, um eine parallele Build-Ebene anzugeben.Sie sind den entsprechenden Optionen des nativen Build-Tools zugeordnet.
Wie von dkg erwähnt, können Sie auch die Umgebungsvariable festlegen CMAKE_BUILD_PARALLEL_LEVEL
.
Links zur CMake-Dokumentation:
Andere Tipps
Wenn Sie CMake v2.8.8 oder höher haben, können Sie verwenden Ninja als Alternative zu GNU make
:
mkdir build
cd build
cmake -G Ninja ..
ninja # Parallel build (no need -j12)
oder
mkdir build
cd build
cmake -G Ninja ..
cmake --build . # Parallel build using Ninja
Wie Sie sehen, ist die Verwendung nicht erforderlich CMAKE_MAKE_PROGRAM
, wird der Build standardmäßig parallel ausgeführt, wodurch die Anzahl der Jobs abhängig von den verfügbaren CPU-Kernen optimiert wird.
Ninja basiert auf einer Low-Level-JSON-Konfiguration, um die Startphase zu beschleunigen.Daher ist die JSON-Konfiguration nicht einfach von Hand zu schreiben und ich erstelle sie immer mit einem High-Level-Tool/einer IDE:
- CMake v2.8.8 (2012)
- Qt Creator v2.6 (2012)
- KDevelop v4.6 (2013)
- Meson unter Linux (2013)
- ...Sehen Sie sich die Generatoren der Ninja-Konfiguration an https://github.com/ninja-build/ninja/wiki/List-of-generators-producing-ninja-build-files
Da ein C++-Build oft viel Speicher benötigt, muss Ihr Computer so viel Speicher bereitstellen, wie die Anzahl der CPU-Kerne.
Wie von hervorgehoben Ruslan, CMake 3.12 (2018) hat eine neue Option cmake --build -j <N>
um den Build zu beschränken <N>
Kerne (Jobs) und begrenzt so den Speicherverbrauch (siehe auch die Dokumentation).Wenn Sie eine ältere CMake-Version verwenden, können Sie diese weiterhin verwenden cmake --build -- -j <N>
.Die Option --
weist CMake an, den Rest direkt an das zugrunde liegende Builder-Tool zu übergeben, hier ist es Ninja.
Dies ist nicht plattformübergreifend möglich.Die Option -jN ist ein zu erstellender Parameter und nicht Teil des generierten Makefiles.Sie könnten jedoch CMake ein Bash-Skript generieren lassen, das make für Ihr Projekt mit -jN ausführt (wobei das Skript die Anzahl Ihrer Kerne ermittelt).
Ich habe mich dazu entschlossen, eine zu schreiben parallelmake.sh
Skript für Unix Makefiles
-basierte Generatoren.Dies geschieht hier: https://github.com/gabyx/ApproxMVBB
Und die relevanten Teile in der CMake-Datei:
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()
# ========================================================================================================================================