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