什麼是Ninja
Ninja是使用C++寫的開源項目。
http://martine.github.io/ninja/
在Unix/Linux下通常使用Makefile來控制代碼的編譯,但是Makefile對於比較大的項目有時候會比較慢,看看上面那副漫畫,代碼在編譯都變成了程序員放鬆的藉口了。所以這個Google的程序員在開發Chrome的時候因爲忍受不了Makefile的速度,自己重新開發出來一套新的控制編譯的工具叫作Ninja,Ninja相對於Makefile這套工具更注重於編譯速度。除了Chrome現在還有一些其他的比較大的項目也在開始使用Ninja,比如LLVM。我試用了一下感覺還是不錯,比如編譯Cmake時間大概是原來的1/4。Ninja試用C++實現,其支持的語法非常簡單,作者在這裏說明了爲了控制複雜度。
代碼如何編譯
其實對於C/C++和很多其他程序的編譯都是一個道理,就是把一些源代碼文件編譯成目標文件,或者有的目標文件再編譯到一個庫裏,然後再鏈接起來。所以Ninja的配置文件分爲兩個部分,rule和文件依賴關係。看個簡單的例子:
cc=gcc cflags= -g -c
rule cc command = $cc $cflags $in -o $out rule link command = $cc $in -o $out rule cleanup command = rm -rf *.exe *.o
build func.o : cc func.c
build main.o : cc main.c
build app.exe : link main.o func.o
build all: phony || app.exe
build clean: cleanup
非常易懂,編譯的可執行未見叫做app.exe, 其中有三條rule: cc, link, cleanup。看看這個官方的試用手冊,還有一些附加參數可以加在rule的下面,比如description用來在編譯的時候顯示出來。Ninja還有個比較好玩的功能就是Ninja -t graph all命令,這可以用來生成編譯時候的依賴關係,可以用dot來生成圖片等。Ninja的實現也可以大概推測到,根據用戶給的依賴關係圖,並行 地編譯各個文件。
配置文件CMakeLists.txt
使用Ninja的一個問題就是需要生成這個build.ninja文件,對於大型項目來說這樣一條一條地寫配置文件是不可能的。幸好我們可以使用Cmake來生成這個配置文件,Cmake對應的是automake這樣的東西。在Cmake的最新版本中已經支持參數Camke -G Ninja,Cmake會根據用戶給定的CMakeLists.txt來生成build.ninja文件。而CmakeLists文件相對來說要簡單一些,只要寫清楚編譯的可執行文件的名字,和其依賴的包含main函數的源文件。把我的迷宮小項目來舉個例子,在項目文件夾下寫配置文件CMakeLists.txt:
cmake_minimum_required(VERSION 2.8) project (Maze) add_library(maze A_star.cpp Algorithm.cpp DFS_L.cpp DFS_R.cpp DisjSets.cpp Maze.cpp) add_executable(Maze.exe main.cpp) target_link_libraries(Maze.exe maze)
add_library寫明瞭生成一個叫做maze.a的庫文件,然後和main.cpp編譯出來的main.o生成可執行文件,寫好CmakeList.txt後運行Cmake -G Ninja, 然後運行ninja all就能編譯這個工程。具體的Cmake語法參考這裏,對於不少項目來說Cmake已經足夠使用,只是我覺得Cmake還是稍微複雜了一點。