3

我有一个非常简单的 helloworld.cpp 程序

#include <iostream>
using namespace std;
int main ()
{
  cout << "Hello World!";
  return 0;
}

我正在尝试使用工具链中的交叉编译器为 android x86 编译它:

/Users/me/android-ndk-r8/toolchains/x86-4.4.3/prebuilt/darwin-x86/bin/i686-android-linux-g++ helloworld.cpp -L "/Users/me/android-ndk-r8/sources/cxx-stl/stlport/libs/x86/" -lstlport_static

但是,我收到错误:

helloworld.cpp:2:20: error: iostream: No such file or directory

知道为什么吗?

4

3 回答 3

7

检查 NDK 中包含的 documentation.html 文件,位于“独立工具链”下。它说如果您以这种方式调用编译器,您将无法“使用任何 C++ STL”。但是,正如文档所解释的那样,如果您首先使用以下命令创建“自定义”工具链安装,则它是可能的:

$NDK/build/tools/make-standalone-toolchain.sh --platform=android-8 --install-dir=/tmp/my-android-toolchain --arch=x86

其中 $NDK 是 NDK 目录的路径。注意 --arch=x86 这意味着工具链是专门为 x86 Android 准备的。这会在一个目录中准备好您需要的内容,包括 STL 标头和文件夹。然后,您应该能够使用 -lstdc++ 链接到 STL(静态版本),例如:

/tmp/my-android-toolchain/bin/i686-android-linux-g++ helloworld.cpp -lstdc++

如需更完整的说明,请参阅 NDK 文档。

于 2012-06-13T02:08:32.807 回答
2

NDK 文档并不完全准确,至少目前不准确。事实上,它在使用预构建工具链时声明“您将无法使用任何 C++ STL(STLport 或 GNU libstdc++)。”,但这已经过时了。我使用包含相同的错误创建了一个小型 hello world 程序。但是,无需创建自己的工具链即可解决此问题,如果您不想在配置过程中再添加一个步骤,并且允许您始终使用最新的 SDK 平台,而无需每次都创建新的工具链,那就太好了。

NDK 附带了几个版本的标准 C++ 库的源代码:GAbi++、STLport 和 GNU STL。每种风格都带有预构建的共享库和静态库。我下面的示例将使用 stlport。

要在其安装位置使用独立工具链,您可以执行以下操作:export CXX='$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi- g++ --sysroot="$NDK_ROOT/platforms/android-19/arch-arm"'

例如,这会将您的 CXX 编译器设置为使用 SDK 平台级别 19 在 OS X 系统上编译 ARM。您可能已经知道这一点。此外,如果您使用它,您可能希望导出您的 CC、CPP、LD、AR 和 RANLIB。我还亲自为 READELF 创建了一个 envar。

要添加对 C++ 库的支持,您可以执行以下操作: $CXX helloworld.cpp -I$NDK_ROOT/sources/cxx-stl/stlport/stlport -L$NDK_ROOT/sources/cxx-stl/stlport/libs/armeabi - lstlport_shared

请注意,这将链接 libstlport_shared.so 现在在运行时需要它,因此您可能需要向上述命令添加相对路径以支持该路径,具体取决于您的 APK 结构。如果您只想测试这个简单的案例,您可以在模拟器上运行它,如下所示:

adb push a.out /data
adb push $NDK_ROOT/sources/cxx-stl/stlport/libs/armeabi/libstlport_shared.so /data
adb shell
# su
# cd /data
# chmod 777 a.out
# ./a.out

为了摆脱处理共享库路径的麻烦,您还可以通过将“-lstlport_shared”更改为“-lstlport_static”来静态链接 C++ 库。这样做会产生一些后果,如 NDK 开发指南中所述。最大的问题是由于静态库在多个位置链接,导致: - 在一个库中分配的内存并在另一个库中释放会泄漏甚至损坏堆。- 在 libfoo.so 中引发的异常不能在 libbar.so 中捕获(并且可能会简单地使程序崩溃)。- std::cout 的缓冲不能正常工作

还包括一个有用的工具,即 readelf 工具,可以查看您的程序具有哪些依赖项。

要查看您的程序需要哪些其他共享库,您可以运行以下命令: $NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-readelf -a a.out | 需要 grep

其他很酷的标准工具: addr2line - 将堆栈跟踪地址转换为代码行 nm - 显示符号表 objdump - 显示对象的信息

于 2014-01-03T16:24:41.437 回答
-1

我从 gnustl 调用其中一个函数,在它从预建的 aosp arm-linux-androideabi-gcc --std=c++11 运行良好并且在崩溃错误之后我无法从日志或原因中获得回溯,我希望转向交叉构建qemu-linux-user 在 arm 上运行主机编译的 i686 二进制文件,困难在于与来自 adt 的跨主机库交互总是在平台特定库以外的任何其他库上崩溃,除非内核模块打包更新是可能的......

于 2021-10-05T18:44:44.173 回答