如何移植library到android(三)

上一篇只是谈到了大方向。有些具体的东西还是没有讲清楚,这次专门讲讲 android ndk .
先看看 android ndk 的目录 layout 大概长的怎么样 .
root
  |------ apps , 所有你要编译的 C c ++ code 都放到这个目录下。
  |------ build
  |        |---- platforms 下面目前为止放了 3 sub fold , 里面分别放了 android 需要的 include , library( 提供的 library 有限)
  |                |------ android 3 代表 android 1.5
  |                |------ android 4 代表 android 1.6
  |                |------ android 5 代表 android 2.0
  |        |---- prebuilt 该目录下存放 toolchain 的可执行档案 , 以及 include & library . 对于 arm - eabi - 4.4 . 0 了解不多 .
  |                |------ arm - eabi - 4.2 . 1
  |                          |------------ bin 所有的 toolchain excute file
  |                          |------------ arm - eabi
  |                                          |------ include
  |                                          |------ lib
  |        |---- tools 这个目录下存放了很多有用的工具,包括下载, build toolchain
  |------ docs 必须仔细读的文档
  |------ out 生成的所有临时文件

先从 docs 开始谈,这个也是非常重要的一步。
1. 纠正 Android - mk . txt 中写的 ndk 只能编译出 static library shared library , 实际上他还提供了命令编译可执行程序 .
   a . include $( BUILD_SHARED_LIBRARY)
   b . include $( BUILD_STATIC_LIBRARY)
   c . include $( BUILD_EXECUTABLE)
   理论上能编译出 so 文件,当然能编译出 execute 文件 . 只是 ndk 是否提供这个接口。
2. apps 目录下,新建一个目录 , 再建立 project 目录 , 这一级目录下建立 Application . mk , 再建立一个 sub fold jni , jni 里面放的都是 c c ++ 源代码 , 还有 Android . mk . Android . mk 就必须仔细写了 .
   常用的有 LOCAL_PATH := $( call my - dir) //访问当前path下的所有子目录,
       < 1 >. LOCAL_DEBUG := no| yes
       < 2 >. LOCAL_OS := linux  //目标平台
       < 3 >. LOCAL_ARCH := arm   //目标平台cpu
       < 4 >. LOCAL_ARM_MODE := arm  //CPU指令集
        < 5 >. COMMON_DEFINES += ISP = isp_arm9 - D_ARM_ //这里通常会把要移植的library中的各种flag写在这里.(从待移植中的Configure或者Makefile中拷贝过来)
       < 6 >. ifeq( $( DEBUG ), no)
             COMMON_FLAGS += -s - O2 - fno - strict - aliasing - DNDEBUG - fno - rtti //好像都采用O2优化,fno-rtti 告诉C++不要runtime 中的一些support.
       < 7 >. COMMON_COMPILE_FLAGS += - fPIC  += - msoft - float += march = armv5t
         
    相对应的有了 COMMON_XXX 就有了 LOCAL_XXX ,
    我们可以定义相关的
        < 1 >. LOCAL_MODULE := libxxx  //定义要编译的moule        
       < 2 >. LOCAL_CFLAGS := - I $( LOCAL_PATH )/ xxx / include 以及局部 FLAG( Configure 或者 Makefile 中拷贝过来) //定义search .h fold
       < 3 >. LOCAL_CXXFILES := //和上面是相同的,只是这个是C++的,上面的是C
       < 4 >. LOCAL_SRC_FILES := XXX . c XXX . cpp XXX . hpp    //定义源代码         
       < 5 >. include $( BUILD_STATIC_LIBRARY) 定义该模块是静态的
    要编译到 android 上运行的 excutable , 还会依赖
        < 1 >. LOCAL_LDLIBS := - L library_path - lxx //定义库的路径,以及要的library, 这里其实用的都是动态库.
        android , 有一个参数是: - dynamic - linker ,/ system / bin / linker , 采用的不是标准的 linux 下的 ld . so . 6( 好像是这个数字,具体的不清楚了) , 而是 / system / bin / linker 来链接 . 这也是为什么我们用其他编译器(比如 codesourcery )编译出来的东西不能在 android 上直接跑的原因,而一定要加上 - static 参数,也就是说用 codesourcery 编译出来的东西必须不依赖 android 的调度,而是靠编译时把所有的库全部加入 . 所以这时候写出来的 helloworld 都可能会有 1 ~ 2 Mb . 提到了 liner , 就不得不提到 android bionic , 这个 C runtime library 设计并不是功能特别强大 , 并且有些 gnu glic 中的函数没有实现 , 这是移植时会碰到的问题 . 而且 , 这个 C runtime library 也并没有采用 crt0 . o , crt1 . o , crti . o crtn . o , crtbegin . o crtend . o , 而是采用了 android 自己的 crtBegin_dynamic . o , crtBegin_static . o crtEnd_android . o crt1 . o crt0 . o 的后续演进版本 , crt1 . o 中会非常重要的 . init 段和 . fini 段以及 _start 函数的入口 .. init 段和 . fini 段实际上是靠 crti . o 以及 crtn . o 来实现的 . init 段是 main 函数之前的初始化工作代码 , 比如全局变量的构造 . fini 段则负责 main 函数之后的清理工作 . crti . o crtn . o 是负责 C 的初始化 , C ++ 则必须依赖 crtbegin . o crtend . o 来帮助实现 .
        So , 在标准的 linux 平台下 , link 的顺序是 : ld crt1 . o crti . o [ user_objects ] [ system_libraries ] crtn . o
        而在 android , link 的顺序是 : arm - eabi - g ++ crtBegin_dynamic . o [ user_objects ] [ system_libraries ] crtEnd_android . o
        所以这就是从另一个方面说明为什么不适合 codesourcery 之类编译来开发 android 底层东西的原因了 , 这里我不包括BSP 之类 .
       < 2 >. LOCAL_STATIC_LIBRARIES := //excute file 依赖的库
        < 3 >. include $( BUILD_EXCUTEABLE)
在谈谈 platform 目录下的东西 , 这里面要说的是可能 include library 中包含的头文件和 library 文件不太够 , 我们可以使用 busybox for android 把我们要的资料都给 pull 出来 . 或者编译 android 源代码 , 需要的都东西都会有 .
prebuilt 目录下 , 有我们编译器的可执行文件 , 但是很不幸 android toolchain 不支持 STL . 目前支持 STL 有两种方法 :
  1. 使用 STLPort( 据说这种方式不是太好)
  2. 重新编译使 android toolchain 支持 STL .
关于如何使 android toolchain 支持 STL , 我后续在谈 .

你可能感兴趣的:(如何移植library到android(三))