1# Copyright (c) 2009, 2018, Oracle and/or its affiliates.
2# Copyright (c) 2011, 2019, MariaDB Corporation.
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; version 2 of the License.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA
16
17
18INCLUDE(CMakeParseArguments)
19
20# MYSQL_ADD_PLUGIN(plugin_name source1...sourceN
21# [STORAGE_ENGINE]
22# [STATIC_ONLY|MODULE_ONLY]
23# [MANDATORY|DEFAULT]
24# [DISABLED]
25# [NOT_EMBEDDED|RECOMPILE_FOR_EMBEDDED]
26# [CLIENT]
27# [MODULE_OUTPUT_NAME module_name]
28# [STATIC_OUTPUT_NAME static_name]
29# [COMPONENT component]
30# [CONFIG cnf_file_name]
31# [VERSION version_string]
32# [LINK_LIBRARIES lib1...libN]
33# [DEPENDS target1...targetN]
34
35MACRO(MYSQL_ADD_PLUGIN)
36  CMAKE_PARSE_ARGUMENTS(ARG
37    "STORAGE_ENGINE;STATIC_ONLY;MODULE_ONLY;MANDATORY;DEFAULT;DISABLED;NOT_EMBEDDED;RECOMPILE_FOR_EMBEDDED;CLIENT"
38    "MODULE_OUTPUT_NAME;STATIC_OUTPUT_NAME;COMPONENT;CONFIG;VERSION"
39    "LINK_LIBRARIES;DEPENDS"
40    ${ARGN}
41  )
42  IF(NOT WITHOUT_SERVER OR ARG_CLIENT)
43
44  # Add common include directories
45  INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
46                    ${CMAKE_SOURCE_DIR}/sql
47                    ${PCRE_INCLUDES}
48                    ${SSL_INCLUDE_DIRS}
49                    ${ZLIB_INCLUDE_DIR})
50
51  LIST(GET ARG_UNPARSED_ARGUMENTS 0 plugin)
52  SET(SOURCES ${ARG_UNPARSED_ARGUMENTS})
53  LIST(REMOVE_AT SOURCES 0)
54  STRING(TOUPPER ${plugin} plugin)
55  STRING(TOLOWER ${plugin} target)
56
57  IF (ARG_MANDATORY)
58    UNSET(PLUGIN_${plugin} CACHE)
59    SET(PLUGIN_${plugin} "YES")
60  ELSE()
61    SET (compat ".")
62    # Figure out whether to build plugin.
63    # recognize and support the maze of old WITH/WITHOUT combinations
64    IF(WITHOUT_${plugin}_STORAGE_ENGINE
65       OR WITHOUT_${plugin}
66       OR WITHOUT_PLUGIN_${plugin}
67       OR WITH_NONE)
68
69      SET(compat "${compat}without")
70    ENDIF()
71    IF(WITH_${plugin}_STORAGE_ENGINE
72       OR WITH_${plugin}
73       OR WITH_PLUGIN_${plugin}
74       OR WITH_ALL
75       OR WITH_MAX
76       OR WITH_MAX_NO_NDB
77       OR ARG_DEFAULT)
78
79      SET(compat "with${compat}")
80    ENDIF()
81
82    IF (ARG_DISABLED)
83      SET(howtobuild NO)
84    ELSEIF (compat STREQUAL ".")
85      SET(howtobuild DYNAMIC)
86    ELSEIF (compat STREQUAL "with.")
87      IF (NOT ARG_MODULE_ONLY)
88        SET(howtobuild STATIC)
89      ELSE()
90        SET(howtobuild DYNAMIC)
91      ENDIF()
92    ELSEIF (compat STREQUAL ".without")
93      SET(howtobuild NO)
94    ELSEIF (compat STREQUAL "with.without")
95      SET(howtobuild STATIC)
96    ENDIF()
97
98    # NO - not at all
99    # YES - static if possible, otherwise dynamic if possible, otherwise abort
100    # AUTO - static if possible, otherwise dynamic, if possible
101    # STATIC - static if possible, otherwise not at all
102    # DYNAMIC - dynamic if possible, otherwise not at all
103    SET(PLUGIN_${plugin} ${howtobuild}
104      CACHE STRING "How to build plugin ${plugin}. Options are: NO STATIC DYNAMIC YES AUTO.")
105  ENDIF()
106
107  IF (NOT PLUGIN_${plugin} MATCHES "^(NO|YES|AUTO|STATIC|DYNAMIC)$")
108    MESSAGE(FATAL_ERROR "Invalid value for PLUGIN_${plugin}")
109  ENDIF()
110
111  IF(ARG_STORAGE_ENGINE)
112    SET(with_var "WITH_${plugin}_STORAGE_ENGINE" )
113  ELSE()
114    SET(with_var "WITH_${plugin}")
115  ENDIF()
116  UNSET(${with_var} CACHE)
117
118  IF(NOT ARG_DEPENDS)
119    SET(ARG_DEPENDS)
120  ENDIF()
121
122  IF(ARG_VERSION)
123    SET(version_string ";PLUGIN_${plugin}_VERSION=\"${ARG_VERSION}\"")
124  ENDIF()
125
126  IF(NOT ARG_MODULE_OUTPUT_NAME)
127    IF(ARG_STORAGE_ENGINE)
128      SET(ARG_MODULE_OUTPUT_NAME "ha_${target}")
129    ELSE()
130      SET(ARG_MODULE_OUTPUT_NAME "${target}")
131    ENDIF()
132  ENDIF()
133
134  # Build either static library or module
135  IF (PLUGIN_${plugin} MATCHES "(STATIC|AUTO|YES)" AND NOT ARG_MODULE_ONLY
136      AND NOT ARG_CLIENT)
137
138    IF(CMAKE_GENERATOR MATCHES "Makefiles|Ninja")
139      # If there is a shared library from previous shared build,
140      # remove it. This is done just for mysql-test-run.pl
141      # so it does not try to use stale shared lib as plugin
142      # in test.
143      FILE(REMOVE
144        ${CMAKE_CURRENT_BINARY_DIR}/${ARG_MODULE_OUTPUT_NAME}${CMAKE_SHARED_MODULE_SUFFIX})
145    ENDIF()
146
147    ADD_LIBRARY(${target} STATIC ${SOURCES})
148    DTRACE_INSTRUMENT(${target})
149    ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDS})
150    RESTRICT_SYMBOL_EXPORTS(${target})
151    IF(WITH_EMBEDDED_SERVER AND (NOT ARG_NOT_EMBEDDED))
152      # Embedded library should contain PIC code and be linkable
153      # to shared libraries (on systems that need PIC)
154      IF(ARG_RECOMPILE_FOR_EMBEDDED OR NOT _SKIP_PIC)
155        # Recompile some plugins for embedded
156        ADD_CONVENIENCE_LIBRARY(${target}_embedded ${SOURCES})
157        RESTRICT_SYMBOL_EXPORTS(${target}_embedded)
158        DTRACE_INSTRUMENT(${target}_embedded)
159        IF(ARG_RECOMPILE_FOR_EMBEDDED)
160          SET_TARGET_PROPERTIES(${target}_embedded
161            PROPERTIES COMPILE_DEFINITIONS "EMBEDDED_LIBRARY${version_string}")
162        ENDIF()
163        ADD_DEPENDENCIES(${target}_embedded GenError ${ARG_DEPENDS})
164      ENDIF()
165    ENDIF()
166
167    IF(ARG_STATIC_OUTPUT_NAME)
168      SET_TARGET_PROPERTIES(${target} PROPERTIES
169      OUTPUT_NAME ${ARG_STATIC_OUTPUT_NAME})
170    ENDIF()
171
172    IF(ARG_LINK_LIBRARIES)
173      TARGET_LINK_LIBRARIES (${target} ${ARG_LINK_LIBRARIES})
174    ENDIF()
175
176    SET(${with_var} ON CACHE INTERNAL "Link ${plugin} statically to the server" FORCE)
177
178    # Update mysqld dependencies
179    SET (MYSQLD_STATIC_PLUGIN_LIBS ${MYSQLD_STATIC_PLUGIN_LIBS}
180      ${target} ${ARG_LINK_LIBRARIES} CACHE INTERNAL "" FORCE)
181
182    IF(WITH_EMBEDDED_SERVER AND (NOT ARG_NOT_EMBEDDED))
183      SET (EMBEDDED_PLUGIN_LIBS ${EMBEDDED_PLUGIN_LIBS}
184      ${target} ${ARG_LINK_LIBRARIES} CACHE INTERNAL "" FORCE)
185    ENDIF()
186
187    IF(ARG_NOT_EMBEDDED)
188      SET(builtin_entry "#ifndef EMBEDDED_LIBRARY\n builtin_maria_${target}_plugin,\n#endif")
189    ELSE()
190      SET(builtin_entry " builtin_maria_${target}_plugin,")
191    ENDIF()
192
193    IF(ARG_MANDATORY)
194      SET (mysql_mandatory_plugins
195        "${mysql_mandatory_plugins}${builtin_entry}\n")
196      SET (mysql_mandatory_plugins ${mysql_mandatory_plugins} PARENT_SCOPE)
197    ELSE()
198      SET (mysql_optional_plugins
199        "${mysql_optional_plugins}${builtin_entry}\n")
200      SET (mysql_optional_plugins ${mysql_optional_plugins} PARENT_SCOPE)
201    ENDIF()
202  ELSEIF(PLUGIN_${plugin} MATCHES "(DYNAMIC|AUTO|YES)"
203         AND NOT ARG_STATIC_ONLY AND NOT WITHOUT_DYNAMIC_PLUGINS)
204
205    ADD_VERSION_INFO(${target} MODULE SOURCES)
206    ADD_LIBRARY(${target} MODULE ${SOURCES})
207    DTRACE_INSTRUMENT(${target})
208
209    SET_TARGET_PROPERTIES (${target} PROPERTIES PREFIX "")
210    IF (NOT ARG_CLIENT)
211      SET_TARGET_PROPERTIES (${target} PROPERTIES
212        COMPILE_DEFINITIONS "MYSQL_DYNAMIC_PLUGIN${version_string}")
213    ENDIF()
214
215    TARGET_LINK_LIBRARIES (${target} mysqlservices ${ARG_LINK_LIBRARIES})
216
217    IF(CMAKE_SYSTEM_NAME MATCHES AIX)
218      TARGET_LINK_OPTIONS(${target} PRIVATE "-Wl,-bE:${CMAKE_SOURCE_DIR}/libservices/mysqlservices_aix.def")
219    ENDIF()
220
221    # Server plugins use symbols defined in mysqld executable.
222    # Some operating systems like Windows and OSX and are pretty strict about
223    # unresolved symbols. Others are less strict and allow unresolved symbols
224    # in shared libraries. On Linux for example, CMake does not even add
225    # executable to the linker command line (it would result into link error).
226    # Thus we skip TARGET_LINK_LIBRARIES on Linux, as it would only generate
227    # an additional dependency.
228    IF(ARG_RECOMPILE_FOR_EMBEDDED OR ARG_STORAGE_ENGINE)
229      IF(MSVC OR CMAKE_SYSTEM_NAME MATCHES AIX)
230        TARGET_LINK_LIBRARIES(${target} server)
231      ELSEIF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
232        TARGET_LINK_LIBRARIES (${target} mariadbd)
233      ENDIF()
234    ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT WITH_ASAN AND NOT WITH_TSAN AND NOT WITH_UBSAN AND NOT WITH_MSAN)
235      TARGET_LINK_LIBRARIES (${target} "-Wl,--no-undefined")
236    ENDIF()
237
238    ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDS})
239
240    SET_TARGET_PROPERTIES(${target} PROPERTIES
241      OUTPUT_NAME "${ARG_MODULE_OUTPUT_NAME}")
242    # Install dynamic library
243    IF(ARG_COMPONENT)
244      IF(CPACK_COMPONENTS_ALL AND
245         NOT CPACK_COMPONENTS_ALL MATCHES ${ARG_COMPONENT}
246         AND INSTALL_SYSCONF2DIR)
247        IF (ARG_STORAGE_ENGINE)
248          STRING(REPLACE "-" "_" ver ${SERVER_VERSION})
249          SET(ver " = ${ver}-%{release}")
250        ELSE()
251          SET(ver "")
252        ENDIF()
253        SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT})
254        SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} PARENT_SCOPE)
255
256        IF (NOT ARG_CLIENT)
257          SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB-server${ver}" PARENT_SCOPE)
258        ENDIF()
259        SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} PARENT_SCOPE)
260        IF (ARG_VERSION)
261          SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_VERSION ${SERVER_VERSION}_${ARG_VERSION} PARENT_SCOPE)
262          SET_PLUGIN_DEB_VERSION(${target} ${SERVER_VERSION}-${ARG_VERSION})
263        ENDIF()
264        IF(NOT ARG_CLIENT AND UNIX)
265          IF (NOT ARG_CONFIG)
266            SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}.cnf")
267            FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n")
268          ENDIF()
269          SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" PARENT_SCOPE)
270          SET(CPACK_RPM_${ARG_COMPONENT}_POST_INSTALL_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/plugin-postin.sh PARENT_SCOPE)
271          SET(CPACK_RPM_${ARG_COMPONENT}_POST_TRANS_SCRIPT_FILE ${CMAKE_SOURCE_DIR}/support-files/rpm/server-posttrans.sh PARENT_SCOPE)
272        ENDIF()
273      ENDIF()
274    ELSE()
275      SET(ARG_COMPONENT Server)
276    ENDIF()
277    MYSQL_INSTALL_TARGETS(${target} DESTINATION ${INSTALL_PLUGINDIR} COMPONENT ${ARG_COMPONENT})
278    IF(ARG_CONFIG AND INSTALL_SYSCONF2DIR)
279      INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR})
280    ENDIF()
281  ENDIF()
282
283  GET_FILENAME_COMPONENT(subpath ${CMAKE_CURRENT_SOURCE_DIR} NAME)
284  IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/mysql-test")
285    INSTALL_MYSQL_TEST("${CMAKE_CURRENT_SOURCE_DIR}/mysql-test/" "plugin/${subpath}")
286  ENDIF()
287
288  IF(TARGET ${target})
289    GET_TARGET_PROPERTY(plugin_type ${target} TYPE)
290    STRING(REPLACE "_LIBRARY" "" plugin_type ${plugin_type})
291    SET(have_target 1)
292  ELSE()
293    SET(plugin_type)
294    SET(have_target 0)
295  ENDIF()
296  IF(ARG_STORAGE_ENGINE)
297    ADD_FEATURE_INFO(${plugin} ${have_target} "Storage Engine ${plugin_type}")
298  ELSEIF(ARG_CLIENT)
299    ADD_FEATURE_INFO(${plugin} ${have_target} "Client plugin ${plugin_type}")
300  ELSE()
301    ADD_FEATURE_INFO(${plugin} ${have_target} "Server plugin ${plugin_type}")
302  ENDIF()
303  ENDIF(NOT WITHOUT_SERVER OR ARG_CLIENT)
304ENDMACRO()
305
306
307# Add all CMake projects under storage  and plugin
308# subdirectories, configure sql_builtins.cc
309MACRO(CONFIGURE_PLUGINS)
310  IF(NOT WITHOUT_SERVER)
311    FILE(GLOB dirs_storage ${CMAKE_SOURCE_DIR}/storage/*)
312  ENDIF()
313
314  FILE(GLOB dirs_plugin ${CMAKE_SOURCE_DIR}/plugin/*)
315  FOREACH(dir ${dirs_storage} ${dirs_plugin})
316    IF (EXISTS ${dir}/CMakeLists.txt)
317      ADD_SUBDIRECTORY(${dir})
318    ENDIF()
319  ENDFOREACH()
320
321  GET_CMAKE_PROPERTY(ALL_VARS VARIABLES)
322  FOREACH (V ${ALL_VARS})
323    IF (V MATCHES "^PLUGIN_" AND ${V} MATCHES "YES")
324      STRING(SUBSTRING ${V} 7 -1 plugin)
325      STRING(TOLOWER ${plugin} target)
326      IF (NOT TARGET ${target})
327        MESSAGE(FATAL_ERROR "Plugin ${plugin} cannot be built")
328      ENDIF()
329    ENDIF()
330  ENDFOREACH()
331ENDMACRO()
332