【问题标题】:Compiling against C++ standard libraries on the android toolchain针对 android 工具链上的 C++ 标准库进行编译
【发布时间】:2012-06-14 20:26:30
【问题描述】:

我有一个非常简单的 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

知道为什么吗?

【问题讨论】:

  • 我已经编辑了您的问题,因为这不是关联问题。
  • 听起来您还需要设置包含路径。此外,另一种构建 android 项目的方式,ndk-build 是首选和更好的支持。
  • 如何设置包含路径?
  • This question 应该可以帮助您理解和设置包含路径。您需要指定iostream 头文件的位置。

标签: android c++ stl android-ndk g++


【解决方案1】:

检查 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 文档。

【讨论】:

    【解决方案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 - 显示对象的信息

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我建议删除这个答案。请下次尝试以建设性的方式回答
      猜你喜欢
      • 2013-10-21
      • 1970-01-01
      • 2016-03-16
      • 2013-03-07
      • 2020-07-24
      • 2020-02-15
      • 1970-01-01
      • 2016-12-30
      • 2013-04-04
      相关资源
      最近更新 更多