cmake:动态链接库(so)中静态链接tcmalloc(gperftools2.4)暨静态链接libstdc++
2016-01-04 18:28
260 查看
将tcmalloc作为动态库使用,非常方便,网上有很多资料介绍了。tcmalloc.a也可以以静态链接的方式加入应用程序中,大概因为使用太方便,网上关于这方面的介绍都是一笔带过,但是如果要在动态 库(so)中静态编译tcmalloc,却是有所不同的。
我的项目中有一个so动态库,需要在java中通过jni调用,因为涉及频繁的内存分配操作所以这个so希望用tcmalloc管理内存池以提高系统运行效率,如果使用以动态库方式使用tcmalloc。那么在应用服务器(tomcat)启动的时候,需要先设置LD_PRELOAD参数指向tcmalloc.so,然后执行startup.sh启动tomcat。这样以来,不仅是我的so库,整java程序在运行过程中的所有向操作系统申请释放内存的过程都交给了tcmalloc管理了,其实挺好的。使用这种方案,我的so库代码不需要在编译时链接tcmalloc,什么都不用改变,就能使用tcmalloc。
但是凡事有利就有弊,这个方案带的成本就是在系统安装、维护时稍显复杂:需要在服务器上安装tcmalloc和libunwind(应用系统运行在64位操作系统下),还可能需要修改tomcat启动脚本以加入LD_PRELOAD参数,对工程实施人员的要求比较高。
于是我觉得用静态链接方式将tcmalloc编译到so库中比较好,这样这个动态库以比较独立的方式发行,不再依赖系统中是否安装了tcmalloc和libunwind。应用服务器启动脚本也不需要做更多修改。
下面是我的
cmake生成的Makefile中实际的连接指令(link.txt的内容)是:
/usr/local/bin/g++ -fPIC -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free -O3 -DNDEBUG -static-libstdc++ -shared …… -pthread -Wl,-Bstatic -ltcmalloc_minimal -Wl,-Bdynamic
一切就绪,重新编译代码,然后就是报错。
大意就是需要用-fPIC参数重新编译tcmalloc,网上找了很多关于”can not be used when making a shared object; recompile with -fPIC”问题的文章(关于-fPIC参数,这个文章讲得挺详细《译与链接的问题 gcc -fPIC -shared》),解决这个问题的方法也大同小异,就是根据这个错误提示用-fPIC参数重新编译相关的库,这里是就是指要重新编译tcmalloc。
于是就用网上介绍的办法,重新编译tcmalloc,在gperftools2.4源代码目录下执行:
./configure CXXFLAGS=-fPIC
make
make install
然后再重新编译so,就通过了。
但是在动态库(so)中静态链接tcmalloc,必须要用-fPIC重新编译tcmalloc。
我的项目中有一个so动态库,需要在java中通过jni调用,因为涉及频繁的内存分配操作所以这个so希望用tcmalloc管理内存池以提高系统运行效率,如果使用以动态库方式使用tcmalloc。那么在应用服务器(tomcat)启动的时候,需要先设置LD_PRELOAD参数指向tcmalloc.so,然后执行startup.sh启动tomcat。这样以来,不仅是我的so库,整java程序在运行过程中的所有向操作系统申请释放内存的过程都交给了tcmalloc管理了,其实挺好的。使用这种方案,我的so库代码不需要在编译时链接tcmalloc,什么都不用改变,就能使用tcmalloc。
但是凡事有利就有弊,这个方案带的成本就是在系统安装、维护时稍显复杂:需要在服务器上安装tcmalloc和libunwind(应用系统运行在64位操作系统下),还可能需要修改tomcat启动脚本以加入LD_PRELOAD参数,对工程实施人员的要求比较高。
于是我觉得用静态链接方式将tcmalloc编译到so库中比较好,这样这个动态库以比较独立的方式发行,不再依赖系统中是否安装了tcmalloc和libunwind。应用服务器启动脚本也不需要做更多修改。
下面是我的
CMakeLists.txt中关于静态连接tcmalloc和libstdc++的代码。(so的代码是以C++11写的,所以还要依赖于libstdc++库,所以我打算把libstdc++库也以静态方式连接到程序中)
##判断操作系统类型 if(CMAKE_SYSTEM_NAME MATCHES "Linux") # 新版本编译器要用 -pthread 而不是 -lpthread # 否则编译时会报错找不到pthread_atfork “undefined reference to pthread_atfork” target_link_libraries(cmimpl -pthread ) #######静态链接c++库################### SET_TARGET_PROPERTIES(cmimpl PROPERTIES LINK_FLAGS "-static-libstdc++") ###这里的参数参见我的另一篇博文 [《gcc下使用tcmalloc(gperftools)2.4的注意事项》](http://blog.csdn.net/10km/article/details/50401005) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free" ) #######加入 tcmalloc 内存池支持(动态链接) ####### #target_link_libraries(cmimpl tcmalloc_minimal) #message(STATUS "tcmalloc(shared) support added") #######linux 下加入 tcmalloc 内存池支持(静态链接) ####### target_link_libraries(cmimpl tcmalloc_minimal.a) message(STATUS "tcmalloc(static) support added") endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
cmake生成的Makefile中实际的连接指令(link.txt的内容)是:
/usr/local/bin/g++ -fPIC -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free -O3 -DNDEBUG -static-libstdc++ -shared …… -pthread -Wl,-Bstatic -ltcmalloc_minimal -Wl,-Bdynamic
一切就绪,重新编译代码,然后就是报错。
/usr/local/bin/g++ -fPIC -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free -O3 -DNDEBUG -static-libstdc++ -shared -Wl,-soname,libcmimpl.so.1 -o ../lib/libcmimpl.so.1.0 CMakeFiles/cmimpl.dir/OverTableManager.cpp.o CMakeFiles/cmimpl.dir/CodeMgrUtils.cpp.o CMakeFiles/cmimpl.dir/HashMapCl.cpp.o CMakeFiles/cmimpl.dir/ICodeManager.cpp.o CMakeFiles/cmimpl.dir/ICodeManagerCPU.cpp.o CMakeFiles/cmimpl.dir/CodeManagerFactory.cpp.o CMakeFiles/cmimpl.dir/TopKCodeBean.cpp.o CMakeFiles/cmimpl.dir/RWLock.cpp.o CMakeFiles/cmimpl.dir/ThreadPool.cpp.o -lpthread -lpthread -Wl,-Bstatic -ltcmalloc_minimal -Wl,-Bdynamic /usr/bin/ld: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../libtcmalloc_minimal.a(libtcmalloc_minimal_la-tcmalloc.o): relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object; recompile with -fPIC gmake[3]: Leaving directory `/home/hadoop/workspace/codemgr.prj' /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../libtcmalloc_minimal.a: could not read symbols: Bad value
大意就是需要用-fPIC参数重新编译tcmalloc,网上找了很多关于”can not be used when making a shared object; recompile with -fPIC”问题的文章(关于-fPIC参数,这个文章讲得挺详细《译与链接的问题 gcc -fPIC -shared》),解决这个问题的方法也大同小异,就是根据这个错误提示用-fPIC参数重新编译相关的库,这里是就是指要重新编译tcmalloc。
于是就用网上介绍的办法,重新编译tcmalloc,在gperftools2.4源代码目录下执行:
./configure CXXFLAGS=-fPIC
make
make install
然后再重新编译so,就通过了。
总结
如果在可执行程序中静态链接tcmalloc时,用默认参数编译tcmalloc就好了,无需带-fPIC参数,但是在动态库(so)中静态链接tcmalloc,必须要用-fPIC重新编译tcmalloc。
相关文章推荐
- 深入探讨Linux静态库与动态库的详解(一看就懂)
- Visual Studio中根据系统区分引用64位、32位DLL动态库文件的配置方法
- (转)Linux如何解决动态库的版本控制
- cmake clion 构建cocos2dx 应用程序并编译ios mac android
- 使用CMake来构建STM32工程
- OpenCV配置,从来没有这么简单!
- linux动态库的入口和出口函数
- MySQL CMake参数说明手册
- CMake 使用方法
- 用 cmake 构建Qt工程(对比qmake进行学习)
- CMake 手册详解(一)
- 一起学习CMake – 01
- 动态库
- linux中的动态库和静态库
- 利用 CMake 和 NDK 交叉编译 Android 下的可执行程序
- MySQL 安装 CMake Error CMAKE_CXX_COMPILER not set
- MySQL5.5安装出现CMake错误找不到CMakelists.txt原因
- 关于Unix静态库和动态库的分析
- 在vc6中使用PCRE-8.33
- linux动态库