+
研究了一下怎樣編譯 LLVM for Pandaboard,過程中發現並不是那麼順利的,網路上僅有少數的資訊,並且頂多是 bug report 的等級,沒有講任何的解法,而我只是暫時找到應對的惡搞方式。
首先,先練習一下 Ubuntu 12.04 on Pandaboard,流程就像在 x86 編一樣:
Device: Pandaboard ES
OS: ubuntu-12.04-preinstalled-server-armhf+omap4
SD: Transcend SDHC Class10 8GB
- Install Ubuntu 12.04 server on Pandaboard (ubuntu-12.04-preinstalled-server-armhf+omap4.img.gz)
- Initial building enviroments
- $ sudp apt-get update && sudo apt-get upgrade
- $ sudo apt-get install subversion gcc g++ make cmake
- Get LLVM/Clang source code
- $ svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_31/final/ ~/llvm-src/
- $ svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_31/final/ ~/llvm-src/tools/clang
- $ svn co http://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_31/final/ ~/llvm-src/projects/compiler-rt
- Built it
- $ mkdir ~/bulid && cd ~/build && cmake -DCMAKE_INSTALL_PREFIX:PATH=$HOME/out ../llvm-src
- $ make -j2 (約120分鐘,且 Pandaboard 是雙核心,故 -j2)
- $ make install
- Testing
- $ ~/out/bin/llvm-config --version
3.1svn - $ ~/out/bin/clang --version
clang version 3.1 (tags/RELEASE_31/final 158045)
Target: armv7l-unknown-linux-gnueabihf
Thread model: posix
很不錯,編出來了,指令操作也很正常,然而,我以為這樣編出來就可以移到 Android ICS 上跑,真是個錯誤的觀念 XD
$ ~/android-sdks/platform-tools/adb shell mkdir /data/ullvm
$ ~/android-sdks/platform-tools/adb push arm-ubuntu-out/bin/clang /data/ullvm/
$ ~/android-sdks/platform-tools/adb shell /data/ullvm/clang
/system/bin/sh: /data/ullvm/clang: No such file or directory
爾後,我才想起 cross compiler 的事情,找了一下 AOSP 裡頭的東西,也就是那些 prebuilt/prebuilts 目錄,翻啊翻,我才發現 NDK 那一包裡頭已經有了,而使用的方式並不是把 CC/CXX 直接指到目錄,先透過 android-ndk-r8/build/tools/make-standalone-toolchain.sh 建立 standalone toolchain 囉,在指定 CC/CXX 位置(此處用 cmake 設定檔)。
工作環境:
OS: Ubuntu 10.04 server x84_64
建立 standalone-toolchain:
$ sh android-ndk-r8/build/tools/make-standalone-toolchain.sh
$ sh android-ndk-r8/build/tools/make-standalone-toolchain.sh --install-dir=$HOME/android-14-toolchain --platform=android-14
透過 CMAKE 編譯前,先寫隻 ~/Android.cmake 初始工作環境:
$ vim ~/Android.cmake
SET(CMAKE_SYSTEM_NAME Linux) # Tell CMake we're cross-compiling
include(CMakeForceCompiler)
# Prefix detection only works with compiler id "GNU"
# CMake will look for prefixed g++, cpp, ld, etc. automatically
CMAKE_FORCE_C_COMPILER(/home/user/android-14-toolchain/bin/arm-linux-androideabi-gcc GNU)
CMAKE_FORCE_CXX_COMPILER(/home/user/android-14-toolchain/bin/arm-linux-androideabi-g++ GNU)
SET(ANDROID TRUE)
正式編譯:
$ mkdir build && cd ~/build && cmake -DCMAKE_TOOLCHAIN_FILE=$HOME/Android.cmake -DCMAKE_INSTALL_PREFIX:PATH=$HOME/out ../llvm-src/
$ make
...
Scanning dependencies of target gtest
[100%] Building CXX object utils/unittest/CMakeFiles/gtest.dir/googletest/gtest.cc.o
/home/user/llvm-src/utils/unittest/googletest/gtest.cc: In static member function 'static bool
esting::internal::String::CaseInsensitiveWideCStringEquals(const wchar_t*, const wchar_t*)':
/home/user/llvm-src/utils/unittest/googletest/gtest.cc:1625: error: 'wcscasecmp' was not declared in this scope
make[2]: *** [utils/unittest/CMakeFiles/gtest.dir/googletest/gtest.cc.o] Error 1
make[1]: *** [utils/unittest/CMakeFiles/gtest.dir/all] Error 2
make: *** [all] Error 2
此處不能用 make -j# 的方式進行,似乎無法平行進行?暫時沒空研究。此外並不是這樣就搞定了,只搞定編譯出 bin/lib/include/share 的產出物,且原先編譯完還會跑 testing,只是碰到 test case 無法編譯出來,暫時就不先管了,有興趣的可以在研究囉。
取出 ~/build/bin 丟進 PandaBoard 中(請留意空間,bin約3xxMB):
$ ~/android-sdks/platform-tools/adb shell df
Filesystem Size Used Free Blksize
/dev 363M 32K 363M 4096
/mnt/asec 363M 0K 363M 4096
/mnt/obb 363M 0K 363M 4096
/system 251M 141M 110M 4096
/data 503M 51M 452M 4096
/cache 251M 4M 247M 4096
/mnt/sdcard 503M 51M 452M 4096
$ ~/android-sdks/platform-tools/adb shell mkdir /data/llvm
$ ~/android-sdks/platform-tools/adb push ~/build/bin /data/ullvm/bin
push: ...
42 files pushed. 0 files skipped.
3065 KB/s (343386572 bytes in 109.394s)
$ ~/android-sdks/platform-tools/adb shell /data/llvm/bin/clang --version
clang version 3.1 (tags/RELEASE_31/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
$ ~/android-sdks/platform-tools/adb shell /data/llvm/bin/llvm-config --version
3.1svn
測試:
$ vim hello.c
#include <stdio.h>
int main() {
printf( "Hello World\n" );
return 0;
}
$ clang -emit-llvm -o hello.bc -c hello.c
$ ~/android-sdks/platform-tools/adb push hello.bc /data/llvm/
出現以下訊息,代表你用的 clang/LLVM 版本跟 LLVM on Android 版本不一致(LLVM沒有向下相容且更新變化快):
$ ~/android-sdks/platform-tools/adb shell /data/llvm/bin/lli /data/llvm/hello.bc
/data/llvm/bin/lli: /data/llvm/hello.mc: error: Invalid MODULE_CODE_GLOBALVAR record
若版本一致的結果:
$ ~/android-sdks/platform-tools/adb shell /data/llvm/bin/lli /data/llvm/hello.bc
LLVM ERROR: Program used external function 'printf' which could not be resolved!
最後分享一下改了啥東西:
- LockFileManager.cpp:58: error: 'getsid' was not declared in this scope
- 上述連結寫得很清楚且在 unistd.h 也有清楚的註解。這邊的解法很危險,把 getsid(PID) == -1 註解起來,然後程式就能產出了 XD 不知哪時會出現未爆彈
- @ llvm-src/lib/Support/LockFileManager.cpp
if (MyHostname == Hostname && /*getsid(PID) == -1 && */ errno == ESRCH) - DynamicLibrary.cpp: In static member function 'static void* llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(const char*)'
- @ llvm-src/lib/Support/DynamicLibrary.cpp
#if defined(__linux__)
{
// EXPLICIT_SYMBOL(stderr);
// EXPLICIT_SYMBOL(stdout);
// EXPLICIT_SYMBOL(stdin);
}
#else
... - JITMemoryManager.cpp:820: error: 'open64' was not declared in this scope
- @ llvm-src/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
//sys::DynamicLibrary::AddSymbol("\x1open64", (void*)(intptr_t)open64); - gtest.cc:1625: error: 'wcscasecmp' was not declared in this scope
- 此為 test case 問題,但不影響 LLVM 產出,所以我就沒理它了
參考資料:
Beuc's Blog/ posts/ Cross-compiling with CMake
沒有留言:
張貼留言