cmake:gperftools性能分析工具find libprofiler 脚本暨profiler的静态连接问题
gperftools是一个很好用的性能分析工具,但没有提供官方的用于查找profiler库的cmake脚本,所以在基于cmake管理的项目中如果要在系统查找libprofiler库就就要自己写FindPROFILER.cmake脚本。
将脚本所在的文件夹加入CMAKE_MODULE_PATH,调用find_package(PROFILER),就会找到系统中安装的gperftools的libprofiler库,
脚本不仅按传统方式输出LIBPROFILER_xxx系列变量,还会创建gperftools::profiler INTERFACE target.方便在项目中引用。
FindPROFILER.cmake
# - Find libprofiler
# - This module determines the libprofiler library of the system
# the vairable can be set
# LIBPROFILER_STATIC_LINK set true for static link library 为TRUE是要求静态连接
# The following variables are set if the library found:
# LIBPROFILER_FOUND - If false do nnt try to use libprofiler.
# LIBPROFILER_INCLUDE_DIRS - where to find the headfile of library.include文件夹位置
# LIBPROFILER_LIBRARY_DIRS - where to find the libprofiler library.profiler库所在位置
# LIBPROFILER_LIBRARIES, the library file name needed to use libprofiler.profiler库及所有依赖库列表
# LIBPROFILER_LIBRARY - the library needed to use libprofiler. profiler库全路径
# imported target
# gperftools::profilerif(LIBPROFILER_FOUND)return()
endif()
include (depcommon)
# linux系统下调用pkg-config查找profiler
if (NOT WIN32)include(FindPkgConfig)unset(_verexp)if(LIBPROFILER_FIND_VERSION)if(LIBPROFILER_FIND_VERSION_EXACT) set(_verexp "=${LIBPROFILER_FIND_VERSION}")else()set(_verexp ">=${LIBPROFILER_FIND_VERSION}")endif()endif()pkg_check_modules (LIBPROFILER libprofiler${_verexp})
endif()if (NOT LIBPROFILER_FOUND)# windows系统下通过查找头文件 gperftools/profiler.h和find_library 查找profiler来实现# find the headfile of libraryset (PROFILER_HEADS gperftools/profiler.h)find_path (LIBPROFILER_INCLUDE_DIRS ${PROFILER_HEADS})set (PROFILER_NAMES ${PROFILER_NAMES} profiler)find_library (LIBPROFILER_LIBRARY NAMES ${PROFILER_NAMES})# just find one of dependency, guess other one.if (NOT LIBPROFILER_LIBRARY AND LIBPROFILER_INCLUDE_DIRS)message ("We just find the headfile, try to guess the library location.")set (LIBPROFILER_LIBRARY_DIRS "${LIBPROFILER_INCLUDE_DIRS}/../lib")find_library (LIBPROFILER_LIBRARY NAMES ${PROFILER_NAMES} PATHS ${LIBPROFILER_LIBRARY_DIRS})elseif (NOT LIBPROFILER_INCLUDE_DIRS AND LIBPROFILER_LIBRARY)message ("We just find the lib file, try to guess the include location.")get_filename_component(LIBPROFILER_LIBRARY_DIRS ${LIBPROFILER_LIBRARY} DIRECTORY)find_path (LIBPROFILER_INCLUDE_DIRS ${PROFILER_HEADS} "${LIBPROFILER_LIBRARY_DIRS}../included")endif()# find the library.if (LIBPROFILER_INCLUDE_DIRS AND LIBPROFILER_LIBRARY)if (NOT LIBPROFILER_LIBRARY_DIRS) get_filename_component(LIBPROFILER_LIBRARY_DIRS ${LIBPROFILER_LIBRARY} DIRECTORY)endif ()list(APPEND profiler pthread)endif()
else ()list(GET MGNCS_LIBRARIES 0 _name)find_library (LIBPROFILER_LIBRARY NAMES ${LIBPROFILER_LIBRARIES} PATHS ${LIBPROFILER_LIBRARY_DIRS})
endif()
# handle the QUIETLY and REQUIRED arguments and set LIBPROFILER_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBPROFILER DEFAULT_MSG LIBPROFILER_LIBRARIES LIBPROFILER_INCLUDE_DIRS)if(LIBPROFILER_FOUND)set(_static_libname libtcmalloc_and_profiler.a)find_library (LIBPROFILER_STATIC_LIBRARY NAMES ${_static_libname} PATHS ${LIBPROFILER_LIBRARY_DIRS})if(NOT LIBPROFILER_FIND_QUIETLY)message(STATUS " -I: ${LIBPROFILER_INCLUDE_DIRS}")message(STATUS " -L: ${LIBPROFILER_LIBRARY_DIRS}")message(STATUS " -l: ${LIBPROFILER_LIBRARIES}")endif()find_library (LIBPROFILER_LIBRARY NAMES ${LIBPROFILER_LIBRARIES} PATHS ${LIBPROFILER_LIBRARY_DIRS})# create imported targetif (NOT TARGET gperftools::profiler)add_library(gperftools::profiler INTERFACE IMPORTED)if(LIBPROFILER_STATIC_LINK)# for linking static profiler,must use libtcmalloc_and_profiler.a,see also README gperftoolsset(_link_libs ${LIBPROFILER_STATIC_LDFLAGS})if(NOT LIBPROFILER_STATIC_LIBRARY)message(FATAL_ERROR "NOT FOUND static library for profiler:${_static_libname} ")endif()# 替换 profiler 为 :libtcmalloc_and_profiler.astring(REPLACE profiler :${_static_libname} _link_libs "${_link_libs}")else()set(_link_libs ${LIBPROFILER_LDFLAGS})endif()set_target_properties(gperftools::profiler PROPERTIESINTERFACE_COMPILE_OPTIONS "${LIBPROFILER_CFLAGS_OTHER}"INTERFACE_INCLUDE_DIRECTORIES "${LIBPROFILER_INCLUDE_DIRS}"INTERFACE_LINK_LIBRARIES "${_link_libs}")if(NOT LIBPROFILER_FIND_QUIETLY)message(STATUS "IMPORTED TARGET: gperftools::profiler,link libraies ${_link_libs}")endif()endif ()endif(LIBPROFILER_FOUND)
静态连接profiler
关于静态连接profiler,之前看过不少博客文章,都指出gperftools不支持静态连接profiler库。但我查看了gperftools(2.7)的官方说明,提供了静态连接profiler库的方法:
下面的英文说明来自gperftools的官方说明(https://github.com/gperftools/gperftools/blob/master/README)
EVERYTHING IN ONE
-----------------
If you want the CPU profiler, heap profiler, and heap leak-checker to
all be available for your application, you can do:gcc -o myapp ... -lprofiler -ltcmallocHowever, if you have a reason to use the static versions of the
library, this two-library linking won't work:gcc -o myapp ... /usr/lib/libprofiler.a /usr/lib/libtcmalloc.a # errors!Instead, use the special libtcmalloc_and_profiler library, which we
make for just this purpose:gcc -o myapp ... /usr/lib/libtcmalloc_and_profiler.a
确实直接静态连接libprofiler.a是不行的,但这里也明确给出了静态连接profiler的方式:用libtcmalloc_and_profiler.a替代libprofiler.a。
所以在上面的cmake脚本中当LIBPROFILER_STATIC_LINK 为TRUE时,会替换 profiler 为 :libtcmalloc_and_profiler.a
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
