Cross compiling for arm using crystax NDK

2019-02-15 00:11发布

问题:

The android ndk supplied by google is unable to compile call to c++11 functions such as std::to_string() and std::stoul etc. {I had tried it in r10b one from the official site}. So the suggestion in SO was to try crystax NDK. I have downloaded and placed the root folder next to the google's NDK. All I changed in my root CMakeLists.txt file was:

from:

set(PLATFORM_PREFIX            "/some-path/android-ndk-r10b/platforms/android-19/arch-arm")
set(PLATFORM_FLAGS             "-fPIC -Wno-psabi --sysroot=${PLATFORM_PREFIX}")
set(CMAKE_CXX_FLAGS            "${PLATFORM_FLAGS} -march=armv7-a -mfloat-abi=softfp -mfpu=neon" CACHE STRING "")

To:

set(PLATFORM_PREFIX            "/some-path/android-ndk-r8-crystax-1/platforms/android-14/arch-arm")
set(PLATFORM_FLAGS             "-fPIC -Wno-psabi --sysroot=${PLATFORM_PREFIX}")
set(CMAKE_CXX_FLAGS            "${PLATFORM_FLAGS} -march=armv7-a -mfloat-abi=softfp -mfpu=neon" CACHE STRING "")

and cmake command-line from:

cmake .. -DCMAKE_CXX_COMPILER=/some-path/android-ndk-r10b/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -DCMAKE_C_COMPILER=/some-path/android-ndk-r10b/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -DANDROID_BUILD=ON -DANDROID_NDK_ROOT=/some-path/android-ndk-r10b

To:

cmake .. -DCMAKE_CXX_COMPILER=/some-path/android-ndk-r8-crystax-1/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -DCMAKE_C_COMPILER=/some-path/android-ndk-r8-crystax-1/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -DANDROID_BUILD=ON -DANDROID_NDK_ROOT=/some-path/android-ndk-r8-crystax-1

ie., changed from normal ndk to crystax-ndk. The program was compiling fine previously till it tried to compile a file with call to std::to_string() etc. But after the change Cmake gives an error that it is unable to compile a simple test program because:

  /some-path/android-ndk-r8-crystax-1/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.7/../../../../arm-linux-androideabi/bin/ld:
  error: cannot find -lcrystax

I can see libcrystax.a and .so in directorie:

/some-path/android-ndk-r8-crystax-1/sources/crystax/libs/armeabi-v7a

I tried adding link_directories("path-to-above") right at the beginning of the CMakeLists.txt file too, but that didn't solve it either.

It should find it there (after i supply the --sysroot etc above) just like the normal ndk. So how should this be solved ? Any other cmake variable to be set or something ?

回答1:

I don't know how your cmake-based build system works, but actually if you properly add path /some-path/android-ndk-r8-crystax-1/sources/crystax/libs/armeabi-v7a to linker search paths, it should find libcrystax and link with it successfully.

Please note that NDK have several parts separated each from other - i.e. sysroot, libcrystax, C++ library - all are separated. It is done to work with NDK build system which offer some flexibility choosing C++ standard library implementation, and NDK build system know where to find all of them. In your case this approach is not so good so I suggest you first make standalone toolchain, which contains all things assembled together. In other words, it would be classic cross-compile toolchain which contains sysroot, libcrystax and GNU C++ standard library in places known to compiler/linker without passing of any additional options.

To create such toolchain, cd to NDK root directory and run the following command:

./build/tools/make-standalone-toolchain.sh --system=linux-x86_64 --toolchain=arm-linux-androideabi-4.7 --platform=android-14 --install-dir=$HOME/arm-linux-androideabi

Then use $HOME/arm-linux-androideabi as full standalone toolchain for your cmake-based build system.

Please note, however, that application built with CrystaX NDK r8 will not run on newest Android 5.0 due to changes in Bionic (libc). Previous Android versions (<=4.4) are all fine. We fixed that issue (and many others) in upcoming r10 release which is on final testing stage. In the meantime you could adopt your project to our r8 release and quickly switch to r10 when it done - the same approach will work with r10 as well as with r8.