Library record crop: Crop a dynamic library

1. What is a library?

I believe that many have told me the same white, with a certain amount of experience in application development, the library concept more or less have some of their own understanding, but at some point if the library was asked who in the end is what when, perhaps also like me, half past one would not know. Excerpt from Wikipedia here a description of the library, I feel very clear exposition of the concept of a computer in the library science: "In computer science, library (English: library) is used to develop the software of routine collection and library. difference executable file that libraries are not independent of the computer program, the code they provide services to other programs . " [ 1 ]

Practical applications, in turn based on the library link in different ways, the library will be further divided into static library (Statically-linked library) and DLL (Dynamic-linked library). Here, the library link refers to the library included in the program. Link library is divided into static linking and dynamic linking . Static link is a link in the linker library was added to the contents of the executable program, the corresponding static library; dynamic linking means when the executable is loaded or run a program, the library is loaded by the operating system loader, the corresponding dynamic library [ 1 ] .

Static library has the advantage that when you publish a binary library file is not required to consider whether there is a problem and the version on the user's computer, and avoid DLL hell problem; but at the same time, the resulting executable file larger, more system resources, when loaded into memory will consume more time [ 2 ] .

Is different from the static library, dynamic link provides a modular shared libraries to ensure multiple programs at the same time a subroutine call, do not need to copy multiple copies of the same code, thus saving required by the application disk and memory space. But at the same time, there will be a dynamic library DLL hell problem, the so-called DLL hell, referring to the multiple applications at the same time using a shared dynamic library, version conflicts occur, resulting in some applications can not execute [ 3 ] .

2. What is the library crop?

As the name suggests, the library that is cut by cutting redundant code in the project file and linked files, in order to achieve the purpose of reducing the size of the compiled library. Document [ 4 ] systematically summarizes several ways of cutting the library, including: (1) delete redundant files, are: assistance programs, configuration files, data templates and unnecessary comment content; (2) a shared library crop, To delete a shared library that is always less than the redundant code; (3) use of alternative packages have the same functionality but take up less space; (4) modify the source code, are: re-configure, compile the package, get rid of unwanted increasing the functional modules of the software, in order to improve cutting efficiency; reconfigure the cores to remove unwanted modules and drivers.

Many libraries cutting application scenarios, such as when we develop software, citing a standard library or library system, but not all of the functions we have used, you can modify the compiler options (such as text [ 5 ] in Qt library mentioned cutting) or modifying the source code (e.g., text [ . 6 ] mentioned cutting libiconv library) for cutting library.

In addition to cutting the library can reduce the size of compiled libraries outside, but also effectively reduce compile time, increase development efficiency, and, after cutting the library can improve operational efficiency, reduce the volume and reduce software costs software release.

3. Engineering Practice record

The current project group is developing projects, mainly based on existing code, according to user needs, reconstruction generates new independent library files available to users. This development model is common in engineering, it can save costs and improve development efficiency. In practice, such a development process, in order to strictly balance user needs and development costs, the need to develop new functions on the basis of the old code, but also delete the old code does not need to function. This development practices at some stage on the need for libraries cut, depending on the user platform, the way of cutting the library will vary, but in essence are deleted or quarantined by independent code, compile and link cancel unnecessary files, in order to achieve the library crop. This is my main tasks this week, mainly based on customer demand, were cut out of the library windows, android, ios mac and four platforms.

(1) windows platform

windows platform library crop is easier to achieve. Because the code used in the branch where otherwise stable release version is being used, in order not to affect the stability of the release version, not directly remove extraneous code. You can add your solution to compile a separate project to generate libraries we need, and the project file configuration properties, properties need to focus on include: Additional Include Directories, preprocessor definitions, additional dependencies, these attributes CI position shown in FIGS. 1 to 3.

Include files

                                                                                                     figure 1

Precompiled header

                                                                                                     figure 2

Additional Dependencies

                                                                                                     image 3

其中,附加包含目录应删除工程不需要依赖的头文件所在的目录,预处理器定义中添加宏定义,该宏定义作用域为当前工程,可以实现在该工程中隔离不需要代码的目的。具体实现可按照下面的方式进行:

// 隔离的宏定义为IS_NEED_ISOLATION

#ifndef IS_NEED_ISOLATION
    {
        code block;    // 稳定发布版本需要但新开发项目不需要的代码块
    }
#endif

附加依赖项中删除项目工程文件不再依赖的静态库文件。除了修改工程属性并在代码中添加隔离宏外,由于部分不需要的代码是直接以文件的形式提供的,还需要在工程目录中删除这些不需要的文件,具体操作如图4所示。

                                                                                                     图 4

在完成了以上工作后,还有最后一步:即修改编译脚本文件。windows平台下的编译脚本一般以cmake文件提供,可以直接拷贝原来的release版本编译脚本并修改文件名为old_name_win_isolation.cmake(此处old_name_win代指原来的文件名),并且,编辑脚本文件中的内容,删除不再需要编译的部分。这样可以有效减少编译发布版本的时间。

(2)android平台

android平台库裁剪也包括无关代码的隔离和无关代码文件的删除。隔离代码通过.bat文件和Application.mk组合实现,比如:首先,在.bat文件中定义了一个变量IS_ISOLATION,并将其值置为true,这个变量作用于.bat文件调用到的所有.mk文件。然后,在Application.mk文件中,根据变量IS_ISOLATION的值,判断是否需要在APP_CFLAGS项添加宏定义IS_NEED_ISOLATION,这个宏定义作用于工程目录下的所有.c文件。(如果项目源文件是用C++编写的,则使用APP_CPPFLAGS)。无关代码文件的删除主要通过在Android.mk文件中隔离不需要的源文件名称来实现。

android平台库裁剪花费了很多时间,耗时的点主要在于:1)安卓编译脚本运行依赖环境搭建更为复杂;2)安卓编译脚本包括old_name_and.bat、Application.mk和Android.mk三类文件,这三者之间的关系没有第一时间厘清;3)安卓裁剪后的库需要借助android studio来验证,而android studio的环境搭建最为复杂。

首先,安卓编译脚本运行依赖环境包括三方面:cygwin、ndk和android sdk,三者缺一不可。cygwin是在windows下模拟unix环境的工具集,其中包括的动态库文件cywin1.dll是编译安卓库文件不可或缺的,这个文件的主要作用是模拟linux下的API,在编译的过程中,如果C/C++ 调用了linux中的API,cygwin就会利用cygwin1.dll 来编译 C/C++源代码,从而可以在windows下生成linux下的lib...so文件[7] 。ndk是一个官方的安卓工具集,能够让开发者以本地平台支持的编程语言(比如C/C++)开发部分安卓应用程序功能代码[8],可以理解为是安卓官方提供的一种跨平台开发的支持。ndk编译命令在检测到所编写代码为本地编程语言开发时,会自动构建并生成二进制文件。android sdk是安卓应用程序开发时必须依赖的官方工具集,使用它可以将由Kotlin、Java或C++编写的应用程序编译成.apk文件[9]

其次,编译安卓库时需要运行.bat文件,其中通过调用ndk_build.cmd文件实现编译。需要说明的是,每次调用ndk_build.cmd后,Application.mk和Android.mk文件会依次运行。起初我对这种运行机制并不清楚,在发现编译脚本.bat文件中定义的变量没有作用到所有.mk文件后,在所有脚本中都加了日志打印,才推理出这种运行机制。由于这种运行机制,在每次调用ndk_build.cmd文件时,必须先对变量IS_ISOLATION进行赋值,然后再执行ndk命令,比如:

call path_of_ndk_cmd\ndk_build.cmd IS_ISOLATION=true clean

Application.mk文件中声明了一些工程范围内的配置,这些配置内容一般包括:应用程序二进制文件接口(Application Binary Interface, ABI,提供了一种系统级的编程约定)、工具链(编译C/C++程序的编译工具)、编译模式(debug或release)和STL。这些配置内容可以通过已定义的宏变量实现,比如:可以通过配置APP_CFLAGS的值,创建应用于当前工程所有.c文件的宏IS_NEED_ISOLATION:[10]

APP_CFLAGS += -DIS_NEED_ISOLATION

Android.mk文件主要包含了本地库文件、定义了作用于当前文件夹下所有文件的宏变量和通过"JNI"目录编译的所有头文件[11]

最后,验证平台android studio在安装完成之后,需要配置代理设置,否则由于公司内网不能连接到相关网站,导致部分jar包无法下载,就会出现安卓工程编译不过的问题。这块主要通过软件cntlm绕过公司的代理,连接到了相关网站,具体细节就不赘述了。

(3) ios和mac平台

这里把ios和mac平台放在一起,主要是因为二者的库都是由.xcode工程编译出来的,二者的库裁剪步骤也是完全相同的。以ios平台为例,库裁剪主要包括无关代码的隔离和无关代码文件的删除,以及编译脚本中代码的修改,这块和windows平台相似,即在项目文件目录下,把原来生成动态库的.xcodeprj文件拷贝一份并重命名后,再通过xcode打开该工程文件,在build_settting选项的preprocessor_macro栏添加宏定义IS_NEED_ISOLATION,这样,工程中的所有无关代码都可以通过宏IS_NEED_ISOLATION实现隔离。并且,删除掉库依赖栏中不再依赖的库文件。最后,在xcode左侧的工程目录下,删除无关代码文件的依赖和不再依赖的库工程文件。在终端执行下面的命令,即可编译生成裁剪后的库文件:

cd path_of_ios_build_script
./old_name_ios_isolation.sh

4. 总结

库裁剪是软件开发过程中不可避免的一个过程,涉及的面比较广,既要求开发者对代码十分熟悉,又要求开发者掌握一定的运维知识,体现了开发者的综合能力。自以为这方面掌握的知识还有所欠缺,具体体现在应用于各平台的库文件生成原理,包括编译、链接和装载的具体原理,这方面的知识仍有待加强。希望通过后续静态库裁剪对这些内容有更深刻的理解。

refs: 

[1] https://zh.wikipedia.org/wiki/%E5%87%BD%E5%BC%8F%E5%BA%AB

[2] https://zh.wikipedia.org/wiki/%E9%9D%99%E6%80%81%E5%BA%93

[3] https://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E9%93%BE%E6%8E%A5%E5%BA%93

[4] http://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=9653

[5] http://blog.chinaunix.net/uid-25765968-id-359557.html

[6] https://blog.csdn.net/mayue_web/article/details/100108034

[7] https://www.cnblogs.com/xiaoxuetu/p/3467613.html

[8] https://developer.android.com/ndk

[9] https://developer.android.com/guide/components/fundamentals

[10] https://developer.android.google.cn/ndk/guides/application_mk.html

[11] https://developer.android.google.cn/ndk/guides/concepts

Guess you like

Origin www.cnblogs.com/niceland/p/0x0008.html