AOSP build on ARM for ARM 4일차


어제까지 일단 nsjail의 빌드는 성공해두었고, kati와 ninja 도 다행히 apt install로 ARM64용 설치 바이너리는 얻을 수 있는 상태라 잘만 섞으면 기본 빌드 환경을 구성할 수 있을 것 같아, lunch 실행시 초반 문제로 나오는 device정보들을 못 긁어와서 lunch에 메뉴로 못 보여주는 부분부터 들어가 봅니다.

lunch 실행시, 결국 build/make/envsetup.sh의 함수를 호출하게 되는데, 빌드인 함수인 get_build_var를 호출하여, device폴더들을 스캔해서 찾아둔 이름들로 메뉴들을 구성해서 보여줍니다. 현재로는 nsjail, kati등의 fail로 제대로 실행이 안되는 것으로 보이므로, 이 부분을 해결하고 넘어가겠습니다.

AOSPonARM:/mnt/bsp/build$ get_build_var COMMON_LUNCH_CHOICES
02:59:11 Build sandboxing disabled due to nsjail error.
02:59:12 Failed to run dumpvars: fork/exec prebuilts/build-tools/linux-x86/bin/ckati: exec format error

./soong/ui/build/sandbox_linux.go:130: c.ctx.Println(“Build sandboxing disabled due to nsjail error.”)

내용을 보니 nsjailPath를 위 go 파일에서 고정으로 지정하고 있는것이 보입니다. go라서 조금 달라질 수 는 있겠지만, bash와 마찬가지로 uname -m으로 구분해서 각각의 x86, arm64를 지정할 수 있을 것 같긴하지만, 급한대로 우선 바꾸고 실행해봅니다. nsjail은 어제 빌드해두었던 파일을 깔끔하게 linux-arm64/bin에 복사해두고 진행합니다. 결과는 동일하게 fail하네요. Sandboxing에 뭔가 옵션등등도 필요한 모양입니다. golang의 Verboseln을 이용하여 메세지를 더 찍고 있는 것으로 보이니 이것을 활성화해서 좀더 보자면 초반부 실행 부분은 build/blueprint/microfactroy/microfactory.go 로 대부분 해결하는 듯 합니다. golang은 1일차때 arm용을 받아서 환경을 변경해 주었으니, 문제 없을 것으로 생각하고 go파일 파고 들어가봅니다. 근데 특별한게 없네요 ^^;;; 다시 돌아가서,

build/soong/soong_ui.bash에서 microfactory로 설정 잡은 뒤로 넘어가봅니다.
결국 마지막 부분에서 빌드한 soong_ui를 실행하는 것으로 보이는데, golang만 맞는 ARCH것이면, 잘 나오는것 같고 soong_ui를 실행할때의 환경들이 어떻게 잡혀 들어가는지를 살펴봐야겠네요.

AOSPonARM:/mnt/bsp/build$ file ../out/soong_ui
../out/soong_ui: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, with debug_info, not stripped

아… make clean이 떠올랐습니다. 일단 out을 날리고 lunch 까지 실행시에는 차이가 없고. get_build_var도 차이가 없네요.. OTL…
다시 soong_ui가 go의 빌드된 바이너리라는 생각에서 아래 파일들을 다시 보기 시작합니다. 보아하니 GOOS하고 GOARCH등은 RUNTIME에서 올라오는것 같은데, 이것을 활용하는 코드들이 약간 중구난방인 듯 합니다.
build/soong/ui/build/config.go
build/soong/ui/build/sandbox_config.go

아래부분을 좀 손 보니, 아예 go build fail이 나네요…

func (c *configImpl) HostPrebuiltTag() string {
▒░░░if runtime.GOOS == “linux” {
▒░░░▒░░░return “linux-x86”
▒░░░} else if runtime.GOOS == “darwin” {
▒░░░▒░░░return “darwin-x86”
▒░░░} else {
▒░░░▒░░░panic(“Unsupported OS”)
▒░░░}
}

네, runtime.GOARCH 는 ‘arm64’ 를 출력으로 주고 있습니다… aarch64 아.. 좀 통일좀 했으면 좋겠습니다.. 아래를 수정후에 이제 좀 PATH가 변경된걸로 보이네요.

AOSPonARM:/mnt/bsp/build/soong$ git diff
diff --git a/ui/build/config.go b/ui/build/config.go
index 409f9d46e..fca4ee24b 100644
--- a/ui/build/config.go<br>+++ b/ui/build/config.go
@@ -1341,7 +1341,13 @@ func (c *configImpl) hostCrossOut() string {
func (c *configImpl) HostPrebuiltTag() string {
if runtime.GOOS == "linux" {
- return "linux-x86"
+ if runtime.GOARCH == "x86" {
+ return "linux-x86"
+ } else if runtime.GOARCH == "arm64" {
+ return "linux-arm64"
+ } else {
+ panic("Unsupported OS")
+ }
} else if runtime.GOOS == "darwin" {
return "darwin-x86"
} else {

AOSPonARM:/mnt/bsp$ get_build_var COMMON_LUNCH_CHOICES
04:50:39 Build sandboxing disabled due to nsjail error.
04:50:39 Failed to run dumpvars: fork/exec prebuilts/build-tools/linux-arm64/bin/ckati: no such file or directory

ckati를 apt로 설치한 바이너리를 가져다가, prebuilts/build-tools/linux-arm64/bin에 복사해주고 실행합니다. 그러면 뭔가, 다시 linux-x86용 toybox 링크로 걸려 있는 host PC용 utility들을 실행하다가 멈추는게 보이네요.. 그냥 linux host꺼 쓰면 되는데 왜 굳이 toybox걸 링크해서 호출하는지 매우 의아합니다만.. –;

AOSPonARM:/mnt/bsp$ get_build_var COMMON_LUNCH_CHOICES
04:57:32 Build sandboxing disabled due to nsjail error.
/bin/bash: /mnt/bsp/prebuilts/build-tools/path/linux-x86/uname: cannot execute binary file: Exec format error
build/make/core/envsetup.mk:1076: error: missing `endif’.
04:57:32 dumpvars failed with: exit status 1

중간에 대충 작업했던 것에 의한 것 일지도 모르겠네요. 아래도 제대로 작업해보겠습니다.

./soong/ui/build/Android.bp:21: pkgPath: “android/soong/ui/build/paths”,
./soong/ui/build/path.go:28: “android/soong/ui/build/paths”
./soong/ui/build/path.go:109: prebuiltsPath, _ := filepath.Abs(“prebuilts/build-tools/path/” + runtime.GOOS + “-x86”)
./soong/ui/build/path.go:144: if , err := microfactory.Build(&cfg, interposer, “android/soong/cmd/path_interposer”); err != nil { ./soong/ui/build/path.go:244: prebuiltsPath, := filepath.Abs(“prebuilts/build-tools/path/” + runtime.GOOS + “-x86”)

path.go내의 arch부분은 교체가 가능한데, 이렇게 할 경우 해당 폴더에 들어 있는게 없어서, 실행이 여전히 안됩니다… 그냥 똑같이 toybox를 arm용으로 빌드해서 집어 넣어봅니다… 뭐. 단말에 들어가는거랑 똑같긴할텐데, /external/toybox에서 ./configure; make -j8 로 간단하게 생성 완료. 빌드된 toybox를 prebuilts/build-tools/linux-arm64/bin에 복사(지금 말고 아래쪽 설명나온 커맨드로 하세요) 뭔가 하나씩 살림이 늘어나는게 나름 진행정도가 눈에 보여서 보람차네요. 이제 링크생성… 아 조금 귀찮….

해서 external/toybox/Makefile을 뒤적거려보니, 스크립트에서 자동생성하는게 보입니다.

install_flat: toybox                                                                                                                                                                                             ▒░░░scripts/install.sh --symlink --force                                                                                                                                                                                                                                                                                                                                                                                          install_airlock: toybox                                                                                                                                                                                          ▒░░░scripts/install.sh --symlink --force --airlock                                                                                                                                                                                                                                                                                                                                                                                install: toybox                                                                                                                                                                                                  ▒░░░scripts/install.sh --long --symlink --force        

근데 make install을 실행하면, /install/bin /install/sbin 에 설치를 하는군요..
external/toybox$ make install_flat PREFIX=../../prebuilts/build-tools/path/linux-arm64 로 하면 일단 모두 다 해당 폴더에 생성은 해주니. 이렇게 하고, toybox를 이동시켜서 link만 다시 거는게 좋을 듯 합니다. 아니면 아예 옵션에서 어떻게든 해보던가.. 아래를 참고해서 toybox를 옮기고, link를 업데이트 하면 끝
linux – How do I move a relative symbolic link? – Stack Overflow

일단 최초의 삽질로 아래의 커맨드를 마지막으로 정정하기는 했는데, Source에 해당하는 부분을 변경하고 , 뒤쪽의 dest, 즉 symbolic link name 에 해당하는 $i는 그대로 남겨두고 -f 옵션으로 강제 업데이트. 상대 경로라서 실행하는 위치도 중요함. ‘..’ 이 하나 더 들어가야 할 수도 있음.

prebuilts/build-tools/path/linux-arm64$ mv toybox ../../linux-arm64/bin
prebuilts/build-tools/path/linux-arm64$ for i in *; do ln -fsr “../linux-arm64/bin/$(readlink “$i”)” “$i”; done;

이제 아래와 같이 결과가 바뀝니다. 여전히 쉽게 통과는 안되네요 T.T

AOSPonARM:/mnt/bsp$ get_build_var COMMON_LUNCH_CHOICES
build/make/core/combo/select.mk:43: error: build/make/core/combo/HOST_linux-aarch64.mk: No such file or directory
09:06:18 dumpvars failed with: exit status 1

어제인가 추가했던, /build/make/envsetup.mk에 오류가 있네요. bash문법으로 추가했던 부분에서 에러가 떴습니다. 확실히 진척이 더 있는 모양입니다. missing operator등으로 뜨니, 코드 다시 보고 다시 짜고, 이제 AndroidProducts.mk 에서 missing operator 가 나오네요. 이건 고쳤던 파일도 아니라서, 좀 더 광범위하게 봐야할것 같습니다. 오늘은 여기까지 하고 마무리 합니다..