ndk-build는 의존성이 여러개인 외부 라이브러리를 손쉽게(?) 빌드하기 어렵다. 이 경우 ndk-build를 사용하는 대신에 AOSP를 소스 트리를 그대로 가져와서 arm_aosp-eng를 빌드한 후에 external/ 하위에 외부 라이브러리를 빌드하면 여러모로 편리하다. 또한 이렇게 하는 경우에 ndk-build와는 다르게 라이브러리 뿐만 아니라 apk 패키지도 같이 빌드할 수 있는 장점도 있다.

기존에는 AOSP 트리 대신에 CyanogenMod 킷캣 소스트리를 사용하고 있었는데 킷캣의 경우 arm64 및 x86_64를 지원하지 않아서 롤리팝 소스트리를 가져다가 빌드 환경을 재구성 하였다.

(AOSP 마쉬멜로우 트리의 경우 전체 빌드는 문제 없이 잘 되었으나, 이를 사용하려 하니 하위 호환성을 무시하고 과감하게 없애버린 몇몇 라이브러리 등등이 문제가 되어 롤리팝 소스트리를 선택하였다)

아무튼 이러한 이유로 AOSP 트리를 받아서 롤리팝을 다음과 같이 컴파일 하였다.

$ repo init -u https://android.googlesource.com/platform/manifest -b android-5.1.1_r38
$ repo sync
$ . build/envsetup.sh
$ lunch aosp_arm-eng
$ make -j4
...

보통은 이렇게 하면 아무런 문제 없이 전체 빌드가 되는데, 우분투 16.04 환경에서 빌드하다고 못보던 오류가 떴다.

해당 오류를 구글로 검색해보니 대략 다음과 같은 내용을 찾을 수 있었다.

http://stackoverflow.com/questions/36048358/building-android-from-sources-unsupported-reloc-43

https://android-review.googlesource.com/#/c/223100/

롤리팝부터는 clang을 host 바이너리 빌드하는 경우에 사용하게 되는데, 이 경우 clang은 자체적으로 내장된 as를 사용하는 대신에 별도의 gcc 툴체인의 as도 같이 사용하고 있다. 그런데 clang에 -B 옵션으로 툴체인의 경로를 지정하지 않는 경우, 툴체인의 as를 사용하는 대신에 host에 이미 설치된 as를 이용해 컴파일 된다. host의 as가 버전이 낮은 경우에는 별 문제가 되지 않는데 최신의 배포판을 사용하는 경우에는 host의 as 버전이 높고,  gcc 툴체인의 ld는 높은 버전으로 컴파일된 오브젝트의 relocation 타입을 인식하지 못하는 문제가 발생하는 것이다.

우분투 16.04를 사용하는 경우 host의 as 버전 (binutils 2.26.1)

$ as -v
GNU assembler version 2.26.1 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.26.1

툴체인의 as 버전 (gcc 4.6 + binutils 2.23.2)

$ prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6/bin/x86_64-linux-as -v
GNU assembler version 2.23.2 (x86_64-linux) using BFD version (GNU Binutils) 2.23.2

위와 같이 툴체인의 as 버전이 host의 as 버전보다 낮다.

일단 위 링크에 써있듯이 -B 옵션을 build/core/clang/HOST_clang_common.mk에 추가하고 다시 컴파일 하였다. (stackoverflow 링크에 나와있듯이 롤리팝의 경우에는 다른 옵션을 건드리지 말고 패치를 수동으로 추가)

  -B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/bin

주의해야 할 것은 이 경우 이미 컴파일 된 오브젝트 파일을 모두 지워줘야 한다는 점이다. 따라서 out/host/* 파일을 지워주고 make -j4 로 재빌드 한다.

by dumpcookie 2017. 2. 26. 21:25