上篇提到的都是使用现有的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 文件操作详解及简单实例
  2. Android下Entity封装工具类
  3. Android下 读写文件
  4. Android中经常用到的方法--SDcard下文件的操作
  5. Android 将被依赖的库项目打包成aar(非jar)文件
  6. android中实现多个apk文件
  7. Android 文件系统移植总结
  8. Android 瘦身之道 ---- so文件
  9. Android 之 向模拟器的sdcard中添加文件

随机推荐

  1. 手动部署Android-apk应用到模拟器
  2. Android音频捕获(录音)(转)
  3. android 新闻系统客户端,服务器端采用JSP
  4. Android -- Wifi启动流程分析
  5. Android中数据解析的实现
  6. 了解android应用开发的更多方面有更好的
  7. 关于解决Andorid的RecyclerView在V7包下
  8. 浅谈Android四大组件之BroadcastReceiver
  9. Android Design Support Library使用详解
  10. android之修改工程名