Finally, I successfully compiled AOSP in WSL (Windows Subsystem for Linux) 終於讓WSL成功運作AOSP
多年以來,要開發Android裝置,基本上你只能使用Linux環境來完成這個工作。過去,我基於 OS X 下的 Vagrent 來編譯 AOSP,但是效能與效果非常地不理想。最終,我只好放棄這開發方式。老實的安裝了一套Linux來做做為開發平台。使用 Ubuntu 來開發 AOSP 說真的非常的方便,但是這跟我常用的Windows 與 macOS 開發平台產生了很大的不方便。
Microsoft Love Linux
大概誰也沒想到Windows會在2016年迎來一個重大的改變,WSL (Windows Subsystem for Linux)。這很不 Microsoft。Windows 中竟然開始支援 Linux Subsystem。這個改變時在嚇壞了大家,也完全顛覆了人們對於Microsoft的刻板印象。 至於甚麼 Linux Subsystem 呢?簡單的說,他不是VirtualMachine,還是採用一種Fusion的方式,把多個不同的Subsystems連結到 Windows 的 Kernel 之中。 換言之,就是這個方式實現了 ABI 的相容。一個 Linux 程式可以不經過編譯,便能在 Windows上執行。不同於VirtualMachine (比方 HyperV 與 VirtualBox) 採用虛擬化的技術讓不同的OS在 HOST 與 GUEST 中切換運行,ABI 可以算是一個更輕量與快速的方式,讓Linux 程式運行在 Windows上。
echo “hello!!!” > /mnt/c/temp/log.txt
安裝 WSL 與 Ubuntu
請參考Microsoft關於如何安裝WSL與Ubuntun的方式
首先你一定得有套Windows 10。之後,選擇一個適合的Ubuntun版本。這邊我推薦 16.04,原因我們之後再說。但是我自己則是花了不少時間才在18.04成功編譯出 AOSP 的。所以以下的內容都是基於 18.04開發過程所寫成的。
再來我們要講述如何建立環境與編譯AOSP。所以我們假設你已經了解如何在一般的傳統的 Linux 編譯 AOSP Android Project。我們就不贅述這些基礎知識。
WSL 的限制與不同
在講述這一切之前,我們先理解 WSL 在編譯環境中與真實的 Linux 有甚麼不同,有哪些限制。
- 只能只行64位元的程式。也就是常見的 ELF32 是不能夠在 WSL 上執行的。
- WSL 下,能夠用行 Win32 EXE 程式。但是注意,對執行的Windows程式來說,本質上還是運行於 Windows 上的程式,所有的檔案結構依然是Windows 那套。也就是說,/mnt/c/ 這樣的檔案名稱是無法被這樣的Windows 程式存取的。(這點很重要,也成為我們解套AOSP編譯的一個重要契機)
- WSL 預設是用 lxfs 檔案系統來當成 rootfs。而且這個檔案系統是分大小寫的。
- 你可以存取 NTFS,但是 NTFS 預設是不分大小寫。但請注意 AOSP 只能在區分大小寫的檔案系統上編譯。所幸,在新版的 Windows 10 中,NTFS 已經能夠開啟大小寫區分了。我們可以動態的開啟這些功能。
- WSL 藉由 DrvFs 來存取Windows 的檔案系統。
C:\ on /mnt/c type drvfs (rw,noatime,uid=1000,gid=1000,metadata,case=off) - 接續 5. 你的外接裝置比方 USB DISK,並不會自動的加入 WSL 的系統。最簡單的方式就是重新啟動 WSL。
wsl — shutdown or wsl -t Ubuntu or Restart-Service LxssManager - WSL的安裝位置。預設來說安裝於:這個位置是能夠被改變的,只是相對來說有些難處。
%userprofile%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc - Symbolic Link 的問題:
如果你在 rootfs 上建立 symbolic link,這點跟一般 Linux 下沒甚麼不同。但是如果你在 DrvFs 下的 NTFS 編譯 AOSP,那麼你記住你的檔案系統是與 Windows 共用的。 Windows 下有兩種連結方式,"SYMBOLIC" 與 "JUNCTION" 其中 "S" 類的需要有較高的權限才能使用。另外,我測試的結果是想對目錄時,SYMLINK 是可以的,但是 /mnt/xxx 這類是完全無法在 Windows上正常工作的。
開始編譯AOSP
工作目錄設定:
由於我的 C:\ 容量並不大,而且我想要增加 Winodws 與 WSL 共用性,所以我選擇了 D:\aosp 作為我的工作目錄。以 WSL 來說就是 /mnt/d/aosp。
設定目錄為大小寫:
如同前面所述的,NTFS預設來說並不分大小寫。請開啟cmd,並執行:
fsutil.exe file setCaseSensitiveInfo D:\aosp enable
下載你的AOSP或是你自己的Android Project到這個目錄中:
repo init …
repo sync …
下載開發工具:
sudo apt update && sudo apt full-upgrade -y && sudo apt install -y bc build-essential ccache curl g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5-dev libsdl1.2-dev libssl-dev libwxgtk3.0-dev libxml2 libxml2-utils lzop m4 openjdk-8-jdk pngcrush repo rsync schedtool squashfs-tools xsltproc zip zlib1g-dev
sudo apt-get install libxml-simple-perl && sudo apt-get install python-pip && pip install pycrypto && sudo apt-get install ccache && sudo apt-get install bison
安裝adb: (Android Debug Bridge)
由於 adb 是採用 client & server 的方式運作。為了不用碰觸 usb 支援的問題,我們將在windows 上運行 adb server,這樣一來無論在哪個 WSL 用行 adb client 就都沒有問題了。還有一點必須注意,你必須安裝相同版本的adb才能正常工作。為了保持相同版本我們採用個別安裝:(當然你可以用你自己SDK或是Anndroid Studio的版本)
mkdir ~/android && cd ~/androidwget https://dl.google.com/android/repository/platform-tools-latest-linux.zip && unzip platform-tools-latest-linux.zipecho “alias adb=’~/android/platform-tools/adb’” >> ~/.bash_aliases
echo “alias fastboot=’~/android/platform-tools/fastboot’” >> ~/.bash_aliases
source ~/.bash_aliases
Windows的版本請自行下載:
https://dl.google.com/android/repository/platform-tools-latest-windows.zip
安裝舊版OpenSSL:
如果你用的是16.04那麼你應該不需要這個安裝。因為這個版本的Ubuntu自帶的OpenSSL並不會有甚麼問題。如果你用的是18.04那麼你可能會遇上版本太新的問題。
mkdir ~/openssl && cd ~/opensslwget https://www.openssl.org/source/old/1.0.1/openssl-1.0.1u.tar.gz
tar -zxvf openssl-1.0.1u.tar.gzcd openssl-1.0.1usudo ./config && sudo make && sudo make install# (backup current openssl tool)
sudo cp `which openssl` `which openssl`_new# (create link to the new openssl)
sudo ln -sf /usr/local/ssl/bin/openssl `which openssl`
克服各種ELF32不相容問題:
我們前面說過,WSL 是不能運行 ELF32 程式的。但是 AOSP 中,有許多prebuilts 是採用 32 bits 的方式。我們必須要這些工具置換成64 bits 版本。
Bison
aosp_android_9.0.0/source/prebuilts/misc/linux-x86/bison/bison ==> /aosp_9/prebuilts/build-tools/linux-x86/bin
Using soft-link bison -> ../../../../../aosp_9/prebuilts/build-tools/linux-x86/bin/bison
ln -s ../../../../../aosp_9/prebuilts/build-tools/linux-x86/bin/bison bisonError: prebuilts/misc/linux-x86/bison/bison: prebuilts/build-tools/common/bison/m4sugar/m4sugar.m4: cannot open: No such file or directorycp ../aosp_9/prebuilts/build-tools/common/ ./prebuilts/build-tools/ -rfOrmake bison
export BISON_EXEC=$ANDROID_BUILD_TOP/out/host/linux-x86/bin/bisonijar’s problem
wsl: https://github.com/Microsoft/WSL/issues/3157possible patch: https://review.lineageos.org/c/LineageOS/android_build/+/208102/5/tools/ijar/zip.cccd build/make/tools/ijara18c1d9.diff
a18c1d9.diff
git apply a18c1d9.diffmake ijar
export IJAR_EXEC=$ANDROID_BUILD_TOP/out/host/linux-x86/bin/ijarOrreplace prebuilts/build-tools/linux-x86/bin/ijar with $ANDROID_BUILD_TOP/out/host/linux-x86/bin/ijarmv ijar ijar_back && cp -f $ANDROID_BUILD_TOP/out/host/linux-x86/bin/ijar .Ormake ijar
export IJAR_EXEC=$ANDROID_BUILD_TOP/out/host/linux-x86/bin/ijar
以上是我的置換過程。實際情況還得根據自己遇上的問題。
關於那些預先安裝沒有代碼的執行檔案:
用Win32 EXE替換ELF32:
如我們先前提到,你無法使用執行 ELF32。很多都是因為這個問題造成 AOSP 無法在 WSL 中編譯的。雖然 ELF32 不能被執行,但是 Win32 的 EXE 卻是能直接被WSL執行的。這點也成了我們克服這個問題的重要契機。
舉例來說,我遇上的Qualcomm Sign Tool 的問題:
Qualcomm’s image sign tool bin is 32bits. We must use 64bits.Fortunately, WSL could run win32 .exe directly. We use WIN version to replace LIN.qcom/proprietary/common/scripts/SecImage/bin/LIN
mv crypto_ccm crypto_ccm_32bit_not_work
cp ../WIN/crypto_ccm.exe ./crypto_ccm
cp ../WIN/openssl.* .Although, we can run .exe from WSL direcrtly. The file input and path are not accessible from .exe. 🙁Using mklink junction to connect wsl/ubuntu/tmp with root tmpmklink /j tmp %userprofile%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\tmp
我們用 Win32 EXE 替換了 ELF32,然後再利用mklink 來做符號連結,把NTFS 檔案連到 WSL 的Linux 檔案系統之中。如此一來就能直接在WSL中使用,並且路徑都是正確的。
增快執行效能:
由於 WSL 是採用 ABI 相容的方式執行 ELF64 的程式,在 Windows 子系統中再轉譯這些指令到 Kernel 代碼,所以他的運行上是有一定的耗能。同樣的機器下,絕對是比原生Linux更慢。另外,磁碟效能也是一個問題。WSL 模擬了Linux VFS 然後提供各種對應的 File System。建議,在編譯 AOSP 的期間,可以嘗試把防毒軟體關閉,這樣可以增進檔案系統的效能。
結論:
經過一番努力終於讓 AOSP 能夠在 WSL 上成功的編譯。相對於 HyperV 或是 Virtual Box 上安裝 Linux 的方式,效能與方便性是高上許多。你可以透夠Visual Studio Code 與 Visual Studio 2017/2019 直接編譯,然後也可以透過WSL 介面或 透過 CLI 直接把命令下到 AOSP上。這點可說十分方便。
最後,WSL 上編譯 AOSP 整個難度還是太過困難。我們期待 WSL2 的到來讓一切問題都能被一次性解決!
延伸閱讀:
Windows Subsystem for Linux Overview
Windows Subsystem for Linux (WSL) 原理介紹
LineageOS Android Distribution