1# Copyright (c) 2009, 2021, Oracle and/or its affiliates.
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# cmake -DWITH_EDITLINE=system|bundled
24# or
25# cmake -DWITH_READLINE=system
26# system readline is the default
27
28MACRO (MYSQL_CHECK_MULTIBYTE)
29  SET(CMAKE_EXTRA_INCLUDE_FILES wchar.h)
30  CHECK_TYPE_SIZE(mbstate_t SIZEOF_MBSTATE_T)
31  SET(CMAKE_EXTRA_INCLUDE_FILES)
32  IF(SIZEOF_MBSTATE_T)
33    SET(HAVE_MBSTATE_T 1)
34  ENDIF()
35
36  CHECK_C_SOURCE_COMPILES("
37  #include <langinfo.h>
38  int main(int ac, char **av)
39  {
40    char *cs = nl_langinfo(CODESET);
41    return 0;
42  }"
43  HAVE_LANGINFO_CODESET)
44
45  CHECK_FUNCTION_EXISTS(wcsdup HAVE_WCSDUP)
46
47  SET(CMAKE_EXTRA_INCLUDE_FILES wchar.h)
48  CHECK_TYPE_SIZE(wchar_t SIZEOF_WCHAR_T)
49  IF(SIZEOF_WCHAR_T)
50    SET(HAVE_WCHAR_T 1)
51  ENDIF()
52
53  SET(CMAKE_EXTRA_INCLUDE_FILES wctype.h)
54  CHECK_TYPE_SIZE(wint_t SIZEOF_WINT_T)
55  IF(SIZEOF_WINT_T)
56    SET(HAVE_WINT_T 1)
57  ENDIF()
58  SET(CMAKE_EXTRA_INCLUDE_FILES)
59
60ENDMACRO()
61
62MACRO (FIND_CURSES)
63 FIND_PACKAGE(Curses)
64 MARK_AS_ADVANCED(CURSES_CURSES_H_PATH CURSES_FORM_LIBRARY CURSES_HAVE_CURSES_H)
65 IF(NOT CURSES_FOUND)
66   SET(ERRORMSG "Curses library not found. Please install appropriate package,
67    remove CMakeCache.txt and rerun cmake.")
68   IF(LINUX)
69     SET(ERRORMSG ${ERRORMSG}
70       "On Debian/Ubuntu, package name is libncurses5-dev, on Redhat and derivates "
71       "it is ncurses-devel.")
72   ENDIF()
73   MESSAGE(FATAL_ERROR ${ERRORMSG})
74 ENDIF()
75
76 IF(CURSES_HAVE_CURSES_H)
77   SET(HAVE_CURSES_H 1 CACHE INTERNAL "")
78 ELSEIF(CURSES_HAVE_NCURSES_H)
79   SET(HAVE_NCURSES_H 1 CACHE INTERNAL "")
80 ENDIF()
81
82 IF(LINUX)
83   # -Wl,--as-needed breaks linking with -lcurses, e.g on Fedora
84   # Lower-level libcurses calls are exposed by libtinfo
85   CHECK_LIBRARY_EXISTS(${CURSES_LIBRARY} tputs "" HAVE_TPUTS_IN_CURSES)
86   IF(NOT HAVE_TPUTS_IN_CURSES)
87     CHECK_LIBRARY_EXISTS(tinfo tputs "" HAVE_TPUTS_IN_TINFO)
88     IF(HAVE_TPUTS_IN_TINFO)
89       SET(CURSES_LIBRARY tinfo)
90     ENDIF()
91   ENDIF()
92 ENDIF()
93ENDMACRO()
94
95SET(CURRENT_LIBEDIT_DIRECTORY "extra/libedit/libedit-20191231-3.1")
96
97MACRO (MYSQL_USE_BUNDLED_EDITLINE)
98  SET(WITH_EDITLINE "bundled" CACHE STRING "By default use bundled editline")
99  SET(USE_LIBEDIT_INTERFACE 1)
100  SET(HAVE_HIST_ENTRY 1)
101  SET(XLINE_HAVE_COMPLETION_CHAR 1 CACHE INTERNAL "")
102  SET(USE_NEW_XLINE_INTERFACE 1 CACHE INTERNAL "")
103  SET(EDITLINE_INCLUDE_DIR
104    ${CMAKE_SOURCE_DIR}/${CURRENT_LIBEDIT_DIRECTORY}/src/editline)
105  INCLUDE_DIRECTORIES(BEFORE SYSTEM ${EDITLINE_INCLUDE_DIR})
106  SET(EDITLINE_LIBRARY edit)
107  FIND_CURSES()
108  ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/${CURRENT_LIBEDIT_DIRECTORY}/src)
109ENDMACRO()
110
111MACRO (FIND_SYSTEM_EDITLINE)
112  FIND_PATH(FOUND_EDITLINE_READLINE
113    NAMES editline/readline.h
114  )
115  IF(FOUND_EDITLINE_READLINE)
116    SET(EDITLINE_INCLUDE_DIR "${FOUND_EDITLINE_READLINE}/editline")
117  ELSE()
118    # Different path on FreeBSD
119    FIND_PATH(FOUND_EDIT_READLINE_READLINE
120      NAMES edit/readline/readline.h
121    )
122    IF(FOUND_EDIT_READLINE_READLINE)
123      SET(EDITLINE_INCLUDE_DIR "${FOUND_EDIT_READLINE_READLINE}/edit/readline")
124    ENDIF()
125  ENDIF()
126
127  FIND_LIBRARY(EDITLINE_LIBRARY
128    NAMES
129    edit
130  )
131  MARK_AS_ADVANCED(EDITLINE_INCLUDE_DIR EDITLINE_LIBRARY)
132
133  MESSAGE(STATUS "EDITLINE_INCLUDE_DIR ${EDITLINE_INCLUDE_DIR}")
134  MESSAGE(STATUS "EDITLINE_LIBRARY ${EDITLINE_LIBRARY}")
135
136  INCLUDE(CheckCXXSourceCompiles)
137  IF(EDITLINE_LIBRARY AND EDITLINE_INCLUDE_DIR)
138    CMAKE_PUSH_CHECK_STATE()
139
140    SET(CMAKE_REQUIRED_INCLUDES ${EDITLINE_INCLUDE_DIR})
141    LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${EDITLINE_LIBRARY})
142    CHECK_CXX_SOURCE_COMPILES("
143    #include <stdio.h>
144    #include <readline.h>
145    int main(int argc, char **argv)
146    {
147       HIST_ENTRY entry;
148       return 0;
149    }"
150    EDITLINE_HAVE_HIST_ENTRY)
151
152    CHECK_CXX_SOURCE_COMPILES("
153    #include <stdio.h>
154    #include <readline.h>
155    int main(int argc, char **argv)
156    {
157      typedef int MYFunction(const char*, int);
158      MYFunction* myf= rl_completion_entry_function;
159      int res= (myf)(NULL, 0);
160      completion_matches(0,0);
161      return res;
162    }"
163    XLINE_HAVE_COMPLETION_INT)
164
165    CHECK_CXX_SOURCE_COMPILES("
166    #include <stdio.h>
167    #include <readline.h>
168    int main(int argc, char **argv)
169    {
170      typedef char* MYFunction(const char*, int);
171      MYFunction* myf= rl_completion_entry_function;
172      char *res= (myf)(NULL, 0);
173      completion_matches(0,0);
174      return res != NULL;
175    }"
176    XLINE_HAVE_COMPLETION_CHAR)
177
178    IF(XLINE_HAVE_COMPLETION_INT OR XLINE_HAVE_COMPLETION_CHAR)
179      SET(HAVE_HIST_ENTRY ${EDITLINE_HAVE_HIST_ENTRY})
180      SET(USE_LIBEDIT_INTERFACE 1)
181      SET(EDITLINE_FOUND 1)
182      IF(XLINE_HAVE_COMPLETION_CHAR)
183        SET(USE_NEW_XLINE_INTERFACE 1)
184      ENDIF()
185    ENDIF()
186    CMAKE_POP_CHECK_STATE()
187  ENDIF()
188ENDMACRO()
189
190MACRO (FIND_SYSTEM_READLINE)
191  FIND_CURSES()
192  FIND_PATH(READLINE_INCLUDE_DIR readline.h PATH_SUFFIXES readline)
193  FIND_LIBRARY(READLINE_LIBRARY NAMES readline)
194  MARK_AS_ADVANCED(READLINE_INCLUDE_DIR READLINE_LIBRARY)
195
196  SET(CMAKE_REQUIRES_LIBRARIES ${${name}_LIBRARY} ${CURSES_LIBRARY})
197  CHECK_INCLUDE_FILES("stdio.h;readline/readline.h;readline/history.h"
198                      HAVE_READLINE_HISTORY_H)
199  IF(HAVE_READLINE_HISTORY_H)
200    LIST(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_READLINE_HISTORY_H)
201  ENDIF()
202
203  MESSAGE(STATUS "READLINE_INCLUDE_DIR ${READLINE_INCLUDE_DIR}")
204  MESSAGE(STATUS "READLINE_LIBRARY ${READLINE_LIBRARY}")
205
206  IF(READLINE_LIBRARY AND READLINE_INCLUDE_DIR)
207    SET(CMAKE_REQUIRED_LIBRARIES ${READLINE_LIBRARY} ${CURSES_LIBRARY})
208    SET(CMAKE_REQUIRED_INCLUDES ${READLINE_INCLUDE_DIR})
209    INCLUDE(CheckCXXSourceCompiles)
210    CHECK_CXX_SOURCE_COMPILES("
211    #include <stdio.h>
212    #include <readline.h>
213    #if HAVE_READLINE_HISTORY_H
214    #include <history.h>
215    #endif
216    int main(int argc, char **argv)
217    {
218       HIST_ENTRY entry;
219       return 0;
220    }"
221    READLINE_HAVE_HIST_ENTRY)
222
223    CHECK_CXX_SOURCE_COMPILES("
224    #include <stdio.h>
225    #include <readline.h>
226    int main(int argc, char **argv)
227    {
228      CPPFunction *func1= (CPPFunction*)0;
229      rl_compentry_func_t *func2= (rl_compentry_func_t*)0;
230    }"
231    READLINE_USE_LIBEDIT_INTERFACE)
232
233    CHECK_CXX_SOURCE_COMPILES("
234    #include <stdio.h>
235    #include <readline.h>
236    int main(int argc, char **argv)
237    {
238      rl_completion_func_t *func1= (rl_completion_func_t*)0;
239      rl_compentry_func_t *func2= (rl_compentry_func_t*)0;
240    }"
241    READLINE_USE_NEW_READLINE_INTERFACE)
242
243    IF(READLINE_USE_LIBEDIT_INTERFACE OR READLINE_USE_NEW_READLINE_INTERFACE)
244      SET(READLINE_LIBRARY ${READLINE_LIBRARY} ${CURSES_LIBRARY})
245      SET(READLINE_INCLUDE_DIR ${READLINE_INCLUDE_DIR})
246      SET(HAVE_HIST_ENTRY ${READLINE_HAVE_HIST_ENTRY})
247      SET(USE_LIBEDIT_INTERFACE ${READLINE_USE_LIBEDIT_INTERFACE})
248      SET(USE_NEW_XLINE_INTERFACE ${READLINE_USE_NEW_READLINE_INTERFACE})
249      SET(XLINE_HAVE_COMPLETION_CHAR ${READLINE_USE_NEW_READLINE_INTERFACE})
250      SET(XLINE_HAVE_COMPLETION_INT ${READLINE_USE_LIBEDIT_INTERFACE})
251      SET(READLINE_FOUND 1)
252    ENDIF()
253  ENDIF()
254ENDMACRO()
255
256IF (NOT WITH_EDITLINE AND NOT WITH_READLINE AND NOT WIN32)
257  SET(WITH_READLINE "system" CACHE STRING "By default use system readline")
258ELSEIF (WITH_EDITLINE AND WITH_READLINE)
259  MESSAGE(FATAL_ERROR "Cannot configure WITH_READLINE and WITH_EDITLINE! Use only one setting.")
260ENDIF()
261
262MACRO (MYSQL_CHECK_EDITLINE)
263  IF (NOT WIN32)
264    MYSQL_CHECK_MULTIBYTE()
265
266    IF(WITH_READLINE STREQUAL "system")
267      FIND_SYSTEM_READLINE()
268      IF(NOT READLINE_FOUND)
269        MESSAGE(FATAL_ERROR "Cannot find system readline libraries.")
270      ELSE()
271        SET(MY_READLINE_INCLUDE_DIR ${READLINE_INCLUDE_DIR})
272        SET(MY_READLINE_LIBRARY ${READLINE_LIBRARY} ${CURSES_LIBRARY})
273      ENDIF()
274    ELSEIF(WITH_READLINE STREQUAL "bundled")
275      MESSAGE(FATAL_ERROR "Bundled readline is not supported.")
276    ELSEIF(WITH_EDITLINE STREQUAL "bundled")
277      MYSQL_USE_BUNDLED_EDITLINE()
278      SET(MY_READLINE_INCLUDE_DIR ${EDITLINE_INCLUDE_DIR})
279      SET(MY_READLINE_LIBRARY ${EDITLINE_LIBRARY})
280    ELSEIF(WITH_EDITLINE STREQUAL "system")
281      FIND_SYSTEM_EDITLINE()
282      IF(NOT EDITLINE_FOUND)
283        MESSAGE(FATAL_ERROR "Cannot find system editline libraries.")
284      ELSE()
285        SET(MY_READLINE_INCLUDE_DIR ${EDITLINE_INCLUDE_DIR})
286        SET(MY_READLINE_LIBRARY ${EDITLINE_LIBRARY})
287      ENDIF()
288    ELSE()
289      MESSAGE(FATAL_ERROR "WITH_EDITLINE must be bundled or system")
290    ENDIF()
291  ENDIF(NOT WIN32)
292ENDMACRO()
293
294