顺利入坑-----------~~~~~~--->>>>>
====> 坑:如何通过JNI/NDK将C/C++代码添加到Android项目中?在该项目中 settings.gradle中:
// To generate libs used in this sample:
// 1) enable the gen-libs at end of this file
// 2) enable module build dependency in app/build.gradle
// 3) build the app's APK in Android Studio or on command line
// 4) undo step 1) and 2) above
include ':gen-libs'
所以,去掉最后一行(// include ':gen-libs')的注释,并在 app/build.gradle中打开dependency(最后,去除/* */)语句,sync gradle.
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../distribution)
2.增加引用第三方库,注意add_library的参数(lib名,导入方式{shared static},文档路径或者导入),为第三方库增加路径
add_library(lib_gperf SHARED IMPORTED) //shared library and imported from 3rd part
set_target_properties(lib_gperf PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/gperf/lib/${ANDROID_ABI}/libgperf.so) //the path of so lib
3. 为引用库添加第三方库的头文件目录
target_include_directories(hello-libs PRIVATE
${distribution_DIR}/gmath/include
${distribution_DIR}/gperf/include) //the header files
4.设置接口库对第三方库的链接,其中第一个参数为接口库,后面参数为第三方库
target_link_libraries(hello-libs
android
lib_gmath
lib_gperf //third part so
log)
5. 在app的build.gradle中添加jniLibs路径,该命令决定了在apk打包时候会将该库打包进apk
sourceSets {
main {
// let gradle pack the shared library into apk
jniLibs.srcDirs = ['../distribution/gperf/lib'] //package the so libs into apk
jni.srcDirs = ['src/main/jni', 'src/main/jni/']
}
}
___________________
sourceSets {
main {
// let gradle pack the shared library into apk
jniLibs.srcDirs = ['../distribution/crossadd/lib'] //package the *.so libs in the folder into the APK
jni.srcDirs = ['src/main/jni', 'src/main/jni/']
}
}
====> 坑: 如何构建交叉编译工具链?
export NDK_HOME=/home/xxx/Android/Sdk/ndk-bundle #your ndk path
platform=android-19 #the platform you want to use
#platform>19 support the blow 6 kinds of archs, otherwise support only 3 kinds of archs, when check the path ${NDK_HOME}/platforms/android-x, you will find the difference.
shmake=$NDK_HOME/build/tools/make-standalone-toolchain.sh
archs=( #here list 6 kinds of arch
'arm'
'arm64'
'x86'
'x86_64'
'mips'
'mips64'
)
toolchains=( #here list 6 kinds of toolchains
'arm-linux-androideabi-4.9'
'aarch64-linux-android-4.9'
'x86-4.9'
'x86_64-4.9'
'mipsel-linux-android-4.9'
'mips64el-linux-android-4.9'
)
echo $NDK_HOME
num=${#archs[@]}
for((i=0;i<$num;i++))
do
$shmake --arch=${archs[i]} --platform=$platform --install-dir=$HOME/Android/android-toolchains/${archs[i]} --toolchain=${toolchains[i]}
done
# --install-dir, the direction of the toolchains to be placed
crossadd------
|--c/
| |--CmakeLists.txt
| |--crossadd.c
| |--crossadd.h
|--lib/
|--build.sh
请注意,重点是build.sh和CmakeLists.txt.
#!/bin/bash
cd ./build/
export CC=/home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-gcc
export CXX=/home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-g++
# cmake command
cmake ../c/
#do make
make
#clear the build file, all are generated in the process of compile; optional
rm -rf ./*
#external command. to copy the head file and lib file to the project; user command
sudo cp ../lib/* /home/mechmqx/AndroidStudioProjects/testlib/distribution/crossadd/lib/armeabi-v7a
sudo cp ../c/crossadd.h /home/mechmqx/AndroidStudioProjects/testlib/distribution/crossadd/include
CmakeList.txt内容如下:
project(crossadd)
cmake_minimum_required(VERSION 2.4.1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
#Android 5.0 以上需要在此设置PIE
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
#配置使用NDK Standalone Toolchain 编译
set(NDK_STANDALONE_TOOLCHAIN /home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16)
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 16)
#set(CMAKE_C_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/arm-linux-androideabi-clang) #it seems no work if set compiler here
#set(CMAKE_CXX_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/arm-linux-androideabi-clang++)
#set(CMAKE_C_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/arm-linux-androideabi-gcc)
#set(CMAKE_CXX_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/arm-linux-androideabi-g++)
set(CMAKE_FIND_ROOT_PATH ${NDK_STANDALONE_TOOLCHAIN})
#使用NDK提供的头文件
add_definitions("--sysroot=${NDK_STANDALONE_TOOLCHAIN}/sysroot")
add_library(crossadd SHARED crossadd.c)
set_target_properties(crossadd
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/../lib
)
请注意,实际应用中,在CMakeLists.txt中设置编译器(set(CMAKE_C_COMPILER xxx))语句貌似无用,编译时候仍然是默认的编译器(GNU)
mechmqx@mechmqx-R467-R464-P467:~/mechmqx/testgcc/crosscompile$ ./build_for_test_crossadd.sh
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mechmqx/mechmqx/testgcc/crosscompile/build
Scanning dependencies of target crossadd
[100%] Building C object CMakeFiles/crossadd.dir/crossadd.o
Linking C shared library /home/mechmqx/mechmqx/testgcc/crosscompile/lib/libcrossadd.so
[100%] Built target crossadd
后来修改:注释设置编译器的语句,改用在shell文件中export编译器,后续有提到.(使用错误的编译器编译出的libxxx.so不能够被正常编译,incompatible target)
export CC=/home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-gcc
export CXX=/home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-g++
正确配置编译器后的编译log:
mechmqx@mechmqx-R467-R464-P467:~/mechmqx/testgcc/crosscompile$ ./build_for_test_crossadd.sh
-- The C compiler identification is GNU 4.9.0
-- The CXX compiler identification is GNU 4.9.0
-- Check for working C compiler: /home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-gcc
-- Check for working C compiler: /home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-g++
-- Check for working CXX compiler: /home/mechmqx/mechmqx/arm-linux-androideabi-gcc/arm-android-16/bin/arm-linux-androideabi-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mechmqx/mechmqx/testgcc/crosscompile/build
Scanning dependencies of target crossadd
[100%] Building C object CMakeFiles/crossadd.dir/crossadd.o
Linking C shared library /home/mechmqx/mechmqx/testgcc/crosscompile/lib/libcrossadd.so
[100%] Built target crossadd
ndk{
abiFilters "armeabi-v7a","x86" //filter the abi to be complied
}
static {
System.loadLibrary("crossadd"); //add this line to solve link error
System.loadLibrary("native-lib");
}
注:在使用Android-19真机调试时候,android-ndk-master实例(Git上可以下载)中的hello-libs可以直接运行,但是在Android-16的真机上调试就出现上述linkError.目前不清楚原因,如有大神,还请帮忙解释.(不要问我为什么换成Android-16的,酷派大神ANdroid-19的已经被我玩成砖了...)