安卓系统源码编译系列(4)——LOCAL_WHOLE_STATIC_LIBRARIES和LOCAL_STATIC_LIBRARIES的区别浅析

时间:2021-07-30 00:39:41
安卓系统源码编译系列(四)——LOCAL_WHOLE_STATIC_LIBRARIES和LOCAL_STATIC_LIBRARIES的区别浅析

  当我们需要单独编译安卓系统的某个模块供应用使用时,就需要自己编写或修改Android.mk文件,下面就对Android.mk中两个容易混淆的概念(LOCAL_WHOLE_STATIC_LIBRARIES和LOCAL_STATIC_LIBRARIES)进行分析。

  先看看谷歌的官方文档:

LOCAL_STATIC_LIBRARIES

  These are the static libraries that you want to include in your module. Mostly, we use shared libraries, but there are a couple of places, like executables in sbin and host executables where we use static libraries instead.

LOCAL_WHOLE_STATIC_LIBRARIES

  These are the static libraries that you want to include in your module without allowing the linker to remove dead code from them. This is mostly useful if you want to add a static library to a shared library and have the static library's content exposed from the shared library.

从以上内容可知,LOCAL_WHOLE_STATIC_LIBRARIES会加载整个静态库,LOCAL_STATIC_LIBRARIES只是加载静态库中用到的函数。看起来它们作用只是使最终生成的库文件大小不一样而已,但是却不仅仅如此,下面我们结合一个实例来分析一下。

  现在我们需要静态编译源码中的libchromium_net库,由源码分析可知,libchromium_net需要依赖libicuuc和libicui18n,而libicui18n又会依赖libicuuc。现在我们需要将libicui18n和libicuuc静态编译到libchromium_net中,这里就存在一个嵌套编译的问题。

  如果,在libchromium_net的Android.mk文件中,我们这么加载静态库:

  LOCAL_WHOLE_STATIC_LIBRARIES += libevent modp_b64 dmg_fp libcutils LOCAL_STATIC_LIBRARIES := libicuuc libicui18n LOCAL_SHARED_LIBRARIES := libstlport libexpat libcrypto libssl libz libsqlite libcutils libdl libgabi++

这样编译就会出错,例如:

  /home/zhaoxy/develop/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../../arm-linux-androideabi/bin/ld: out/target/product/maguro/obj/STATIC_LIBRARIES/libicui18n_intermediates/libicui18n.a(ucol_elm.o): in function uprv_uca_addAnElement_48:external/icu4c/i18n/ucol_elm.cpp:1300: error: undefined reference to 'icu_48::CanonicalIterator::~CanonicalIterator()'

提示编译libicui18n时找不到libicuuc中的部分函数。但我们明明已经加载了静态库libicuuc,这是为什么呢?

  因为在Android.mk文件中,我们先引入了libicuuc,系统就引入了libicuuc中所需要的函数,然后再引入libicui18n中所需要的函数,但是系统引入的时候不会递归引入(就是引入libicui18n所需函数的同时再引入这些函数所需的函数),所以libicui18n中所包含的libicuuc并没有被引入。

  当开始编译的时候,如果libicui18n和libchromium_net所需要的libicuuc中的函数相同,就没问题。但是如果不同的话,就会提示libicuuc中部分函数找不到。

  那么如何解决这个问题呢?有以下四个方案:第一是将libicui18n和libicuuc中的函数全部加载;第二是libicuuc部分加载,静态编译了libicuuc的libicui18n全部加载;第三是libicuuc全部加载,libicui18n部分加载;第四是先加载libicui18n,再加载libicuuc,系统就会将libchromium_net和libicui18n所需libicuuc的函数一次性加载。显然第四种方案编译出来的库是最小的。

  相信通过这个实例,大家会对LOCAL_WHOLE_STATIC_LIBRARIES和LOCAL_STATIC_LIBRARIES的区别有一个基本的理解。

  如果需要更深入可以看这篇文章:LOCAL_WHOLE_STATIC_LIBRARIES与LOCAL_STATIC_LIBRARIES的区别