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(DTRACE AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD"
46     AND NOT BUGGY_GCC_NO_DTRACE_MODULES)
47   SET(ENABLE_DTRACE ON CACHE BOOL "Enable dtrace")
48 ENDIF()
49 SET(HAVE_DTRACE ${ENABLE_DTRACE})
50 EXECUTE_PROCESS(
51   COMMAND ${DTRACE} -V
52   OUTPUT_VARIABLE out)
53 IF(out MATCHES "Sun D" OR out MATCHES "Oracle D")
54   IF(NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD" AND
55      NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
56     SET(HAVE_REAL_DTRACE_INSTRUMENTING ON CACHE BOOL "Real DTrace detected")
57   ENDIF()
58 ENDIF()
59 IF(HAVE_REAL_DTRACE_INSTRUMENTING)
60   IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
61     SET(DTRACE_FLAGS -32 CACHE INTERNAL "DTrace architecture flags")
62   ELSE()
63     SET(DTRACE_FLAGS -64 CACHE INTERNAL "DTrace architecture flags")
64   ENDIF()
65 ENDIF()
66ENDMACRO()
67
68CHECK_DTRACE()
69
70# Produce a header file  with
71# DTrace macros
72MACRO (DTRACE_HEADER provider header header_no_dtrace)
73 IF(ENABLE_DTRACE)
74 ADD_CUSTOM_COMMAND(
75   OUTPUT  ${header} ${header_no_dtrace}
76   COMMAND ${DTRACE} -h -s ${provider} -o ${header}
77   COMMAND perl ${CMAKE_SOURCE_DIR}/scripts/dheadgen.pl -f ${provider} > ${header_no_dtrace}
78   DEPENDS ${provider}
79 )
80 ENDIF()
81ENDMACRO()
82
83
84# Create provider headers
85IF(ENABLE_DTRACE)
86  CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/probes_mysql.d.base
87    ${CMAKE_BINARY_DIR}/include/probes_mysql.d COPYONLY)
88  DTRACE_HEADER(
89   ${CMAKE_BINARY_DIR}/include/probes_mysql.d
90   ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h
91   ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h
92  )
93  ADD_CUSTOM_TARGET(gen_dtrace_header
94  DEPENDS
95  ${CMAKE_BINARY_DIR}/include/probes_mysql.d
96  ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h
97  ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h
98  )
99ENDIF()
100
101FUNCTION(DTRACE_INSTRUMENT target)
102  IF(BUGGY_GCC_NO_DTRACE_MODULES)
103    GET_TARGET_PROPERTY(target_type ${target} TYPE)
104    IF(target_type MATCHES "MODULE_LIBRARY")
105      RETURN()
106    ENDIF()
107  ENDIF()
108  IF(ENABLE_DTRACE)
109    ADD_DEPENDENCIES(${target} gen_dtrace_header)
110
111    # Invoke dtrace to generate object file and link it together with target.
112    IF(HAVE_REAL_DTRACE_INSTRUMENTING)
113      SET(objdir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}.dir)
114      SET(outfile ${objdir}/${target}_dtrace.o)
115      GET_TARGET_PROPERTY(target_type ${target} TYPE)
116      ADD_CUSTOM_COMMAND(
117        TARGET ${target} PRE_LINK
118        COMMAND ${CMAKE_COMMAND}
119          -DDTRACE=${DTRACE}
120          -DOUTFILE=${outfile}
121          -DDFILE=${CMAKE_BINARY_DIR}/include/probes_mysql.d
122          -DDTRACE_FLAGS=${DTRACE_FLAGS}
123          -DDIRS=.
124          -DTYPE=${target_type}
125          -P ${CMAKE_SOURCE_DIR}/cmake/dtrace_prelink.cmake
126        WORKING_DIRECTORY ${objdir}
127      )
128    ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
129      # dtrace on Linux runs gcc and uses flags from environment
130      SET(CFLAGS_SAVED $ENV{CFLAGS})
131      # We want to strip off all warning flags, including -Werror=xxx-xx,
132      # but keep flags like
133      #  -Wp,-D_FORTIFY_SOURCE=2
134      STRING(REGEX REPLACE "-W[A-Za-z0-9][-A-Za-z0-9=]+" ""
135        C_FLAGS "${CMAKE_C_FLAGS}")
136
137      SET(ENV{CFLAGS} ${C_FLAGS})
138      SET(outfile "${CMAKE_BINARY_DIR}/probes_mysql.o")
139      # Systemtap object
140      EXECUTE_PROCESS(
141        COMMAND ${DTRACE} -G -s ${CMAKE_SOURCE_DIR}/include/probes_mysql.d.base
142        -o ${outfile}
143        )
144      SET(ENV{CFLAGS} ${CFLAGS_SAVED})
145    ENDIF()
146
147    # Do not try to extend the library if we have not built the .o file
148    IF(outfile)
149      # Add full  object path to linker flags
150      GET_TARGET_PROPERTY(target_type ${target} TYPE)
151      IF(NOT target_type MATCHES "STATIC")
152        SET_TARGET_PROPERTIES(${target} PROPERTIES LINK_FLAGS "${outfile}")
153      ELSE()
154        # For static library flags, add the object to the library.
155        # Note: DTrace probes in static libraries are  unusable currently
156        # (see explanation for DTRACE_INSTRUMENT_STATIC_LIBS below)
157        # but maybe one day this will be fixed.
158        GET_TARGET_PROPERTY(target_location ${target} LOCATION)
159        ADD_CUSTOM_COMMAND(
160          TARGET ${target} POST_BUILD
161          COMMAND ${CMAKE_AR} r  ${target_location} ${outfile}
162	  COMMAND ${CMAKE_RANLIB} ${target_location}
163          )
164        # Used in DTRACE_INSTRUMENT_WITH_STATIC_LIBS
165        SET(TARGET_OBJECT_DIRECTORY_${target}  ${objdir} CACHE INTERNAL "")
166      ENDIF()
167    ENDIF()
168  ENDIF()
169ENDFUNCTION()
170
171
172# Ugly workaround for Solaris' DTrace inability to use probes
173# from static libraries, discussed e.g in this thread
174# (http://opensolaris.org/jive/thread.jspa?messageID=432454)
175# We have to collect all object files that may be instrumented
176# and go into the mysqld (also those that come from in static libs)
177# run them again through dtrace -G to generate an ELF file that links
178# to mysqld.
179MACRO (DTRACE_INSTRUMENT_STATIC_LIBS target libs)
180IF(HAVE_REAL_DTRACE_INSTRUMENTING AND ENABLE_DTRACE)
181  # Filter out non-static libraries in the list, if any
182  SET(static_libs)
183  FOREACH(lib ${libs})
184    GET_TARGET_PROPERTY(libtype ${lib} TYPE)
185    IF(libtype MATCHES STATIC_LIBRARY)
186      SET(static_libs ${static_libs} ${lib})
187    ENDIF()
188  ENDFOREACH()
189
190  FOREACH(lib ${static_libs})
191    SET(dirs ${dirs} ${TARGET_OBJECT_DIRECTORY_${lib}})
192  ENDFOREACH()
193
194  SET (obj ${CMAKE_CURRENT_BINARY_DIR}/${target}_dtrace_all.o)
195  ADD_CUSTOM_COMMAND(
196  OUTPUT ${obj}
197  DEPENDS ${static_libs}
198  COMMAND ${CMAKE_COMMAND}
199   -DDTRACE=${DTRACE}
200   -DOUTFILE=${obj}
201   -DDFILE=${CMAKE_BINARY_DIR}/include/probes_mysql.d
202   -DDTRACE_FLAGS=${DTRACE_FLAGS}
203   "-DDIRS=${dirs}"
204   -DTYPE=MERGE
205   -P ${CMAKE_SOURCE_DIR}/cmake/dtrace_prelink.cmake
206   VERBATIM
207  )
208  ADD_CUSTOM_TARGET(${target}_dtrace_all  DEPENDS ${obj})
209  ADD_DEPENDENCIES(${target} ${target}_dtrace_all)
210  TARGET_LINK_LIBRARIES(${target} ${obj})
211ENDIF()
212ENDMACRO()
213