在android工具链上编译C ++标准库

时间:2012-06-11 22:41:39

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

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

知道为什么吗?

2 个答案:

答案 0 :(得分:6)

在“Standalone Toolchain”下查看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文档。

答案 1 :(得分:2)

NDK文档并不完全准确,至少目前不是。实际上,它说明了使用预构建的工具链时#34;您无法使用任何C ++ STL(STLport或GNU libstdc ++)。#34;,但这已经过时了。我使用包含相同错误的include创建了一个小的hello world程序。它可以在不创建自己的工具链的情况下解决,如果您不想再为配置过程添加一个步骤并且允许您始终使用最新的SDK平台而不必每次都创建新的工具链,那么这很好。

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

要在其安装位置使用独立工具链,您可以执行以下操作: 导出CXX =&#39; $ NDK_ROOT / toolchains / arm-linux-androideabi-4.8 / prebuilt / darwin-x86_64 / bin / arm-linux-androideabi -g ++ --sysroot =&#34; $ NDK_ROOT / platforms / android- 19 /拱形臂&#34;&#39;

例如,这会将您的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

为了摆脱处理共享库路径的麻烦,您还可以通过更改&#34; -lstlport_shared&#34;来静态链接C ++库。到&#34; -lstlport_static&#34;。如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 - 显示对象的信息