shelper
shelper

Reputation: 10573

cross compile for android on linux with __ANDROID_API__ predefinition fails my program

I setup conan for cross building android app on my linux, i have my_profile below for conan for this cross building, which that I run conan create . user/testing -pr=my_profile

include(default)
target_host=aarch64-linux-android
android_ndk=$HOME/android-ndk-r21
api_level=21
[settings]
arch=armv8
build_type=Release
compiler=clang
compiler.libcxx=libc++
compiler.version=9
os=Android
os.api_level=$api_level
[build_requires]
[options]
[env]
PATH=[$android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin]
CHOST=$target_host
AR=$target_host-ar
AS=$target_host-as
LD=$target_host-ld
STRIP=$target_host-strip
RANLIB=$target_host-ranlib
CC=$target_host$api_level-clang
CXX=$target_host$api_level-clang++
CONAN_MAKE_PROGRAM=$android_ndk/prebuilt/linux-x86_64/bin/make
CONAN_CMAKE_TOOLCHAIN_FILE=$android_ndk/build/cmake/android.toolchain.cmake

and I made a very simple file:

#include <fcntl.h>
int raw_fallocate(int fd, off_t length) {
  if (fallocate(fd, 0, 0, length) == 0)    return 0;
  return -1;
}

I found that in the fcntl.h, it only defines fallocate when __ANDROID_API >=21 with #ifdef so in my CMakeLists.txt, I need to put target_compile_definitions(hello PRIVATE __ANDROID_API__=21) to make it compile, otherwise, the compiler will complain it cannot find definition of fallocate.

That all make sense. However, when I put this preprocessor definition, I still got a warning message saying:

In file included from <built-in>:413:
<command line>:1:9: warning: '__ANDROID_API__' macro redefined [-Wmacro-redefined]
#define __ANDROID_API__ 21
        ^
<built-in>:405:9: note: previous definition is here
#define __ANDROID_API__ 16
        ^
1 warning generated.

What I don't understand is I could not find this built-in thing..., i searched my whole android_ndk folder, and could not find where is this #define __ANDROID_API__ 16

Also I only have android_ndk v21 installed, I have no idea where this version of 16 came from.

Any idea?

Upvotes: 2

Views: 5217

Answers (2)

Alex Cohn
Alex Cohn

Reputation: 57173

This #define __ANDROID_API__ 16 comes from the NDK itself (this is the lowest supported API for android-ndk-r21. To set it to 21, you must pass ANDROID_PLATFORM parameter to CMake. Update: this is actually wrong. For ABI arm64-v8a the minimal API is 21. So, the problem is that arch=armv8 didn't work.

According to the conan instructions, set os.api_level=21 should have worked. But with this approach, you should not supply the CONAN_CMAKE_TOOLCHAIN_FILE. Update: this does not work because conan is not compatible with NDK r21.

I assume that when you do supply CONAN_CMAKE_TOOLCHAIN_FILE, all the settings, like CC= and AR= become irrelevant. Same for os.api_level and arch. But if you replace cmake with a script that calls the original cmake binary and sets the necessarycommand-line parameters, including -DANDROID_PLATFORM=android-21, you should be set. Simply add to my_profile: CONAN_CMAKE_PROGRAM=cmake-wrapper

This approach is used in https://github.com/bincrafters/conan-android_ndk_installer package.

Upvotes: 4

shelper
shelper

Reputation: 10573

So I've been digging into this a little bit, and I think I found where the problem is. As @Alex Cohn said, the android ndk sets the min api level to 16 in the file $android_ndk/build/cmake/platforms.cmake, it says on the first line set(NDK_MIN_PLATFORM_LEVEL "16"). After I change it to 21, everything works.

Now the question becomes: How can I override this value externally without touching this platforms.cmake file (I just don't want to touch files come with ndk package)? I tried to put set(NDK_MIN_PLATFORM_LEVEL "16") in my CMakelists.txt file for my project, but that does not work as I believe it is overridden later on by platforms.cmake.

Of course the second method of using conan's ndk-installer also works, and I checked the same platforms.cmake file in the installed ndk folder, it has the same value of 16. So there must be somewhere in conan settings that updated the value to 21, and I would like to learn where / how this is changed when using ndk-installer, so I can do the same for my manually installled android ndk.

Upvotes: 0

Related Questions