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