如果有自己編譯過AOSP的源碼牺勾,可能大家都會遇到這樣的一個問題:
ninja: error: '*******', needed by '*********', missing and no known rule to make it
在剛剛開始接觸AOSP的時候正罢,我基本上都會直奔主題,大概清楚問題后禽最,然后解決問題腺怯、重新編譯,所以一直都沒有注意到一個關(guān)鍵字:"Ninja"川无,今天我們就一起來學習/實踐一下這個"熟悉的陌生人"呛占,主要介紹一下目前Android的編譯系統(tǒng),以及以一個小Demo為例懦趋,實踐一下Ninja的使用晾虑,如果想了解更多關(guān)于Ninja在AOSP中的使用,見參考鏈接。
一帜篇、Android編譯系統(tǒng)
早期的Android系統(tǒng)采用Android.mk的配置來編譯源碼糙捺,從Android 7.0開始引入Android.bp粤剧。大體梳理一下Android版本相應的發(fā)展演變過程:
- Android 7.0引入ninja和kati
- Android 8.0使用Android.bp來替換Android.mk谤逼,引入Soong
- Android 9.0強制使用Android.bp
上圖就是各個文件之間的轉(zhuǎn)化關(guān)系网棍,這里涉及到Ninja, kati, Soong, bp概念篷扩,簡單介紹一下:
1. Ninja
ninja是一個編譯框架,會根據(jù)相應的ninja格式的配置文件進行編譯潮孽,但是ninja文件一般不會手動修改喻粹,而是通過將Android.bp文件轉(zhuǎn)換成ninja格文件來編譯帜慢。
2. Android.bp
Android.bp的出現(xiàn)就是為了替換Android.mk文件坏快。bp跟mk文件不同铅檩,它是純粹的配置,沒有分支莽鸿、循環(huán)等流程控制昧旨,不能做算數(shù)邏輯運算。如果需要控制邏輯祥得,那么只能通過Go語言編寫兔沃。
3. Soong
Soong類似于之前的Makefile編譯系統(tǒng)的核心,負責提供Android.bp語義解析级及,并將之轉(zhuǎn)換成Ninja文件粘拾。Soong還會編譯生成一個androidmk命令,用于將Android.mk文件轉(zhuǎn)換為Android.bp文件创千,不過這個轉(zhuǎn)換功能僅限于沒有分支、循環(huán)等流程控制的Android.mk才有效入偷。
4. Blueprint
Blueprint是生成追驴、解析Android.bp的工具,是Soong的一部分疏之。Soong負責Android編譯而設計的工具殿雪,而Blueprint只是解析文件格式,Soong解析內(nèi)容的具體含義锋爪。Blueprint和Soong都是由Golang寫的項目丙曙,從Android 7.0,prebuilts/go/目錄下新增Golang所需的運行環(huán)境其骄,在編譯時使用亏镰。
5. Kati
kati是專為Android開發(fā)的一個基于Golang和C++的工具,主要功能是把Android中的Android.mk文件轉(zhuǎn)換成Ninja文件拯爽。代碼路徑是build/kati/索抓,編譯后的產(chǎn)物是ckati。
二、Ninja的介紹
從上面我們可以看到逼肯,Android最后的編譯工作都會交給Ninja耸黑,那么它到底是個什么東西呢,為什么Google需要在Android引入Ninja呢篮幢?
Ninja is a small build system with a focus on speed. It differs from other build systems in two major respects: it is designed to have its input files generated by a higher-level build system, and it is designed to run builds as fast as possible.
Ninja是一個專注于速度的構(gòu)建系統(tǒng)大刊,和其他構(gòu)建系統(tǒng)相比,主要有兩點不同:
- Ninja的輸入文件一般都是有更高級的構(gòu)建系統(tǒng)產(chǎn)生的三椿,比如cmake缺菌;
- Ninja設計之初就是為了更快的構(gòu)建;
其實從第一點赋续,我們就能看出來Ninja的設計哲學:相比Makefile是設計出來給人手寫的男翰,但是Ninja設計出來是給其它程序生成的。 如果說Makefile是C語言纽乱,那么Ninja就是匯編語言蛾绎。 如果說Makefile是一個DSL,那么Ninja就是一種配置文件鸦列。 Makefile支持分支租冠、循環(huán)等流程控制,而Ninja只支持一些固定形式的配置薯嗤。
三顽爹、Ninja的實踐
工欲善其事,必先利其器骆姐,所以我們需要先準備好相關(guān)工具:CMake镜粤,ninja,以Mac OS為例玻褪,安裝步驟為:
brew install cmake
brew install ninja
正式開始肉渴,以一個最簡單的Hello,Ninja為例:
- main.cpp
#include <iostream>
int main() {
std::cout << "Hello, Ninja!" << std::endl;
return 0;
}
- CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(ninja)
set(CMAKE_CXX_STANDARD 14)
add_executable(ninja main.cpp)
OK带射,一個簡單的Hello同规,Ninja的C++工程已經(jīng)完成,接下來我們開始編譯窟社,使用如下命令券勺,生成build.ninja
文件:
[min@bogon:] ninja $ cmake -G Ninja -B build .
-- The C compiler identification is AppleClang 9.1.0.9020039
-- The CXX compiler identification is AppleClang 9.1.0.9020039
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/min/Desktop/workspace/c/ninja/build
可以看到在build
目錄下,生成了如下文件:
[min@bogon:] build $ tree -L 2
.
├── CMakeCache.txt
├── CMakeFiles
│ ├── 3.15.5
│ ├── CMakeOutput.log
│ ├── CMakeTmp
│ ├── TargetDirectories.txt
│ ├── cmake.check_cache
│ └── ninja.dir
├── build.ninja
├── cmake_install.cmake
└── rules.ninja
其中最重要的就是這個build.ninja
文件灿里,接下來关炼,我們使用Ninja命令,開始編譯:
[min@bogon:] ninja $ cd build/
[min@bogon:] build $ ninja
[2/2] Linking CXX executable ninja
[min@bogon:] build $ ./ninja
Hello, Ninja!
至此匣吊,一個簡單的Hello, Ninja!就已經(jīng)實踐完成了盗扒,具體關(guān)于AOSP中Ninja的編譯跪楞,希望大家可以自己去摸索一下~