上篇提到的都是使用现有的ndk-build建立共享库。如何建立可执行的C/C++文件?将jni/Android.mk内的

include $(BUILD_SHARED_LIBRARY) 改成include $(BUILD_EXECUTABLE) 即可。那么,想“自由使用”工具链,比如 直接使用gcc/g++那样,尤其是想往Android上面移植 C/C++程序或者库时,如何才能跳出ndk-build的限制?

  I.提取Android的gcc工具链

     如果你想偷懒的话,你很幸运,有现成的 ,附件的perl脚本agcc(csdn搞不出附件,只好链接新帖子 ) ,即可以完成工具链的抽取和封装,可以像使用 gcc 那样使用它,它最先来自

plausible.org/andy/agcc

    不过这个是面对整个Android开发包的(包括Android/SDK/NDK的所有文件),而且没有C++/STL支持,我对它进行了修改,使它与上篇给出的ndk-r4配合,完全支持c/c++。

     如果你想自己动手,请这样做:

1.分别对

1)生成可执行文件

2)静态库

3) 动态库

4)多个源文件 的不同类型的工程使用

#ndk-build -B V=1

命令,会让ndk-build “揭露出”整个工具链的不同使用过程 ,比如上篇中的helloworld工程:

显示:

Compile thumb  : helloworld <= /opt/android/android-ndk-r4c/samples/helloworld/jni/helloworld.c
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-gcc -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__  -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64  -I/opt/android/android-ndk-r4c/samples/helloworld/jni -DANDROID  -Wa,--noexecstack -O2 -DNDEBUG -g  -c -MMD -MP -MF /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o.d /opt/android/android-ndk-r4c/samples/helloworld/jni/helloworld.c -o /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o
SharedLibrary  : libhelloworld.so
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-gcc -nostdlib -Wl,-soname,libhelloworld.so -Wl,-shared,-Bsymbolic  /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o -Wl,--whole-archive  -Wl,--no-whole-archive  /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a  /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libc.so /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libm.so    -Wl,--no-undefined -Wl,-z,noexecstack  -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a -o /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/libhelloworld.so

......


从这些命令记录分别提取出

1)工具的名称和位置

例如gcc/g++工具是 arm-eabi-gcc/g++,位置是 /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/。。

2)工具相关选项和参数

交叉编译时,最重要的就是编译工具的相关参数设置,以及从环境中提取的文件(头文件夹,链接文件,库文件..)。下面的从上面提取的相关参数就不用我解释了吧?(如果不熟悉这些的话,真的不应该直接从Android上手学交叉编译,道理你们懂的。。)

CC = arm-eabi-gcc

CFLAGS/CXXFLAGS ="-fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums  -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64"

CPPFLAGS ="-I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -I/opt/android/android-ndk-r4c/samples/helloworld/jni -DANDROID "

CXX =arm-eabi-g++

LDFLAGS = "-nostdlib -Wl,-soname,libhelloworld.so -Wl,-shared,-Bsymbolic  -Wl,--whole-archive  -Wl,--no-whole-archive  /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a  /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libc.so /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libm.so    -Wl,--no-undefined -Wl,-z,noexecstack  -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a"

3)工具的使用过程

  主要是面对不同的源文件(.c/.cpp/.o/.h...),以及不同的目标(生成什么?.o/.exe/.s...),工具的使用过程和参数都是不同的,比如上例:

.c-->.o

$CC $CPPFLAGS $CFLAGS helloworld.c -c -g -o helloworld.o

仅仅 预处理-->编译,未链接

然后

.o-->.so

$CC $LDFLAGS helloworld.o -o libhelloworld.so

完成链接

4)大家可以查看其他几类情况,使用的工具和参数各不相同。


II.直接使用工具链

  提取出了工具链,弄清其不同参数和工作流程后,就可以自己指明使用了。首先将工具加入$PATH,然后,例如编译如下的两个全面测试C++功能的.cpp文件,要求ahoo.cpp -->libahoo.so(动态库);a.cpp+libahoo.so --->a(程序):

ahoo.h

#include #include #include #include void ahoo(char** ); class A { public: A(); ~A(); }; class B:public A { public: B(); ~B(); }; 

ahoo.cpp

#include"ahoo.h" int hana; A::A(){printf("ahoooooooooo coming!/n");} A::~A(){printf("ahoooooooooo dying!/n");} void ahoo(char** a) { hana = 100; printf("sizeof hana:%d/n",hana); *a=(char*) malloc(256); memset(*a,0,256); std::string s = "Hello from JNI !"; try { if (std::getenv("NON_EXISTENT_ENVIRONMENT_VARIABLE") == NULL) throw std::runtime_error("libahoo.so:--exception.runtime_error.string:/t--琉球の海風にいる !"); } catch (std::exception &ex) { s = ex.what(); s = s+"/nlibahoo.so:--exception.catch.string:/t--You are Foooooooooyoooooooed!/n"; } strcpy(*a,s.c_str()); }

a.cpp

#include "ahoo.h" #include"pthread.h" B::B(){printf("bagaaaaaaaaa coming!/n");} B::~B(){printf("bagaaaaaaaaa dying!/n");} template class C { public: T a; T b; C(T fa,T fb):a(fa),b(fb){printf("%s/n%s/n",a.c_str(),b.c_str());} }; typedef void* (*thread_main_t)(void*); extern int hana; int main() { pthread_t thread; char* ah =NULL; B* pb=new B; delete pb; C c("Horaaaaaaaaaaa","Woraaaaaaaaaaaa"); pthread_create(&thread,NULL,(thread_main_t)&ahoo,(void*)&ah); pthread_join(thread,NULL); printf("sizeof hana:%d/n",hana); if(ah) { printf("%s",ah); free(ah); } std::string str="づっと、づっと乙女の側に居るように!/n"; printf("a/t:--string:/t--%s/n",str.c_str()); return 0; }

命令就是:(都是先编译,再链接,注意参数的区别)

1)ahoo.cpp--->ahoo.o a.cpp-->a.o

arm-eabi-g++ ahoo.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o ahoo.o

 

arm-eabi-g++ a.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o a.o


2) ahoo.o -->libahoo.so

arm-eabi-gcc ahoo.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a -o libahoo.so

 

3) a.o -->a

arm-eabi-gcc a.o -nostdlib -Bdynamic -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/crtend_android.o /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/crtbegin_dynamic.o -o a -lahoo -L./

  你是什么感觉呢,不觉得太长太麻烦了吗?何苦呢?何必呢?所以我才将所有的内容都封装在agcc 内的啊,你难道不想也这样做吗?(尤其是对程序或者库进行 ./configure 的时候!),上面的例子,直接用我的agcc 的话(先将包含arm-eabi-*的路径加入$PATH

#agcc ahoo.cpp -shared -o libahoo.so

Compile Thumb++    :ahoo.cpp    ===> ahoo.o

...

Link ARM shared lib    : ahoo.o     ====> libahoo.so

...

#agcc a.cpp -o a -lahoo -L./

Compile Thumb++    :a.cpp    ===> a.o

....

Link ARM executable    : a.o     ====> a

...

# file a
a: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
#file libahoo.so
libahoo.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped

#arm-eabi-readelf -d a
Dynamic section at offset 0x132cc contains 23 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]
 0x00000001 (NEEDED)                     Shared library: [libahoo.so]
 0x00000020 (PREINIT_ARRAY)              0x1c2a4
 0x00000021 (PREINIT_ARRAYSZ)            0x8

.................

搞定!现在你也可以从自己的NDK出发提取组合自己的工具链了吧!

 

更多相关文章

  1. Android中如何使用JUnit进行单元测试
  2. afinal logoAndroid的快速开发框架 afinal
  3. How to create and use SDCard image for Android(安卓)emulator
  4. Android中Tomcat的简单配置和使用
  5. android内所使用的资源类型
  6. iPhone和Android,谁将成为赢家?
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. Zend数据库适配器-未捕获异常-堆栈跟踪显
  2. PHP中使用sleep函数实现定时任务实例分享
  3. PHP脚本在我的Wordpress文件中。请解码或
  4. 微信JS-SDK——微信分享给朋友
  5. 一个简易的PHP读取CSV文件的方法
  6. php is_dir 判断是否存在这目录
  7. php使用openssl进行Rsa长数据加密(117)解
  8. php和apache的关系和作用()
  9. php中static 静态变量和普通变量的区别
  10. 解析错误:语法错误,第12行/home/public_htm