Android cross compile
Android交叉编译需要Android NDK环境,应先下载NDK环境.
一般使用NDK环境是使用
生成编译工具链
1
2//生成静态编译工具链
$ $ANDROID_NDK_ROOT_DIR/build/tools/make_standalone_toolchain.py --arch $ARM --api $ANDROID_API --stl=libc++ --install-dir $ANDROID_TOOLCHAIN_INSTALL_DIR1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16├── AndroidVersion.txt
├── MODULE_LICENSE_BSD_LIKE
├── MODULE_LICENSE_MIT
├── NOTICE
├── aarch64-linux-android
├── arm-linux-androideabi
├── bin //可执行目录
├── i686-linux-android
├── include //头文件依赖
├── lib //lib
├── lib64 //lib64
├── libexec
├── manifest_5220042.xml
├── share
├── sysroot //sysroot目录
└── x86_64-linux-android使用生成的编译工具链交叉编译适合Android运行的可执行程序
1
$arm-linux-android-clang++ main.cc -o main_Android
Android 重要编译说明
mfpu //使用浮点运算
mfloat-abi //浮点运算规则 soft softfp hard
Wl,-rpath= //-Wl 是告诉编译器 之后的参数都传入连接器 -rpath是指定程序连接的库路径 此选项不LD_PATH优先级高
Wl,-soname= //-soname 可执行文件在连接库的时候 实际连接的库名字
[注]一般-Wl,-rpath= -Wl,-soname 都加上 // -Wl,-rpath=. -Wl,-soname=libXXX.so
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//android常用参数说明
--atrget //指定架构(arm-linux-androideabi/aarch64-linux-android)
--gcc-toolchain //指定编译工具链路径
-march=armv7-a //选择arm处理器指令集 在mac系统中一般是使用-arch(armv7,armv7s,arm64,x86_64)
-mthumb //应该是选择是否支持thumb指令集
-mfpu=vfpv3-d16 //忘记是啥作用了
-mfloat-abi=softfp //浮点数设置 具体忘记了
-funwind-tables
-no-canonical-prefixes
-nostdlib // 如果不加会出现找不到xxx.o的问题
-sysroot //指定编译器在编译的时候搜索的目录(一般在找不到文件的时候需要用户指定目录)
//for release
-O3 //编译O3级别优化
-DNDEBUG //编译时去除DEBUG信息,比如assert选项等
//其他参数可根据业务需求增添使用cmake文件交叉编译
1
2
3
4
5
6
7
8// buidl.cmake
set (CMAKE_SYSTEM_NAME Android)
set (CMAKE_SYSTEM_VERSION 16)
set (CMAKE_ANDROID_ARCH_ABI armeabi-v7a)
set (CMAKE_ANDROID_STANDALONE_TOOLCHAIN /Users/jay/Work_Android/Do_Work/armeabi-v7a/armv7_16_toolchain)
// 在cmake编译的时候选择 使用cmake文件进行编译 cmake记得使用GUI的 省事
编译lightGBM
-frtti -fexceptions -mfloat-abi=softfp -mfpu=neon -std=gnu++0x -Wno-deprecated -ftree-vectorize -ffast-math -fsingle-precision-constant -nostdlib -D__ANDROID_API__=24
然后加上 -L最低支持的api路径
arm64-v8a:/Users/jay/Work_Android/Do_Work/arm64-v8a/aarch64_21_toolchain/bin/clang++ -D__ANDROID_API__=24 -L/Users/jay/Work_Android/Do_Work/arm64-v8a/aarch64_21_toolchain/sysroot/usr/lib/aarch64-linux-android/21 -lc++_shared –target=aarch64-none-linux-android –gcc-toolchain=/Users/jay/Work_Android/Do_Work/arm64-v8a/aarch64_21_toolchain –sysroot=/Users/jay/Work_Android/Do_Work/arm64-v8a/aarch64_21_toolchain/sysroot -frtti -fexceptions -mfloat-abi=softfp -mfpu=neon -std=gnu++0x -Wno-deprecated -ftree-vectorize -ffast-math -fsingle-precision-constant -fopenmp=libomp -std=c++11 -pthread -O3 -Wextra -Wall -Wno-ignored-attributes -Wno-unknown-pragmas -Wno-return-type -fPIC -funroll-loops -g -fPIE -pie -Wl,–gc-sections CMakeFiles/lightgbm.dir/src/main.cpp.o CMakeFiles/lightgbm.dir/src/application/application.cpp.o CMakeFiles/lightgbm.dir/src/boosting/boosting.cpp.o CMakeFiles/lightgbm.dir/src/boosting/gbdt.cpp.o CMakeFiles/lightgbm.dir/src/boosting/gbdt_model_text.cpp.o CMakeFiles/lightgbm.dir/src/boosting/gbdt_prediction.cpp.o CMakeFiles/lightgbm.dir/src/boosting/prediction_early_stop.cpp.o CMakeFiles/lightgbm.dir/src/io/bin.cpp.o CMakeFiles/lightgbm.dir/src/io/config.cpp.o CMakeFiles/lightgbm.dir/src/io/config_auto.cpp.o CMakeFiles/lightgbm.dir/src/io/dataset.cpp.o CMakeFiles/lightgbm.dir/src/io/dataset_loader.cpp.o CMakeFiles/lightgbm.dir/src/io/file_io.cpp.o CMakeFiles/lightgbm.dir/src/io/json11.cpp.o CMakeFiles/lightgbm.dir/src/io/metadata.cpp.o CMakeFiles/lightgbm.dir/src/io/parser.cpp.o CMakeFiles/lightgbm.dir/src/io/tree.cpp.o CMakeFiles/lightgbm.dir/src/metric/dcg_calculator.cpp.o CMakeFiles/lightgbm.dir/src/metric/metric.cpp.o CMakeFiles/lightgbm.dir/src/network/linker_topo.cpp.o CMakeFiles/lightgbm.dir/src/network/linkers_mpi.cpp.o CMakeFiles/lightgbm.dir/src/network/linkers_socket.cpp.o CMakeFiles/lightgbm.dir/src/network/network.cpp.o CMakeFiles/lightgbm.dir/src/objective/objective_function.cpp.o CMakeFiles/lightgbm.dir/src/treelearner/data_parallel_tree_learner.cpp.o CMakeFiles/lightgbm.dir/src/treelearner/feature_parallel_tree_learner.cpp.o CMakeFiles/lightgbm.dir/src/treelearner/gpu_tree_learner.cpp.o CMakeFiles/lightgbm.dir/src/treelearner/serial_tree_learner.cpp.o CMakeFiles/lightgbm.dir/src/treelearner/tree_learner.cpp.o CMakeFiles/lightgbm.dir/src/treelearner/voting_parallel_tree_learner.cpp.o -o ../lightgbm
lightGBM:
编译条件: 将最低版本的crtend_android.o和crtbegin_dynamic.o连接到编译工程Makefile所在的目录
编译参数:-frtti -fexceptions -mfloat-abi=softfp -mfpu=neon -Wno-deprecated -ftree-vectorize -ffast-math -D__ANDROID_API__=24
1.lightGBM编译报找不到getifaddrs和freeifaddrs,NDK中最低支持版本为Android API24.其中arm64v8最低Android API要求21;armv7最低Android API要求16.该函数在lightGBM中分布式中使用.
2.在lightGBM/log.h中有使用stderr和stdout,在anroid中可以通过指定android-api适配该功能.在lightGBM中log系统中使用.
1.仅提取使用到的算法(去除分布式和log系统).
2.自定义实现1中的两个函数.
- armv7:
- error: undefined reference to ‘pthread_atfork ->连接平台的libc++.so (16/libc++.solibc++.so)
- error: undefined reference to ‘stderr’ -> 通过指定Android API -D__ANDROID_API__=24
- error: undefined reference to ‘getifaddrs’ -> NDK中不包含
- armv8: 类似armv7
iOS cross compile
MacOS iOS 使用的编译环境都是XCode提供的.Apple使用的编译环境是llvm.
一般Apple的llvm环境在/Applications/Xcode.app/Contents/中.其中编译工具可执行文件
在/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin下
如何使用apple编译工具编译适合不同平台的程序
编译适合MacOS运行的可执行程序(-mmacosx-version-min=10.9:最低版本要求)
1
2$g++/clang++ main.cc -o main //编译
$file main 或者 $lipo -info main //提示为x86_64架构的程序编译适合iOS运行的可执行程序 (最关键的 -arch -miphones-version-min -isysroot 其他连接库-stdlib=libc++ -lc++ -lc++abi)
其中-stdlib=libc++:代表的是连接到clang的c库上,在交叉编译的时候如果不加次连接条件会出现类似“ld: symbol(s) not found for architecture armv7”1
2$g++/clang++ main.cc -o main_ios -arch armv7 -miphoneos-version-min=6.1 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iphoneos11.4.sdk
$file main-ios 或者$lipo -info main-ios//提示为armv7的可执行程序1. -arch:为apple llvm编译环境的架构选择参数(armv7 armv7s arm64 x86_64).
2. -miphoneos-version-min:为最低支持的版本库.
3. -isysroot:为编译时依赖的平台环境.
mac 使用小技巧
- 查找编译器默认搜索路径
1
clang++ -E -x c++ - -v < /dev/null
Android 调试技术
Android是arm指令集定制linux系统.
- 直接将Android当作一个开发版调试
Andorid可执行目录为/system/bin目录
- 将system目录从新挂载为可读写 (root权限下:su)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//查询当前/system 挂载信息 ro:read only
PHONE
//将/system修改为可读写权限,使用auto自动选择挂载位置
PHONE
//验证是否修改成功 ro->rw
PHONE
之后就可以将交叉编译后的可执行文件导入system/bin目录下如同操作linux一样操作了
//导入system中 //system不具备使用adb直接导入,先导入sdcard/Download
PC$adb push XXX /mnt/sdcard/Download
PHONE:
进入system/bin/XXX中操作目标.
- 使用AndroidStudio集成测试.
将需要测试的c库使用Android native集成到工程中在App中测试.
//AndroidStudio使用lldb调试.
(lldb)add-dsym xx.x.so //导入xx.x.so符号表(-g) 之后就可以跟踪调试了.