1# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; version 2 of the License.
6#
7# This program is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10# GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with this program; if not, write to the Free Software
14# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA
15
16IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_COMPILER_IS_GNUCXX
17  AND CMAKE_SIZEOF_VOID_P EQUAL 4)
18  IF(NOT DEFINED BUGGY_GCC_NO_DTRACE_MODULES)
19    EXECUTE_PROCESS(
20      COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}  --version
21      OUTPUT_VARIABLE out)
22    IF(out MATCHES "3.4.6")
23     # This gcc causes crashes in dlopen() for dtraced shared libs,
24     # while standard shipped with Solaris10 3.4.3 is ok
25     SET(BUGGY_GCC_NO_DTRACE_MODULES 1 CACHE INTERNAL "")
26    ELSE()
27     SET(BUGGY_GCC_NO_DTRACE_MODULES 0 CACHE INTERNAL "")
28    ENDIF()
29  ENDIF()
30ENDIF()
31
32# Check if OS supports DTrace
33MACRO(CHECK_DTRACE)
34 FIND_PROGRAM(DTRACE dtrace)
35 MARK_AS_ADVANCED(DTRACE)
36
37 IF(CMAKE_C_COMPILER MATCHES "ccache" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
38   # dtrace fails on fedora if  CC='ccache gcc' is used
39   SET(BUGGY_LINUX_DTRACE 1)
40 ENDIF()
41
42 # On FreeBSD, dtrace does not handle userland tracing yet
43 IF(DTRACE AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD"
44     AND NOT BUGGY_GCC_NO_DTRACE_MODULES
45     AND NOT BUGGY_LINUX_DTRACE
46     AND NOT CMAKE_SYSTEM_NAME MATCHES "SunOS"
47     AND NOT WIN32)
48   SET(ENABLE_DTRACE ON CACHE BOOL "Enable dtrace")
49 ENDIF()
50 # On GNU/Hurd, dtrace is not supported
51 IF(DTRACE AND CMAKE_SYSTEM_NAME MATCHES "GNU")
52   SET(ENABLE_DTRACE OFF CACHE BOOL "Disable dtrace")
53 ENDIF()
54 SET(HAVE_DTRACE ${ENABLE_DTRACE})
55 IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
56   IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
57     SET(DTRACE_FLAGS -32 CACHE INTERNAL "DTrace architecture flags")
58   ELSE()
59     SET(DTRACE_FLAGS -64 CACHE INTERNAL "DTrace architecture flags")
60   ENDIF()
61 ENDIF()
62ENDMACRO()
63
64CHECK_DTRACE()
65
66# Produce a header file  with
67# DTrace macros
68MACRO (DTRACE_HEADER provider header header_no_dtrace)
69 IF(ENABLE_DTRACE)
70 ADD_CUSTOM_COMMAND(
71   OUTPUT  ${header} ${header_no_dtrace}
72   COMMAND ${DTRACE} -h -s ${provider} -o ${header}
73   COMMAND perl ${CMAKE_SOURCE_DIR}/scripts/dheadgen.pl -f ${provider} > ${header_no_dtrace}
74   DEPENDS ${provider}
75 )
76 ENDIF()
77ENDMACRO()
78
79
80# Create provider headers
81IF(ENABLE_DTRACE)
82  CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/probes_mysql.d.base
83    ${CMAKE_BINARY_DIR}/include/probes_mysql.d COPYONLY)
84  DTRACE_HEADER(
85   ${CMAKE_BINARY_DIR}/include/probes_mysql.d
86   ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h
87   ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h
88  )
89  ADD_CUSTOM_TARGET(gen_dtrace_header
90  DEPENDS
91  ${CMAKE_BINARY_DIR}/include/probes_mysql.d
92  ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h
93  ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h
94  )
95ELSE()
96 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/probes_mysql_nodtrace.h.in
97   ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h COPYONLY)
98ENDIF()
99
100FUNCTION(DTRACE_INSTRUMENT target)
101  IF(BUGGY_GCC_NO_DTRACE_MODULES)
102    GET_TARGET_PROPERTY(target_type ${target} TYPE)
103    IF(target_type MATCHES "MODULE_LIBRARY")
104      RETURN()
105    ENDIF()
106  ENDIF()
107  IF(ENABLE_DTRACE)
108    ADD_DEPENDENCIES(${target} gen_dtrace_header)
109
110    # Invoke dtrace to generate object file and link it together with target.
111    IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
112      SET(objdir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}.dir)
113      SET(outfile ${objdir}/${target}_dtrace.o)
114      GET_TARGET_PROPERTY(target_type ${target} TYPE)
115      ADD_CUSTOM_COMMAND(
116        TARGET ${target} PRE_LINK
117        COMMAND ${CMAKE_COMMAND}
118          -DDTRACE=${DTRACE}
119          -DOUTFILE=${outfile}
120          -DDFILE=${CMAKE_BINARY_DIR}/include/probes_mysql.d
121          -DDTRACE_FLAGS=${DTRACE_FLAGS}
122          -DDIRS=.
123          -DTYPE=${target_type}
124          -P ${CMAKE_SOURCE_DIR}/cmake/dtrace_prelink.cmake
125        WORKING_DIRECTORY ${objdir}
126      )
127    ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
128      # dtrace on Linux runs gcc and uses flags from environment
129      SET(CFLAGS_SAVED $ENV{CFLAGS})
130      SET(ENV{CFLAGS} ${CMAKE_C_FLAGS})
131      SET(outfile "${CMAKE_BINARY_DIR}/probes_mysql.o")
132      # Systemtap object
133      EXECUTE_PROCESS(
134        COMMAND ${DTRACE} -G -s ${CMAKE_SOURCE_DIR}/include/probes_mysql.d.base
135        -o ${outfile}
136        )
137      SET(ENV{CFLAGS} ${CFLAGS_SAVED})
138    ENDIF()
139
140    # Do not try to extend the library if we have not built the .o file
141    IF(outfile)
142      # Add full  object path to linker flags
143      GET_TARGET_PROPERTY(target_type ${target} TYPE)
144      IF(NOT target_type MATCHES "STATIC")
145        SET_TARGET_PROPERTIES(${target} PROPERTIES LINK_FLAGS "${outfile}")
146      ELSE()
147        # For static library flags, add the object to the library.
148        # Note: DTrace probes in static libraries are  unusable currently
149        # (see explanation for DTRACE_INSTRUMENT_STATIC_LIBS below)
150        # but maybe one day this will be fixed.
151        ADD_CUSTOM_COMMAND(
152          TARGET ${target} POST_BUILD
153          COMMAND ${CMAKE_AR} r  $<TARGET_FILE:${target}> ${outfile}
154          COMMAND ${CMAKE_RANLIB} $<TARGET_FILE:${target}>
155          )
156        # Used in DTRACE_INSTRUMENT_WITH_STATIC_LIBS
157        SET(TARGET_OBJECT_DIRECTORY_${target}  ${objdir} CACHE INTERNAL "")
158      ENDIF()
159    ENDIF()
160  ENDIF()
161ENDFUNCTION()
162
163
164# Ugly workaround for Solaris' DTrace inability to use probes
165# from static libraries, discussed e.g in this thread
166# (http://opensolaris.org/jive/thread.jspa?messageID=432454)
167# We have to collect all object files that may be instrumented
168# and go into the mysqld (also those that come from in static libs)
169# run them again through dtrace -G to generate an ELF file that links
170# to mysqld.
171MACRO (DTRACE_INSTRUMENT_STATIC_LIBS target libs)
172IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND ENABLE_DTRACE)
173  # Filter out non-static libraries in the list, if any
174  SET(static_libs)
175  FOREACH(lib ${libs})
176    GET_TARGET_PROPERTY(libtype ${lib} TYPE)
177    IF(libtype MATCHES STATIC_LIBRARY)
178      SET(static_libs ${static_libs} ${lib})
179    ENDIF()
180  ENDFOREACH()
181
182  FOREACH(lib ${static_libs})
183    SET(dirs ${dirs} ${TARGET_OBJECT_DIRECTORY_${lib}})
184  ENDFOREACH()
185
186  SET (obj ${CMAKE_CURRENT_BINARY_DIR}/${target}_dtrace_all.o)
187  ADD_CUSTOM_COMMAND(
188  OUTPUT ${obj}
189  DEPENDS ${static_libs}
190  COMMAND ${CMAKE_COMMAND}
191   -DDTRACE=${DTRACE}
192   -DOUTFILE=${obj}
193   -DDFILE=${CMAKE_BINARY_DIR}/include/probes_mysql.d
194   -DDTRACE_FLAGS=${DTRACE_FLAGS}
195   "-DDIRS=${dirs}"
196   -DTYPE=MERGE
197   -P ${CMAKE_SOURCE_DIR}/cmake/dtrace_prelink.cmake
198   VERBATIM
199  )
200  ADD_CUSTOM_TARGET(${target}_dtrace_all  DEPENDS ${obj})
201  ADD_DEPENDENCIES(${target} ${target}_dtrace_all)
202  TARGET_LINK_LIBRARIES(${target} ${obj})
203ENDIF()
204ENDMACRO()
205