Android 编译静态链接的可执行文件

Android 编译静态链接的可执行文件

在Android 开发与调试过程中往往遇到以下两种场景,导致我们编译的可执行程序无法运行:

  • 不支持动态链接,比如系统初始化进程init和Recovery模式下执行的recovery,它们在执行的时候,往往不会挂载/system分区,不存在ld和ldd.so等动态加载工具和C库,这样的可执行程序往往需要静态链接。
  • 一些辅助测试的工具程序。比如busybox等,如果是动态链接的话,依赖的库的接口如有变化,往往会导致程序无法执行。一般都是静态链接,一次编译后,可以随时执行。

    那么在Android 中如何编译一个静态链接的可执行程序呢?
    其实非常简单,我们仿照源码中的bootable/recovery/Android.mk,简化出如下的编译模板:

LOCAL_PATH := $(call my-dir)
#复位编译参数
include $(CLEAR_VARS)
#指定模块名
LOCAL_MODULE := module_name
#标志该模块需要强制静态链接
LOCAL_FORCE_STATIC_EXECUTABLE := true
#指定额外的编译、链接参数
LOCAL_CFLAGS += 
#编译源文件列表
LOCAL_SRC_FILES :=
#该模块需要链接的静态库列表,这里千万别忘记需要静态链接libc  
LOCAL_STATIC_LIBRARIES := libc \
            ....
#编译成可执行文件 
include $(BUILD_EXECUTABLE)

其中核心的就两句:
LOCAL_FORCE_STATIC_EXECUTABLE := true 表明该模块需要静态链接
LOCAL_STATIC_LIBRARIES := 给出该模块需要链接的静态库列表。

编译指令还是include $(BUILD_EXECUTABLE)

如何判断一个可执行程序是动态链接还是静态编译的呢?可以通过file指令。
如下图,recoery是静态链接的(statically linked).

david@david-Macmini:~/work-dir/android601_r46/out/target/product/mini-emulator-x86/root$ file init
init: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), statically linked, BuildID[md5/uuid]=02402d7e0969337b0240427f8bbe25c0, stripped

而sh是动态链接的,使用动态库(dynamically linked (uses shared libs))。

david@david-Macmini:~/work-dir/android601_r46/out/target/product/mini-emulator-x86/system/bin$ file sh
sh: ELF 32-bit LSB  shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), BuildID[md5/uuid]=ac75e2c45ea4e5b8971720f877bc35c1, stripped

猜你喜欢

转载自blog.csdn.net/sunao2002002/article/details/51902387