mirror of
https://github.com/gperftools/gperftools
synced 2024-12-22 07:20:01 +00:00
9bb2937261
It is supported everywhere now.
1578 lines
63 KiB
CMake
1578 lines
63 KiB
CMake
cmake_minimum_required(VERSION 3.12)
|
|
|
|
# Please note that cmake support is very preliminary. Autotools-based
|
|
# build is the only fully supported build for now.
|
|
|
|
# Based on configure.ac
|
|
|
|
project(gperftools VERSION 2.8.1 LANGUAGES C CXX
|
|
DESCRIPTION "Performance tools for C++"
|
|
HOMEPAGE_URL http://code.google.com/p/gperftools/)
|
|
|
|
# Update this value for every release!
|
|
set(TCMALLOC_SO_VERSION 9.6.5)
|
|
set(PROFILER_SO_VERSION 5.1.5)
|
|
set(TCMALLOC_AND_PROFILER_SO_VERSION 10.1.6)
|
|
|
|
# The user can choose not to compile in the heap-profiler, the
|
|
# heap-checker, or the cpu-profiler. There's also the possibility
|
|
# for a 'fully minimal' compile, which leaves out the stacktrace
|
|
# code as well. By default, we include all of these that the
|
|
# target system supports.
|
|
set(DEFAULT_BUILD_CPU_PROFILER ON)
|
|
set(DEFAULT_BUILD_HEAP_PROFILER ON)
|
|
set(DEFAULT_BUILD_HEAP_CHECKER ON)
|
|
set(DEFAULT_BUILD_DEBUGALLOC ON)
|
|
set(DEFAULT_BUILD_MINIMAL OFF)
|
|
|
|
set(DEFAULT_TCMALLOC_ALIGNMENT 16)
|
|
set(NEED_NANOSLEEP ON) # Used later, to decide if to run ACX_NANOSLEEP
|
|
|
|
set(HOST string(TOLOWER "${CMAKE_SYSTEM_NAME}"))
|
|
|
|
if(MINGW OR MSVC)
|
|
set(DEFAULT_BUILD_MINIMAL ON)
|
|
set(DEFAULT_BUILD_DEBUGALLOC OFF)
|
|
set(NEED_NANOSLEEP OFF)
|
|
elseif(CYGWIN)
|
|
set(DEFAULT_BUILD_HEAP_CHECKER OFF)
|
|
set(DEFAULT_BUILD_CPU_PROFILER OFF)
|
|
elseif(HOST MATCHES "freebsd")
|
|
set(DEFAULT_BUILD_HEAP_CHECKER OFF)
|
|
elseif(APPLE)
|
|
set(DEFAULT_BUILD_HEAP_CHECKER OFF)
|
|
endif()
|
|
|
|
include(CheckCCompilerFlag)
|
|
include(CheckCSourceCompiles)
|
|
include(CheckCXXSourceCompiles)
|
|
include(CheckFunctionExists)
|
|
include(CheckIncludeFile)
|
|
include(CheckLibraryExists)
|
|
include(CheckSymbolExists)
|
|
include(CheckTypeSize)
|
|
include(CheckVariableExists)
|
|
include(CMakeDependentOption)
|
|
include(CTest)
|
|
include(CPack)
|
|
include(GNUInstallDirs)
|
|
|
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
|
include(CheckNoFPByDefault)
|
|
include(DefineTargetVariables)
|
|
include(FindObjcopyWithWeaken)
|
|
include(PCFromUContext)
|
|
|
|
define_target_variables()
|
|
|
|
# Currently only backtrace works on s390.
|
|
if(s390)
|
|
set(default_enable_libunwind OFF)
|
|
set(default_enable_backtrace ON)
|
|
else()
|
|
set(default_enable_libunwind ON)
|
|
set(default_enable_backtrace OFF)
|
|
endif()
|
|
|
|
# Disable libunwind linking on ppc64 by default.
|
|
if(PPC64)
|
|
set(default_enable_libunwind OFF)
|
|
set(default_tcmalloc_pagesize 64)
|
|
else()
|
|
set(default_enable_libunwind ON)
|
|
set(default_tcmalloc_pagesize 8)
|
|
endif()
|
|
|
|
cmake_dependent_option(
|
|
GPERFTOOLS_BUILD_CPU_PROFILER "Build cpu-profiler" ${DEFAULT_BUILD_CPU_PROFILER}
|
|
"NOT gperftools_build_minimal" OFF)
|
|
cmake_dependent_option(
|
|
GPERFTOOLS_BUILD_HEAP_PROFILER "Build heap-profiler" ${DEFAULT_BUILD_HEAP_PROFILER}
|
|
"NOT gperftools_build_minimal" OFF)
|
|
cmake_dependent_option(
|
|
GPERFTOOLS_BUILD_HEAP_CHECKER "Build heap-checker" ${DEFAULT_BUILD_HEAP_CHECKER}
|
|
"NOT gperftools_build_minimal" OFF)
|
|
cmake_dependent_option(
|
|
GPERFTOOLS_BUILD_DEBUGALLOC "Build debugalloc" ${DEFAULT_BUILD_DEBUGALLOC}
|
|
"NOT gperftools_build_minimal" OFF)
|
|
option(
|
|
gperftools_build_minimal
|
|
"Build only tcmalloc-minimal (and maybe tcmalloc-minimal-debug)"
|
|
${DEFAULT_BUILD_MINIMAL})
|
|
if(gperftools_build_minimal)
|
|
set(GPERFTOOLS_BUILD_CPU_PROFILER OFF)
|
|
set(GPERFTOOLS_BUILD_HEAP_PROFILER OFF)
|
|
set(GPERFTOOLS_BUILD_HEAP_CHECKER OFF)
|
|
endif()
|
|
|
|
cmake_dependent_option(
|
|
gperftools_build_benchmark "Build benchmark" ON "NOT MINGW AND NOT MSVC" OFF)
|
|
|
|
option(gperftools_enable_stacktrace_via_backtrace
|
|
"Enable use of backtrace() for stacktrace capturing (may deadlock)"
|
|
${default_enable_backtrace})
|
|
option(gperftools_enable_libunwind
|
|
"Enable libunwind linking"
|
|
${default_enable_libunwind})
|
|
|
|
set(enable_backtrace ${gperftools_enable_stacktrace_via_backtrace})
|
|
set(enable_libunwind ${gperftools_enable_libunwind})
|
|
|
|
set(gperftools_tcmalloc_pagesize ${default_tcmalloc_pagesize}
|
|
CACHE STRING "Set the tcmalloc internal page size")
|
|
set_property(CACHE gperftools_tcmalloc_pagesize PROPERTY STRINGS "8" "32" "64")
|
|
if(NOT gperftools_tcmalloc_pagesize STREQUAL "8" AND
|
|
NOT gperftools_tcmalloc_pagesize STREQUAL "32" AND
|
|
NOT gperftools_tcmalloc_pagesize STREQUAL "64")
|
|
message(WARNING
|
|
"Invalid gperftools_tcmalloc_pagesize (${gperftools_tcmalloc_pagesize}), "
|
|
"setting to default value (${default_tcmalloc_pagesize})")
|
|
set(gperftools_tcmalloc_pagesize ${default_tcmalloc_pagesize})
|
|
endif()
|
|
if (gperftools_tcmalloc_pagesize STREQUAL "32" OR
|
|
gperftools_tcmalloc_pagesize STREQUAL "64")
|
|
set(TCMALLOC_${gperftools_tcmalloc_pagesize}K_PAGES ON)
|
|
endif()
|
|
|
|
set(gperftools_tcmalloc_alignment ${DEFAULT_TCMALLOC_ALIGNMENT}
|
|
CACHE STRING "Set the tcmalloc allocation alignment")
|
|
set_property(CACHE gperftools_tcmalloc_alignment PROPERTY STRINGS "8" "16")
|
|
if(NOT gperftools_tcmalloc_alignment STREQUAL "8" AND
|
|
NOT gperftools_tcmalloc_alignment STREQUAL "16")
|
|
message(WARNING
|
|
"Invalid gperftools_tcmalloc_alignment (${gperftools_tcmalloc_alignment}), "
|
|
"setting to default value (${DEFAULT_TCMALLOC_ALIGNMENT})")
|
|
set(gperftools_tcmalloc_alignment ${DEFAULT_TCMALLOC_ALIGNMENT})
|
|
endif()
|
|
if(gperftools_tcmalloc_alignment STREQUAL "8")
|
|
set(TCMALLOC_ALIGN_8BYTES ON)
|
|
endif()
|
|
|
|
# AX_CXX_COMPILE_STDCXX(11, ext, mandatory)
|
|
if(cxx_std_17 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
|
set(CMAKE_CXX_STANDARD 17) # std::align_val_t
|
|
else()
|
|
set(CMAKE_CXX_STANDARD 11)
|
|
endif()
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS ON)
|
|
|
|
# Check if we have an objcopy installed that supports -W
|
|
find_objcopy_with_weaken()
|
|
|
|
# AX_C___ATTRIBUTE__
|
|
check_c_source_compiles("#include <stdlib.h>
|
|
static void foo(void) __attribute__ ((unused));
|
|
void foo(void) { exit(1); }
|
|
int main() { return 0; }"
|
|
HAVE___ATTRIBUTE__)
|
|
|
|
check_type_size("__int64" __INT64 LANGUAGE CXX) # defined in some windows platforms
|
|
set(CMAKE_EXTRA_INCLUDE_FILES "malloc.h")
|
|
check_type_size("struct mallinfo" STRUCT_MALLINFO LANGUAGE CXX)
|
|
set(CMAKE_EXTRA_INCLUDE_FILES "elf.h")
|
|
check_type_size("Elf32_Versym" ELF32_VERSYM LANGUAGE CXX) # for vdso_support.h
|
|
set(CMAKE_EXTRA_INCLUDE_FILES)
|
|
check_function_exists("sbrk" HAVE_SBRK) # for tcmalloc to get memory
|
|
check_function_exists("__sbrk" HAVE_SBRK) # for tcmalloc to get memory
|
|
check_function_exists("geteuid" HAVE_GETEUID) # for turning off services when run as root
|
|
check_function_exists("fork" HAVE_FORK) # for the pthread_atfork setup
|
|
check_include_file("features.h" HAVE_FEATURES_H) # for vdso_support.h, Where __GLIBC__ is defined
|
|
check_include_file("malloc.h" HAVE_MALLOC_H) # some systems define stuff there, others not
|
|
check_include_file("glob.h" HAVE_GLOB_H) # for heap-profile-table (cleaning up profiles)
|
|
check_include_file("execinfo.h" HAVE_EXECINFO_H) # for stacktrace? and heapchecker_unittest
|
|
check_include_file("unwind.h" HAVE_UNWIND_H) # for stacktrace
|
|
check_include_file("sched.h" HAVE_SCHED_H) # for being nice in our spinlock code
|
|
check_include_file("conflict-signal.h" HAVE_CONFLICT_SIGNAL_H) # defined on some windows platforms?
|
|
check_include_file("sys/prctl.h" HAVE_SYS_PRCTL_H) # for thread_lister (needed by leak-checker)
|
|
check_include_file("linux/ptrace.h" HAVE_LINUX_PTRACE_H) # also needed by leak-checker
|
|
check_include_file("sys/syscall.h" HAVE_SYS_SYSCALL_H)
|
|
check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H) # optional; for forking out to symbolizer
|
|
check_include_file("sys/wait.h" HAVE_SYS_WAIT_H) # optional; for forking out to symbolizer
|
|
check_include_file("poll.h" HAVE_POLL_H) # optional; for forking out to symbolizer
|
|
check_include_file("fcntl.h" HAVE_FCNTL_H) # for tcmalloc_unittest
|
|
check_include_file("grp.h" HAVE_GRP_H) # for heapchecker_unittest
|
|
check_include_file("pwd.h" HAVE_PWD_H) # for heapchecker_unittest
|
|
check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H) # for memalign_unittest.cc
|
|
check_include_file("valgrind.h" HAVE_VALGRIND_H) # we have a local copy if this isn't found
|
|
check_include_file("sys/cdefs.h" HAVE_SYS_CDEFS_H) # Where glibc defines __THROW
|
|
|
|
check_include_file("unistd.h" HAVE_UNISTD_H)
|
|
check_include_file("inttypes.h" HAVE_INTTYPES_H)
|
|
# We also need <ucontext.h>/<sys/ucontext.h>, but we get those from
|
|
# AC_PC_FROM_UCONTEXT, below.
|
|
|
|
# for windows
|
|
check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF)
|
|
|
|
# We override a lot of memory allocation routines, not all of which are
|
|
# standard. For those the system doesn't declare, we'll declare ourselves.
|
|
set(CMAKE_REQUIRED_DEFINITIONS -D_XOPEN_SOURCE=600)
|
|
check_symbol_exists("cfree" "stdlib.h;malloc.h" HAVE_DECL_CFREE)
|
|
check_symbol_exists("posix_memalign" "stdlib.h;malloc.h" HAVE_DECL_POSIX_MEMALIGN)
|
|
check_symbol_exists("memalign" "stdlib.h;malloc.h" HAVE_DECL_MEMALIGN)
|
|
check_symbol_exists("valloc" "stdlib.h;malloc.h" HAVE_DECL_VALLOC)
|
|
check_symbol_exists("pvalloc" "stdlib.h;malloc.h" HAVE_DECL_PVALLOC)
|
|
set(CMAKE_REQUIRED_DEFINITIONS)
|
|
|
|
if(HAVE_STRUCT_MALLINFO)
|
|
set(HAVE_STRUCT_MALLINFO 1)
|
|
else()
|
|
set(HAVE_STRUCT_MALLINFO 0)
|
|
endif()
|
|
|
|
# We hardcode HAVE_MMAP to 1. There are no interesting systems anymore
|
|
# without functional mmap. And our windows (except mingw) builds
|
|
# aren't using autoconf. So we keep HAVE_MMAP define, but only to
|
|
# distingush windows and rest.
|
|
if(NOT WIN32)
|
|
set(HAVE_MMAP 1)
|
|
endif()
|
|
|
|
# If AtomicWord != Atomic32, we need to define two versions of all the
|
|
# atomicops functions. If they're the same, we want to define only one.
|
|
check_c_source_compiles("
|
|
#include <stdint.h>
|
|
int main()
|
|
{
|
|
int32_t v1 = 0;
|
|
intptr_t v2 = 0;
|
|
return (&v1 - &v2);
|
|
}"
|
|
INT32_EQUALS_INTPTR)
|
|
|
|
# We want to access the "PC" (Program Counter) register from a struct
|
|
# ucontext. Every system has its own way of doing that. We try all the
|
|
# possibilities we know about. Note REG_PC should come first (REG_RIP
|
|
# is also defined on solaris, but does the wrong thing). But don't
|
|
# bother if we're not doing cpu-profiling.
|
|
# [*] means that we've not actually tested one of these systems
|
|
if (GPERFTOOLS_BUILD_CPU_PROFILER)
|
|
pc_from_ucontext(PC_FROM_UCONTEXT_DEF)
|
|
endif ()
|
|
|
|
# Some tests test the behavior of .so files, and only make sense for dynamic.
|
|
option(GPERFTOOLS_BUILD_STATIC "Enable Static" ON)
|
|
|
|
if(gperftools_enable_libunwind)
|
|
check_include_file("libunwind.h" HAVE_LIBUNWIND_H)
|
|
if(HAVE_LIBUNWIND_H)
|
|
find_library(libunwind_location NAMES unwind)
|
|
if(libunwind_location)
|
|
check_library_exists(
|
|
unwind backtrace ${libunwind_location} have_libunwind)
|
|
endif()
|
|
if(have_libunwind)
|
|
set(unwind_libs ${libunwind_location})
|
|
set(will_use_libunwind ON)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
# On x86_64, instead of libunwind, we can choose to compile with frame-pointers.
|
|
# Some x86_64 systems do not insert frame pointers by default.
|
|
# We want to see if the current system is one of those.
|
|
if(x86_64)
|
|
check_omit_fp_by_default(omit_fp_by_default)
|
|
endif()
|
|
|
|
if(x86_64 AND omit_fp_by_default)
|
|
set(fp_option_enabled "Success")
|
|
else()
|
|
set(fp_option_enabled "Failed")
|
|
if(NOT x86_64)
|
|
set(fp_option_enabled "${fp_option_enabled}, not x86_64")
|
|
elseif(NOT omit_fp_by_default)
|
|
set(fp_option_enabled
|
|
"${fp_option_enabled}, frame pointer not omitted by default")
|
|
endif()
|
|
message(STATUS
|
|
"Enable option gperftools_enable_frame_pointers - ${fp_option_enabled}")
|
|
endif()
|
|
|
|
cmake_dependent_option(
|
|
gperftools_enable_frame_pointers
|
|
"On x86_64 systems, compile with -fno-omit-frame-pointer (see INSTALL)"
|
|
OFF
|
|
"x86_64;omit_fp_by_default"
|
|
OFF)
|
|
|
|
# See if the compiler supports -Wno-unused-result.
|
|
# Newer ubuntu's turn on -D_FORTIFY_SOURCE=2, enabling
|
|
# __attribute__((warn_unused_result)) for things like write(),
|
|
# which we don't care about.
|
|
check_c_compiler_flag("-Wno-unused-result" have_w_no_unused_result)
|
|
|
|
option(gperftools_dynamic_sized_delete_support
|
|
"Try to build run-time switch for sized delete operator"
|
|
OFF)
|
|
if(gperftools_dynamic_sized_delete_support)
|
|
set(ENABLE_DYNAMIC_SIZED_DELETE 1)
|
|
endif()
|
|
|
|
option(gperftools_sized_delete "Build sized delete operator" OFF)
|
|
if(gperftools_sized_delete)
|
|
set(ENABLE_SIZED_DELETE 1)
|
|
endif()
|
|
|
|
if(NOT MSVC)
|
|
set(CMAKE_REQUIRED_FLAGS -fsized-deallocation)
|
|
check_cxx_source_compiles("
|
|
#include <new>
|
|
int main() { (::operator delete)(0, 256); return 0; }"
|
|
have_sized_deallocation)
|
|
set(CMAKE_REQUIRED_FLAGS)
|
|
endif()
|
|
|
|
check_cxx_source_compiles("
|
|
#include <new>
|
|
int main() { (::operator delete)((::operator new)(256, std::align_val_t(16)), std::align_val_t(16)); return 0; }"
|
|
HAVE_STD_ALIGN_VAL_T)
|
|
if(HAVE_STD_ALIGN_VAL_T)
|
|
set(HAVE_STD_ALIGN_VAL_T 1)
|
|
else()
|
|
set(HAVE_STD_ALIGN_VAL_T 0)
|
|
endif()
|
|
|
|
check_c_source_compiles(
|
|
"namespace abc { void foo() {} } int main() { abc::foo(); return 0; }"
|
|
HAVE_NAMESPACES)
|
|
|
|
check_c_source_compiles("
|
|
#include <unwind.h>
|
|
int main()
|
|
{
|
|
&_Unwind_Backtrace;
|
|
return 0;
|
|
}"
|
|
HAVE_UNWIND_BACKTRACE)
|
|
|
|
if(enable_backtrace)
|
|
set(default_emergency_malloc ON)
|
|
else()
|
|
set(default_emergency_malloc OFF)
|
|
endif()
|
|
|
|
if(will_use_libunwind AND ARM)
|
|
set(default_emergency_malloc ON)
|
|
endif()
|
|
|
|
option(gperftools_emergency_malloc
|
|
"Build emergency malloc"
|
|
${default_emergency_malloc})
|
|
|
|
check_c_source_compiles(
|
|
"int main() { void* sp = __builtin_stack_pointer(); return 0; }"
|
|
HAVE_BUILTIN_STACK_POINTER)
|
|
check_c_source_compiles(
|
|
"int main() { return __builtin_expect(main != 0, 1); }"
|
|
HAVE_BUILTIN_EXPECT)
|
|
|
|
check_c_source_compiles("
|
|
#include <unistd.h>
|
|
int main()
|
|
{
|
|
char** env = __environ;
|
|
return 0;
|
|
}"
|
|
HAVE___ENVIRON)
|
|
|
|
# If we support __thread, that can speed up tcmalloc a bit.
|
|
# Note, however, that our code tickles a bug in gcc < 4.1.2
|
|
# involving TLS and -fPIC (which our libraries will use) on x86:
|
|
# http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html
|
|
#
|
|
# And mingw also does compile __thread but resultant code actually
|
|
# fails to work correctly at least in some not so ancient version:
|
|
# http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.html
|
|
#
|
|
# Also it was reported that earlier gcc versions for mips compile
|
|
# __thread but it doesn't really work
|
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND
|
|
CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.1.2")
|
|
message(WARNING "gcc has this bug: http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html")
|
|
elseif(APPLE)
|
|
message(WARNING "OSX __thread support is known to call malloc which makes "
|
|
"it unsafe to use from malloc replacement")
|
|
elseif(MINGW)
|
|
message(WARNING "mingw doesn't really support tls")
|
|
else()
|
|
check_c_source_compiles("static __thread int p = 0;" HAVE_TLS)
|
|
endif()
|
|
|
|
if(NEED_NANOSLEEP)
|
|
check_c_source_compiles(
|
|
"#include <time.h>
|
|
int main()
|
|
{ static struct timespec ts; nanosleep(&ts, NULL); return 0; }"
|
|
nanosleep_ok)
|
|
if(NOT nanosleep_ok)
|
|
set(CMAKE_REQUIRED_LIBRARIES rt)
|
|
check_c_source_compiles(
|
|
"#include <time.h>
|
|
int main()
|
|
{ static struct timespec ts; nanosleep(&ts, NULL); return 0; }"
|
|
nanosleep_ok)
|
|
if(nanosleep_ok)
|
|
set(nanosleep_libs rt)
|
|
else()
|
|
message(FATAL_ERROR "cannot find the nanosleep function")
|
|
endif()
|
|
set(CMAKE_REQUIRED_LIBRARIES)
|
|
endif()
|
|
endif()
|
|
|
|
# Nanosleep requires extra libraries on some architectures (solaris).
|
|
# This sets NANOSLEEP_LIBS. nanosleep doesn't exist on mingw, which
|
|
# is fine for us because we don't compile libspinlock, which uses it.
|
|
if(enable_backtrace)
|
|
check_symbol_exists("backtrace" "execinfo.h" HAVE_DECL_BACKTRACE)
|
|
check_function_exists("backtrace" backtrace_exists)
|
|
if(NOT backtrace_exists)
|
|
set(CMAKE_REQUIRED_LIBRARIES execinfo)
|
|
check_function_exists("backtrace" backtrace_exists)
|
|
set(CMAKE_REQUIRED_LIBRARIES)
|
|
if(backtrace_exists)
|
|
list(INSERT unwind_libs 0 execinfo)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
find_package(Threads REQUIRED)
|
|
set(HAVE_PTHREAD ${CMAKE_USE_PTHREADS_INIT})
|
|
foreach(attr "PTHREAD_CREATE_JOINABLE" "PTHREAD_CREATE_UNDETACHED")
|
|
check_c_source_compiles("
|
|
#include <pthread.h>
|
|
int main() { int attr = ${attr}; return attr; }"
|
|
${attr}_ATTR)
|
|
if(${attr}_ATTR)
|
|
set(PTHREAD_CREATE_JOINABLE ${attr})
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
|
|
if(FreeBSD)
|
|
set(PTHREADS_CRASHES_IF_RUN_TOO_EARLY ON)
|
|
endif()
|
|
|
|
set(libstdcxx_la_linker_flag)
|
|
if(EXISTS /usr/sfw/lib/libstdc++.la)
|
|
file(READ /usr/sfw/lib/libstdc++.la _ch LIMIT 1)
|
|
if(string(LENGTH _ch) EQUAL 0)
|
|
set(libstdcxx_la_linker_flag "-L${CMAKE_CURRENT_SOURCE_DIR}/src/solaris")
|
|
endif()
|
|
endif()
|
|
|
|
# We also need to check if the kernel supports __thread, which requires uname()
|
|
check_symbol_exists("uname" "sys/utsname.h" HAVE_DECL_UNAME)
|
|
|
|
check_cxx_source_compiles(
|
|
"#include <string>
|
|
#include <vector>
|
|
int main() { pthread_t th; pthread_join(th, 0); return 0; }"
|
|
have_pthread_despite_asking_for)
|
|
|
|
check_cxx_source_compiles(
|
|
"#include <vector>
|
|
int main() { vector<int> t; return 0; }"
|
|
STL_NAMESPACE_NONE)
|
|
if(STL_NAMESPACE_NONE)
|
|
set(STL_NAMESPACE "")
|
|
else()
|
|
check_cxx_source_compiles(
|
|
"#include <vector>
|
|
int main() { std::vector<int> t; return 0; }"
|
|
STL_NAMESPACE_STD)
|
|
if (STL_NAMESPACE_STD)
|
|
set(STL_NAMESPACE "std")
|
|
endif()
|
|
endif()
|
|
|
|
check_variable_exists("program_invocation_name" HAVE_PROGRAM_INVOCATION_NAME)
|
|
|
|
if(MINGW)
|
|
check_symbol_exists("sleep" "unistd.h" HAVE_DECL_SLEEP)
|
|
check_symbol_exists("nanosleep" "time.h" HAVE_DECL_NANOSLEEP)
|
|
endif()
|
|
|
|
if(LINUX)
|
|
check_c_source_compiles("
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
int main() { return SIGEV_THREAD_ID || CLOCK_THREAD_CPUTIME_ID; }"
|
|
HAVE_LINUX_SIGEV_THREAD_ID)
|
|
endif()
|
|
|
|
configure_file(cmake/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)
|
|
configure_file(cmake/tcmalloc.h.in
|
|
${CMAKE_CURRENT_BINARY_DIR}/gperftools/tcmalloc.h
|
|
@ONLY)
|
|
|
|
if(GPERFTOOLS_BUILD_CPU_PROFILER OR
|
|
GPERFTOOLS_BUILD_HEAP_PROFILER OR
|
|
GPERFTOOLS_BUILD_HEAP_CHECKER)
|
|
set(WITH_STACK_TRACE ON)
|
|
endif()
|
|
|
|
if(gperftools_enable_frame_pointers AND
|
|
NOT unwind_libs AND
|
|
NOT gperftools_build_minimal)
|
|
if(HAVE_UNWIND_BACKTRACE)
|
|
message(WARNING "No frame pointers and no libunwind. "
|
|
"Using experimental backtrace capturing via libgcc. "
|
|
"Expect crashy cpu profiler.")
|
|
if(gperftools_enable_stacktrace_via_backtrace)
|
|
message(WARNING "No frame pointers and no libunwind. "
|
|
"Using experimental backtrace(). "
|
|
"Expect crashy cpu profiler.")
|
|
else()
|
|
message(FATAL_ERROR "No frame pointers and no libunwind. "
|
|
"The compilation will fail.")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
# Based on Makefile.am
|
|
|
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|
# This is so we can #include <gperftools/foo>
|
|
include_directories($<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
|
|
|
|
if(NOT WITH_STACK_TRACE)
|
|
add_compile_definitions(NO_TCMALLOC_SAMPLES)
|
|
endif()
|
|
|
|
# These are good warnings to turn on by default.
|
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare")
|
|
|
|
# On i386, -mmmx is needed for the mmx-based instructions in
|
|
# atomicops-internal-x86.h. Also as of gcc 4.6, -fomit-frame-pointer
|
|
# is the default. Since we must always have frame pointers for I386
|
|
# in order to generate backtraces we now specify -fno-omit-frame-pointer
|
|
# by default.
|
|
if(i386)
|
|
add_compile_options(-mmmx -fno-omit-frame-pointer)
|
|
endif()
|
|
endif()
|
|
|
|
if(have_w_no_unused_result)
|
|
add_compile_options(-Wno-unused-result)
|
|
endif()
|
|
|
|
if(have_sized_deallocation)
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsized-deallocation")
|
|
endif()
|
|
|
|
if(have_f_aligned_new)
|
|
add_compile_options(-faligned-new)
|
|
endif()
|
|
|
|
# LIBSTDCXX_LA_LINKER_FLAG is used to fix a Solaris bug.
|
|
add_link_options(${libstdcxx_la_linker_flag})
|
|
|
|
# These are x86-specific, having to do with frame-pointers. In
|
|
# particular, some x86_64 systems do not insert frame pointers by
|
|
# default (all i386 systems that I know of, do. I don't know about
|
|
# non-x86 chips). We need to tell perftools what to do about that.
|
|
if(x86_64 AND x86_no_fp_by_default)
|
|
if(gperftools_enable_frame_pointers)
|
|
add_compile_options(-fno-omit-frame-pointer)
|
|
elseif(CMAKE_CXX_FLAGS MATCHES "-fomit-frame-pointer")
|
|
add_compile_definitions(NO_FRAME_POINTER)
|
|
endif()
|
|
endif()
|
|
|
|
# For windows systems (at least, mingw), we need to tell all our
|
|
# tests to link in libtcmalloc using -u. This is because libtcmalloc
|
|
# accomplishes its tasks via patching, leaving no work for the linker
|
|
# to identify, so the linker will ignore libtcmalloc by default unless
|
|
# we explicitly create a dependency via -u.
|
|
set(TCMALLOC_FLAGS)
|
|
if(MINGW)
|
|
list(APPEND TCMALLOC_FLAGS "-Wl,-u__tcmalloc")
|
|
endif()
|
|
|
|
set(googleinclude_HEADERS
|
|
src/google/heap-checker.h
|
|
src/google/heap-profiler.h
|
|
src/google/malloc_extension.h
|
|
src/google/malloc_extension_c.h
|
|
src/google/malloc_hook.h
|
|
src/google/malloc_hook_c.h
|
|
src/google/profiler.h
|
|
src/google/stacktrace.h
|
|
src/google/tcmalloc.h
|
|
)
|
|
install(FILES ${googleinclude_HEADERS}
|
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/google
|
|
)
|
|
|
|
# This is a 'convenience library' -- it's not actually installed or anything
|
|
set(LOGGING_INCLUDES
|
|
src/base/logging.h
|
|
src/base/commandlineflags.h
|
|
src/base/basictypes.h
|
|
src/base/dynamic_annotations.h
|
|
src/third_party/valgrind.h)
|
|
set(liblogging_la_SOURCES src/base/logging.cc
|
|
src/base/dynamic_annotations.c
|
|
${LOGGING_INCLUDES})
|
|
add_library(logging STATIC ${liblogging_la_SOURCES})
|
|
|
|
set(SYSINFO_INCLUDES
|
|
src/base/sysinfo.h
|
|
src/getenv_safe.h
|
|
src/base/logging.h
|
|
src/base/commandlineflags.h
|
|
src/base/arm_instruction_set_select.h
|
|
src/base/basictypes.h)
|
|
set(libsysinfo_la_SOURCES src/base/sysinfo.cc
|
|
${SYSINFO_INCLUDES})
|
|
set(libsysinfo_la_LIBADD ${NANOSLEEP_LIBS})
|
|
add_library(sysinfo STATIC ${libsysinfo_la_SOURCES})
|
|
target_link_libraries(sysinfo ${libsysinfo_la_LIBADD})
|
|
|
|
# For MinGW, we use also have to use libwindows Luckily, we need the
|
|
# windows.a library in exactly the same place we need spinlock.a
|
|
# (pretty much everywhere), so we can use the same variable name for
|
|
# each. We can also optimize the MinGW rule a bit by leaving out
|
|
# files we know aren't used on windows, such as
|
|
# atomicops-internals-x86.cc. libwindows also obsoletes the need for
|
|
# other files like system_alloc.cc.
|
|
if(MINGW OR MSVC)
|
|
set(WINDOWS_INCLUDES
|
|
src/windows/port.h
|
|
src/windows/mingw.h
|
|
src/windows/mini_disassembler.h
|
|
src/windows/mini_disassembler_types.h
|
|
src/windows/preamble_patcher.h)
|
|
set(libwindows_la_SOURCES ${WINDOWS_INCLUDES}
|
|
src/windows/port.cc
|
|
src/windows/system-alloc.cc
|
|
src/windows/ia32_modrm_map.cc
|
|
src/windows/ia32_opcode_map.cc
|
|
src/windows/mini_disassembler.cc
|
|
src/windows/patch_functions.cc
|
|
src/windows/preamble_patcher.cc
|
|
src/windows/preamble_patcher_with_stub.cc)
|
|
add_library(windows_object OBJECT ${libwindows_la_SOURCES})
|
|
add_library(windows INTERFACE)
|
|
target_sources(windows INTERFACE $<TARGET_OBJECTS:windows_object>)
|
|
# patch_functions.cc uses Psapi.lib. MSVC has a #pragma for that, but not us.
|
|
target_link_libraries(windows INTERFACE psapi)
|
|
|
|
set(SPINLOCK_INCLUDES src/base/spinlock.h
|
|
src/base/spinlock_internal.h
|
|
src/base/spinlock_win32-inl.h
|
|
src/base/spinlock_linux-inl.h
|
|
src/base/spinlock_posix-inl.h
|
|
src/base/atomicops-internals-macosx.h
|
|
src/base/atomicops-internals-linuxppc.h
|
|
src/base/atomicops-internals-arm-generic.h
|
|
src/base/atomicops-internals-arm-v6plus.h
|
|
src/base/atomicops-internals-mips.h
|
|
src/base/atomicops-internals-windows.h
|
|
src/base/atomicops-internals-gcc.h
|
|
src/base/atomicops-internals-x86.h)
|
|
set(libspinlock_la_SOURCES src/base/spinlock.cc
|
|
src/base/spinlock_internal.cc
|
|
src/base/atomicops-internals-x86.cc
|
|
${SPINLOCK_INCLUDES})
|
|
add_library(spinlock STATIC ${libspinlock_la_SOURCES})
|
|
set(LIBSPINLOCK windows spinlock sysinfo logging)
|
|
# We also need to tell mingw that sysinfo.cc needs shlwapi.lib.
|
|
# (We do this via a #pragma for msvc, but need to do it here for mingw).
|
|
target_link_libraries(sysinfo shlwapi)
|
|
|
|
if(have_pthread_despite_asking_for)
|
|
add_library(maybe_threads STATIC src/maybe_threads.cc)
|
|
set(maybe_threads_lib maybe_threads)
|
|
endif()
|
|
else()
|
|
set(SPINLOCK_INCLUDES src/base/spinlock.h
|
|
src/base/spinlock_internal.h
|
|
src/base/atomicops.h
|
|
src/base/atomicops-internals-macosx.h
|
|
src/base/atomicops-internals-linuxppc.h
|
|
src/base/atomicops-internals-windows.h
|
|
src/base/atomicops-internals-x86.h)
|
|
set(libspinlock_la_SOURCES src/base/spinlock.cc
|
|
src/base/spinlock_internal.cc
|
|
src/base/atomicops-internals-x86.cc
|
|
${SPINLOCK_INCLUDES})
|
|
add_library(spinlock STATIC ${libspinlock_la_SOURCES})
|
|
target_link_libraries(spinlock ${nanosleep_libs})
|
|
set(LIBSPINLOCK spinlock sysinfo logging)
|
|
set(TCMALLOC_CC "src/tcmalloc.cc")
|
|
set(SYSTEM_ALLOC_CC "src/system-alloc.cc")
|
|
|
|
add_library(maybe_threads STATIC src/maybe_threads.cc)
|
|
set(maybe_threads_lib maybe_threads)
|
|
endif()
|
|
|
|
if(BUILD_TESTING)
|
|
set(LOW_LEVEL_ALLOC_UNITTEST_INCLUDES
|
|
src/base/low_level_alloc.h
|
|
src/base/basictypes.h
|
|
src/gperftools/malloc_hook.h
|
|
src/gperftools/malloc_hook_c.h
|
|
src/malloc_hook-inl.h
|
|
src/malloc_hook_mmap_linux.h
|
|
src/malloc_hook_mmap_freebsd.h
|
|
${SPINLOCK_INCLUDES}
|
|
${LOGGING_INCLUDES})
|
|
set(low_level_alloc_unittest_SOURCES src/base/low_level_alloc.cc
|
|
src/malloc_hook.cc
|
|
src/tests/low_level_alloc_unittest.cc
|
|
${LOW_LEVEL_ALLOC_UNITTEST_INCLUDES})
|
|
if(MSVC OR MINGW)
|
|
list(APPEND low_level_alloc_unittest_SOURCES src/windows/port.cc)
|
|
endif()
|
|
add_executable(low_level_alloc_unittest ${low_level_alloc_unittest_SOURCES})
|
|
# By default, MallocHook takes stack traces for use by the heap-checker.
|
|
# We don't need that functionality here, so we turn it off to reduce deps.
|
|
target_compile_definitions(low_level_alloc_unittest PRIVATE NO_TCMALLOC_SAMPLES)
|
|
target_link_libraries(low_level_alloc_unittest spinlock sysinfo logging ${maybe_threads_lib})
|
|
add_test(low_level_alloc_unittest low_level_alloc_unittest)
|
|
|
|
set(ATOMICOPS_UNITTEST_INCLUDES src/base/atomicops.h
|
|
src/base/atomicops-internals-macosx.h
|
|
src/base/atomicops-internals-windows.h
|
|
src/base/atomicops-internals-x86.h
|
|
${LOGGING_INCLUDES})
|
|
set(atomicops_unittest_SOURCES src/tests/atomicops_unittest.cc
|
|
${ATOMICOPS_UNITTEST_INCLUDES})
|
|
if(MSVC OR MINGW)
|
|
list(APPEND atomicops_unittest_SOURCES src/windows/port.cc)
|
|
endif()
|
|
add_executable(atomicops_unittest ${atomicops_unittest_SOURCES})
|
|
target_link_libraries(atomicops_unittest spinlock sysinfo logging)
|
|
add_test(atomicops_unittest atomicops_unittest)
|
|
endif()
|
|
|
|
### ------- stack trace
|
|
|
|
if(WITH_STACK_TRACE)
|
|
|
|
set(S_STACKTRACE_INCLUDES src/stacktrace_impl_setup-inl.h
|
|
src/stacktrace_generic-inl.h
|
|
src/stacktrace_libgcc-inl.h
|
|
src/stacktrace_libunwind-inl.h
|
|
src/stacktrace_arm-inl.h
|
|
src/stacktrace_powerpc-inl.h
|
|
src/stacktrace_powerpc-darwin-inl.h
|
|
src/stacktrace_powerpc-linux-inl.h
|
|
src/stacktrace_x86-inl.h
|
|
src/stacktrace_win32-inl.h
|
|
src/stacktrace_instrument-inl.h
|
|
src/base/elf_mem_image.h
|
|
src/base/vdso_support.h)
|
|
|
|
set(SG_STACKTRACE_INCLUDES src/gperftools/stacktrace.h)
|
|
set(STACKTRACE_INCLUDES ${S_STACKTRACE_INCLUDES} ${SG_STACKTRACE_INCLUDES})
|
|
list(APPEND perftoolsinclude_HEADERS ${SG_STACKTRACE_INCLUDES})
|
|
|
|
### Making the library
|
|
set(libstacktrace_la_SOURCES src/stacktrace.cc
|
|
src/base/elf_mem_image.cc
|
|
src/base/vdso_support.cc
|
|
${STACKTRACE_INCLUDES})
|
|
add_library(stacktrace INTERFACE)
|
|
add_library(stacktrace_object OBJECT ${libstacktrace_la_SOURCES})
|
|
target_link_libraries(stacktrace INTERFACE ${unwind_libs} ${LIBSPINLOCK})
|
|
target_sources(stacktrace INTERFACE $<TARGET_OBJECTS:stacktrace_object>)
|
|
|
|
set(libfake_stacktrace_scope_la_SOURCES src/fake_stacktrace_scope.cc)
|
|
add_library(fake_stacktrace_scope ${libfake_stacktrace_scope_la_SOURCES})
|
|
|
|
if(BUILD_TESTING)
|
|
set(STACKTRACE_UNITTEST_INCLUDES src/config_for_unittests.h
|
|
src/base/commandlineflags.h
|
|
${STACKTRACE_INCLUDES}
|
|
${LOGGING_INCLUDES})
|
|
set(stacktrace_unittest_SOURCES src/tests/stacktrace_unittest.cc
|
|
${STACKTRACE_UNITTEST_INCLUDES})
|
|
add_executable(stacktrace_unittest ${stacktrace_unittest_SOURCES})
|
|
target_link_libraries(stacktrace_unittest stacktrace logging fake_stacktrace_scope)
|
|
add_test(stacktrace_unittest stacktrace_unittest)
|
|
endif()
|
|
|
|
endif()
|
|
|
|
### ------- pprof
|
|
|
|
# If we are not compiling with stacktrace support, pprof is worthless
|
|
if(WITH_STACK_TRACE)
|
|
install(FILES src/pprof DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME pprof-symbolize)
|
|
|
|
if(BUILD_TESTING)
|
|
add_test(NAME pprof_unittest
|
|
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/src/pprof" -test
|
|
VERBATIM)
|
|
list(APPEND TESTS_ENVIRONMENT "PPROF_PATH=${CMAKE_CURRENT_SOURCE_DIR}/src/pprof")
|
|
endif()
|
|
if(INSTALL_PPROF)
|
|
install(FILES src/pprof DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
endif()
|
|
endif()
|
|
|
|
### ------- tcmalloc_minimal (thread-caching malloc)
|
|
|
|
### The header files we use. We divide into categories based on directory
|
|
set(S_TCMALLOC_MINIMAL_INCLUDES src/common.h
|
|
src/internal_logging.h
|
|
src/system-alloc.h
|
|
src/packed-cache-inl.h
|
|
${SPINLOCK_INCLUDES}
|
|
src/tcmalloc_guard.h
|
|
src/base/commandlineflags.h
|
|
src/base/basictypes.h
|
|
src/pagemap.h
|
|
src/sampler.h
|
|
src/central_freelist.h
|
|
src/linked_list.h
|
|
src/libc_override.h
|
|
src/libc_override_gcc_and_weak.h
|
|
src/libc_override_glibc.h
|
|
src/libc_override_osx.h
|
|
src/libc_override_redefine.h
|
|
src/page_heap.h
|
|
src/page_heap_allocator.h
|
|
src/span.h
|
|
src/static_vars.h
|
|
src/symbolize.h
|
|
src/thread_cache.h
|
|
src/stack_trace_table.h
|
|
src/base/thread_annotations.h
|
|
src/malloc_hook-inl.h
|
|
src/malloc_hook_mmap_linux.h
|
|
src/malloc_hook_mmap_freebsd.h)
|
|
set(SG_TCMALLOC_MINIMAL_INCLUDES src/gperftools/malloc_hook.h
|
|
src/gperftools/malloc_hook_c.h
|
|
src/gperftools/malloc_extension.h
|
|
src/gperftools/malloc_extension_c.h
|
|
src/gperftools/nallocx.h)
|
|
set(TCMALLOC_MINIMAL_INCLUDES ${S_TCMALLOC_MINIMAL_INCLUDES} ${SG_TCMALLOC_MINIMAL_INCLUDES} ${SG_STACKTRACE_INCLUDES})
|
|
list(APPEND perftoolsinclude_HEADERS ${SG_TCMALLOC_MINIMAL_INCLUDES})
|
|
|
|
### Making the library
|
|
|
|
set(libtcmalloc_minimal_internal_la_SOURCES src/common.cc
|
|
src/internal_logging.cc
|
|
${SYSTEM_ALLOC_CC}
|
|
src/memfs_malloc.cc
|
|
src/central_freelist.cc
|
|
src/page_heap.cc
|
|
src/sampler.cc
|
|
src/span.cc
|
|
src/stack_trace_table.cc
|
|
src/static_vars.cc
|
|
src/symbolize.cc
|
|
src/thread_cache.cc
|
|
src/malloc_hook.cc
|
|
src/malloc_extension.cc
|
|
${TCMALLOC_MINIMAL_INCLUDES})
|
|
add_library(tcmalloc_minimal_internal_object OBJECT ${libtcmalloc_minimal_internal_la_SOURCES})
|
|
# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal.
|
|
target_compile_definitions(tcmalloc_minimal_internal_object PRIVATE NO_TCMALLOC_SAMPLES NO_HEAP_CHECK NDEBUG)
|
|
add_library(tcmalloc_minimal_internal INTERFACE)
|
|
target_link_libraries(tcmalloc_minimal_internal INTERFACE ${LIBSPINLOCK} ${maybe_threads_lib})
|
|
target_sources(tcmalloc_minimal_internal INTERFACE $<TARGET_OBJECTS:tcmalloc_minimal_internal_object>)
|
|
|
|
set(libtcmalloc_minimal_la_SOURCES ${TCMALLOC_CC} ${TCMALLOC_MINIMAL_INCLUDES})
|
|
set(libtcmalloc_minimal_la_DEFINES NO_TCMALLOC_SAMPLES NDEBUG)
|
|
add_library(tcmalloc_minimal SHARED ${libtcmalloc_minimal_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_minimal PRIVATE ${libtcmalloc_minimal_la_DEFINES})
|
|
set(libtcmalloc_minimal_la_LIBADD tcmalloc_minimal_internal)
|
|
target_link_libraries(tcmalloc_minimal PRIVATE tcmalloc_minimal_internal Threads::Threads)
|
|
if(MINGW)
|
|
target_link_libraries(tcmalloc_minimal PRIVATE stacktrace)
|
|
endif()
|
|
set_target_properties(tcmalloc_minimal PROPERTIES
|
|
VERSION ${TCMALLOC_SO_VERSION}
|
|
SOVERSION ${TCMALLOC_SO_VERSION})
|
|
weaken_object(tcmalloc_minimal)
|
|
install(TARGETS tcmalloc_minimal)
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
add_library(tcmalloc_minimal_static STATIC ${libtcmalloc_minimal_internal_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_minimal_static PRIVATE NO_TCMALLOC_SAMPLES NDEBUG)
|
|
target_link_libraries(tcmalloc_minimal_static PRIVATE tcmalloc_minimal_internal Threads::Threads)
|
|
if(MINGW)
|
|
target_link_libraries(tcmalloc_minimal_static PRIVATE stacktrace)
|
|
endif()
|
|
if(NOT MSVC)
|
|
set_target_properties(tcmalloc_minimal_static PROPERTIES
|
|
OUTPUT_NAME tcmalloc_minimal)
|
|
endif()
|
|
weaken_object(tcmalloc_minimal_static)
|
|
install(TARGETS tcmalloc_minimal_static)
|
|
endif()
|
|
|
|
if(BUILD_TESTING)
|
|
set(tcmalloc_minimal_unittest_SOURCES
|
|
src/tests/tcmalloc_unittest.cc
|
|
src/tests/testutil.h src/tests/testutil.cc
|
|
${TCMALLOC_UNITTEST_INCLUDES})
|
|
set(tcmalloc_minimal_unittest_LDADD
|
|
${TCMALLOC_FLAGS} Threads::Threads logging)
|
|
# We want libtcmalloc last on the link line, but due to a bug in
|
|
# libtool involving convenience libs, they need to come last on the
|
|
# link line in order to get dependency ordering right. This is ok:
|
|
# convenience libraries are .a's, so tcmalloc is still the last .so.
|
|
# We also put pthreads after tcmalloc, because some pthread
|
|
# implementations define their own malloc, and we need to go on the
|
|
# first linkline to make sure our malloc 'wins'.
|
|
add_executable(tcmalloc_minimal_unittest ${tcmalloc_minimal_unittest_SOURCES})
|
|
target_link_libraries(tcmalloc_minimal_unittest tcmalloc_minimal ${tcmalloc_minimal_unittest_LDADD})
|
|
add_test(tcmalloc_minimal_unittest tcmalloc_minimal_unittest)
|
|
|
|
if(NOT MSVC)
|
|
add_executable(tcm_min_asserts_unittest
|
|
src/tests/tcmalloc_unittest.cc
|
|
src/tests/testutil.cc)
|
|
target_compile_definitions(tcm_min_asserts_unittest PUBLIC NO_TCMALLOC_SAMPLES NO_HEAP_CHECK)
|
|
target_link_libraries(tcm_min_asserts_unittest tcmalloc_minimal Threads::Threads)
|
|
add_test(tcm_min_asserts_unittest tcm_min_asserts_unittest)
|
|
endif()
|
|
|
|
add_executable(tcmalloc_minimal_large_unittest
|
|
src/tests/tcmalloc_large_unittest.cc
|
|
src/tests/testutil.cc
|
|
src/tests/testutil.h)
|
|
target_link_libraries(tcmalloc_minimal_large_unittest tcmalloc_minimal Threads::Threads)
|
|
add_test(tcmalloc_minimal_large_unittest tcmalloc_minimal_large_unittest)
|
|
|
|
add_executable(tcmalloc_minimal_large_heap_fragmentation_unittest
|
|
src/tests/large_heap_fragmentation_unittest.cc)
|
|
target_link_libraries(
|
|
tcmalloc_minimal_large_heap_fragmentation_unittest PUBLIC tcmalloc_minimal)
|
|
add_test(tcmalloc_minimal_large_heap_fragmentation_unittest tcmalloc_minimal_large_heap_fragmentation_unittest)
|
|
|
|
if(BUILD_SHARED_LIBS AND NOT MINGW)
|
|
add_custom_target(maybe_threads_unittest
|
|
COMMAND src/tests/maybe_threads_unittest.sh
|
|
VERBATIM)
|
|
add_test(maybe_threads_unittest maybe_threads_unittest)
|
|
endif()
|
|
|
|
if(MINGW OR MSVC)
|
|
set(port_src src/windows/port.cc)
|
|
endif()
|
|
add_executable(addressmap_unittest
|
|
src/tests/addressmap_unittest.cc
|
|
src/addressmap-inl.h
|
|
${port_src})
|
|
target_link_libraries(addressmap_unittest logging)
|
|
add_test(addressmap_unittest addressmap_unittest)
|
|
|
|
if(NOT MINGW)
|
|
add_executable(system_alloc_unittest src/tests/system-alloc_unittest.cc)
|
|
target_link_libraries(system_alloc_unittest PUBLIC tcmalloc_minimal)
|
|
add_test(system_alloc_unittest system_alloc_unittest)
|
|
endif()
|
|
|
|
add_executable(packed_cache_test src/tests/packed-cache_test.cc)
|
|
target_link_libraries(packed_cache_test PUBLIC tcmalloc_minimal)
|
|
add_test(packed_cache_test packed_cache_test)
|
|
|
|
add_executable(frag_unittest src/tests/frag_unittest.cc)
|
|
target_link_libraries(frag_unittest PUBLIC tcmalloc_minimal)
|
|
add_test(frag_unittest frag_unittest)
|
|
|
|
add_executable(markidle_unittest
|
|
src/tests/markidle_unittest.cc
|
|
src/tests/testutil.cc)
|
|
target_link_libraries(markidle_unittest tcmalloc_minimal Threads::Threads)
|
|
add_test(markidle_unittest markidle_unittest)
|
|
|
|
add_executable(current_allocated_bytes_test
|
|
src/tests/current_allocated_bytes_test.cc)
|
|
target_link_libraries(current_allocated_bytes_test PUBLIC tcmalloc_minimal)
|
|
add_test(current_allocated_bytes_test current_allocated_bytes_test)
|
|
|
|
add_executable(malloc_hook_test
|
|
src/tests/malloc_hook_test.cc
|
|
src/tests/testutil.cc)
|
|
target_link_libraries(malloc_hook_test tcmalloc_minimal Threads::Threads)
|
|
add_test(malloc_hook_test malloc_hook_test)
|
|
|
|
set(malloc_extension_test_SOURCES src/tests/malloc_extension_test.cc
|
|
src/config_for_unittests.h
|
|
src/base/logging.h
|
|
src/gperftools/malloc_extension.h
|
|
src/gperftools/malloc_extension_c.h)
|
|
set(malloc_extension_test_LIBADD Threads::Threads ${TCMALLOC_FLAGS})
|
|
add_executable(malloc_extension_test ${malloc_extension_test_SOURCES})
|
|
target_link_libraries(malloc_extension_test tcmalloc_minimal ${malloc_extension_test_LIBADD})
|
|
add_test(malloc_extension_test malloc_extension_test)
|
|
|
|
if(NOT MSVC)
|
|
add_executable(malloc_extension_c_test src/tests/malloc_extension_c_test.c)
|
|
target_link_libraries(malloc_extension_c_test PUBLIC
|
|
tcmalloc_minimal stdc++ m)
|
|
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
|
target_compile_options(malloc_extension_c_test PUBLIC "-ansi")
|
|
endif()
|
|
add_test(malloc_extension_c_test malloc_extension_c_test)
|
|
endif()
|
|
|
|
if(NOT MINGW AND NOT MSVC AND NOT APPLE)
|
|
set(memalign_unittest_SOURCES src/tests/memalign_unittest.cc
|
|
src/tcmalloc.h
|
|
src/config_for_unittests.h
|
|
src/tests/testutil.h src/tests/testutil.cc)
|
|
add_executable(memalign_unittest ${memalign_unittest_SOURCES})
|
|
target_link_libraries(memalign_unittest tcmalloc_minimal Threads::Threads)
|
|
add_test(memalign_unittest memalign_unittest)
|
|
endif()
|
|
|
|
add_executable(page_heap_test src/tests/page_heap_test.cc)
|
|
if(MSVC)
|
|
target_link_libraries(page_heap_test tcmalloc_minimal_static)
|
|
else()
|
|
target_link_libraries(page_heap_test tcmalloc_minimal)
|
|
endif()
|
|
add_test(page_heap_test page_heap_test)
|
|
|
|
add_executable(pagemap_unittest src/tests/pagemap_unittest.cc)
|
|
target_link_libraries(pagemap_unittest PUBLIC tcmalloc_minimal)
|
|
add_test(pagemap_unittest pagemap_unittest)
|
|
|
|
set(realloc_unittest_SOURCES src/tests/realloc_unittest.cc
|
|
src/config_for_unittests.h
|
|
src/base/logging.h)
|
|
set(realloc_unittest_LDFLAGS Threads::Threads ${TCMALLOC_FLAGS})
|
|
add_executable(realloc_unittest ${realloc_unittest_SOURCES})
|
|
target_link_libraries(realloc_unittest PUBLIC tcmalloc_minimal ${realloc_unittest_LDFLAGS})
|
|
add_test(realloc_unittest realloc_unittest)
|
|
|
|
add_executable(stack_trace_table_test src/tests/stack_trace_table_test.cc)
|
|
target_link_libraries(stack_trace_table_test PUBLIC tcmalloc_minimal)
|
|
add_test(stack_trace_table_test stack_trace_table_test)
|
|
|
|
add_executable(thread_dealloc_unittest
|
|
src/tests/thread_dealloc_unittest.cc
|
|
src/tests/testutil.cc)
|
|
target_link_libraries(thread_dealloc_unittest tcmalloc_minimal Threads::Threads)
|
|
add_test(thread_dealloc_unittest thread_dealloc_unittest)
|
|
endif()
|
|
|
|
### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation)
|
|
|
|
if(GPERFTOOLS_BUILD_DEBUGALLOC)
|
|
set(libtcmalloc_minimal_debug_la_SOURCES src/debugallocation.cc
|
|
${TCMALLOC_MINIMAL_INCLUDES})
|
|
add_library(tcmalloc_minimal_debug SHARED ${libtcmalloc_minimal_debug_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_minimal_debug PRIVATE ${libtcmalloc_minimal_la_DEFINES}
|
|
TCMALLOC_FOR_DEBUGALLOCATION)
|
|
target_link_libraries(tcmalloc_minimal_debug PRIVATE ${libtcmalloc_minimal_la_LIBADD})
|
|
weaken_object(tcmalloc_minimal_debug)
|
|
install(TARGETS tcmalloc_minimal_debug)
|
|
set_target_properties(tcmalloc_minimal_debug PROPERTIES
|
|
VERSION ${TCMALLOC_SO_VERSION}
|
|
SOVERSION ${TCMALLOC_SO_VERSION})
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
add_library(tcmalloc_minimal_debug_static STATIC ${libtcmalloc_minimal_debug_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_minimal_debug_static PRIVATE ${libtcmalloc_minimal_la_DEFINES}
|
|
TCMALLOC_FOR_DEBUGALLOCATION)
|
|
if(NOT MSVC)
|
|
set_target_properties(tcmalloc_minimal_debug_static PROPERTIES
|
|
OUTPUT_NAME tcmalloc_minimal_debug)
|
|
endif()
|
|
target_link_libraries(tcmalloc_minimal_debug_static PRIVATE ${libtcmalloc_minimal_la_LIBADD})
|
|
weaken_object(tcmalloc_minimal_debug_static)
|
|
install(TARGETS tcmalloc_minimal_debug_static)
|
|
endif()
|
|
|
|
### Unittests
|
|
|
|
if(BUILD_TESTING)
|
|
add_executable(tcmalloc_minimal_debug_unittest ${tcmalloc_minimal_unittest_SOURCES})
|
|
target_compile_definitions(tcmalloc_minimal_debug_unittest PRIVATE DEBUGALLOCATION)
|
|
target_link_libraries(tcmalloc_minimal_debug_unittest tcmalloc_minimal_debug ${tcmalloc_minimal_unittest_LDADD})
|
|
add_test(tcmalloc_minimal_debug_unittest tcmalloc_minimal_debug_unittest)
|
|
|
|
add_executable(malloc_extension_debug_test ${malloc_extension_test_SOURCES})
|
|
target_link_libraries(malloc_extension_debug_test tcmalloc_minimal_debug ${malloc_extension_test_LIBADD})
|
|
add_test(malloc_extension_debug_test malloc_extension_debug_test)
|
|
|
|
if(NOT MINGW AND NOT APPLE)
|
|
add_executable(memalign_debug_unittest ${memalign_unittest_SOURCES})
|
|
target_link_libraries(memalign_debug_unittest
|
|
tcmalloc_minimal_debug Threads::Threads)
|
|
add_test(memalign_debug_unittest memalign_debug_unittest)
|
|
endif()
|
|
|
|
add_executable(realloc_debug_unittest ${realloc_unittest_SOURCES})
|
|
target_link_libraries(realloc_debug_unittest PUBLIC tcmalloc_minimal_debug)
|
|
add_test(realloc_debug_unittest realloc_debug_unittest)
|
|
|
|
if(WITH_STACK_TRACE)
|
|
add_executable(debugallocation_test src/tests/debugallocation_test.cc)
|
|
target_link_libraries(debugallocation_test PUBLIC tcmalloc_minimal_debug Threads::Threads)
|
|
|
|
add_test(NAME debugallocation_test
|
|
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/tests/debugallocation_test.sh)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT MINGW AND NOT MSVC)
|
|
if(gperftools_build_benchmark)
|
|
add_library(run_benchmark benchmark/run_benchmark.c)
|
|
|
|
add_executable(malloc_bench benchmark/malloc_bench.cc)
|
|
target_link_libraries(malloc_bench run_benchmark ${TCMALLOC_FLAGS})
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
target_link_libraries(malloc_bench tcmalloc_minimal_static)
|
|
else()
|
|
target_link_libraries(malloc_bench tcmalloc_minimal)
|
|
endif()
|
|
add_executable(malloc_bench_shared benchmark/malloc_bench.cc)
|
|
target_link_libraries(malloc_bench_shared run_benchmark tcmalloc_minimal ${TCMALLOC_FLAGS} Threads::Threads)
|
|
|
|
if(GPERFTOOLS_BUILD_HEAP_CHECKER OR GPERFTOOLS_BUILD_HEAP_PROFILER)
|
|
add_executable(malloc_bench_shared_full benchmark/malloc_bench.cc)
|
|
target_link_libraries(malloc_bench_shared_full run_benchmark tcmalloc ${TCMALLOC_FLAGS} Threads::Threads)
|
|
endif()
|
|
|
|
add_executable(binary_trees benchmark/binary_trees.cc)
|
|
target_link_libraries(binary_trees Threads::Threads ${TCMALLOC_FLAGS})
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
target_link_libraries(binary_trees tcmalloc_minimal_static)
|
|
else()
|
|
target_link_libraries(binary_trees tcmalloc_minimal)
|
|
endif()
|
|
add_executable(binary_trees_shared benchmark/binary_trees.cc)
|
|
target_link_libraries(binary_trees_shared tcmalloc_minimal Threads::Threads ${TCMALLOC_FLAGS})
|
|
endif()
|
|
endif()
|
|
|
|
### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker)
|
|
|
|
if(GPERFTOOLS_BUILD_HEAP_CHECKER OR GPERFTOOLS_BUILD_HEAP_PROFILER)
|
|
### The header files we use. We divide into categories based on directory
|
|
set(S_TCMALLOC_INCLUDES ${S_TCMALLOC_MINIMAL_INCLUDES}
|
|
${LOGGING_INCLUDES}
|
|
src/addressmap-inl.h
|
|
src/raw_printer.h
|
|
src/base/elfcore.h
|
|
src/base/googleinit.h
|
|
src/base/linux_syscall_support.h
|
|
src/base/linuxthreads.h
|
|
src/base/stl_allocator.h
|
|
src/base/sysinfo.h
|
|
src/base/thread_lister.h
|
|
src/heap-profile-table.h
|
|
src/heap-profile-stats.h
|
|
src/maybe_emergency_malloc.h
|
|
src/emergency_malloc.h)
|
|
|
|
set(SG_TCMALLOC_INCLUDES src/gperftools/heap-profiler.h
|
|
src/gperftools/heap-checker.h)
|
|
set(TCMALLOC_INCLUDES ${S_TCMALLOC_INCLUDES} ${SG_TCMALLOC_MINIMAL_INCLUDES}
|
|
${SG_TCMALLOC_INCLUDES} ${SG_STACKTRACE_INCLUDES})
|
|
list(APPEND perftoolsinclude_HEADERS ${SG_TCMALLOC_INCLUDES})
|
|
|
|
if(gperftools_emergency_malloc)
|
|
set(EMERGENCY_MALLOC_CC
|
|
src/emergency_malloc.cc
|
|
src/emergency_malloc_for_stacktrace.cc)
|
|
set(EMERGENCY_MALLOC_DEFINE ENABLE_EMERGENCY_MALLOC)
|
|
else()
|
|
set(EMERGENCY_MALLOC_CC src/fake_stacktrace_scope.cc)
|
|
endif()
|
|
|
|
### Making the library
|
|
|
|
set(libtcmalloc_internal_la_SOURCES ${libtcmalloc_minimal_internal_la_SOURCES}
|
|
${TCMALLOC_INCLUDES}
|
|
src/base/low_level_alloc.cc
|
|
src/heap-profile-table.cc
|
|
src/heap-profiler.cc
|
|
src/raw_printer.cc
|
|
${EMERGENCY_MALLOC_CC}
|
|
src/memory_region_map.cc)
|
|
set(libtcmalloc_internal_la_DEFINE NDEBUG ${EMERGENCY_MALLOC_DEFINE})
|
|
set(libtcmalloc_internal_la_LIBADD stacktrace Threads::Threads)
|
|
|
|
set(libtcmalloc_la_SOURCES ${TCMALLOC_CC} ${TCMALLOC_INCLUDES})
|
|
set(libtcmalloc_la_DEFINE NDEBUG ${EMERGENCY_MALLOC_DEFINE})
|
|
set(libtcmalloc_la_LIBADD tcmalloc_internal ${maybe_threads_lib} Threads::Threads)
|
|
if(GPERFTOOLS_BUILD_HEAP_CHECKER)
|
|
# heap-checker-bcad is last, in hopes its global ctor will run first.
|
|
# (Note this is added to libtcmalloc.la, not libtcmalloc_internal.la,
|
|
# but that's ok; the internal/external distinction is only useful for
|
|
# cygwin, and cygwin doesn't use HEAP_CHECKER anyway.)
|
|
set(HEAP_CHECKER_SOURCES src/base/thread_lister.c
|
|
src/base/linuxthreads.cc
|
|
src/heap-checker.cc
|
|
src/heap-checker-bcad.cc)
|
|
list(APPEND libtcmalloc_la_SOURCES ${HEAP_CHECKER_SOURCES})
|
|
else()
|
|
list(APPEND libtcmalloc_internal_la_DEFINE NO_HEAP_CHECK)
|
|
list(APPEND libtcmalloc_la_DEFINE NO_HEAP_CHECK)
|
|
endif()
|
|
|
|
add_library(tcmalloc_internal_object OBJECT ${libtcmalloc_internal_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_internal_object PRIVATE ${libtcmalloc_internal_la_DEFINE})
|
|
add_library(tcmalloc_internal INTERFACE)
|
|
target_sources(tcmalloc_internal INTERFACE $<TARGET_OBJECTS:tcmalloc_internal_object>)
|
|
target_link_libraries(tcmalloc_internal INTERFACE ${libtcmalloc_internal_la_LIBADD})
|
|
|
|
add_library(tcmalloc SHARED ${libtcmalloc_la_SOURCES})
|
|
target_compile_definitions(tcmalloc PRIVATE ${libtcmalloc_la_DEFINE})
|
|
target_link_libraries(tcmalloc ${libtcmalloc_la_LIBADD})
|
|
set_target_properties(tcmalloc PROPERTIES
|
|
VERSION ${TCMALLOC_SO_VERSION}
|
|
SOVERSION ${TCMALLOC_SO_VERSION})
|
|
weaken_object(tcmalloc)
|
|
install(TARGETS tcmalloc)
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
add_library(tcmalloc_static STATIC ${libtcmalloc_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_static PRIVATE ${libtcmalloc_la_DEFINE})
|
|
if(NOT MSVC)
|
|
set_target_properties(tcmalloc_static PROPERTIES OUTPUT_NAME tcmalloc)
|
|
endif()
|
|
target_link_libraries(tcmalloc_static PRIVATE ${libtcmalloc_la_LIBADD})
|
|
weaken_object(tcmalloc_static)
|
|
install(TARGETS tcmalloc_static)
|
|
endif()
|
|
|
|
### Unittests
|
|
if(BUILD_TESTING)
|
|
set(TCMALLOC_UNITTEST_INCLUDES src/config_for_unittests.h
|
|
src/gperftools/malloc_extension.h)
|
|
set(tcmalloc_unittest_SOURCES src/tests/tcmalloc_unittest.cc
|
|
src/tcmalloc.h
|
|
src/tests/testutil.h src/tests/testutil.cc
|
|
${TCMALLOC_UNITTEST_INCLUDES})
|
|
set(tcmalloc_unittest_LIBADD ${TCMALLOC_FLAGS} logging Threads::Threads)
|
|
add_executable(tcmalloc_unittest ${tcmalloc_unittest_SOURCES})
|
|
target_link_libraries(tcmalloc_unittest tcmalloc ${tcmalloc_unittest_LIBADD})
|
|
add_test(NAME tcmalloc_unittest
|
|
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/tcmalloc_unittest.sh")
|
|
|
|
# This makes sure it's safe to link in both tcmalloc and
|
|
# tcmalloc_minimal. (One would never do this on purpose, but perhaps
|
|
# by accident...) When we can compile libprofiler, we also link it in
|
|
# to make sure that works too. NOTE: On OS X, it's *not* safe to
|
|
# link both in (we end up with two copies of every global var, and
|
|
# the code tends to pick one arbitrarily), so don't run the test there.
|
|
set(tcmalloc_both_unittest_srcs src/tests/tcmalloc_unittest.cc
|
|
src/tests/testutil.h src/tests/testutil.cc
|
|
${TCMALLOC_UNITTEST_INCLUDES})
|
|
if(GPERFTOOLS_BUILD_CPU_PROFILER)
|
|
set(tcmalloc_both_unittest_ladd tcmalloc tcmalloc_minimal profiler logging Threads::Threads)
|
|
else()
|
|
set(tcmalloc_both_unittest_ladd tcmalloc tcmalloc_minimal logging Threads::Threads)
|
|
endif()
|
|
if(NOT APPLE)
|
|
add_executable(tcmalloc_both_unittest ${tcmalloc_both_unittest_srcs})
|
|
target_link_libraries(tcmalloc_both_unittest ${TCMALLOC_FLAGS} ${tcmalloc_both_unittest_ladd})
|
|
add_test(tcmalloc_both_unittest tcmalloc_both_unittest)
|
|
endif()
|
|
|
|
add_executable(tcmalloc_large_unittest src/tests/tcmalloc_large_unittest.cc)
|
|
target_link_libraries(tcmalloc_large_unittest tcmalloc Threads::Threads)
|
|
add_test(tcmalloc_large_unittest tcmalloc_large_unittest)
|
|
|
|
add_executable(tcmalloc_large_heap_fragmentation_unittest src/tests/large_heap_fragmentation_unittest.cc)
|
|
target_link_libraries(tcmalloc_large_heap_fragmentation_unittest tcmalloc Threads::Threads)
|
|
add_test(tcmalloc_large_heap_fragmentation_unittest tcmalloc_large_heap_fragmentation_unittest)
|
|
|
|
add_executable(raw_printer_test src/tests/raw_printer_test.cc)
|
|
target_link_libraries(raw_printer_test tcmalloc Threads::Threads)
|
|
add_test(raw_printer_test raw_printer_test)
|
|
|
|
# sampler_test and sampling_test both require sampling to be turned
|
|
# on, which it's not by default. Use the "standard" value of 2^19.
|
|
list(APPEND TESTS_ENVIRONMENT TCMALLOC_SAMPLE_PARAMETER=524288)
|
|
|
|
set(sampler_test_SOURCES src/tests/sampler_test.cc
|
|
src/config_for_unittests.h)
|
|
set(sampler_test_LIBADD ${TCMALLOC_FLAGS} Threads::Threads m)
|
|
add_executable(sampler_test ${sampler_test_SOURCES})
|
|
target_link_libraries(sampler_test tcmalloc ${sampler_test_LIBADD})
|
|
add_test(sampler_test sampler_test)
|
|
|
|
# These unittests often need to run binaries. They're in the current dir
|
|
list(APPEND TESTS_ENVIRONMENT BINDIR=. TMPDIR=/tmp/perftools)
|
|
set(SAMPLING_TEST_INCLUDES src/config_for_unittests.h
|
|
src/base/logging.h
|
|
src/gperftools/malloc_extension.h)
|
|
set(sampling_test_SOURCES src/tests/sampling_test.cc
|
|
${SAMPLING_TEST_INCLUDES})
|
|
add_executable(sampling_test ${sampling_test_SOURCES})
|
|
target_link_libraries(sampling_test ${TCMALLOC_FLAGS} tcmalloc Threads::Threads)
|
|
add_test(NAME sampling_test.sh
|
|
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/sampling_test.sh" sampling_test)
|
|
if(GPERFTOOLS_BUILD_HEAP_PROFILER)
|
|
set(HEAP_PROFILER_UNITTEST_INCLUDES src/config_for_unittests.h
|
|
src/gperftools/heap-profiler.h)
|
|
set(heap_profiler_unittest_SOURCES src/tests/heap-profiler_unittest.cc
|
|
${HEAP_PROFILER_UNITTEST_INCLUDES})
|
|
add_executable(heap_profiler_unittest ${heap_profiler_unittest_SOURCES})
|
|
target_link_libraries(heap_profiler_unittest ${TCMALLOC_FLAGS} tcmalloc Threads::Threads)
|
|
add_test(NAME heap-profiler_unittest.sh
|
|
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/heap-profiler_unittest.sh" heap-profiler_unittest)
|
|
|
|
# Tests the compatibility include-headers in google/. Requires a function
|
|
# defined in the heap-profiler, which is why the test lives here.
|
|
add_executable(simple_compat_test src/tests/simple_compat_test.cc
|
|
${googleinclude_HEADERS})
|
|
target_link_libraries(simple_compat_test ${TCMALLOC_FLAGS} tcmalloc)
|
|
add_test(simple_compat_test simple_compat_test)
|
|
endif()
|
|
if(GPERFTOOLS_BUILD_HEAP_CHECKER)
|
|
set(HEAP_CHECKER_UNITTEST_INCLUDES src/config_for_unittests.h
|
|
src/memory_region_map.h
|
|
src/base/commandlineflags.h
|
|
src/base/googleinit.h
|
|
src/gperftools/heap-checker.h
|
|
${LOGGING_INCLUDES})
|
|
set(heap_checker_unittest_SOURCES src/tests/heap-checker_unittest.cc
|
|
${HEAP_CHECKER_UNITTEST_INCLUDES})
|
|
add_executable(heap_checker_unittest ${heap_checker_unittest_SOURCES})
|
|
target_link_libraries(heap_checker_unittest ${TCMALLOC_FLAGS} tcmalloc logging Threads::Threads)
|
|
add_test(NAME heap-checker_unittest.sh
|
|
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/heap-checker_unittest.sh" heap_checker_unittest)
|
|
add_test(NAME heap-checker-death_unittest.sh
|
|
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/heap-checker-death_unittest.sh")
|
|
endif()
|
|
endif()
|
|
|
|
endif()
|
|
|
|
### ------- tcmalloc with debugallocation
|
|
if(GPERFTOOLS_BUILD_DEBUGALLOC)
|
|
if(GPERFTOOLS_BUILD_HEAP_CHECKER OR GPERFTOOLS_BUILD_HEAP_PROFILER)
|
|
add_library(tcmalloc_debug SHARED src/debugallocation.cc ${HEAP_CHECKER_SOURCES} ${TCMALLOC_INCLUDES})
|
|
target_compile_definitions(tcmalloc_debug PRIVATE ${libtcmalloc_la_DEFINE}
|
|
TCMALLOC_FOR_DEBUGALLOCATION)
|
|
target_link_libraries(tcmalloc_debug PRIVATE ${libtcmalloc_la_LIBADD})
|
|
set_target_properties(tcmalloc_debug PROPERTIES
|
|
VERSION ${TCMALLOC_SO_VERSION}
|
|
SOVERSION ${TCMALLOC_SO_VERSION})
|
|
weaken_object(tcmalloc_debug)
|
|
install(TARGETS tcmalloc_debug)
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
add_library(tcmalloc_debug_static STATIC src/debugallocation.cc ${HEAP_CHECKER_SOURCES} ${TCMALLOC_INCLUDES})
|
|
target_compile_definitions(tcmalloc_debug_static PRIVATE ${libtcmalloc_la_DEFINE}
|
|
TCMALLOC_FOR_DEBUGALLOCATION)
|
|
target_link_libraries(tcmalloc_debug_static PRIVATE ${libtcmalloc_la_LIBADD})
|
|
if(NOT MSVC)
|
|
set_target_properties(tcmalloc_debug_static PROPERTIES
|
|
OUTPUT_NAME tcmalloc_debug)
|
|
endif()
|
|
weaken_object(tcmalloc_debug_static)
|
|
install(TARGETS tcmalloc_debug_static)
|
|
endif()
|
|
|
|
### Unittests
|
|
if(BUILD_TESTING)
|
|
add_executable(tcmalloc_debug_unittest ${tcmalloc_unittest_SOURCES})
|
|
target_compile_definitions(tcmalloc_debug_unittest PRIVATE DEBUGALLOCATION ${tcmalloc_unittest})
|
|
target_link_libraries(tcmalloc_debug_unittest tcmalloc_debug ${tcmalloc_unittest_LIBADD})
|
|
add_test(tcmalloc_debug_unittest tcmalloc_debug_unittest)
|
|
|
|
add_executable(sampler_debug_test ${sampler_test_SOURCES})
|
|
target_link_libraries(sampler_debug_test tcmalloc_debug ${tcmalloc_unittest_LIBADD})
|
|
add_test(sampler_debug_test sampler_debug_test)
|
|
|
|
add_executable(sampling_debug_test ${sampling_test_SOURCES})
|
|
target_link_libraries(sampling_debug_test ${TCMALLOC_FLAGS} tcmalloc_debug Threads::Threads)
|
|
add_test(sampling_debug_test.sh "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/sampling_test.sh" sampling_debug_test)
|
|
|
|
if(GPERFTOOLS_BUILD_HEAP_PROFILER)
|
|
add_executable(heap_profiler_debug_unittest ${heap_profiler_unittest_SOURCES})
|
|
target_link_libraries(heap_profiler_debug_unittest ${TCMALLOC_FLAGS} tcmalloc_debug Threads::Threads)
|
|
add_test(heap-profiler_debug_unittest.sh "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/heap-profiler_unittest.sh" heap-profiler_debug_unittest)
|
|
endif()
|
|
if(GPERFTOOLS_BUILD_HEAP_CHECKER)
|
|
add_executable(heap_checker_debug_unittest ${heap_checker_unittest_SOURCES})
|
|
target_link_libraries(heap_checker_debug_unittest ${TCMALLOC_FLAGS} tcmalloc_debug logging Threads::Threads)
|
|
add_test(heap-checker_debug_unittest.sh "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/heap-checker_unittest.sh" heap-checker_debug_unittest)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
### ------- CPU profiler
|
|
if(GPERFTOOLS_BUILD_CPU_PROFILER)
|
|
### The header files we use. We divide into categories based on directory
|
|
set(S_CPU_PROFILER_INCLUDES src/profiledata.h
|
|
src/profile-handler.h
|
|
src/getpc.h
|
|
src/base/basictypes.h
|
|
src/base/commandlineflags.h
|
|
src/base/googleinit.h
|
|
src/base/logging.h
|
|
src/base/simple_mutex.h
|
|
src/base/sysinfo.h
|
|
${SPINLOCK_INCLUDES}
|
|
${LOGGING_INCLUDES})
|
|
set(SG_CPU_PROFILER_INCLUDES src/gperftools/profiler.h)
|
|
set(CPU_PROFILER_INCLUDES ${S_CPU_PROFILER_INCLUDES} ${SG_CPU_PROFILER_INCLUDES}
|
|
${SG_STACKTRACE_INCLUDES})
|
|
list(APPEND perftoolsinclude_HEADERS ${SG_CPU_PROFILER_INCLUDES})
|
|
|
|
### Making the library
|
|
set(libprofiler_la_SOURCES src/profiler.cc
|
|
src/profile-handler.cc
|
|
src/profiledata.cc
|
|
${CPU_PROFILER_INCLUDES})
|
|
set(libprofiler_la_LIBADD stacktrace ${maybe_threads_lib} fake_stacktrace_scope)
|
|
add_library(profiler SHARED ${libprofiler_la_SOURCES})
|
|
target_link_libraries(profiler PRIVATE ${libprofiler_la_LIBADD})
|
|
set_target_properties(profiler PROPERTIES
|
|
VERSION ${PROFILER_SO_VERSION}
|
|
SOVERSION ${PROFILER_SO_VERSION})
|
|
install(TARGETS profiler)
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
add_library(profiler_static STATIC ${libprofiler_la_SOURCES})
|
|
target_link_libraries(profiler_static PRIVATE ${libprofiler_la_LIBADD})
|
|
if(NOT MSVC)
|
|
set_target_properties(profiler_static PROPERTIES OUTPUT_NAME profiler)
|
|
endif()
|
|
install(TARGETS profiler_static)
|
|
endif()
|
|
|
|
# See discussion above (under LIBTCMALLOC_MINIMAL) for why we do this.
|
|
# Basically it's to work around systems where --rpath doesn't work right.
|
|
set(LIBPROFILER stacktrace profiler)
|
|
|
|
if(BUILD_TESTING)
|
|
add_executable(getpc_test src/tests/getpc_test.cc src/getpc.h)
|
|
add_test(getpc_test getpc_test)
|
|
|
|
add_executable(profiledata_unittest src/tests/profiledata_unittest.cc
|
|
src/profiledata.h
|
|
src/base/commandlineflags.h
|
|
src/base/logging.h
|
|
src/base/basictypes.h)
|
|
target_link_libraries(profiledata_unittest ${LIBPROFILER})
|
|
add_test(profiledata_unittest profiledata_unittest)
|
|
|
|
add_executable(profile_handler_unittest src/tests/profile-handler_unittest.cc
|
|
src/profile-handler.h)
|
|
target_link_libraries(profile_handler_unittest ${LIBPROFILER} Threads::Threads)
|
|
add_test(profile_handler_unittest profile_handler_unittest)
|
|
|
|
add_test(NAME profiler_unittest.sh
|
|
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/profiler_unittest.sh")
|
|
set(PROFILER_UNITTEST_INCLUDES src/config_for_unittests.h
|
|
src/gperftools/profiler.h)
|
|
set(PROFILER_UNITTEST_SRCS src/tests/profiler_unittest.cc
|
|
src/tests/testutil.h src/tests/testutil.cc
|
|
${PROFILER_UNITTEST_INCLUDES})
|
|
add_executable(profiler1_unittest ${PROFILER_UNITTEST_SRCS})
|
|
target_compile_definitions(profiler1_unittest PRIVATE NO_THREADS)
|
|
target_link_libraries(profiler1_unittest ${LIBPROFILER})
|
|
add_executable(profiler2_unittest ${PROFILER_UNITTEST_SRCS})
|
|
target_compile_definitions(profiler2_unittest PRIVATE NO_THREADS)
|
|
target_link_libraries(profiler2_unittest stacktrace profiler)
|
|
add_executable(profiler3_unittest ${PROFILER_UNITTEST_SRCS})
|
|
target_link_libraries(profiler3_unittest ${LIBPROFILER} Threads::Threads)
|
|
add_executable(profiler4_unittest ${PROFILER_UNITTEST_SRCS})
|
|
target_link_libraries(profiler4_unittest stacktrace profiler Threads::Threads)
|
|
endif()
|
|
endif()
|
|
|
|
install(FILES
|
|
${CMAKE_CURRENT_BINARY_DIR}/gperftools/tcmalloc.h
|
|
${perftoolsinclude_HEADERS}
|
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gperftools)
|
|
|
|
### ------- CPU profiler and heap checker, in one!
|
|
|
|
# Ideally, folks who wanted to use both tcmalloc and libprofiler,
|
|
# could just link them both into their application. But while this
|
|
# works fine for .so files, it does not for .a files. The easiest way
|
|
# around this -- and I've tried a bunch of the hard ways -- is to just
|
|
# to create another set of libraries that has both functionality in it.
|
|
|
|
if(GPERFTOOLS_BUILD_HEAP_PROFILER OR GPERFTOOLS_BUILD_HEAP_CHECKER)
|
|
if(GPERFTOOLS_BUILD_CPU_PROFILER)
|
|
add_library(tcmalloc_and_profiler SHARED ${libtcmalloc_la_SOURCES} ${libprofiler_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_and_profiler PRIVATE ${libtcmalloc_la_DEFINE})
|
|
set_target_properties(tcmalloc_and_profiler PROPERTIES
|
|
VERSION ${TCMALLOC_AND_PROFILER_SO_VERSION}
|
|
SOVERSION ${TCMALLOC_AND_PROFILER_SO_VERSION})
|
|
# We don't include libprofiler_la_LIBADD here because all it adds is
|
|
# libstacktrace.la, which we already get via libtcmalloc. Trying to
|
|
# specify it twice causes link-time duplicate-definition errors. :-(
|
|
target_link_libraries(tcmalloc_and_profiler PRIVATE ${libtcmalloc_la_LIBADD})
|
|
weaken_object(tcmalloc_and_profiler)
|
|
install(TARGETS tcmalloc_and_profiler)
|
|
if(GPERFTOOLS_BUILD_STATIC)
|
|
add_library(tcmalloc_and_profiler_static STATIC ${libtcmalloc_la_SOURCES} ${libprofiler_la_SOURCES})
|
|
target_compile_definitions(tcmalloc_and_profiler_static PRIVATE ${libtcmalloc_la_DEFINE})
|
|
target_link_libraries(tcmalloc_and_profiler_static PRIVATE ${libtcmalloc_la_LIBADD})
|
|
if(NOT MSVC)
|
|
set_target_properties(tcmalloc_and_profiler_static PROPERTIES
|
|
OUTPUT_NAME tcmalloc_and_profiler)
|
|
endif()
|
|
weaken_object(tcmalloc_and_profiler_static)
|
|
install(TARGETS tcmalloc_and_profiler_static)
|
|
endif()
|
|
|
|
if(BUILD_TESTING)
|
|
add_executable(tcmalloc_and_profiler_unittest ${tcmalloc_both_unittest_srcs})
|
|
target_link_libraries(tcmalloc_and_profiler_unittest tcmalloc_and_profiler Threads::Threads)
|
|
add_test(tcmalloc_and_profiler_unittest tcmalloc_and_profiler_unittest)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(BUILD_TESTING)
|
|
get_directory_property(tests TESTS)
|
|
message("TESTS_ENVIRONMENT:${TESTS_ENVIRONMENT}")
|
|
if(TESTS_ENVIRONMENT)
|
|
foreach(test IN LISTS tests)
|
|
set_tests_properties(${test} PROPERTIES ENVIRONMENT "${TESTS_ENVIRONMENT}")
|
|
endforeach()
|
|
endif()
|
|
endif()
|
|
|
|
if(MSVC)
|
|
add_subdirectory(src/windows)
|
|
endif()
|
|
|
|
## ^^^^ END OF RULES TO MAKE YOUR LIBRARIES, BINARIES, AND UNITTESTS
|
|
#TODO rpm deb
|
|
|
|
# http://linux.die.net/man/1/pkg-config, http://pkg-config.freedesktop.org/wiki
|
|
# I get the description and URL lines from the rpm spec. I use sed to
|
|
# try to rewrite exec_prefix, libdir, and includedir in terms of
|
|
# prefix, if possible.
|
|
set(PTHREAD_FLAGS)
|
|
foreach(flag IN ITEMS INTERFACE_LINK_LIBRARIES INTERFACE_LINK_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_COMPILE_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_SOURCES)
|
|
get_target_property(T Threads::Threads ${flag})
|
|
if(T)
|
|
set(PTHREAD_FLAGS "${PTHREAD_FLAGS} ${T}")
|
|
endif()
|
|
endforeach()
|
|
set(NAME tcmalloc)
|
|
configure_file(cmake/pkgconfig.pc libtcmalloc.pc @ONLY)
|
|
set(NAME tcmalloc_debug)
|
|
configure_file(cmake/pkgconfig.pc libtcmalloc_debug.pc @ONLY)
|
|
set(NAME tcmalloc_minimal)
|
|
configure_file(cmake/pkgconfig.pc libtcmalloc_minimal.pc @ONLY)
|
|
set(NAME tcmalloc_minimal_debug)
|
|
configure_file(cmake/pkgconfig.pc libtcmalloc_minimal_debug.pc @ONLY)
|
|
set(NAME profiler)
|
|
configure_file(cmake/pkgconfig.pc libprofiler.pc @ONLY)
|
|
install(FILES
|
|
${CMAKE_CURRENT_BINARY_DIR}/libtcmalloc.pc
|
|
${CMAKE_CURRENT_BINARY_DIR}/libtcmalloc_minimal.pc
|
|
${CMAKE_CURRENT_BINARY_DIR}/libtcmalloc_debug.pc
|
|
${CMAKE_CURRENT_BINARY_DIR}/libtcmalloc_minimal_debug.pc
|
|
${CMAKE_CURRENT_BINARY_DIR}/libprofiler.pc
|
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
|
|
|
#TODO @GENERATE_CHANGELOG_RULES@
|
|
#TODO dist
|