Android 系统编译与调试

Android 系统编译与调试[原创]

Android 编译

   Android 编译系统(详见附件),在阅读本文时可以先阅读附件,我是读了好多遍,并加于实践,才能比较深刻理解编译系统工作原理以及如何编译生成image文件。我觉得理解一个平台,首要先弄清一个平台的编译系统,一方面可以解决编译问题,另一方面可以了解系统的文件编译顺序,对于解决运行时碰到问题有帮助。

   我这边着要介绍我们可能涉及到的Android.mk写法.

1.       从编译helloworld 说起

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
 LOCAL_SRC_FILES:= /
        com_ura_test_JNITest.c
 LOCAL_C_INCLUDES := /
        $(JNI_H_INCLUDE)
 LOCAL_SHARED_LIBRARIES := libutils
 LOCAL_PRELINK_MODULE := false
 LOCAL_MODULE := libJNITest
 include $(BUILD_SHARED_LIBRARY)

      

LOCAL_PATH - 编译时的目录

$(call 目录,目录….) 目录引入操作符

如该目录下有个文件夹名称Src,则可以这样写 $(call src)

 

CLEAR_VARS –

build/core/config.mk 定义 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk

       详细看build/core/clear_vars.mk

      Include *.mk 文件的运算符。可以通过include 包含自定义的.mk文件(即是自定义编译规则)或是引用系统其他的.mk文件(系统定义的编译规则)。

  

LOCAL_SRC_FILES - 编译的源文件

可以是.c, .cpp, .java, .S(汇编文件)或是.aidl等格式

写法是不同的文件用空格隔开。如果编译目录子目录,采用相对路径,如子目录/文件名。也可以通过$(call 目录),指明编译某目录下所有.c/.cpp/.java/.S/ .aidl文件.

追加文件 LOCAL_SRC_FILES += 文件

 

LOCAL_C_INCLUDES - 需要包含的头文件目录

     可以是系统定义路径,也可以是相对路径. 如该编译目录下有个include目录,写法是include/*.h

 

LOCAL_SHARED_LIBRARIES - 链接时需要的外部共享库

   还有链接的外部静态库用LOCAL_STATIC_LIBRARY

如果是java文件,要加入jar包用LOCAL_JAVA_LIBRARIES

 

LOCAL_PRELINK_MODULE 是否需要prelink处理 .Prelink利用事先链接代替运行时链接的方法来加速共享库的加载,它不仅可以加快起动速度,还可以减少部分内存开销,是各种Linux架构上用于减少程序加载时间、缩短系统启动时间和加快应用程序启动的很受欢迎的一个工具.

 

LOCAL_MODULE 编译的目标对象

module 是指系统的native code ,相对用Java 写成的 Android  application 称为packagePackageLOCAL_PACKAGE_NAME.

 

BUILD_SHARED_LIBRARY 指明要编译成动态库。

编译的目标,用include 操作符,动态库会用到系统的编译脚本host_share_library.mk 编译静态库目标,会用到系统的编译脚本host_static_library.mk . BUILD_STATIC_LIBRARY来指明要编译成静态库。如果是java文件的话,会用到系统的编译脚本host_java_library.mk,用BUILD_PACKAGE来指明。三个编译脚本都放到build/core目录下。

 

LOCAL_ARM_MODE := arm

目前Android大部分都是基于Arm处理器的,Arm指令用两种模式Thumb(每条指令两个字节)arm指令(每条指令四个字节)

 

LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays

通过设定编译器操作,优化级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高

   

Android.mk 也通过ifeq关键字支持条件选择语句,类如下面

ifeq ($(HOST_OS),linux)

# Use the futex based mutex and condition variable

# implementation from android-arm because it's shared mem safe

  LOCAL_SRC_FILES += /

         futex_synchro.c /

         executablepath_linux.cpp

endif

ifeq ($(HOST_OS),darwin)

  LOCAL_SRC_FILES += /

         executablepath_darwin.cpp

endif

   总结,android.mk 的写法,系统源代码提供了大量的android.mk可以作为参考资料。在编写android.mk的时候,有任何碰到疑问的地方,可以拿系统的android.mk看看, 相信写个android.mk 应该没有什么困难.

调试

       我们用Eclipse调试java程序都习以为常,这边我着重介绍如何Windows上调试android native code

1.        编译gdb for android arm platform.

具体步骤大概,下载cygwin, gdb6.8(最新gdb)源代码。将gdb 做如下配置

./configure –target=arm-linux.  就会编译生成arm-linux-gdb.exe, 能解析linux-arm调试格式。后面附件有gdb编译后生成的可执行文件。

2 编译gdbserver. 也可以不编译, 在源代码prebuild/android-arm/gdbserver上直接可以获得。

3.将gdbserver拷贝到模拟器或是机器里面(假定在/dev/sample目录下)。

adb gdberver  /dev/sample/

然后chmod 777 ./gdbserver 赋予权限

4.运行gdbserver .

./gdbserver 127.0.0.1:1234 helloworld

Process helloworld created; pid = 744

Listening on port 1234

5.为来让gdb能连接到模拟器上到gdbserver,必须进行数据转发:
telnet localhost 5554
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Android Console: type 'help' for a list of commands
OK
redir add tcp:1234:1234
OK

6 运行gdb,进行调试

D:/>arm-linux-gdb.exe

GNU gdb 6.8

Copyright (C) 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.  Type "show copying"

and "show warranty" for details.

This GDB was configured as "--host=i686-pc-cygwin --target=arm-linux".

(gdb) target remote 127.0.0.1:1234 [和模拟器的应用程序建立连接]

Remote debugging using 127.0.0.1:1234

0xb0000100 in ?? ()

(gdb) break main

No symbol table is loaded.  Use the "file" command.

(gdb) file helloworld  [加载调试信息]

A program is being debugged already.

Are you sure you want to change the file? (y or n) y

Reading symbols from /cygdrive/d/helloworld...done.

(gdb) break main

Breakpoint 1 at 0x8364: file external/helloworld/hello.c, line 4.

(gdb) c

Continuing.

 

Breakpoint 1, main () at external/helloworld/hello.c:4

4       external/helloworld/hello.c: No such file or directory. [这边需要路径映射]

        in external/helloworld/hello.c

(gdb) n

3       in external/helloworld/hello.c

(gdb) c

Continuing.

Program exited normally.

调试这边还有很多需要讲,比如调试信息位置,如何在eclipe调试native code(c++/c文件) 如何查看二进制文件, 调试技巧等等。 写起来可能要很多了,怕大家没有耐心看下去, 先点到为止。这次创新文档已经写了很多,调试的深入研究会在后续文档里面提到。

 

附件

 


 

 

 

你可能感兴趣的:(Android 系统编译与调试)