1# cmake/modules/ocaml.cmake
2#
3# Copyright (C) 2008 Andrew Ross
4# Copyright (C) 2009 Hezekiah M. Carty
5# Copyright (C) 2009-2017 Alan W. Irwin
6#
7# This file is part of PLplot.
8#
9# PLplot is free software; you can redistribute it and/or modify
10# it under the terms of the GNU Library General Public License as published
11# by the Free Software Foundation; version 2 of the License.
12#
13# PLplot is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU Library General Public License for more details.
17#
18# You should have received a copy of the GNU Library General Public License
19# along with the file PLplot; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
22# Module for determining OCaml binding configuration options
23
24if(DEFAULT_NO_BINDINGS)
25  option(ENABLE_ocaml "Enable OCaml binding" OFF)
26else(DEFAULT_NO_BINDINGS)
27  option(ENABLE_ocaml "Enable OCaml binding" ON)
28endif(DEFAULT_NO_BINDINGS)
29
30if(ENABLE_ocaml AND NOT PL_DOUBLE)
31  message(STATUS "WARNING: "
32    "Only single-precision floating point. Disabling Ocaml binding because of run-time errors in this case.")
33  set(ENABLE_ocaml OFF CACHE BOOL "Enable Ocaml binding" FORCE)
34endif(ENABLE_ocaml AND NOT PL_DOUBLE)
35
36if(ENABLE_ocaml)
37  find_program(OCAMLC NAMES ocamlc.opt ocamlc)
38  if (OCAMLC)
39    message(STATUS "OCAMLC = ${OCAMLC}")
40  else (OCAMLC)
41    message(STATUS "WARNING: "
42      "The ocamlc application not found. Disabling OCaml binding")
43    set(ENABLE_ocaml OFF CACHE BOOL "Enable OCaml binding" FORCE)
44  endif (OCAMLC)
45endif(ENABLE_ocaml)
46
47if(ENABLE_ocaml)
48  find_program(CAMLIDL camlidl)
49  if (CAMLIDL)
50    message(STATUS "CAMLIDL = ${CAMLIDL}")
51  else (CAMLIDL)
52    message(STATUS "WARNING: "
53      "The camlidl application not found. Disabling OCaml binding")
54    set(ENABLE_ocaml OFF CACHE BOOL "Enable OCaml binding" FORCE)
55  endif (CAMLIDL)
56endif(ENABLE_ocaml)
57
58if(ENABLE_ocaml)
59  find_program(OCAMLMKLIB ocamlmklib)
60  if (OCAMLMKLIB)
61    message(STATUS "OCAMLMKLIB = ${OCAMLMKLIB}")
62  else (OCAMLMKLIB)
63    message(STATUS "WARNING: "
64      "The ocamlmklib application not found. Disabling OCaml binding")
65    set(ENABLE_ocaml OFF CACHE BOOL "Enable OCaml binding" FORCE)
66  endif (OCAMLMKLIB)
67endif(ENABLE_ocaml)
68
69if(ENABLE_ocaml)
70  option(FORCE_OCAMLC "Force use of ocamlc rather than ocamlopt?" OFF)
71  if(NOT FORCE_OCAMLC)
72    find_program(OCAMLOPT NAMES ocamlopt.opt ocamlopt)
73  endif(NOT FORCE_OCAMLC)
74
75  if (OCAMLOPT)
76    message(STATUS "OCAMLOPT = ${OCAMLOPT}")
77  else (OCAMLOPT)
78    message(STATUS "WARNING: "
79      "The ocamlopt application not found. Disabling native code OCaml binding")
80  endif (OCAMLOPT)
81endif(ENABLE_ocaml)
82
83if(ENABLE_ocaml)
84  find_program(OCAMLFIND ocamlfind)
85  if (OCAMLFIND)
86    message(STATUS "OCAMLFIND = ${OCAMLFIND}")
87  else (OCAMLFIND)
88    message(STATUS "WARNING: "
89      "The ocamlfind application not found.")
90  endif (OCAMLFIND)
91endif(ENABLE_ocaml)
92
93if(ENABLE_ocaml AND BUILD_DOC)
94  find_program(OCAMLDOC NAMES ocamldoc.opt ocamldoc)
95  if (OCAMLDOC)
96    message(STATUS "OCAMLDOC = ${OCAMLDOC}")
97  else (OCAMLDOC)
98    message(STATUS "WARNING: "
99      "The ocamldoc application not found. Disabling OCaml API documentation generation")
100  endif (OCAMLDOC)
101endif(ENABLE_ocaml AND BUILD_DOC)
102
103if(ENABLE_ocaml)
104  execute_process(COMMAND ${OCAMLC} -version
105    OUTPUT_VARIABLE OCAML_VERSION
106    OUTPUT_STRIP_TRAILING_WHITESPACE
107    )
108  execute_process(COMMAND ${OCAMLC} -where
109    OUTPUT_VARIABLE OCAML_LIB_PATH
110    OUTPUT_STRIP_TRAILING_WHITESPACE
111    )
112  message(STATUS "OCAML_LIB_PATH = ${OCAML_LIB_PATH}")
113  if(OCAMLFIND)
114    execute_process(COMMAND ${OCAMLFIND} query camlidl
115      OUTPUT_VARIABLE CAMLIDL_LIB_PATH
116      OUTPUT_STRIP_TRAILING_WHITESPACE
117      )
118    find_path(CAMLIDL_LIB_DIR libcamlidl.a PATHS ${CAMLIDL_LIB_PATH} ${OCAML_LIB_PATH} )
119  else(OCAMLFIND)
120    find_path(CAMLIDL_LIB_DIR libcamlidl.a PATHS ${OCAML_LIB_PATH} )
121  endif(OCAMLFIND)
122  if(CAMLIDL_LIB_DIR)
123    message(STATUS "CAMLIDL_LIB_DIR = ${CAMLIDL_LIB_DIR}")
124  else(CAMLIDL_LIB_DIR)
125    message(STATUS "WARNING: "
126      "The camlidl library not found. Disabling OCaml binding")
127    set(ENABLE_ocaml OFF CACHE BOOL "Enable OCaml binding" FORCE)
128  endif(CAMLIDL_LIB_DIR)
129
130endif(ENABLE_ocaml)
131
132if(ENABLE_ocaml)
133  # Installation follows the Debian ocaml policy for want of a better
134  # standard.
135  set(
136    OCAML_INSTALL_DIR
137    ${CMAKE_INSTALL_PREFIX}/lib/ocaml
138    CACHE PATH "PLplot install location for ocaml files"
139    )
140  list(APPEND INSTALL_LOCATION_VARIABLES_LIST OCAML_INSTALL_DIR)
141
142  if(ADD_SPECIAL_CONSISTENCY_CHECKING)
143    option(GENERATE_PLPLOT_H_INC "Generate generated_plplot_h.inc" ON)
144  else(ADD_SPECIAL_CONSISTENCY_CHECKING)
145    # Leave this OFF by default since this target requires extra
146    # dependencies such as libpcre-ocaml-dev package on Debian.
147    option(GENERATE_PLPLOT_H_INC "Generate generated_plplot_h.inc" OFF)
148  endif(ADD_SPECIAL_CONSISTENCY_CHECKING)
149
150  if(GENERATE_PLPLOT_H_INC)
151    find_program(OCAML ocaml)
152    if (OCAML)
153      message(STATUS "OCAML = ${OCAML}")
154    else (OCAML)
155      message(STATUS "WARNING: "
156	"The ocaml application not found. Disabling generation of generated_plplot_h.inc")
157      set(GENERATE_PLPLOT_H_INC OFF CACHE BOOL "Generate generated_plplot_h.inc" FORCE)
158    endif (OCAML)
159  endif(GENERATE_PLPLOT_H_INC)
160
161  # Test for availability of topfind and pcre (and unix).
162  if(GENERATE_PLPLOT_H_INC)
163    set(text
164"#use \"topfind\";;
165#require \"unix\";;
166#require \"pcre\";;
167"
168      )
169    file(WRITE ${CMAKE_BINARY_DIR}/test_ocaml.ml ${text})
170    # For some reason the return code is not set if an error occurs
171    # with test_ocaml.ml so look for any stdout or stderr output as a sign
172    # of an error condition.
173    execute_process(
174      COMMAND ${OCAML} test_ocaml.ml
175      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
176      OUTPUT_VARIABLE output
177      ERROR_VARIABLE error
178      OUTPUT_STRIP_TRAILING_WHITESPACE
179      ERROR_STRIP_TRAILING_WHITESPACE
180      )
181    if(output OR error)
182      message(STATUS "WARNING: "
183	"One or all of topfind, unix, or pcre components of ocaml are not installed.  Disabling generation of generated_plplot_h.inc")
184      set(GENERATE_PLPLOT_H_INC OFF CACHE BOOL "Generate generated_plplot_h.inc" FORCE)
185    endif(output OR error)
186
187  endif(GENERATE_PLPLOT_H_INC)
188
189  # Test for the availability of Cairo and Gtk+ bindings
190  if(OCAMLFIND)
191    if(PLD_extcairo)
192      option(OCAML_HAS_CAIRO "OCaml has the cairo package" ON)
193      # Disable since substantial maintenance is required before this component
194      # of PLplot will configure, build, and/or run.
195      message(STATUS "WARNING: PLplot OCaml Cairo support currently requires substantial development effort so is indefinitely disabled")
196      set(OCAML_HAS_CAIRO OFF CACHE BOOL "OCaml has the cairo package" FORCE)
197
198      if(OCAML_HAS_CAIRO)
199	set(text_cairo "module C = Cairo")
200	file(WRITE ${CMAKE_BINARY_DIR}/test_cairo.ml ${text_cairo})
201	execute_process(
202          COMMAND ${OCAMLFIND} c -package cairo2 -linkpkg test_cairo.ml -o test_cairo
203          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
204          RESULT_VARIABLE OCAML_HAS_CAIRO_RC
205	  OUTPUT_QUIET
206	  ERROR_QUIET
207          )
208	# non-zero return code indicates errors.
209	if(OCAML_HAS_CAIRO_RC)
210	  set(OCAML_HAS_CAIRO OFF CACHE BOOL "OCaml has the cairo package" FORCE)
211	endif(OCAML_HAS_CAIRO_RC)
212      endif(OCAML_HAS_CAIRO)
213
214      if(OCAML_HAS_CAIRO)
215        message(STATUS "Cairo OCaml library found")
216	if(PKG_CONFIG_EXECUTABLE)
217	  pkg_check_pkgconfig(cairo includedir libdir linkflags cflags version _CAIRO1)
218	  # Transform from CMake form to pkg-config form required by ocaml build
219	  # commands.
220	  if(linkflags)
221	    string(REGEX REPLACE ";" " " CAIRO_COMPILE_FLAGS "${cflags}")
222	    pkg_config_link_flags(CAIRO_LINK_FLAGS "${linkflags}")
223	    #message(STATUS "DEBUG: cairo linkflags = ${linkflags}")
224	    #message(STATUS "DEBUG: CAIRO_LINK_FLAGS = ${CAIRO_LINK_FLAGS}")
225	  else(linkflags)
226            message(STATUS "WARNING: "
227            "pkg-config could not find cairo module.  Disabling Plcairo module")
228	  set(OCAML_HAS_CAIRO OFF CACHE BOOL "OCaml has the cairo package" FORCE)
229	  endif(linkflags)
230	else(PKG_CONFIG_EXECUTABLE)
231          message(STATUS "WARNING: "
232            "pkg-config not found.  Disabling Plcairo module")
233	  set(OCAML_HAS_CAIRO OFF CACHE BOOL "OCaml has the cairo package" FORCE)
234	endif(PKG_CONFIG_EXECUTABLE)
235      endif(OCAML_HAS_CAIRO)
236
237      if(OCAML_HAS_CAIRO)
238	option(OCAML_HAS_GTK "OCaml has the cairo2.lablgtk2 package" ON)
239      else(OCAML_HAS_CAIRO)
240	set(OCAML_HAS_GTK OFF CACHE BOOL "OCaml has the cairo2.lablgtk2 package" FORCE)
241      endif(OCAML_HAS_CAIRO)
242
243      if(DROP_GTK_PLUS_2_BUILDS)
244	set(OCAML_HAS_GTK OFF CACHE BOOL "OCaml has the cairo2.lablgtk2 package" FORCE)
245      endif(DROP_GTK_PLUS_2_BUILDS)
246
247      if(OCAML_HAS_GTK)
248	set(text_gtk
249	  "module G = Gtk
250  module C = Cairo_gtk"
251          )
252	file (WRITE ${CMAKE_BINARY_DIR}/test_gtk.ml ${text_gtk})
253	execute_process(
254          COMMAND ${OCAMLFIND} c -package cairo2.lablgtk2 -linkpkg test_gtk.ml -o test_gtk
255          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
256          RESULT_VARIABLE OCAML_HAS_GTK_RC
257	  OUTPUT_QUIET
258	  ERROR_QUIET
259          )
260	# non-zero return code indicates errors.
261	if(OCAML_HAS_GTK_RC)
262	  set(OCAML_HAS_GTK OFF CACHE BOOL "OCaml has the cairo2.lablgtk2 package" FORCE)
263	endif(OCAML_HAS_GTK_RC)
264      endif(OCAML_HAS_GTK)
265
266      if(OCAML_HAS_GTK)
267        message(STATUS "lablgtk2 OCaml library found")
268      else(OCAML_HAS_GTK)
269        # permanently disabled: message(STATUS "WARNING: lablgtk2 OCaml library not found.")
270      endif(OCAML_HAS_GTK)
271    endif (PLD_extcairo)
272  else(OCAMLFIND)
273    message(STATUS "WARNING: "
274      "ocamlfind not available.  Disabling Plcairo module and lablgtk2 support")
275    set(OCAML_HAS_CAIRO OFF CACHE BOOL "OCaml has the cairo package" FORCE)
276    set(OCAML_HAS_GTK OFF CACHE BOOL "OCaml has the cairo2.lablgtk2 package" FORCE)
277  endif(OCAMLFIND)
278else(ENABLE_ocaml)
279  message(STATUS "WARNING: "
280    "ENABLE_ocaml is OFF so disabling Plcairo module and lablgtk2 support")
281  set(OCAML_HAS_CAIRO OFF CACHE BOOL "OCaml has the cairo package" FORCE)
282  set(OCAML_HAS_GTK OFF CACHE BOOL "OCaml has the cairo2.lablgtk2 package" FORCE)
283endif(ENABLE_ocaml)
284