Fix #1004, 1005: Various meson problems
[geeqie.git] / meson.build
1 # This file is a part of Geeqie project (https://www.geeqie.org/).
2 # Copyright (C) 2008 - 2022 The Geeqie Team
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; either version 2 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13
14 # Meson default directories used in this project:
15 # prefix - /usr/local
16 # bindir - bin
17 # datadir - share
18
19 # Meson core options:
20 # buildtype
21 # debug
22
23 # Project expanded default directories:
24 # prefix        /usr/local/
25 # bindir        /usr/local/bin                          geeqie executable
26 # gq_bindir     /usr/local/lib/geeqie               *   plugins scripts
27 # datadir       /usr/local/share/
28 #               /usr/local/share/applications           geeqie.desktop
29 # [gq_]appdir   /usr/local/share/geeqie/            *   template.desktop
30 # desktopdir    /usr/local/share/geeqie/applications    plugin desktop files
31 # appdatadir    /usr/local/share/metainfo               org.geeqie.Geeqie.appdata.xml
32 # icondir       /usr/local/share/pixmaps                geeqie.png icon
33 # [gq_]helpdir  /usr/local/share/doc/geeqie         *   readme files etc.
34 # [gq_]htmldir  /usr/local/share/doc/geeqie/html    *   help files
35 # gq_localedir  /usr/locale/share/locale
36 # mandir1       /usr/local/share/man/man1               man page
37 # podir         project_root/po
38
39 # * See meson_options.txt file
40
41 project(
42     'geeqie',
43     'c',
44     'cpp',
45     version : run_command('./version.sh', check : true).stdout().strip(),
46     license : ['GPL-2.0-or-later'],
47     meson_version : '>=0.53.0',
48     default_options : ['warning_level=3', 'buildtype=debugoptimized']
49 )
50
51 # To inhibit warnings from the generated files icons_inline.h and ui_icons.h
52 add_global_arguments('-Wno-overlength-strings', language : 'c')
53
54 # Used for colored text in user messages
55 c_red = '\033[91m'
56 c_end = '\033[0m'
57 disabled = c_red + 'DISABLED' + c_end
58 notfound = c_red + ' NOT FOUND' + c_end
59
60 # Project requirements
61 project_sources = []
62 gnome = import('gnome')
63 thread_dep = dependency('threads')
64 cc = meson.get_compiler('c')
65 i18n = import('i18n')
66 configuration_inc = include_directories('.')
67
68 user_options_message = 'Optional features:\n'
69 user_documentation_message = 'Documentation and other features:\n'
70 user_thumbnailer_message = 'Thumbnailer options:\n'
71
72 # External programs
73 gdk_pixbuf_csource = find_program('gdk-pixbuf-csource', required : true)
74 glib_genmarshal = find_program('glib-genmarshal', required : true)
75 gnome_doc_tool = find_program('yelp-build', required : false)
76 if gnome_doc_tool.found()
77     user_documentation_message += 'Help files will be created\n'
78 else
79     user_documentation_message += 'yelp-build ' + notfound + ' - Help files not created\n'
80 endif
81
82 debug = get_option('debug')
83
84 # Note that main.c sets prefix to the directory above where the executable is run from.
85 # This is to allow AppImages to be used
86
87 # These gq_* variables are paths relative to /prefix/,
88 # and are also used in defines in the source as GQ_*
89 if get_option('gq_appdir') == ''
90     gq_appdir = join_paths(get_option('datadir'), 'geeqie')
91 else
92     gq_appdir = get_option('gq_appdir')
93 endif
94
95 # This is not the same as Meson bindir
96 if get_option('gq_bindir') == ''
97     gq_bindir = 'lib/geeqie'
98 else
99     gq_bindir = get_option('gq_bindir')
100 endif
101
102 if get_option('gq_helpdir') == ''
103     gq_helpdir = join_paths(get_option('datadir'), 'doc/geeqie')
104 else
105     gq_helpdir = get_option('gq_helpdir')
106 endif
107
108 if get_option('gq_htmldir') == ''
109     gq_htmldir = join_paths(get_option('datadir'), 'doc/geeqie/html')
110 else
111     gq_htmldir = get_option('gq_htmldir')
112 endif
113
114 if get_option('gq_localedir') == ''
115     gq_localedir = join_paths(get_option('datadir'), 'locale')
116 else
117     gq_localedir = get_option('gq_localedir')
118 endif
119
120
121 # Set up the absolute directory paths used
122 prefix = get_option('prefix')
123 datadir = join_paths(prefix, get_option('datadir'))
124
125 # Installation paths are absolute
126 appdir = join_paths(prefix, gq_appdir)
127 appdatadir = join_paths(datadir, 'metainfo')
128 desktopdir = join_paths(datadir, meson.project_name(), 'applications')
129 helpdir = join_paths(prefix, gq_helpdir)
130 htmldir = join_paths(prefix, gq_htmldir)
131 icondir = join_paths(datadir, 'pixmaps')
132 mandir1 = join_paths(datadir, 'man', 'man1')
133
134 podir = join_paths(meson.source_root(), 'po')
135
136 # Create the define constants used in the sources. Set via config.h.in
137 conf_data = configuration_data()
138 conf_data.set_quoted('VERSION', run_command('./version.sh', check : true).stdout())
139 conf_data.set('DEBUG', debug)
140
141 gtk_dep = dependency('gtk+-3.0', version : '>=3.22', required: true)
142 glib_dep = dependency('glib-2.0', version : '>=2.52', required: true)
143
144 libarchive_dep = []
145 req_version = '>=3.4.0'
146 option = get_option('archive')
147 if not option.disabled()
148     libarchive_dep = dependency('libarchive', version : req_version, required : get_option('archive'))
149     if libarchive_dep.found()
150         conf_data.set('HAVE_ARCHIVE', 1)
151         user_options_message += 'archive: archive files e.g. .zip supported\n'
152     else
153         user_options_message += 'archive: libarchive ' + req_version + notfound + ' - archive files e.g. .zip not supported\n'
154     endif
155 else
156     user_options_message += 'archive: ' + disabled + ' - archive files e.g. .zip not supported\n'
157 endif
158
159 lcms_dep = []
160 req_version = '>=2.0'
161 option = get_option('cms')
162 if not option.disabled()
163     lcms_dep = dependency('lcms2', version : req_version, required : get_option('cms'))
164     if lcms_dep.found()
165         conf_data.set('HAVE_LCMS', 1)
166         conf_data.set('HAVE_LCMS2', 1)
167         user_options_message += 'cms: color management supported\n'
168     else
169         user_options_message += 'cms: lcms2 '+ req_version + notfound + ' - color management not supported\n'
170     endif
171 else
172     user_options_message += 'cms: ' + disabled + ' - color management not supported\n'
173 endif
174
175 ddjvuapi_dep = []
176 req_version = '>=2.5.27'
177 option = get_option('djvu')
178 if not option.disabled()
179     ddjvuapi_dep = dependency('ddjvuapi', version : req_version, required : get_option('djvu'))
180     if ddjvuapi_dep.found()
181         conf_data.set('HAVE_DJVU', 1)
182         user_options_message += 'djvu: djvu files supported\n'
183     else
184         user_options_message += 'djvu: ddjvuapi ' + req_version + notfound + ' - djvu files not supported\n'
185     endif
186 else
187     user_options_message += 'djvu: ' + disabled + ' - djvu files not supported\n'
188 endif
189
190 exiv2_dep = []
191 req_version = '>=0.11'
192 option = get_option('exiv2')
193 if not option.disabled()
194     exiv2_dep = dependency('exiv2', version : req_version, required : get_option('exiv2'))
195     if exiv2_dep.found()
196         conf_data.set('HAVE_EXIV2', 1)
197         user_options_message += 'exiv2: image metadata processed by exiv2\n'
198     else
199         user_options_message += 'exiv2: exiv2 ' + req_version + notfound + ' - image data not processed by exiv2\n'
200     endif
201 else
202     user_options_message += 'exiv2: ' + disabled + '- image data not processed by exiv2\n'
203 endif
204
205 libffmpegthumbnailer_dep = []
206 req_version = '>=2.1.0'
207 option = get_option('videothumbnailer')
208 if not option.disabled()
209     libffmpegthumbnailer_dep = dependency('libffmpegthumbnailer',
210         version : req_version,
211         required : get_option('videothumbnailer'))
212
213     if libffmpegthumbnailer_dep.found()
214         conf_data.set('HAVE_FFMPEGTHUMBNAILER', 1)
215         user_options_message += 'videothumbnailer: thumbnails of video files supported\n'
216
217         if cc.has_member('struct video_thumbnailer_struct', 'prefer_embedded_metadata',
218             prefix : '#include <libffmpegthumbnailer/videothumbnailerc.h>')
219
220             conf_data.set('HAVE_FFMPEGTHUMBNAILER_METADATA', 1)
221             user_thumbnailer_message += 'fmpegthumbnailer_metadata: found\n'
222         else
223             user_thumbnailer_message += 'ffmpegthumbnailer_metadata: ' + notfound + '\n'
224         endif
225
226         if cc.has_member('struct image_data_struct', 'image_data_width',
227             prefix : '#include <libffmpegthumbnailer/videothumbnailerc.h>' )
228
229             conf_data.set('HAVE_FFMPEGTHUMBNAILER_RGB', 1)
230             user_thumbnailer_message += 'ffmpegthumbnailer_rgb: found\n'
231         else
232             user_thumbnailer_message += 'ffmpegthumbnailer_rgb: ' + notfound + '\n'
233         endif
234
235         if cc.has_function('video_thumbnailer_set_size',
236             dependencies : libffmpegthumbnailer_dep)
237
238             conf_data.set('HAVE_FFMPEGTHUMBNAILER_WH', 1)
239             user_thumbnailer_message += 'ffmpegthumbnailer_set_size: found\n'
240         else
241             user_thumbnailer_message += 'ffmpegthumbnailer_set_size: ' + notfound + '\n'
242         endif
243     else
244         user_options_message += 'videothumbnailer: libvideothumbnailer ' + req_version + notfound + ' - no thumbnails of video files\n'
245     endif
246 else
247     user_options_message += 'videothumbnailer: ' + disabled + '- no thumbnails of video files\n'
248 endif
249
250 champlain_dep = []
251 champlain_gtk_dep = []
252 clutter_dep = []
253 clutter_gtk_dep = []
254 req_version_champlain = '>=0.12'
255 req_version_champlain_gtk = '>=0.12'
256 req_version_clutter = '>=1.0'
257 req_version_clutter_gtk = '>=1.0'
258 option = get_option('gps-map')
259 if not option.disabled()
260     champlain_dep = dependency('champlain-0.12', version : req_version_champlain, required : get_option('gps-map'))
261     champlain_gtk_dep = dependency('champlain-gtk-0.12', version : req_version_champlain_gtk, required : get_option('gps-map'))
262     if champlain_dep.found() and champlain_gtk_dep.found()
263         clutter_dep = dependency('clutter-1.0', version : req_version_clutter, required : get_option('gps-map'))
264         clutter_gtk_dep = dependency('clutter-gtk-1.0', version : req_version_clutter_gtk, required : get_option('gps-map'))
265         if clutter_dep.found() and clutter_gtk_dep.found()
266             conf_data.set('HAVE_CLUTTER', 1)
267             conf_data.set('HAVE_LIBCHAMPLAIN', 1)
268             conf_data.set('HAVE_LIBCHAMPLAIN_GTK', 1)
269             user_options_message += 'gps-map: GPS map displayed\n'
270         else
271             if not clutter_dep.found()
272                 user_options_message += 'gps-map: clutter-1.0 ' + req_version_clutter + notfound + ' - GPS map not displayed\n'
273             endif
274             if not clutter_gtk_dep.found()
275                 user_options_message += 'gps-map: clutter-gtk-1.0 ' + req_version_clutter_gtk + notfound + ' - GPS map not displayed\n'
276             endif
277         endif
278     else
279         if not champlain_dep.found()
280             user_options_message += 'gps-map: champlain-0.12 ' + req_version_champlain + notfound + ' - GPS map not displayed\n'
281         endif
282         if not champlain_gtk_dep.found()
283             user_options_message += 'gps-map: champlain-gtk-0.12 ' + req_version_champlain_gtk + notfound + ' - GPS map not displayed\n'
284         endif
285     endif
286 else
287     user_options_message += 'gps-map: ' + disabled + ' - GPS map not displayed\n'
288 endif
289
290 libheif_dep = []
291 req_version = '>=1.3.2'
292 option = get_option('heif')
293 if not option.disabled()
294     libheif_dep = dependency('libheif', version : req_version, required : get_option('heif'))
295     if libheif_dep.found()
296         conf_data.set('HAVE_HEIF', 1)
297         user_options_message += 'heif: heif files supported\n'
298     else
299         user_options_message += 'heif: libheif ' + req_version + notfound + ' - heif files not supported\n'
300     endif
301 else
302     user_options_message += 'heif: ' + disabled + ' - heif files not supported\n'
303 endif
304
305 libopenjp2_dep = []
306 req_version = '>=2.3.0'
307 option = get_option('j2k')
308 if not option.disabled()
309     libopenjp2_dep = dependency('libopenjp2', version : req_version, required : get_option('j2k'))
310     if libopenjp2_dep.found()
311         conf_data.set('HAVE_J2K', 1)
312         user_options_message += 'j2k: j2k files supported\n'
313     else
314         user_options_message += 'j2k: libopenjp2 ' + req_version + notfound + ' - j2k files not supported\n'
315     endif
316 else
317     user_options_message += 'j2k: ' + disabled + ' - j2k files not supported\n'
318 endif
319
320 libjpeg_dep = []
321 option = get_option('jpeg')
322 if not option.disabled()
323 libjpeg_dep = dependency('libjpeg', required : get_option('jpeg'))
324     if libjpeg_dep.found()
325         if cc.has_function('jpeg_destroy_decompress', dependencies : libjpeg_dep)
326             conf_data.set('HAVE_JPEG', 1)
327             user_options_message += 'jpeg: jpeg files supported\n'
328         else
329             user_options_message += 'jpeg: jpeg_destroy_decompress ' + notfound + ' - jpeg files not supported\n'
330         endif
331     else
332         user_options_message += 'jpeg: libjpeg: ' + notfound + '\n'
333     endif
334 else
335     user_options_message += 'jpeg: ' + disabled + ' - jpeg files not supported\n'
336 endif
337
338 libjxl_dep = []
339 req_version = '>=0.3.7'
340 option = get_option('jpegxl')
341 if not option.disabled()
342     libjxl_dep = dependency('libjxl', version : req_version, required : get_option('jpegxl'))
343     if libjxl_dep.found()
344         conf_data.set('HAVE_JPEGXL', 1)
345         user_options_message += 'jpegxl: jpegxl files supported\n'
346     else
347         user_options_message += 'jpegxl: libjxl ' + req_version + notfound + ' - jpegxl files not supported\n'
348     endif
349 else
350     user_options_message += 'jpegxl: ' + disabled + ' - jpegxl files not supported\n'
351 endif
352
353 libraw_dep = []
354 req_version = '>=0.20'
355 option = get_option('libraw')
356 if not option.disabled()
357     libraw_dep = dependency('libraw', version : req_version, required : get_option('libraw'))
358     if libraw_dep.found()
359         conf_data.set('HAVE_RAW', 1)
360         user_options_message += 'libraw: .cr3 files supported\n'
361     else
362         user_options_message += 'libraw: libraw ' + req_version + notfound + ' - .cr3 files not supported\n'
363     endif
364 else
365     user_options_message += 'libraw: ' + disabled + ' - .cr3 files not supported\n'
366 endif
367
368 lua_dep = []
369 req_version = '>=5.1'
370 option = get_option('lua')
371 if not option.disabled()
372     lua_dep = dependency('lua5.1',  version : req_version, required : get_option('lua'))
373     if lua_dep.found()
374         conf_data.set('HAVE_LUA', 1)
375         user_options_message += 'lua: lua supported\n'
376     else
377         user_options_message += 'lua: lua5.1 ' + req_version + notfound + ' - lua not supported\n'
378     endif
379 else
380     user_options_message += 'lua: ' + disabled + ' - lua not supported\n'
381 endif
382
383 poppler_glib_dep = []
384 req_version = '>=0.62'
385 option = get_option('pdf')
386 if not option.disabled()
387     poppler_glib_dep = dependency('poppler-glib', version : req_version, required : get_option('pdf'))
388     if poppler_glib_dep.found()
389         conf_data.set('HAVE_PDF', 1)
390         user_options_message += 'pdf: pdf files supported\n'
391     else
392         user_options_message += 'pdf: poppler-glib ' + req_version + notfound + ' - pdf files not supported\n'
393     endif
394 else
395     user_options_message += 'pdf: ' + disabled + ' - pdf files not supported\n'
396 endif
397
398 gspell_dep = []
399 req_version = '>=1.6'
400 option = get_option('spell')
401 if not option.disabled()
402     gspell_dep = dependency('gspell-1', version : req_version, required: get_option('spell'))
403     if gspell_dep.found()
404         conf_data.set('HAVE_SPELL', 1)
405         user_options_message += 'spell: spelling checks enabled\n'
406     else
407         user_options_message += 'spell: gspell-1 ' + req_version + notfound + ' - spelling checks not enabled\n'
408     endif
409 else
410     user_options_message += 'spell: ' + disabled + ' - spelling checks not enabled\n'
411 endif
412
413 tiff_dep = []
414 option = get_option('tiff')
415 if not option.disabled()
416     tiff_dep = cc.find_library('libtiff', required: get_option('tiff'))
417     if tiff_dep.found()
418         if cc.has_function('TIFFClientOpen',
419             dependencies : tiff_dep)
420
421             conf_data.set('HAVE_TIFF', 1)
422             user_options_message += 'tiff: tiff files supported\n'
423         else
424             user_options_message += 'tiff: TIFFClientOpen ' + notfound + ' - tiff files not supported\n'
425         endif
426     else
427         user_options_message += 'tiff: libtiff ' + notfound + ' - tiff files not supported\n'
428     endif
429 else
430     user_options_message += 'tiff: ' + disabled + ' - tiff files not supported\n'
431 endif
432
433 libwebp_dep = []
434 req_version = '>=0.6.1'
435 option = get_option('webp')
436 if not option.disabled()
437     libwebp_dep = dependency('libwebp', version : req_version, required : get_option('webp'))
438     if libwebp_dep.found()
439         conf_data.set('HAVE_WEBP', 1)
440         user_options_message += 'webp: webp files supported\n'
441     else
442         user_options_message += 'webp: libwebp ' + req_version + notfound + ' - webp files not supported\n'
443     endif
444 else
445     user_options_message += 'webp: ' + disabled + ' - webp files not supported\n'
446 endif
447
448 # Check for nl_langinfo and _NL_TIME_FIRST_WEEKDAY
449 code = '''#include <langinfo.h>
450 #include<stdio.h>
451 int main (int argc, char ** argv) {
452     char *c;
453     c =  nl_langinfo(_NL_TIME_FIRST_WEEKDAY);
454     return 0;
455 }'''
456 if cc.links(code, name : 'nl_langinfo and _NL_TIME_FIRST_WEEKDAY')
457     conf_data.set('HAVE__NL_TIME_FIRST_WEEKDAY', 1)
458     user_documentation_message += 'nl_langinfo - first weekday depends on locale\n'
459 else
460     user_documentation_message += 'nl_langinfo ' + notfound + ' - first weekday defaults to Monday\n'
461 endif
462
463 conf_data.set_quoted('GETTEXT_PACKAGE', meson.project_name())
464 conf_data.set_quoted('GQ_APPDIR', gq_appdir)
465 conf_data.set_quoted('GQ_BINDIR', gq_bindir)
466 conf_data.set_quoted('GQ_HELPDIR', gq_helpdir)
467 conf_data.set_quoted('GQ_HTMLDIR', gq_htmldir)
468 conf_data.set_quoted('GQ_LOCALEDIR', gq_localedir)
469
470 conf_data.set_quoted('PACKAGE', meson.project_name())
471 conf_data.set_quoted('PACKAGE_NAME', meson.project_name())
472 conf_data.set_quoted('PACKAGE_STRING', meson.project_version())
473 conf_data.set_quoted('PACKAGE_TARNAME', meson.project_name())
474 conf_data.set_quoted('PACKAGE_VERSION', meson.project_version())
475 conf_data.set_quoted('VERSION', meson.project_version())
476
477 configure_file(input : 'config.h.in',
478                output : 'config.h',
479                encoding : 'UTF-8',
480                configuration : conf_data)
481
482 # Process subdirs before the sources
483 subdir('po')
484 subdir('plugins')
485
486 # Generate the executable
487 subdir('src')
488
489 # Generate the help files
490 subdir('doc')
491
492 # Install other project files
493 run_command(find_program('gen_changelog.sh'), meson.source_root(), meson.build_root(), check : true)
494
495 pandoc = find_program('pandoc', required : false)
496 if pandoc.found()
497     run_command(find_program('gen_readme.sh'), meson.source_root(), meson.build_root(), check : false)
498
499     install_data('README.md', 'COPYING', 'TODO', 'AUTHORS',
500         join_paths(meson.build_root(), 'ChangeLog'),
501         join_paths(meson.build_root(), 'README.html'),
502         join_paths(meson.build_root(), 'ChangeLog.html'),
503         install_dir : helpdir)
504
505     user_documentation_message += 'README.html created\n'
506 else
507     install_data('README.md', 'COPYING', 'TODO', 'AUTHORS',
508         join_paths(meson.build_root(), 'ChangeLog'),
509         join_paths(meson.build_root(), 'ChangeLog.html'),
510         install_dir : helpdir)
511
512     user_documentation_message += 'pandoc ' + notfound + ' - README.html not created\n'
513 endif
514
515 evince = find_program('evince', required : false)
516 if evince.found()
517     user_documentation_message += 'print preview supported \n'
518 else
519     user_documentation_message += 'evince ' + notfound + ' - print preview not available\n'
520 endif
521
522 install_data('geeqie.png', install_dir : icondir)
523 install_data('geeqie.1', install_dir : mandir1)
524
525 i18n.merge_file(
526     input : 'geeqie.desktop.in',
527     output : 'geeqie.desktop',
528     type : 'desktop',
529     po_dir : podir,
530     install : true,
531     install_dir : join_paths(datadir, 'applications'))
532
533 i18n.merge_file(
534     input : 'org.geeqie.Geeqie.appdata.xml.in',
535     output : 'org.geeqie.Geeqie.appdata.xml',
536     type : 'xml',
537     po_dir : podir,
538     install : true,
539     install_dir : appdatadir)
540
541 configure_file(input: 'geeqie.spec.in', output: 'geeqie.spec', configuration: conf_data)
542
543 user_message = ''.join('Configuration Summary -\n\n', user_options_message, '\n', user_documentation_message, '\n', user_thumbnailer_message)
544 message(user_message)