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