前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >minigui:静态编译连接mgncs库时遇到的xml2的问题

minigui:静态编译连接mgncs库时遇到的xml2的问题

作者头像
10km
发布2019-05-25 20:54:56
1.7K0
发布2019-05-25 20:54:56
举报
文章被收录于专栏:10km的专栏10km的专栏10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433476

最近做一个基于minigui/mgncs的项目,在开发阶段因为是在ubuntu下基于minigui的模拟器开发,所以编译时都是标准的动态库连接。没啥问题,很顺序。

现在项目功能开发告一段落,要向嵌入式平台移植了,就要把编译改为全静态连接(--static)。问题就来了。

编译正常,连接时报了如下一大堆错误:

/usr/lib/x86_64-linux-gnu/libxml2.a(nanohttp.o): In function `xmlNanoHTTPConnectHost':
(.text+0x924): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/x86_64-linux-gnu/libxml2.a(nanohttp.o): In function `xmlNanoHTTPConnectHost':
(.text+0x9f4): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/x86_64-linux-gnu/libxml2.a(xpath.o): In function `xmlXPathCastNumberToString':
(.text+0xa3d7): undefined reference to `log10'
/usr/lib/x86_64-linux-gnu/libxml2.a(xmlschemastypes.o): In function `xmlSchemaGetCanonValue':
(.text+0xb84e): undefined reference to `trunc'
/usr/lib/x86_64-linux-gnu/libxml2.a(xmlschemastypes.o): In function `xmlSchemaGetCanonValue':
(.text+0xb89a): undefined reference to `trunc'
/usr/lib/x86_64-linux-gnu/libxml2.a(xzlib.o): In function `xz_head':
(.text+0x69e): undefined reference to `lzma_auto_decoder'
/usr/lib/x86_64-linux-gnu/libxml2.a(xzlib.o): In function `xz_head':
(.text+0x76e): undefined reference to `lzma_properties_decode'
/usr/lib/x86_64-linux-gnu/libxml2.a(xzlib.o): In function `xz_decomp':
(.text+0x11a0): undefined reference to `lzma_code'
/usr/lib/x86_64-linux-gnu/libxml2.a(xzlib.o): In function `__libxml2_xzclose':
(.text+0x1f95): undefined reference to `lzma_end'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `openIcuConverter':
(.text+0x104b): undefined reference to `ucnv_open_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `openIcuConverter':
(.text+0x1077): undefined reference to `UCNV_FROM_U_CALLBACK_STOP_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `openIcuConverter':
(.text+0x107c): undefined reference to `ucnv_setFromUCallBack_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `openIcuConverter':
(.text+0x109b): undefined reference to `ucnv_open_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `openIcuConverter':
(.text+0x10b7): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `openIcuConverter':
(.text+0x10eb): undefined reference to `UCNV_TO_U_CALLBACK_STOP_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `openIcuConverter':
(.text+0x10f0): undefined reference to `ucnv_setToUCallBack_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `closeIcuConverter':
(.text+0x111d): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `closeIcuConverter':
(.text+0x1126): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlFindCharEncodingHandler':
(.text+0x2793): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlFindCharEncodingHandler':
(.text+0x279d): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlFindCharEncodingHandler':
(.text+0x27b3): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o):(.text+0x27bc): more undefined references to `ucnv_close_55' follow
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncFirstLineInt':
(.text+0x2f6e): undefined reference to `ucnv_convertEx_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncFirstLine':
(.text+0x3270): undefined reference to `ucnv_convertEx_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncFirstLineInput':
(.text+0x365a): undefined reference to `ucnv_convertEx_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncInput':
(.text+0x3a47): undefined reference to `ucnv_convertEx_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncInFunc':
(.text+0x3de7): undefined reference to `ucnv_convertEx_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o):(.text+0x4197): more undefined references to `ucnv_convertEx_55' follow
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncCloseFunc':
(.text+0x4bb0): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncCloseFunc':
(.text+0x4bba): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncCloseFunc':
(.text+0x4bdd): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlCharEncCloseFunc':
(.text+0x4be7): undefined reference to `ucnv_close_55'
/usr/lib/x86_64-linux-gnu/libxml2.a(encoding.o): In function `xmlByteConsumed':
(.text+0x4f2d): undefined reference to `ucnv_convertEx_55'
collect2: error: ld returned 1 exit status

可以发现,问题都来自于mgncs依赖的xml2这个库。分析问题原因花了好长时间,找到原因倒是很简单:

xml2这个库其实还依赖其他的库

用ldd命令查看libxml2.so的依赖库:

$ ldd /usr/lib/x86_64-linux-gnu/libxml2.so
	linux-vdso.so.1 =>  (0x00007ffd7fbaa000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ffb86d88000)
	libicuuc.so.55 => /usr/lib/x86_64-linux-gnu/libicuuc.so.55 (0x00007ffb869f4000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007ffb867da000)
	liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007ffb865b8000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ffb862af000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffb85ee5000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ffb87347000)
	libicudata.so.55 => /usr/lib/x86_64-linux-gnu/libicudata.so.55 (0x00007ffb8442e000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ffb840ac000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ffb83e96000)

所以虽然连接动态库时很简单,只需要加上-lxml2就可以了,但在静态连接时,就要把xml2所依赖的所有库都要加上,用pkg-config命令就可以查看xml2静态连接和动态连接所需要的参数,如下

# 动态库连接只需要-lxml2
$ pkg-config --libs libxml-2.0
-lxml2
# 静态库连接则需要一堆的库
$ pkg-config --static --libs libxml-2.0
-lxml2 -licui18n -licuuc -licudata -lz -llzma -lm

于是我按照上面pkg-config命令的输出加上静态连接相应的参数,再次编译,这下总该没事了吧?

然而又是一堆连接错误,如下

/usr/lib/x86_64-linux-gnu/libxml2.a(threads.o): In function `xmlRMutexLock':
(.text+0x1ff): undefined reference to `pthread_cond_wait'
/usr/lib/x86_64-linux-gnu/libxml2.a(threads.o): In function `xmlRMutexUnlock':
(.text+0x285): undefined reference to `pthread_cond_signal'
/usr/lib/x86_64-linux-gnu/libxml2.a(threads.o): In function `xmlIsMainThread':
(.text+0x4a8): undefined reference to `pthread_cond_wait'
/usr/lib/x86_64-linux-gnu/libxml2.a(threads.o): In function `xmlIsMainThread':
(.text+0x4d1): undefined reference to `pthread_cond_signal'
/usr/lib/x86_64-linux-gnu/libxml2.a(threads.o): In function `xmlInitThreads':
(.text+0x5e0): undefined reference to `pthread_cond_wait'
/usr/lib/x86_64-linux-gnu/libxml2.a(threads.o): In function `xmlInitThreads':
(.text+0x609): undefined reference to `pthread_cond_signal'
/usr/lib/x86_64-linux-gnu/libicuuc.a(putil.ao): In function `uprv_dl_open_55':
(.text+0x18c2): undefined reference to `dlopen'
/usr/lib/x86_64-linux-gnu/libicuuc.a(putil.ao): In function `uprv_dlsym_func_55':
(.text+0x190d): undefined reference to `dlsym'
/usr/lib/x86_64-linux-gnu/libicuuc.a(putil.ao): In function `uprv_dl_close_55':
(.text+0x18f1): undefined reference to `dlclose'
/usr/lib/x86_64-linux-gnu/libicuuc.a(umutex.ao): In function `icu_55::umtx_initImplPreInit(icu_55::UInitOnce&)':
(.text+0xaf): undefined reference to `pthread_cond_wait'
/usr/lib/x86_64-linux-gnu/libicuuc.a(umutex.ao): In function `icu_55::umtx_initImplPostInit(icu_55::UInitOnce&)':
(.text+0x10e): undefined reference to `pthread_cond_broadcast'
/usr/lib/x86_64-linux-gnu/libicuuc.a(umutex.ao): In function `umtx_condWait_55':
(.text+0x4f): undefined reference to `pthread_cond_wait'
/usr/lib/x86_64-linux-gnu/libicuuc.a(umutex.ao): In function `umtx_condBroadcast_55':
(.text+0x61): undefined reference to `pthread_cond_broadcast'
/usr/lib/x86_64-linux-gnu/libicuuc.a(umutex.ao): In function `umtx_condSignal_55':
(.text+0x71): undefined reference to `pthread_cond_signal'

可以看出原来的问题解决了,但是新问题来了,不过这次的问题倒简单,一看就明白,就是找不到pthread,dl这两个库(pthread_开头的引用都是pthread相关函数,dl开头的函数dlopen,dlclose都是dl库的函数)

其实前面用ldd命令查看libxml2.so的依赖库时,就显示有dl库。但不知道为什么没有显示pthread库。

于是再为xml2库加上-lpthread -ldl就可以编译通过了(-lpthread -ldl的先后顺序没有关系)

下面就是静态连接xml2的完整连接参数:

-lxml2 -licui18n -licuuc -licudata -lz -llzma -lm -lpthread -ldl
# 实际测试没有-licui18n也是可以连接通过的

你真的需要xml2码?

编译通过之后,满心欢喜,顺序查看了一下编译后的executable文件大小,吓我一大跳:44MB!!!

立即就崩溃了,目标平台上内存才32MB,这么大的可执行文件没法用呐。项目中用到的这么多连接库,到底哪个是最大的呢?幸运的是很快就找到了最大的连接库,就是-licudata

$ ll -h /usr/lib/x86_64-linux-gnu/libicudata.so.55.1 
-rw-r--r-- 1 root root 25M 3月  27  2018 /usr/lib/x86_64-linux-gnu/libicudata.so.55.1

ICU 是开源项目, 提供了最新的unicode标准,字符集转换, 以及超过300个国家的本地数据, 比如数字,时间和信息显示格式等,以及不同语言下的文本排序,日历相关的日期时间操作等。

详细内容可以访问: http://userguide.icu-project.org/

这个libicudata.so.55.1动态库就是ICU库用到的数据。

是不是可以通过自己编译减小icudata的大小?

如何编译ICU?

这又是一个要好一阵折腾的事儿,头大了。

这样被一个又一个出现的问题牵着鼻子走,何时是个头呢?

我打算跳出这个工作思路。

回头看mgncs的编译脚本,在${libmgncs-1.2.0}/configure.ac中找到下面的代码。

原来可以通过--enable-dbxml命令行参数控制是否使用xml2 !

AC_ARG_ENABLE(dbxml,
[ --enable-dbxml    enable libxml2 datasource support <default=yes>],
build_datasource_xml=$enableval)

if test "x$build_datasource_xml" = "xyes"; then
    AC_CHECK_LIB(xml2, xmlFree,
        DEP_LIBS="$DEP_LIBS -lxml2",
        build_datasource_xml=no)
fi

if test "x$build_datasource_xml" = "xyes"; then
    AC_DEFINE(_MGNCSDB_DATASOURCE, 1,
        [Define if support datasource])
    AC_DEFINE(_MGNCSDB_XML, 1,
		[Define if support xml datasource])
    CPPFLAGS="$CPPFLAGS -I/usr/include/libxml2"
fi

进一步查看_MGNCSDB_XML_MGNCSDB_DATASOURCE宏定义所涉及的代码,就搞明白了如果在mgncs中禁用xml2,就会禁用mxmlds.h这个接口文件定义的所有功能。

mxmlds.h会不会被应用项目用到呢?

mxmlds.h用于读写xml文件,MiniStudio中生成的资源文件就是xml格式,所以这个模块应该就是用于读写xml格式的资源文件,而在程序编译运行的时候,资源文件已经编译成.res的二进制文件了不再需要xml解析。

事实上,mgncs根本没有把这个mxmlds.h文件release出来,只是mgncs内部配合MiniStudio时使用的,所以编译目标平台的mgncs库时禁用它完全没问题。

于是如下在编译mgncs时加上--enable-dbxml=no,重新编译mgncs。

./configure \
	--host=$host \
	--prefix=$sh_folder/release/$mgncs_folder/$host \
	--enable-develmode 	\
	--enable-dbxml=no \
	MINIGUI_CFLAGS="-I$sh_folder/release/$minigui_folder/$host/include" \
	MGUTILS_CFLAGS="-I$sh_folder/release/$mgutils_folder/$host/include" \
	MINIGUI_LIBS="-L$sh_folder/release/$minigui_folder/$host/lib -l:libminigui_ths.a -ljpeg -lpng -lm -lfreetype -lz -lpng12 -lfreetype -lpthread" \
	MGUTILS_LIBS="-L$sh_folder/release/$mgutils_folder/$host/lib -l:libmgutils.a -ljpeg -lpng -lm -lfreetype -lz -lpng12 -lfreetype -lpthread" \
	MGPLUS_CFLAGS="-I$sh_folder/release/$mgplus_folder/$host/include" \
	MGPLUS_LIBS="-L$sh_folder/release/$mgplus_folder/$host/lib -l:libmgplus.a -lfreetype -lpthread -lstdc++" \
	|| exit -1

make -j8  || exit -1
make install

编译通过后再ldd查看libmgncs.so的信赖库,已经没有xml2了。

$ ldd release/libmgncs-1.2.0/x86_64-linux-gnu/lib/libmgncs-1.2.so.0
	linux-vdso.so.1 =>  (0x00007fff449c2000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe8e8a22000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe8e8719000)
	libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007fe8e846f000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe8e8252000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe8e803c000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe8e7c72000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fe8e9305000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fe8e7a58000)
	libpng12.so.0 => /lib/x86_64-linux-gnu/libpng12.so.0 (0x00007fe8e7833000)

再用没有了xml2依赖的mgncs库作项目的静态编译。executable文件的体积变成了17MB,再经过strip后,只剩下8MB.虽然还是偏大,但这是Debug版,还没有优化,这个体积算是正常啦。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年10月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 你真的需要xml2码?
    • mxmlds.h会不会被应用项目用到呢?
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档