CMake+Ninja 使ってるヤツは直ちに CMake-3.9 に乗り換えろ
タイトルだけで完結しました。 CMake 愛に関しては冥界一を自負し、かつ Ninja-build 大好きな中村です。
以下、私が llvm-dev に投稿したポエムの翻訳ではありません。
http://lists.llvm.org/pipermail/llvm-dev/2017-July/115646.html
Other Changes -- CMake-3.9 Release Notes
The Ninja generator has loosened the dependencies of object compilation. Object compilation now depends only on custom targets and custom commands associated with libraries on which the object’s target depends and no longer depends on the libraries themselves. Source files in dependent targets may now compile without waiting for their targets’ dependencies to link.
add_library(foo.c)
, add_executable(foo.c)
などにおいて、foo.c
のコンパイルが target_link_libraries(foo ...)
のライブラリに依存しなくなります。つまりなにもしていないのに並列度が向上します。具体的な例を、先日投稿した記事(CMake: target_link_libraries(PUBLIC/PRIVATE/INTERFACE) の実践的な解説)のSHARED
の例を使って説明しましょう。
add_library(lib1 SHARED lib1.c)
add_library(lib2 SHARED lib2.c)
target_link_libraries(lib2 PRIVATE lib1)
add_library(lib3 SHARED lib3.c)
target_link_libraries(lib3 PRIVATE lib2)
add_executable(foo foo.c)
# キーワードは省略可もしくはPRIVATE/PUBLIC
# foo は lib1 にも依存しているのでここで明示
target_link_libraries(foo lib1 lib3)
CMake < 3.9 においては、この例におけるすべてのアクションが直列に実行されます。64コアプロセッサを使ってるデベロッパには到底許されることではありません。
Order | アクション |
---|---|
1 | lib1.o: lib1.c |
2 | lib1.dll: lib1.o |
3 | lib2.o: lib2.c |
4 | lib2.dll: lib2.o lib1.dll |
5 | lib3.o: lib3.c |
6 | lib3.dll: lib3.o lib2.dll |
7 | foo.o: foo.c |
8 | foo.exe: foo.o lib1.dll lib3.dll |
CMake-3.9+Ninja では以下のように並列化されます。DAGを図示した方がいいのですがよだきい(方言)のでご容赦ください。
ポイントは、*.o: *.c
が並列化されているところです。もちろん先日の記事にてINTERFACE
を利用している場合には *.a: *.o
も並列化されます(DLL どうしはシンボル解決の必要があるため依存関係を崩せない)。
Order | アクション | |||
---|---|---|---|---|
1 | lib1.o: lib1.c | lib2.o: lib2.c | lib3.o: lib3.c | foo.o: foo.c |
2 | lib1.dll: lib1.o | |||
3 | lib2.dll: lib2.o lib1.dll | |||
4 | lib3.dll: lib3.o lib2.dll | |||
5 | foo.exe: foo.o lib1.dll lib3.dll |
※実際には foo.exe は lib2.dll に依存していないので直接の依存関係はありません。
なお、既存のルールにおける互換性として、add_custom_command()
, add_custom_target()
, add_dependencies()
により追加された依存は先送りされず add_library(lib1.c)
の lib1.o: lib1.c
に依存するようになります。つまりヘッダファイル生成などのカスタムルールが無視されたりすることはありません。逆にいうと add_executable(foo.c)
の foo.o: foo.c
は、もし依存ライブラリが add_dependencies()
を持っていた場合、それに依存することになります。
以上、CMake-3.9 における劇的な改良点のひとつを紹介しました。個人的には dirty hack が実装されたようにしか見えないんですけどね…
先日の投稿(CMake: target_link_libraries(PUBLIC/PRIVATE/INTERFACE) の実践的な解説) のノウハウを骨抜きにしてしまいかねない改良ですが、あくまでも本記事の内容は -GNinja でのみ有効です。CMake を使わされているみなさんは諦めてキレイな CMakeLists.txt を書きましょう。
CMake そのものが汚いけどな!!! (俺が言いたかったのはこれだけ)
Author And Source
この問題について(CMake+Ninja 使ってるヤツは直ちに CMake-3.9 に乗り換えろ), 我々は、より多くの情報をここで見つけました https://qiita.com/chapuni/items/abfe155b6e67be0e6730著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .