【问题标题】:How to use cpu-feature in a native library?如何在本机库中使用 cpu 功能?
【发布时间】:2017-09-13 09:11:35
【问题描述】:

我们最近添加了 cpu 功能来检测 ARMV8 和 CRC、AES 和 SHA 等平台功能。我们发现了一个bug report 用于针对最新的 NDK 进行构建。当我们尝试在 armeabi 项目中包含 <cpu-features.h> 时,会导致:

$ make -f GNUmakefile-cross
arm-linux-androideabi-g++ -DNDEBUG -g2 -O3 -fPIC -pipe -march=armv5te -mtune=xscale -mthumb -msoft-float
-funwind-tables -fexceptions -frtti -DANDROID --sysroot=/opt/android-ndk/platforms/android-21/arch-arm
-Wa,--noexecstack -I/opt/android-ndk/sources/cxx-stl/gnu-libstdc++/4.9/include
-I/opt/android-ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include -c cpu.cpp
In file included from cpu.cpp:26:0:
/opt/android-ndk/platforms/android-21/arch-arm/usr/include/machine/cpu-features.h:52:6: error:
 #    error Unknown or unsupported ARM architecture
      ^
cpu.cpp: In function 'bool CryptoPP::CPU_QueryNEON()':
cpu.cpp:402:29: error: 'android_getCpuFeatures' was not declared in this scope
  if (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)
                             ^
cpu.cpp:402:33: error: 'ANDROID_CPU_ARM_FEATURE_NEON' was not declared in this scope
  if (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON)
                                 ^
make: *** [cpu.o] Error 1

我们使用的CXXFLAGS 直接来自我几年前创建的一个 JNI 项目。我使用ndk-build 检查了Android 构建系统设置的标志,然后将它们转移到我们的脚本中。我们不是在编造它们;它们是官方的 NDK 编译器选项。

当我cat 标头cpu-features.h 时,我看到了一个不祥之兆:

/* __ARM_ARCH__ is a number corresponding to the ARM revision
 * we're going to support. Our toolchain doesn't define __ARM_ARCH__
 * so try to guess it.
 */
#ifndef __ARM_ARCH__
#  if defined __ARM_ARCH_7__   || defined __ARM_ARCH_7A__ || \
        defined __ARM_ARCH_7R__  || defined __ARM_ARCH_7M__
#    define __ARM_ARCH__ 7
#  elif defined __ARM_ARCH_6__   || defined __ARM_ARCH_6J__ || \
        defined __ARM_ARCH_6K__  || defined __ARM_ARCH_6Z__ || \
        defined __ARM_ARCH_6KZ__ || defined __ARM_ARCH_6T2__
#    define __ARM_ARCH__ 6
#  else
#    error Unknown or unsupported ARM architecture
#  endif
#endif

我们似乎在流程和实施过程中遗漏了一些东西。首先,所有需要的定义都由预处理器提供(见下文)。预处理器提供__ARM_ARCH,但Android 的标头会检查__ARM_ARCH__

其次,<machine/cpu-features.h> 似乎没有包含所需的声明:

$ cat /opt/android-ndk/platforms/android-21/arch-arm/usr/include/machine/cpu-features.h | grep -i android_getCpuFeatures
$

我们不使用 Android 的构建系统,所以这很少适用:The cpufeatures Library。它也太高了,缺少我们需要的一些细节。

我的问题是,我们如何在常规原生库中使用 cpu 功能?第一个和第二个问题我们缺少什么?


我们的脚本集CXXCXXFLAGS 等。一旦获取脚本,它们就可以使用。在这种情况下:

$ echo $CXX
arm-linux-androideabi-g++

还有:

$ $CXX -dM -E - </dev/null | sort
#define __ACCUM_EPSILON__ 0x1P-15K
#define __ACCUM_FBIT__ 15
#define __ACCUM_IBIT__ 16
#define __ACCUM_MAX__ 0X7FFFFFFFP-15K
#define __ACCUM_MIN__ (-0X1P15K-0X1P15K)
#define __ANDROID__ 1
#define __APCS_32__ 1
#define __arm__ 1
#define __ARM_32BIT_STATE 1
#define __ARM_ARCH 5
#define __ARM_ARCH_5TE__ 1
#define __ARM_ARCH_ISA_ARM 1
#define __ARM_ARCH_ISA_THUMB 1
#define __ARM_EABI__ 1
#define __ARMEL__ 1
#define __ARM_FEATURE_CLZ 1
#define __ARM_FEATURE_DSP 1
#define __ARM_FEATURE_QBIT 1
#define __ARM_FP 12
#define __ARM_NEON_FP 4
#define __ARM_PCS 1
#define __ARM_SIZEOF_MINIMAL_ENUM 4
#define __ARM_SIZEOF_WCHAR_T 4
#define __ATOMIC_ACQ_REL 4
#define __ATOMIC_ACQUIRE 2
#define __ATOMIC_CONSUME 1
#define __ATOMIC_RELAXED 0
#define __ATOMIC_RELEASE 3
#define __ATOMIC_SEQ_CST 5
#define __BIGGEST_ALIGNMENT__ 8
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
...

似乎没有声明或定义任何 cpu 功能:

$ echo $AOSP_SYSROOT
/opt/android-ndk/platforms/android-21/arch-arm
$ grep -IR android_getCpuFeatures $AOSP_SYSROOT
$ grep -IR ANDROID_CPU_ARM_FEATURE_NEON $AOSP_SYSROOT
$

【问题讨论】:

标签: android android-ndk shared-libraries cpu


【解决方案1】:

该库不是作为 NDK 的一部分预构建的,而是作为源代码提供的。使用ndk-build构建时,可以通过引用自动构建该库,但使用外部构建系统时,需要确保自己包含并构建。

来源位于android-ndk/sources/android/cpufeatures,您会在其中找到不同的cpu-features.h。 (为了找到你找到的那个,你可能包含了machine/cpu-features.h,这是完全不同的事情。)

因此,您需要在构建过程中包含来自android-ndk/sources/android/cpufeaturescpu-features.h 和构建cpu-features.c。或者,如果您要生成静态库,也可以针对此标头构建代码,并记录库的用户在生成最终共享库时需要包含 cpufeatures 库。

【讨论】:

  • 谢谢@mstorsjo。关于不正确使用定义的任何想法?由于 Android 使用了错误的预处理器宏,我们是否需要定义一些东西?
  • 我看不出有什么问题。您不小心尝试包含的标头在任何情况下都不应该包含。
  • 由于 Android 的 f::k'd 目录布局和源文件位置,我们正在捕获更多相关错误。我希望他们能从他们的 a$$ 中抽出头来并使用 --sysroot 他们在过去 20 年左右一直使用它的方式。他们需要停止制造 s::t 在他们前进的过程中。顺便说一句,我们没有意外地包含任何东西。我们所做的一切都是有原因的。这里的问题似乎是 AOSP 在 SYSROOT 或路径上留下了损坏的 &lt;cpu-features.h&gt;
  • SYSROOT 中没有损坏的&lt;cpu-features.h&gt;&lt;ndk&gt;/platforms/android-XX/arch-XX/usr/include/machine 中有一个。当我尝试使用您引用的确切命令行构建一个包含&lt;cpu-features.h&gt; 的虚拟cpp 文件时,它找不到来自.../usr/include/machine 的另一个标头,因此您的首要任务是弄清楚是什么使它从machine 子目录,默认情况下绝对不应该查看它。
猜你喜欢
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多