使用 __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 instructions,set os.api_level=21
应该有效。但是使用这种方法,您不应该提供 CONAN_CMAKE_TOOLCHAIN_FILE
。 更新: 这不起作用,因为 conan
与 NDK r21.
不兼容
我假设当您提供 CONAN_CMAKE_TOOLCHAIN_FILE
时,所有设置,如 CC=
和 AR=
都变得无关紧要。 os.api_level
和 arch
相同。但是,如果您将 cmake
替换为调用原始 cmake
二进制文件并设置必要的命令行参数(包括 -DANDROID_PLATFORM=android-21
)的 script,您应该会被设置。只需添加到 my_profile
:
CONAN_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.
我在我的 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 instructions,set os.api_level=21
应该有效。但是使用这种方法,您不应该提供 CONAN_CMAKE_TOOLCHAIN_FILE
。 更新: 这不起作用,因为 conan
与 NDK r21.
我假设当您提供 CONAN_CMAKE_TOOLCHAIN_FILE
时,所有设置,如 CC=
和 AR=
都变得无关紧要。 os.api_level
和 arch
相同。但是,如果您将 cmake
替换为调用原始 cmake
二进制文件并设置必要的命令行参数(包括 -DANDROID_PLATFORM=android-21
)的 script,您应该会被设置。只需添加到 my_profile
:
CONAN_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.