使用 __ANDROID_API__ 预定义在 linux 上交叉编译 android 我的程序失败

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

我在我的 linux 上设置了 conan for cross building android 应用程序,我在下面有 my_profile 这个 cross building 的 conan,我 运行 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

我做了一个非常简单的文件:

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

我发现在fcntl.h中,当__ANDROID_API >=21#ifdef时,它只定义了fallocate 所以在我的 CMakeLists.txt 中,我需要输入 target_compile_definitions(hello PRIVATE __ANDROID_API__=21) 让它编译,否则,编译器会抱怨找不到 fallocate.

的定义

这一切都有道理。但是,当我放置这个预处理器定义时,我仍然收到一条警告消息:

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.

我不明白的是我找不到这个内置的东西...,我搜索了整个 android_ndk 文件夹,但找不到这个 #define __ANDROID_API__ 16

而且我只安装了android_ndkv21,不知道16这个版本是从哪里来的

有什么想法吗?

这个#define __ANDROID_API__ 16来自NDK本身(这是android-ndk-r21支持的最低API。要设置它到 21,你必须将 ANDROID_PLATFORM 参数传递给 CMake。更新: 这实际上是错误的。对于 ABI arm64-v8a最小的 API 是 21。所以,问题是 arch=armv8 不起作用。

根据 conan instructionsset os.api_level=21 应该有效。但是使用这种方法,您不应该提供 CONAN_CMAKE_TOOLCHAIN_FILE更新: 这不起作用,因为 conan 与 NDK r21.

不兼容

我假设当您提供 CONAN_CMAKE_TOOLCHAIN_FILE 时,所有设置,如 CC=AR= 都变得无关紧要。 os.api_levelarch 相同。但是,如果您将 cmake 替换为调用原始 cmake 二进制文件并设置必要的命令行参数(包括 -DANDROID_PLATFORM=android-21)的 script,您应该会被设置。只需添加到 my_profileCONAN_CMAKE_PROGRAM=cmake-wrapper

https://github.com/bincrafters/conan-android_ndk_installer 包中使用了这种方法。

所以我对此进行了深入研究,我想我找到了问题所在。正如@Alex Cohn 所说,android ndk 在文件中将最小 api 级别设置为 16 $android_ndk/build/cmake/platforms.cmake,它在第一行显示 set(NDK_MIN_PLATFORM_LEVEL "16")。我把它改成21后,一切正常。

现在问题变成了:如何在不触及这个 platforms.cmake 文件的情况下从外部覆盖这个值(我只是不想触及 ndk 包附带的文件)?我试图将 set(NDK_MIN_PLATFORM_LEVEL "16") 放入我的项目的 CMakelists.txt 文件中,但这不起作用,因为我相信它稍后会被 platforms.cmake.

覆盖

当然第二种方法使用conan的ndk-installer也可以,我在安装的ndk文件夹中检查了相同的platforms.cmake文件,它具有相同的值16。所以 conan 设置中一定有某个地方将值更新为 21,我想了解使用 ndk-installer 时在哪里/如何更改它,所以我可以手动执行相同的操作安装了 android ndk.