diff options
Diffstat (limited to 'cmake/dtrace.cmake')
-rw-r--r-- | cmake/dtrace.cmake | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/cmake/dtrace.cmake b/cmake/dtrace.cmake new file mode 100644 index 00000000..dae3b56b --- /dev/null +++ b/cmake/dtrace.cmake @@ -0,0 +1,204 @@ +# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA + +IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_COMPILER_IS_GNUCXX + AND CMAKE_SIZEOF_VOID_P EQUAL 4) + IF(NOT DEFINED BUGGY_GCC_NO_DTRACE_MODULES) + EXECUTE_PROCESS( + COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} --version + OUTPUT_VARIABLE out) + IF(out MATCHES "3.4.6") + # This gcc causes crashes in dlopen() for dtraced shared libs, + # while standard shipped with Solaris10 3.4.3 is ok + SET(BUGGY_GCC_NO_DTRACE_MODULES 1 CACHE INTERNAL "") + ELSE() + SET(BUGGY_GCC_NO_DTRACE_MODULES 0 CACHE INTERNAL "") + ENDIF() + ENDIF() +ENDIF() + +# Check if OS supports DTrace +MACRO(CHECK_DTRACE) + FIND_PROGRAM(DTRACE dtrace) + MARK_AS_ADVANCED(DTRACE) + + IF(CMAKE_C_COMPILER MATCHES "ccache" AND CMAKE_SYSTEM_NAME MATCHES "Linux") + # dtrace fails on fedora if CC='ccache gcc' is used + SET(BUGGY_LINUX_DTRACE 1) + ENDIF() + + # On FreeBSD, dtrace does not handle userland tracing yet + IF(DTRACE AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD" + AND NOT BUGGY_GCC_NO_DTRACE_MODULES + AND NOT BUGGY_LINUX_DTRACE + AND NOT CMAKE_SYSTEM_NAME MATCHES "SunOS" + AND NOT WIN32) + SET(ENABLE_DTRACE ON CACHE BOOL "Enable dtrace") + ENDIF() + # On GNU/Hurd, dtrace is not supported + IF(DTRACE AND CMAKE_SYSTEM_NAME MATCHES "GNU") + SET(ENABLE_DTRACE OFF CACHE BOOL "Disable dtrace") + ENDIF() + SET(HAVE_DTRACE ${ENABLE_DTRACE}) + IF(CMAKE_SYSTEM_NAME MATCHES "SunOS") + IF(CMAKE_SIZEOF_VOID_P EQUAL 4) + SET(DTRACE_FLAGS -32 CACHE INTERNAL "DTrace architecture flags") + ELSE() + SET(DTRACE_FLAGS -64 CACHE INTERNAL "DTrace architecture flags") + ENDIF() + ENDIF() +ENDMACRO() + +CHECK_DTRACE() + +# Produce a header file with +# DTrace macros +MACRO (DTRACE_HEADER provider header header_no_dtrace) + IF(ENABLE_DTRACE) + ADD_CUSTOM_COMMAND( + OUTPUT ${header} ${header_no_dtrace} + COMMAND ${DTRACE} -h -s ${provider} -o ${header} + COMMAND perl ${CMAKE_SOURCE_DIR}/scripts/dheadgen.pl -f ${provider} > ${header_no_dtrace} + DEPENDS ${provider} + ) + ENDIF() +ENDMACRO() + + +# Create provider headers +IF(ENABLE_DTRACE) + CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/probes_mysql.d.base + ${CMAKE_BINARY_DIR}/include/probes_mysql.d COPYONLY) + DTRACE_HEADER( + ${CMAKE_BINARY_DIR}/include/probes_mysql.d + ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h + ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h + ) + ADD_CUSTOM_TARGET(gen_dtrace_header + DEPENDS + ${CMAKE_BINARY_DIR}/include/probes_mysql.d + ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h + ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h + ) +ELSE() + CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/probes_mysql_nodtrace.h.in + ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h COPYONLY) +ENDIF() + +FUNCTION(DTRACE_INSTRUMENT target) + IF(BUGGY_GCC_NO_DTRACE_MODULES) + GET_TARGET_PROPERTY(target_type ${target} TYPE) + IF(target_type MATCHES "MODULE_LIBRARY") + RETURN() + ENDIF() + ENDIF() + IF(ENABLE_DTRACE) + ADD_DEPENDENCIES(${target} gen_dtrace_header) + + # Invoke dtrace to generate object file and link it together with target. + IF(CMAKE_SYSTEM_NAME MATCHES "SunOS") + SET(objdir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}.dir) + SET(outfile ${objdir}/${target}_dtrace.o) + GET_TARGET_PROPERTY(target_type ${target} TYPE) + ADD_CUSTOM_COMMAND( + TARGET ${target} PRE_LINK + COMMAND ${CMAKE_COMMAND} + -DDTRACE=${DTRACE} + -DOUTFILE=${outfile} + -DDFILE=${CMAKE_BINARY_DIR}/include/probes_mysql.d + -DDTRACE_FLAGS=${DTRACE_FLAGS} + -DDIRS=. + -DTYPE=${target_type} + -P ${CMAKE_SOURCE_DIR}/cmake/dtrace_prelink.cmake + WORKING_DIRECTORY ${objdir} + ) + ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") + # dtrace on Linux runs gcc and uses flags from environment + SET(CFLAGS_SAVED $ENV{CFLAGS}) + SET(ENV{CFLAGS} ${CMAKE_C_FLAGS}) + SET(outfile "${CMAKE_BINARY_DIR}/probes_mysql.o") + # Systemtap object + EXECUTE_PROCESS( + COMMAND ${DTRACE} -G -s ${CMAKE_SOURCE_DIR}/include/probes_mysql.d.base + -o ${outfile} + ) + SET(ENV{CFLAGS} ${CFLAGS_SAVED}) + ENDIF() + + # Do not try to extend the library if we have not built the .o file + IF(outfile) + # Add full object path to linker flags + GET_TARGET_PROPERTY(target_type ${target} TYPE) + IF(NOT target_type MATCHES "STATIC") + SET_TARGET_PROPERTIES(${target} PROPERTIES LINK_FLAGS "${outfile}") + ELSE() + # For static library flags, add the object to the library. + # Note: DTrace probes in static libraries are unusable currently + # (see explanation for DTRACE_INSTRUMENT_STATIC_LIBS below) + # but maybe one day this will be fixed. + ADD_CUSTOM_COMMAND( + TARGET ${target} POST_BUILD + COMMAND ${CMAKE_AR} r $<TARGET_FILE:${target}> ${outfile} + COMMAND ${CMAKE_RANLIB} $<TARGET_FILE:${target}> + ) + # Used in DTRACE_INSTRUMENT_WITH_STATIC_LIBS + SET(TARGET_OBJECT_DIRECTORY_${target} ${objdir} CACHE INTERNAL "") + ENDIF() + ENDIF() + ENDIF() +ENDFUNCTION() + + +# Ugly workaround for Solaris' DTrace inability to use probes +# from static libraries, discussed e.g in this thread +# (http://opensolaris.org/jive/thread.jspa?messageID=432454) +# We have to collect all object files that may be instrumented +# and go into the mysqld (also those that come from in static libs) +# run them again through dtrace -G to generate an ELF file that links +# to mysqld. +MACRO (DTRACE_INSTRUMENT_STATIC_LIBS target libs) +IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND ENABLE_DTRACE) + # Filter out non-static libraries in the list, if any + SET(static_libs) + FOREACH(lib ${libs}) + GET_TARGET_PROPERTY(libtype ${lib} TYPE) + IF(libtype MATCHES STATIC_LIBRARY) + SET(static_libs ${static_libs} ${lib}) + ENDIF() + ENDFOREACH() + + FOREACH(lib ${static_libs}) + SET(dirs ${dirs} ${TARGET_OBJECT_DIRECTORY_${lib}}) + ENDFOREACH() + + SET (obj ${CMAKE_CURRENT_BINARY_DIR}/${target}_dtrace_all.o) + ADD_CUSTOM_COMMAND( + OUTPUT ${obj} + DEPENDS ${static_libs} + COMMAND ${CMAKE_COMMAND} + -DDTRACE=${DTRACE} + -DOUTFILE=${obj} + -DDFILE=${CMAKE_BINARY_DIR}/include/probes_mysql.d + -DDTRACE_FLAGS=${DTRACE_FLAGS} + "-DDIRS=${dirs}" + -DTYPE=MERGE + -P ${CMAKE_SOURCE_DIR}/cmake/dtrace_prelink.cmake + VERBATIM + ) + ADD_CUSTOM_TARGET(${target}_dtrace_all DEPENDS ${obj}) + ADD_DEPENDENCIES(${target} ${target}_dtrace_all) + TARGET_LINK_LIBRARIES(${target} ${obj}) +ENDIF() +ENDMACRO() |