首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

cmake:动态链接库(so)中静态链接tcmalloc(gperftools2.4)暨静态链接libstdc++

将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参数,对工程实施人员的要求比较高。

01
您找到你想要的搜索结果了吗?
是的
没有找到

CMake vs Make对比

程序员现在已经使用了CMake和Make了很久。当您加入大公司或开始使用大型代码库开发项目时,您需要处理所有这些构建。你必须看到这些“CMakeLists.txt”文件浮动。你应该在终端上运行“cmake”和“make”命令。很多人只是盲目地按照指示,不是真的关心为什么我们需要以某种方式做事情。这个整个构建过程是什么,为什么它这样构造?CMake和Make之间有什么区别?有关系吗?可以互换吗? 事实证明,它们是完全不同的。了解他们之间的区别是非常重要的,以确保您不会陷入困境。在分析之前,先看看它们是什么。 make 我们设计软件系统的方式是我们首先编写代码,然后编译器编译并创建可执行文件。这些可执行文件是执行实际任务的可执行文件。“Make”是从程序的源文件中控制程序的可执行文件和其他非源文件的生成工具。 “Make”工具需要知道如何构建程序。它了解如何从名为“makefile”的文件构建程序。这个makefile列出了每个非源文件以及如何从其他文件中计算它。编写程序时,应该为其编写一个makefile,以便可以使用“Make”来构建和安装程序。简单的东西!如果您不明白,请再次阅读该段落,因为下一部分重要。 为什么我们需要“Make”? 我们需要“Make”的原因是因为它使最终用户能够构建和安装您的软件包,而无需了解其操作的详细信息。每个项目都有自己的规则和细微差别,每当你有一个新的合作者,它都会变得非常痛苦。这就是我们有这个makefile的原因。构建过程的细节实际上记录在您提供的makefile中。根据哪些源文件已更改,“自动”自动显示需要更新的文件。它还自动确定更新文件的正确顺序,以防一个非源文件依赖于另一个非源文件。 每当我们改变系统的一小部分时,重新编译整个程序将是低效的。因此,如果您更改了一些源文件,然后运行“Make”,它不会重新编译整个事情。它仅更新直接或间接依赖于您更改的源文件的那些非源文件。很整洁!“Make”不限于任何特定语言。对于程序中的每个非源文件,makefile指定了用于计算它的shell命令。这些shell命令可以运行一个编译器来产生一个对象文件,链接器生成一个可执行文件,以便更新一个库,Makeinfo格式化文档等。“Make”不仅限于构建一个包。您还可以使用“Make”来控制安装或卸载软件包,为其生成标签表, CMake的 CMake代表跨平台制作。CMake识别哪个编译器用于给定类型的源。如果您不知道,您不能使用相同的编译器来构建所有不同类型的源。您可以在每次建立项目时手动执行,但这将是乏味和痛苦的。CMake为每种类型的目标调用正确的命令序列。因此,没有明确指定像$(CC)这样的命令。 为了编码真正想要血液细节的垃圾,请继续阅读。如果你不是所有的,你可以跳到下一节。处理包含头文件,库等的所有常见的编译器/链接器标记都被平台独立的和构建系统无关的命令所取代。调试标志包括将变量CMAKE_BUILD_TYPE设置为“调试”,或者在调用程序时将其传递给CMake: cmake -DCMAKE_BUILD_TYPE:STRING =调试。 CMake还提供平台独立包含'-fPIC'标志(通过POSITION_INDEPENDENT_CODE属性)和许多其他。尽管如此,还可以通过CMake以及Makefile(通过使用COMPILE_FLAGS和类似属性)手动实现更为模糊的设置。当然,当第三方库(如OpenGL)以便携式的方式被包含时,CMake真的开始闪耀。 有什么不同? 如果您使用Makefile,即在命令行中键入“make”,则构建过程有一个步骤。对于CMake,有两个步骤:首先,您需要设置构建环境(通过在构建目录中键入cmake <source_dir>或运行某些GUI客户端)。根据您选择的构建系统(例如,在Windows上的Make on * nix,VC ++或MinGW等),这将创建一个makefile或相当的东西。构建系统可以作为参数传递给CMake。但是,CMake根据您的系统配置做出合理的默认选项。其次,您在选定的构建系统中执行实际构建。 我们将在这里跳入GNU构建系统领域。如果你不熟悉,这一段可能看起来像是jibber-jabber给你。好的,现在我给了法定的警告,我们继续吧!我们可以比较CMake和Autotools。当我们这样做时,我们可以看到Make的缺点,它们构成了Autotools创建的原因。我们还可以看到CMake对Make的明显优势。Autoconf解决了一个重要的问题,即可靠地发现系统特定的构建和运行时信息。但这只是便携式软件开发中的一小部分。为此,GNU项目开发了一套集成的实用工具来完成Autoconf开始的工作:GNU构建系统,其最重要的组件是Autoconf,Automake和Libtool。 “做”不能这样做,至少没

03

automake编译和安装方式说明

作为良好的习惯,建议为第三方库建立专门的目录,目录取名为thirdparty。然后,再在thirdparty下建立名叫src_package,用来存放第三方库的源码包,如没有特别说明,第三方库默认均为automake编译和安装方式。并且,一般建议将第三方库安装在thirdparty目录下,而不是系统的/usr/local目录下,目的是尽量减少对系统目录的污染,保持系统目录的整洁。 【automake编译和安装方式说明】 通常Linux系统自带automake编译工具,C/C++开源库一般都采用automake编译。 假设源代码库文件名为protobuf-2.4.1.tar.gz,则编译和安装操作步骤如下: 1) 将源代码包文件protobuf-2.4.1.tar.gz上传到Linux机上,这里假设上传到Linux机的/tmp目录 2) 进入/tmp目录 3) 解压源代码包文件:tar xzf protobuf-2.4.1.tar.gz,完成后会在/tmp目录下会出现一个子目录protobuf-2.4.1 4) 进入/tmp的子目录子目录protobuf-2.4.1 5) 执行configure命令,以生成Makefile文件:./configure --prefix=/usr/local/protobuf-2.4.1,这里假设将Protocol Buffers安装到/usr/local/protobuf-2.4.1 6) 上一步会生成编译用的Makefile文件,接下来执行make编译:make 7) make成功后,再执行make install安装 8) 成功后,就可以ls /usr/local/protobuf-2.4.1查看安装结果了; 9) 建立不带版本号的软链接:ln -s /usr/local/protobuf-2.4.1 /usr/local/protobuf 【automake编译和安装方式补充说明】 a) 源代码包如果是protobuf-2.4.1.tar.bz2形式,则表示是bzip2压缩包,而protobuf-2.4.1.tar.gz是gzip压缩包,对于bzip2压缩包,tar解压参数请由xzf改成xjf b) 上述第9步不是必须的,但会是一个良好的Linux风俗,建议保持 c) 注意第5步,如果生成的静态库会被其它共享库使用,则可能需要为configure增加参数,否则在链接生成共享库时,可能会报被链接的静态库需要带-fPIC参数重新编译,这个问题不难解决,如下变通一下即可: ./configure --prefix=/usr/local/protobuf-2.4.1 CXXFLAGS=-fPIC LDFLAGS=-fPIC d) 开源的C/C++库源代码包文件一般都采用类似于protobuf-2.4.1.tar.gz的命名方式 【推荐的编译环境目录结构】 假设有一项目mooon,它的目录结构如下,和SVN目录结构保持一致,但SVN上不存放中间目录和文件,mooon本身可以基于用户主目录,或者其它合适的目录,如/data目录下: mooon |-- doc |-- src `-- thirdparty     |-- apr-util     |-- boost     |-- gflags     |-- protobuf     |-- sqlite     |-- src_package     |   |-- apr-util-1.5.1.tar.gz     |   |-- boost_1_53_0.tar.gz     |   |-- cgicc-3.2.10.tar.gz     |   |-- gflags-2.0.tar.gz     |   |-- protobuf-2.4.1.tar.gz     |   |-- sqlite-autoconf-3071401.tar.gz     |   `-- thrift-0.9.0.tar.gz     `-- thrift 安装openssl:  # ./config --prefix=/usr/local/thirdparty/openssl-1.0.2a shared threads 安装httpd(apache),支持https:  # ./configure --with-apr=/usr/local/thirdparty/apr-1.4.6 --with-apr-util=/usr/local/thirdparty/apr-util-1.5.1 --with-ssl=/usr/local/thirdparty/openssl-1.0.2a --with-pcre=/usr/local/thirdpar

03

企业应用架构的基本模式之插件模式

当应用程序代码需要在多个环境运行,且每个环境对特定行为需要不同的实现时,通常会使用分离接口模式。大多数开发通过编写一个工厂方法来在不同的环境下生成相应的实现。假定通过分离接口来定义你的主键生成器,以便你可以使用一个简单的内存计数器来进行单元测试,而在真实环境由数据库管理的序列。你的工厂方法很可能包含一条判断语句,这一语句检查一个局部环境变量以确定系统是否处于测试模式,并返回正确的结果。当你有数个工厂以后,你的手头会变得一团糟。建立一个新的部署配置需要在多个工厂中修改条件语句,然后重新编译和部署。配置工作不应当如此分散在整个应用程序当中,也不应当重新编译和部署。插件模式通过集中化的、运行时配置的方法解决了这些问题。

01
领券